/src/away3d/core/partition/QuadTreeNode.as

http://github.com/away3d/away3d-core-fp11 · ActionScript · 106 lines · 87 code · 18 blank · 1 comment · 12 complexity · f5915af4ed49f469cd73570149042a83 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 flash.geom.Vector3D;
  8. use namespace arcane;
  9. public class QuadTreeNode extends NodeBase
  10. {
  11. private var _centerX:Number;
  12. private var _centerZ:Number;
  13. private var _depth:Number;
  14. private var _leaf:Boolean;
  15. private var _height:Number;
  16. private var _rightFar:QuadTreeNode;
  17. private var _leftFar:QuadTreeNode;
  18. private var _rightNear:QuadTreeNode;
  19. private var _leftNear:QuadTreeNode;
  20. private var _halfExtentXZ:Number;
  21. private var _halfExtentY:Number;
  22. public function QuadTreeNode(maxDepth:int = 5, size:Number = 10000, height:Number = 1000000, centerX:Number = 0, centerZ:Number = 0, depth:int = 0)
  23. {
  24. var hs:Number = size*.5;
  25. _centerX = centerX;
  26. _centerZ = centerZ;
  27. _height = height;
  28. _depth = depth;
  29. _halfExtentXZ = size*.5;
  30. _halfExtentY = height*.5;
  31. _leaf = depth == maxDepth;
  32. if (!_leaf) {
  33. var hhs:Number = hs*.5;
  34. addNode(_leftNear = new QuadTreeNode(maxDepth, hs, height, centerX - hhs, centerZ - hhs, depth + 1));
  35. addNode(_rightNear = new QuadTreeNode(maxDepth, hs, height, centerX + hhs, centerZ - hhs, depth + 1));
  36. addNode(_leftFar = new QuadTreeNode(maxDepth, hs, height, centerX - hhs, centerZ + hhs, depth + 1));
  37. addNode(_rightFar = new QuadTreeNode(maxDepth, hs, height, centerX + hhs, centerZ + hhs, depth + 1));
  38. }
  39. }
  40. // todo: fix to infinite height so that height needn't be passed in constructor
  41. override public function isInFrustum(planes:Vector.<Plane3D>, numPlanes:int):Boolean
  42. {
  43. for (var i:uint = 0; i < numPlanes; ++i) {
  44. var plane:Plane3D = planes[i];
  45. var flippedExtentX:Number = plane.a < 0? -_halfExtentXZ : _halfExtentXZ;
  46. var flippedExtentY:Number = plane.b < 0? -_halfExtentY : _halfExtentY;
  47. var flippedExtentZ:Number = plane.c < 0? -_halfExtentXZ : _halfExtentXZ;
  48. var projDist:Number = plane.a*(_centerX + flippedExtentX) + plane.b*flippedExtentY + plane.c*(_centerZ + flippedExtentZ) - plane.d;
  49. if (projDist < 0)
  50. return false;
  51. }
  52. return true;
  53. }
  54. override public function findPartitionForEntity(entity:Entity):NodeBase
  55. {
  56. var bounds:BoundingVolumeBase = entity.worldBounds;
  57. var min:Vector3D = bounds.min;
  58. var max:Vector3D = bounds.max;
  59. return findPartitionForBounds(min.x, min.z, max.x, max.z);
  60. }
  61. private function findPartitionForBounds(minX:Number, minZ:Number, maxX:Number, maxZ:Number):QuadTreeNode
  62. {
  63. var left:Boolean, right:Boolean;
  64. var far:Boolean, near:Boolean;
  65. if (_leaf)
  66. return this;
  67. right = maxX > _centerX;
  68. left = minX < _centerX;
  69. far = maxZ > _centerZ;
  70. near = minZ < _centerZ;
  71. if (left && right)
  72. return this;
  73. if (near) {
  74. if (far)
  75. return this;
  76. if (left)
  77. return _leftNear.findPartitionForBounds(minX, minZ, maxX, maxZ);
  78. else
  79. return _rightNear.findPartitionForBounds(minX, minZ, maxX, maxZ);
  80. } else {
  81. if (left)
  82. return _leftFar.findPartitionForBounds(minX, minZ, maxX, maxZ);
  83. else
  84. return _rightFar.findPartitionForBounds(minX, minZ, maxX, maxZ);
  85. }
  86. }
  87. }
  88. }