package geometry._theory { import flash.events.Event; import flash.geom.Matrix3D; import flash.geom.Orientation3D; import flash.geom.Vector3D; import triga.shapes.CrossHair; import triga.shapes.Label; import triga.shapes.Tick; import triga.shapes.XYZ; /** * @author Nicolas Barradeau * http://en.nicoptere.net */ public class G_MatrixRotation extends BaseScene { private var nativeMatrix:XYZ; private var tick:XYZ; private const DEGREES_TO_RADIANS:Number = Math.PI / 180; private const RADIANS_TO_DEGREES:Number = 180 / Math.PI; public function G_MatrixRotation() { setup(); addMesh( new XYZ(100, 100, 100, WHITE ), tick = new XYZ( 50 ), nativeMatrix = new XYZ( 50 ) ); addChild( GlobalTextField.instance ); //we create an empty matrix var mat:Matrix3D = new Matrix3D(); //we choose an angle var angleX:Number = 45 * DEGREES_TO_RADIANS; var angleY:Number = 10 * DEGREES_TO_RADIANS; var angleZ:Number = 30 * DEGREES_TO_RADIANS; var cx:Number = Math.cos( angleX ); var cy:Number = Math.cos( angleY ); var cz:Number = Math.cos( angleZ ); var sx:Number = Math.sin( angleX ); var sy:Number = Math.sin( angleY ); var sz:Number = Math.sin( angleZ ); /* the following example comes from here http://www.euclideanspace.com/maths/geometry/rotations/euler/index.htm rotations on each axes are represented respectively by RX 1 0 0 0 0 cx -sx 0 0 sx cx 0 0 0 0 1 RY cy 0 sy 0 0 1 0 0 -sy 0 cy 0 0 0 0 1 RZ cz -sz 0 0 sz cz 0 0 0 0 1 0 0 0 0 1 to combine the rotations we need to multiply each matrix in the right order as the 4th column and the 4th row are always the same ( used to make the Matrix homogenous ) we can simply ignore them to compute rotations so, first multiply RX by RY: ( RX * RY ) RX*RY cy sx*sy cx*sy 0 cx - sx -sy sx*cy cx*cy then multiply the result by RZ: ( RX * RY ) * RZ RX*RY*RZ cy * cz sx*sy*cz-cx*sz cx*sy*cz+sx*sz, cy * sz sx*sy*sz +cx*cz cx*sy*sz-sx*cz, -sy sx*cy cx*cy which gives us this horrible piece of computation : mat.rawData = Vector.( [ cy * cz, sx * sy * cz - cx * sz, cx * sy * cz + sx * sz, 0, cy * sz, sx * sy * sz +cx * cz, cx * sy * sz - sx * cz, 0, -sy, sx * cy, cx * cy, 0, 0, 0, 0, 1 ] ); mat.transpose(); as it doesn't follow the Adobe's Matrix3D specs, we have to transpose it .... hehe... here's a correct rotation matrix : */ mat.rawData = Vector.( [ cy * cz, cy * sz, -sy, 0, sx * sy * cz - cx * sz, sx * sy * sz +cx * cz, sx * cy, 0, cx * sy * cz + sx * sz, cx * sy * sz - sx * cz, cx * cy, 0, 0, 0, 0, 1 ] ); //when we assign that matrix to our object, we end up with a combined rotation on the 3 axes tick.transform = mat; addMesh( new Label( new Vector3D( 0, -15 ), 'manual\nrotation' ) ); //fortunately for us, there's a more user firnedly way of putting it: Matrix3D.recompose() mat.identity(); var position:Vector3D = new Vector3D(100); var rotation:Vector3D = new Vector3D( angleX, angleY, angleZ ); var scale:Vector3D = new Vector3D(1,1,1); mat.recompose( Vector.( [ position, rotation, scale ] ), Orientation3D.EULER_ANGLES ); nativeMatrix.transform = mat; addMesh( new Label( new Vector3D( 100, -15 ), 'native\nrotation' ) ); } } }