PageRenderTime 3782ms CodeModel.GetById 37ms RepoModel.GetById 2ms app.codeStats 0ms

/sandy/haxe/tags/3.0.2/src/sandy/core/scenegraph/Camera3D.hx

http://sandy.googlecode.com/
Haxe | 467 lines | 245 code | 49 blank | 173 comment | 23 complexity | 3242239be04b7dc251a93b897c045ad2 MD5 | raw file
  1. /*
  2. # ***** BEGIN LICENSE BLOCK *****
  3. Copyright the original author or authors.
  4. Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.mozilla.org/MPL/MPL-1.1.html
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. # ***** END LICENSE BLOCK *****
  14. */
  15. package sandy.core.scenegraph;
  16. import flash.display.Sprite;
  17. import flash.geom.Rectangle;
  18. import sandy.core.Scene3D;
  19. import sandy.core.data.Matrix4;
  20. import sandy.core.data.Vertex;
  21. import sandy.core.data.Polygon;
  22. import sandy.util.NumberUtil;
  23. import sandy.view.Frustum;
  24. import sandy.view.ViewPort;
  25. /**
  26. * The Camera3D class is used to create a camera for the Sandy world.
  27. *
  28. * <p>As of this version of Sandy, the camera is added to the object tree,
  29. * which means it is transformed in the same manner as any other object.</p>
  30. *
  31. * @author Thomas Pfeiffer - kiroukou
  32. * @author Niel Drummond - haXe port
  33. *
  34. */
  35. class Camera3D extends ATransformable
  36. {
  37. /**
  38. * <p>Inverse of the model matrix
  39. * This is apply at the culling phasis
  40. * The matrix is inverted in comparison of the real model view matrix.<br/>
  41. * This allows replacement of the objects in the correct camera frame before projection</p>
  42. */
  43. public var invModelMatrix:Matrix4;
  44. /**
  45. * The camera viewport
  46. */
  47. public var viewport:ViewPort;
  48. /**
  49. * The frustum of the camera.
  50. */
  51. public var frustrum:Frustum;
  52. /**
  53. * Creates a camera for projecting visible objects in the world.
  54. *
  55. * <p>By default the camera shows a perspective projection. <br />
  56. * The camera is at -300 in z axis and look at the world 0,0,0 point.</p>
  57. *
  58. * @param p_nWidth Width of the camera viewport in pixels
  59. * @param p_nHeight Height of the camera viewport in pixels
  60. * @param p_nFov The vertical angle of view in degrees - Default 45
  61. * @param p_nNear The distance from the camera to the near clipping plane - Default 50
  62. * @param p_nFar The distance from the camera to the far clipping plane - Default 10000
  63. */
  64. public function new( p_nWidth:Int, p_nHeight:Int, ?p_nFov:Float, ?p_nNear:Float, ?p_nFar:Float )
  65. {
  66. if (p_nFov == null) p_nFov = 45;
  67. if (p_nNear == null) p_nNear = 50;
  68. if (p_nFar == null) p_nFar = 10000;
  69. super( null );
  70. invModelMatrix = new Matrix4();
  71. viewport = new ViewPort(640,480);
  72. frustrum = new Frustum();
  73. _perspectiveChanged = false;
  74. _mp = new Matrix4();
  75. _mpInv = new Matrix4();
  76. m_aDisplayList = new Array();
  77. viewport.width = p_nWidth;
  78. viewport.height = p_nHeight;
  79. // --
  80. _nFov = p_nFov;
  81. _nFar = p_nFar;
  82. _nNear = p_nNear;
  83. // --
  84. setPerspectiveProjection( _nFov, viewport.ratio, _nNear, _nFar );
  85. m_nOffx = viewport.width2;
  86. m_nOffy = viewport.height2;
  87. viewport.hasChanged = false;
  88. // It's a non visible node
  89. visible = false;
  90. z = -300;
  91. lookAt( 0,0,0 );
  92. }
  93. /**
  94. * The angle of view of this camera in degrees.
  95. */
  96. public function __setFov( p_nFov:Float ):Float
  97. {
  98. _nFov = p_nFov;
  99. _perspectiveChanged = true;
  100. return p_nFov;
  101. }
  102. /**
  103. * @private
  104. */
  105. public var fov(__getFov, __setFov):Float;
  106. private function __getFov():Float
  107. {return _nFov;}
  108. /**
  109. * Focal length of camera.
  110. *
  111. * <p>This value is a function of fov angle and viewport dimensions.
  112. * Writing this value changes fov angle only.</p>
  113. */
  114. public function __setFocalLength( f:Float ):Float
  115. {
  116. _nFov = Math.atan2 (viewport.height2, f) * 114.591559 /* 2 * (180 / Math.PI) */;
  117. _perspectiveChanged = true;
  118. return f;
  119. }
  120. /**
  121. * @private
  122. */
  123. public var focalLength(__getFocalLength, __setFocalLength):Float;
  124. private function __getFocalLength():Float
  125. {
  126. return viewport.height2 / Math.tan (_nFov * 0.00872664626 /* 1 / 2 * (Math.PI / 180) */ );
  127. }
  128. /**
  129. * Near plane distance for culling/clipping.
  130. */
  131. public function __setNear( pNear:Float ):Float
  132. {_nNear = pNear; _perspectiveChanged = true; return pNear;}
  133. /**
  134. * @private
  135. */
  136. public var near(__getNear, __setNear):Float;
  137. private function __getNear():Float
  138. {return _nNear;}
  139. /**
  140. * Far plane distance for culling/clipping.
  141. */
  142. public function __setFar( pFar:Float ):Float
  143. {_nFar = pFar;_perspectiveChanged = true; return pFar;}
  144. /**
  145. * @private
  146. */
  147. public var far(__getFar, __setFar):Float;
  148. private function __getFar():Float
  149. {return _nFar;}
  150. ///////////////////////////////////////
  151. //// GRAPHICAL ELEMENTS MANAGMENT /////
  152. ///////////////////////////////////////
  153. /**
  154. * Process the rendering of the scene.
  155. * The camera has all the information needed about the objects to render.
  156. *
  157. * The camera stores all the visible shape/polygons into an array, and loop through it calling their display method.
  158. * Before the display call, the container graphics is cleared.
  159. */
  160. public function renderDisplayList( p_oScene:Scene3D ):Void
  161. {
  162. var l_oShape:IDisplayable;
  163. // --
  164. if ( m_aDisplayedList != null )
  165. {
  166. for ( l_oShape in m_aDisplayedList )
  167. {
  168. l_oShape.clear();
  169. }
  170. }
  171. // --
  172. var l_mcContainer:Sprite = p_oScene.container;
  173. // we go high quality for drawing part
  174. //l_mcContainer.stage.quality = StageQuality.HIGH;
  175. // --
  176. /* we need to bypass visibility - untyped does not work on getters/setters */
  177. #if flash
  178. untyped m_aDisplayList.sortOn( "m_nDepth", Array.NUMERIC | Array.DESCENDING );
  179. #else
  180. m_aDisplayList.sort(function(a,b){return (a.depth>b.depth)?1:a.depth<b.depth?-1:0;} );
  181. #end
  182. for ( l_oShape in m_aDisplayList )
  183. {
  184. l_oShape.display( p_oScene );
  185. l_mcContainer.addChild( l_oShape.container );
  186. }
  187. // -- back to low quality
  188. //l_mcContainer.stage.quality = StageQuality.LOW;
  189. // --
  190. m_aDisplayedList = m_aDisplayList.splice(0,m_aDisplayList.length);
  191. }
  192. /**
  193. * Adds a displayable object to the display list.
  194. *
  195. * @param p_oShape The object to add
  196. */
  197. public function addToDisplayList( p_oShape:IDisplayable ):Void
  198. {
  199. if( p_oShape != null ) m_aDisplayList[m_aDisplayList.length] = ( p_oShape );
  200. }
  201. /**
  202. * Adds a displayable array of object to the display list.
  203. *
  204. * @param p_oShape The object to add
  205. */
  206. public function addArrayToDisplayList( p_aShapeArray:Array<IDisplayable> ):Void
  207. {
  208. m_aDisplayList = m_aDisplayList.concat( p_aShapeArray );
  209. }
  210. /**
  211. * <p>Project the vertices list given in parameter.
  212. * The vertices are projected to the screen, as a 2D position.
  213. * </p>
  214. */
  215. public function projectArray( p_oList:Array<Vertex> ):Void
  216. {
  217. var l_nX:Float = viewport.offset.x + m_nOffx;
  218. var l_nY:Float = viewport.offset.y + m_nOffy;
  219. var l_nCste:Float;
  220. var l_mp11_offx:Float = mp11 * m_nOffx;
  221. var l_mp22_offy:Float = mp22 * m_nOffy;
  222. for ( l_oVertex in p_oList )
  223. {
  224. if( !l_oVertex.projected )
  225. {
  226. l_nCste = 1 / l_oVertex.wz;
  227. l_oVertex.sx = l_nCste * l_oVertex.wx * l_mp11_offx + l_nX;
  228. l_oVertex.sy = -l_nCste * l_oVertex.wy * l_mp22_offy + l_nY;
  229. //nbVertices += 1;
  230. l_oVertex.projected = true;
  231. }
  232. }
  233. }
  234. /**
  235. * <p>Project the vertex passed as parameter.
  236. * The vertices are projected to the screen, as a 2D position.
  237. * </p>
  238. */
  239. public function projectVertex( p_oVertex:Vertex ):Void
  240. {
  241. var l_nX:Float = (viewport.offset.x + m_nOffx);
  242. var l_nY:Float = (viewport.offset.y + m_nOffy);
  243. var l_nCste:Float = 1 / p_oVertex.wz;
  244. p_oVertex.sx = l_nCste * p_oVertex.wx * mp11 * m_nOffx + l_nX;
  245. p_oVertex.sy = -l_nCste * p_oVertex.wy * mp22 * m_nOffy + l_nY;
  246. }
  247. /**
  248. * Nothing is done here - the camera is not rendered
  249. */
  250. public override function render( p_oScene:Scene3D, p_oCamera:Camera3D):Void
  251. {
  252. return;/* Nothing to do here */
  253. }
  254. /**
  255. * Updates the state of the camera transformation.
  256. *
  257. * @param p_oScene The current scene
  258. * @param p_oModelMatrix The matrix which represents the parent model matrix. Basically it stores the rotation/translation/scale of all the nodes above the current one.
  259. * @param p_bChanged A boolean value which specify if the state has changed since the previous rendering. If false, we save some matrix multiplication process.
  260. */
  261. public override function update( p_oScene:Scene3D, p_oModelMatrix:Matrix4, p_bChanged:Bool ):Void
  262. {
  263. if( viewport.hasChanged )
  264. {
  265. _perspectiveChanged = true;
  266. // -- update the local values
  267. m_nOffx = viewport.width2;
  268. m_nOffy = viewport.height2;
  269. // -- Apply a scrollRect to the container at the viewport dimension
  270. if( p_oScene.rectClipping )
  271. p_oScene.container.scrollRect = new Rectangle( 0, 0, viewport.width, viewport.height );
  272. // -- we warn the the modification has been taken under account
  273. viewport.hasChanged = false;
  274. }
  275. // --
  276. if( _perspectiveChanged ) updatePerspective();
  277. super.update( p_oScene, p_oModelMatrix, p_bChanged );
  278. // -- fast camera model matrix inverssion
  279. invModelMatrix.n11 = modelMatrix.n11;
  280. invModelMatrix.n12 = modelMatrix.n21;
  281. invModelMatrix.n13 = modelMatrix.n31;
  282. invModelMatrix.n21 = modelMatrix.n12;
  283. invModelMatrix.n22 = modelMatrix.n22;
  284. invModelMatrix.n23 = modelMatrix.n32;
  285. invModelMatrix.n31 = modelMatrix.n13;
  286. invModelMatrix.n32 = modelMatrix.n23;
  287. invModelMatrix.n33 = modelMatrix.n33;
  288. invModelMatrix.n14 = -(modelMatrix.n11 * modelMatrix.n14 + modelMatrix.n21 * modelMatrix.n24 + modelMatrix.n31 * modelMatrix.n34);
  289. invModelMatrix.n24 = -(modelMatrix.n12 * modelMatrix.n14 + modelMatrix.n22 * modelMatrix.n24 + modelMatrix.n32 * modelMatrix.n34);
  290. invModelMatrix.n34 = -(modelMatrix.n13 * modelMatrix.n14 + modelMatrix.n23 * modelMatrix.n24 + modelMatrix.n33 * modelMatrix.n34);
  291. }
  292. /**
  293. * Nothing to do - the camera can't be culled
  294. */
  295. public override function cull( p_oScene:Scene3D, p_oFrustum:Frustum, p_oViewMatrix:Matrix4, p_bChanged:Bool ):Void
  296. {
  297. return;
  298. }
  299. /**
  300. * Returns the projection matrix of this camera.
  301. *
  302. * @return The projection matrix
  303. */
  304. public var projectionMatrix(__getProjectionMatrix,null):Matrix4;
  305. private function __getProjectionMatrix():Matrix4
  306. {
  307. return _mp;
  308. }
  309. /**
  310. * Returns the inverse of the projection matrix of this camera.
  311. *
  312. * @return The inverted projection matrix
  313. */
  314. public var invProjectionMatrix(__getInvProjectionMatrix,null):Matrix4;
  315. private function __getInvProjectionMatrix():Matrix4
  316. {
  317. _mpInv.copy( _mp );
  318. _mpInv.inverse();
  319. return _mpInv;
  320. }
  321. /**
  322. * Sets a projection matrix with perspective.
  323. *
  324. * <p>This projection allows a natural visual presentation of objects, mimicking 3D perspective.</p>
  325. *
  326. * @param p_nFovY The angle of view in degrees - Default 45.
  327. * @param p_nAspectRatio The ratio between vertical and horizontal dimension - Default the viewport ratio (width/height)
  328. * @param p_nZNear The distance betweeen the camera and the near plane - Default 10.
  329. * @param p_nZFar The distance betweeen the camera position and the far plane. Default 10 000.
  330. */
  331. private function setPerspectiveProjection(p_nFovY:Float, p_nAspectRatio:Float, p_nZNear:Float, p_nZFar:Float):Void
  332. {
  333. var cotan:Float, Q:Float;
  334. // --
  335. frustrum.computePlanes(p_nAspectRatio, p_nZNear, p_nZFar, p_nFovY );
  336. // --
  337. p_nFovY = NumberUtil.toRadian( p_nFovY );
  338. cotan = 1 / Math.tan(p_nFovY / 2);
  339. Q = p_nZFar/(p_nZFar - p_nZNear);
  340. _mp.zero();
  341. _mp.n11 = cotan / p_nAspectRatio;
  342. _mp.n22 = cotan;
  343. _mp.n33 = Q;
  344. _mp.n34 = -Q*p_nZNear;
  345. _mp.n43 = 1;
  346. // to optimize later
  347. mp11 = _mp.n11; mp21 = _mp.n21; mp31 = _mp.n31; mp41 = _mp.n41;
  348. mp12 = _mp.n12; mp22 = _mp.n22; mp32 = _mp.n32; mp42 = _mp.n42;
  349. mp13 = _mp.n13; mp23 = _mp.n23; mp33 = _mp.n33; mp43 = _mp.n43;
  350. mp14 = _mp.n14; mp24 = _mp.n24; mp34 = _mp.n34; mp44 = _mp.n44;
  351. changed = true;
  352. }
  353. /**
  354. * Updates the perspective projection.
  355. */
  356. private function updatePerspective():Void
  357. {
  358. setPerspectiveProjection( _nFov, viewport.ratio, _nNear, _nFar );
  359. _perspectiveChanged = false;
  360. }
  361. /**
  362. * Delete the camera node and clear its displaylist.
  363. *
  364. */
  365. public override function destroy():Void
  366. {
  367. var l_oShape:IDisplayable;
  368. // --
  369. for ( l_oShape in m_aDisplayedList )
  370. {
  371. if( l_oShape != null ) l_oShape.clear();
  372. }
  373. for ( l_oShape in m_aDisplayList )
  374. {
  375. if( l_oShape != null ) l_oShape.clear();
  376. }
  377. // --
  378. m_aDisplayedList = null;
  379. m_aDisplayList = null;
  380. viewport = null;
  381. // --
  382. super.destroy();
  383. }
  384. public override function toString():String
  385. {
  386. return "sandy.core.scenegraph.Camera3D";
  387. }
  388. //////////////////////////
  389. /// PRIVATE PROPERTIES ///
  390. //////////////////////////
  391. private var _perspectiveChanged:Bool;
  392. private var _mp:Matrix4;
  393. private var _mpInv:Matrix4;
  394. private var m_aDisplayList:Array<IDisplayable>;
  395. private var m_aDisplayedList:Array<IDisplayable>;
  396. private var _nFov:Float;
  397. private var _nFar:Float;
  398. private var _nNear:Float;
  399. private var mp11:Float;
  400. private var mp21:Float;
  401. private var mp31:Float;
  402. private var mp41:Float;
  403. private var mp12:Float;
  404. private var mp22:Float;
  405. private var mp32:Float;
  406. private var mp42:Float;
  407. private var mp13:Float;
  408. private var mp23:Float;
  409. private var mp33:Float;
  410. private var mp43:Float;
  411. private var mp14:Float;
  412. private var mp24:Float;
  413. private var mp34:Float;
  414. private var mp44:Float;
  415. private var m_nOffx:Float;
  416. private var m_nOffy:Float;
  417. }