// papervision3D greate white // template v01 // kalle saas | http://kallesaas.com package { // flash import flash.display.Sprite; import flash.events.*; import flash.utils.*; import flash.text.TextField; // Papervision import org.papervision3d.cameras.FreeCamera3D; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.scenes.Scene3D; import org.papervision3d.view.Viewport3D; // Primitives import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cube; import org.papervision3d.objects.primitives.Plane; // Materials import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.utils.MaterialsList; // Math stuff import org.papervision3d.core.math.*; // debug import org.papervision3d.materials.special.LineMaterial ; import org.papervision3d.core.geom.Lines3D; public class VirtualTrackball extends Sprite { // papervision3D private var viewport:Viewport3D; private var scene:Scene3D; private var camera:FreeCamera3D; private var renderer:BasicRenderEngine; // Primitives private var cube:Cube; private var cubeMaterials:MaterialsList; // MouseEvents private var mouseDownState:Boolean = false; private var mouseUpState:Boolean = false; private var mouseMoveState:Boolean = false; // vektor private var vectorMouseDown:Number3D; private var vectorMouseDrag:Number3D; private var trackBallVektor:Number3D; private var rotAxis:Number3D; private var rotY:Number = 0; // current cube rotation private var currRot:Quaternion; // gismo private var gismo:Cube; private var ObjectsWithGismo:Array = new Array(); private var lines:Array = null; /** * Konstruktor * @return */ public function VirtualTrackball() { init(); } private function init():void { initPapervision(); initMaterials(); initObjects(); initListeners(); initAnimation(); } /** * Alles was zum erstellen benötigt wird. * Viewport3D, scene, camera, renderer */ private function initPapervision():void { viewport = new Viewport3D( 800, 600, true, true ); addChild( viewport); scene = new Scene3D(); camera = new FreeCamera3D(); renderer = new BasicRenderEngine(); } /** * Erstelle alle Materialien die benötigt werden: */ private function initMaterials():void { // CubeMaterial cubeMaterials = new MaterialsList({ all: new WireframeMaterial( 0xDDDDDD, 100, 1 ) }); } /** * Erstelle alle Objekte */ private function initObjects():void { cube = new Cube(cubeMaterials, 500,500,500, 4, 4, 4) scene.addChild(cube, 'cube') ObjectsWithGismo.push(cube) insertAxisVectors(); } /** * Initiiere alle EventListener. */ private function initListeners():void { addEventListener( Event.ENTER_FRAME, onEnterFrame ); addEventListener( Event.ENTER_FRAME, rotate ); // erfassen der mouse events stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpEvent); stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownEvent); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveEvent); } /** * Initiiere die EventListener für Animationen. */ private function initAnimation():void { } /*_________________________________________________________________________ * Funktionen für EventListener */ private function onEnterFrame( e:Event ):void { // scale the coordinate system and save the mouse position: var trackballX:Number = stage.mouseX / (stage.stageWidth/2 ) - 1 var trackballY:Number = 1 - stage.mouseY / (stage.stageHeight/2) // calculate the Z coordinat var trackballZ:Number; var z2:Number = 1 - trackballX*trackballX -trackballY*trackballY if(z2>0){ trackballZ = Math.sqrt(z2) }else{ trackballZ = 0 } trackBallVektor = new Number3D( trackballX, trackballY, trackballZ ) trackBallVektor.normalize(); // save vector at mouse events (drag) for down see the eventListener below // vectorMouseDown und vectorMouseDrag if(mouseDownState == true && mouseMoveState == true){ vectorMouseDrag = trackBallVektor // calculate the rotation axis: see cross product rotAxis = Number3D.cross(vectorMouseDown, vectorMouseDrag); // calculate the amount of rotation var rotAngle:Number = angleBetween(vectorMouseDown, vectorMouseDrag); // wenn angle == NAN ist if(!rotAngle){rotAngle=0} // applaying the rotation // convert to Quaternion, the cube rotaion and the mouse drag var deltaQ:Quaternion = Quaternion.createFromAxisAngle(rotAxis.x, rotAxis.y, rotAxis.z, rotAngle); var q = Quaternion.createFromEuler(cube.rotationX, cube.rotationY, cube.rotationZ) q.mult(deltaQ); q.normalize(); // multiply drag rotation with current rot of the cube q.mult(currRot); var newTransform = q.toMatrix(); cube.transform = newTransform; showVectors(); } // papervision renderer.renderScene( scene, camera, viewport ); } private function onMouseDownEvent(event:MouseEvent):void { vectorMouseDown = trackBallVektor trace(vectorMouseDown) currRot = Quaternion.createFromMatrix(cube.transform) currRot.normalize(); mouseDownState = true mouseUpState = false } private function onMouseUpEvent(event:MouseEvent):void { mouseUpState = true mouseDownState = false } private function onMouseMoveEvent(event:MouseEvent):void { mouseMoveState = true } /*_________________________________________________________________________ * Funktionen für Animationen */ private function rotate( e:* ):void { //cube.pitch(1) } /*_________________________________________________________________________ * Funktionen für Animationen */ private function toAxisRotation( q:Quaternion ):Number3D { q.normalize(); var cos_a = q.w; var angle = Math.acos( cos_a ) * 2; var sin_a = Math.sqrt( 1.0 - cos_a * cos_a ); if(Math.abs(sin_a)< 0.0005 ){ sin_a = 1 } var axisRotation:Number3D = new Number3D(); axisRotation.x = q.x / sin_a; axisRotation.y = q.y / sin_a; axisRotation.z = q.z / sin_a; trace(cos_a + " " + angle + " " + sin_a ) return axisRotation } private function angleBetween(v1:Number3D, v2:Number3D):Number { var angle:Number = Math.acos( Number3D.dot( v1, v2 ) / ( v1.modulo * v2.modulo ) ) return angle } private function insertAxisVectors():void { for (var i:String in ObjectsWithGismo) { //Create gismo var gismo = new Cube( new MaterialsList({ all: new ColorMaterial(0x888888) }), 10, 10, 10 ); ObjectsWithGismo[i].addChild(gismo); // X = Red; Y = Green; Z = Blue var bx:Cube = new Cube( new MaterialsList({ all: new ColorMaterial(0xFF0000) }), 3, 3, 3 ); var by:Cube = new Cube( new MaterialsList({ all: new ColorMaterial(0x00FF00) }), 3, 3, 3 ); var bz:Cube = new Cube( new MaterialsList({ all: new ColorMaterial(0x0000FF) }), 3, 3, 3 ); bx.x = 100; by.y = 100; bz.z = -100; bx.scaleX = 20; by.scaleY = 20; bz.scaleZ = 20; gismo.addChild(bx); gismo.addChild(by); gismo.addChild(bz); } } private function showVectors():void { if(lines != null){ for each(var l:Lines3D in lines){ scene.removeChild(l); } } lines = []; var xl:Lines3D = new Lines3D(new LineMaterial(0xFF0000)); scene.addChild(xl); xl.addNewLine(2, 0,0,0, vectorMouseDrag.x*(2*stage.stageWidth), vectorMouseDrag.y*(2*stage.stageWidth), vectorMouseDrag.z*(2*stage.stageWidth)); lines.push(xl); var x3:Lines3D = new Lines3D(new LineMaterial(0x00FF00)); scene.addChild(x3); x3.addNewLine(2, 0,0,0, vectorMouseDown.x*(10000), vectorMouseDown.y*(10000), vectorMouseDown.z*(10000)); lines.push(x3); var x2:Lines3D = new Lines3D(new LineMaterial(0x0000FF)); scene.addChild(x2); x2.addNewLine(2, 0,0,0, rotAxis.x*(2*stage.stageWidth), rotAxis.y*(2*stage.stageWidth), rotAxis.z*(2*stage.stageWidth)); lines.push(x2); } } }