PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/sandy/as3/branches/1.5/sandy/view/Camera3D.as

http://sandy.googlecode.com/
ActionScript | 535 lines | 289 code | 44 blank | 202 comment | 8 complexity | 27294095071e7350f0930631383eb943 MD5 | raw file
  1. ///////////////////////////////////////////////////////////
  2. // Camera3D.as
  3. // Macromedia ActionScript Implementation of the Class Camera3D
  4. // Generated by Enterprise Architect
  5. // Created on: 26-VII-2006 13:46:04
  6. // Original author: Thomas Pfeiffer - kiroukou
  7. ///////////////////////////////////////////////////////////
  8. package sandy.view
  9. {
  10. import sandy.core.data.Matrix4;
  11. import sandy.core.data.Vector;
  12. import sandy.view.IScreen;
  13. import sandy.core.transform.Interpolator3D;
  14. import sandy.events.InterpolationEvent;
  15. import sandy.math.Matrix4Math;
  16. import sandy.math.VectorMath;
  17. import sandy.core.transform.TransformType;
  18. import flash.display.Sprite;
  19. import flash.geom.Rectangle;
  20. /**
  21. * Camera3D
  22. * @author Thomas Pfeiffer - kiroukou
  23. * @version 1.0
  24. * @date 05.08.2006
  25. * @created 26-VII-2006 13:46:04
  26. */
  27. public class Camera3D
  28. {
  29. private var _compiled: Boolean;// boolean allowing kind of cache matrix computation
  30. private var _mp: Matrix4;// projection Matrix4
  31. private var _mt: Matrix4;// Matrix4 of tranformations
  32. private var _mv: Matrix4;// ViewPort matrix
  33. private var _nFocal: Number;// Nodal Distance of camera ( and not Focal )
  34. private var _nRoll: Number;// current roll value
  35. private var _nTilt: Number;// current tilt value
  36. private var _nYaw: Number;// current yaw value
  37. private var _p: Vector;// Position of camera ( a Vector )
  38. private var _rDim: Rectangle;// screen size useful to create an offset
  39. private var _vOut: Vector;// Camera view Orientation Vector
  40. private var _vSide: Vector;// Camera Side Orientation Vector
  41. private var _vUp: Vector;// Camera up Orientation Vector
  42. private var _screen:IScreen;// associated screen
  43. private var _oInt:Interpolator3D;// The interpolator
  44. /**
  45. * Camera's name
  46. */
  47. public var name:String;
  48. /**
  49. * Camera's angle
  50. */
  51. public var _angle:Vector;
  52. /**
  53. * final Matrix4 which is the result of the transformation and projection matrix's
  54. * multiplication.
  55. */
  56. public var matrix:Matrix4;
  57. /**
  58. * Create a new Camera3D.
  59. *
  60. * @param nFoc The focal of the Camera3D
  61. * @param s the screen associated to the camera
  62. */
  63. public function Camera3D( nFoc:Number, s:IScreen, nm:String = "Camera" )
  64. {
  65. name = nm;
  66. _p = new Vector();
  67. _screen = s;
  68. _nFocal = nFoc;
  69. // --
  70. _vOut = new Vector( 0, 0, 1 );
  71. _vSide = new Vector( 1, 0, 0 );
  72. _vUp = new Vector( 0, 1 ,0 );
  73. // --
  74. _nRoll = 0;
  75. _nTilt = 0;
  76. _nYaw = 0;
  77. // --
  78. _screen.setCamera ( this );
  79. _rDim = _screen.getSize();
  80. _mt = _mp = matrix = _mv = Matrix4.createIdentity();
  81. _compiled = false;
  82. __loadSimpleProjection();
  83. _oInt = null;
  84. }
  85. public function getScreen():IScreen
  86. {
  87. return _screen;
  88. }
  89. public function moveAroundY(pos:Vector,angle:Number,diatance:Number):void
  90. {
  91. _compiled=false;
  92. _angle.y+=angle;
  93. _p.x=pos.x+diatance*Math.sin(_angle.y);
  94. _p.z=pos.z+diatance*Math.cos(_angle.y);
  95. this.lookAt(pos.x,pos.y,pos.z);
  96. }
  97. /**
  98. * Allow the camera to translate along its side vector.
  99. * If you imagine yourself in a game, it would be a step on your right or on your left
  100. * @param d Number Move the camera along its side vector
  101. */
  102. public function moveSideways( d : Number ):void
  103. {
  104. _compiled = false;
  105. _p.x += _vSide.x * d;
  106. _p.y += _vSide.y * d;
  107. _p.z += _vSide.z * d;
  108. }
  109. /**
  110. * Allow the camera to translate along its up vector.
  111. * If you imagine yourself in a game, it would be a jump on the direction of your body (so not always the vertical!)
  112. * @param d Number Move the camera along its up vector
  113. */
  114. public function moveUpwards( d : Number ):void
  115. {
  116. _compiled = false;
  117. _p.x += _vUp.x * d;
  118. _p.y += _vUp.y * d;
  119. _p.z += _vUp.z * d;
  120. }
  121. /**
  122. * Allow the camera to translate along its view vector.
  123. * If you imagine yourself in a game, it would be a step in the direction you look at. If you look the sky
  124. * you will translate upwards ! So be careful with its use.
  125. * @param d Number Move the camera along its viw vector
  126. */
  127. public function moveForward( d : Number ):void
  128. {
  129. _compiled = false;
  130. _p.x += _vOut.x * d;
  131. _p.y += _vOut.y * d;
  132. _p.z += _vOut.z * d;
  133. }
  134. /**
  135. * Allow the camera to translate horizontally
  136. * If you imagine yourself in a game, it would be a step in the direction you look at but without changing
  137. * your altitude.
  138. * @param d Number Move the camera horizontally
  139. */
  140. public function moveHorizontally( d:Number ):void
  141. {
  142. _compiled = false;
  143. _p.x += _vOut.x * d;
  144. _p.z += _vOut.z * d;
  145. }
  146. /**
  147. * Allow the camera to translate vertically
  148. * If you imagine yourself in a game, it would be a jump strictly vertical.
  149. * @param d Number Move the camera vertically
  150. */
  151. public function moveVertically( d:Number ):void
  152. {
  153. _compiled = false;
  154. _p.y -= d;
  155. }
  156. /**
  157. * Translate the camera from it's actual position with the offset values pased in parameters
  158. *
  159. * @param px x offset that will be added to the x coordinate of the camera
  160. * @param py y offset that will be added to the y coordinate position of the camera
  161. * @param pz z offset that will be added to the z coordinate position of the camera
  162. */
  163. public function translate( px:Number, py:Number, pz:Number ):void
  164. {
  165. _compiled = false;
  166. // we must consider the screen y-axis inversion
  167. _p.x += px;
  168. _p.y -= py;
  169. _p.z += pz;
  170. }
  171. /**
  172. * Allow the camera to translate lateraly
  173. * If you imagine yourself in a game, it would be a step on the right with a positiv parameter and to the left
  174. * with a negative parameter
  175. * @param d Number Move the camera lateraly
  176. */
  177. public function moveLateraly( d:Number ):void
  178. {
  179. _compiled = false;
  180. _p.x += d;
  181. }
  182. /**
  183. * Rotate the camera around a specific axis by an angle passed in parameter
  184. * @param ax Number The x coordinate of the axis
  185. * @param ay Number The y coordinate of the axis
  186. * @param az Number The z coordinate of the axis
  187. * @param nAngle Number The amount of rotation. This angle is in degrees.
  188. */
  189. public function rotateAxis( ax:Number, ay:Number, az:Number, nAngle:Number ):void
  190. {
  191. _compiled = false;
  192. nAngle = (nAngle + 360)%360;
  193. var n:Number = Math.sqrt( ax*ax + ay*ay + az*az );
  194. var m : Matrix4 = Matrix4Math.axisRotation( ax/n, ay/n, az/n, nAngle );
  195. Matrix4Math.vectorMult3x3( m, _vSide);
  196. Matrix4Math.vectorMult3x3( m, _vUp);
  197. Matrix4Math.vectorMult3x3( m, _vOut);
  198. }
  199. /**
  200. * Make the camera look at a specific position. Useful to follow a moving object or a static object while the camera is moving.
  201. * @param px Number The x position to look at
  202. * @param py Number The y position to look at
  203. * @param pz Number The z position to look at
  204. */
  205. public function lookAt( px:Number, py:Number, pz:Number ):void
  206. {
  207. _compiled = false;
  208. _vOut = VectorMath.sub( new Vector(px, -py, pz), _p );
  209. VectorMath.normalize( _vOut );
  210. _vSide = VectorMath.cross( _vOut, new Vector(0, -1, 0) );
  211. VectorMath.normalize( _vSide );
  212. _vUp = VectorMath.cross( _vOut, _vSide );
  213. VectorMath.normalize( _vUp );
  214. }
  215. /**
  216. * RotateX - Rotation around the global X axis of the camera frame
  217. * @param nAngle Number The angle of rotation in degree.
  218. * @return Void
  219. */
  220. public function rotateX ( nAngle:Number ):void
  221. {
  222. _compiled = false;
  223. nAngle = (nAngle + 360)%360;
  224. var m:Matrix4 = Matrix4Math.axisRotation ( 1, 0, 0, nAngle );
  225. Matrix4Math.vectorMult3x3( m, _vUp);
  226. Matrix4Math.vectorMult3x3( m, _vSide);
  227. Matrix4Math.vectorMult3x3( m, _vOut);
  228. }
  229. /**
  230. * rotateY - Rotation around the global Y axis of the camera frame
  231. * @param nAngle Number The angle of rotation in degree.
  232. * @return Void
  233. */
  234. public function rotateY ( nAngle:Number ):void
  235. {
  236. _compiled = false;
  237. nAngle = (nAngle + 360)%360;
  238. var m:Matrix4 = Matrix4Math.axisRotation ( 0, 1, 0, nAngle );
  239. Matrix4Math.vectorMult3x3( m, _vUp);
  240. Matrix4Math.vectorMult3x3( m, _vSide);
  241. Matrix4Math.vectorMult3x3( m, _vOut);
  242. }
  243. /**
  244. * rotateZ - Rotation around the global Z axis of the camera frame
  245. * @param nAngle Number The angle of rotation in degree between : [ -180; 180 ].
  246. * @return
  247. */
  248. public function rotateZ ( nAngle:Number ):void
  249. {
  250. _compiled = false;
  251. nAngle = (nAngle + 360)%360;
  252. var m:Matrix4 = Matrix4Math.axisRotation ( 0, 0, 1, nAngle );
  253. Matrix4Math.vectorMult3x3( m, _vUp);
  254. Matrix4Math.vectorMult3x3( m, _vSide);
  255. Matrix4Math.vectorMult3x3( m, _vOut);
  256. }
  257. /**
  258. * Tilt - Rotation around the local X axis of the camera frame
  259. * Range from -90 to +90 where 0 = Horizon, +90 = straight up and –90 = straight down.
  260. * @param nAngle Number The angle of rotation in degree.
  261. * @return Void
  262. */
  263. public function tilt ( nAngle:Number ):void
  264. {
  265. //_nTilt = NumberUtil.constrain( _nTilt + nAngle, -90, 90 );
  266. //if( _nTilt == -90 || _nTilt == 90 ) return;
  267. _compiled = false;
  268. nAngle = (nAngle + 360)%360;
  269. var m:Matrix4 = Matrix4Math.axisRotation ( _vSide.x, _vSide.y, _vSide.z, nAngle );
  270. Matrix4Math.vectorMult3x3( m, _vUp);
  271. Matrix4Math.vectorMult3x3( m, _vOut);
  272. }
  273. /**
  274. * Pan - Rotation around the local Y axis of the camera frame
  275. * Range from 0 to 360 where 0=North, 90=East, 180=South and 270=West.
  276. * @param nAngle Number The angle of rotation in degree.
  277. * @return Void
  278. */
  279. public function pan ( nAngle:Number ):void
  280. {
  281. _compiled = false;
  282. nAngle = (nAngle + 360)%360;
  283. //_nYaw = NumberUtil.constrain( (_nYaw + nAngle)%360, 0, 360 );
  284. var m:Matrix4 = Matrix4Math.axisRotation ( _vUp.x, _vUp.y, _vUp.z, nAngle );
  285. Matrix4Math.vectorMult3x3( m, _vSide);
  286. Matrix4Math.vectorMult3x3( m, _vOut);
  287. }
  288. /**
  289. * roll - Rotation around the local Z axis of the camera frame
  290. * Range from -180 to +180 where 0 means the plane is aligned with the horizon,
  291. * +180 = Full roll right and –180 = Full roll left. In both cases, when the roll is 180 and –180,
  292. * the plane is flipped on its back.
  293. * @param nAngle Number The angle of rotation in degree.
  294. * @return
  295. */
  296. public function roll ( nAngle:Number ):void
  297. {
  298. //_nRoll = NumberUtil.constrain( _nRoll + nAngle, -180, 180 );
  299. //if( _nRoll == -180 || _nRoll == 180 ) return;
  300. _compiled = false;
  301. nAngle = (nAngle + 360)%360;
  302. var m:Matrix4 = Matrix4Math.axisRotation ( _vOut.x, _vOut.y, _vOut.z, nAngle );
  303. Matrix4Math.vectorMult3x3( m, _vSide);
  304. Matrix4Math.vectorMult3x3( m, _vUp);
  305. }
  306. /**
  307. * Set the position of the camera. Basically apply a translation.
  308. * @param x x position of the camera
  309. * @param y y position of the camera
  310. * @param z z position of the camera
  311. */
  312. public function setPosition( x : Number, y : Number, z : Number ):void
  313. {
  314. _compiled = false;
  315. // we must consider the screen y-axis inversion
  316. _p.x = x;
  317. _p.y = -y;
  318. _p.z = z;
  319. }
  320. /**
  321. * Get the offset of the screen of the camera along axis.
  322. * @return a Number corresponding to the offset
  323. */
  324. public function getXOffset():Number
  325. {
  326. return _rDim.width / 2;
  327. }
  328. /**
  329. * Get the offset of the screen of the camera along Y axis.
  330. * @return a Number corresponding to the offset
  331. */
  332. public function getYOffset():Number
  333. {
  334. return _rDim.height / 2;
  335. }
  336. /**
  337. * Get the position of the camera.
  338. * @return the position of the camera as a Vector
  339. */
  340. public function getPosition():Vector
  341. {
  342. return new Vector(_p.x, - _p.y, _p.z );
  343. }
  344. /**
  345. * Set the screen of the camera.
  346. * @param {code s} the Screen instance
  347. */
  348. public function setScreen( s:IScreen ):void
  349. {
  350. _screen = s;
  351. _rDim = _screen.getSize();
  352. _screen.setCamera ( this );
  353. }
  354. /**
  355. * Set the nodal distance of the camera.
  356. * @param n the nodal distance
  357. */
  358. public function setFocal( n:Number ):void
  359. {
  360. _compiled = false;
  361. _nFocal = n;
  362. __loadSimpleProjection();
  363. }
  364. /**
  365. * Return the nodal distance of the camera.
  366. * @return a Number as the nodal distance
  367. */
  368. public function getFocal():Number
  369. {
  370. return _nFocal;
  371. }
  372. /**
  373. * Set an interpolator to the camera. Currently the camera handles only a Path interpolator or a Position interpolation.
  374. * @param i Interpolator3D The interpolator you want to apply to the camera. It must be a Path interpolator or a Position interpolation
  375. * @return Boolean True is the operation goes well, false otherwise
  376. */
  377. public function setInterpolator( i:Interpolator3D ):Boolean
  378. {
  379. if( i.getType() == TransformType.PATH_INTERPOLATION || i.getType() == TransformType.TRANSLATION_INTERPOLATION )
  380. {
  381. removeInterpolator();
  382. _oInt = i;
  383. _oInt.addEventListener( InterpolationEvent.onProgressEVENT, __onInterpolation );
  384. return true;
  385. }
  386. else
  387. {
  388. return false;
  389. }
  390. }
  391. /**
  392. * REmove the interpolator is exist. remove also the listeners.
  393. * @param Void
  394. * @return Boolean True is the operation goes well, false otherwise.
  395. */
  396. public function removeInterpolator():Boolean
  397. {
  398. if( null == _oInt )
  399. {
  400. return false;
  401. }
  402. else
  403. {
  404. _oInt.removeEventListener( InterpolationEvent.onProgressEVENT, __onInterpolation );
  405. _oInt = null;
  406. return true;
  407. }
  408. }
  409. /**
  410. * This method helps you to know if something has changed in the camera, and if you need to compile it again to take care about the modifications.
  411. * @param Void
  412. * @return Boolean True value is returned if something has changed, false otherwise.
  413. */
  414. public function isModified():Boolean
  415. {
  416. return (_compiled == false);
  417. }
  418. /**
  419. * Compile the camera transformations by multiplicating the matrix together.
  420. * Be carefull to call isModified method before to save computations.
  421. */
  422. public function compile():void
  423. {
  424. if(! _compiled )
  425. {
  426. // we set up the rotation matrix from euler's angle
  427. _mt = __updateRotationMatrix();
  428. // we add the translation effect
  429. _mt = Matrix4Math.multiply ( _mt, Matrix4Math.translation( -_p.x, - _p.y, -_p.z ) );
  430. matrix = Matrix4Math.multiply ( _mp, _mt );
  431. _compiled = true;
  432. }
  433. }
  434. /**
  435. * Return the projection matrix.
  436. *
  437. * @return Matrix4
  438. */
  439. public function getProjectionMatrix():Matrix4
  440. {
  441. return _mp;
  442. }
  443. /**
  444. * Return the transformation matrix.
  445. *
  446. * @return Matrix4
  447. */
  448. public function getTransformMatrix():Matrix4
  449. {
  450. return _mt;
  451. }
  452. //
  453. // PRIVATE
  454. //
  455. /**
  456. * __loadProjection (private)
  457. *
  458. * <p>Compute the projection matrix</p>
  459. *
  460. */
  461. private function __loadSimpleProjection():void
  462. {
  463. _mp.n12 = _mp.n13 = _mp.n14 = _mp.n21 = _mp.n23 = _mp.n24 = _mp.n31 = _mp.n32 = _mp.n34 = _mp.n41 = _mp.n42 = _mp.n44 = 0;
  464. _mp.n11 = _mp.n22 = _mp.n33 = _nFocal;
  465. _mp.n43 = 1;
  466. }
  467. private function __updateRotationMatrix ():Matrix4
  468. {
  469. return new Matrix4( _vSide.x, _vSide.y, _vSide.z, 0,
  470. _vUp.x, _vUp.y, _vUp.z, 0,
  471. _vOut.x, _vOut.y, _vOut.z, 0,
  472. 0, 0, 0, 1 );
  473. }
  474. /**
  475. * On an interpolation event, we compute the correct position, and update the camera.
  476. * @param e
  477. */
  478. private function __onInterpolation( e:InterpolationEvent ):void
  479. {
  480. var m:Matrix4 = (e.target as Interpolator3D).getMatrix();
  481. _p.x = m.n14;
  482. _p.y = m.n24;
  483. _p.z = m.n34;
  484. _compiled = false;
  485. }
  486. public function toString():String
  487. {
  488. return "Camera3D: " + name;
  489. }
  490. }//end Camera3D
  491. }