PageRenderTime 63ms CodeModel.GetById 49ms app.highlight 9ms RepoModel.GetById 2ms app.codeStats 0ms

/src/away3d/core/partition/NodeBase.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 197 lines | 112 code | 27 blank | 58 comment | 19 complexity | fa1ab96aa6b40694177533e1b3f59f2d MD5 | raw file
  1package away3d.core.partition
  2{
  3	import away3d.core.math.Plane3D;
  4	
  5	import flash.geom.Vector3D;
  6	
  7	import away3d.arcane;
  8	import away3d.core.traverse.PartitionTraverser;
  9	import away3d.entities.Entity;
 10	import away3d.primitives.WireframePrimitiveBase;
 11	
 12	use namespace arcane;
 13	
 14	/**
 15	 * The NodeBase class is an abstract base class for any type of space partition tree node. The concrete
 16	 * subtype will control the creation of its child nodes, which are necessarily of the same type. The exception is
 17	 * the creation of leaf entity nodes, which is handled by the Partition3D class.
 18	 *
 19	 * @see away3d.partition.EntityNode
 20	 * @see away3d.partition.Partition3D
 21	 * @see away3d.containers.Scene3D
 22	 */
 23	public class NodeBase
 24	{
 25		arcane var _parent:NodeBase;
 26		protected var _childNodes:Vector.<NodeBase>;
 27		protected var _numChildNodes:uint;
 28		protected var _debugPrimitive:WireframePrimitiveBase;
 29		
 30		arcane var _numEntities:int;
 31		arcane var _collectionMark:uint;
 32		
 33		/**
 34		 * Creates a new NodeBase object.
 35		 */
 36		public function NodeBase()
 37		{
 38			_childNodes = new Vector.<NodeBase>();
 39		}
 40		
 41		public function get showDebugBounds():Boolean
 42		{
 43			return _debugPrimitive != null;
 44		}
 45		
 46		public function set showDebugBounds(value:Boolean):void
 47		{
 48			if (Boolean(_debugPrimitive) == value)
 49				return;
 50			
 51			if (value)
 52				_debugPrimitive = createDebugBounds();
 53			else {
 54				_debugPrimitive.dispose();
 55				_debugPrimitive = null;
 56			}
 57			
 58			for (var i:uint = 0; i < _numChildNodes; ++i)
 59				_childNodes[i].showDebugBounds = value;
 60		}
 61		
 62		/**
 63		 * The parent node. Null if this node is the root.
 64		 */
 65		public function get parent():NodeBase
 66		{
 67			return _parent;
 68		}
 69		
 70		/**
 71		 * Adds a node to the tree. By default, this is used for both static as dynamic nodes, but for some data
 72		 * structures such as BSP trees, it can be more efficient to only use this for dynamic nodes, and add the
 73		 * static child nodes using custom links.
 74		 *
 75		 * @param node The node to be added as a child of the current node.
 76		 */
 77		arcane function addNode(node:NodeBase):void
 78		{
 79			node._parent = this;
 80			_numEntities += node._numEntities;
 81			_childNodes[_numChildNodes++] = node;
 82			node.showDebugBounds = _debugPrimitive != null;
 83			
 84			// update numEntities in the tree
 85			var numEntities:int = node._numEntities;
 86			node = this;
 87			
 88			do
 89				node._numEntities += numEntities;
 90			while ((node = node._parent) != null);
 91		}
 92		
 93		/**
 94		 * Removes a child node from the tree.
 95		 * @param node The child node to be removed.
 96		 */
 97		arcane function removeNode(node:NodeBase):void
 98		{
 99			// a bit faster than splice(i, 1), works only if order is not important
100			// override item to be removed with the last in the list, then remove that last one
101			// Also, the "real partition nodes" of the tree will always remain unmoved, first in the list, so if there's
102			// an order dependency for them, it's still okay
103			var index:uint = _childNodes.indexOf(node);
104			_childNodes[index] = _childNodes[--_numChildNodes];
105			_childNodes.pop();
106			
107			// update numEntities in the tree
108			var numEntities:int = node._numEntities;
109			node = this;
110			
111			do
112				node._numEntities -= numEntities;
113			while ((node = node._parent) != null);
114		}
115		
116		/**
117		 * Tests if the current node is at least partly inside the frustum.
118		 * @param viewProjectionRaw The raw data of the view projection matrix
119		 *
120		 * @return Whether or not the node is at least partly inside the view frustum.
121		 */
122		public function isInFrustum(planes:Vector.<Plane3D>, numPlanes:int):Boolean
123		{
124			planes = planes;
125			numPlanes = numPlanes;
126			return true;
127		}
128		
129		/**
130		 * Tests if the current node is intersecting with a ray.
131		 * @param rayPosition The starting position of the ray
132		 * @param rayDirection The direction vector of the ray
133		 *
134		 * @return Whether or not the node is at least partly intersecting the ray.
135		 */
136		public function isIntersectingRay(rayPosition:Vector3D, rayDirection:Vector3D):Boolean
137		{
138			rayPosition = rayPosition;
139			rayDirection = rayDirection;
140			return true;
141		}
142		
143		/**
144		 * Finds the partition that contains (or should contain) the given entity.
145		 */
146		public function findPartitionForEntity(entity:Entity):NodeBase
147		{
148			entity = entity;
149			return this;
150		}
151		
152		/**
153		 * Allows the traverser to visit the current node. If the traverser's enterNode method returns true, the
154		 * traverser will be sent down the child nodes of the tree.
155		 * This method should be overridden if the order of traversal is important (such as for BSP trees) - or if static
156		 * child nodes are not added using addNode, but are linked to separately.
157		 *
158		 * @param traverser The traverser visiting the node.
159		 *
160		 * @see away3d.core.traverse.PartitionTraverser
161		 */
162		public function acceptTraverser(traverser:PartitionTraverser):void
163		{
164			if (_numEntities == 0 && !_debugPrimitive)
165				return;
166			
167			if (traverser.enterNode(this)) {
168				var i:uint;
169				while (i < _numChildNodes)
170					_childNodes[i++].acceptTraverser(traverser);
171				
172				if (_debugPrimitive)
173					traverser.applyRenderable(_debugPrimitive);
174			}
175		}
176		
177		protected function createDebugBounds():WireframePrimitiveBase
178		{
179			return null;
180		}
181		
182		protected function get numEntities():int
183		{
184			return _numEntities;
185		}
186		
187		protected function updateNumEntities(value:int):void
188		{
189			var diff:int = value - _numEntities;
190			var node:NodeBase = this;
191			
192			do
193				node._numEntities += diff;
194			while ((node = node._parent) != null);
195		}
196	}
197}