/src/away3d/core/partition/Partition3D.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 142 lines · 82 code · 26 blank · 34 comment · 18 complexity · 1843073b06ae3de3c591f20c63d01c3b MD5 · raw file

  1. package away3d.core.partition
  2. {
  3. import away3d.arcane;
  4. import away3d.core.traverse.PartitionTraverser;
  5. import away3d.entities.Entity;
  6. use namespace arcane;
  7. /**
  8. * Partition3D is the core of a space partition system. The space partition system typically subdivides the 3D scene
  9. * hierarchically into a number of non-overlapping subspaces, forming a tree data structure. This is used to more
  10. * efficiently perform frustum culling, potential visibility determination and collision detection.
  11. */
  12. public class Partition3D
  13. {
  14. protected var _rootNode:NodeBase;
  15. private var _updatesMade:Boolean;
  16. private var _updateQueue:EntityNode;
  17. /**
  18. * Creates a new Partition3D object.
  19. * @param rootNode The root node of the space partition system. This will indicate which type of data structure will be used.
  20. */
  21. public function Partition3D(rootNode:NodeBase)
  22. {
  23. _rootNode = rootNode || new NullNode();
  24. }
  25. public function get showDebugBounds():Boolean
  26. {
  27. return _rootNode.showDebugBounds;
  28. }
  29. public function set showDebugBounds(value:Boolean):void
  30. {
  31. _rootNode.showDebugBounds = value;
  32. }
  33. /**
  34. * Sends a traverser through the partition tree.
  35. * @param traverser
  36. *
  37. * @see away3d.core.traverse.PartitionTraverser
  38. */
  39. public function traverse(traverser:PartitionTraverser):void
  40. {
  41. if (_updatesMade)
  42. updateEntities();
  43. ++PartitionTraverser._collectionMark;
  44. _rootNode.acceptTraverser(traverser);
  45. }
  46. /**
  47. * Mark a scene graph entity for updating. This will trigger a reassignment within the tree, based on the
  48. * object's bounding box, upon the next traversal.
  49. * @param entity The entity to be updated in the tree.
  50. */
  51. arcane function markForUpdate(entity:Entity):void
  52. {
  53. var node:EntityNode = entity.getEntityPartitionNode();
  54. // already marked to be updated
  55. var t:EntityNode = _updateQueue;
  56. // if already marked for update
  57. while (t) {
  58. if (node == t)
  59. return;
  60. t = t._updateQueueNext;
  61. }
  62. node._updateQueueNext = _updateQueue;
  63. _updateQueue = node;
  64. _updatesMade = true;
  65. }
  66. /**
  67. * Removes an entity from the partition tree.
  68. * @param entity The entity to be removed.
  69. */
  70. arcane function removeEntity(entity:Entity):void
  71. {
  72. var node:EntityNode = entity.getEntityPartitionNode();
  73. var t:EntityNode;
  74. node.removeFromParent();
  75. // remove from update list if it's in
  76. if (node == _updateQueue)
  77. _updateQueue = node._updateQueueNext;
  78. else {
  79. t = _updateQueue;
  80. while (t && t._updateQueueNext != node)
  81. t = t._updateQueueNext;
  82. if (t)
  83. t._updateQueueNext = node._updateQueueNext;
  84. }
  85. node._updateQueueNext = null;
  86. // any updates have been made undone
  87. if (!_updateQueue)
  88. _updatesMade = false;
  89. }
  90. /**
  91. * Updates all entities that were marked for update.
  92. */
  93. private function updateEntities():void
  94. {
  95. var node:EntityNode = _updateQueue;
  96. var targetNode:NodeBase;
  97. var t:EntityNode;
  98. // clear updateQueue early to allow for newly marked entity updates
  99. _updateQueue = null;
  100. _updatesMade = false;
  101. do {
  102. targetNode = _rootNode.findPartitionForEntity(node.entity);
  103. // if changed, find and attach the mesh node to the best suited partition node
  104. if (node.parent != targetNode) {
  105. if (node)
  106. node.removeFromParent();
  107. targetNode.addNode(node);
  108. }
  109. t = node._updateQueueNext;
  110. node._updateQueueNext = null;
  111. //call an internal update on the entity to fire any attached logic
  112. node.entity.internalUpdate();
  113. } while ((node = t) != null);
  114. }
  115. }
  116. }