PageRenderTime 777ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/sandy/core/data/Polygon.hx

http://github.com/sandy3d/sandy-hx
Haxe | 953 lines | 594 code | 86 blank | 273 comment | 128 complexity | cfb70d9895e6697331a13707b3cc0fb5 MD5 | raw file
  1. package sandy.core.data;
  2. import flash.display.Sprite;
  3. import flash.events.Event;
  4. import flash.events.KeyboardEvent;
  5. import flash.events.MouseEvent;
  6. import flash.geom.Matrix;
  7. import flash.geom.Point;
  8. import flash.geom.Rectangle;
  9. import sandy.math.PlaneMath;
  10. import sandy.core.Scene3D;
  11. #if !(cpp || neko) //TODO
  12. import sandy.core.interaction.VirtualMouse;
  13. #end
  14. import sandy.core.scenegraph.Geometry3D;
  15. import sandy.core.scenegraph.IDisplayable;
  16. import sandy.core.scenegraph.Shape3D;
  17. import sandy.events.BubbleEventBroadcaster;
  18. import sandy.events.SandyEvent;
  19. import sandy.events.Shape3DEvent;
  20. import sandy.materials.Appearance;
  21. import sandy.materials.Material;
  22. import sandy.math.IntersectionMath;
  23. import sandy.math.Point3DMath;
  24. import sandy.view.CullingState;
  25. import sandy.view.Frustum;
  26. import sandy.HaxeTypes;
  27. /**
  28. * Polygon's are the building blocks of visible 3D shapes.
  29. *
  30. * @author Thomas Pfeiffer - kiroukou
  31. * @author Mirek Mencel
  32. * @author Niel Drummond - haXe port
  33. * @author Russell Weir - haXe port
  34. * @since 1.0
  35. * @version 3.1
  36. * @date 24.08.2007
  37. *
  38. * @see sandy.core.scenegraph.Shape3D
  39. */
  40. class Polygon implements IDisplayable
  41. {
  42. // _______
  43. // STATICS_______________________________________________________
  44. private static var _ID_:Int = 0;
  45. /**
  46. * This property lists all the polygons.
  47. * This is an helping property since it allows to retrieve a polygon instance from its unique ID.
  48. * Polygon objects have an unique ID with myPolygon.id.
  49. * Using : Polygon.POLYGON_MAP[myPolygon.id] returns myPolygon (for sure this example has no interesst except showing the use of the property.
  50. */
  51. public static var POLYGON_MAP:IntHash<Polygon> = new IntHash();
  52. // ______
  53. // PUBLIC________________________________________________________
  54. /**
  55. * [READ-ONLY] property
  56. * Unique polygon ID Number.
  57. */
  58. public var id:Int;
  59. /**
  60. * [READ-ONLY] property.
  61. * Link to the Shape3D instance this polygon is related too.
  62. */
  63. public var shape:Shape3D;
  64. /**
  65. * [READ-ONLY] property.
  66. * Specify if the polygon has been clipped
  67. */
  68. public var isClipped:Bool;
  69. /**
  70. * An array of clipped vertices. Check the <code>isClipped</code> property first to see if this array will contain the useful data.
  71. */
  72. public var cvertices:Array<Vertex>;
  73. /**
  74. * Array of original vertices.
  75. */
  76. public var vertices:Array<Vertex>;
  77. /**
  78. * An array of the polygon's vertex normals.
  79. */
  80. public var vertexNormals:Array<Vertex>;
  81. public var aUVCoord:Array<UVCoord>;
  82. /**
  83. * An array of the polygon's edges.
  84. */
  85. public var aEdges:Array<Edge3D>;
  86. public var caUVCoord:Array<UVCoord>;
  87. /**
  88. * The texture bounds.
  89. */
  90. public var uvBounds:Rectangle;
  91. /**
  92. * An array of polygons that share an edge with this polygon.
  93. */
  94. public var aNeighboors:Array<Polygon>;
  95. /**
  96. * Specifies whether the face of the polygon is visible.
  97. */
  98. public var visible:Bool;
  99. /**
  100. * Minimum depth value of that polygon in the camera space
  101. */
  102. public var minZ:Float;
  103. public var a:Vertex;
  104. public var b:Vertex;
  105. public var c:Vertex;
  106. public var d:Vertex;
  107. private var _area:Float;
  108. public var area(__getArea,null):Float;
  109. private inline function __getArea ():Float {
  110. if (Math.isNaN (_area)) {
  111. // triangle area is 1/2 of sides cross product
  112. var ab:Vertex = b.clone (); ab.sub (a);
  113. var ac:Vertex = c.clone (); ac.sub (a);
  114. _area = 0.5 * ab.cross (ac).getNorm ();
  115. if (d != null) {
  116. var ad:Vertex = d.clone (); ad.sub (a);
  117. _area += 0.5 * ac.cross (ad).getNorm ();
  118. }
  119. }
  120. return _area;
  121. }
  122. /**
  123. * Creates a new polygon.
  124. *
  125. * @param p_oShape The shape this polygon belongs to
  126. * @param p_geometry The geometry this polygon is part of
  127. * @param p_aVertexID The vertexID array of this polygon
  128. * @param p_aUVCoordsID The UVCoordsID array of this polygon
  129. * @param p_nFaceNormalID The faceNormalID of this polygon
  130. * @param p_nEdgesID The edgesID of this polygon
  131. */
  132. public function new( p_oOwner:Shape3D, p_geometry:Geometry3D, p_aVertexID:Array<Int>, ?p_aUVCoordsID:Array<Int>, ?p_nFaceNormalID:Int=0, ?p_nEdgesID:Int=0 )
  133. {
  134. // public initializers
  135. id = _ID_++;
  136. isClipped = false;
  137. aNeighboors = new Array();
  138. //private initializers
  139. mouseEvents = false;
  140. mouseInteractivity = false;
  141. shape = p_oOwner;
  142. m_oGeometry = p_geometry;
  143. // --
  144. __create( p_aVertexID, p_aUVCoordsID, p_nFaceNormalID, p_nEdgesID );
  145. m_oContainer = new Sprite();
  146. // --
  147. POLYGON_MAP.set( id, this );
  148. m_oEB = new BubbleEventBroadcaster(this);
  149. }
  150. public function update( p_aVertexID:Array<Int> ):Void
  151. {
  152. var i:Int=0;
  153. // --
  154. for ( id in p_aVertexID )
  155. {
  156. vertices[i] = m_oGeometry.aVertex[ id ];
  157. vertexNormals[i] = m_oGeometry.aVertexNormals[ id ];
  158. i++;
  159. }
  160. // --
  161. a = vertices[0];
  162. b = vertices[1];
  163. c = vertices[2];
  164. d = vertices[3];
  165. }
  166. public var changed(__getChanged, __setChanged) : Bool;
  167. private function __getChanged():Bool {
  168. return shape.changed;
  169. }
  170. private function __setChanged(v:Bool): Bool {
  171. shape.changed = v;
  172. return v;
  173. }
  174. /**
  175. * A reference to the Scene3D object this polygon is in.
  176. */
  177. public var scene(__getScene, __setScene) : Scene3D;
  178. private var m_oScene : Scene3D;
  179. public function __setScene(p_oScene:Scene3D):Scene3D
  180. {
  181. if( p_oScene == null ) return null;
  182. if( m_oScene != null )
  183. {
  184. m_oScene.removeEventListener(SandyEvent.SCENE_RENDER_FINISH, _finishMaterial );
  185. m_oScene.removeEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST, _beginMaterial );
  186. }
  187. // --
  188. m_oScene = p_oScene;
  189. // --
  190. m_oScene.addEventListener(SandyEvent.SCENE_RENDER_FINISH, _finishMaterial );
  191. m_oScene.addEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST, _beginMaterial );
  192. return p_oScene;
  193. }
  194. public function __getScene():Scene3D
  195. {
  196. return m_oScene;
  197. }
  198. /**
  199. * Creates the vertices and normals for this polygon.
  200. *
  201. * <p>Calling this method make the polygon gets its vertice and normals by reference
  202. * instead of accessing them by their ID.<br/>
  203. * This method shall be called once the geometry created.</p>
  204. *
  205. * @param p_aVertexID The vertexID array of this polygon
  206. * @param p_aUVCoordsID The UVCoordsID array of this polygon
  207. * @param p_nFaceNormalID The faceNormalID of this polygon
  208. * @param p_nEdgesID The edgesID of this polygon
  209. */
  210. private function __create( p_aVertexID:Array<Int>, p_aUVCoordsID:Array<Int>, p_nFaceNormalID:Int, p_nEdgeListID:Int ):Void
  211. {
  212. var i:Int=0, l:Int;
  213. // --
  214. vertexNormals = new Array();
  215. vertices = new Array();
  216. for ( o in p_aVertexID )
  217. {
  218. vertices[i] = m_oGeometry.aVertex[ p_aVertexID[i] ];
  219. vertexNormals[i] = m_oGeometry.aVertexNormals[ p_aVertexID[i] ];
  220. i++;
  221. }
  222. // --
  223. a = vertices[0];
  224. b = vertices[1];
  225. c = vertices[2];
  226. d = vertices[3];
  227. // -- every polygon does not have some texture coordinates
  228. if( p_aUVCoordsID != null )
  229. {
  230. var l_nMinU:Float = Math.POSITIVE_INFINITY, l_nMinV:Float = Math.POSITIVE_INFINITY,
  231. l_nMaxU:Float = Math.NEGATIVE_INFINITY, l_nMaxV:Float = Math.NEGATIVE_INFINITY;
  232. // --
  233. aUVCoord = new Array();
  234. i = 0;
  235. if( p_aUVCoordsID != null) {
  236. for ( p in p_aUVCoordsID )
  237. {
  238. var l_oUV:UVCoord = m_oGeometry.aUVCoords[ p_aUVCoordsID[i] ];
  239. aUVCoord[i] = l_oUV;
  240. if( l_oUV.u < l_nMinU ) l_nMinU = l_oUV.u;
  241. else if( l_oUV.u > l_nMaxU ) l_nMaxU = l_oUV.u;
  242. // --
  243. if( l_oUV.v < l_nMinV ) l_nMinV = l_oUV.v;
  244. else if( l_oUV.v > l_nMaxV ) l_nMaxV = l_oUV.v;
  245. // --
  246. i++;
  247. }
  248. // --
  249. uvBounds = new Rectangle( l_nMinU, l_nMinV, l_nMaxU-l_nMinU, l_nMaxV-l_nMinV );
  250. }
  251. else
  252. {
  253. aUVCoord = [new UVCoord(), new UVCoord(), new UVCoord()];
  254. uvBounds = new Rectangle(0,0,0,0);
  255. }
  256. }
  257. // --
  258. m_nNormalId = p_nFaceNormalID;
  259. normal = m_oGeometry.aFacesNormals[ p_nFaceNormalID ];
  260. // If no normal has been given, we create it ourself.
  261. if( normal == null )
  262. {
  263. var l_oNormal:Point3D = createNormal();
  264. m_nNormalId = m_oGeometry.setFaceNormal( m_oGeometry.getNextFaceNormalID(), l_oNormal.x, l_oNormal.y, l_oNormal.z );
  265. }
  266. // --
  267. aEdges = new Array();
  268. for ( l_nEdgeId in m_oGeometry.aFaceEdges[p_nEdgeListID] )
  269. {
  270. var l_oEdge:Edge3D = m_oGeometry.aEdges[ l_nEdgeId ];
  271. l_oEdge.vertex1 = m_oGeometry.aVertex[ l_oEdge.vertexId1 ];
  272. l_oEdge.vertex2 = m_oGeometry.aVertex[ l_oEdge.vertexId2 ];
  273. aEdges.push( l_oEdge );
  274. }
  275. }
  276. public var normal(__getNormal,__setNormal) : Vertex;
  277. private function __getNormal():Vertex
  278. {
  279. return m_oGeometry.aFacesNormals[ m_nNormalId ];
  280. }
  281. public function __setNormal( p_oVertex:Vertex ):Vertex
  282. {
  283. if( p_oVertex != null )
  284. m_oGeometry.aFacesNormals[ m_nNormalId ].copy( p_oVertex );
  285. return p_oVertex;
  286. }
  287. public function updateNormal():Void
  288. {
  289. var x:Float = ((a.y - b.y) * (c.z - b.z)) - ((a.z - b.z) * (c.y - b.y)) ;
  290. var y:Float = ((a.z - b.z) * (c.x - b.x)) - ((a.x - b.x) * (c.z - b.z)) ;
  291. var z:Float = ((a.x - b.x) * (c.y - b.y)) - ((a.y - b.y) * (c.x - b.x)) ;
  292. normal.reset( x, y, z );
  293. if (normal.getNorm () > 0) normal.normalize(); else normal.y = 1;
  294. }
  295. /**
  296. * The depth of the polygon.
  297. */
  298. public var depth(__getDepth,__setDepth):Float;
  299. private function __getDepth():Float{ return m_nDepth; }
  300. private function __setDepth( p_nDepth:Float ):Float{ m_nDepth = p_nDepth; return p_nDepth; }
  301. /**
  302. * The broadcaster property.
  303. *
  304. * <p>The broadcaster is the property used to send events to listeners.</p>
  305. */
  306. public var broadcaster(__getBroadcaster,null):BubbleEventBroadcaster;
  307. private function __getBroadcaster():BubbleEventBroadcaster
  308. {
  309. return m_oEB;
  310. }
  311. /**
  312. * Adds a listener for specifical event.
  313. *
  314. * @param p_sEvent Name of the Event.
  315. * @param oL Listener object.
  316. */
  317. public function addEventListener(p_sEvent:String, oL:Dynamic, arguments:Array<Dynamic> ) : Void
  318. {
  319. Reflect.callMethod( m_oEB.addEventListener, m_oEB, arguments );
  320. }
  321. /**
  322. * Removes a listener for specifical event.
  323. *
  324. * @param p_sEvent Name of the Event.
  325. * @param oL Listener object.
  326. */
  327. public function removeEventListener(p_sEvent:String, oL:Dynamic) : Void
  328. {
  329. m_oEB.removeEventListener(p_sEvent, oL);
  330. }
  331. /**
  332. * Computes several properties of the polygon.
  333. * <p>The computed properties are listed below:</p>
  334. * <ul>
  335. * <li><code>visible</code></li>
  336. * <li><code>minZ</code></li>
  337. * <li><code>depth</code></li>
  338. * </ul>
  339. */
  340. public function precompute():Void
  341. {
  342. isClipped = false;
  343. // --
  344. minZ = a.wz;
  345. if (b.wz < minZ) minZ = b.wz;
  346. m_nDepth = a.wz + b.wz;
  347. // --
  348. if (c != null)
  349. {
  350. if (c.wz < minZ) minZ = c.wz;
  351. m_nDepth += c.wz;
  352. }
  353. if (d != null)
  354. {
  355. if (d.wz < minZ) minZ = d.wz;
  356. m_nDepth += d.wz;
  357. }
  358. m_nDepth /= vertices.length;
  359. }
  360. /**
  361. * Returns a Point3D (3D position) on the polygon relative to the specified point on the 2D screen.
  362. *
  363. * @example Below is an example of how to get the 3D coordinate of the polygon under the position of the mouse:
  364. * <listing version="3.1">
  365. * var screenPoint:Point = new Point(myPolygon.container.mouseX, myPolygon.container.mouseY);
  366. * var scenePosition:Point3D = myPolygon.get3DFrom2D(screenPoint);
  367. * </listing>
  368. *
  369. * @return A Point3D that corresponds to the specified point.
  370. */
  371. public function get3DFrom2D( p_oScreenPoint:Point ):Point3D
  372. {
  373. /// NEW CODE ADDED BY MAX with the help of makc ///
  374. var m1:Matrix= new Matrix(
  375. vertices[1].sx-vertices[0].sx,
  376. vertices[2].sx-vertices[0].sx,
  377. vertices[1].sy-vertices[0].sy,
  378. vertices[2].sy-vertices[0].sy,
  379. 0,
  380. 0);
  381. m1.invert();
  382. var capA:Float = m1.a *(p_oScreenPoint.x-vertices[0].sx) + m1.b * (p_oScreenPoint.y -vertices[0].sy);
  383. var capB:Float = m1.c *(p_oScreenPoint.x-vertices[0].sx) + m1.d * (p_oScreenPoint.y -vertices[0].sy);
  384. var l_oPoint:Point3D = new Point3D(
  385. vertices[0].x + capA*(vertices[1].x -vertices[0].x) + capB *(vertices[2].x - vertices[0].x),
  386. vertices[0].y + capA*(vertices[1].y -vertices[0].y) + capB *(vertices[2].y - vertices[0].y),
  387. vertices[0].z + capA*(vertices[1].z -vertices[0].z) + capB *(vertices[2].z - vertices[0].z)
  388. );
  389. // transform the vertex with the model Matrix
  390. this.shape.matrix.transform( l_oPoint );
  391. return l_oPoint;
  392. }
  393. /**
  394. * Returns a UV coordinate elative to the specified point on the 2D screen.
  395. *
  396. * @example Below is an example of how to get the UV coordinate under the position of the mouse:
  397. * <listing version="3.1">
  398. * var screenPoint:Point = new Point(myPolygon.container.mouseX, myPolygon.container.mouseY);
  399. * var scenePosition:Point3D = myPolygon.getUVFrom2D(screenPoint);
  400. * </listing>
  401. *
  402. * @return A the UV coordinate that corresponds to the specified point.
  403. */
  404. public function getUVFrom2D( p_oScreenPoint:Point ):UVCoord
  405. {
  406. var p0:Point = new Point(vertices[0].sx, vertices[0].sy);
  407. var p1:Point = new Point(vertices[1].sx, vertices[1].sy);
  408. var p2:Point = new Point(vertices[2].sx, vertices[2].sy);
  409. var u0:UVCoord = aUVCoord[0];
  410. var u1:UVCoord = aUVCoord[1];
  411. var u2:UVCoord = aUVCoord[2];
  412. var v01:Point = new Point(p1.x - p0.x, p1.y - p0.y );
  413. var vn01:Point = v01.clone();
  414. vn01.normalize(1);
  415. var v02:Point = new Point(p2.x - p0.x, p2.y - p0.y );
  416. var vn02:Point = v02.clone(); vn02.normalize(1);
  417. // sub that from click point
  418. var v4:Point = new Point( p_oScreenPoint.x - v01.x, p_oScreenPoint.y - v01.y );
  419. // we now have everything to find 1 intersection
  420. var l_oInter:Point = IntersectionMath.intersectionLine2D( p0, p2, p_oScreenPoint, v4 );
  421. // find Point3Ds to intersection
  422. var vi02:Point = new Point( l_oInter.x - p0.x, l_oInter.y - p0.y );
  423. var vi01:Point = new Point( p_oScreenPoint.x - l_oInter.x , p_oScreenPoint.y - l_oInter.y );
  424. // interpolation coeffs
  425. var d1:Float = vi01.length / v01.length ;
  426. var d2:Float = vi02.length / v02.length;
  427. // -- on interpole linéairement pour trouver la position du point dans repere de la texture (normalisé)
  428. return new UVCoord( u0.u + d1*(u1.u - u0.u) + d2*(u2.u - u0.u),
  429. u0.v + d1*(u1.v - u0.v) + d2*(u2.v - u0.v));
  430. }
  431. /**
  432. * Clips the polygon.
  433. *
  434. * @return An array of vertices clipped by the camera frustum.
  435. */
  436. public function clip( p_oFrustum:Frustum ):Array<Vertex>
  437. {
  438. cvertices = null;
  439. caUVCoord = null;
  440. // --
  441. var l_oCull:Int = p_oFrustum.polygonInFrustum( this );
  442. if( l_oCull == CullingState.INSIDE )
  443. return vertices;
  444. else if( l_oCull == CullingState.OUTSIDE )
  445. return null;
  446. // For lines we only apply front plane clipping
  447. if( vertices.length < 3 )
  448. {
  449. clipFrontPlane( p_oFrustum );
  450. }
  451. else
  452. {
  453. cvertices = vertices.copy();
  454. caUVCoord = aUVCoord.copy();
  455. // --
  456. isClipped = p_oFrustum.clipFrustum( cvertices, caUVCoord );
  457. }
  458. return cvertices;
  459. }
  460. /**
  461. * Perform a clipping against the near frustum plane.
  462. *
  463. * @return The array of clipped vertices
  464. */
  465. public function clipFrontPlane( p_oFrustum:Frustum ):Array<Vertex>
  466. {
  467. cvertices = vertices.copy();
  468. // If line
  469. if( vertices.length < 3 )
  470. {
  471. isClipped = p_oFrustum.clipLineFrontPlane( cvertices );
  472. }
  473. else
  474. {
  475. caUVCoord = aUVCoord.copy();
  476. isClipped = p_oFrustum.clipFrontPlane( cvertices, caUVCoord );
  477. }
  478. return cvertices;
  479. }
  480. /**
  481. * Clears the polygon's container.
  482. */
  483. public function clear():Void
  484. {
  485. if (m_oContainer != null) m_oContainer.graphics.clear();
  486. }
  487. /**
  488. * Draws the polygon on its container if visible.
  489. *
  490. * @param p_oScene The scene this polygon is rendered in.
  491. * @param p_oContainer The container to draw on.
  492. */
  493. public function display( ?p_oContainer:Sprite ):Void
  494. {
  495. // --
  496. var lCont:Sprite = (p_oContainer != null)?p_oContainer:m_oContainer;
  497. if( material != null )
  498. material.renderPolygon( scene, this, lCont );
  499. }
  500. /**
  501. * Returns the material currently used by the renderer
  502. * @return Material the material used to render
  503. */
  504. public var material(__getMaterial,__setMaterial) : Material;
  505. private function __getMaterial():Material
  506. {
  507. if( m_oAppearance == null ) return null;
  508. return ( visible ) ? m_oAppearance.frontMaterial : m_oAppearance.backMaterial;
  509. }
  510. private function __setMaterial(v:Material) : Material
  511. {
  512. return throw "unimplemented";
  513. }
  514. /**
  515. * The container for this polygon.
  516. */
  517. public var container(__getContainer,null):Sprite;
  518. private function __getContainer():Sprite
  519. {
  520. return m_oContainer;
  521. }
  522. /**
  523. * Returns a string representing of this polygon.
  524. *
  525. * @return The string representation.
  526. */
  527. public function toString():String
  528. {
  529. return "sandy.core.data.Polygon::id=" +id+ " [Points: " + vertices.length + "]";
  530. }
  531. /**
  532. * Specifies whether mouse events are enabled for this polygon.
  533. *
  534. * <p>To apply events to a polygon, listeners must be added with the <code>addEventListener()</code> method.</p>
  535. *
  536. * @see #addEventListener()
  537. */
  538. public var enableEvents(__getEnableEvents,__setEnableEvents):Bool;
  539. private function __getEnableEvents():Bool { return mouseEvents; }
  540. private function __setEnableEvents( b:Bool ):Bool
  541. {
  542. if( b && !mouseEvents )
  543. {
  544. container.addEventListener(MouseEvent.CLICK, _onInteraction);
  545. container.addEventListener(MouseEvent.MOUSE_UP, _onInteraction);
  546. container.addEventListener(MouseEvent.MOUSE_DOWN, _onInteraction);
  547. container.addEventListener(MouseEvent.ROLL_OVER, _onInteraction);
  548. container.addEventListener(MouseEvent.ROLL_OUT, _onInteraction);
  549. container.addEventListener(MouseEvent.DOUBLE_CLICK, _onInteraction);
  550. container.addEventListener(MouseEvent.MOUSE_MOVE, _onInteraction);
  551. container.addEventListener(MouseEvent.MOUSE_OVER, _onInteraction);
  552. container.addEventListener(MouseEvent.MOUSE_OUT, _onInteraction);
  553. container.addEventListener(MouseEvent.MOUSE_WHEEL, _onInteraction);
  554. }
  555. else if( !b && mouseEvents )
  556. {
  557. container.removeEventListener(MouseEvent.CLICK, _onInteraction);
  558. container.removeEventListener(MouseEvent.MOUSE_UP, _onInteraction);
  559. container.removeEventListener(MouseEvent.MOUSE_DOWN, _onInteraction);
  560. container.removeEventListener(MouseEvent.ROLL_OVER, _onInteraction);
  561. container.removeEventListener(MouseEvent.ROLL_OUT, _onInteraction);
  562. container.removeEventListener(MouseEvent.DOUBLE_CLICK, _onInteraction);
  563. container.removeEventListener(MouseEvent.MOUSE_MOVE, _onInteraction);
  564. container.removeEventListener(MouseEvent.MOUSE_OVER, _onInteraction);
  565. container.removeEventListener(MouseEvent.MOUSE_OUT, _onInteraction);
  566. container.removeEventListener(MouseEvent.MOUSE_WHEEL, _onInteraction);
  567. }
  568. mouseEvents = b;
  569. return b;
  570. }
  571. private var m_bWasOver:Bool;
  572. /**
  573. * @private
  574. */
  575. private function _onInteraction( p_oEvt:Event ):Void
  576. {
  577. var l_oClick:Point = new Point( m_oContainer.mouseX, m_oContainer.mouseY );
  578. var l_oUV:UVCoord = getUVFrom2D( l_oClick );
  579. var l_oPt3d:Point3D = get3DFrom2D( l_oClick );
  580. shape.m_oLastContainer = this.m_oContainer;
  581. shape.m_oLastEvent = new Shape3DEvent( p_oEvt.type, shape, this, l_oUV, l_oPt3d, p_oEvt );
  582. m_oEB.dispatchEvent( shape.m_oLastEvent );
  583. if( p_oEvt.type == MouseEvent.MOUSE_OVER )
  584. shape.m_bWasOver = true;
  585. }
  586. /**
  587. * @private
  588. */
  589. public function _startMouseInteraction( ?e : MouseEvent ) : Void
  590. {
  591. container.addEventListener(MouseEvent.CLICK, _onTextureInteraction);
  592. container.addEventListener(MouseEvent.MOUSE_UP, _onTextureInteraction);
  593. container.addEventListener(MouseEvent.MOUSE_DOWN, _onTextureInteraction);
  594. container.addEventListener(MouseEvent.DOUBLE_CLICK, _onTextureInteraction);
  595. container.addEventListener(MouseEvent.MOUSE_MOVE, _onTextureInteraction);
  596. container.addEventListener(MouseEvent.MOUSE_OVER, _onTextureInteraction);
  597. container.addEventListener(MouseEvent.MOUSE_OUT, _onTextureInteraction);
  598. container.addEventListener(MouseEvent.MOUSE_WHEEL, _onTextureInteraction);
  599. container.addEventListener(KeyboardEvent.KEY_DOWN, _onTextureInteraction);
  600. container.addEventListener(KeyboardEvent.KEY_UP, _onTextureInteraction);
  601. m_oContainer.addEventListener( Event.ENTER_FRAME, _onTextureInteraction );
  602. }
  603. /**
  604. * @private
  605. */
  606. public function _stopMouseInteraction( ?e : MouseEvent ) : Void
  607. {
  608. container.addEventListener(MouseEvent.CLICK, _onTextureInteraction);
  609. container.addEventListener(MouseEvent.MOUSE_UP, _onTextureInteraction);
  610. container.addEventListener(MouseEvent.MOUSE_DOWN, _onTextureInteraction);
  611. container.addEventListener(MouseEvent.DOUBLE_CLICK, _onTextureInteraction);
  612. container.addEventListener(MouseEvent.MOUSE_MOVE, _onTextureInteraction);
  613. container.addEventListener(MouseEvent.MOUSE_OVER, _onTextureInteraction);
  614. container.addEventListener(MouseEvent.MOUSE_OUT, _onTextureInteraction);
  615. container.addEventListener(MouseEvent.MOUSE_WHEEL, _onTextureInteraction);
  616. container.addEventListener(KeyboardEvent.KEY_DOWN, _onTextureInteraction);
  617. container.addEventListener(KeyboardEvent.KEY_UP, _onTextureInteraction);
  618. m_oContainer.addEventListener( Event.ENTER_FRAME, _onTextureInteraction );
  619. }
  620. /**
  621. * Specifies whether <code>MouseEvent.ROLL_&#42;</code> events are enabled for this polygon.
  622. *
  623. * <p>To apply events to a polygon, listeners must be added with the <code>addEventListener()</code> method.</p>
  624. *
  625. * @see #addEventListener()
  626. */
  627. public var enableInteractivity(__getEnableInteractivity,__setEnableInteractivity):Bool;
  628. private function __getEnableInteractivity():Bool { return mouseInteractivity; }
  629. private function __setEnableInteractivity( p_bState:Bool ):Bool
  630. {
  631. if( p_bState != mouseInteractivity )
  632. {
  633. if( p_bState )
  634. {
  635. container.addEventListener( MouseEvent.ROLL_OVER, _startMouseInteraction, false );
  636. container.addEventListener( MouseEvent.ROLL_OUT, _stopMouseInteraction, false );
  637. }
  638. else
  639. {
  640. _stopMouseInteraction();
  641. }
  642. // --
  643. mouseInteractivity = p_bState;
  644. }
  645. return p_bState;
  646. }
  647. /**
  648. * @private
  649. */
  650. public function _onTextureInteraction( ?p_oEvt:Event ) : Void
  651. {
  652. var l_oEvt : MouseEvent = null;
  653. if ( p_oEvt == null || !Std.is( p_oEvt, MouseEvent ) )
  654. {
  655. l_oEvt = new MouseEvent( MouseEvent.MOUSE_MOVE, true, false, 0, 0, null, false, false, false, false, 0);
  656. } else {
  657. l_oEvt = cast p_oEvt;
  658. }
  659. // get the position of the mouse on the poly
  660. var pt2D : Point = new Point( scene.container.mouseX, scene.container.mouseY );
  661. var uv : UVCoord = getUVFrom2D( pt2D );
  662. #if !(cpp || neko) //TODO
  663. VirtualMouse.getInstance().interactWithTexture( this, uv, l_oEvt );
  664. #end
  665. _onInteraction( p_oEvt );
  666. }
  667. /**
  668. * Returns the transformed normal Point3D of the polygon.
  669. *
  670. * @return The transformed normal Point3D of the polygon.
  671. */
  672. public function createTransformedNormal():Point3D
  673. {
  674. if( vertices.length > 2 )
  675. {
  676. var v:Point3D, w:Point3D;
  677. var a:Vertex = vertices[0], b:Vertex = vertices[1], c:Vertex = vertices[2];
  678. v = new Point3D( b.wx - a.wx, b.wy - a.wy, b.wz - a.wz );
  679. w = new Point3D( b.wx - c.wx, b.wy - c.wy, b.wz - c.wz );
  680. // we compute de cross product
  681. var l_normal:Point3D = Point3DMath.cross( v, w );
  682. // we normalize the resulting Point3D
  683. Point3DMath.normalize( l_normal ) ;
  684. // we return the resulting vertex
  685. return l_normal;
  686. }
  687. else
  688. {
  689. return new Point3D();
  690. }
  691. }
  692. /**
  693. * Returns the transformed normal Point3D of the polygon.
  694. *
  695. * @return The transformed normal Point3D of the polygon.
  696. */
  697. public function createNormal():Point3D
  698. {
  699. if( vertices.length > 2 )
  700. {
  701. var v:Point3D, w:Point3D;
  702. var a:Vertex = vertices[0], b:Vertex = vertices[1], c:Vertex = vertices[2];
  703. v = new Point3D( b.wx - a.wx, b.wy - a.wy, b.wz - a.wz );
  704. w = new Point3D( b.wx - c.wx, b.wy - c.wy, b.wz - c.wz );
  705. // we compute de cross product
  706. var l_normal:Point3D = Point3DMath.cross( v, w );
  707. // we normalize the resulting vector
  708. Point3DMath.normalize( l_normal ) ;
  709. // we return the resulting vertex
  710. return l_normal;
  711. }
  712. else
  713. {
  714. return new Point3D();
  715. }
  716. }
  717. /**
  718. * The appearance of this polygon.
  719. */
  720. public var appearance(__getAppearance,__setAppearance):Appearance;
  721. private function __getAppearance():Appearance
  722. {
  723. return m_oAppearance;
  724. }
  725. private function __setAppearance( p_oApp:Appearance ):Appearance
  726. {
  727. if( p_oApp == m_oAppearance ) return null;
  728. // --
  729. if( m_oAppearance != null && p_oApp != null)
  730. {
  731. if( p_oApp.frontMaterial != m_oAppearance.frontMaterial )
  732. {
  733. if(m_oAppearance.frontMaterial != null)
  734. m_oAppearance.frontMaterial.unlink( this );
  735. p_oApp.frontMaterial.init( this );
  736. }
  737. if( m_oAppearance.frontMaterial != m_oAppearance.backMaterial && p_oApp.backMaterial != m_oAppearance.backMaterial )
  738. {
  739. m_oAppearance.backMaterial.unlink( this );
  740. }
  741. if( p_oApp.frontMaterial != p_oApp.backMaterial && p_oApp.backMaterial != m_oAppearance.backMaterial )
  742. {
  743. p_oApp.backMaterial.init( this );
  744. }
  745. m_oAppearance = p_oApp;
  746. }
  747. else if( p_oApp != null )
  748. {
  749. m_oAppearance = p_oApp;
  750. m_oAppearance.frontMaterial.init( this );
  751. if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
  752. m_oAppearance.backMaterial.init( this );
  753. }
  754. else if( m_oAppearance != null )
  755. {
  756. if(m_oAppearance.frontMaterial != null)
  757. m_oAppearance.frontMaterial.unlink( this );
  758. if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
  759. m_oAppearance.backMaterial.unlink( this );
  760. m_oAppearance = null;
  761. }
  762. return p_oApp;
  763. }
  764. private function _finishMaterial( pEvt:SandyEvent ):Void
  765. {
  766. if( m_oAppearance == null ) return;
  767. // --
  768. if( m_oAppearance.frontMaterial != null )
  769. {
  770. m_oAppearance.frontMaterial.finish( m_oScene );
  771. }
  772. if( m_oAppearance.backMaterial != null && m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
  773. {
  774. m_oAppearance.backMaterial.finish( m_oScene );
  775. }
  776. }
  777. private function _beginMaterial( pEvt:SandyEvent ):Void
  778. {
  779. if( m_oAppearance == null ) return;
  780. // --
  781. if( m_oAppearance.frontMaterial != null )
  782. {
  783. m_oAppearance.frontMaterial.begin( m_oScene );
  784. }
  785. if( m_oAppearance.backMaterial != null && m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
  786. {
  787. m_oAppearance.backMaterial.begin( m_oScene );
  788. }
  789. }
  790. /**
  791. * Changes which side is the "normal" culling side.
  792. *
  793. * <p>The method also swaps the front and back skins.</p>
  794. */
  795. public function swapCulling():Void
  796. {
  797. normal.negate();
  798. }
  799. /**
  800. * Destroys the sprite attache to this polygon.
  801. */
  802. public function destroy():Void
  803. {
  804. clear();
  805. if(scene != null) {
  806. scene.removeEventListener(SandyEvent.SCENE_RENDER_FINISH, _finishMaterial );
  807. scene.removeEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST, _beginMaterial );
  808. }
  809. // --
  810. enableEvents = false;
  811. enableInteractivity = false;
  812. if( appearance != null )
  813. {
  814. //appearance.dispose();
  815. if( appearance.frontMaterial != null ) appearance.frontMaterial.unlink(this);
  816. if( appearance.backMaterial != null ) appearance.backMaterial.unlink(this);
  817. appearance = null;
  818. }
  819. if( m_oContainer != null ) {
  820. if( m_oContainer.parent != null ) m_oContainer.parent.removeChild( m_oContainer );
  821. m_oContainer = null;
  822. }
  823. // --
  824. cvertices = null;
  825. vertices = null;
  826. m_oEB = null;
  827. m_oGeometry = null;
  828. shape = null;
  829. scene = null;
  830. // -- memory leak fix from nopmb on mediabox forums
  831. POLYGON_MAP.remove( id );
  832. }
  833. public function getPlane (?centered:Bool = true):Plane {
  834. // calculate center of polygon
  835. var center:Point3D = a.getPoint3D ();
  836. if (centered) {
  837. center.x += b.x; center.y += b.y; center.z += b.z;
  838. center.x += c.x; center.y += c.y; center.z += c.z;
  839. if (d != null) {
  840. center.x += d.x; center.y += d.y; center.z += d.z;
  841. center.scale (0.25);
  842. } else {
  843. center.scale (1/3);
  844. }
  845. }
  846. // return plane
  847. return PlaneMath.createFromNormalAndPoint (normal.getPoint3D (), center);
  848. }
  849. // _______
  850. // PRIVATE_______________________________________________________
  851. /** Reference to its owner geometry */
  852. private var m_oGeometry:Geometry3D;
  853. private var m_oAppearance:Appearance;
  854. private var m_nNormalId:Int;
  855. private var m_nDepth:Float;
  856. /**
  857. * @private
  858. */
  859. private var m_oContainer:Sprite;
  860. /**
  861. * @private
  862. */
  863. private var m_oEB:BubbleEventBroadcaster;
  864. /** Boolean representing the state of the event activation */
  865. private var mouseEvents:Bool;
  866. private var mouseInteractivity:Bool;
  867. }