PageRenderTime 93ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/!src/net/badimon/five3D/display/Sprite3D.as

https://github.com/tluczyns/tluczyns-as3-base
ActionScript | 618 lines | 350 code | 66 blank | 202 comment | 37 complexity | 080727e33258d7b89e872ee04f5e75b1 MD5 | raw file
  1. /*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. FIVe3D
  3. Flash Interactive Vector-based 3D
  4. Mathieu Badimon | five3d@mathieu-badimon.com
  5. http://five3D.mathieu-badimon.com | http://five3d.mathieu-badimon.com/archives/ | http://code.google.com/p/five3d/
  6. /*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  7. package net.badimon.five3D.display {
  8. import net.badimon.five3D.utils.InternalUtils;
  9. import flash.display.DisplayObject;
  10. import flash.display.Graphics;
  11. import flash.display.Sprite;
  12. import flash.geom.ColorTransform;
  13. import flash.geom.Matrix3D;
  14. import flash.geom.Point;
  15. import flash.geom.Rectangle;
  16. import flash.geom.Vector3D;
  17. /**
  18. * The Sprite3D class is the equivalent in the FIVe3D package of the Sprite class in the Flash package.
  19. *
  20. * @see Sprite2D
  21. * @see http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/display/Sprite.html
  22. */
  23. public class Sprite3D extends Sprite implements IObject3D {
  24. private var __visible:Boolean = true;
  25. private var __x:Number = 0;
  26. private var __y:Number = 0;
  27. private var __z:Number = 0;
  28. private var __scaleX:Number = 1;
  29. private var __scaleY:Number = 1;
  30. private var __scaleZ:Number = 1;
  31. private var __rotationX:Number = 0;
  32. private var __rotationY:Number = 0;
  33. private var __rotationZ:Number = 0;
  34. private var __matrix:Matrix3D;
  35. private var __concatenatedMatrix:Matrix3D;
  36. private var __graphics:Graphics3D;
  37. private var __singleSided:Boolean = false;
  38. private var __flatShaded:Boolean = false;
  39. private var __childrenSorted:Boolean = false;
  40. private var __render:Boolean = true;
  41. private var __renderCulling:Boolean = false;
  42. private var __renderShading:Boolean = false;
  43. private var __flatShading:Boolean = false;
  44. // Calculation
  45. private var __isMatrixDirty:Boolean = true;
  46. private var __autoUpdatePropertiesOnMatrixChange:Boolean = false;
  47. private var __vectorIn:Vector.<Number>;
  48. private var __vectorOut:Vector.<Number>;
  49. private var __normalVector:Vector3D = new Vector3D();
  50. private var __normalVectorCalculated:Boolean = false;
  51. private var __cameraVector:Vector3D = new Vector3D();
  52. private var __culling:Boolean = false;
  53. /**
  54. * Creates a new Sprite3D instance.
  55. */
  56. public function Sprite3D() {
  57. __matrix = new Matrix3D();
  58. __concatenatedMatrix = new Matrix3D();
  59. __graphics = new Graphics3D();
  60. initVectors();
  61. }
  62. private function initVectors():void {
  63. __vectorIn = new Vector.<Number>(6, true);
  64. __vectorIn[5] = 1;
  65. __vectorOut = new Vector.<Number>(6, true);
  66. }
  67. //----------------------------------------------------------------------------------------------------
  68. // Properties (from normal "Sprite" class)
  69. //----------------------------------------------------------------------------------------------------
  70. /**
  71. * Whether or not the Sprite3D instance is visible. When the Sprite3D instance is not visible, 3D calculation and rendering are not executed.
  72. * Any change of this property takes effect the next time the instance is being rendered.
  73. *
  74. * <p>This property has the same behavior than the normal Sprite <code>visible</code> property.</p>
  75. */
  76. override public function get visible():Boolean {
  77. return __visible;
  78. }
  79. override public function set visible(value:Boolean):void {
  80. __visible = value;
  81. }
  82. /**
  83. * Indicates the x coordinate (in pixels) of the mouse position on the 3D plane defined by the Sprite3D instance.
  84. *
  85. * <p>This property calculation is intensive and requires the same matrix transformations than the <code>mouseY</code> property calculation.
  86. * Therefore using <code>mouseXY</code> is faster than <code>mouseX</code> and <code>mouseY</code> separately.</p>
  87. *
  88. * @see #mouseXY
  89. */
  90. override public function get mouseX():Number {
  91. var scene:Scene3D = InternalUtils.getScene(this);
  92. if (scene == null) {
  93. return NaN;
  94. } else {
  95. return InternalUtils.getInverseCoordinates(__concatenatedMatrix, scene.mouseX, scene.mouseY, scene.viewDistance).x;
  96. }
  97. }
  98. /**
  99. * Indicates the y coordinate (in pixels) of the mouse position on the 3D plane defined by the Sprite3D instance.
  100. *
  101. * <p>This property calculation is intensive and requires the same matrix transformations than the <code>mouseY</code> property calculation.
  102. * Therefore using <code>mouseXY</code> is faster than <code>mouseX</code> and <code>mouseY</code> separately.</p>
  103. *
  104. * @see #mouseXY
  105. */
  106. override public function get mouseY():Number {
  107. var scene:Scene3D = InternalUtils.getScene(this);
  108. if (scene == null) {
  109. return NaN;
  110. } else {
  111. return InternalUtils.getInverseCoordinates(__concatenatedMatrix, scene.mouseX, scene.mouseY, scene.viewDistance).y;
  112. }
  113. }
  114. /**
  115. * Indicates the x and y coordinates (in pixels) of the mouse position on the 3D plane defined by the Sprite3D instance.
  116. */
  117. public function get mouseXY():Point {
  118. var scene:Scene3D = InternalUtils.getScene(this);
  119. if (scene == null) {
  120. return null;
  121. } else {
  122. return InternalUtils.getInverseCoordinates(__concatenatedMatrix, scene.mouseX, scene.mouseY, scene.viewDistance);
  123. }
  124. }
  125. /**
  126. * Indicates the x coordinate along the x-axis of the Sprite3D instance relative to the local coordinate system of the 3D parent container.
  127. *
  128. * <p>This property has the same behavior than the normal Sprite <code>x</code> property.</p>
  129. */
  130. override public function get x():Number {
  131. return __x;
  132. }
  133. override public function set x(value:Number):void {
  134. __x = value;
  135. __isMatrixDirty = true;
  136. askRendering();
  137. }
  138. /**
  139. * Indicates the y coordinate along the y-axis of the Sprite3D instance relative to the local coordinate system of the 3D parent container.
  140. *
  141. * <p>This property has the same behavior than the normal Sprite <code>y</code> property.</p>
  142. */
  143. override public function get y():Number {
  144. return __y;
  145. }
  146. override public function set y(value:Number):void {
  147. __y = value;
  148. __isMatrixDirty = true;
  149. askRendering();
  150. }
  151. /**
  152. * Indicates the z coordinate along the z-axis of the Sprite3D instance relative to the local coordinate system of the 3D parent container.
  153. *
  154. * <p>This property has the same behavior than the normal Sprite <code>z</code> property.</p>
  155. */
  156. override public function get z():Number {
  157. return __z;
  158. }
  159. override public function set z(value:Number):void {
  160. __z = value;
  161. __isMatrixDirty = true;
  162. askRendering();
  163. }
  164. /**
  165. * Indicates the x-axis scale (percentage) of the Sprite3D instance from its registration point relative to the local coordinate system of the 3D parent container.
  166. * A value of 0.0 equals a 0% scale and a value of 1.0 equals a 100% scale.
  167. *
  168. * <p>This property has the same behavior than the normal Sprite <code>scaleX</code> property.</p>
  169. */
  170. override public function get scaleX():Number {
  171. return __scaleX;
  172. }
  173. override public function set scaleX(value:Number):void {
  174. __scaleX = value;
  175. __isMatrixDirty = true;
  176. askRendering();
  177. }
  178. /**
  179. * Indicates the y-axis scale (percentage) of the Sprite3D instance from its registration point relative to the local coordinate system of the 3D parent container.
  180. * A value of 0.0 equals a 0% scale and a value of 1.0 equals a 100% scale.
  181. *
  182. * <p>This property has the same behavior than the normal Sprite <code>scaleY</code> property.</p>
  183. */
  184. override public function get scaleY():Number {
  185. return __scaleY;
  186. }
  187. override public function set scaleY(value:Number):void {
  188. __scaleY = value;
  189. __isMatrixDirty = true;
  190. askRendering();
  191. }
  192. /**
  193. * Indicates the z-axis scale (percentage) of the Sprite3D instance from its registration point relative to the local coordinate system of the 3D parent container.
  194. * A value of 0.0 equals a 0% scale and a value of 1.0 equals a 100% scale.
  195. *
  196. * <p>This property has the same behavior than the normal Sprite <code>scaleZ</code> property.</p>
  197. */
  198. override public function get scaleZ():Number {
  199. return __scaleZ;
  200. }
  201. override public function set scaleZ(value:Number):void {
  202. __scaleZ = value;
  203. __isMatrixDirty = true;
  204. askRendering();
  205. }
  206. /**
  207. * Indicates the x-axis rotation (in degrees) of the Sprite3D instance from its original orientation relative to the local coordinate system of the 3D parent container.
  208. * Values go from -180 (included) to 180 (included). Values outside this range will be formated to fit in.
  209. *
  210. * <p>This property has the same behavior than the normal Sprite <code>rotationX</code> property.</p>
  211. */
  212. override public function get rotationX():Number {
  213. return __rotationX;
  214. }
  215. override public function set rotationX(value:Number):void {
  216. __rotationX = InternalUtils.formatRotation(value);
  217. __isMatrixDirty = true;
  218. askRendering();
  219. }
  220. /**
  221. * Indicates the y-axis rotation (in degrees) of the Sprite3D instance from its original orientation relative to the local coordinate system of the 3D parent container.
  222. * Values go from -180 (included) to 180 (included). Values outside this range will be formated to fit in.
  223. *
  224. * <p>This property has the same behavior than the normal Sprite <code>rotationY</code> property.</p>
  225. */
  226. override public function get rotationY():Number {
  227. return __rotationY;
  228. }
  229. override public function set rotationY(value:Number):void {
  230. __rotationY = InternalUtils.formatRotation(value);
  231. __isMatrixDirty = true;
  232. askRendering();
  233. }
  234. /**
  235. * Indicates the z-axis rotation (in degrees) of the Sprite3D instance from its original orientation relative to the local coordinate system of the 3D parent container.
  236. * Values go from -180 (included) to 180 (included). Values outside this range will be formated to fit in.
  237. *
  238. * <p>This property has the same behavior than the normal Sprite <code>rotationZ</code> property.</p>
  239. */
  240. override public function get rotationZ():Number {
  241. return __rotationZ;
  242. }
  243. override public function set rotationZ(value:Number):void {
  244. __rotationZ = InternalUtils.formatRotation(value);
  245. __isMatrixDirty = true;
  246. askRendering();
  247. }
  248. //----------------------------------------------------------------------------------------------------
  249. // Properties (new)
  250. //----------------------------------------------------------------------------------------------------
  251. /**
  252. * Indicates a Matrix3D object representing the combined transformation matrixes of the Sprite3D instance and all of its parent 3D objects, back to the scene level.
  253. */
  254. public function get concatenatedMatrix():Matrix3D {
  255. return __concatenatedMatrix;
  256. }
  257. /**
  258. * Specifies the Graphics3D object that belongs to this Sprite3D instance where vector drawing commands can occur.
  259. *
  260. * <p>This property replaces the normal Sprite <code>graphics</code> property. The access to the normal Sprite <code>graphics</code> property throws an error.</p>
  261. */
  262. public function get graphics3D():Graphics3D {
  263. return __graphics;
  264. }
  265. /**
  266. * A Matrix3D object containing values that affect the scaling, rotation, and translation of the Sprite3D instance.
  267. */
  268. public function get matrix():Matrix3D {
  269. if (__isMatrixDirty) {
  270. InternalUtils.setMatrix(__matrix, __x, __y, __z, __rotationX, __rotationY, __rotationZ, __scaleX, __scaleY, __scaleZ);
  271. __isMatrixDirty = false;
  272. }
  273. return __matrix;
  274. }
  275. public function set matrix(value:Matrix3D):void {
  276. __matrix = value;
  277. __isMatrixDirty = false;
  278. askRendering();
  279. if (autoUpdatePropertiesOnMatrixChange) updatePropertiesFromMatrix();
  280. }
  281. /**
  282. * Whether or not the Sprite3D instance transformation properties (x, y, z, scaleX, scaleY, scaleZ, rotationX, rotationY, rotationZ) are updated immediately after the matrix has been changed manually.
  283. *
  284. * @see #matrix
  285. * @see #updatePropertiesFromMatrix()
  286. */
  287. public function get autoUpdatePropertiesOnMatrixChange():Boolean {
  288. return __autoUpdatePropertiesOnMatrixChange;
  289. }
  290. public function set autoUpdatePropertiesOnMatrixChange(value:Boolean):void {
  291. __autoUpdatePropertiesOnMatrixChange = value;
  292. }
  293. /**
  294. * Whether or not the Sprite3D instance is visible when not facing the screen.
  295. */
  296. public function get singleSided():Boolean {
  297. return __singleSided;
  298. }
  299. public function set singleSided(value:Boolean):void {
  300. __singleSided = value;
  301. if (__singleSided) {
  302. __renderCulling = true;
  303. } else {
  304. __renderCulling = false;
  305. __culling = false;
  306. }
  307. }
  308. /**
  309. * Whether or not the Sprite3D instance colors are being altered by the scene ligthing parameters.
  310. *
  311. * @see net.badimon.five3D.display.Scene3D.#ambientLightVector
  312. * @see net.badimon.five3D.display.Scene3D.#ambientLightIntensity
  313. */
  314. public function get flatShaded():Boolean {
  315. return __flatShaded;
  316. }
  317. public function set flatShaded(value:Boolean):void {
  318. __flatShaded = value;
  319. if (__flatShaded) {
  320. __renderShading = true;
  321. } else {
  322. __renderShading = false;
  323. if (__flatShading) removeFlatShading();
  324. }
  325. }
  326. /**
  327. * Whether or not the Sprite3D instance will sort its direct children according to their respective depths. The depth of each child is determined by the z coordinate of its registration point.
  328. */
  329. public function get childrenSorted():Boolean {
  330. return __childrenSorted;
  331. }
  332. public function set childrenSorted(value:Boolean):void {
  333. __childrenSorted = value;
  334. }
  335. //----------------------------------------------------------------------------------------------------
  336. // Methods (new)
  337. //----------------------------------------------------------------------------------------------------
  338. /**
  339. * Updates the transformation properties (x, y, z, scaleX, scaleY, scaleZ, rotationX, rotationY, rotationZ) of the Sprite3D instance according to the matrix values.
  340. *
  341. * @see #matrix
  342. * @see #autoUpdatePropertiesOnMatrixChange
  343. */
  344. public function updatePropertiesFromMatrix():void {
  345. var matrixVector:Vector.<Vector3D> = __matrix.decompose();
  346. var translationVector:Vector3D = matrixVector[0];
  347. var rotationVector:Vector3D = matrixVector[1];
  348. var scaleVector:Vector3D = matrixVector[2];
  349. __x = translationVector.x;
  350. __y = translationVector.y;
  351. __z = translationVector.z;
  352. __rotationX = InternalUtils.formatRotation(rotationVector.x * InternalUtils.RAD_TO_DEG);
  353. __rotationY = InternalUtils.formatRotation(rotationVector.y * InternalUtils.RAD_TO_DEG);
  354. __rotationZ = InternalUtils.formatRotation(rotationVector.z * InternalUtils.RAD_TO_DEG);
  355. __scaleX = scaleVector.x;
  356. __scaleY = scaleVector.y;
  357. __scaleZ = scaleVector.z;
  358. }
  359. //----------------------------------------------------------------------------------------------------
  360. // Workflow
  361. //----------------------------------------------------------------------------------------------------
  362. /**
  363. * @private
  364. */
  365. public function askRendering():void {
  366. __render = true;
  367. __graphics.askRendering();
  368. if (__singleSided) __renderCulling = true;
  369. if (__flatShaded) __renderShading = true;
  370. var num:int = numChildren;
  371. for (var i:int = 0;i < num; i++) IObject3D(getChildAt(i)).askRendering();
  372. }
  373. /**
  374. * @private
  375. */
  376. public function askRenderingShading():void {
  377. if (__flatShaded) __renderShading = true;
  378. var num:int = numChildren;
  379. for (var i:int = 0;i < num; i++) IObject3D(getChildAt(i)).askRenderingShading();
  380. }
  381. /**
  382. * @private
  383. */
  384. public function render(scene:Scene3D):void {
  385. if (!__visible && super.visible) super.visible = false;
  386. else if (__visible) {
  387. if (__render) {
  388. if (__isMatrixDirty) {
  389. InternalUtils.setMatrix(__matrix, __x, __y, __z, __rotationX, __rotationY, __rotationZ, __scaleX, __scaleY, __scaleZ);
  390. __isMatrixDirty = false;
  391. }
  392. InternalUtils.setConcatenatedMatrix(__concatenatedMatrix, parent, __matrix);
  393. __normalVectorCalculated = false;
  394. __render = false;
  395. }
  396. if (__renderCulling) {
  397. setNormalVector();
  398. setCulling(scene.viewDistance);
  399. __normalVectorCalculated = true;
  400. __renderCulling = false;
  401. }
  402. if (__culling) {
  403. if (super.visible) super.visible = false;
  404. } else {
  405. if (!super.visible) super.visible = true;
  406. __graphics.render(super.graphics, __concatenatedMatrix, scene.viewDistance);
  407. if (__renderShading) {
  408. setNormalVector();
  409. applyFlatShading(scene);
  410. __renderShading = false;
  411. }
  412. var num:int = numChildren;
  413. for (var i:int = 0;i < num; i++) IObject3D(getChildAt(i)).render(scene);
  414. if (__childrenSorted) sortChildren();
  415. }
  416. }
  417. }
  418. private function setNormalVector():void {
  419. __concatenatedMatrix.transformVectors(__vectorIn, __vectorOut);
  420. __normalVector.x = __vectorOut[3] - __vectorOut[0];
  421. __normalVector.y = __vectorOut[4] - __vectorOut[1];
  422. __normalVector.z = __vectorOut[5] - __vectorOut[2];
  423. }
  424. private function setCulling(viewDistance:Number):void {
  425. __cameraVector.x = __vectorOut[0];
  426. __cameraVector.y = __vectorOut[1];
  427. __cameraVector.z = __vectorOut[2] + viewDistance;
  428. __culling = __normalVector.dotProduct(__cameraVector) < 0;
  429. }
  430. private function applyFlatShading(scene:Scene3D):void {
  431. __normalVector.normalize();
  432. InternalUtils.setFlatShading(this, __normalVector, scene.ambientLightVectorNormalized, scene.ambientLightIntensity, alpha);
  433. __flatShading = true;
  434. }
  435. private function removeFlatShading():void {
  436. transform.colorTransform = new ColorTransform();
  437. __flatShading = false;
  438. }
  439. private function sortChildren():void {
  440. var child:IObject3D, sort:Array = [];
  441. var num:int = numChildren;
  442. for (var i:int = 0;i < num; i++) {
  443. child = getChildAt(i) as IObject3D;
  444. sort.push({child:child, z:child.concatenatedMatrix.position.z});
  445. }
  446. sort.sortOn("z", Array.DESCENDING | Array.NUMERIC);
  447. for (i = 0;i < num; i++) setChildIndex(sort[i]["child"], i);
  448. }
  449. //----------------------------------------------------------------------------------------------------
  450. // Errors
  451. //----------------------------------------------------------------------------------------------------
  452. /**
  453. * @private
  454. */
  455. override public function get height():Number {
  456. throw new Error("The Sprite3D class does not implement this property or method.");
  457. }
  458. /**
  459. * @private
  460. */
  461. override public function set height(value:Number):void {
  462. throw new Error("The Sprite3D class does not implement this property or method.");
  463. }
  464. /**
  465. * @private
  466. */
  467. override public function get rotation():Number {
  468. throw new Error("The Sprite3D class does not implement this property or method.");
  469. }
  470. /**
  471. * @private
  472. */
  473. override public function set rotation(value:Number):void {
  474. throw new Error("The Sprite3D class does not implement this property or method.");
  475. }
  476. /**
  477. * @private
  478. */
  479. override public function get scale9Grid():Rectangle {
  480. throw new Error("The Sprite3D class does not implement this property or method.");
  481. }
  482. /**
  483. * @private
  484. */
  485. override public function set scale9Grid(value:Rectangle):void {
  486. throw new Error("The Sprite3D class does not implement this property or method.");
  487. }
  488. /**
  489. * @private
  490. */
  491. override public function get scrollRect():Rectangle {
  492. throw new Error("The Sprite3D class does not implement this property or method.");
  493. }
  494. /**
  495. * @private
  496. */
  497. override public function set scrollRect(value:Rectangle):void {
  498. throw new Error("The Sprite3D class does not implement this property or method.");
  499. }
  500. /**
  501. * @private
  502. */
  503. override public function get width():Number {
  504. throw new Error("The Sprite3D class does not implement this property or method.");
  505. }
  506. /**
  507. * @private
  508. */
  509. override public function set width(value:Number):void {
  510. throw new Error("The Sprite3D class does not implement this property or method.");
  511. }
  512. /**
  513. * @private
  514. */
  515. override public function globalToLocal(point:Point):Point {
  516. throw new Error("The Sprite3D class does not implement this property or method.");
  517. }
  518. /**
  519. * @private
  520. */
  521. override public function localToGlobal(point:Point):Point {
  522. throw new Error("The Sprite3D class does not implement this property or method.");
  523. }
  524. /**
  525. * @private
  526. */
  527. override public function get dropTarget():DisplayObject {
  528. throw new Error("The Sprite3D class does not implement this property or method.");
  529. }
  530. /**
  531. * @private
  532. */
  533. override public function get graphics():Graphics {
  534. throw new Error("The Sprite3D class does not implement this property or method (use \"graphics3D\" instead).");
  535. }
  536. /**
  537. * @private
  538. */
  539. override public function startDrag(lockCenter:Boolean = false, bounds:Rectangle = null):void {
  540. throw new Error("The Sprite3D class does not implement this property or method.");
  541. }
  542. /**
  543. * @private
  544. */
  545. override public function stopDrag():void {
  546. throw new Error("The Sprite3D class does not implement this property or method.");
  547. }
  548. }
  549. }