﻿package classes.away3d.core.base
{
	import classes.away3d.arcane;
	import classes.away3d.animators.*;
	import classes.away3d.containers.*;
	import classes.away3d.core.math.*;
	import classes.away3d.core.render.*;
	import classes.away3d.core.session.*;
	import classes.away3d.core.traverse.*;
	import classes.away3d.core.utils.*;
	import classes.away3d.core.vos.*;
	import classes.away3d.events.*;
	import classes.away3d.loaders.utils.*;
	import classes.away3d.primitives.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
    
    use namespace arcane;
    
	/**
	 * Dispatched when the local transform matrix of the 3d object changes.
	 * 
	 * @eventType away3d.events.Object3DEvent
	 * @see	#transform
	 */
	[Event(name="transformChanged",type="away3d.events.Object3DEvent")]
	
	/**
	 * Dispatched when the scene transform matrix of the 3d object changes.
	 * 
	 * @eventType away3d.events.Object3DEvent
	 * @see	#sceneTransform
	 */
	[Event(name="scenetransformChanged",type="away3d.events.Object3DEvent")]
	
	/**
	 * Dispatched when the parent scene of the 3d object changes.
	 * 
	 * @eventType away3d.events.Object3DEvent
	 * @see	#scene
	 */
	[Event(name="sceneChanged",type="away3d.events.Object3DEvent")]
	
	/**
	 * Dispatched when the render session property of the 3d object changes.
	 * 
	 * @eventType away3d.events.Object3DEvent
	 * @see	#session
	 */
	[Event(name="sessionChanged",type="away3d.events.Object3DEvent")]
	
	/**
	 * Dispatched when the contents of the 3d object updates.
	 * 
	 * @eventType away3d.events.Object3DEvent
	 */
	[Event(name="contentUpdated",type="away3d.events.Object3DEvent")]
	
	/**
	 * Dispatched when the bounding dimensions of the 3d object changes.
	 * 
	 * @eventType away3d.events.Object3DEvent
	 * @see	#minX
	 * @see	#maxX
	 * @see	#minY
	 * @see	#maxY
	 * @see	#minZ
	 * @see	#maxZ
	 */
	[Event(name="dimensionsChanged",type="away3d.events.Object3DEvent")]
    
	/**
	 * Dispatched when a user moves the cursor while it is over the 3d object.
	 * 
	 * @eventType away3d.events.MouseEvent3D
	 */
	[Event(name="mouseMove",type="away3d.events.MouseEvent3D")]
    
	/**
	 * Dispatched when a user presses the left hand mouse button while the cursor is over the 3d object.
	 * 
	 * @eventType away3d.events.MouseEvent3D
	 */
	[Event(name="mouseDown",type="away3d.events.MouseEvent3D")]
    
	/**
	 * Dispatched when a user releases the left hand mouse button while the cursor is over the 3d object.
	 * 
	 * @eventType away3d.events.MouseEvent3D
	 */
	[Event(name="mouseUp",type="away3d.events.MouseEvent3D")]
    
	/**
	 * Dispatched when a user moves the cursor over the 3d object.
	 * 
	 * @eventType away3d.events.MouseEvent3D
	 */
	[Event(name="mouseOver",type="away3d.events.MouseEvent3D")]
    
	/**
	 * Dispatched when a user moves the cursor away from the 3d object.
	 * 
	 * @eventType away3d.events.MouseEvent3D
	 */
	[Event(name="mouseOut",type="away3d.events.MouseEvent3D")]
	
	/**
	 * Dispatched when a user rolls over the 3d object.
	 * 
	 * @eventType away3d.events.MouseEvent3D
	 */
	[Event(name="rollOver",type="away3d.events.MouseEvent3D")]
    
	/**
	 * Dispatched when a user rolls out of the 3d object.
	 * 
	 * @eventType away3d.events.MouseEvent3D
	 */
	[Event(name="rollOut",type="away3d.events.MouseEvent3D")]
	
    /**
     * Base class for all 3d objects.
     */
    public class Object3D extends EventDispatcher implements IClonable
    {
    	/** @private */
        arcane var spriteVO:SpriteVO = new SpriteVO();
        /** @private */
        arcane var _mouseEnabled:Boolean = true;
		/** @private */
        arcane var _transformDirty:Boolean;
        /** @private */
        arcane var _transform:Matrix3D = new Matrix3D();
        /** @private */
        arcane var _sceneTransformDirty:Boolean = true;
        /** @private */
        arcane var _sceneTransform:Matrix3D = new Matrix3D();
        /** @private */
        arcane var _positionDirty:Boolean;
        /** @private */
        arcane var _scaleDirty:Boolean;
        /** @private */
        private var _dimensionsDirty:Boolean = false;
        /** @private */
        arcane var _boundingRadius:Number = 0;
        /** @private */
        arcane var _boundingScale:Number = 1;
        /** @private */
        arcane var _maxX:Number = 0;
        /** @private */
        arcane var _minX:Number = 0;
        /** @private */
        arcane var _maxY:Number = 0;
        /** @private */
        arcane var _minY:Number = 0;
        /** @private */
        arcane var _maxZ:Number = 0;
        /** @private */
        arcane var _minZ:Number = 0;
        /** @private */
        arcane var _lookingAtTarget:Vector3D = new Vector3D();
		
		
		//BSP
		     /** 
          * Indicates in which scene graph node this object resides (used for BSP dynamics)
          * @private
          */
        arcane var _sceneGraphMark : int = -1;
        
		/**
		 * added for scene graph-based culling
		 * @private
		 */
        arcane var _preCulled : Boolean; 
        
        /**
		 * added for scene graph-based culling
		 * @private
		 */
		arcane var _preCullClassification : int;
        
        /**
		 * added for BSP sorting
		 * @private
		 */
        arcane var _preSorted : Boolean;
        
        /** 
         * @private
         */
        arcane var _collider : Boolean;
        
        /**
         * Indicates whether this object is used for collision detection. Currently only used for dynamic objects in BSP trees.
         */
        public function get collider() : Boolean
		{
			return _collider;
		}
		
		public function set collider(collider : Boolean) : void
		{
			_collider = collider;
		}
		
		
		
		
		
		
         /** @private */
        public function get lookingAtTarget():Vector3D
        {
            return _lookingAtTarget;
        }
        /** @private */
        public function get parentMaxX():Number
        {
            return boundingRadius*_boundingScale + _transform.rawData[uint(12)];
        }
		/** @private */
        public function get parentMinX():Number
        {
            return -boundingRadius*_boundingScale + _transform.rawData[uint(12)];
        }
		/** @private */
        public function get parentMaxY():Number
        {
            return boundingRadius*_boundingScale + _transform.rawData[uint(13)];
        }
		/** @private */
        public function get parentMinY():Number
        {
            return -boundingRadius*_boundingScale + _transform.rawData[uint(13)];
        }
		/** @private */
        public function get parentMaxZ():Number
        {
            return boundingRadius*_boundingScale + _transform.rawData[uint(14)];
        }
		/** @private */
        public function get parentMinZ():Number
        {
            return -boundingRadius*_boundingScale + _transform.rawData[uint(14)];
        }
        /** @private */
        public function get parentBoundingRadius():Number
        {
        	return boundingRadius*_boundingScale;
        }
        /** @private */
        private function notifyVisibilityUpdate():void
        {
        	if (_session)
	        	_session.updateSession();
	        
			if (!hasEventListener(Object3DEvent.VISIBLITY_UPDATED))
                return;
                
			if (!_visibilityupdated)
				_visibilityupdated = new Object3DEvent(Object3DEvent.VISIBLITY_UPDATED, this);
            
            dispatchEvent(_visibilityupdated);
        }
        /** @private */
        private function notifyPositionChange():void
        {
			if (_positionDirty)
				return;
			
			_positionDirty = true;
			
			if (!hasEventListener(Object3DEvent.POSITION_CHANGED))
                return;
			
            if (!_positionchanged)
                _positionchanged = new Object3DEvent(Object3DEvent.POSITION_CHANGED, this);
            
            dispatchEvent(_positionchanged);
        }
        /** @private */
        private function notifyScaleChange():void
        {
			if (_scaleDirty)
				return;
			
			_scaleDirty = true;
        	
            if (!hasEventListener(Object3DEvent.SCALE_CHANGED))
                return;
			
            if (!_scalechanged)
                _scalechanged = new Object3DEvent(Object3DEvent.SCALE_CHANGED, this);
            
            dispatchEvent(_scalechanged);
        }
        /** @private */
        private function notifySceneTransformChange():void
        {
        	if (_sceneTransformDirty)
        		return;
        	
        	_sceneTransformDirty = true;
        	
        	if (_scene)
        		_scene.flagObject(this);
        		
        	if (_session)	
        		_session.updateSession();

        	
            if (!hasEventListener(Object3DEvent.SCENETRANSFORM_CHANGED))
                return;
			
            if (!_scenetransformchanged)
                _scenetransformchanged = new Object3DEvent(Object3DEvent.SCENETRANSFORM_CHANGED, this);
            
            dispatchEvent(_scenetransformchanged);
        }
        /** @private */
        private function notifySceneChange():void
        {
        	notifySceneTransformChange();
        	
            if (!hasEventListener(Object3DEvent.SCENE_CHANGED))
                return;
			
            if (!_scenechanged)
                _scenechanged = new Object3DEvent(Object3DEvent.SCENE_CHANGED, this);
            
            dispatchEvent(_scenechanged);
        }
         /** @private */
        private function notifySessionChange():void
        {
        	if (_ownSession)
        		_session = _ownSession;
        	else if (_parent)
        		_session = _parent.session;
        	else
        		_session = null;
        	
        	if (_session)	
        		_session.updateSession();
        	
            if (!hasEventListener(Object3DEvent.SESSION_CHANGED))
                return;
			
            if (!_sessionchanged)
                _sessionchanged = new Object3DEvent(Object3DEvent.SESSION_CHANGED, this);
            
            dispatchEvent(_sessionchanged);
        }
        /** @private */
        protected function notifyDimensionsChange():void
        {
            if (_dimensionsDirty)
            	return;
            
            _dimensionsDirty = true;
        	
           	if (!hasEventListener(Object3DEvent.DIMENSIONS_CHANGED))
                return;
            
            if (!_dimensionschanged)
                _dimensionschanged = new Object3DEvent(Object3DEvent.DIMENSIONS_CHANGED, this);
                
            dispatchEvent(_dimensionschanged);
            
        }
        /** @private */
		arcane function dispatchMouseEvent(event:MouseEvent3D):Boolean
        {
            if (!hasEventListener(event.type))
                return false;

            dispatchEvent(event);

            return true;
        }
        /** @private */
		arcane function onAnimatorStart(event:AnimatorEvent):void
        {
        	if (_playingAnimator)
        		_playingAnimator.stop();
        	
        	_playingAnimator = event.animator;
        }
		/** @private */
		arcane function onAnimatorStop(event:AnimatorEvent):void
        {
        	_playingAnimator = null;
        }
        
        private static var toDEGREES:Number = 180 / Math.PI;
        private static var toRADIANS:Number = Math.PI / 180;
		
		arcane var _id:int;
		private var _eulers:Vector3D = new Vector3D();
        private var _rotationDirty:Boolean;
        arcane var _contentDirty:Boolean;
        arcane var _rotationX:Number = 0;
        arcane var _rotationY:Number = 0;
        arcane var _rotationZ:Number = 0;
        arcane var _scaleX:Number = 1;
        arcane var _scaleY:Number = 1;
        arcane var _scaleZ:Number = 1;
        protected var _pivotPoint:Vector3D = new Vector3D();
        private var _scenePivotPoint:Vector3D = new Vector3D();
        arcane var _scene:Scene3D;
        private var _oldscene:Scene3D;
        private var _parent:ObjectContainer3D;
		private var _quaternion:Quaternion = new Quaternion();
		private var _rot:Vector3D;
		private var _sca:Vector3D;
        private var _pivotZero:Boolean;
		private var _vector:Vector3D;
    	private var _flipY:Matrix3D = new Matrix3D();
    	private var _rotationTransform:Matrix3D = new Matrix3D();
    	private var _upAxis:Vector3D = new Vector3D(0, -1, 0);
    	
    	private var _visibilityupdated:Object3DEvent;      
        private var _positionchanged:Object3DEvent;
        private var _scalechanged:Object3DEvent;
        private var _scenetransformchanged:Object3DEvent;
        private var _scenechanged:Object3DEvent;
        private var _sessionchanged:Object3DEvent;
        private var _dimensionschanged:Object3DEvent;
		arcane var _session:AbstractSession;
		private var _ownSession:AbstractSession;
		private var _ownCanvas:Boolean;
		private var _filters:Array;
		private var _alpha:Number;
		private var _blendMode:String;
		private var _renderer:Renderer;
		private var _debugBoundingSphere:WireSphere;
		private var _debugBoundingBox:WireCube;
		private var _visible:Boolean;
		private var _playingAnimator:Animator;
		
        private function updateSceneTransform():void
        {
            _sceneTransform.rawData = _parent.sceneTransform.rawData;
            _sceneTransform.prepend(transform);
            
            if (!_pivotZero) {
				_scenePivotPoint = _sceneTransform.deltaTransformVector(_pivotPoint);
				_sceneTransform.position = _sceneTransform.position.subtract(_scenePivotPoint);
            }
            
            //calulate the inverse transform of the scene (used for lights and bones)
            inverseSceneTransform.rawData = _sceneTransform.rawData;
            inverseSceneTransform.invert();
            
			_sceneTransformDirty = false;
        }
		
        private function updateRotation():void
        {
            _rot = Vector3DUtils.matrix2euler(_transform);
            _rotationX = _rot.x;
            _rotationY = _rot.y;
            _rotationZ = _rot.z;
    		
            _rotationDirty = false;
        }
		
		private function onParentVisibilityUpdate(event:Object3DEvent):void
        {
        	notifyVisibilityUpdate();
        }
        
        private function onParentSessionChange(event:Object3DEvent):void
        {
			if (_ownSession && event.object.session.parent)
				event.object.session.parent.removeChildSession(_ownSession);
    		
        	if (_ownSession && _parent.session)
        		_parent.session.addChildSession(_ownSession);
        		
            if (!_ownSession && _session != _parent.session)
            	notifySessionChange();
        }
        
        private function onParentSceneChange(event:Object3DEvent):void
        {
        	_oldscene = _scene;
        	
            if (_scene)
        		_scene.clearId(_id);
        	
            _scene = _parent.scene;
            
        	if (_scene)
        		_scene.setId(this);
            
            notifySceneChange();
        }
		
        private function onParentTransformChange(event:Object3DEvent):void
        {
			notifySceneTransformChange();
        }
        
        /**
         * Instance of the Init object used to hold and parse default property values
         * specified by the initialiser object in the 3d object constructor.
         */
		protected var ini:Init;
        
        protected function updateTransform():void
        {
        	if (_rotationDirty) 
                updateRotation();
            
            _quaternion.euler2quaternion(_rotationY, _rotationZ, -_rotationX); // Swapped
            
            _vector = _transform.position;
            
            _transform = Matrix3DUtils.quaternion2matrix(_quaternion);
            
            _transform.prependScale(_scaleX, _scaleY, _scaleZ);
            
            _transform.position = _vector;
			
            _transformDirty = false;
        }
        
        protected function updateDimensions():void
        {
        	_dimensionsDirty = false;
        	
        	if (debugbb)
            {
            	if (!_debugBoundingBox) {
					_debugBoundingBox = new WireCube({material:"#333333"});
					//_scene.setId(_debugBoundingBox);
            	}
            	
                if (_boundingRadius) {
                	_debugBoundingBox.visible = true;
                	_debugBoundingBox.v000.setValue(_minX, _minY, _minZ);
                	_debugBoundingBox.v100.setValue(_maxX, _minY, _minZ);
                	_debugBoundingBox.v010.setValue(_minX, _maxY, _minZ);
                	_debugBoundingBox.v110.setValue(_maxX, _maxY, _minZ);
                	_debugBoundingBox.v001.setValue(_minX, _minY, _maxZ);
                	_debugBoundingBox.v101.setValue(_maxX, _minY, _maxZ);
                	_debugBoundingBox.v011.setValue(_minX, _maxY, _maxZ);
                	_debugBoundingBox.v111.setValue(_maxX, _maxY, _maxZ);
                	_debugBoundingBox.geometry.updateGeometry();
                } else {
                	debugBoundingBox.visible = false;
                }
            }
            
            if (debugbs)
            {
            	if (!_debugBoundingSphere) {
					_debugBoundingSphere = new WireSphere({material:"#cyan", segmentsW:16, segmentsH:12});
					//_scene.setId(_debugBoundingSphere);
            	}
            	
                if (_boundingRadius) {
					_debugBoundingSphere.visible = true;
					_debugBoundingSphere.radius = _boundingRadius;
					_debugBoundingSphere.updatePrimitive();
					_debugBoundingSphere.applyPosition(-_pivotPoint.x, -_pivotPoint.y, -_pivotPoint.z);
					_debugBoundingSphere.geometry.updateGeometry();
            	} else {
            		debugBoundingSphere.visible = false;
            	}
            }
        }
        
		/**
		 * Elements use their furthest point from the camera when z-sorting
		 */
        public var pushback:Boolean;
		
		/**
		 * Elements use their nearest point to the camera when z-sorting
		 */
        public var pushfront:Boolean;
        
		/**
		 * Defines an additional offset to the x coordinate used on mesh elements or objects with ownCanvas set to true
		 */
        public var screenXOffset:Number;
        
		/**
		 * Defines an additional offset to the y coordinate used on mesh elements or objects with ownCanvas set to true
		 */
        public var screenYOffset:Number;
        
		/**
		 * Defines an additional offset to the z-sorting algorithm used on mesh elements or objects with ownCanvas set to true
		 */
        public var screenZOffset:Number;
        
    	/**
    	 * Returns the inverse of sceneTransform.
    	 * 
    	 * @see #sceneTransform
    	 */
        public var inverseSceneTransform:Matrix3D = new Matrix3D();
		
    	/**
    	 * An optional name string for the 3d object.
    	 * 
    	 * Can be used to access specific 3d object in a scene by calling the <code>getChildByName</code> method on the parent <code>ObjectContainer3D</code>.
    	 * 
    	 * @see away3d.containers.ObjectContainer3D#getChildByName()
    	 */
        public var name:String;
        
    	/**
    	 * An optional untyped object that can contain used-defined properties
    	 */
        public var extra:Object;
		
    	/**
    	 * Defines whether mouse events are received on the 3d object
    	 */
        public var mouseEnabled:Boolean = true;
        
    	/**
    	 * Defines whether a hand cursor is displayed when the mouse rolls over the 3d object.
    	 */
        public var useHandCursor:Boolean = false;
        
        /**
        * Reference container for all materials used in the container. Populated in <code>Collada</code>, <code>Max3DS</code> and <code>Obj</code> parsers.
        * 
        * @see away3d.loaders.Collada
        * @see away3d.loaders.Max3DS
        * @see away3d.loaders.Obj
        */
    	public var materialLibrary:MaterialLibrary;

        /**
        * Reference container for all animations used in the container. Populated in <code>Collada</code> parsers.
        * 
        * @see away3d.loaders.Collada
        */
    	public var animationLibrary:AnimationLibrary;

        /**
        * Reference container for all geometries used in the container. Populated in <code>Collada</code> and <code>Max3DS</code> parsers.
        * 
        * @see away3d.loaders.Collada
        * @see away3d.loaders.Max3DS
        */
    	public var geometryLibrary:GeometryLibrary;
		
        /**
        * Indicates whether a debug bounding box should be rendered around the 3d object.
        */
        public var debugbb:Boolean;
		
        /**
        * Indicates whether a debug bounding sphere should be rendered around the 3d object.
        */
        public var debugbs:Boolean;
		
		public function get debugBoundingBox():WireCube
		{	
            if (_dimensionsDirty || !_debugBoundingBox)
            	updateDimensions();
            
			return _debugBoundingBox;
		}
		
		public function get debugBoundingSphere():WireSphere
		{
            if (_dimensionsDirty || !_debugBoundingSphere)
            	updateDimensions();
            
            return _debugBoundingSphere;
		}
		
    	/**
    	 * The render session used by the 3d object
    	 */
        public function get session():AbstractSession
        {
        	return _session;
        }
        
    	/**
    	 * Returns the bounding radius of the 3d object
    	 */
        public function get boundingRadius():Number
        {
            if (_dimensionsDirty)
            	updateDimensions();
           
           return _boundingRadius;
        }
        
    	/**
    	 * Returns the maximum x value of the 3d object
    	 * 
    	 * @see	#x
    	 */
        public function get maxX():Number
        {
            if (_dimensionsDirty)
            	updateDimensions();
           
           return _maxX;
        }
        
    	/**
    	 * Returns the minimum x value of the 3d object
    	 * 
    	 * @see	#x
    	 */
        public function get minX():Number
        {
            if (_dimensionsDirty)
            	updateDimensions();
           
           return _minX;
        }
        
    	/**
    	 * Returns the maximum y value of the 3d object
    	 * 
    	 * @see	#y
    	 */
        public function get maxY():Number
        {
            if (_dimensionsDirty)
            	updateDimensions();
           
           return _maxY;
        }
        
    	/**
    	 * Returns the minimum y value of the 3d object
    	 * 
    	 * @see	#y
    	 */
        public function get minY():Number
        {
            if (_dimensionsDirty)
            	updateDimensions();
           
           return _minY;
        }
        
    	/**
    	 * Returns the maximum z value of the 3d object
    	 * 
    	 * @see	#z
    	 */
        public function get maxZ():Number
        {
            if (_dimensionsDirty)
            	updateDimensions();
           
           return _maxZ;
        }
        
    	/**
    	 * Returns the minimum z value of the 3d object
    	 * 
    	 * @see	#z
    	 */
        public function get minZ():Number
        {
            if (_dimensionsDirty)
            	updateDimensions();
           
           return _minZ;
        }
				
		/**
		* Boundary width of the 3d object
		* 
		*@return	The width of the object
		*/
		public function get objectWidth():Number
		{
            if (_dimensionsDirty)
            	updateDimensions();
           
			return _maxX - _minX;
		}
		
		/**
		* Boundary height of the 3d object
		* 
		*@return	The height of the mesh
		*/
		public function get objectHeight():Number
		{
            if (_dimensionsDirty)
            	updateDimensions();
           
			return _maxY - _minY;
		}
		
		/**
		* Boundary depth of the 3d object
		* 
		*@return	The depth of the mesh
		*/
		public function get objectDepth():Number
		{
            if (_dimensionsDirty)
            	updateDimensions();
           
			return  _maxZ - _minZ;
		}
        
    	/**
    	 * Defines whether the 3d object is visible in the scene
    	 */
        public function get visible():Boolean
        {
            return _visible;
        }
    
        public function set visible(val:Boolean):void
        {
        	if (_visible == val)
        		return;
        	
        	_visible = val;
        	
        	notifyVisibilityUpdate();
        }
        
    	/**
    	 * Defines whether the contents of the 3d object are rendered using it's own render session
    	 */
        public function get ownCanvas():Boolean
        {
            return _ownCanvas;
        }
    
        public function set ownCanvas(val:Boolean):void
        {
        	if (_ownCanvas == val)
        		return;
        	
        	if (val)
        		ownSession = new SpriteSession();
        	else if (this is Scene3D)
        		throw new Error("Scene cannot have ownCanvas set to false");
        	else
        		ownSession = null;
        }
        
    	/**
    	 * An optional renderer object that can be used to render the contents of the object.
    	 * 
    	 * Requires <code>ownCanvas</code> to be set to true.
    	 * 
    	 * @see #ownCanvas
    	 */
        public function get renderer():Renderer
        {
            return _renderer;
        }
    
        public function set renderer(val:Renderer):void
        {
        	if (_renderer == val)
        		return;
        	
        	_renderer = val;
        	
        	if (_ownSession)
        		_ownSession.renderer = _renderer;
        	
        	if (_session)	
        		_session.updateSession();
        }
        
    	/**
    	 * An optional array of filters that can be applied to the 3d object.
    	 * 
    	 * Requires <code>ownCanvas</code> to be set to true.
    	 * 
    	 * @see #ownCanvas
    	 */
        public function get filters():Array
        {
            return _filters;
        }
    
        public function set filters(val:Array):void
        {
        	if (_filters == val)
        		return;
        	
        	_filters = val;
        	
        	if (_ownSession)
        		_ownSession.filters = _filters;
        }
        
    	/**
    	 * An optional alpha value that can be applied to the 3d object.
    	 * 
    	 * Requires <code>ownCanvas</code> to be set to true.
    	 * 
    	 * @see #ownCanvas
    	 */
        public function get alpha():Number
        {
            return _alpha;
        }
    
        public function set alpha(val:Number):void
        {
        	if (_alpha == val)
        		return;
        	
        	_alpha = val;
        	
        	if (_ownSession)
        		_ownSession.alpha = _alpha;
        }
        
    	/**
    	 * An optional blend mode that can be applied to the 3d object.
    	 * 
    	 * Requires <code>ownCanvas</code> to be set to true.
    	 * 
    	 * @see #ownCanvas
    	 */
        public function get blendMode():String
        {
            return _blendMode;
        }
    
        public function set blendMode(val:String):void
        {
        	if (_blendMode == val)
        		return;
        	
        	_blendMode = val;
        	
        	if (_ownSession)
        		_ownSession.blendMode = _blendMode;
        }
        
    	/**
    	 * Defines a unique render session for the 3d object.
    	 */
        public function get ownSession():AbstractSession
        {
            return _ownSession;
        }
    
        public function set ownSession(val:AbstractSession):void
        {
        	if (_ownSession == val)
        		return;
        	
        	if (_ownSession) {
		    	//remove old session from parent session
        		if (_parent && _parent.session)
        			_parent.session.removeChildSession(_ownSession);
        		
	        	//reset old session children
        		_ownSession.clearChildSessions();
				_ownSession.renderer = null;
				_ownSession.object3D = null;
        	}
        	
        	//set new session
        	_ownSession = val;
        	
        	if (_ownSession) {
	        	//add new session to parent session
	        	if (_parent && _parent.session)
	        		_parent.session.addChildSession(_ownSession);
	        	
		    	//reset new session children and session properties
        		_ownSession.clearChildSessions();
        		_ownSession.renderer = _renderer;
	        	_ownSession.filters = _filters;
	    		_ownSession.alpha = _alpha;
				_ownSession.blendMode = _blendMode;
				_ownSession.object3D = this;
        	} else if (this is Scene3D) {
        		throw new Error("Scene cannot have ownSession set to null");
        	}
        	
        	
        	//update ownCanvas property
        	if (_ownSession)
        		_ownCanvas = true;
        	else
        		_ownCanvas = false;
        	
        	notifySessionChange();
        }
        
    	/**
    	 * Defines the x coordinate of the 3d object relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
    	 */
        public function get x():Number
        {
            return _transform.rawData[uint(12)];
        }
    
        public function set x(value:Number):void
        {
            if (isNaN(value))
                throw new Error("isNaN(x)");
			
			if (int(1000*_transform.rawData[uint(12)]) == int(1000*value))
				return;
			
            if (value == Infinity)
                Debug.warning("x == Infinity");

            if (value == -Infinity)
                Debug.warning("x == -Infinity");

            _transform.appendTranslation(value - _transform.rawData[12], 0, 0);
            
			notifyPositionChange();
			
			notifySceneTransformChange();
        }
		
    	/**
    	 * Defines the y coordinate of the 3d object relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
    	 */
        public function get y():Number
        {
            return _transform.rawData[uint(13)];
        }
    
        public function set y(value:Number):void
        {
            if (isNaN(value))
                throw new Error("isNaN(y)");
			
			if (int(1000*_transform.rawData[uint(13)]) == int(1000*value))
				return;
			
            if (value == Infinity)
                Debug.warning("y == Infinity");

            if (value == -Infinity)
                Debug.warning("y == -Infinity");

            _transform.appendTranslation(0, value - _transform.rawData[uint(13)], 0);
			
			notifyPositionChange();
			
			notifySceneTransformChange();
        }
		
    	/**
    	 * Defines the z coordinate of the 3d object relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
    	 */
        public function get z():Number
        {
            return _transform.rawData[uint(14)];
        }
    	
        public function set z(value:Number):void
        {
            if (isNaN(value))
                throw new Error("isNaN(z)");
			
			if (int(1000*_transform.rawData[uint(14)]) == int(1000*value))
				return;
			
            if (value == Infinity)
                Debug.warning("z == Infinity");

            if (value == -Infinity)
                Debug.warning("z == -Infinity");

            _transform.appendTranslation(0, 0, value - _transform.rawData[uint(14)]);
			
			notifyPositionChange();
			
			notifySceneTransformChange();
        }
		
    	/**
    	 * 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>.
    	 */
        public function get rotationX():Number
        {
            if (_rotationDirty) 
                updateRotation();
    
            return _rotationX*toDEGREES;
        }
    
        public function set rotationX(rot:Number):void
        {
        	if (rotationX == rot)
        		return;
        	
            _rotationX = rot*toRADIANS;
            
			_transformDirty = true;
            
			notifySceneTransformChange();
        }
		
    	/**
    	 * 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>.
    	 */
        public function get rotationY():Number
        {
            if (_rotationDirty) 
                updateRotation();
    
            return _rotationY*toDEGREES;
        }
    
        public function set rotationY(rot:Number):void
        {
        	if (rotationY == rot)
        		return;
        	
            _rotationY = rot*toRADIANS;
            
			_transformDirty = true;
            
			notifySceneTransformChange();
        }
		
    	/**
    	 * 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>.
    	 */
        public function get rotationZ():Number
        {
            if (_rotationDirty) 
                updateRotation();
    
            return _rotationZ*toDEGREES;
        }
    
        public function set rotationZ(rot:Number):void
        {
			
        	if (rotationZ == rot)
        		return;
        	
            _rotationZ = rot*toRADIANS;
            
			_transformDirty = true;
            
			notifySceneTransformChange();
        }
		
    	/**
    	 * Defines the scale of the 3d object along the x-axis, relative to local coordinates.
    	 */
        public function get scaleX():Number
        {
            return _scaleX;
        }
    
        public function set scaleX(scale:Number):void
        {
        	if (_scaleX == scale)
        		return;
        	
            _scaleX = scale;
            
			_transformDirty = true;
			
            notifyScaleChange();
            
			notifySceneTransformChange();
        }
		
    	/**
    	 * Defines the scale of the 3d object along the y-axis, relative to local coordinates.
    	 */
        public function get scaleY():Number
        {
            return _scaleY;
        }
    
        public function set scaleY(scale:Number):void
        {
        	if (_scaleY == scale)
        		return;
        	
            _scaleY = scale;
            
			_transformDirty = true;
			
            notifyScaleChange();
            
			notifySceneTransformChange();
        }
		
    	/**
    	 * Defines the scale of the 3d object along the z-axis, relative to local coordinates.
    	 */
        public function get scaleZ():Number
        {
            return _scaleZ;
        }
    
        public function set scaleZ(scale:Number):void
        {
        	if (_scaleZ == scale)
        		return;
        	
            _scaleZ = scale;
            
			_transformDirty = true;
			
            notifyScaleChange();
            
			notifySceneTransformChange();
        }
        
    	/**
    	 * Defines the position of the 3d object, relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
    	 */
        public function get position():Vector3D
        {
            return transform.position;
        }
		
        public function set position(value:Vector3D):void
        {
            _transform.position = value;
			
            notifyPositionChange();
			
			notifySceneTransformChange();
        }
        
    	/**
    	 * Defines the rotation of the 3d object as a <code>Vector3D</code> object containing euler angles for rotation around x, y and z axis.
    	 */
        public function get eulers():Vector3D
        {
        	if (_rotationDirty) 
                updateRotation();
            
            _eulers.x = _rotationX*toDEGREES;
            _eulers.y = _rotationY*toDEGREES;
            _eulers.z = _rotationZ*toDEGREES;
            
            return _eulers;
        }
		
        public function set eulers(value:Vector3D):void
        {
            _rotationX = value.x*toRADIANS;
            _rotationY = value.y*toRADIANS;
            _rotationZ = value.z*toRADIANS;
			
			_transformDirty = true;
            
			notifySceneTransformChange();
        }
        
    	/**
    	 * Defines the transformation of the 3d object, relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
    	 */
        public function get transform():Matrix3D
        {
            if (_transformDirty) 
                updateTransform();
            
			_positionDirty = false;
			_scaleDirty = false;
			
            return _transform;
        }

        public function set transform(value:Matrix3D):void
        {
            if (Matrix3DUtils.compare(_transform, value))
                return;
			
			if (_transform.rawData[uint(12)] != value.rawData[uint(12)] || _transform.rawData[uint(13)] != value.rawData[uint(13)] || _transform.rawData[uint(14)] != value.rawData[uint(14)]) {
				notifyPositionChange();
			}
			
            _transform = value.clone();
            
            _sca = Vector3DUtils.matrix2scale(_transform);
        	
    		if (_scaleX != _sca.x || _scaleY != _sca.y || _scaleZ != _sca.z) {
    			_scaleX = _sca.x;
    			_scaleY = _sca.y;
    			_scaleZ = _sca.z;
    			
    			notifyScaleChange();
    		}
			
            _transformDirty = false;
            _rotationDirty = true;
    		
			notifySceneTransformChange();
        }
		
    	/**
    	 * Defines the parent of the 3d object.
    	 */
        public function get parent():ObjectContainer3D
        {
            return _parent;
        }
		
        public function set parent(value:ObjectContainer3D):void
        {
        	if (this is Scene3D)
        		 throw new Error("Scene cannot be parented");
			
            if (value == _parent)
                return;
			
            _oldscene = _scene;
			
            if (_parent != null) {
            	_parent.removeOnVisibilityUpdate(onParentVisibilityUpdate);
            	_parent.removeOnSessionChange(onParentSessionChange);
                _parent.removeOnSceneChange(onParentSceneChange);
                _parent.removeOnSceneTransformChange(onParentTransformChange);
                
                _parent.internalRemoveChild(this);
                
                if (_ownSession && _parent.session)
					_parent.session.removeChildSession(_ownSession);
            }
			
            _parent = value;
            _scene = _parent ? _parent.scene : null;
			
            if (_parent != null) {
            	_parent.internalAddChild(this);
            	
            	_parent.addOnVisibilityUpdate(onParentVisibilityUpdate);
                _parent.addOnSessionChange(onParentSessionChange);
                _parent.addOnSceneChange(onParentSceneChange);
                _parent.addOnSceneTransformChange(onParentTransformChange);
                
                if (_ownSession && _parent.session)
					_parent.session.addChildSession(_ownSession);
				
				notifySceneTransformChange();
            }
			
            if (_scene != _oldscene) {
            	if (_oldscene)
            		_oldscene.clearId(_id);
            	if (_scene)
            		_scene.setId(this);
                notifySceneChange();
            }
            
			if (!_ownSession && (!_parent || _session != _parent.session))
				notifySessionChange();
        }
        
    	/**
    	 * Returns the transformation of the 3d object, relative to the global coordinates of the <code>Scene3D</code> object.
    	 */
        public function get sceneTransform():Matrix3D
        {
        	//for camera transforms
            if (_scene == null || _scene == this) {
            	_sceneTransformDirty = false;
                return transform;
            }
			
            if (_transformDirty) 
                updateTransform();
			
            if (_sceneTransformDirty) 
                updateSceneTransform();
        	
            return _sceneTransform;
        }
        
		/**
		 * Defines the local point around which the object rotates.
		 * 
		 * @param	pivotPoint		The Number 3D for the new pivot point
		 */
        public function get pivotPoint():Vector3D
        {
        	return _pivotPoint;
        }
		public function set pivotPoint(pivot:Vector3D):void
        {
			_pivotPoint = pivot.clone();
			
        	_pivotZero = (!_pivotPoint.x && !_pivotPoint.y && !_pivotPoint.z);
        	
        	notifyDimensionsChange();
        	
        	notifySceneTransformChange();
		}
    	
    	/**
    	 * Returns the position of the 3d object, relative to the global coordinates of the <code>Scene3D</code> object.
    	 */
        public function get scenePosition():Vector3D
        {
            return sceneTransform.position;
        }
		
    	/**
    	 * Returns the parent scene of the 3d object
    	 */
        public function get scene():Scene3D
        {
            return _scene;
        }
		
        public function get pivotZero():Boolean
        {
        	return _pivotZero;
        }
        
        public function get scenePivotPoint():Vector3D
        {
        	if (_sceneTransformDirty)
        		updateSceneTransform();
        		
        	return _scenePivotPoint;
        }
        
        public function get id():int
        {
        	return _id;
        }
        
    	/**
    	 * @private
    	 */
        public function Object3D(init:Object = null):void
        {
            ini = Init.parse(init);
			
        	if (this is Scene3D)
        		_scene = this as Scene3D;
        	else
            	parent = ini.getObject3D("parent") as ObjectContainer3D;
        	
            name = ini.getString("name", name);
            ownSession = ini.getObject("ownSession", AbstractSession) as AbstractSession;
            ownCanvas = ini.getBoolean("ownCanvas", ownCanvas);
            visible = ini.getBoolean("visible", true);
            mouseEnabled = ini.getBoolean("mouseEnabled", mouseEnabled);
            useHandCursor = ini.getBoolean("useHandCursor", useHandCursor);
            renderer = ini.getObject("renderer", Renderer) as Renderer;
            filters = ini.getArray("filters");
            alpha = ini.getNumber("alpha", 1);
            blendMode = ini.getString("blendMode", BlendMode.NORMAL);
            debugbb = ini.getBoolean("debugbb", false);
            debugbs = ini.getBoolean("debugbs", false);
            pushback = ini.getBoolean("pushback", false);
            pushfront = ini.getBoolean("pushfront", false);
            screenXOffset = ini.getNumber("screenXOffset", 0);
            screenYOffset = ini.getNumber("screenYOffset", 0);
            screenZOffset = ini.getNumber("screenZOffset", 0);
            x = ini.getNumber("x", 0);
            y = ini.getNumber("y", 0);
            z = ini.getNumber("z", 0);        
            rotationX = ini.getNumber("rotationX", 0);
            rotationY = ini.getNumber("rotationY", 0);
            rotationZ = ini.getNumber("rotationZ", 0);
            pivotPoint = ini.getVector3D("pivotPoint") || new Vector3D();
            extra = ini.getObject("extra");
            scale( ini.getNumber("scale", 1) );
			
			_flipY.appendScale(1, -1, 1);
			
			_sceneTransformDirty = false;
		}
		
    	/**
    	 * Scales the contents of the 3d object.
    	 * 
    	 * @param	scale	The scaling value
    	 */
        public function scale(scale:Number):void
        {
        	_scaleX = _scaleY = _scaleZ = scale;
        	_transformDirty = true;
        	
        	notifyDimensionsChange();
        	
        	notifySceneTransformChange();
        }
        
    	/**
    	 * Calulates the absolute distance between the local 3d object position and the position of the given 3d object
    	 * 
    	 * @param	obj		The 3d object to use for calulating the distance
    	 * @return			The scalar distance between objects
    	 * 
    	 * @see	#position
    	 */
        public function distanceTo(obj:Object3D):Number
        {
            var m1:Matrix3D = _scene == this ? transform : sceneTransform;
            var m2:Matrix3D = obj.scene == obj ? obj.transform : obj.sceneTransform;

            var dx:Number = m1.rawData[uint(12)] - m2.rawData[uint(12)];
            var dy:Number = m1.rawData[uint(13)] - m2.rawData[uint(13)];
            var dz:Number = m1.rawData[uint(14)] - m2.rawData[uint(14)];
    
            return Math.sqrt(dx*dx + dy*dy + dz*dz);
        }
    	
    	/**
    	 * Used when traversing the scenegraph
    	 * 
    	 * @param	tranverser		The traverser object
    	 * 
    	 * @see	away3d.core.traverse.BlockerTraverser
    	 * @see	away3d.core.traverse.PrimitiveTraverser
    	 * @see	away3d.core.traverse.ProjectionTraverser
    	 * @see	away3d.core.traverse.TickTraverser
    	 */
        public function traverse(traverser:Traverser):void
        {
        	
            if (traverser.match(this))
            {
            	
                traverser.enter(this);
				traverser.apply(this);
                traverser.leave(this);
               
            }
        }
        
        /**
         * Moves the 3d object forwards along it's local z axis
         * 
         * @param	distance	The length of the movement
         */
        public function moveForward(distance:Number):void 
        {
			translate(Vector3D.Z_AXIS, distance); 
        }
        
        /**
         * Moves the 3d object backwards along it's local z axis
         * 
         * @param	distance	The length of the movement
         */
        public function moveBackward(distance:Number):void 
        { 
            translate(Vector3D.Z_AXIS, -distance); 
        }
        
        /**
         * Moves the 3d object backwards along it's local x axis
         * 
         * @param	distance	The length of the movement
         */
        public function moveLeft(distance:Number):void 
        { 
            translate(Vector3D.X_AXIS, -distance); 
        }
        
        /**
         * Moves the 3d object forwards along it's local x axis
         * 
         * @param	distance	The length of the movement
         */
        public function moveRight(distance:Number):void 
        {
			translate(Vector3D.X_AXIS, distance); 
        }
        
        /**
         * Moves the 3d object forwards along it's local y axis
         * 
         * @param	distance	The length of the movement
         */
        public function moveUp(distance:Number):void 
        {
			translate(Vector3D.Y_AXIS, distance); 
        }
        
        /**
         * Moves the 3d object backwards along it's local y axis
         * 
         * @param	distance	The length of the movement
         */
        public function moveDown(distance:Number):void 
        { 
            translate(Vector3D.Y_AXIS, -distance); 
        }
        
        /**
         * Moves the 3d object directly to a point in space
         * 
		 * @param	dx		The amount of movement along the local x axis.
		 * @param	dy		The amount of movement along the local y axis.
		 * @param	dz		The amount of movement along the local z axis.
         */
        public function moveTo(dx:Number, dy:Number, dz:Number):void
        {
        	if (_transform.rawData[uint(12)] == dx && _transform.rawData[uint(13)] == dy && _transform.rawData[uint(14)] == dz)
        		return;
        	
            _transform.position = new Vector3D(dx, dy, dz);
            
            notifyPositionChange();
            
            notifySceneTransformChange();
        }
        
		/**
		 * Adjusts the pivot point of the object so that it lies at the center of it's geoemtry.
		 */
		public function centerPivot():void
        {
        	var offset:Vector3D = new Vector3D((maxX + minX)/2, (maxY + minY)/2, (maxZ + minZ)/2);
        	movePivot(offset.x, offset.y, offset.z);
        	offset = transform.transformVector(offset);
			moveTo(x + offset.x, y + offset.y, z + offset.z);
        }
		/**
		 * Moves the local point around which the object rotates.
		 * 
		 * @param	dx		The amount of movement along the local x axis.
		 * @param	dy		The amount of movement along the local y axis.
		 * @param	dz		The amount of movement along the local z axis.
		 */
        public function movePivot(dx:Number, dy:Number, dz:Number):void
        {
        	_pivotPoint.x = dx;
        	_pivotPoint.y = dy;
        	_pivotPoint.z = dz;
			 
        	_pivotZero = (!dx && !dy && !dz);
        	
        	notifyDimensionsChange();
        	
			notifySceneTransformChange();
        }
        
		/**
		 * Moves the 3d object along a vector by a defined length
		 * 
		 * @param	axis		The vector defining the axis of movement
		 * @param	distance	The length of the movement
		 */
        public function translate(axis:Vector3D, distance:Number):void
        {
        	axis.normalize();
        	
            _vector = transform.deltaTransformVector(axis);
            
            _vector.scaleBy(distance);
            
            position = position.add(_vector);
        }
        
        /**
         * Rotates the 3d object around it's local x-axis
         * 
         * @param	angle		The amount of rotation in degrees
         */
        public function pitch(angle:Number):void
		{
			rotate(Vector3D.X_AXIS, angle);
        }
        
        /**
         * Rotates the 3d object around it's local y-axis
         * 
         * @param	angle		The amount of rotation in degrees
         */
        public function yaw(angle:Number):void
		{
			rotate(Vector3D.Y_AXIS, angle);
        }
        
        /**
         * Rotates the 3d object around it's local z-axis
         * 
         * @param	angle		The amount of rotation in degrees
         */
        public function roll(angle:Number):void
		{
			rotate(Vector3D.Z_AXIS, angle);
        }
        
        /**
         * Rotates the 3d object directly to a euler angle
    	 * 
    	 * @param	ax		The angle in degrees of the rotation around the x axis.
    	 * @param	ay		The angle in degrees of the rotation around the y axis.
    	 * @param	az		The angle in degrees of the rotation around the z axis.
    	 */
		public function rotateTo(ax:Number, ay:Number, az:Number):void
		{
			_rotationX = ax*toRADIANS;
            _rotationY = ay*toRADIANS;
            _rotationZ = az*toRADIANS;
            _rotationDirty = false;
            _transformDirty = true;
			
			notifySceneTransformChange();
		}
		
		/**
		 * Rotates the 3d object around an axis by a defined angle
		 * 
		 * @param	axis		The vector defining the axis of rotation
		 * @param	angle		The amount of rotation in degrees
		 */
        public function rotate(axis:Vector3D, angle:Number):void
        {
        	axis.normalize();
        	
			transform.prependRotation(angle, axis);
			
            _rotationDirty = true;
            
            notifySceneTransformChange();
        }
		
		/**
		 * Rotates the 3d object around to face a point defined relative to the local coordinates of the parent <code>ObjectContainer3D</code>.
		 * 
		 * @param	target		The vector defining the point to be looked at
		 * @param	upAxis		An optional vector used to define the desired up orientation of the 3d object after rotation has occurred
		 */
        public function lookAt(target:Vector3D, upAxis:Vector3D = null):void
        {
        	_lookingAtTarget = target;
        	
        	var oldTransform:Matrix3D = transform.clone();
        	
        	if (upAxis) {
        		//make sure upAxis uses absolute coordinates
				var zAxis:Vector3D = target.subtract(position);
				zAxis.y = 0;
				zAxis.normalize();
				_rotationTransform.rawData = _flipY.rawData;
				_rotationTransform.appendRotation(-Math.acos(Vector3D.Z_AXIS.dotProduct(zAxis))*180/Math.PI, Vector3D.Y_AXIS);
				upAxis = _rotationTransform.transformVector(upAxis);
        	} else {
	        	upAxis = _upAxis;
        	}
			
            _transform.pointAt(target, Vector3D.Z_AXIS, upAxis);
			
			if (Matrix3DUtils.compare(oldTransform, _transform))
                return;
			
            _rotationDirty = true;
            
            notifySceneTransformChange();
        }
		
		/**
 		* Apply the local rotations to the object without altering the apperance of child objects
 		*/
		public function applyRotations():void
		{
			throw new Error("Not implemented in Object3D - Use Mesh or ObjectContainer3D");
		}
		
		/**
 		* Apply the given position to the object without altering the apperance of child objects
 		*/
		public function applyPosition(dx:Number, dy:Number, dz:Number):void
		{
			throw new Error("Not implemented in Object3D - Use Mesh or ObjectContainer3D");
		}
		
		/**
		 * Used to trace the values of a 3d object.
		 * 
		 * @return A string representation of the 3d object.
		 */
        public override function toString():String
        {
            return (name ? name : "$") + ': x:' + Math.round(x) + ' y:' + Math.round(y) + ' z:' + Math.round(z);
        }
		
		/**
		 * Called by the <code>TickTraverser</code>.
		 * 
		 * Can be overridden to provide updates to the 3d object based on individual render calls from the renderer.
		 * 
		 * @param	time		The absolute time at the start of the render cycle
		 * 
		 * @see away3d.core.traverse.TickTraverser
		 */
        public function tick(time:int):void
        {
        }
		
		/**
		 * Duplicates the 3d object's properties to another <code>Object3D</code> object
		 * 
		 * @param	object	[optional]	The new object instance into which all properties are copied
		 * @return						The new object instance with duplicated properties applied
		 */
        public function clone(object:Object3D = null):Object3D
        {
            var object3D:Object3D = object || new Object3D();
            object3D.transform = transform;
            object3D.name = name;
            object3D.ownCanvas = _ownCanvas;
            object3D.renderer = _renderer;
            object3D.filters = _filters.concat();
            object3D.blendMode = blendMode;
            object3D.alpha = _alpha;
            object3D.visible = visible;
            object3D.mouseEnabled = mouseEnabled;
            object3D.useHandCursor = useHandCursor;
            object3D.pushback = pushback;
            object3D.pushfront = pushfront;
            object3D.screenZOffset = screenZOffset;
            object3D.pivotPoint = pivotPoint;
            object3D.extra = (extra is IClonable) ? (extra as IClonable).clone() : extra;
            
            return object3D;
        }
		
		/**
		 * Default method for adding a visibilityUpdated event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnVisibilityUpdate(listener:Function):void
        {
			addEventListener(Object3DEvent.VISIBLITY_UPDATED, listener, false, 0, true);
        }
		
		/**
		 * Default method for removing a visibilityUpdated event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnVisibilityUpdate(listener:Function):void
        {
            removeEventListener(Object3DEvent.VISIBLITY_UPDATED, listener, false);
        }
        		
		/**
		 * Default method for adding a scenetransformchanged event listener
		 * 
		 * @param	listener		The listener function
		 */
		public function addOnSceneTransformChange(listener:Function):void
        {
            addEventListener(Object3DEvent.SCENETRANSFORM_CHANGED, listener, false, 0, true);
        }
		
		/**
		 * Default method for removing a scenetransformchanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnSceneTransformChange(listener:Function):void
        {
            removeEventListener(Object3DEvent.SCENETRANSFORM_CHANGED, listener, false);
        }
		
		/**
		 * Default method for adding a scenechanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnSceneChange(listener:Function):void
        {
            addEventListener(Object3DEvent.SCENE_CHANGED, listener, false, 0, true);
        }
		
		/**
		 * Default method for removing a scenechanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnSceneChange(listener:Function):void
        {
            removeEventListener(Object3DEvent.SCENE_CHANGED, listener, false);
        }
		
		/**
		 * Default method for adding a sessionchanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnSessionChange(listener:Function):void
        {
            addEventListener(Object3DEvent.SESSION_CHANGED, listener, false, 0, true);
        }
		
		/**
		 * Default method for removing a sessionchanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnSessionChange(listener:Function):void
        {
            removeEventListener(Object3DEvent.SESSION_CHANGED, listener, false);
        }
                
		/**
		 * Default method for adding a dimensionschanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnDimensionsChange(listener:Function):void
        {
            addEventListener(Object3DEvent.DIMENSIONS_CHANGED, listener, false, 0, true);
        }
		
		/**
		 * Default method for removing a dimensionschanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnDimensionsChange(listener:Function):void
        {
            removeEventListener(Object3DEvent.DIMENSIONS_CHANGED, listener, false);
        }
        
		/**
		 * Default method for adding a positionchanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnPositionChange(listener:Function):void
        {
            addEventListener(Object3DEvent.POSITION_CHANGED, listener, false, 0, true);
        }
		
		/**
		 * Default method for removing a positionchanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnPositionChange(listener:Function):void
        {
            removeEventListener(Object3DEvent.POSITION_CHANGED, listener, false);
        }
		
		/**
		 * Default method for adding a scalechanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnScaleChange(listener:Function):void
        {
			addEventListener(Object3DEvent.SCALE_CHANGED, listener, false, 0, true);
        }
		
		/**
		 * Default method for removing a scalechanged event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnScaleChange(listener:Function):void
        {
            removeEventListener(Object3DEvent.SCALE_CHANGED, listener, false);
        }
        	
		/**
		 * Default method for adding a mouseMove3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnMouseMove(listener:Function):void
        {
            addEventListener(MouseEvent3D.MOUSE_MOVE, listener, false, 0, false);
        }
		
		/**
		 * Default method for removing a mouseMove3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnMouseMove(listener:Function):void
        {
            removeEventListener(MouseEvent3D.MOUSE_MOVE, listener, false);
        }
		
		/**
		 * Default method for adding a mouseDown3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnMouseDown(listener:Function):void
        {
            addEventListener(MouseEvent3D.MOUSE_DOWN, listener, false, 0, false);
        }
		
		/**
		 * Default method for removing a mouseDown3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnMouseDown(listener:Function):void
        {
            removeEventListener(MouseEvent3D.MOUSE_DOWN, listener, false);
        }
		
		/**
		 * Default method for adding a mouseUp3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnMouseUp(listener:Function):void
        {
            addEventListener(MouseEvent3D.MOUSE_UP, listener, false, 0, false);
        }
		
		/**
		 * Default method for removing a mouseUp3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnMouseUp(listener:Function):void
        {
            removeEventListener(MouseEvent3D.MOUSE_UP, listener, false);
        }
		
		/**
		 * Default method for adding a mouseOver3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnMouseOver(listener:Function):void
        {
            addEventListener(MouseEvent3D.MOUSE_OVER, listener, false, 0, false);
        }
		
		/**
		 * Default method for removing a mouseOver3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnMouseOver(listener:Function):void
        {
            removeEventListener(MouseEvent3D.MOUSE_OVER, listener, false);
        }
		
		/**
		 * Default method for adding a mouseOut3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnMouseOut(listener:Function):void
        {
            addEventListener(MouseEvent3D.MOUSE_OUT, listener, false, 0, false);
        }
		
		/**
		 * Default method for removing a mouseOut3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnMouseOut(listener:Function):void
        {
            removeEventListener(MouseEvent3D.MOUSE_OUT, listener, false);
        }
		
		/**
		 * Default method for adding a rollOver3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnRollOver(listener:Function):void
        {
            addEventListener(MouseEvent3D.ROLL_OVER, listener, false, 0, false);
        }
		
		/**
		 * Default method for removing a rollOver3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnRollOver(listener:Function):void
        {
            removeEventListener(MouseEvent3D.ROLL_OVER, listener, false);
        }
		
		/**
		 * Default method for adding a rollOut3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function addOnRollOut(listener:Function):void
        {
            addEventListener(MouseEvent3D.ROLL_OUT, listener, false, 0, false);
        }
		
		/**
		 * Default method for removing a rollOut3D event listener
		 * 
		 * @param	listener		The listener function
		 */
        public function removeOnRollOut(listener:Function):void
        {
            removeEventListener(MouseEvent3D.ROLL_OUT, listener, false);
        }
    }
}
