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