PageRenderTime 59ms CodeModel.GetById 15ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 1ms

/src/away3d/core/base/Object3D.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 969 lines | 561 code | 171 blank | 237 comment | 71 complexity | 64a6ed0d38d82951b78f9a48b492447c MD5 | raw file
  1package away3d.core.base
  2{
  3	import away3d.*;
  4	import away3d.controllers.*;
  5	import away3d.core.math.*;
  6	import away3d.events.*;
  7	import away3d.library.assets.*;
  8	
  9	import flash.geom.*;
 10	
 11	use namespace arcane;
 12	
 13	/**
 14	 * Dispatched when the position of the 3d object changes.
 15	 *
 16	 * @eventType away3d.events.Object3DEvent
 17	 */
 18	[Event(name="positionChanged", type="away3d.events.Object3DEvent")]
 19	
 20	/**
 21	 * Dispatched when the scale of the 3d object changes.
 22	 *
 23	 * @eventType away3d.events.Object3DEvent
 24	 */
 25	[Event(name="scaleChanged", type="away3d.events.Object3DEvent")]
 26	
 27	/**
 28	 * Dispatched when the rotation of the 3d object changes.
 29	 *
 30	 * @eventType away3d.events.Object3DEvent
 31	 */
 32	[Event(name="rotationChanged", type="away3d.events.Object3DEvent")]
 33	
 34	/**
 35	 * Object3D provides a base class for any 3D object that has a (local) transformation.<br/><br/>
 36	 *
 37	 * Standard Transform:
 38	 * <ul>
 39	 *     <li> The standard order for transformation is [parent transform] * (Translate+Pivot) * (Rotate) * (-Pivot) * (Scale) * [child transform] </li>
 40	 *     <li> This is the order of matrix multiplications, left-to-right. </li>
 41	 *     <li> The order of transformation is right-to-left, however!
 42	 *          (Scale) happens before (-Pivot) happens before (Rotate) happens before (Translate+Pivot)
 43	 *          with no pivot, the above transform works out to [parent transform] * Translate * Rotate * Scale * [child transform]
 44	 *          (Scale) happens before (Rotate) happens before (Translate) </li>
 45	 *     <li> This is based on code in updateTransform and ObjectContainer3D.updateSceneTransform(). </li>
 46	 *     <li> Matrix3D prepend = operator on rhs - e.g. transform' = transform * rhs; </li>
 47	 *     <li> Matrix3D append =  operator on lhr - e.g. transform' = lhs * transform; </li>
 48	 * </ul>
 49	 *
 50	 * To affect Scale:
 51	 * <ul>
 52	 *     <li> set scaleX/Y/Z directly, or call scale(delta) </li>
 53	 * </ul>
 54	 *
 55	 * To affect Pivot:
 56	 * <ul>
 57	 *     <li> set pivotPoint directly, or call movePivot() </li>
 58	 * </ul>
 59	 *
 60	 * To affect Rotate:
 61	 * <ul>
 62	 *    <li> set rotationX/Y/Z individually (using degrees), set eulers [all 3 angles] (using radians), or call rotateTo()</li>
 63	 *    <li> call pitch()/yaw()/roll()/rotate() to add an additional rotation *before* the current transform.
 64	 *         rotationX/Y/Z will be reset based on these operations. </li>
 65	 * </ul>
 66	 *
 67	 * To affect Translate (post-rotate translate):
 68	 *
 69	 * <ul>
 70	 *    <li> set x/y/z/position or call moveTo(). </li>
 71	 *    <li> call translate(), which modifies x/y/z based on a delta vector. </li>
 72	 *    <li> call moveForward()/moveBackward()/moveLeft()/moveRight()/moveUp()/moveDown()/translateLocal() to add an
 73	 *         additional translate *before* the current transform. x/y/z will be reset based on these operations. </li>
 74	 * </ul>
 75	 */
 76	
 77	public class Object3D extends NamedAssetBase
 78	{
 79		/** @private */
 80		arcane var _controller:ControllerBase;
 81		
 82		private var _smallestNumber:Number = 0.0000000000000000000001;
 83		private var _transformDirty:Boolean = true;
 84		
 85		private var _positionDirty:Boolean;
 86		private var _rotationDirty:Boolean;
 87		private var _scaleDirty:Boolean;
 88		
 89		// TODO: not used
 90		// private var _positionValuesDirty:Boolean;
 91		// private var _rotationValuesDirty:Boolean;
 92		// private var _scaleValuesDirty:Boolean;
 93		
 94		private var _positionChanged:Object3DEvent;
 95		private var _rotationChanged:Object3DEvent;
 96		private var _scaleChanged:Object3DEvent;
 97		
 98		private var _rotationX:Number = 0;
 99		private var _rotationY:Number = 0;
100		private var _rotationZ:Number = 0;
101		private var _eulers:Vector3D = new Vector3D();
102		
103		private var _flipY:Matrix3D = new Matrix3D();
104		private var _listenToPositionChanged:Boolean;
105		private var _listenToRotationChanged:Boolean;
106		private var _listenToScaleChanged:Boolean;
107		
108		protected var _zOffset:int = 0;
109		
110		private function invalidatePivot():void
111		{
112			_pivotZero = (_pivotPoint.x == 0) && (_pivotPoint.y == 0) && (_pivotPoint.z == 0);
113			
114			invalidateTransform();
115		}
116		
117		private function invalidatePosition():void
118		{
119			if (_positionDirty)
120				return;
121			
122			_positionDirty = true;
123			
124			invalidateTransform();
125			
126			if (_listenToPositionChanged)
127				notifyPositionChanged();
128		}
129		
130		private function notifyPositionChanged():void
131		{
132			if (!_positionChanged)
133				_positionChanged = new Object3DEvent(Object3DEvent.POSITION_CHANGED, this);
134			
135			dispatchEvent(_positionChanged);
136		}
137		
138		override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
139		{
140			super.addEventListener(type, listener, useCapture, priority, useWeakReference);
141			switch (type) {
142				case Object3DEvent.POSITION_CHANGED:
143					_listenToPositionChanged = true;
144					break;
145				case Object3DEvent.ROTATION_CHANGED:
146					_listenToRotationChanged = true;
147					break;
148				case Object3DEvent.SCALE_CHANGED:
149					_listenToRotationChanged = true;
150					break;
151			}
152		}
153		
154		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
155		{
156			super.removeEventListener(type, listener, useCapture);
157			
158			if (hasEventListener(type))
159				return;
160			
161			switch (type) {
162				case Object3DEvent.POSITION_CHANGED:
163					_listenToPositionChanged = false;
164					break;
165				case Object3DEvent.ROTATION_CHANGED:
166					_listenToRotationChanged = false;
167					break;
168				case Object3DEvent.SCALE_CHANGED:
169					_listenToScaleChanged = false;
170					break;
171			}
172		}
173		
174		private function invalidateRotation():void
175		{
176			if (_rotationDirty)
177				return;
178			
179			_rotationDirty = true;
180			
181			invalidateTransform();
182			
183			if (_listenToRotationChanged)
184				notifyRotationChanged();
185		}
186		
187		private function notifyRotationChanged():void
188		{
189			if (!_rotationChanged)
190				_rotationChanged = new Object3DEvent(Object3DEvent.ROTATION_CHANGED, this);
191			
192			dispatchEvent(_rotationChanged);
193		}
194		
195		private function invalidateScale():void
196		{
197			if (_scaleDirty)
198				return;
199			
200			_scaleDirty = true;
201			
202			invalidateTransform();
203			
204			if (_listenToScaleChanged)
205				notifyScaleChanged();
206		}
207		
208		private function notifyScaleChanged():void
209		{
210			if (!_scaleChanged)
211				_scaleChanged = new Object3DEvent(Object3DEvent.SCALE_CHANGED, this);
212			
213			dispatchEvent(_scaleChanged);
214		}
215		
216		protected var _transform:Matrix3D = new Matrix3D();
217		protected var _scaleX:Number = 1;
218		protected var _scaleY:Number = 1;
219		protected var _scaleZ:Number = 1;
220		protected var _x:Number = 0;
221		protected var _y:Number = 0;
222		protected var _z:Number = 0;
223		protected var _pivotPoint:Vector3D = new Vector3D();
224		protected var _pivotZero:Boolean = true;
225		protected var _pos:Vector3D = new Vector3D();
226		protected var _rot:Vector3D = new Vector3D();
227		protected var _sca:Vector3D = new Vector3D();
228		protected var _transformComponents:Vector.<Vector3D>;
229		
230		/**
231		 * An object that can contain any extra data.
232		 */
233		public var extra:Object;
234		
235		/**
236		 * Defines the x coordinate of the 3d object relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
237		 */
238		public function get x():Number
239		{
240			return _x;
241		}
242		
243		public function set x(val:Number):void
244		{
245			if (_x == val)
246				return;
247			
248			_x = val;
249			
250			invalidatePosition();
251		}
252		
253		/**
254		 * Defines the y coordinate of the 3d object relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
255		 */
256		public function get y():Number
257		{
258			return _y;
259		}
260		
261		public function set y(val:Number):void
262		{
263			if (_y == val)
264				return;
265			
266			_y = val;
267			
268			invalidatePosition();
269		}
270		
271		/**
272		 * Defines the z coordinate of the 3d object relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
273		 */
274		public function get z():Number
275		{
276			return _z;
277		}
278		
279		public function set z(val:Number):void
280		{
281			if (_z == val)
282				return;
283			
284			_z = val;
285			
286			invalidatePosition();
287		}
288		
289		/**
290		 * Defines the euler angle of rotation of the 3d object around the x-axis, relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
291		 */
292		public function get rotationX():Number
293		{
294			return _rotationX*MathConsts.RADIANS_TO_DEGREES;
295		}
296		
297		public function set rotationX(val:Number):void
298		{
299			if (rotationX == val)
300				return;
301			
302			_rotationX = val*MathConsts.DEGREES_TO_RADIANS;
303			
304			invalidateRotation();
305		}
306		
307		/**
308		 * Defines the euler angle of rotation of the 3d object around the y-axis, relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
309		 */
310		public function get rotationY():Number
311		{
312			return _rotationY*MathConsts.RADIANS_TO_DEGREES;
313		}
314		
315		public function set rotationY(val:Number):void
316		{
317			if (rotationY == val)
318				return;
319			
320			_rotationY = val*MathConsts.DEGREES_TO_RADIANS;
321			
322			invalidateRotation();
323		}
324		
325		/**
326		 * Defines the euler angle of rotation of the 3d object around the z-axis, relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
327		 */
328		public function get rotationZ():Number
329		{
330			return _rotationZ*MathConsts.RADIANS_TO_DEGREES;
331		}
332		
333		public function set rotationZ(val:Number):void
334		{
335			if (rotationZ == val)
336				return;
337			
338			_rotationZ = val*MathConsts.DEGREES_TO_RADIANS;
339			
340			invalidateRotation();
341		}
342		
343		/**
344		 * Defines the scale of the 3d object along the x-axis, relative to local coordinates.
345		 */
346		public function get scaleX():Number
347		{
348			return _scaleX;
349		}
350		
351		public function set scaleX(val:Number):void
352		{
353			if (_scaleX == val)
354				return;
355			
356			_scaleX = val;
357			
358			invalidateScale();
359		}
360		
361		/**
362		 * Defines the scale of the 3d object along the y-axis, relative to local coordinates.
363		 */
364		public function get scaleY():Number
365		{
366			return _scaleY;
367		}
368		
369		public function set scaleY(val:Number):void
370		{
371			if (_scaleY == val)
372				return;
373			
374			_scaleY = val;
375			
376			invalidateScale();
377		}
378		
379		/**
380		 * Defines the scale of the 3d object along the z-axis, relative to local coordinates.
381		 */
382		public function get scaleZ():Number
383		{
384			return _scaleZ;
385		}
386		
387		public function set scaleZ(val:Number):void
388		{
389			if (_scaleZ == val)
390				return;
391			
392			_scaleZ = val;
393			
394			invalidateScale();
395		}
396		
397		/**
398		 * Defines the rotation of the 3d object as a <code>Vector3D</code> object containing euler angles for rotation around x, y and z axis.
399		 */
400		public function get eulers():Vector3D
401		{
402			_eulers.x = _rotationX*MathConsts.RADIANS_TO_DEGREES;
403			_eulers.y = _rotationY*MathConsts.RADIANS_TO_DEGREES;
404			_eulers.z = _rotationZ*MathConsts.RADIANS_TO_DEGREES;
405			
406			return _eulers;
407		}
408		
409		public function set eulers(value:Vector3D):void
410		{
411			_rotationX = value.x*MathConsts.DEGREES_TO_RADIANS;
412			_rotationY = value.y*MathConsts.DEGREES_TO_RADIANS;
413			_rotationZ = value.z*MathConsts.DEGREES_TO_RADIANS;
414			
415			invalidateRotation();
416		}
417		
418		/**
419		 * The transformation of the 3d object, relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
420		 */
421		public function get transform():Matrix3D
422		{
423			if (_transformDirty)
424				updateTransform();
425			
426			return _transform;
427		}
428		
429		public function set transform(val:Matrix3D):void
430		{
431			//ridiculous matrix error
432			var raw:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
433			val.copyRawDataTo(raw);
434			if (!raw[uint(0)]) {
435				raw[uint(0)] = _smallestNumber;
436				val.copyRawDataFrom(raw);
437			}
438			
439			var elements:Vector.<Vector3D> = Matrix3DUtils.decompose(val);
440			var vec:Vector3D;
441			
442			vec = elements[0];
443			
444			if (_x != vec.x || _y != vec.y || _z != vec.z) {
445				_x = vec.x;
446				_y = vec.y;
447				_z = vec.z;
448				
449				invalidatePosition();
450			}
451			
452			vec = elements[1];
453			
454			if (_rotationX != vec.x || _rotationY != vec.y || _rotationZ != vec.z) {
455				_rotationX = vec.x;
456				_rotationY = vec.y;
457				_rotationZ = vec.z;
458				
459				invalidateRotation();
460			}
461			
462			vec = elements[2];
463			
464			if (_scaleX != vec.x || _scaleY != vec.y || _scaleZ != vec.z) {
465				_scaleX = vec.x;
466				_scaleY = vec.y;
467				_scaleZ = vec.z;
468				
469				invalidateScale();
470			}
471		}
472		
473		/**
474		 * Defines the local point around which the object rotates.
475		 */
476		public function get pivotPoint():Vector3D
477		{
478			return _pivotPoint;
479		}
480		
481		public function set pivotPoint(pivot:Vector3D):void
482		{
483			if(!_pivotPoint) _pivotPoint = new Vector3D();
484			_pivotPoint.x = pivot.x;
485			_pivotPoint.y = pivot.y;
486			_pivotPoint.z = pivot.z;
487
488			invalidatePivot();
489		}
490		
491		/**
492		 * Defines the position of the 3d object, relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
493		 */
494		public function get position():Vector3D
495		{
496			transform.copyColumnTo(3, _pos);
497			
498			return _pos.clone();
499		}
500		
501		public function set position(value:Vector3D):void
502		{
503			_x = value.x;
504			_y = value.y;
505			_z = value.z;
506			
507			invalidatePosition();
508		}
509
510		/**
511		 * Defines the position of the 3d object, relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
512		 * @param v the destination Vector3D
513		 * @return
514		 */
515		public function getPosition(v:Vector3D = null):Vector3D {
516			if(!v) v = new Vector3D();
517			transform.copyColumnTo(3, v);
518			return v;
519		}
520		
521		/**
522		 *
523		 */
524		public function get forwardVector():Vector3D
525		{
526			return Matrix3DUtils.getForward(transform);
527		}
528		
529		/**
530		 *
531		 */
532		public function get rightVector():Vector3D
533		{
534			return Matrix3DUtils.getRight(transform);
535		}
536		
537		/**
538		 *
539		 */
540		public function get upVector():Vector3D
541		{
542			return Matrix3DUtils.getUp(transform);
543		}
544		
545		/**
546		 *
547		 */
548		public function get backVector():Vector3D
549		{
550			var director:Vector3D = Matrix3DUtils.getForward(transform);
551			director.negate();
552			
553			return director;
554		}
555		
556		/**
557		 *
558		 */
559		public function get leftVector():Vector3D
560		{
561			var director:Vector3D = Matrix3DUtils.getRight(transform);
562			director.negate();
563			
564			return director;
565		}
566
567		/**
568		 *
569		 */
570		public function get downVector():Vector3D
571		{
572			var director:Vector3D = Matrix3DUtils.getUp(transform);
573			director.negate();
574			
575			return director;
576		}
577		
578		/**
579		 * Creates an Object3D object.
580		 */
581		public function Object3D()
582		{
583			// Cached vector of transformation components used when
584			// recomposing the transform matrix in updateTransform()
585			_transformComponents = new Vector.<Vector3D>(3, true);
586			_transformComponents[0] = _pos;
587			_transformComponents[1] = _rot;
588			_transformComponents[2] = _sca;
589			
590			_transform.identity();
591			
592			_flipY.appendScale(1, -1, 1);
593		}
594		
595		/**
596		 * Appends a uniform scale to the current transformation.
597		 * @param value The amount by which to scale.
598		 */
599		public function scale(value:Number):void
600		{
601			_scaleX *= value;
602			_scaleY *= value;
603			_scaleZ *= value;
604			
605			invalidateScale();
606		}
607		
608		/**
609		 * Moves the 3d object forwards along it's local z axis
610		 *
611		 * @param    distance    The length of the movement
612		 */
613		public function moveForward(distance:Number):void
614		{
615			translateLocal(Vector3D.Z_AXIS, distance);
616		}
617		
618		/**
619		 * Moves the 3d object backwards along it's local z axis
620		 *
621		 * @param    distance    The length of the movement
622		 */
623		public function moveBackward(distance:Number):void
624		{
625			translateLocal(Vector3D.Z_AXIS, -distance);
626		}
627		
628		/**
629		 * Moves the 3d object backwards along it's local x axis
630		 *
631		 * @param    distance    The length of the movement
632		 */
633		public function moveLeft(distance:Number):void
634		{
635			translateLocal(Vector3D.X_AXIS, -distance);
636		}
637		
638		/**
639		 * Moves the 3d object forwards along it's local x axis
640		 *
641		 * @param    distance    The length of the movement
642		 */
643		public function moveRight(distance:Number):void
644		{
645			translateLocal(Vector3D.X_AXIS, distance);
646		}
647		
648		/**
649		 * Moves the 3d object forwards along it's local y axis
650		 *
651		 * @param    distance    The length of the movement
652		 */
653		public function moveUp(distance:Number):void
654		{
655			translateLocal(Vector3D.Y_AXIS, distance);
656		}
657		
658		/**
659		 * Moves the 3d object backwards along it's local y axis
660		 *
661		 * @param    distance    The length of the movement
662		 */
663		public function moveDown(distance:Number):void
664		{
665			translateLocal(Vector3D.Y_AXIS, -distance);
666		}
667		
668		/**
669		 * Moves the 3d object directly to a point in space
670		 *
671		 * @param    dx        The amount of movement along the local x axis.
672		 * @param    dy        The amount of movement along the local y axis.
673		 * @param    dz        The amount of movement along the local z axis.
674		 */
675		public function moveTo(dx:Number, dy:Number, dz:Number):void
676		{
677			if (_x == dx && _y == dy && _z == dz)
678				return;
679			_x = dx;
680			_y = dy;
681			_z = dz;
682			
683			invalidatePosition();
684		}
685		
686		/**
687		 * Moves the local point around which the object rotates.
688		 *
689		 * @param    dx        The amount of movement along the local x axis.
690		 * @param    dy        The amount of movement along the local y axis.
691		 * @param    dz        The amount of movement along the local z axis.
692		 */
693		public function movePivot(dx:Number, dy:Number, dz:Number):void
694		{
695			if(!_pivotPoint) _pivotPoint = new Vector3D();
696			_pivotPoint.x += dx;
697			_pivotPoint.y += dy;
698			_pivotPoint.z += dz;
699			
700			invalidatePivot();
701		}
702		
703		/**
704		 * Moves the 3d object along a vector by a defined length
705		 *
706		 * @param    axis        The vector defining the axis of movement
707		 * @param    distance    The length of the movement
708		 */
709		public function translate(axis:Vector3D, distance:Number):void
710		{
711			var x:Number = axis.x, y:Number = axis.y, z:Number = axis.z;
712			var len:Number = distance/Math.sqrt(x*x + y*y + z*z);
713			
714			_x += x*len;
715			_y += y*len;
716			_z += z*len;
717			
718			invalidatePosition();
719		}
720		
721		/**
722		 * Moves the 3d object along a vector by a defined length
723		 *
724		 * @param    axis        The vector defining the axis of movement
725		 * @param    distance    The length of the movement
726		 */
727		public function translateLocal(axis:Vector3D, distance:Number):void
728		{
729			var x:Number = axis.x, y:Number = axis.y, z:Number = axis.z;
730			var len:Number = distance/Math.sqrt(x*x + y*y + z*z);
731			
732			transform.prependTranslation(x*len, y*len, z*len);
733			
734			_transform.copyColumnTo(3, _pos);
735			
736			_x = _pos.x;
737			_y = _pos.y;
738			_z = _pos.z;
739			
740			invalidatePosition();
741		}
742		
743		/**
744		 * Rotates the 3d object around it's local x-axis
745		 *
746		 * @param    angle        The amount of rotation in degrees
747		 */
748		public function pitch(angle:Number):void
749		{
750			rotate(Vector3D.X_AXIS, angle);
751		}
752		
753		/**
754		 * Rotates the 3d object around it's local y-axis
755		 *
756		 * @param    angle        The amount of rotation in degrees
757		 */
758		public function yaw(angle:Number):void
759		{
760			rotate(Vector3D.Y_AXIS, angle);
761		}
762		
763		/**
764		 * Rotates the 3d object around it's local z-axis
765		 *
766		 * @param    angle        The amount of rotation in degrees
767		 */
768		public function roll(angle:Number):void
769		{
770			rotate(Vector3D.Z_AXIS, angle);
771		}
772		
773		public function clone():Object3D
774		{
775			var clone:Object3D = new Object3D();
776			clone.pivotPoint = pivotPoint;
777			clone.transform = transform;
778			clone.name = name;
779			// todo: implement for all subtypes
780			return clone;
781		}
782		
783		/**
784		 * Rotates the 3d object directly to a euler angle
785		 *
786		 * @param    ax        The angle in degrees of the rotation around the x axis.
787		 * @param    ay        The angle in degrees of the rotation around the y axis.
788		 * @param    az        The angle in degrees of the rotation around the z axis.
789		 */
790		public function rotateTo(ax:Number, ay:Number, az:Number):void
791		{
792			_rotationX = ax*MathConsts.DEGREES_TO_RADIANS;
793			_rotationY = ay*MathConsts.DEGREES_TO_RADIANS;
794			_rotationZ = az*MathConsts.DEGREES_TO_RADIANS;
795			
796			invalidateRotation();
797		}
798		
799		/**
800		 * Rotates the 3d object around an axis by a defined angle
801		 *
802		 * @param    axis        The vector defining the axis of rotation
803		 * @param    angle        The amount of rotation in degrees
804		 */
805		public function rotate(axis:Vector3D, angle:Number):void
806		{
807			var m:Matrix3D = new Matrix3D();
808			m.prependRotation(angle, axis);
809			
810			var vec:Vector3D = m.decompose()[1];
811			
812			_rotationX += vec.x;
813			_rotationY += vec.y;
814			_rotationZ += vec.z;
815			
816			invalidateRotation();
817		}
818
819		private static var tempAxeX:Vector3D;
820		private static var tempAxeY:Vector3D;
821		private static var tempAxeZ:Vector3D;
822		/**
823		 * Rotates the 3d object around to face a point defined relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
824		 *
825		 * @param    target        The vector defining the point to be looked at
826		 * @param    upAxis        An optional vector used to define the desired up orientation of the 3d object after rotation has occurred
827		 */
828		public function lookAt(target:Vector3D, upAxis:Vector3D = null):void
829		{
830			if(!tempAxeX) tempAxeX = new Vector3D();
831			if(!tempAxeY) tempAxeY = new Vector3D();
832			if(!tempAxeZ) tempAxeZ = new Vector3D();
833			var xAxis:Vector3D = tempAxeX;
834			var yAxis:Vector3D = tempAxeY;
835			var zAxis:Vector3D = tempAxeZ;
836
837			var raw:Vector.<Number>;
838			
839			upAxis ||= Vector3D.Y_AXIS;
840
841			if (_transformDirty) {
842				updateTransform();
843			}
844
845			zAxis.x = target.x - _x;
846			zAxis.y = target.y - _y;
847			zAxis.z = target.z - _z;
848			zAxis.normalize();
849
850			xAxis.x = upAxis.y*zAxis.z - upAxis.z*zAxis.y;
851			xAxis.y = upAxis.z*zAxis.x - upAxis.x*zAxis.z;
852			xAxis.z = upAxis.x*zAxis.y - upAxis.y*zAxis.x;
853			xAxis.normalize();
854			
855			if (xAxis.length < .05) {
856				xAxis.x = upAxis.y;
857				xAxis.y = upAxis.x;
858				xAxis.z = 0;
859				xAxis.normalize();
860			}
861
862			yAxis.x = zAxis.y*xAxis.z - zAxis.z*xAxis.y;
863			yAxis.y = zAxis.z*xAxis.x - zAxis.x*xAxis.z;
864			yAxis.z = zAxis.x*xAxis.y - zAxis.y*xAxis.x;
865			
866			raw = Matrix3DUtils.RAW_DATA_CONTAINER;
867			
868			raw[uint(0)] = _scaleX*xAxis.x;
869			raw[uint(1)] = _scaleX*xAxis.y;
870			raw[uint(2)] = _scaleX*xAxis.z;
871			raw[uint(3)] = 0;
872			
873			raw[uint(4)] = _scaleY*yAxis.x;
874			raw[uint(5)] = _scaleY*yAxis.y;
875			raw[uint(6)] = _scaleY*yAxis.z;
876			raw[uint(7)] = 0;
877			
878			raw[uint(8)] = _scaleZ*zAxis.x;
879			raw[uint(9)] = _scaleZ*zAxis.y;
880			raw[uint(10)] = _scaleZ*zAxis.z;
881			raw[uint(11)] = 0;
882			
883			raw[uint(12)] = _x;
884			raw[uint(13)] = _y;
885			raw[uint(14)] = _z;
886			raw[uint(15)] = 1;
887			
888			_transform.copyRawDataFrom(raw);
889			
890			transform = transform;
891			
892			if (zAxis.z < 0) {
893				rotationY = (180 - rotationY);
894				rotationX -= 180;
895				rotationZ -= 180;
896			}
897		}
898		
899		/**
900		 * Cleans up any resources used by the current object.
901		 */
902		public function dispose():void
903		{
904		}
905		
906		/**
907		 * @inheritDoc
908		 */
909		public function disposeAsset():void
910		{
911			dispose();
912		}
913		
914		/**
915		 * Invalidates the transformation matrix, causing it to be updated upon the next request
916		 */
917		arcane function invalidateTransform():void
918		{
919			_transformDirty = true;
920		}
921		
922		protected function updateTransform():void
923		{
924			_pos.x = _x;
925			_pos.y = _y;
926			_pos.z = _z;
927			
928			_rot.x = _rotationX;
929			_rot.y = _rotationY;
930			_rot.z = _rotationZ;
931
932			if (!_pivotZero) {
933				_sca.x = 1;
934				_sca.y = 1;
935				_sca.z = 1;
936
937				_transform.recompose(_transformComponents);
938				_transform.appendTranslation(_pivotPoint.x, _pivotPoint.y, _pivotPoint.z);
939				_transform.prependTranslation(-_pivotPoint.x, -_pivotPoint.y, -_pivotPoint.z);
940				_transform.prependScale(_scaleX, _scaleY, _scaleZ);
941
942				_sca.x = _scaleX;
943				_sca.y = _scaleY;
944				_sca.z = _scaleZ;
945			}else{
946				_sca.x = _scaleX;
947				_sca.y = _scaleY;
948				_sca.z = _scaleZ;
949
950				_transform.recompose(_transformComponents);
951			}
952			
953			_transformDirty = false;
954			_positionDirty = false;
955			_rotationDirty = false;
956			_scaleDirty = false;
957		}
958		
959		public function get zOffset():int
960		{
961			return _zOffset;
962		}
963		
964		public function set zOffset(value:int):void
965		{
966			_zOffset = value;
967		}
968	}
969}