/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

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