PageRenderTime 4495ms CodeModel.GetById 28ms RepoModel.GetById 5ms app.codeStats 0ms

/sandy/as3/branches/3.0.1/src/sandy/core/data/Polygon.as

http://sandy.googlecode.com/
ActionScript | 764 lines | 396 code | 81 blank | 287 comment | 42 complexity | 55a8d93bf658a97137d0b71bbb60574c MD5 | raw file
  1. /*
  2. # ***** BEGIN LICENSE BLOCK *****
  3. Copyright the original author Thomas PFEIFFER
  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.data
  16. {
  17. import flash.display.Sprite;
  18. import flash.events.Event;
  19. import flash.events.MouseEvent;
  20. import flash.geom.Point;
  21. import flash.geom.Rectangle;
  22. import flash.utils.Dictionary;
  23. import sandy.core.Scene3D;
  24. import sandy.core.interaction.VirtualMouse;
  25. import sandy.core.scenegraph.Geometry3D;
  26. import sandy.core.scenegraph.IDisplayable;
  27. import sandy.core.scenegraph.Shape3D;
  28. import sandy.events.BubbleEvent;
  29. import sandy.events.BubbleEventBroadcaster;
  30. import sandy.materials.Appearance;
  31. import sandy.math.IntersectionMath;
  32. import sandy.math.Matrix4Math;
  33. import sandy.math.VectorMath;
  34. import sandy.util.NumberUtil;
  35. import sandy.view.Frustum;
  36. import flash.events.KeyboardEvent;
  37. /**
  38. * Polygon's are the building blocks of visible 3D shapes.
  39. *
  40. * @author Thomas Pfeiffer - kiroukou
  41. * @author Mirek Mencel
  42. * @since 1.0
  43. * @version 3.0
  44. * @date 24.08.2007
  45. */
  46. public final class Polygon implements IDisplayable
  47. {
  48. // _______
  49. // STATICS_______________________________________________________
  50. private static var _ID_:uint = 0;
  51. /**
  52. * This property lists all the polygons.
  53. * This is an helping property since it allows to retrieve a polygon instance from its unique ID.
  54. * Polygon objects have an unique ID with myPolygon.id.
  55. * Using : Polygon.POLYGON_MAP[myPolygon.id] returns myPolygon (for sure this example has no interesst except showing the use of the property.
  56. */
  57. public static var POLYGON_MAP:Dictionary = new Dictionary(true);
  58. // ______
  59. // PUBLIC________________________________________________________
  60. /**
  61. * [READ-ONLY] property
  62. * Unique polygon ID Number.
  63. */
  64. public const id:uint = _ID_++;
  65. /**
  66. * [READ-ONLY] property.
  67. * Link to the Shape3D instance this polygon is related too.
  68. */
  69. public var shape:Shape3D;
  70. /**
  71. * [READ-ONLY] property.
  72. * Refers to the Scene3D the shape is linked to.
  73. */
  74. public var scene:Scene3D;
  75. /**
  76. * [READ-ONLY] property.
  77. * Specify if the polygon has been clipped
  78. */
  79. public var isClipped:Boolean = false;
  80. /**
  81. * [READ-ONLY] property.
  82. * Array of clipped vertices. Check isClipped property first to see if this array shall be containing the useful data or not.
  83. */
  84. public var cvertices:Array;
  85. /**
  86. * [READ-ONLY] property.
  87. * Array of original vertices.
  88. */
  89. public var vertices:Array;
  90. /**
  91. * [READ-ONLY] property.
  92. */
  93. public var vertexNormals:Array;
  94. /**
  95. * [READ-ONLY] property.
  96. */
  97. public var normal:Vertex;
  98. /**
  99. * [READ-ONLY] property.
  100. */
  101. public var aUVCoord:Array;
  102. /**
  103. * [READ-ONLY] property.
  104. */
  105. public var aEdges:Array;
  106. /**
  107. * [READ-ONLY] property.
  108. */
  109. public var caUVCoord:Array;
  110. /**
  111. * [READ-ONLY] property.
  112. * This property contains the texture bounds as a Rectangle.
  113. */
  114. public var uvBounds:Rectangle;
  115. /**
  116. * [READ-ONLY] property
  117. * Array of polygons that share an edge with the current polygon.
  118. */
  119. public var aNeighboors:Array = new Array();
  120. /**
  121. * [READ-ONLY] property.
  122. * Min values of this polygon
  123. */
  124. public var minBounds:Vector = new Vector();
  125. /**
  126. * [READ-ONLY] property.
  127. * Max values of this polygon
  128. */
  129. public var maxBounds:Vector = new Vector();
  130. /**
  131. * [READ-ONLY] property.
  132. * Mean values of this polygon
  133. */
  134. public var meanBounds:Vector = new Vector();
  135. /**
  136. * Creates a new polygon.
  137. *
  138. * @param p_oShape The shape this polygon belongs to
  139. * @param p_geometry The geometry this polygon is part of
  140. * @param p_aVertexID The vertexID array of this polygon
  141. * @param p_aUVCoordsID The UVCoordsID array of this polygon
  142. * @param p_nFaceNormalID The faceNormalID of this polygon
  143. * @param p_nEdgesID The edgesID of this polygon
  144. */
  145. public function Polygon( p_oOwner:Shape3D, p_geometry:Geometry3D, p_aVertexID:Array, p_aUVCoordsID:Array=null, p_nFaceNormalID:Number=0, p_nEdgesID:uint=0 )
  146. {
  147. shape = p_oOwner;
  148. m_oGeometry = p_geometry;
  149. // --
  150. __update( p_aVertexID, p_aUVCoordsID, p_nFaceNormalID, p_nEdgesID );
  151. m_oContainer = new Sprite();
  152. // --
  153. POLYGON_MAP[id] = this;
  154. }
  155. /**
  156. * The broadcaster property.
  157. *
  158. * <p>The broadcaster is the property used to send events to listeners.</p>
  159. */
  160. public function get broadcaster():BubbleEventBroadcaster
  161. {
  162. return m_oEB;
  163. }
  164. /**
  165. * Adds a listener for specifical event.
  166. *
  167. * @param p_sEvent Name of the Event.
  168. * @param oL Listener object.
  169. */
  170. public function addEventListener(p_sEvent:String, oL:*) : void
  171. {
  172. m_oEB.addEventListener.apply(m_oEB, arguments);
  173. }
  174. /**
  175. * Removes a listener for specifical event.
  176. *
  177. * @param p_sEvent Name of the Event.
  178. * @param oL Listener object.
  179. */
  180. public function removeEventListener(p_sEvent:String, oL:*) : void
  181. {
  182. m_oEB.removeEventListener(p_sEvent, oL);
  183. }
  184. /**
  185. * Pre-compute several properties of the polygon in the same time.
  186. * List of the computed properties :
  187. * - visibility : if the polygon is visible
  188. */
  189. public function computeVisibility():void
  190. {
  191. // all normals are refreshed every loop. Face is visible is normal face to the camera
  192. var l_nDot:Number = ( m_oVisibilityRef.wx * normal.wx + m_oVisibilityRef.wy * normal.wy + m_oVisibilityRef.wz * normal.wz );
  193. m_bVisible = ( l_nDot < 0 );
  194. }
  195. /**
  196. * Pre-compute several properties of the polygon in the same time.
  197. * List of the computed properties :
  198. * <ul>
  199. * <li>mean z depth : the mean z depth used for basic sorting</li>
  200. * <li>max bounds : the maximum bounds of the polygon</li>
  201. * <li>min bounds : the minimum bounds of the polygon</li>
  202. * <li>mean bounds : the mean of each components of the polygon. It is center actually.</li>
  203. * </ul>
  204. */
  205. public function precomputeBounds():void
  206. {
  207. const l_aVert:Array = vertices;
  208. // --
  209. meanBounds.reset();
  210. minBounds.resetToPositiveInfinity();
  211. maxBounds.resetToNegativeInfinity();
  212. // --
  213. for each ( var v:Vertex in l_aVert )
  214. {
  215. if( v.wx < minBounds.x ) minBounds.x = v.wx;
  216. else if( v.wx > maxBounds.x ) maxBounds.x = v.wx;
  217. // --
  218. if( v.wy < minBounds.y ) minBounds.y = v.wy;
  219. else if( v.wy > maxBounds.y ) maxBounds.y = v.wy;
  220. // --
  221. if( v.wz < minBounds.z ) minBounds.z = v.wz;
  222. else if( v.wz > maxBounds.z ) maxBounds.z = v.wz;
  223. // --
  224. meanBounds.x += v.wx;
  225. meanBounds.y += v.wy;
  226. meanBounds.z += v.wz;
  227. }
  228. // -- We normalize the sum and return it
  229. meanBounds.scale( 1 / l_aVert.length );
  230. }
  231. /**
  232. * Is this face visible?.
  233. * The method returns the visibility value pre computed after precompute method call. This getter shall be called afer the precompute call.
  234. * @return true if this face is visible, false otherwise.
  235. */
  236. public function get visible(): Boolean
  237. {return m_bVisible;}
  238. /**
  239. * Returns the real 3D position of the 2D screen position.
  240. * The 2D position is usually coming from :
  241. * <listing version="3.0">
  242. * var l_nClicX:Number = m_oScene.container.mouseX;
  243. * var l_nClicY:Number = m_oScene.container.mouseY;
  244. * </listing>
  245. *
  246. * @return the real 3D position which correspond to the intersection onto that polygone
  247. */
  248. public function get3DFrom2D( p_oScreenPoint:Point ):Vector
  249. {
  250. var l_nX:Number = (p_oScreenPoint.x - scene.camera.viewport.width2)/ scene.camera.viewport.width2;
  251. var l_nY:Number = -(p_oScreenPoint.y - scene.camera.viewport.height2)/scene.camera.viewport.height2;
  252. var l_oPoint:Vector = new Vector( l_nX, l_nY, 0 );
  253. // -- on prend la matrice de projection inverse
  254. var l_oMatrix:Matrix4 = scene.camera.invProjectionMatrix;
  255. l_oMatrix.vectorMult( l_oPoint );
  256. l_oMatrix = scene.camera.matrix;
  257. l_oMatrix.vectorMult( l_oPoint );
  258. // -- maintenant nous avons la direction du rayon logiquement.
  259. // -- reste a calculer son intersection avec le polygone
  260. var l_oNormale:Vector = normal.getVector();
  261. var l_oOrigineRayon:Vector = scene.camera.getPosition();
  262. l_oPoint.sub( l_oOrigineRayon );
  263. //on normalise le vecteur car c'est lui qui sert de vecteur directeur du rayon qui part
  264. l_oPoint.normalize();
  265. // on chope la constante du plan
  266. var l_nPlaneConst:Number = VectorMath.dot( (vertices[0] as Vertex).getVector(), l_oNormale );
  267. // Calcul le produit scalaire Normale du plan avec le vecteur directeur du rayon
  268. var l_nDotNormalePlanRayon:Number = l_oNormale.dot( l_oPoint );
  269. // In case the ray is parallel to the plane
  270. if( l_nDotNormalePlanRayon >= -NumberUtil.TOL && l_nDotNormalePlanRayon <= NumberUtil.TOL )
  271. return null;
  272. // distance from ray to plane
  273. var l_nDistRayonPlan:Number = (l_oOrigineRayon.dot( l_oNormale ))/(l_oNormale.getNorm());
  274. // lpane distance
  275. var t:Number = - l_nDistRayonPlan / l_nDotNormalePlanRayon
  276. // No collision
  277. if( t < NumberUtil.TOL )
  278. return null;
  279. // -- intersection point
  280. return new Vector( l_oOrigineRayon.x + t * l_oPoint.x,
  281. l_oOrigineRayon.y + t * l_oPoint.y,
  282. l_oOrigineRayon.z + t * l_oPoint.z );;
  283. }
  284. /**
  285. * Get the UVCoord under the 2D screen position after a mouse click or something
  286. * The 2D position is usually coming from :
  287. * <listing version="3.0">
  288. * var l_nClicX:Number = m_oScene.container.mouseX;
  289. * var l_nClicY:Number = m_oScene.container.mouseY;
  290. * </listing>
  291. *
  292. * @return the UVCoord under the 2D screen point
  293. */
  294. public function getUVFrom2D( p_oScreenPoint:Point ):UVCoord
  295. {
  296. var p0:Point = new Point(vertices[0].sx, vertices[0].sy);
  297. var p1:Point = new Point(vertices[1].sx, vertices[1].sy);
  298. var p2:Point = new Point(vertices[2].sx, vertices[2].sy);
  299. var u0:UVCoord = aUVCoord[0];
  300. var u1:UVCoord = aUVCoord[1];
  301. var u2:UVCoord = aUVCoord[2];
  302. var v01:Point = new Point(p1.x - p0.x, p1.y - p0.y );
  303. var vn01:Point = v01.clone();
  304. vn01.normalize(1);
  305. var v02:Point = new Point(p2.x - p0.x, p2.y - p0.y );
  306. var vn02:Point = v02.clone(); vn02.normalize(1);
  307. // sub that from click point
  308. var v4:Point = new Point( p_oScreenPoint.x - v01.x, p_oScreenPoint.y - v01.y );
  309. // we now have everything to find 1 intersection
  310. var l_oInter:Point = IntersectionMath.intersectionLine2D( p0, p2, p_oScreenPoint, v4 );
  311. // find vectors to intersection
  312. var vi02:Point = new Point( l_oInter.x - p0.x, l_oInter.y - p0.y );
  313. var vi01:Point = new Point( p_oScreenPoint.x - l_oInter.x , p_oScreenPoint.y - l_oInter.y );
  314. // interpolation coeffs
  315. var d1:Number = vi01.length / v01.length ;
  316. var d2:Number = vi02.length / v02.length;
  317. // -- on interpole linéairement pour trouver la position du point dans repere de la texture (normalisé)
  318. return new UVCoord( u0.u + d1*(u1.u - u0.u) + d2*(u2.u - u0.u),
  319. u0.v + d1*(u1.v - u0.v) + d2*(u2.v - u0.v));
  320. }
  321. /**
  322. * Returns an array containing the vertices, clipped by the camera frustum.
  323. *
  324. * @return The array of clipped vertices
  325. */
  326. public function clip( p_oFrustum:Frustum ):Array
  327. {
  328. isClipped = true;
  329. // For lines we only apply front plane clipping
  330. if( vertices.length < 3 )
  331. {
  332. clipFrontPlane( p_oFrustum );
  333. }
  334. else
  335. {
  336. cvertices = null;
  337. caUVCoord = null;
  338. // --
  339. cvertices = vertices.concat();
  340. caUVCoord = aUVCoord.concat();
  341. // --
  342. p_oFrustum.clipFrustum( cvertices, caUVCoord );
  343. }
  344. return cvertices;
  345. }
  346. /**
  347. * Perform a clipping against the near frustum plane.
  348. *
  349. * @return The array of clipped vertices
  350. */
  351. public function clipFrontPlane( p_oFrustum:Frustum ):Array
  352. {
  353. isClipped = true;
  354. cvertices = null;
  355. cvertices = vertices.concat();
  356. // If line
  357. if( vertices.length < 3 )
  358. {
  359. p_oFrustum.clipLineFrontPlane( cvertices );
  360. }
  361. else
  362. {
  363. caUVCoord = null;
  364. caUVCoord = aUVCoord.concat();
  365. p_oFrustum.clipFrontPlane( cvertices, caUVCoord );
  366. }
  367. return cvertices;
  368. }
  369. /**
  370. * Updates the vertices and normals for this polygon.
  371. *
  372. * <p>Calling this method make the polygon gets its vertice and normals by reference
  373. * instead of accessing them by their ID.<br/>
  374. * This method shall be called once the geometry created.</p>
  375. *
  376. * @param p_aVertexID The vertexID array of this polygon
  377. * @param p_aUVCoordsID The UVCoordsID array of this polygon
  378. * @param p_nFaceNormalID The faceNormalID of this polygon
  379. * @param p_nEdgesID The edgesID of this polygon
  380. */
  381. private function __update( p_aVertexID:Array, p_aUVCoordsID:Array, p_nFaceNormalID:uint, p_nEdgeListID:uint ):void
  382. {
  383. var i:int=0, l:int;
  384. // --
  385. vertexNormals = new Array();
  386. vertices = new Array();
  387. for each( var o:* in p_aVertexID )
  388. {
  389. vertices[i] = Vertex( m_oGeometry.aVertex[ p_aVertexID[i] ] );
  390. vertexNormals[i] = m_oGeometry.aVertexNormals[ p_aVertexID[i] ];
  391. i++;
  392. }
  393. // --
  394. m_oVisibilityRef = vertices[0];
  395. // -- every polygon does not have some texture coordinates
  396. if( p_aUVCoordsID )
  397. {
  398. var l_nMinU:Number = Number.POSITIVE_INFINITY, l_nMinV:Number = Number.POSITIVE_INFINITY,
  399. l_nMaxU:Number = Number.NEGATIVE_INFINITY, l_nMaxV:Number = Number.NEGATIVE_INFINITY;
  400. // --
  401. aUVCoord = new Array();
  402. i = 0;
  403. for each( var p:* in p_aUVCoordsID )
  404. {
  405. var l_oUV:UVCoord = UVCoord( m_oGeometry.aUVCoords[ p_aUVCoordsID[i] ] );
  406. aUVCoord[i] = l_oUV;
  407. if( l_oUV.u < l_nMinU ) l_nMinU = l_oUV.u;
  408. else if( l_oUV.u > l_nMaxU ) l_nMaxU = l_oUV.u;
  409. // --
  410. if( l_oUV.v < l_nMinV ) l_nMinV = l_oUV.v;
  411. else if( l_oUV.v > l_nMaxV ) l_nMaxV = l_oUV.v;
  412. // --
  413. i++;
  414. }
  415. // --
  416. uvBounds = new Rectangle( l_nMinU, l_nMinV, l_nMaxU-l_nMinU, l_nMaxV-l_nMinV );
  417. }
  418. // --
  419. normal = Vertex( m_oGeometry.aFacesNormals[ p_nFaceNormalID ] );
  420. // If no normal has been given, we create it ourself.
  421. if( normal == null )
  422. {
  423. var l_oNormal:Vector = createNormal();
  424. var l_nID:Number = m_oGeometry.setFaceNormal( m_oGeometry.getNextFaceNormalID(), l_oNormal.x, l_oNormal.y, l_oNormal.z );
  425. normal = Vertex( m_oGeometry.aFacesNormals[ l_nID ] );
  426. }
  427. // --
  428. aEdges = new Array();
  429. for each( var l_nEdgeId:uint in m_oGeometry.aFaceEdges[p_nEdgeListID] )
  430. {
  431. var l_oEdge:Edge3D = m_oGeometry.aEdges[ l_nEdgeId ];
  432. l_oEdge.vertex1 = m_oGeometry.aVertex[ l_oEdge.vertexId1 ];
  433. l_oEdge.vertex2 = m_oGeometry.aVertex[ l_oEdge.vertexId2 ];
  434. aEdges.push( l_oEdge );
  435. }
  436. }
  437. /**
  438. * Clears the container of this polygon from graphics.
  439. */
  440. public function clear():void
  441. {
  442. m_oContainer.graphics.clear();
  443. }
  444. /**
  445. * Displays this polygon on its container if visible.
  446. *
  447. * @param p_oScene The current scene this polygon is rendered into
  448. * @param p_oContainer The container to draw on
  449. */
  450. public function display( p_oScene:Scene3D, p_oContainer:Sprite = null ):void
  451. {
  452. scene = p_oScene;
  453. // --
  454. const lCont:Sprite = (p_oContainer)?p_oContainer:m_oContainer;
  455. if( m_bVisible )
  456. {
  457. m_oAppearance.frontMaterial.renderPolygon( p_oScene, this, lCont );
  458. }
  459. else
  460. {
  461. m_oAppearance.backMaterial.renderPolygon( p_oScene, this, lCont );
  462. }
  463. }
  464. /**
  465. * The container for this polygon.
  466. */
  467. public function get container():Sprite
  468. {
  469. return m_oContainer;
  470. }
  471. /**
  472. * @private
  473. */
  474. public function get depth():Number
  475. {
  476. return meanBounds.z;
  477. }
  478. /**
  479. * The z depth of this polygon.
  480. */
  481. public function set depth( p_nDepth:Number ):void
  482. {
  483. meanBounds.z = p_nDepth;
  484. }
  485. /**
  486. * Returns a string representing of this polygon.
  487. *
  488. * @return The string representation.
  489. */
  490. public function toString():String
  491. {
  492. return "sandy.core.data.Polygon::id=" +id+ " [Points: " + vertices.length + "]";
  493. }
  494. /**
  495. * Enables or disables object events for this polygon.
  496. *
  497. * <p>If a value of true is passed, the object events onPress, onRollOver and onRollOut are enabled.<br />.
  498. * To use them, you have to add listeners for the events.</p>
  499. *
  500. * @param b Pass true to enable the events, false to disable.
  501. */
  502. public function set enableEvents( b:Boolean ):void
  503. {
  504. if( b && !mouseEvents )
  505. {
  506. container.addEventListener(MouseEvent.CLICK, _onInteraction);
  507. container.addEventListener(MouseEvent.MOUSE_UP, _onInteraction);
  508. container.addEventListener(MouseEvent.MOUSE_DOWN, _onInteraction);
  509. container.addEventListener(MouseEvent.ROLL_OVER, _onInteraction);
  510. container.addEventListener(MouseEvent.ROLL_OUT, _onInteraction);
  511. container.addEventListener(MouseEvent.DOUBLE_CLICK, _onInteraction);
  512. container.addEventListener(MouseEvent.MOUSE_MOVE, _onInteraction);
  513. container.addEventListener(MouseEvent.MOUSE_OVER, _onInteraction);
  514. container.addEventListener(MouseEvent.MOUSE_OUT, _onInteraction);
  515. container.addEventListener(MouseEvent.MOUSE_WHEEL, _onInteraction);
  516. }
  517. else if( !b && mouseEvents )
  518. {
  519. container.removeEventListener(MouseEvent.CLICK, _onInteraction);
  520. container.removeEventListener(MouseEvent.MOUSE_UP, _onInteraction);
  521. container.removeEventListener(MouseEvent.MOUSE_DOWN, _onInteraction);
  522. container.removeEventListener(MouseEvent.ROLL_OVER, _onInteraction);
  523. container.removeEventListener(MouseEvent.ROLL_OUT, _onInteraction);
  524. container.removeEventListener(MouseEvent.DOUBLE_CLICK, _onInteraction);
  525. container.removeEventListener(MouseEvent.MOUSE_MOVE, _onInteraction);
  526. container.removeEventListener(MouseEvent.MOUSE_OVER, _onInteraction);
  527. container.removeEventListener(MouseEvent.MOUSE_OUT, _onInteraction);
  528. container.removeEventListener(MouseEvent.MOUSE_WHEEL, _onInteraction);
  529. }
  530. mouseEvents = b;
  531. }
  532. public function get enableEvents():Boolean
  533. { return mouseEvents; }
  534. protected function _onInteraction( p_oEvt:Event ):void
  535. {m_oEB.broadcastEvent( new BubbleEvent( p_oEvt.type, this, p_oEvt ) );}
  536. protected function _startMouseInteraction( e : MouseEvent = null ) : void
  537. {
  538. container.addEventListener(MouseEvent.CLICK, _onTextureInteraction);
  539. container.addEventListener(MouseEvent.MOUSE_UP, _onTextureInteraction);
  540. container.addEventListener(MouseEvent.MOUSE_DOWN, _onTextureInteraction);
  541. container.addEventListener(MouseEvent.DOUBLE_CLICK, _onTextureInteraction);
  542. container.addEventListener(MouseEvent.MOUSE_MOVE, _onTextureInteraction);
  543. container.addEventListener(MouseEvent.MOUSE_OVER, _onTextureInteraction);
  544. container.addEventListener(MouseEvent.MOUSE_OUT, _onTextureInteraction);
  545. container.addEventListener(MouseEvent.MOUSE_WHEEL, _onTextureInteraction);
  546. container.addEventListener(KeyboardEvent.KEY_DOWN, _onTextureInteraction);
  547. container.addEventListener(KeyboardEvent.KEY_UP, _onTextureInteraction);
  548. m_oContainer.addEventListener( Event.ENTER_FRAME, _onTextureInteraction );
  549. }
  550. protected function _stopMouseInteraction( e : MouseEvent = null ) : void
  551. {
  552. container.removeEventListener(MouseEvent.CLICK, _onTextureInteraction);
  553. container.removeEventListener(MouseEvent.MOUSE_UP, _onTextureInteraction);
  554. container.removeEventListener(MouseEvent.MOUSE_DOWN, _onTextureInteraction);
  555. container.removeEventListener(MouseEvent.DOUBLE_CLICK, _onTextureInteraction);
  556. container.removeEventListener(MouseEvent.MOUSE_MOVE, _onTextureInteraction);
  557. container.removeEventListener(MouseEvent.MOUSE_OVER, _onTextureInteraction);
  558. container.removeEventListener(MouseEvent.MOUSE_OUT, _onTextureInteraction);
  559. container.removeEventListener(MouseEvent.MOUSE_WHEEL, _onTextureInteraction);
  560. m_oContainer.removeEventListener( Event.ENTER_FRAME, _onTextureInteraction );
  561. container.removeEventListener(KeyboardEvent.KEY_DOWN, _onTextureInteraction);
  562. container.removeEventListener(KeyboardEvent.KEY_UP, _onTextureInteraction);
  563. }
  564. public function set enableInteractivity( p_bState:Boolean ):void
  565. {
  566. if( p_bState != mouseInteractivity )
  567. {
  568. if( p_bState )
  569. {
  570. container.addEventListener( MouseEvent.ROLL_OVER, _startMouseInteraction, false );
  571. container.addEventListener( MouseEvent.ROLL_OUT, _stopMouseInteraction, false );
  572. }
  573. else
  574. {
  575. _stopMouseInteraction();
  576. }
  577. // --
  578. mouseInteractivity = p_bState;
  579. }
  580. }
  581. public function get enableInteractivity():Boolean
  582. { return mouseInteractivity; }
  583. protected function _onTextureInteraction( p_oEvt:Event = null ) : void
  584. {
  585. if ( p_oEvt == null || !(p_oEvt is MouseEvent) ) p_oEvt = new MouseEvent( MouseEvent.MOUSE_MOVE, true, false, 0, 0, null, false, false, false, false, 0);
  586. // get the position of the mouse on the poly
  587. var pt2D : Point = new Point( scene.container.mouseX, scene.container.mouseY );
  588. var uv : UVCoord = getUVFrom2D( pt2D );
  589. VirtualMouse.getInstance().interactWithTexture( this, uv, p_oEvt as MouseEvent );
  590. _onInteraction( p_oEvt );
  591. }
  592. /**
  593. * Calculates and returns the normal vector of the polygon.
  594. *
  595. * @return The normal vector
  596. */
  597. public function createNormal():Vector
  598. {
  599. if( vertices.length > 2 )
  600. {
  601. var v:Vector, w:Vector;
  602. var a:Vertex = vertices[0], b:Vertex = vertices[1], c:Vertex = vertices[2];
  603. v = new Vector( b.wx - a.wx, b.wy - a.wy, b.wz - a.wz );
  604. w = new Vector( b.wx - c.wx, b.wy - c.wy, b.wz - c.wz );
  605. // we compute de cross product
  606. var l_normal:Vector = VectorMath.cross( v, w );
  607. // we normalize the resulting vector
  608. VectorMath.normalize( l_normal ) ;
  609. // we return the resulting vertex
  610. return l_normal;
  611. }
  612. else
  613. {
  614. return new Vector();
  615. }
  616. }
  617. /**
  618. * The appearance of this polygon.
  619. */
  620. public function set appearance( p_oApp:Appearance ):void
  621. {
  622. m_oAppearance = p_oApp;
  623. // --
  624. p_oApp.frontMaterial.init( this );
  625. p_oApp.backMaterial.init( this );
  626. }
  627. /**
  628. * @private
  629. */
  630. public function get appearance():Appearance
  631. {
  632. return m_oAppearance;
  633. }
  634. /**
  635. * Changes which side is the "normal" culling side.
  636. *
  637. * <p>The method also swaps the front and back skins.</p>
  638. */
  639. public function swapCulling():void
  640. {
  641. //TODO Check the acuracy of this method
  642. // reverse the normal
  643. var v:Vector = normal.getVector();
  644. var m:Matrix4 = Matrix4Math.axisRotation( vertices[0].x - vertices[1].x, vertices[0].y - vertices[1].y, vertices[0].z - vertices[1].z, 180 );
  645. m.vectorMult3x3( v );
  646. v.normalize();
  647. normal.x = v.x;
  648. normal.y = v.y;
  649. normal.z = v.z;
  650. v = null;
  651. m = null;
  652. }
  653. /**
  654. * Destroys the sprite attache to this polygon.
  655. */
  656. public function destroy():void
  657. {
  658. clear();
  659. // --
  660. if( m_oContainer.parent ) m_oContainer.parent.removeChild( m_oContainer );
  661. if( m_oContainer ) m_oContainer = null;
  662. // --
  663. cvertices = null;
  664. vertices = null;
  665. m_oEB = null;
  666. }
  667. // _______
  668. // PRIVATE_______________________________________________________
  669. /** Reference to its owner geometry */
  670. private var m_oGeometry:Geometry3D;
  671. private var m_oAppearance:Appearance;
  672. /** array of ID of uv coordinates in geometry object */
  673. private var m_aUVCoords:Array;
  674. private var m_bVisible:Boolean = false;
  675. protected var m_oContainer:Sprite;
  676. protected var m_oVisibilityRef:Vertex;
  677. protected var m_oEB:BubbleEventBroadcaster = new BubbleEventBroadcaster();
  678. /** Boolean representing the state of the event activation */
  679. private var mouseEvents:Boolean = false;
  680. private var mouseInteractivity:Boolean = false;
  681. }
  682. }