/as3/tags/1_5/src/org/papervision3d/objects/DisplayObject3D.as

http://papervision3d.googlecode.com/ · ActionScript · 1027 lines · 417 code · 204 blank · 406 comment · 65 complexity · 745f5688a1aba9ab7338f8d89abdbe3a MD5 · raw file

  1. /*
  2. * PAPER ON ERVIS NPAPER ISION PE IS ON PERVI IO APER SI PA
  3. * AP VI ONPA RV IO PA SI PA ER SI NP PE ON AP VI ION AP
  4. * PERVI ON PE VISIO APER IONPA RV IO PA RVIS NP PE IS ONPAPE
  5. * ER NPAPER IS PE ON PE ISIO AP IO PA ER SI NP PER
  6. * RV PA RV SI ERVISI NP ER IO PE VISIO AP VISI PA RV3D
  7. * ______________________________________________________________________
  8. * papervision3d.org • blog.papervision3d.org • osflash.org/papervision3d
  9. */
  10. /*
  11. * Copyright 2006 (c) Carlos Ulloa Matesanz, noventaynueve.com.
  12. *
  13. * Permission is hereby granted, free of charge, to any person
  14. * obtaining a copy of this software and associated documentation
  15. * files (the "Software"), to deal in the Software without
  16. * restriction, including without limitation the rights to use,
  17. * copy, modify, merge, publish, distribute, sublicense, and/or sell
  18. * copies of the Software, and to permit persons to whom the
  19. * Software is furnished to do so, subject to the following
  20. * conditions:
  21. *
  22. * The above copyright notice and this permission notice shall be
  23. * included in all copies or substantial portions of the Software.
  24. *
  25. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  27. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  29. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  30. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  31. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  32. * OTHER DEALINGS IN THE SOFTWARE.
  33. */
  34. // _______________________________________________________________________ DisplayObject3D
  35. package org.papervision3d.objects
  36. {
  37. import com.blitzagency.xray.logger.XrayLog;
  38. import flash.display.Sprite;
  39. import flash.geom.Matrix;
  40. import flash.utils.Dictionary;
  41. import org.papervision3d.Papervision3D;
  42. import org.papervision3d.core.Matrix3D;
  43. import org.papervision3d.core.Number3D;
  44. import org.papervision3d.core.geom.Face3DInstance;
  45. import org.papervision3d.core.proto.CameraObject3D;
  46. import org.papervision3d.core.proto.DisplayObjectContainer3D;
  47. import org.papervision3d.core.proto.GeometryObject3D;
  48. import org.papervision3d.core.proto.MaterialObject3D;
  49. import org.papervision3d.core.proto.SceneObject3D;
  50. import org.papervision3d.materials.MaterialsList;
  51. import org.papervision3d.scenes.InteractiveScene3D;
  52. import org.papervision3d.utils.InteractiveSceneManager;
  53. /**
  54. * The DisplayObject class represents instances of 3D objects that are contained in the scene.
  55. * <p/>
  56. * That includes all objects in the scene, not only those that can be rendered, but also the camera and its target.
  57. * <p/>
  58. * The DisplayObject3D class supports basic functionality like the x, y and z position of an object, as well as rotationX, rotationY, rotationZ, scaleX, scaleY and scaleZ and visible. It also supports more advanced properties of the object such as its transform Matrix3D.
  59. * <p/>
  60. * <p/>
  61. * DisplayObject3D is not an abstract base class; therefore, you can call DisplayObject3D directly. Invoking new DisplayObject() creates a new empty object in 3D space, like when you used createEmptyMovieClip().
  62. *
  63. */
  64. public class DisplayObject3D extends DisplayObjectContainer3D
  65. {
  66. // ___________________________________________________________________ P O S I T I O N
  67. /**
  68. * An Number that sets the X coordinate of a object relative to the scene coordinate system.
  69. */
  70. public function get x():Number
  71. {
  72. return this.transform.n14;
  73. }
  74. public function set x( value:Number ):void
  75. {
  76. this.transform.n14 = value;
  77. }
  78. /**
  79. * An Number that sets the Y coordinate of a object relative to the scene coordinates.
  80. */
  81. public function get y():Number
  82. {
  83. return this.transform.n24;
  84. }
  85. public function set y( value:Number ):void
  86. {
  87. this.transform.n24 = value;
  88. }
  89. /**
  90. * An Number that sets the Z coordinate of a object relative to the scene coordinates.
  91. */
  92. public function get z():Number
  93. {
  94. return this.transform.n34;
  95. }
  96. public function set z( value:Number ):void
  97. {
  98. this.transform.n34 = value;
  99. }
  100. // ___________________________________________________________________ R O T A T I O N
  101. /**
  102. * Specifies the rotation around the X axis from its original orientation.
  103. */
  104. public function get rotationX():Number
  105. {
  106. if( this._rotationDirty ) updateRotation();
  107. return Papervision3D.useDEGREES? -this._rotationX * toDEGREES : -this._rotationX;
  108. }
  109. public function set rotationX( rot:Number ):void
  110. {
  111. this._rotationX = Papervision3D.useDEGREES? -rot * toRADIANS : -rot;
  112. this._transformDirty = true;
  113. }
  114. /**
  115. * Specifies the rotation around the Y axis from its original orientation.
  116. */
  117. public function get rotationY():Number
  118. {
  119. if( this._rotationDirty ) updateRotation();
  120. return Papervision3D.useDEGREES? -this._rotationY * toDEGREES : -this._rotationY;
  121. }
  122. public function set rotationY( rot:Number ):void
  123. {
  124. this._rotationY = Papervision3D.useDEGREES? -rot * toRADIANS : -rot;
  125. this._transformDirty = true;
  126. }
  127. /**
  128. * Specifies the rotation around the Z axis from its original orientation.
  129. */
  130. public function get rotationZ():Number
  131. {
  132. if( this._rotationDirty ) updateRotation();
  133. return Papervision3D.useDEGREES? -this._rotationZ * toDEGREES : -this._rotationZ;
  134. }
  135. public function set rotationZ( rot:Number ):void
  136. {
  137. this._rotationZ = Papervision3D.useDEGREES? -rot * toRADIANS : -rot;
  138. this._transformDirty = true;
  139. }
  140. // Update rotation values
  141. private function updateRotation():void
  142. {
  143. var rot:Number3D = Matrix3D.matrix2euler( this.transform );
  144. this._rotationX = rot.x * toRADIANS;
  145. this._rotationY = rot.y * toRADIANS;
  146. this._rotationZ = rot.z * toRADIANS;
  147. this._rotationDirty = false;
  148. }
  149. // ___________________________________________________________________ S C A L E
  150. /**
  151. * Sets the 3D scale as applied from the registration point of the object.
  152. */
  153. public function get scale():Number
  154. {
  155. if( this._scaleX == this._scaleY && this._scaleX == this._scaleZ )
  156. if( Papervision3D.usePERCENT ) return this._scaleX * 100;
  157. else return this._scaleX;
  158. else return NaN;
  159. }
  160. public function set scale( scale:Number ):void
  161. {
  162. if( Papervision3D.usePERCENT ) scale /= 100;
  163. this._scaleX = this._scaleY = this._scaleZ = scale;
  164. this._transformDirty = true;
  165. }
  166. /**
  167. * Sets the scale along the local X axis as applied from the registration point of the object.
  168. */
  169. public function get scaleX():Number
  170. {
  171. if( Papervision3D.usePERCENT ) return this._scaleX * 100;
  172. else return this._scaleX;
  173. }
  174. public function set scaleX( scale:Number ):void
  175. {
  176. if( Papervision3D.usePERCENT ) this._scaleX = scale / 100;
  177. else this._scaleX = scale;
  178. this._transformDirty = true;
  179. }
  180. /**
  181. * Sets the scale along the local Y axis as applied from the registration point of the object.
  182. */
  183. public function get scaleY():Number
  184. {
  185. if( Papervision3D.usePERCENT ) return this._scaleY * 100;
  186. else return this._scaleY;
  187. }
  188. public function set scaleY( scale:Number ):void
  189. {
  190. if( Papervision3D.usePERCENT ) this._scaleY = scale / 100;
  191. else this._scaleY = scale;
  192. this._transformDirty = true;
  193. }
  194. /**
  195. * Sets the scale along the local Z axis as applied from the registration point of the object.
  196. */
  197. public function get scaleZ():Number
  198. {
  199. if( Papervision3D.usePERCENT ) return this._scaleZ * 100;
  200. else return this._scaleZ;
  201. }
  202. public function set scaleZ( scale:Number ):void
  203. {
  204. if( Papervision3D.usePERCENT ) this._scaleZ = scale / 100;
  205. else this._scaleZ = scale;
  206. this._transformDirty = true;
  207. }
  208. /**
  209. * Whether or not the display object is visible.
  210. * <p/>
  211. * A Boolean value that indicates whether the object is projected, transformed and rendered. A value of false will effectively ignore the object. The default value is true.
  212. */
  213. public var visible :Boolean;
  214. /**
  215. * An optional object name.
  216. */
  217. public var name :String;
  218. /**
  219. * [read-only] Unique id of this instance.
  220. */
  221. public var id :int;
  222. /**
  223. * An object that contains user defined properties.
  224. * <p/>
  225. * All properties of the extra field are copied into the new instance. The properties specified with extra are publicly available.
  226. */
  227. public var extra :Object // = {}; TBD
  228. /**
  229. * The Sprite that you draw into when rendering in a MovieScene3D.
  230. *
  231. * While Scene3D uses a single Sprite container for all the objects, MovieScene3D renders each object in its own unique Sprite.
  232. *
  233. * You can use the container like any other Sprite. For example, you can add events to it, apply filters or change the blend mode.
  234. */
  235. public var container :Sprite;
  236. /**
  237. * The default material for the object instance. Materials collect data about how objects appear when rendered.
  238. */
  239. public var material :MaterialObject3D;
  240. /**
  241. * The list of materials for this instance.
  242. */
  243. public var materials :MaterialsList;
  244. /**
  245. * If an InteractiveScene3D is used, this will DisplayObject3D will be registered with the InteractiveSceneManager
  246. */
  247. public var interactiveSceneManager:InteractiveSceneManager;
  248. /**
  249. * The scene where the object belongs.
  250. */
  251. protected var _scene :SceneObject3D = null;
  252. public function set scene(p_scene:SceneObject3D):void
  253. {
  254. // set scene property
  255. _scene = p_scene;
  256. for each( var child:DisplayObject3D in this._childrenByName )
  257. {
  258. if(child.scene == null) child.scene = _scene;
  259. }
  260. // if this is NOT an interactiveScene3D, just return
  261. if(_scene is InteractiveScene3D == false) return;
  262. // if we have an InteractiveScene3D, register this and the children to add them to the InteractiveSceneManager
  263. interactiveSceneManager = InteractiveScene3D(_scene).interactiveSceneManager;
  264. }
  265. public function get scene():SceneObject3D { return _scene; }
  266. /**
  267. * [read-only] Indicates the DisplayObjectContainer3D object that contains this display object.
  268. */
  269. public var parent :DisplayObjectContainer3D;
  270. /**
  271. * tells Mesh3D's render() method to sort by measuring from the center of a triangle
  272. */
  273. public static const MESH_SORT_CENTER:uint = 1;
  274. /**
  275. * tells Mesh3D's render() method to sort by measuring from the farthest point of a triangle
  276. */
  277. public static const MESH_SORT_FAR:uint = 2;
  278. /**
  279. * tells Mesh3D's render() method to sort by measuring from the closest point of a triangle
  280. */
  281. public static const MESH_SORT_CLOSE:uint = 3;
  282. /**
  283. * tells Mesh3D's render() method to compare the measurement choice of the user for a triangle's sorting
  284. */
  285. public var meshSort:uint = MESH_SORT_CENTER;
  286. /**
  287. * Returns an empty DiplayObject3D object positioned in the center of the 3D coordinate system (0, 0 ,0).
  288. */
  289. static public function get ZERO():DisplayObject3D
  290. {
  291. return new DisplayObject3D();
  292. }
  293. /**
  294. * Relative directions.
  295. */
  296. static private var FORWARD :Number3D = new Number3D( 0, 0, 1 );
  297. static private var BACKWARD :Number3D = new Number3D( 0, 0, -1 );
  298. static private var LEFT :Number3D = new Number3D( -1, 0, 0 );
  299. static private var RIGHT :Number3D = new Number3D( 1, 0, 0 );
  300. static private var UP :Number3D = new Number3D( 0, 1, 0 );
  301. static private var DOWN :Number3D = new Number3D( 0, -1, 0 );
  302. /**
  303. * A Matrix3D object containing values that affect the scaling, rotation, and translation of the display object.
  304. */
  305. public var transform :Matrix3D;
  306. /**
  307. * [internal-use] A camera transformed Matrix3D object.
  308. */
  309. public var view :Matrix3D;
  310. /**
  311. * [internal-use]
  312. */
  313. public var faces :Array = new Array();
  314. /**
  315. * The GeometryObject3D object that contains the 3D definition of this instance.
  316. * <p/>
  317. * When different objects share the same geometry, they become instances. They are the same object, displayed multiple times. Changing the shape of this object changes the shape of all of its instances.
  318. * <p/>
  319. * Instancing an object saves system memory, and is useful to display an object multiple times while maintaining its shape.
  320. * <p/>
  321. * For example, you could create armies and forests full of duplicate objects without needing the memory to handle that much actual geometry. Each instance has its own transform node so it can have its own position, rotation, and scaling.
  322. */
  323. public var geometry :GeometryObject3D;
  324. /**
  325. * [internal-use] The depth (z coordinate) of the transformed object's center. Also known as the distance from the camera. Used internally for z-sorting.
  326. */
  327. public var screenZ :Number;
  328. // ___________________________________________________________________________________________________
  329. // N E W
  330. // NN NN EEEEEE WW WW
  331. // NNN NN EE WW WW WW
  332. // NNNNNN EEEE WWWWWWWW
  333. // NN NNN EE WWW WWW
  334. // NN NN EEEEEE WW WW
  335. /**
  336. * Creates a new DisplayObject3D instance. After creating the instance, call the addChild() method of a DisplayObjectContainer3D.
  337. *
  338. * @param name [optional] - The name of the newly created object.
  339. * @param geometry [optional] - The geometry of the newly created object.
  340. * @param initObject [optional] - An object that contains user defined properties with which to populate the newly created DisplayObject3D.
  341. *
  342. * <ul>
  343. * <li><b>x</b></b>: An Number that sets the X coordinate of a object relative to the scene coordinate system.</li>
  344. * <p/>
  345. * <li><b>y</b>: An Number that sets the Y coordinate of a object relative to the scene coordinate system.</li>
  346. * <p/>
  347. * <li><b>z</b>: An Number that sets the Z coordinate of a object relative to the scene coordinate system.</li>
  348. * <p/>
  349. * <li><b>rotationX</b>: Specifies the rotation around the X axis from its original orientation.</li>
  350. * <p/>
  351. * <li><b>rotationY</b>: Specifies the rotation around the Y axis from its original orientation.</li>
  352. * <p/>
  353. * <li><b>rotationZ</b>: Specifies the rotation around the Z axis from its original orientation.</li>
  354. * <p/>
  355. * <li><b>scaleX</b>: Sets the scale along the local X axis as applied from the registration point of the object.</li>
  356. * <p/>
  357. * <li><b>scaleY</b>: Sets the scale along the local Y axis as applied from the registration point of the object.</li>
  358. * <p/>
  359. * <li><b>scaleZ</b>: Sets the scale along the local Z axis as applied from the registration point of the object.</li>
  360. * <p/>
  361. * <li><b>visible</b>: Whether or not the display object is visible.
  362. * <p/>
  363. * A Boolean value that indicates whether the object is projected, transformed and rendered. A value of false will effectively ignore the object. The default value is true.</li>
  364. * <p/>
  365. * <li><b>container</b>: The MovieClip that you draw into when rendering. Use only when the object is rendered in its own unique MovieClip.
  366. * <p/>
  367. * It's Boolean value determines whether the container MovieClip should be cleared before rendering.</li>
  368. * <p/>
  369. * <li><b>extra</b>: An object that contains user defined properties.
  370. * <p/>
  371. * All properties of the extra field are copied into the new instance. The properties specified with extra are publicly available.</li>
  372. * </ul>
  373. */
  374. public function DisplayObject3D( name:String=null, geometry:GeometryObject3D=null, initObject:Object=null ):void
  375. {
  376. super();
  377. Papervision3D.log( "DisplayObject3D: " + name );
  378. this.transform = Matrix3D.IDENTITY;
  379. this.view = Matrix3D.IDENTITY;
  380. // TODO if( initObject )...
  381. this.x = initObject? initObject.x || 0 : 0;
  382. this.y = initObject? initObject.y || 0 : 0;
  383. this.z = initObject? initObject.z || 0 : 0;
  384. rotationX = initObject? initObject.rotationX || 0 : 0;
  385. rotationY = initObject? initObject.rotationY || 0 : 0;
  386. rotationZ = initObject? initObject.rotationZ || 0 : 0;
  387. var scaleDefault:Number = Papervision3D.usePERCENT? 100 : 1;
  388. scaleX = initObject? initObject.scaleX || scaleDefault : scaleDefault;
  389. scaleY = initObject? initObject.scaleY || scaleDefault : scaleDefault;
  390. scaleZ = initObject? initObject.scaleZ || scaleDefault : scaleDefault;
  391. if( initObject && initObject.extra ) this.extra = initObject.extra;
  392. if( initObject && initObject.container ) this.container = initObject.container;
  393. this.visible = true;
  394. this.id = _totalDisplayObjects++;
  395. this.name = name || String( this.id );
  396. if( geometry ) addGeometry( geometry );
  397. }
  398. // ___________________________________________________________________________________________________
  399. // U T I L S
  400. /**
  401. * Adds a child DisplayObject3D instance to this DisplayObjectContainer instance.
  402. *
  403. * [TODO: If you add a child object that already has a different display object container as a parent, the object is removed from the child list of the other display object container.]
  404. *
  405. * @param child The DisplayObject3D instance to add as a child of this DisplayObjectContainer3D instance.
  406. * @param name An optional name of the child to add or create. If no name is provided, the child name will be used.
  407. * @return The DisplayObject3D instance that you have added or created.
  408. */
  409. public override function addChild( child :DisplayObject3D, name:String=null ):DisplayObject3D
  410. {
  411. child = super.addChild( child, name );
  412. if( child.scene == null ) child.scene = scene;
  413. return child;
  414. }
  415. /**
  416. * Adds a geometry definition to the instance.
  417. *
  418. * A geometry describes the visual shape and appearance of an object in a scene.
  419. *
  420. * @param geometry A geometry definition.
  421. */
  422. public function addGeometry( geometry:GeometryObject3D=null ):void
  423. {
  424. if( geometry )
  425. this.geometry = geometry;
  426. /*
  427. if( geometry.material )
  428. this.material = geometry.material.clone();
  429. if( geometry.materials )
  430. this.materials = geometry.materials.clone();
  431. */
  432. }
  433. // ___________________________________________________________________________________________________
  434. // C O L L I S I O N
  435. /**
  436. * Gets the distance to the position of the given object.
  437. *
  438. * @param obj The display object to measure the distance to.
  439. * @return The distance to the registration point of the given object.
  440. */
  441. public function distanceTo( obj:DisplayObject3D ):Number
  442. {
  443. var x :Number = this.x - obj.x;
  444. var y :Number = this.y - obj.y;
  445. var z :Number = this.z - obj.z;
  446. return Math.sqrt( x*x + y*y + z*z );
  447. }
  448. /**
  449. * Evaluates the display object to see if it overlaps or intersects with the point specified by the x, y and z parameters.
  450. * <p/>
  451. * The x, y and z parameters specify a point in the coordinate space of the instance parent object, not the scene (unless that parent object is the scene).
  452. *
  453. * @param x The x coordinate to test against this object.
  454. * @param y The y coordinate to test against this object.
  455. * @param z The z coordinate to test against this object.
  456. * @return true if the display object overlaps or intersects with the specified point; false otherwise.
  457. */
  458. public function hitTestPoint( x:Number, y:Number, z:Number ):Boolean
  459. {
  460. var dx :Number = this.x - x;
  461. var dy :Number = this.y - y;
  462. var dz :Number = this.z - z;
  463. var d2 :Number = x*x + y*y + z*z;
  464. var sA :Number = this.geometry? this.geometry.boundingSphere2 : 0;
  465. return sA > d2;
  466. }
  467. /**
  468. * Evaluates the display object to see if it overlaps or intersects with the obj display object.
  469. *
  470. * @param obj The display object to test against.
  471. * @return true if the display objects intersect; false if not.
  472. */
  473. // TODO: Use group boundingSphere
  474. public function hitTestObject( obj:DisplayObject3D, multiplier:Number=1 ):Boolean
  475. {
  476. var dx :Number = this.x - obj.x;
  477. var dy :Number = this.y - obj.y;
  478. var dz :Number = this.z - obj.z;
  479. var d2 :Number = dx*dx + dy*dy + dz*dz;
  480. var sA :Number = this.geometry? this.geometry.boundingSphere2 : 0;
  481. var sB :Number = obj.geometry? obj.geometry.boundingSphere2 : 0;
  482. sA = sA * multiplier;
  483. return sA + sB > d2;
  484. }
  485. // ___________________________________________________________________________________________________
  486. // M A T E R I A L S
  487. /**
  488. * Returns the material that exists with the specified name in the materials list.
  489. * </p>
  490. * If more that one material object has the specified name, the method returns the first material object in the materials list.
  491. * </p>
  492. * @param name The name of the material to return.
  493. * @return The material object with the specified name.
  494. */
  495. // TODO: Recursive
  496. public function getMaterialByName( name:String ):MaterialObject3D
  497. {
  498. var material:MaterialObject3D = this.materials.getMaterialByName( name );
  499. if( material )
  500. return material;
  501. else
  502. for each( var child :DisplayObject3D in this._childrenByName )
  503. {
  504. material = child.getMaterialByName( name );
  505. if( material ) return material;
  506. }
  507. return null;
  508. }
  509. /**
  510. * Returns a string value with the list of material names of the materials list.
  511. *
  512. * @return A string.
  513. */
  514. // TODO: Recursive
  515. public function materialsList():String
  516. {
  517. var list:String = "";
  518. for( var name:String in this.materials )
  519. list += name + "\n";
  520. for each( var child :DisplayObject3D in this._childrenByName )
  521. {
  522. for( name in child.materials.materialsByName )
  523. list += "+ " + name + "\n";
  524. }
  525. return list;
  526. }
  527. // ___________________________________________________________________________________________________
  528. // P R O J E C T
  529. // PPPPP RRRRR OOOO JJ EEEEEE CCCC TTTTTT
  530. // PP PP RR RR OO OO JJ EE CC CC TT
  531. // PPPPP RRRRR OO OO JJ EEEE CC TT
  532. // PP RR RR OO OO JJ JJ EE CC CC TT
  533. // PP RR RR OOOO JJJJ EEEEEE CCCC TT
  534. /**
  535. * [internal-use] Projects three dimensional coordinates onto a two dimensional plane to simulate the relationship of the camera to subject.
  536. * <p/>
  537. * This is the first step in the process of representing three dimensional shapes two dimensionally.
  538. *
  539. * @param parent The DisplayObject3D object that contains this display object.
  540. * @param camera Camera3D object to render from.
  541. * @param sorted The list of faces of the current sort branch.
  542. */
  543. public function project( parent :DisplayObject3D, camera :CameraObject3D, sorted :Array=null ):Number
  544. {
  545. if( ! sorted ) this._sorted = sorted = new Array();
  546. if( this._transformDirty ) updateTransform();
  547. this.view.calculateMultiply( parent.view, this.transform ); // TODO: OPTIMIZE (MED) Inline this
  548. var screenZs :Number = 0;
  549. var children :Number = 0;
  550. for each( var child:DisplayObject3D in this._childrenByName )
  551. {
  552. if( child.visible )
  553. {
  554. screenZs += child.project( this, camera, sorted );
  555. children++;
  556. }
  557. }
  558. return this.screenZ = screenZs / children;
  559. }
  560. // ___________________________________________________________________________________________________
  561. // R E N D E R
  562. // RRRRR EEEEEE NN NN DDDDD EEEEEE RRRRR
  563. // RR RR EE NNN NN DD DD EE RR RR
  564. // RRRRR EEEE NNNNNN DD DD EEEE RRRRR
  565. // RR RR EE NN NNN DD DD EE RR RR
  566. // RR RR EEEEEE NN NN DDDDD EEEEEE RR RR
  567. /**
  568. * [internal-use] Render the projected object.
  569. *
  570. * @param scene The scene where the object belongs.
  571. */
  572. public function render( scene :SceneObject3D ):void
  573. {
  574. var iFaces :Array = this._sorted;
  575. iFaces.sortOn( 'screenZ', Array.DESCENDING | Array.NUMERIC );
  576. // Render
  577. var container :Sprite = this.container || scene.container;
  578. var rendered :Number = 0;
  579. var iFace :Face3DInstance;
  580. for( var i:int = 0; iFace = iFaces[i]; i++ )
  581. {
  582. if( iFace.visible )
  583. rendered += iFace.face.render( iFace.instance, container );
  584. }
  585. // Update stats
  586. scene.stats.rendered += rendered;
  587. }
  588. // ___________________________________________________________________________________________________
  589. // L O C A L T R A N S F O R M S
  590. // LL OOOO CCCC AA LL
  591. // LL OO OO CC CC AAAA LL
  592. // LL OO OO CC AA AA LL
  593. // LL OO OO CC CC AAAAAA LL
  594. // LLLLLL OOOO CCCC AA AA LLLLLL
  595. /**
  596. * Translate the display object in the direction it is facing, i.e. it's positive Z axis.
  597. *
  598. * @param distance The distance that the object should move forward.
  599. */
  600. public function moveForward ( distance:Number ):void { translate( distance, FORWARD ); }
  601. /**
  602. * Translate the display object in the opposite direction it is facing, i.e. it's negative Z axis.
  603. *
  604. * @param distance The distance that the object should move backward.
  605. */
  606. public function moveBackward ( distance:Number ):void { translate( distance, BACKWARD ); }
  607. /**
  608. * Translate the display object lateraly, to the left of the direction it is facing, i.e. it's negative X axis.
  609. *
  610. * @param distance The distance that the object should move left.
  611. */
  612. public function moveLeft ( distance:Number ):void { translate( distance, LEFT ); }
  613. /**
  614. * Translate the display object lateraly, to the right of the direction it is facing, i.e. it's positive X axis.
  615. *
  616. * @param distance The distance that the object should move right.
  617. */
  618. public function moveRight ( distance:Number ):void { translate( distance, RIGHT ); }
  619. /**
  620. * Translate the display object upwards, with respect to the direction it is facing, i.e. it's positive Y axis.
  621. *
  622. * @param distance The distance that the object should move up.
  623. */
  624. public function moveUp ( distance:Number ):void { translate( distance, UP ); }
  625. /**
  626. * Translate the display object downwards, with respect to the direction it is facing, i.e. it's negative Y axis.
  627. *
  628. * @param distance The distance that the object should move down.
  629. */
  630. public function moveDown ( distance:Number ):void { translate( distance, DOWN ); }
  631. // ___________________________________________________________________________________________________
  632. // L O C A L T R A N S L A T I O N
  633. /**
  634. * Move the object along a given direction.
  635. *
  636. * @param distance The distance that the object should travel.
  637. * @param axis The direction that the object should move towards.
  638. */
  639. public function translate( distance:Number, axis:Number3D ):void
  640. {
  641. var vector:Number3D = axis.clone();
  642. if( this._transformDirty ) updateTransform();
  643. Matrix3D.rotateAxis( transform, vector )
  644. this.x += distance * vector.x;
  645. this.y += distance * vector.y;
  646. this.z += distance * vector.z;
  647. }
  648. // ___________________________________________________________________________________________________
  649. // L O C A L R O T A T I O N
  650. /**
  651. * Rotate the display object around its lateral or transverse axis —an axis running from the pilot's left to right in piloted aircraft, and parallel to the wings of a winged aircraft; thus the nose pitches up and the tail down, or vice-versa.
  652. *
  653. * @param angle The angle to rotate.
  654. */
  655. public function pitch( angle:Number ):void
  656. {
  657. angle = Papervision3D.useDEGREES? angle * toRADIANS : angle;
  658. var vector:Number3D = RIGHT.clone();
  659. if( this._transformDirty ) updateTransform();
  660. Matrix3D.rotateAxis( transform, vector );
  661. var m:Matrix3D = Matrix3D.rotationMatrix( vector.x, vector.y, vector.z, angle );
  662. // this.transform.copy3x3( Matrix3D.multiply3x3( m ,transform ) );
  663. this.transform.calculateMultiply3x3( m ,transform );
  664. this._rotationDirty = true;
  665. }
  666. /**
  667. * Rotate the display object around about the vertical axis —an axis drawn from top to bottom.
  668. *
  669. * @param angle The angle to rotate.
  670. */
  671. public function yaw( angle:Number ):void
  672. {
  673. angle = Papervision3D.useDEGREES? angle * toRADIANS : angle;
  674. var vector:Number3D = UP.clone();
  675. if( this._transformDirty ) updateTransform();
  676. Matrix3D.rotateAxis( transform, vector );
  677. var m:Matrix3D = Matrix3D.rotationMatrix( vector.x, vector.y, vector.z, angle );
  678. this.transform.calculateMultiply3x3( m ,transform );
  679. this._rotationDirty = true;
  680. }
  681. /**
  682. * Rotate the display object around the longitudinal axis —an axis drawn through the body of the vehicle from tail to nose in the normal direction of flight, or the direction the object is facing.
  683. *
  684. * @param angle
  685. */
  686. public function roll( angle:Number ):void
  687. {
  688. angle = Papervision3D.useDEGREES? angle * toRADIANS : angle;
  689. var vector:Number3D = FORWARD.clone();
  690. if( this._transformDirty ) updateTransform();
  691. Matrix3D.rotateAxis( transform, vector );
  692. var m:Matrix3D = Matrix3D.rotationMatrix( vector.x, vector.y, vector.z, angle );
  693. this.transform.calculateMultiply3x3( m ,transform );
  694. this._rotationDirty = true;
  695. }
  696. /**
  697. * Make the object look at a specific position.
  698. *
  699. * @param targetObject Object to look at.
  700. * @param upAxis The vertical axis of the universe. Normally the positive Y axis.
  701. */
  702. public function lookAt( targetObject:DisplayObject3D, upAxis:Number3D=null ):void
  703. {
  704. var position :Number3D = new Number3D( this.x, this.y, this.z );
  705. var target :Number3D = new Number3D( targetObject.x, targetObject.y, targetObject.z );
  706. var zAxis :Number3D = Number3D.sub( target, position );
  707. zAxis.normalize();
  708. if( zAxis.modulo > 0.1 )
  709. {
  710. var xAxis :Number3D = Number3D.cross( zAxis, upAxis || UP );
  711. xAxis.normalize();
  712. var yAxis :Number3D = Number3D.cross( zAxis, xAxis );
  713. yAxis.normalize();
  714. var look :Matrix3D = this.transform;
  715. look.n11 = xAxis.x;
  716. look.n21 = xAxis.y;
  717. look.n31 = xAxis.z;
  718. look.n12 = -yAxis.x;
  719. look.n22 = -yAxis.y;
  720. look.n32 = -yAxis.z;
  721. look.n13 = zAxis.x;
  722. look.n23 = zAxis.y;
  723. look.n33 = zAxis.z;
  724. this._transformDirty = false;
  725. this._rotationDirty = true;
  726. // TODO: Implement scale
  727. }
  728. else
  729. {
  730. var log:XrayLog = new XrayLog();
  731. log.debug( "lookAt Error" );
  732. }
  733. }
  734. // ___________________________________________________________________________________________________
  735. // T R A N S F O R M
  736. // TTTTTT RRRRR AA NN NN SSSSS FFFFFF OOOO RRRRR MM MM
  737. // TT RR RR AAAA NNN NN SS FF OO OO RR RR MMM MMM
  738. // TT RRRRR AA AA NNNNNN SSSS FFFF OO OO RRRRR MMMMMMM
  739. // TT RR RR AAAAAA NN NNN SS FF OO OO RR RR MM M MM
  740. // TT RR RR AA AA NN NN SSSSS FF OOOO RR RR MM MM
  741. /**
  742. * Copies the position information (x, y and z coordinates) from another object or Matrix3D.
  743. *
  744. * @param reference A DisplayObject3D or Matrix3D object to copy the position from.
  745. */
  746. public function copyPosition( reference:* ):void
  747. {
  748. var trans :Matrix3D = this.transform;
  749. var matrix :Matrix3D = (reference is DisplayObject3D)? reference.transform : reference;
  750. trans.n14 = matrix.n14;
  751. trans.n24 = matrix.n24;
  752. trans.n34 = matrix.n34;
  753. }
  754. /**
  755. * Copies the transformation information (position, rotation and scale) from another object or Matrix3D.
  756. *
  757. * @param reference A DisplayObject3D or Matrix3D object to copy the position from.
  758. */
  759. public function copyTransform( reference:* ):void
  760. {
  761. var trans :Matrix3D = this.transform;
  762. var matrix :Matrix3D = (reference is DisplayObject3D)? reference.transform : reference;
  763. trans.n11 = matrix.n11; trans.n12 = matrix.n12;
  764. trans.n13 = matrix.n13; trans.n14 = matrix.n14;
  765. trans.n21 = matrix.n21; trans.n22 = matrix.n22;
  766. trans.n23 = matrix.n23; trans.n24 = matrix.n24;
  767. trans.n31 = matrix.n31; trans.n32 = matrix.n32;
  768. trans.n33 = matrix.n33; trans.n34 = matrix.n34;
  769. this._transformDirty = false;
  770. this._rotationDirty = true;
  771. }
  772. /**
  773. * [internal-use] Updates the transform Matrix3D with the current rotation and scale values.
  774. */
  775. // TODO OPTIMIZE (HIGH)
  776. protected function updateTransform():void
  777. {
  778. var q:Object = Matrix3D.euler2quaternion( -this._rotationY, -this._rotationZ, this._rotationX ); // Swapped
  779. var m:Matrix3D = Matrix3D.quaternion2matrix( q.x, q.y, q.z, q.w );
  780. var transform:Matrix3D = this.transform;
  781. m.n14 = transform.n14;
  782. m.n24 = transform.n24;
  783. m.n34 = transform.n34;
  784. transform.copy( m );
  785. // Scale
  786. var scaleM:Matrix3D = Matrix3D.IDENTITY;
  787. scaleM.n11 = this._scaleX;
  788. scaleM.n22 = this._scaleY;
  789. scaleM.n33 = this._scaleZ;
  790. this.transform.calculateMultiply( transform, scaleM );
  791. this._transformDirty = false;
  792. }
  793. // ___________________________________________________________________________________________________
  794. /**
  795. * Returns a string value representing the three-dimensional position values of the display object instance.
  796. *
  797. * @return A string.
  798. */
  799. public override function toString(): String
  800. {
  801. return this.name + ': x:' + Math.round(this.x) + ' y:' + Math.round(this.y) + ' z:' + Math.round(this.z);
  802. }
  803. // ___________________________________________________________________________________________________
  804. // P R I V A T E
  805. /**
  806. * [internal-use]
  807. */
  808. protected var _transformDirty :Boolean = false;
  809. private var _rotationX :Number;
  810. private var _rotationY :Number;
  811. private var _rotationZ :Number;
  812. private var _rotationDirty :Boolean = false;
  813. private var _scaleX :Number;
  814. private var _scaleY :Number;
  815. private var _scaleZ :Number;
  816. private var _scaleDirty :Boolean = false;
  817. protected var _sorted :Array;
  818. static private var _totalDisplayObjects :int = 0;
  819. static private var toDEGREES :Number = 180/Math.PI;
  820. static private var toRADIANS :Number = Math.PI/180;
  821. }
  822. }