/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

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