PageRenderTime 23ms CodeModel.GetById 9ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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}