// 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; // Materials import org.papervision3d.materials.WireframeMaterial; 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 rotY:Number = 0; // debug private var lines:Array = null; private var vl:Lines3D = new Lines3D(new LineMaterial(0xff)); /** * 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, false, 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') } /** * 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 // debug var vMouseDrag = getChildByName('vMouseDrag') vMouseDrag.text = "x: " + vectorMouseDrag.x + "\ny: " + vectorMouseDrag.y + "\nz: " + vectorMouseDrag.z // calculate the rotation axis: see cross product var rotAxis:Number3D = Number3D.cross(vectorMouseDown, vectorMouseDrag); // calculate the amount of rotation var rotAngle:Number = angleBetween(vectorMouseDown, vectorMouseDrag); // applaying the rotation // convert to Quaternion, the cube rotaion and the mouse drag var deltaQ:Quaternion = new Quaternion(rotAxis.x, rotAxis.y, rotAxis.z, rotAngle); var q = Quaternion.createFromEuler(cube.rotationX, cube.rotationY, cube.rotationZ) q.mult(deltaQ); var newTransform = q.toMatrix(); cube.transform = newTransform // debug var rotVector = getChildByName('rotVector') rotVector.text = "x: " + rotAxis.x + "\ny: " + rotAxis.y + "\nz: " + rotAxis.z var angle = getChildByName('angle') angle.text = rotAngle } // debugging: var posX = getChildByName('posX') posX.text = stage.mouseX var posY = getChildByName('posY') posY.text = stage.mouseY var cubeRotation = getChildByName('cubeRotation') cubeRotation.text = "x: " + cube.rotationX + "\ny: " + cube.rotationY + "\nz: " + cube.rotationZ var trackPosX = getChildByName('trackPosX') trackPosX.text = trackballX var trackPosY = getChildByName('trackPosY') trackPosY.text = trackballY var trackPosZ = getChildByName('trackPosZ') trackPosZ.text = trackballZ var mouseDownStateEvent = getChildByName('onMouseDownState') mouseDownStateEvent.text = mouseDownState var onMouseUpStateEvent = getChildByName('onMouseUpState') onMouseUpStateEvent.text = mouseUpState showVector(); // papervision renderer.renderScene( scene, camera, viewport ); } private function onMouseDownEvent(event:MouseEvent):void { vectorMouseDown = trackBallVektor mouseDownState = true mouseUpState = false var vMouseDown = getChildByName('vMouseDown') vMouseDown.text = "x: " + vectorMouseDown.x + "\ny: " + vectorMouseDown.y + "\nz: " + vectorMouseDown.z } 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 showVector():void{ if(lines != null){ for each(var l:Lines3D in lines){ scene.removeChild(l); } } lines = []; var m:Matrix3D = cube.transform; var xl:Lines3D = new Lines3D(new LineMaterial()); scene.addChild(xl); xl.addNewLine(2, cube.x,cube.y,cube.z, cube.x + m.n11*300, cube.y + m.n21*300 , cube.z + m.n31*300); lines.push(xl); var yl:Lines3D = new Lines3D(new LineMaterial(0xff)); scene.addChild(yl); yl.addNewLine(2, cube.x,cube.y,cube.z, cube.x + m.n12*300, cube.y + m.n22*300 , cube.z + m.n32*300); lines.push(yl); var zl:Lines3D = new Lines3D(new LineMaterial(0xff00)); scene.addChild (zl); zl.addNewLine(2, cube.x,cube.y,cube.z, cube.x + m.n13*300, cube.y + m.n23*300 , cube.z + m.n33*300); lines.push(zl); } } }