PageRenderTime 486ms CodeModel.GetById 181ms app.highlight 101ms RepoModel.GetById 201ms app.codeStats 0ms

/src/away3d/cameras/Camera3D.as

http://github.com/away3d/away3d-core-fp11
ActionScript | 293 lines | 191 code | 41 blank | 61 comment | 7 complexity | ff4076876ac062d1feaaf0c1be16c82f MD5 | raw file
  1package away3d.cameras
  2{
  3	import away3d.core.math.Matrix3DUtils;
  4
  5	import flash.geom.Matrix3D;
  6	import flash.geom.Vector3D;
  7	
  8	import away3d.arcane;
  9	import away3d.bounds.BoundingVolumeBase;
 10	import away3d.bounds.NullBounds;
 11	import away3d.cameras.lenses.LensBase;
 12	import away3d.cameras.lenses.PerspectiveLens;
 13	import away3d.core.math.Plane3D;
 14	import away3d.core.partition.CameraNode;
 15	import away3d.core.partition.EntityNode;
 16	import away3d.entities.Entity;
 17	import away3d.events.CameraEvent;
 18	import away3d.events.LensEvent;
 19	import away3d.library.assets.AssetType;
 20	
 21	use namespace arcane;
 22	
 23	/**
 24	 * A Camera3D object represents a virtual camera through which we view the scene.
 25	 */
 26	public class Camera3D extends Entity
 27	{
 28		private var _viewProjection:Matrix3D = new Matrix3D();
 29		private var _viewProjectionDirty:Boolean = true;
 30		private var _lens:LensBase;
 31		private var _frustumPlanes:Vector.<Plane3D>;
 32		private var _frustumPlanesDirty:Boolean = true;
 33		
 34		/**
 35		 * Creates a new Camera3D object
 36		 * @param lens An optional lens object that will perform the projection. Defaults to PerspectiveLens.
 37		 *
 38		 * @see away3d.cameras.lenses.PerspectiveLens
 39		 */
 40		public function Camera3D(lens:LensBase = null)
 41		{
 42			super();
 43			
 44			//setup default lens
 45			_lens = lens || new PerspectiveLens();
 46			_lens.addEventListener(LensEvent.MATRIX_CHANGED, onLensMatrixChanged);
 47			
 48			//setup default frustum planes
 49			_frustumPlanes = new Vector.<Plane3D>(6, true);
 50			
 51			for (var i:int = 0; i < 6; ++i)
 52				_frustumPlanes[i] = new Plane3D();
 53			
 54			z = -1000;
 55		}
 56		
 57		override protected function getDefaultBoundingVolume():BoundingVolumeBase
 58		{
 59			return new NullBounds();
 60		}
 61		
 62		public override function get assetType():String
 63		{
 64			return AssetType.CAMERA;
 65		}
 66		
 67		private function onLensMatrixChanged(event:LensEvent):void
 68		{
 69			_viewProjectionDirty = true;
 70			_frustumPlanesDirty = true;
 71			
 72			dispatchEvent(event);
 73		}
 74		
 75		/**
 76		 *
 77		 */
 78		public function get frustumPlanes():Vector.<Plane3D>
 79		{
 80			if (_frustumPlanesDirty)
 81				updateFrustum();
 82			
 83			return _frustumPlanes;
 84		}
 85		
 86		private function updateFrustum():void
 87		{
 88			var a:Number, b:Number, c:Number;
 89			//var d : Number;
 90			var c11:Number, c12:Number, c13:Number, c14:Number;
 91			var c21:Number, c22:Number, c23:Number, c24:Number;
 92			var c31:Number, c32:Number, c33:Number, c34:Number;
 93			var c41:Number, c42:Number, c43:Number, c44:Number;
 94			var p:Plane3D;
 95			var raw:Vector.<Number> = Matrix3DUtils.RAW_DATA_CONTAINER;
 96			var invLen:Number;
 97			viewProjection.copyRawDataTo(raw);
 98			
 99			c11 = raw[uint(0)];
100			c12 = raw[uint(4)];
101			c13 = raw[uint(8)];
102			c14 = raw[uint(12)];
103			c21 = raw[uint(1)];
104			c22 = raw[uint(5)];
105			c23 = raw[uint(9)];
106			c24 = raw[uint(13)];
107			c31 = raw[uint(2)];
108			c32 = raw[uint(6)];
109			c33 = raw[uint(10)];
110			c34 = raw[uint(14)];
111			c41 = raw[uint(3)];
112			c42 = raw[uint(7)];
113			c43 = raw[uint(11)];
114			c44 = raw[uint(15)];
115			
116			// left plane
117			p = _frustumPlanes[0];
118			a = c41 + c11;
119			b = c42 + c12;
120			c = c43 + c13;
121			invLen = 1/Math.sqrt(a*a + b*b + c*c);
122			p.a = a*invLen;
123			p.b = b*invLen;
124			p.c = c*invLen;
125			p.d = -(c44 + c14)*invLen;
126			
127			// right plane
128			p = _frustumPlanes[1];
129			a = c41 - c11;
130			b = c42 - c12;
131			c = c43 - c13;
132			invLen = 1/Math.sqrt(a*a + b*b + c*c);
133			p.a = a*invLen;
134			p.b = b*invLen;
135			p.c = c*invLen;
136			p.d = (c14 - c44)*invLen;
137			
138			// bottom
139			p = _frustumPlanes[2];
140			a = c41 + c21;
141			b = c42 + c22;
142			c = c43 + c23;
143			invLen = 1/Math.sqrt(a*a + b*b + c*c);
144			p.a = a*invLen;
145			p.b = b*invLen;
146			p.c = c*invLen;
147			p.d = -(c44 + c24)*invLen;
148			
149			// top
150			p = _frustumPlanes[3];
151			a = c41 - c21;
152			b = c42 - c22;
153			c = c43 - c23;
154			invLen = 1/Math.sqrt(a*a + b*b + c*c);
155			p.a = a*invLen;
156			p.b = b*invLen;
157			p.c = c*invLen;
158			p.d = (c24 - c44)*invLen;
159			
160			// near
161			p = _frustumPlanes[4];
162			a = c31;
163			b = c32;
164			c = c33;
165			invLen = 1/Math.sqrt(a*a + b*b + c*c);
166			p.a = a*invLen;
167			p.b = b*invLen;
168			p.c = c*invLen;
169			p.d = -c34*invLen;
170			
171			// far
172			p = _frustumPlanes[5];
173			a = c41 - c31;
174			b = c42 - c32;
175			c = c43 - c33;
176			invLen = 1/Math.sqrt(a*a + b*b + c*c);
177			p.a = a*invLen;
178			p.b = b*invLen;
179			p.c = c*invLen;
180			p.d = (c34 - c44)*invLen;
181			
182			_frustumPlanesDirty = false;
183		}
184		
185		/**
186		 * @inheritDoc
187		 */
188		override protected function invalidateSceneTransform():void
189		{
190			super.invalidateSceneTransform();
191			
192			_viewProjectionDirty = true;
193			_frustumPlanesDirty = true;
194		}
195		
196		/**
197		 * @inheritDoc
198		 */
199		override protected function updateBounds():void
200		{
201			_bounds.nullify();
202			
203			_boundsInvalid = false;
204		}
205		
206		/**
207		 * @inheritDoc
208		 */
209		override protected function createEntityPartitionNode():EntityNode
210		{
211			return new CameraNode(this);
212		}
213		
214		/**
215		 * The lens used by the camera to perform the projection;
216		 */
217		public function get lens():LensBase
218		{
219			return _lens;
220		}
221		
222		public function set lens(value:LensBase):void
223		{
224			if (_lens == value)
225				return;
226			
227			if (!value)
228				throw new Error("Lens cannot be null!");
229
230			_lens.removeEventListener(LensEvent.MATRIX_CHANGED, onLensMatrixChanged);
231
232			_lens = value;
233			
234			_lens.addEventListener(LensEvent.MATRIX_CHANGED, onLensMatrixChanged);
235			
236			dispatchEvent(new CameraEvent(CameraEvent.LENS_CHANGED, this));
237		}
238		
239		/**
240		 * The view projection matrix of the camera.
241		 */
242		public function get viewProjection():Matrix3D
243		{
244			if (_viewProjectionDirty) {
245				_viewProjection.copyFrom(inverseSceneTransform);
246				_viewProjection.append(_lens.matrix);
247				_viewProjectionDirty = false;
248			}
249			
250			return _viewProjection;
251		}
252		
253		/**
254		 * Calculates the scene position of the given normalized coordinates in screen space.
255		 *
256		 * @param nX The normalised x coordinate in screen space, -1 corresponds to the left edge of the viewport, 1 to the right.
257		 * @param nY The normalised y coordinate in screen space, -1 corresponds to the top edge of the viewport, 1 to the bottom.
258		 * @param sZ The z coordinate in screen space, representing the distance into the screen.
259		 * @param v The destination Vector3D object
260		 * @return The scene position of the given screen coordinates.
261		 */
262		public function unproject(nX:Number, nY:Number, sZ:Number, v:Vector3D = null):Vector3D
263		{
264			return Matrix3DUtils.transformVector(sceneTransform, lens.unproject(nX, nY, sZ, v), v)
265		}
266		
267		/**
268		 * Calculates the ray in scene space from the camera to the given normalized coordinates in screen space.
269		 *
270		 * @param nX The normalised x coordinate in screen space, -1 corresponds to the left edge of the viewport, 1 to the right.
271		 * @param nY The normalised y coordinate in screen space, -1 corresponds to the top edge of the viewport, 1 to the bottom.
272		 * @param sZ The z coordinate in screen space, representing the distance into the screen.
273		 * @param v The destination Vector3D object
274		 * @return The ray from the camera to the scene space position of the given screen coordinates.
275		 */
276		public function getRay(nX:Number, nY:Number, sZ:Number, v:Vector3D = null):Vector3D
277		{
278			return Matrix3DUtils.deltaTransformVector(sceneTransform,lens.unproject(nX, nY, sZ, v), v);
279		}
280		
281		/**
282		 * Calculates the normalised position in screen space of the given scene position.
283		 *
284		 * @param point3d the position vector of the scene coordinates to be projected.
285		 * @param v The destination Vector3D object
286		 * @return The normalised screen position of the given scene coordinates.
287		 */
288		public function project(point3d:Vector3D, v:Vector3D = null):Vector3D
289		{
290			return lens.project(Matrix3DUtils.transformVector(inverseSceneTransform,point3d,v), v);
291		}
292	}
293}