/src/away3d/core/partition/OctreeNode.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 157 lines · 137 code · 18 blank · 2 comment · 20 complexity · 5283bacba07b0c51cc8735d1d91bf68f MD5 · raw file

  1. package away3d.core.partition
  2. {
  3. import away3d.arcane;
  4. import away3d.bounds.BoundingVolumeBase;
  5. import away3d.core.math.Plane3D;
  6. import away3d.entities.Entity;
  7. import away3d.primitives.WireframeCube;
  8. import away3d.primitives.WireframePrimitiveBase;
  9. import flash.geom.Vector3D;
  10. use namespace arcane;
  11. public class OctreeNode extends NodeBase
  12. {
  13. private var _centerX:Number;
  14. private var _centerY:Number;
  15. private var _centerZ:Number;
  16. private var _minX:Number;
  17. private var _minY:Number;
  18. private var _minZ:Number;
  19. private var _maxX:Number;
  20. private var _maxY:Number;
  21. private var _maxZ:Number;
  22. private var _quadSize:Number;
  23. private var _depth:Number;
  24. private var _leaf:Boolean;
  25. private var _rightTopFar:OctreeNode;
  26. private var _leftTopFar:OctreeNode;
  27. private var _rightBottomFar:OctreeNode;
  28. private var _leftBottomFar:OctreeNode;
  29. private var _rightTopNear:OctreeNode;
  30. private var _leftTopNear:OctreeNode;
  31. private var _rightBottomNear:OctreeNode;
  32. private var _leftBottomNear:OctreeNode;
  33. //private var _entityWorldBounds : Vector.<Number> = new Vector.<Number>();
  34. private var _halfExtent:Number;
  35. public function OctreeNode(maxDepth:int = 5, size:Number = 10000, centerX:Number = 0, centerY:Number = 0, centerZ:Number = 0, depth:int = 0)
  36. {
  37. init(size, centerX, centerY, centerZ, depth, maxDepth);
  38. }
  39. private function init(size:Number, centerX:Number, centerY:Number, centerZ:Number, depth:int, maxDepth:int):void
  40. {
  41. _halfExtent = size*.5;
  42. _centerX = centerX;
  43. _centerY = centerY;
  44. _centerZ = centerZ;
  45. _quadSize = size;
  46. _depth = depth;
  47. _minX = centerX - _halfExtent;
  48. _minY = centerY - _halfExtent;
  49. _minZ = centerZ - _halfExtent;
  50. _maxX = centerX + _halfExtent;
  51. _maxY = centerY + _halfExtent;
  52. _maxZ = centerZ + _halfExtent;
  53. _leaf = depth == maxDepth;
  54. if (!_leaf) {
  55. var hhs:Number = _halfExtent*.5;
  56. addNode(_leftTopNear = new OctreeNode(maxDepth, _halfExtent, centerX - hhs, centerY + hhs, centerZ - hhs, depth + 1));
  57. addNode(_rightTopNear = new OctreeNode(maxDepth, _halfExtent, centerX + hhs, centerY + hhs, centerZ - hhs, depth + 1));
  58. addNode(_leftBottomNear = new OctreeNode(maxDepth, _halfExtent, centerX - hhs, centerY - hhs, centerZ - hhs, depth + 1));
  59. addNode(_rightBottomNear = new OctreeNode(maxDepth, _halfExtent, centerX + hhs, centerY - hhs, centerZ - hhs, depth + 1));
  60. addNode(_leftTopFar = new OctreeNode(maxDepth, _halfExtent, centerX - hhs, centerY + hhs, centerZ + hhs, depth + 1));
  61. addNode(_rightTopFar = new OctreeNode(maxDepth, _halfExtent, centerX + hhs, centerY + hhs, centerZ + hhs, depth + 1));
  62. addNode(_leftBottomFar = new OctreeNode(maxDepth, _halfExtent, centerX - hhs, centerY - hhs, centerZ + hhs, depth + 1));
  63. addNode(_rightBottomFar = new OctreeNode(maxDepth, _halfExtent, centerX + hhs, centerY - hhs, centerZ + hhs, depth + 1));
  64. }
  65. }
  66. override protected function createDebugBounds():WireframePrimitiveBase
  67. {
  68. var cube:WireframeCube = new WireframeCube(_quadSize, _quadSize, _quadSize);
  69. cube.x = _centerX;
  70. cube.y = _centerY;
  71. cube.z = _centerZ;
  72. return cube;
  73. }
  74. override public function isInFrustum(planes:Vector.<Plane3D>, numPlanes:int):Boolean
  75. {
  76. for (var i:uint = 0; i < numPlanes; ++i) {
  77. var plane:Plane3D = planes[i];
  78. var flippedExtentX:Number = plane.a < 0? -_halfExtent : _halfExtent;
  79. var flippedExtentY:Number = plane.b < 0? -_halfExtent : _halfExtent;
  80. var flippedExtentZ:Number = plane.c < 0? -_halfExtent : _halfExtent;
  81. var projDist:Number = plane.a*(_centerX + flippedExtentX) + plane.b*(_centerY + flippedExtentY) + plane.c*(_centerZ + flippedExtentZ) - plane.d;
  82. if (projDist < 0)
  83. return false;
  84. }
  85. return true;
  86. }
  87. override public function findPartitionForEntity(entity:Entity):NodeBase
  88. {
  89. var bounds:BoundingVolumeBase = entity.worldBounds;
  90. var min:Vector3D = bounds.min;
  91. var max:Vector3D = bounds.max;
  92. return findPartitionForBounds(min.x, min.y, min.z, max.x, max.y, max.z);
  93. }
  94. // TODO: this can be done quicker through inversion
  95. private function findPartitionForBounds(minX:Number, minY:Number, minZ:Number, maxX:Number, maxY:Number, maxZ:Number):OctreeNode
  96. {
  97. var left:Boolean, right:Boolean;
  98. var far:Boolean, near:Boolean;
  99. var top:Boolean, bottom:Boolean;
  100. if (_leaf)
  101. return this;
  102. right = maxX > _centerX;
  103. left = minX < _centerX;
  104. top = maxY > _centerY;
  105. bottom = minY < _centerY;
  106. far = maxZ > _centerZ;
  107. near = minZ < _centerZ;
  108. if ((left && right) || (far && near))
  109. return this;
  110. if (top) {
  111. if (bottom)
  112. return this;
  113. if (near) {
  114. if (left)
  115. return _leftTopNear.findPartitionForBounds(minX, minY, minZ, maxX, maxY, maxZ);
  116. else
  117. return _rightTopNear.findPartitionForBounds(minX, minY, minZ, maxX, maxY, maxZ);
  118. } else {
  119. if (left)
  120. return _leftTopFar.findPartitionForBounds(minX, minY, minZ, maxX, maxY, maxZ);
  121. else
  122. return _rightTopFar.findPartitionForBounds(minX, minY, minZ, maxX, maxY, maxZ);
  123. }
  124. } else {
  125. if (near) {
  126. if (left)
  127. return _leftBottomNear.findPartitionForBounds(minX, minY, minZ, maxX, maxY, maxZ);
  128. else
  129. return _rightBottomNear.findPartitionForBounds(minX, minY, minZ, maxX, maxY, maxZ);
  130. } else {
  131. if (left)
  132. return _leftBottomFar.findPartitionForBounds(minX, minY, minZ, maxX, maxY, maxZ);
  133. else
  134. return _rightBottomFar.findPartitionForBounds(minX, minY, minZ, maxX, maxY, maxZ);
  135. }
  136. }
  137. }
  138. }
  139. }