PageRenderTime 141ms CodeModel.GetById 16ms app.highlight 100ms RepoModel.GetById 11ms app.codeStats 1ms

/src/away3d/bounds/BoundingVolumeBase.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 351 lines | 228 code | 36 blank | 87 comment | 29 complexity | f86ffc13b8d160d7dec0417071bd51ab MD5 | raw file
  1package away3d.bounds
  2{
  3	import away3d.arcane;
  4	import away3d.core.base.*;
  5	import away3d.core.math.Plane3D;
  6	import away3d.errors.*;
  7	import away3d.primitives.*;
  8	
  9	import flash.geom.*;
 10	
 11	use namespace arcane;
 12	
 13	/**
 14	 * An abstract base class for all bounding volume classes. It should not be instantiated directly.
 15	 */
 16	public class BoundingVolumeBase
 17	{
 18		protected var _min:Vector3D;
 19		protected var _max:Vector3D;
 20		protected var _aabbPoints:Vector.<Number> = new Vector.<Number>();
 21		protected var _aabbPointsDirty:Boolean = true;
 22		protected var _boundingRenderable:WireframePrimitiveBase;
 23		
 24		/**
 25		 * The maximum extreme of the bounds
 26		 */
 27		public function get max():Vector3D
 28		{
 29			return _max;
 30		}
 31		
 32		/**
 33		 * The minimum extreme of the bounds
 34		 */
 35		public function get min():Vector3D
 36		{
 37			return _min;
 38		}
 39		
 40		/**
 41		 * Returns a vector of values representing the concatenated cartesian triplet of the 8 axial extremities of the bounding volume.
 42		 */
 43		public function get aabbPoints():Vector.<Number>
 44		{
 45			if (_aabbPointsDirty)
 46				updateAABBPoints();
 47			
 48			return _aabbPoints;
 49		}
 50		
 51		/**
 52		 * Returns the bounding renderable object for the bounding volume, in cases where the showBounds
 53		 * property of the entity is set to true.
 54		 *
 55		 * @see away3d.entities.Entity#showBounds
 56		 */
 57		public function get boundingRenderable():WireframePrimitiveBase
 58		{
 59			if (!_boundingRenderable) {
 60				_boundingRenderable = createBoundingRenderable();
 61				updateBoundingRenderable();
 62			}
 63			
 64			return _boundingRenderable;
 65		}
 66		
 67		/**
 68		 * Creates a new <code>BoundingVolumeBase</code> object
 69		 */
 70		public function BoundingVolumeBase()
 71		{
 72			_min = new Vector3D();
 73			_max = new Vector3D();
 74		}
 75		
 76		/**
 77		 * Sets the bounds to zero size.
 78		 */
 79		public function nullify():void
 80		{
 81			_min.x = _min.y = _min.z = 0;
 82			_max.x = _max.y = _max.z = 0;
 83			_aabbPointsDirty = true;
 84			if (_boundingRenderable)
 85				updateBoundingRenderable();
 86		}
 87		
 88		/**
 89		 * Disposes of the bounds renderable object. Used to clear memory after a bounds rendeable is no longer required.
 90		 */
 91		public function disposeRenderable():void
 92		{
 93			if (_boundingRenderable)
 94				_boundingRenderable.dispose();
 95			_boundingRenderable = null;
 96		}
 97		
 98		/**
 99		 * Updates the bounds to fit a list of vertices
100		 *
101		 * @param vertices A Vector.&lt;Number&gt; of vertex data to be bounded.
102		 */
103		public function fromVertices(vertices:Vector.<Number>):void
104		{
105			var i:uint;
106			var len:uint = vertices.length;
107			var minX:Number, minY:Number, minZ:Number;
108			var maxX:Number, maxY:Number, maxZ:Number;
109			
110			if (len == 0) {
111				nullify();
112				return;
113			}
114			
115			var v:Number;
116			
117			minX = maxX = vertices[uint(i++)];
118			minY = maxY = vertices[uint(i++)];
119			minZ = maxZ = vertices[uint(i++)];
120			
121			while (i < len) {
122				v = vertices[i++];
123				if (v < minX)
124					minX = v;
125				else if (v > maxX)
126					maxX = v;
127				v = vertices[i++];
128				if (v < minY)
129					minY = v;
130				else if (v > maxY)
131					maxY = v;
132				v = vertices[i++];
133				if (v < minZ)
134					minZ = v;
135				else if (v > maxZ)
136					maxZ = v;
137			}
138			
139			fromExtremes(minX, minY, minZ, maxX, maxY, maxZ);
140		}
141		
142		/**
143		 * Updates the bounds to fit a Geometry object.
144		 *
145		 * @param geometry The Geometry object to be bounded.
146		 */
147		public function fromGeometry(geometry:Geometry):void
148		{
149			var subGeoms:Vector.<ISubGeometry> = geometry.subGeometries;
150			var numSubGeoms:uint = subGeoms.length;
151			var minX:Number, minY:Number, minZ:Number;
152			var maxX:Number, maxY:Number, maxZ:Number;
153			
154			if (numSubGeoms > 0) {
155				var subGeom:ISubGeometry = subGeoms[0];
156				var vertices:Vector.<Number> = subGeom.vertexData;
157				var i:uint = subGeom.vertexOffset;
158				minX = maxX = vertices[i];
159				minY = maxY = vertices[i + 1];
160				minZ = maxZ = vertices[i + 2];
161
162				var j:uint = 0;
163				while (j < numSubGeoms) {
164					subGeom = subGeoms[j++];
165					vertices = subGeom.vertexData;
166					var vertexDataLen:uint = vertices.length;
167					i = subGeom.vertexOffset;
168					var stride:uint = subGeom.vertexStride;
169					
170					while (i < vertexDataLen) {
171						var v:Number = vertices[i];
172						if (v < minX)
173							minX = v;
174						else if (v > maxX)
175							maxX = v;
176						v = vertices[i + 1];
177						if (v < minY)
178							minY = v;
179						else if (v > maxY)
180							maxY = v;
181						v = vertices[i + 2];
182						if (v < minZ)
183							minZ = v;
184						else if (v > maxZ)
185							maxZ = v;
186						i += stride;
187					}
188				}
189				
190				fromExtremes(minX, minY, minZ, maxX, maxY, maxZ);
191			} else
192				fromExtremes(0, 0, 0, 0, 0, 0);
193		}
194		
195		/**
196		 * Sets the bound to fit a given sphere.
197		 *
198		 * @param center The center of the sphere to be bounded
199		 * @param radius The radius of the sphere to be bounded
200		 */
201		public function fromSphere(center:Vector3D, radius:Number):void
202		{
203			// this is BETTER overridden, because most volumes will have shortcuts for this
204			// but then again, sphere already overrides it, and if we'd call "fromSphere", it'd probably need a sphere bound anyway
205			fromExtremes(center.x - radius, center.y - radius, center.z - radius, center.x + radius, center.y + radius, center.z + radius);
206		}
207		
208		/**
209		 * Sets the bounds to the given extrema.
210		 *
211		 * @param minX The minimum x value of the bounds
212		 * @param minY The minimum y value of the bounds
213		 * @param minZ The minimum z value of the bounds
214		 * @param maxX The maximum x value of the bounds
215		 * @param maxY The maximum y value of the bounds
216		 * @param maxZ The maximum z value of the bounds
217		 */
218		public function fromExtremes(minX:Number, minY:Number, minZ:Number, maxX:Number, maxY:Number, maxZ:Number):void
219		{
220			_min.x = minX;
221			_min.y = minY;
222			_min.z = minZ;
223			_max.x = maxX;
224			_max.y = maxY;
225			_max.z = maxZ;
226			_aabbPointsDirty = true;
227			if (_boundingRenderable)
228				updateBoundingRenderable();
229		}
230		
231		/**
232		 * Tests if the bounds are in the camera frustum.
233		 *
234		 * @param mvpMatrix The model view projection matrix for the object to which this bounding box belongs.
235		 * @return True if the bounding box is at least partially inside the frustum
236		 */
237		public function isInFrustum(planes:Vector.<Plane3D>, numPlanes:int):Boolean
238		{
239			throw new AbstractMethodError();
240		}
241		
242		/**
243		 * Tests if the bounds overlap other bounds, treating both bounds as AABBs.
244		 */
245		public function overlaps(bounds:BoundingVolumeBase):Boolean
246		{
247			var min:Vector3D = bounds._min;
248			var max:Vector3D = bounds._max;
249			return _max.x > min.x &&
250				_min.x < max.x &&
251				_max.y > min.y &&
252				_min.y < max.y &&
253				_max.z > min.z &&
254				_min.z < max.z;
255		}
256		
257		/*public function classifyAgainstPlane(plane : Plane3D) : int
258		 {
259		 throw new AbstractMethodError();
260		 return -1;
261		 }*/
262		
263		/**
264		 * Clones the current BoundingVolume object
265		 * @return An exact duplicate of this object
266		 */
267		public function clone():BoundingVolumeBase
268		{
269			throw new AbstractMethodError();
270		}
271		
272		/**
273		 * Method for calculating whether an intersection of the given ray occurs with the bounding volume.
274		 *
275		 * @param position The starting position of the casting ray in local coordinates.
276		 * @param direction A unit vector representing the direction of the casting ray in local coordinates.
277		 * @param targetNormal The vector to store the bounds' normal at the point of collision
278		 * @return A Boolean value representing the detection of an intersection.
279		 */
280		public function rayIntersection(position:Vector3D, direction:Vector3D, targetNormal:Vector3D):Number
281		{
282			position = position;
283			direction = direction;
284			targetNormal = targetNormal;
285			return -1;
286		}
287		
288		/**
289		 * Method for calculating whether the given position is contained within the bounding volume.
290		 *
291		 * @param position The position in local coordinates to be checked.
292		 * @return A Boolean value representing the detection of a contained position.
293		 */
294		public function containsPoint(position:Vector3D):Boolean
295		{
296			position = position;
297			return false;
298		}
299		
300		protected function updateAABBPoints():void
301		{
302			var maxX:Number = _max.x, maxY:Number = _max.y, maxZ:Number = _max.z;
303			var minX:Number = _min.x, minY:Number = _min.y, minZ:Number = _min.z;
304			_aabbPoints[0] = minX;
305			_aabbPoints[1] = minY;
306			_aabbPoints[2] = minZ;
307			_aabbPoints[3] = maxX;
308			_aabbPoints[4] = minY;
309			_aabbPoints[5] = minZ;
310			_aabbPoints[6] = minX;
311			_aabbPoints[7] = maxY;
312			_aabbPoints[8] = minZ;
313			_aabbPoints[9] = maxX;
314			_aabbPoints[10] = maxY;
315			_aabbPoints[11] = minZ;
316			_aabbPoints[12] = minX;
317			_aabbPoints[13] = minY;
318			_aabbPoints[14] = maxZ;
319			_aabbPoints[15] = maxX;
320			_aabbPoints[16] = minY;
321			_aabbPoints[17] = maxZ;
322			_aabbPoints[18] = minX;
323			_aabbPoints[19] = maxY;
324			_aabbPoints[20] = maxZ;
325			_aabbPoints[21] = maxX;
326			_aabbPoints[22] = maxY;
327			_aabbPoints[23] = maxZ;
328			_aabbPointsDirty = false;
329		}
330		
331		protected function updateBoundingRenderable():void
332		{
333			throw new AbstractMethodError();
334		}
335		
336		protected function createBoundingRenderable():WireframePrimitiveBase
337		{
338			throw new AbstractMethodError();
339		}
340		
341		public function classifyToPlane(plane:Plane3D):int
342		{
343			throw new AbstractMethodError();
344		}
345		
346		public function transformFrom(bounds:BoundingVolumeBase, matrix:Matrix3D):void
347		{
348			throw new AbstractMethodError();
349		}
350	}
351}