[prev in list] [next in list] [prev in thread] [next in thread] 

List:       osflash-sandy
Subject:    [Sandy] [sandy commit] r921 - in trunk/sandy/as3/trunk/src/sandy:
From:       codesite-noreply () google ! com
Date:       2009-02-23 21:54:24
Message-ID: 0016369202cbb2b35d04639d0b3c () google ! com
[Download RAW message or body]

Author: kiroukou
Date: Mon Feb 23 13:53:09 2009
New Revision: 921

Added:
    trunk/sandy/as3/trunk/src/sandy/view/BasicView.as   (contents, props  
changed)
Modified:
    trunk/sandy/as3/trunk/src/sandy/core/Renderer.as
    trunk/sandy/as3/trunk/src/sandy/core/data/Polygon.as
    trunk/sandy/as3/trunk/src/sandy/materials/BitmapMaterial.as
    trunk/sandy/as3/trunk/src/sandy/materials/Material.as

Log:
Bug fix with Cache system and moviematerial.
Addition of a new util class, BasicView which simplify the Sandy scene  
setup.

Modified: trunk/sandy/as3/trunk/src/sandy/core/Renderer.as
==============================================================================
--- trunk/sandy/as3/trunk/src/sandy/core/Renderer.as	(original)
+++ trunk/sandy/as3/trunk/src/sandy/core/Renderer.as	Mon Feb 23 13:53:09  
2009
@@ -1 +1 @@
-
package sandy.core
{
	import flash.display.Sprite;
	
	import sandy.core.data.Matrix4;
	import sandy.core.data.Point3D;
	import sandy.core.data.Polygon;
	import sandy.core.data.Pool;
	import sandy.core.data.Vertex;
	import sandy.core.scenegraph.Camera3D;
	import sandy.core.scenegraph.IDisplayable;
	import sandy.core.scenegraph.Renderable;
	import sandy.core.scenegraph.Shape3D;
	import sandy.core.scenegraph.Sprite2D;
	import sandy.view.CullingState;
	import sandy.view.Frustum;

	/**
	 * @author thomas
	 */
	public class Renderer
	{
		protected const m_aDisplayList:Array = new Array();
		protected var m_nDisplayListCount:int;
		protected var m_aCamera:Camera3D;
		
		protected const m_aRenderingList:Array = new Array();
		protected var m_nRenderingListCount:int;
		private var pool:Pool = new Pool();
		
		private var m_bGlobalRedraw:Boolean;
		
		/**
		 * Default renderer.
		 */
		public function Renderer()
		{
			m_nRenderingListCount = 0;
			m_nDisplayListCount = 0;
		}

		/**
		 * Init the renderer internal data
		 */
		public function init():void
		{
			m_nDisplayListCount = 0;
			m_bGlobalRedraw = false;
		}
		
		/**
		 * Process the rendering of the scene.
		 * The camera has all the information needed about the objects to render.
		 *
		 * The camera stores all the visible shape/polygons into an array, and  
loop through it calling their display method.
		 * Before the display call, the container graphics is cleared.
		 *
		 * @param p_oScene The Scene3D object to render
		 */
		public function renderDisplayList( p_oScene:Scene3D ):void
		{
			const l_mcContainer:Sprite = p_oScene.container;
		    // --
		    m_aRenderingList.sortOn( "depth", Array.NUMERIC | Array.DESCENDING );
		    // -- This is the new list to be displayed.
			var l_oFace:IDisplayable;
			for( var i:int = 0; i < m_nRenderingListCount; i++ )
			{
				l_oFace = m_aRenderingList[int(i)];				
				if( l_oFace.changed || ((l_oFace.material !=  
null)?l_oFace.material.modified:false) || p_oScene.camera.changed )
				{
					l_oFace.display();
				}
				// --
				if( i < l_mcContainer.numChildren )
				{
					if( l_mcContainer.getChildAt(i) != l_oFace.container )
					{
						l_mcContainer.addChildAt( l_oFace.container, i );
					}
				}
				else
				{
					l_mcContainer.addChildAt( l_oFace.container, i );
				}
			}
		}
		
		public function addToDisplayList( p_oObject:IDisplayable ):void
		{
			m_aDisplayList[m_nDisplayListCount++] = p_oObject;
			m_bGlobalRedraw = m_bGlobalRedraw || p_oObject.changed ||  
((p_oObject.material != null)?p_oObject.material.modified:false);
		}
			
		/**
		 * Render the given scene.
		 * Objects are transformed, clipped and projected into that function.
		 *
		 * @param p_bUseCache Boolean value, default to true, use a cache system  
to avoid unnecessary computation
		 */
		public function render( p_oScene:Scene3D, p_bUseCache:Boolean = true  
):Boolean
		{
			var 	m11:Number, m21:Number, m31:Number,
					m12:Number, m22:Number, m32:Number,
					m13:Number, m23:Number, m33:Number,
					m14:Number, m24:Number, m34:Number,
					x:Number, y:Number, z:Number;
			var		l_oCamera:Camera3D = p_oScene.camera;		
			var  	l_nZNear:Number = l_oCamera.near, l_oCamPos:Point3D =  
pool.nextPoint3D, l_nPolyFlags:uint = 0,
	        		l_oMatrix:Matrix4, l_oFrustum:Frustum = l_oCamera.frustrum,
					l_oVertex:Vertex, l_aVertices:Array, l_oFace:Polygon, l_nMinZ:Number,  
l_nFlags:int;
			var 	l_nVisiblePolyCount:int = 0, i:int;
		
			var l_bForceRedraw:Boolean = p_oScene.camera.changed || !p_bUseCache;
			
			// -- return false because we do not even need to refresh display
			if( m_bGlobalRedraw == false && l_bForceRedraw == false )
				return false;
				
			// -- Note, this is the displayed list from the previous iteration!
			for each( var l_oObj:IDisplayable in m_aRenderingList )
			{
				if( l_oObj )
				{
					if( l_bForceRedraw == true || ((l_oObj.material !=  
null)?l_oObj.material.modified:false) || l_oObj.changed == true )
					{
						l_oObj.clear();
					}
				}
			}
				
			// --
			m_nRenderingListCount = 0;
			m_aRenderingList.length = 0;
			// --
			for( i = 0; i < m_nDisplayListCount; i ++ )
			{
				if( m_aDisplayList[int(i)] is Shape3D )
				{
					var l_oShape:Shape3D = m_aDisplayList[int(i)] as Shape3D;
					// if no change for that object, directly go to the draw level
					if( l_oShape.changed == false && l_bForceRedraw == false )
					{
						if( l_oShape.useSingleContainer )
							m_aRenderingList[int(m_nRenderingListCount++)] = l_oShape;
						else
						{
							for each( l_oFace in l_oShape.aVisiblePolygons )
								m_aRenderingList[int(m_nRenderingListCount++)] = l_oFace;
						}
						continue;
					}
					// --
					l_nFlags = l_oShape.appearance.flags;
					l_oShape.depth = 0;
					l_oShape.aVisiblePolygons.length = 0;
					l_oCamPos.reset(l_oCamera.modelMatrix.n14, l_oCamera.modelMatrix.n24,  
l_oCamera.modelMatrix.n34);
					l_oShape.invModelMatrix.transform( l_oCamPos );
					// --
					l_oMatrix = l_oShape.viewMatrix;
					m11 = l_oMatrix.n11; m21 = l_oMatrix.n21; m31 = l_oMatrix.n31;
					m12 = l_oMatrix.n12; m22 = l_oMatrix.n22; m32 = l_oMatrix.n32;
					m13 = l_oMatrix.n13; m23 = l_oMatrix.n23; m33 = l_oMatrix.n33;
					m14 = l_oMatrix.n14; m24 = l_oMatrix.n24; m34 = l_oMatrix.n34;
					// --
					var l_bClipped:Boolean = ((l_oShape.culled == CullingState.INTERSECT)  
&& ( l_oShape.enableClipping || l_oShape.enableNearClipping ));
					// --
					for each( l_oVertex in l_oShape.geometry.aVertex )
					{
						l_oVertex.projected = l_oVertex.transformed = false;
					}
					// --
					for each( l_oFace in l_oShape.aPolygons )
		            {
						if( l_oShape.animated )
							l_oFace.updateNormal();
		                // -- visibility test
		                l_oVertex = l_oFace.normal;
		                x = l_oFace.a.x; y = l_oFace.a.y; z = l_oFace.a.z;
			            l_oFace.visible = (l_oVertex.x*( l_oCamPos.x - x) +  
l_oVertex.y*( l_oCamPos.y - y) + l_oVertex.z*( l_oCamPos.z - z)) > 0;
			            // --
		                if( l_oShape.enableBackFaceCulling )
		                {
			                if( l_oFace.visible == false )
			                	continue;
		                }
		                // --
		                l_oVertex = l_oFace.a;
		                if( l_oVertex.transformed == false )// (l_oVertex.flags &  
SandyFlags.VERTEX_CAMERA) == 0)
		                {
							l_oVertex.wx = (x) * m11 + (y) * m12 + (z) * m13 + m14;
							l_oVertex.wy = x * m21 + y * m22 + z * m23 + m24;
							l_oVertex.wz = x * m31 + y * m32 + z * m33 + m34;
							//l_oVertex.flags |= SandyFlags.VERTEX_CAMERA;
							l_oVertex.transformed = true;
						}
						
						l_oVertex = l_oFace.b;
						if( l_oVertex.transformed == false )// (l_oVertex.flags &  
SandyFlags.VERTEX_CAMERA) == 0)
		                {
							l_oVertex.wx = (x=l_oVertex.x) * m11 + (y=l_oVertex.y) * m12 +  
(z=l_oVertex.z) * m13 + m14;
							l_oVertex.wy = x * m21 + y * m22 + z * m23 + m24;
							l_oVertex.wz = x * m31 + y * m32 + z * m33 + m34;
							//l_oVertex.flags |= SandyFlags.VERTEX_CAMERA;
							l_oVertex.transformed = true;
		                }
		          						
						l_oVertex = l_oFace.c;
						if( l_oVertex )
		                {
							if( l_oVertex.transformed == false )//(l_oVertex.flags &  
SandyFlags.VERTEX_CAMERA) == 0)
			                {
								l_oVertex.wx = (x=l_oVertex.x) * m11 + (y=l_oVertex.y) * m12 +  
(z=l_oVertex.z) * m13 + m14;
								l_oVertex.wy = x * m21 + y * m22 + z * m23 + m24;
								l_oVertex.wz = x * m31 + y * m32 + z * m33 + m34;
								//l_oVertex.flags |= SandyFlags.VERTEX_CAMERA;
								l_oVertex.transformed = true;
			                }
		                }

		                l_oVertex = l_oFace.d;
						if( l_oVertex )
		                {
							if( l_oVertex.transformed == false )
							{
								l_oVertex.wx = (x=l_oVertex.x) * m11 + (y=l_oVertex.y) * m12 +  
(z=l_oVertex.z) * m13 + m14;
								l_oVertex.wy = x * m21 + y * m22 + z * m23 + m24;
								l_oVertex.wz = x * m31 + y * m32 + z * m33 + m34;
								l_oVertex.transformed = true;
							}
		                }

		                // --               	
						l_oFace.precompute();
		                l_nMinZ = l_oFace.minZ;
		                // -- culling/clipping phasis
		                if( l_bClipped )
		                {
		                	if( l_oShape.enableClipping ) // NEED COMPLETE CLIPPING
							{
								l_oFace.clip( l_oFrustum );
							}
							else if( l_oShape.enableNearClipping && l_nMinZ < l_nZNear ) //  
PARTIALLY VISIBLE
							{
								l_oFace.clipFrontPlane( l_oFrustum );
							}
							else if( l_nMinZ < l_nZNear )
							{
								continue;
							}
		                }
		  				else if( l_nMinZ < l_nZNear )
						{
							continue;
						}
						// --
						l_aVertices = l_oFace.isClipped ? l_oFace.cvertices :  
l_oFace.vertices;
						if( l_aVertices.length > 1 )
						{
							l_oCamera.projectArray( l_aVertices );
							if(l_oShape.enableForcedDepth)
								l_oFace.depth = l_oShape.forcedDepth;
							else
								l_oShape.depth += l_oFace.depth;
							// --
							l_nVisiblePolyCount++;
							l_oShape.aVisiblePolygons[int(l_oShape.aVisiblePolygons.length)] =  
l_oFace;
							// --
							l_nPolyFlags |= l_nFlags;
							// --
							if( l_oShape.useSingleContainer == false )
								m_aRenderingList[int(m_nRenderingListCount++)] = l_oFace;
						}
					}
					// --
					if( l_oShape.aVisiblePolygons.length > 0 )
					{
						if( l_oShape.useSingleContainer == true )
						{
							if(l_oShape.enableForcedDepth)
								l_oShape.depth = l_oShape.forcedDepth;
							else
								l_oShape.depth /= l_oShape.aVisiblePolygons.length;
							// --
							m_aRenderingList[int(m_nRenderingListCount++)] = l_oShape;
						}
						// --
						if( l_nFlags != 0 || l_nPolyFlags != 0 )
						{
							if( (l_nFlags | l_nPolyFlags) & SandyFlags.POLYGON_NORMAL_WORLD )
				            {
				            	l_oMatrix = l_oShape.modelMatrix;
				           		m11 = l_oMatrix.n11; m21 = l_oMatrix.n21; m31 =  
l_oMatrix.n31;
				            	m12 = l_oMatrix.n12; m22 = l_oMatrix.n22; m32 =  
l_oMatrix.n32;
				            	m13 = l_oMatrix.n13; m23 = l_oMatrix.n23; m33 =  
l_oMatrix.n33;
				                // -- Now we transform the normals.
				                for each( l_oFace in l_oShape.aVisiblePolygons )
								{
				                    l_oVertex = l_oFace.normal;
				                    l_oVertex.wx  = (x=l_oVertex.x) * m11 +  
(y=l_oVertex.y) * m12 + (z=l_oVertex.z) * m13;
				                    l_oVertex.wy  = x * m21 + y * m22 + z * m23;
				                    l_oVertex.wz  = x * m31 + y * m32 + z * m33;
				                }
				            }
				            if( (l_nFlags | l_nPolyFlags) &  
SandyFlags.VERTEX_NORMAL_WORLD )
				            {
				            	l_oMatrix = l_oShape.modelMatrix;
				           		m11 = l_oMatrix.n11; m21 = l_oMatrix.n21; m31 =  
l_oMatrix.n31;
				            	m12 = l_oMatrix.n12; m22 = l_oMatrix.n22; m32 =  
l_oMatrix.n32;
				            	m13 = l_oMatrix.n13; m23 = l_oMatrix.n23; m33 =  
l_oMatrix.n33;
				                // -- Now we transform the normals.
				                for each( l_oVertex in l_oShape.geometry.aVertexNormals  
)
				                {
				                    l_oVertex.wx  = (x=l_oVertex.x) * m11 +  
(y=l_oVertex.y) * m12 + (z=l_oVertex.z) * m13;
				                    l_oVertex.wy  = x * m21 + y * m22 + z * m23;
				                    l_oVertex.wz  = x * m31 + y * m32 + z * m33;
				                }
				            }
						}
					}
				}
				else if( m_aDisplayList[int(i)] is Sprite2D )
				{
					var l_oSprite2D:Sprite2D = m_aDisplayList[int(i)] as Sprite2D;
					l_oSprite2D.v.projected = false;
					l_oSprite2D.vx.projected = false;
					l_oSprite2D.vy.projected = false;
					
					l_oVertex = l_oSprite2D.v;
					l_oMatrix = l_oSprite2D.viewMatrix;
					l_oVertex.wx = l_oVertex.x * l_oMatrix.n11 + l_oVertex.y *  
l_oMatrix.n12 + l_oVertex.z * l_oMatrix.n13 + l_oMatrix.n14;
					l_oVertex.wy = l_oVertex.x * l_oMatrix.n21 + l_oVertex.y *  
l_oMatrix.n22 + l_oVertex.z * l_oMatrix.n23 + l_oMatrix.n24;
					l_oVertex.wz = l_oVertex.x * l_oMatrix.n31 + l_oVertex.y *  
l_oMatrix.n32 + l_oVertex.z * l_oMatrix.n33 + l_oMatrix.n34;
		
					l_oSprite2D.depth = l_oSprite2D.enableForcedDepth ?  
l_oSprite2D.forcedDepth : l_oVertex.wz;
		
					l_oCamera.projectVertex( l_oVertex );
					m_aRenderingList[int(m_nRenderingListCount++)] = l_oSprite2D;
		
					l_oSprite2D.vx.copy (l_oVertex); l_oSprite2D.vx.wx++;  
l_oCamera.projectVertex (l_oSprite2D.vx);
					l_oSprite2D.vy.copy (l_oVertex); l_oSprite2D.vy.wy++;  
l_oCamera.projectVertex (l_oSprite2D.vy);
				}
				else if( m_aDisplayList[int(i)] is Renderable )
				{
					(m_aDisplayList[int(i)] as Renderable).render(l_oCamera);
					m_aRenderingList[int(m_nRenderingListCount++)] =  
m_aDisplayList[int(i)] as Renderable;
				}
			}
			// true because need need to refresh display
			return true;
		}
	}
}
\ No newline at end of file
+
package sandy.core
{
	import flash.display.Sprite;
	
	import sandy.core.data.Matrix4;
	import sandy.core.data.Point3D;
	import sandy.core.data.Polygon;
	import sandy.core.data.Pool;
	import sandy.core.data.Vertex;
	import sandy.core.scenegraph.Camera3D;
	import sandy.core.scenegraph.IDisplayable;
	import sandy.core.scenegraph.Renderable;
	import sandy.core.scenegraph.Shape3D;
	import sandy.core.scenegraph.Sprite2D;
	import sandy.view.CullingState;
	import sandy.view.Frustum;

	/**
	 * @author thomas
	 */
	public class Renderer
	{
		protected const m_aDisplayList:Array = new Array();
		protected var m_nDisplayListCount:int;
		protected var m_aCamera:Camera3D;
		
		protected const m_aRenderingList:Array = new Array();
		protected var m_nRenderingListCount:int;
		private var pool:Pool = new Pool();
		
		private var m_bGlobalRedraw:Boolean;
		
		/**
		 * Default renderer.
		 */
		public function Renderer()
		{
			m_nRenderingListCount = 0;
			m_nDisplayListCount = 0;
		}

		/**
		 * Init the renderer internal data
		 */
		public function init():void
		{
			m_nDisplayListCount = 0;
			m_bGlobalRedraw = false;
		}
		
		/**
		 * Process the rendering of the scene.
		 * The camera has all the information needed about the objects to render.
		 *
		 * The camera stores all the visible shape/polygons into an array, and  
loop through it calling their display method.
		 * Before the display call, the container graphics is cleared.
		 *
		 * @param p_oScene The Scene3D object to render
		 */
		public function renderDisplayList( p_oScene:Scene3D ):void
		{
			const l_mcContainer:Sprite = p_oScene.container;
		    // --
		    m_aRenderingList.sortOn( "depth", Array.NUMERIC | Array.DESCENDING );
		    // -- This is the new list to be displayed.
			var l_oFace:IDisplayable;
			for( var i:int = 0; i < m_nRenderingListCount; i++ )
			{
				l_oFace = m_aRenderingList[int(i)];				
				if( l_oFace.changed || ((l_oFace.material !=  
null)?l_oFace.material.modified:false) || p_oScene.camera.changed )
				{
					l_oFace.display();
				}
				// --
				if( i < l_mcContainer.numChildren )
				{
					if( l_mcContainer.getChildAt(i) != l_oFace.container )
					{
						l_mcContainer.addChildAt( l_oFace.container, i );
					}
				}
				else
				{
					l_mcContainer.addChildAt( l_oFace.container, i );
				}
			}
		}
		
		public function addToDisplayList( p_oObject:IDisplayable ):void
		{
			m_aDisplayList[m_nDisplayListCount++] = p_oObject;
			m_bGlobalRedraw = m_bGlobalRedraw || p_oObject.changed ||  
((p_oObject.material != null)?p_oObject.material.modified:false);
		}
			
		/**
		 * Render the given scene.
		 * Objects are transformed, clipped and projected into that function.
		 *
		 * @param p_bUseCache Boolean value, default to true, use a cache system  
to avoid unnecessary computation
		 */
		public function render( p_oScene:Scene3D, p_bUseCache:Boolean = true  
):Boolean
		{
			var 	m11:Number, m21:Number, m31:Number,
					m12:Number, m22:Number, m32:Number,
					m13:Number, m23:Number, m33:Number,
					m14:Number, m24:Number, m34:Number,
					x:Number, y:Number, z:Number;
			var		l_oCamera:Camera3D = p_oScene.camera;		
			var  	l_nZNear:Number = l_oCamera.near, l_oCamPos:Point3D =  
pool.nextPoint3D, l_nPolyFlags:uint = 0,
	        		l_oMatrix:Matrix4, l_oFrustum:Frustum = l_oCamera.frustrum,
					l_oVertex:Vertex, l_aVertices:Array, l_oFace:Polygon, l_nMinZ:Number,  
l_nFlags:int;
			var 	l_nVisiblePolyCount:int = 0, i:int;
		
			var l_bForceRedraw:Boolean = p_oScene.camera.changed || !p_bUseCache;
			
			// -- return false because we do not even need to refresh display
			if( m_bGlobalRedraw == false && l_bForceRedraw == false )
				return false;
				
			// -- Note, this is the displayed list from the previous iteration!
			for each( var l_oObj:IDisplayable in m_aRenderingList )
			{
				if( l_oObj )
				{
					if( l_bForceRedraw == true || ((l_oObj.material !=  
null)?l_oObj.material.modified:false) || l_oObj.changed == true )
					{
						l_oObj.clear();
					}
				}
			}
			// --
			m_nRenderingListCount = 0;
			m_aRenderingList.length = 0;
			// --
			for( i = 0; i < m_nDisplayListCount; i ++ )
			{
				if( m_aDisplayList[int(i)] is Shape3D )
				{
					var l_oShape:Shape3D = m_aDisplayList[int(i)] as Shape3D;
					// if no change for that object, directly go to the draw level
					if( l_oShape.changed == false && l_bForceRedraw == false )
					{
						if( l_oShape.useSingleContainer )
							m_aRenderingList[int(m_nRenderingListCount++)] = l_oShape;
						else
						{
							for each( l_oFace in l_oShape.aVisiblePolygons )
								m_aRenderingList[int(m_nRenderingListCount++)] = l_oFace;
						}
						continue;
					}
					// --
					l_nFlags = l_oShape.appearance.flags;
					l_oShape.depth = 0;
					l_oShape.aVisiblePolygons.length = 0;
					l_oCamPos.reset(l_oCamera.modelMatrix.n14, l_oCamera.modelMatrix.n24,  
l_oCamera.modelMatrix.n34);
					l_oShape.invModelMatrix.transform( l_oCamPos );
					// --
					l_oMatrix = l_oShape.viewMatrix;
					m11 = l_oMatrix.n11; m21 = l_oMatrix.n21; m31 = l_oMatrix.n31;
					m12 = l_oMatrix.n12; m22 = l_oMatrix.n22; m32 = l_oMatrix.n32;
					m13 = l_oMatrix.n13; m23 = l_oMatrix.n23; m33 = l_oMatrix.n33;
					m14 = l_oMatrix.n14; m24 = l_oMatrix.n24; m34 = l_oMatrix.n34;
					// --
					var l_bClipped:Boolean = ((l_oShape.culled == CullingState.INTERSECT)  
&& ( l_oShape.enableClipping || l_oShape.enableNearClipping ));
					// --
					for each( l_oVertex in l_oShape.geometry.aVertex )
					{
						l_oVertex.projected = l_oVertex.transformed = false;
					}
					// --
					for each( l_oFace in l_oShape.aPolygons )
		            {
						if( l_oShape.animated )
							l_oFace.updateNormal();
		                // -- visibility test
		                l_oVertex = l_oFace.normal;
		                x = l_oFace.a.x; y = l_oFace.a.y; z = l_oFace.a.z;
			            l_oFace.visible = (l_oVertex.x*( l_oCamPos.x - x) +  
l_oVertex.y*( l_oCamPos.y - y) + l_oVertex.z*( l_oCamPos.z - z)) > 0;
			            // --
		                if( l_oShape.enableBackFaceCulling )
		                {
			                if( l_oFace.visible == false )
			                	continue;
		                }
		                // --
		                l_oVertex = l_oFace.a;
		                if( l_oVertex.transformed == false )// (l_oVertex.flags &  
SandyFlags.VERTEX_CAMERA) == 0)
		                {
							l_oVertex.wx = (x) * m11 + (y) * m12 + (z) * m13 + m14;
							l_oVertex.wy = x * m21 + y * m22 + z * m23 + m24;
							l_oVertex.wz = x * m31 + y * m32 + z * m33 + m34;
							//l_oVertex.flags |= SandyFlags.VERTEX_CAMERA;
							l_oVertex.transformed = true;
						}
						
						l_oVertex = l_oFace.b;
						if( l_oVertex.transformed == false )// (l_oVertex.flags &  
SandyFlags.VERTEX_CAMERA) == 0)
		                {
							l_oVertex.wx = (x=l_oVertex.x) * m11 + (y=l_oVertex.y) * m12 +  
(z=l_oVertex.z) * m13 + m14;
							l_oVertex.wy = x * m21 + y * m22 + z * m23 + m24;
							l_oVertex.wz = x * m31 + y * m32 + z * m33 + m34;
							//l_oVertex.flags |= SandyFlags.VERTEX_CAMERA;
							l_oVertex.transformed = true;
		                }
		          						
						l_oVertex = l_oFace.c;
						if( l_oVertex )
		                {
							if( l_oVertex.transformed == false )//(l_oVertex.flags &  
SandyFlags.VERTEX_CAMERA) == 0)
			                {
								l_oVertex.wx = (x=l_oVertex.x) * m11 + (y=l_oVertex.y) * m12 +  
(z=l_oVertex.z) * m13 + m14;
								l_oVertex.wy = x * m21 + y * m22 + z * m23 + m24;
								l_oVertex.wz = x * m31 + y * m32 + z * m33 + m34;
								//l_oVertex.flags |= SandyFlags.VERTEX_CAMERA;
								l_oVertex.transformed = true;
			                }
		                }

		                l_oVertex = l_oFace.d;
						if( l_oVertex )
		                {
							if( l_oVertex.transformed == false )
							{
								l_oVertex.wx = (x=l_oVertex.x) * m11 + (y=l_oVertex.y) * m12 +  
(z=l_oVertex.z) * m13 + m14;
								l_oVertex.wy = x * m21 + y * m22 + z * m23 + m24;
								l_oVertex.wz = x * m31 + y * m32 + z * m33 + m34;
								l_oVertex.transformed = true;
							}
		                }

		                // --               	
						l_oFace.precompute();
		                l_nMinZ = l_oFace.minZ;
		                // -- culling/clipping phasis
		                if( l_bClipped )
		                {
		                	if( l_oShape.enableClipping ) // NEED COMPLETE CLIPPING
							{
								l_oFace.clip( l_oFrustum );
							}
							else if( l_oShape.enableNearClipping && l_nMinZ < l_nZNear ) //  
PARTIALLY VISIBLE
							{
								l_oFace.clipFrontPlane( l_oFrustum );
							}
							else if( l_nMinZ < l_nZNear )
							{
								continue;
							}
		                }
		  				else if( l_nMinZ < l_nZNear )
						{
							continue;
						}
						// --
						l_aVertices = l_oFace.isClipped ? l_oFace.cvertices :  
l_oFace.vertices;
						if( l_aVertices.length > 1 )
						{
							l_oCamera.projectArray( l_aVertices );
							if(l_oShape.enableForcedDepth)
								l_oFace.depth = l_oShape.forcedDepth;
							else
								l_oShape.depth += l_oFace.depth;
							// --
							l_nVisiblePolyCount++;
							l_oShape.aVisiblePolygons[int(l_oShape.aVisiblePolygons.length)] =  
l_oFace;
							// --
							l_nPolyFlags |= l_nFlags;
							// --
							if( l_oShape.useSingleContainer == false )
								m_aRenderingList[int(m_nRenderingListCount++)] = l_oFace;
						}
					}
					// --
					if( l_oShape.aVisiblePolygons.length > 0 )
					{
						if( l_oShape.useSingleContainer == true )
						{
							if(l_oShape.enableForcedDepth)
								l_oShape.depth = l_oShape.forcedDepth;
							else
								l_oShape.depth /= l_oShape.aVisiblePolygons.length;
							// --
							m_aRenderingList[int(m_nRenderingListCount++)] = l_oShape;
						}
						// --
						if( l_nFlags != 0 || l_nPolyFlags != 0 )
						{
							if( (l_nFlags | l_nPolyFlags) & SandyFlags.POLYGON_NORMAL_WORLD )
				            {
				            	l_oMatrix = l_oShape.modelMatrix;
				           		m11 = l_oMatrix.n11; m21 = l_oMatrix.n21; m31 =  
l_oMatrix.n31;
				            	m12 = l_oMatrix.n12; m22 = l_oMatrix.n22; m32 =  
l_oMatrix.n32;
				            	m13 = l_oMatrix.n13; m23 = l_oMatrix.n23; m33 =  
l_oMatrix.n33;
				                // -- Now we transform the normals.
				                for each( l_oFace in l_oShape.aVisiblePolygons )
								{
				                    l_oVertex = l_oFace.normal;
				                    l_oVertex.wx  = (x=l_oVertex.x) * m11 +  
(y=l_oVertex.y) * m12 + (z=l_oVertex.z) * m13;
				                    l_oVertex.wy  = x * m21 + y * m22 + z * m23;
				                    l_oVertex.wz  = x * m31 + y * m32 + z * m33;
				                }
				            }
				            if( (l_nFlags | l_nPolyFlags) &  
SandyFlags.VERTEX_NORMAL_WORLD )
				            {
				            	l_oMatrix = l_oShape.modelMatrix;
				           		m11 = l_oMatrix.n11; m21 = l_oMatrix.n21; m31 =  
l_oMatrix.n31;
				            	m12 = l_oMatrix.n12; m22 = l_oMatrix.n22; m32 =  
l_oMatrix.n32;
				            	m13 = l_oMatrix.n13; m23 = l_oMatrix.n23; m33 =  
l_oMatrix.n33;
				                // -- Now we transform the normals.
				                for each( l_oVertex in l_oShape.geometry.aVertexNormals  
)
				                {
				                    l_oVertex.wx  = (x=l_oVertex.x) * m11 +  
(y=l_oVertex.y) * m12 + (z=l_oVertex.z) * m13;
				                    l_oVertex.wy  = x * m21 + y * m22 + z * m23;
				                    l_oVertex.wz  = x * m31 + y * m32 + z * m33;
				                }
				            }
						}
					}
				}
				else if( m_aDisplayList[int(i)] is Sprite2D )
				{
					var l_oSprite2D:Sprite2D = m_aDisplayList[int(i)] as Sprite2D;
					l_oSprite2D.v.projected = false;
					l_oSprite2D.vx.projected = false;
					l_oSprite2D.vy.projected = false;
					
					l_oVertex = l_oSprite2D.v;
					l_oMatrix = l_oSprite2D.viewMatrix;
					l_oVertex.wx = l_oVertex.x * l_oMatrix.n11 + l_oVertex.y *  
l_oMatrix.n12 + l_oVertex.z * l_oMatrix.n13 + l_oMatrix.n14;
					l_oVertex.wy = l_oVertex.x * l_oMatrix.n21 + l_oVertex.y *  
l_oMatrix.n22 + l_oVertex.z * l_oMatrix.n23 + l_oMatrix.n24;
					l_oVertex.wz = l_oVertex.x * l_oMatrix.n31 + l_oVertex.y *  
l_oMatrix.n32 + l_oVertex.z * l_oMatrix.n33 + l_oMatrix.n34;
		
					l_oSprite2D.depth = l_oSprite2D.enableForcedDepth ?  
l_oSprite2D.forcedDepth : l_oVertex.wz;
		
					l_oCamera.projectVertex( l_oVertex );
					m_aRenderingList[int(m_nRenderingListCount++)] = l_oSprite2D;
		
					l_oSprite2D.vx.copy (l_oVertex); l_oSprite2D.vx.wx++;  
l_oCamera.projectVertex (l_oSprite2D.vx);
					l_oSprite2D.vy.copy (l_oVertex); l_oSprite2D.vy.wy++;  
l_oCamera.projectVertex (l_oSprite2D.vy);
				}
				else if( m_aDisplayList[int(i)] is Renderable )
				{
					(m_aDisplayList[int(i)] as Renderable).render(l_oCamera);
					m_aRenderingList[int(m_nRenderingListCount++)] =  
m_aDisplayList[int(i)] as Renderable;
				}
			}
			// true because need need to refresh display
			return true;
		}
	}
}
\ No newline at end of file

Modified: trunk/sandy/as3/trunk/src/sandy/core/data/Polygon.as
==============================================================================
--- trunk/sandy/as3/trunk/src/sandy/core/data/Polygon.as	(original)
+++ trunk/sandy/as3/trunk/src/sandy/core/data/Polygon.as	Mon Feb 23  
13:53:09 2009
@@ -1 +1 @@
-
package sandy.core.data
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	
	import sandy.core.Scene3D;
	import sandy.core.interaction.VirtualMouse;
	import sandy.core.scenegraph.Geometry3D;
	import sandy.core.scenegraph.IDisplayable;
	import sandy.core.scenegraph.Shape3D;
	import sandy.events.BubbleEventBroadcaster;
	import sandy.events.SandyEvent;
	import sandy.events.Shape3DEvent;
	import sandy.materials.Appearance;
	import sandy.materials.Material;
	import sandy.math.IntersectionMath;
	import sandy.math.Point3DMath;
	import sandy.view.CullingState;
	import sandy.view.Frustum;

	/**
	 * Polygon's are the building blocks of visible 3D shapes.
	 *
	 * @author		Thomas Pfeiffer - kiroukou
	 * @author		Mirek Mencel
	 * @since		1.0
	 * @version		3.1
	 * @date 		24.08.2007
	 *
	 * @see sandy.core.scenegraph.Shape3D
	 */
	public final class Polygon implements IDisplayable
	{
	// _______
	// STATICS_______________________________________________________
		private static var _ID_:uint = 0;
		
		/**
		 * This property lists all the polygons.
		 * This is a helper property since it allows all polygons of a scene to  
be retrieved from a single list by its unique identifier.
		 * A polygon's unique identifier can be retrieved useing  
<code>myPolygon.id</code>.
		 *
		 * @example The examples below shows how to retrieve a ploygon from this  
property.
		 * <listing version="3.1">
		 * var p:Polygon = Polygon.POLYGON_MAP[myPolygon.id];
		 * </listing>
		 */
		public static var POLYGON_MAP:Dictionary = new Dictionary(true);
	// ______
	// PUBLIC________________________________________________________
		/**
		 * The unique identifier for this polygon.
		 */
		public const id:uint = _ID_++;

		/**
		 * A reference to the Shape3D object this polygon belongs to.
		 */
		public var shape:Shape3D;
				
		/**
		 * Specifies if the polygon has been clipped.
		 */
		public var isClipped:Boolean = false;
		
		/**
		 * An array of clipped vertices. Check the <code>isClipped</code>  
property first to see if this array will contain the useful data.
		 */
		public var cvertices:Array;
		
		/**
		 * An array of the polygon's original vertices.
		 */
		public var vertices:Array;
		
		/**
		 * An array of the polygon's vertex normals.
		 */
		public var vertexNormals:Array;
		
		public var aUVCoord:Array;

		/**
		 * An array of the polygon's edges.
		 */
		public var aEdges:Array;

		public var caUVCoord:Array;

		/**
		 * The texture bounds.
		 */
		public var uvBounds:Rectangle;
		
		/**
		 * An array of polygons that share an edge with this polygon.
		 */
		public var aNeighboors:Array = new Array();

		/**
		 * Specifies whether the face of the polygon is visible.
		 */
		public var visible:Boolean;
		
		/**
		 * Minimum depth value of that polygon in the camera space
		 */
		public var minZ:Number;
		
		
		public var a:Vertex, b:Vertex, c:Vertex, d:Vertex;
		
		/**
		 * Creates a new polygon.
		 *
		 * @param p_oShape			The shape the polygon belongs to.
		 * @param p_geometry		The geometry the polygon belongs to.
		 * @param p_aVertexID		An array of verticies of the polygon.
		 * @param p_aUVCoordsID		An array of UV coordinates of this polygon.
		 * @param p_nFaceNormalID	The faceNormalID of this polygon.
		 * @param p_nEdgesID		The edgesID of this polygon.
		 */
		public function Polygon( p_oOwner:Shape3D, p_geometry:Geometry3D,  
p_aVertexID:Array, p_aUVCoordsID:Array=null, p_nFaceNormalID:Number=0,  
p_nEdgesID:uint=0 )
		{
			shape = p_oOwner;
			m_oGeometry = p_geometry;
			// --
			__update( p_aVertexID, p_aUVCoordsID, p_nFaceNormalID, p_nEdgesID );
			m_oContainer = new Sprite();
			// --
			POLYGON_MAP[id] = this;
			m_oEB = new BubbleEventBroadcaster(this);
		}

		public function get changed():Boolean
		{
			return shape.changed;
		}
		
		/**
		 * A reference to the Scene3D object this polygon is in.
		 */
		public function set scene(p_oScene:Scene3D):void
		{
			if( p_oScene == null ) return;
			if( scene != null )
			{
				scene.removeEventListener(SandyEvent.SCENE_RENDER_FINISH,  
_finishMaterial );
				scene.removeEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST,  
_beginMaterial );
			}
			// --
			m_oScene = p_oScene;
			// --
			scene.addEventListener(SandyEvent.SCENE_RENDER_FINISH, _finishMaterial );
			scene.addEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST,  
_beginMaterial );
		}
		
		public function get scene():Scene3D
		{
			return m_oScene;
		}
		private var m_oScene:Scene3D = null;
		
		/**
		 * Updates the vertices and normals for this polygon.
		 *
		 * <p>Calling this method make the polygon gets its vertice and normals  
by reference
		 * instead of accessing them by their ID.<br/>
		 * This method shall be called once the geometry created.</p>
		 *
		 * @param p_aVertexID		The vertexID array of this polygon
		 * @param p_aUVCoordsID		The UVCoordsID array of this polygon
		 * @param p_nFaceNormalID	The faceNormalID of this polygon
		 * @param p_nEdgesID		The edgesID of this polygon
		 */
		private function __update( p_aVertexID:Array, p_aUVCoordsID:Array,  
p_nFaceNormalID:uint, p_nEdgeListID:uint ):void
		{
			var i:int=0;
			// --
			vertexNormals = new Array();
			vertices = new Array();
			for each( var o:* in p_aVertexID )
			{
				vertices[i] = Vertex( m_oGeometry.aVertex[ p_aVertexID[i] ] );
				vertexNormals[i] = m_oGeometry.aVertexNormals[ p_aVertexID[i] ];
				i++;
			}
			// --
			a = vertices[0];
			b = vertices[1];
			c = vertices[2];
			d = vertices[3];
			// -- every polygon does not have some texture coordinates
			if( p_aUVCoordsID )
			{
				var l_nMinU:Number = Number.POSITIVE_INFINITY, l_nMinV:Number =  
Number.POSITIVE_INFINITY,
									l_nMaxU:Number = Number.NEGATIVE_INFINITY, l_nMaxV:Number =  
Number.NEGATIVE_INFINITY;
				// --
				aUVCoord = new Array();
				i = 0;
				if( p_aUVCoordsID )
				{
					for each( var p:* in p_aUVCoordsID )
					{
						var l_oUV:UVCoord = ( m_oGeometry.aUVCoords[ p_aUVCoordsID[i] ] as  
UVCoord);
						if( l_oUV == null ) l_oUV = new UVCoord(0,0);
						// --
						aUVCoord[i] = l_oUV;
						if( l_oUV.u < l_nMinU ) l_nMinU = l_oUV.u;
						else if( l_oUV.u > l_nMaxU ) l_nMaxU = l_oUV.u;
						// --
						if( l_oUV.v < l_nMinV ) l_nMinV = l_oUV.v;
						else if( l_oUV.v > l_nMaxV ) l_nMaxV = l_oUV.v;
						// --
						i++;
					}
					// --
					uvBounds = new Rectangle( l_nMinU, l_nMinV, l_nMaxU-l_nMinU,  
l_nMaxV-l_nMinV );
				}
				else
				{
					aUVCoord = [new UVCoord(), new UVCoord(), new UVCoord()];
					uvBounds = new Rectangle(0,0,0,0);
				}
			}
			// --
			m_nNormalId = p_nFaceNormalID;
			normal = Vertex( m_oGeometry.aFacesNormals[ p_nFaceNormalID ] );
			// If no normal has been given, we create it ourself.
			if( normal == null )
			{
				var l_oNormal:Point3D = createNormal();
				m_nNormalId = m_oGeometry.setFaceNormal(  
m_oGeometry.getNextFaceNormalID(), l_oNormal.x, l_oNormal.y, l_oNormal.z );
			}
			// --
			aEdges = new Array();
			for each( var l_nEdgeId:uint in  m_oGeometry.aFaceEdges[p_nEdgeListID] )
			{
				var l_oEdge:Edge3D = m_oGeometry.aEdges[ l_nEdgeId ];
				l_oEdge.vertex1 = m_oGeometry.aVertex[ l_oEdge.vertexId1 ];
				l_oEdge.vertex2 = m_oGeometry.aVertex[ l_oEdge.vertexId2 ];
				aEdges.push( l_oEdge );
			}
		}
		
		public function get normal():Vertex
		{
			return m_oGeometry.aFacesNormals[ m_nNormalId ];
		}
		
		public function set normal( p_oVertex:Vertex ):void
		{
			if( p_oVertex != null )
				m_oGeometry.aFacesNormals[ m_nNormalId ].copy( p_oVertex );
		}
		
		public function updateNormal():void
		{
			var x:Number = 	((a.y - b.y) * (c.z - b.z)) - ((a.z - b.z) * (c.y -  
b.y)) ;
			var y:Number =	((a.z - b.z) * (c.x - b.x)) - ((a.x - b.x) * (c.z -  
b.z)) ;
			var z:Number = 	((a.x - b.x) * (c.y - b.y)) - ((a.y - b.y) * (c.x -  
b.x)) ;
			normal.reset( x, y, z );
		}
		
		/**
		 * The depth of the polygon.
		 */
		public function get depth():Number
		{
			return m_nDepth;
		}
		
		/**
		 * @private
		 */
		public function set depth( p_nDepth:Number ):void
		{
			m_nDepth = p_nDepth;
		}
		
		/**
		 * The broadcaster of the polygon that sends events to listeners.
		 */
		public function get broadcaster():BubbleEventBroadcaster
		{
			return m_oEB;
		}

		/**
		 * Adds an event listener to the polygon.
		 *
		 * @param p_sEvent 	The name of the event to add.
		 * @param oL 		The listener object.
		 */
		public function addEventListener(p_sEvent:String, oL:*) : void
		{
			m_oEB.addEventListener.apply(m_oEB, arguments);
		}

		/**
		 * Removes an event listener to the polygon.
		 *
		 * @param p_sEvent 	The name of the event to remove.
		 * @param oL 		The listener object.
		 */
		public function removeEventListener(p_sEvent:String, oL:*) : void
		{
			m_oEB.removeEventListener(p_sEvent, oL);
		}

		/**
		 * Computes several properties of the polygon.
		 * <p>The computed properties are listed below:</p>
		 * <ul>
		 *  <li><code>visible</code></li>
		 *  <li><code>minZ</code></li>
		 *  <li><code>depth</code></li>
		 * </ul>
		 */
		public function precompute():void
		{
			isClipped = false;
			// --
			minZ = a.wz;
			if (b.wz < minZ) minZ = b.wz;
			m_nDepth = a.wz + b.wz;
			// --
			if (c != null)
			{
				if (c.wz < minZ) minZ = c.wz;
				m_nDepth += c.wz;
			}
			if (d != null)
			{
				if (d.wz < minZ) minZ = d.wz;
				m_nDepth += d.wz;
			}
			m_nDepth /= vertices.length;
		}
	
		/**
		 * Returns a Point3D (3D position) on the polygon relative to the  
specified point on the 2D screen.
		 *
		 * @example	Below is an example of how to get the 3D coordinate of the  
polygon under the position of the mouse:
		 * <listing version="3.1">
		 * var screenPoint:Point = new Point(myPolygon.container.mouseX,  
myPolygon.container.mouseY);
		 * var scenePosition:Point3D = myPolygon.get3DFrom2D(screenPoint);
          * </listing>
          *
          * @return A Point3D that corresponds to the specified point.
          */
		public function get3DFrom2D( p_oScreenPoint:Point ):Point3D
		{
     		/// NEW CODE ADDED BY MAX with the help of makc ///
			
			var m1:Matrix= new Matrix(
						vertices[1].sx-vertices[0].sx,
						vertices[2].sx-vertices[0].sx,
						vertices[1].sy-vertices[0].sy,
						vertices[2].sy-vertices[0].sy,
						0,
						0);
			m1.invert();
								
			var capA:Number = m1.a *(p_oScreenPoint.x-vertices[0].sx) + m1.b *  
(p_oScreenPoint.y -vertices[0].sy);
			var capB:Number = m1.c *(p_oScreenPoint.x-vertices[0].sx) + m1.d *  
(p_oScreenPoint.y -vertices[0].sy);
			
			var l_oPoint:Point3D = new Point3D(			
				vertices[0].x + capA*(vertices[1].x -vertices[0].x) + capB  
*(vertices[2].x - vertices[0].x),
				vertices[0].y + capA*(vertices[1].y -vertices[0].y) + capB  
*(vertices[2].y - vertices[0].y),
				vertices[0].z + capA*(vertices[1].z -vertices[0].z) + capB  
*(vertices[2].z - vertices[0].z)
				);
											
			// transform the vertex with the model Matrix
			this.shape.matrix.transform( l_oPoint );
			return l_oPoint;
		}
		
		/**
		 * Returns a UV coordinate elative to the specified point on the 2D  
screen.
		 *
		 * @example	Below is an example of how to get the UV coordinate under the  
position of the mouse:
		 * <listing version="3.1">
		 * var screenPoint:Point = new Point(myPolygon.container.mouseX,  
myPolygon.container.mouseY);
		 * var scenePosition:Point3D = myPolygon.getUVFrom2D(screenPoint);
          * </listing>
          *
          * @return A the UV coordinate that corresponds to the specified  
point.
          */
		public function getUVFrom2D( p_oScreenPoint:Point ):UVCoord
		{
			var p0:Point = new Point(vertices[0].sx, vertices[0].sy);
             var p1:Point = new Point(vertices[1].sx, vertices[1].sy);
             var p2:Point = new Point(vertices[2].sx, vertices[2].sy);

             var u0:UVCoord = aUVCoord[0];
             var u1:UVCoord = aUVCoord[1];
             var u2:UVCoord = aUVCoord[2];

             var v01:Point = new Point(p1.x - p0.x, p1.y - p0.y );

             var vn01:Point = v01.clone();
             vn01.normalize(1);

             var v02:Point = new Point(p2.x - p0.x, p2.y - p0.y );
             var vn02:Point = v02.clone(); vn02.normalize(1);

             // sub that from click point
             var v4:Point = new Point( p_oScreenPoint.x - v01.x,  
p_oScreenPoint.y - v01.y );

             // we now have everything to find 1 intersection
             var l_oInter:Point = IntersectionMath.intersectionLine2D( p0,  
p2, p_oScreenPoint, v4 );

             // find Point3Ds to intersection
             var vi02:Point = new Point( l_oInter.x - p0.x, l_oInter.y -  
p0.y );
             var vi01:Point = new Point( p_oScreenPoint.x - l_oInter.x ,  
p_oScreenPoint.y - l_oInter.y );

             // interpolation coeffs
             var d1:Number = vi01.length / v01.length ;
             var d2:Number = vi02.length / v02.length;

             // -- on interpole linéairement pour trouver la position du  
point dans repere de la texture (normalisé)
             return new UVCoord( u0.u + d1*(u1.u - u0.u) + d2*(u2.u - u0.u),
				                u0.v + d1*(u1.v - u0.v) + d2*(u2.v - u0.v));
		}
		
		/**
		 * Clips the polygon.
		 *
		 * @return An array of vertices clipped by the camera frustum.
		 */
		public function clip( p_oFrustum:Frustum ):Array
		{
			cvertices = null;
			caUVCoord = null;
			// --
			var l_oCull:CullingState = p_oFrustum.polygonInFrustum( this );
			if( l_oCull == CullingState.INSIDE )
				return vertices;
			else if( l_oCull == CullingState.OUTSIDE )
				return null;
			// For lines we only apply front plane clipping
			if( vertices.length < 3 )
			{
				clipFrontPlane( p_oFrustum );
			}
			else
			{
				cvertices = vertices.slice();
				caUVCoord = aUVCoord.slice();
				// --
				isClipped = p_oFrustum.clipFrustum( cvertices, caUVCoord );
			}
			return cvertices;
		}

		/**
		 * Perform a clipping against the camera frustum's front plane.
		 *
		 * @return An array of vertices clipped by the camera frustum's front  
plane.
		 */
		public function clipFrontPlane( p_oFrustum:Frustum ):Array
		{
			cvertices = vertices.slice();
			// If line
			if( vertices.length < 3 )
			{
				isClipped = p_oFrustum.clipLineFrontPlane( cvertices );
			}
			else
			{
				caUVCoord = aUVCoord.slice();
				isClipped = p_oFrustum.clipFrontPlane( cvertices, caUVCoord );
			}
			return cvertices;
		}

		/**
		 * Clears the polygon's container.
		 */
		public function clear():void
		{
			if (m_oContainer != null) m_oContainer.graphics.clear();
		}

		/**
		 * Draws the polygon on its container if visible.
		 *
		 * @param p_oScene		The scene this polygon is rendered in.
		 * @param p_oContainer	The container to draw on.
		 */
		public function display( p_oContainer:Sprite = null ):void
		{
			const lCont:Sprite = (p_oContainer)?p_oContainer:m_oContainer;
			if( visible )
			{
				m_oAppearance.frontMaterial.renderPolygon( scene, this, lCont );
			}
			else
			{
				m_oAppearance.backMaterial.renderPolygon( scene, this, lCont );
			}
		}
		
		/**
		 * Returns the material currently used by the renderer
		 * @return Material the material used to render
		 */
		public function get material():Material
		{
			return ( visible ) ? m_oAppearance.frontMaterial :  
m_oAppearance.backMaterial;
		}

		/**
		 * The polygon's container.
		 */
		public function get container():Sprite
		{
			return m_oContainer;
		}

		/**
		 * Returns a string representation of this object.
		 *
		 * @return	The fully qualified name of this object.
		 */
		public function toString():String
		{
			return "sandy.core.data.Polygon::id=" +id+ " [Points: " +  
vertices.length + "]";
		}

		/**
		 * Specifies whether mouse events are enabled for this polygon.
		 *
		 * <p>To apply events to a polygon, listeners must be added with the  
<code>addEventListener()</code> method.</p>
		 *
		 * @see #addEventListener()
		 */
		public function get enableEvents():Boolean
		{
			return mouseEvents;
		}
		
		/**
		 * @private
		 */
		public function set enableEvents( b:Boolean ):void
		{
	        if( b && !mouseEvents )
	        {
	        	container.addEventListener(MouseEvent.CLICK, _onInteraction);
	    		container.addEventListener(MouseEvent.MOUSE_UP, _onInteraction);
	    		container.addEventListener(MouseEvent.MOUSE_DOWN, _onInteraction);
	    		container.addEventListener(MouseEvent.ROLL_OVER, _onInteraction);
	    		container.addEventListener(MouseEvent.ROLL_OUT, _onInteraction);
	    		
				container.addEventListener(MouseEvent.DOUBLE_CLICK, _onInteraction);
				container.addEventListener(MouseEvent.MOUSE_MOVE, _onInteraction);
				container.addEventListener(MouseEvent.MOUSE_OVER, _onInteraction);
				container.addEventListener(MouseEvent.MOUSE_OUT, _onInteraction);
				container.addEventListener(MouseEvent.MOUSE_WHEEL, _onInteraction);

			}
			else if( !b && mouseEvents )
			{
				container.removeEventListener(MouseEvent.CLICK, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_UP, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_DOWN, _onInteraction);
				container.removeEventListener(MouseEvent.ROLL_OVER, _onInteraction);
				container.removeEventListener(MouseEvent.ROLL_OUT, _onInteraction);
				
				container.removeEventListener(MouseEvent.DOUBLE_CLICK, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_MOVE, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_OVER, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_OUT, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_WHEEL, _onInteraction);
	    	}
	    	mouseEvents = b;
		}

		/**
		 * @private
		 */
		protected function _onInteraction( p_oEvt:Event ):void
		{
			var l_oClick:Point = new Point( m_oContainer.mouseX, m_oContainer.mouseY  
);
			var l_oUV:UVCoord = getUVFrom2D( l_oClick );
			var l_oPt3d:Point3D = get3DFrom2D( l_oClick );
			m_oEB.dispatchEvent( new Shape3DEvent( p_oEvt.type, shape, this, l_oUV,  
l_oPt3d, p_oEvt ) );
		}
		
		/**
		 * @private
		 */
		protected function _startMouseInteraction( e : MouseEvent = null ) : void
		{
			container.addEventListener(MouseEvent.CLICK, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_UP, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_DOWN, _onTextureInteraction);
			
			container.addEventListener(MouseEvent.DOUBLE_CLICK,  
_onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_MOVE, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_OVER, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_OUT, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_WHEEL,  
_onTextureInteraction);
			
			container.addEventListener(KeyboardEvent.KEY_DOWN,  
_onTextureInteraction);
			container.addEventListener(KeyboardEvent.KEY_UP, _onTextureInteraction);
			
			m_oContainer.addEventListener( Event.ENTER_FRAME, _onTextureInteraction  
);
		}
		
		/**
		 * @private
		 */
		protected function _stopMouseInteraction( e : MouseEvent = null ) : void
		{
			container.removeEventListener(MouseEvent.CLICK, _onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_UP,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_DOWN,  
_onTextureInteraction);
			
			container.removeEventListener(MouseEvent.DOUBLE_CLICK,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_MOVE,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_OVER,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_OUT,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_WHEEL,  
_onTextureInteraction);
			m_oContainer.removeEventListener( Event.ENTER_FRAME,  
_onTextureInteraction );
			
			container.removeEventListener(KeyboardEvent.KEY_DOWN,  
_onTextureInteraction);
			container.removeEventListener(KeyboardEvent.KEY_UP,  
_onTextureInteraction);
			
		}
		
		/**
		 * Specifies whether <code>MouseEvent.ROLL_&#42;</code> events are  
enabled for this polygon.
		 *
		 * <p>To apply events to a polygon, listeners must be added with the  
<code>addEventListener()</code> method.</p>
		 *
		 * @see #addEventListener()
		 */
		public function get enableInteractivity():Boolean
		{
			return mouseInteractivity;
		}
		
		/**
		 * @private
		 */
		public function set enableInteractivity( p_bState:Boolean ):void
		{
			if( p_bState != mouseInteractivity )
			{
				if( p_bState )
				{
					container.addEventListener( MouseEvent.ROLL_OVER,  
_startMouseInteraction, false );
					container.addEventListener( MouseEvent.ROLL_OUT,  
_stopMouseInteraction, false );
				}
				else
				{
					_stopMouseInteraction();
				}
				// --
				mouseInteractivity = p_bState;
			}
		}
		
		/**
		 * @private
		 */
		protected function _onTextureInteraction( p_oEvt:Event = null ) : void
		{
			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);
			
		    //	get the position of the mouse on the poly
			var pt2D : Point = new Point( scene.container.mouseX,  
scene.container.mouseY );
			var uv : UVCoord = getUVFrom2D( pt2D );
			
			VirtualMouse.getInstance().interactWithTexture( this, uv, p_oEvt as  
MouseEvent );
			_onInteraction( p_oEvt );
		}
	
		/**
		 * Returns the transformed normal Point3D of the polygon.
		 *
		 * @return The transformed normal Point3D of the polygon.
		 */
		public function createTransformedNormal():Point3D
		{
			if( vertices.length > 2 )
			{
				var v:Point3D, w:Point3D;
				var a:Vertex = vertices[0], b:Vertex = vertices[1], c:Vertex =  
vertices[2];
				v = new Point3D( b.wx - a.wx, b.wy - a.wy, b.wz - a.wz );
				w = new Point3D( b.wx - c.wx, b.wy - c.wy, b.wz - c.wz );
				// we compute de cross product
				var l_normal:Point3D = Point3DMath.cross( v, w );
				// we normalize the resulting Point3D
				Point3DMath.normalize( l_normal ) ;
				// we return the resulting vertex
				return l_normal;
			}
			else
			{
				return new Point3D();
			}
		}

		/**
		 * Returns the normal Point3D of the polygon.
		 *
		 * @return The normal Point3D of the polygon.
		 */
		public function createNormal():Point3D
		{
			if( vertices.length > 2 )
			{
				var v:Point3D, w:Point3D;
				var a:Vertex = vertices[0], b:Vertex = vertices[1], c:Vertex =  
vertices[2];
				v = new Point3D( b.x - a.x, b.y - a.y, b.z - a.z );
				w = new Point3D( b.x - c.x, b.y - c.y, b.z - c.z );
				// we compute de cross product
				var l_normal:Point3D = Point3DMath.cross( v, w );
				// we normalize the resulting Point3D
				Point3DMath.normalize( l_normal ) ;
				// we return the resulting vertex
				return l_normal;
			}
			else
			{
				return new Point3D();
			}
		}
		
		/**
		 * The appearance of this polygon.
		 */
		public function get appearance():Appearance
		{
			return m_oAppearance;
		}
		
		/**
		 * @private
		 */
		public function set appearance( p_oApp:Appearance ):void
		{
			if( p_oApp != null )
			{
				m_oAppearance = p_oApp;
				// --
				m_oAppearance.frontMaterial.init( this );
				if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
				{
					m_oAppearance.backMaterial.init( this );
				}
			}
		}
		
		private function _finishMaterial( pEvt:SandyEvent ):void
		{
			if( !m_oAppearance ) return;
			if( !visible ) return;
			// --
			m_oAppearance.frontMaterial.finish( scene );
			if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
			{
				m_oAppearance.backMaterial.finish( scene );
			}
		}
		
		private function _beginMaterial( pEvt:SandyEvent ):void
		{
			if( !m_oAppearance ) return;
			if( !visible ) return;
			// --
			m_oAppearance.frontMaterial.begin( scene );
			if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
			{
				m_oAppearance.backMaterial.begin( scene );
			}
		}

		/**
		 * Changes which side is the "normal" culling side.
		 *
		 * <p>This method also swaps the front and back skins.</p>
		 */
		public function swapCulling():void
		{
			normal.negate();
		}

		/**
		 * Removes the polygon's container from the stage.
		 */
		public function destroy():void
		{
			clear();
			scene.removeEventListener(SandyEvent.SCENE_RENDER_FINISH,  
_finishMaterial );
			scene.removeEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST,  
_beginMaterial );
			// --
			enableEvents = false;
			enableInteractivity = false;
			if( appearance.backMaterial ) appearance.backMaterial.unlink( this );
			if( appearance.frontMaterial ) appearance.frontMaterial.unlink( this );
			appearance = null;
			if( m_oContainer.parent ) m_oContainer.parent.removeChild( m_oContainer  
);
			if( m_oContainer ) m_oContainer = null;
			// --
			cvertices = null;
			vertices = null;
			m_oEB = null;
			m_oGeometry = null;
			shape = null;
			scene = null;
			// -- memory leak fix from nopmb on mediabox forums
			delete POLYGON_MAP[id];
		}


	// _______
	// PRIVATE_______________________________________________________

		/** Reference to its owner geometry */
		private var m_oGeometry:Geometry3D;
		private var m_oAppearance:Appearance;
		private var m_nNormalId:uint;
		private var m_nDepth:Number;
		/**
		 * @private
		 */
		protected var m_oContainer:Sprite;

		/**
		 * @private
		 */
		protected var m_oEB:BubbleEventBroadcaster;

		/** Boolean representing the state of the event activation */
		private var mouseEvents:Boolean = false;
		private var mouseInteractivity:Boolean = false;
	}
}
\ No newline at end of file
+
package sandy.core.data
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	
	import sandy.core.Scene3D;
	import sandy.core.interaction.VirtualMouse;
	import sandy.core.scenegraph.Geometry3D;
	import sandy.core.scenegraph.IDisplayable;
	import sandy.core.scenegraph.Shape3D;
	import sandy.events.BubbleEventBroadcaster;
	import sandy.events.SandyEvent;
	import sandy.events.Shape3DEvent;
	import sandy.materials.Appearance;
	import sandy.materials.Material;
	import sandy.math.IntersectionMath;
	import sandy.math.Point3DMath;
	import sandy.view.CullingState;
	import sandy.view.Frustum;

	/**
	 * Polygon's are the building blocks of visible 3D shapes.
	 *
	 * @author		Thomas Pfeiffer - kiroukou
	 * @author		Mirek Mencel
	 * @since		1.0
	 * @version		3.1
	 * @date 		24.08.2007
	 *
	 * @see sandy.core.scenegraph.Shape3D
	 */
	public final class Polygon implements IDisplayable
	{
	// _______
	// STATICS_______________________________________________________
		private static var _ID_:uint = 0;
		
		/**
		 * This property lists all the polygons.
		 * This is a helper property since it allows all polygons of a scene to  
be retrieved from a single list by its unique identifier.
		 * A polygon's unique identifier can be retrieved useing  
<code>myPolygon.id</code>.
		 *
		 * @example The examples below shows how to retrieve a ploygon from this  
property.
		 * <listing version="3.1">
		 * var p:Polygon = Polygon.POLYGON_MAP[myPolygon.id];
		 * </listing>
		 */
		public static var POLYGON_MAP:Dictionary = new Dictionary(true);
	// ______
	// PUBLIC________________________________________________________
		/**
		 * The unique identifier for this polygon.
		 */
		public const id:uint = _ID_++;

		/**
		 * A reference to the Shape3D object this polygon belongs to.
		 */
		public var shape:Shape3D;
				
		/**
		 * Specifies if the polygon has been clipped.
		 */
		public var isClipped:Boolean = false;
		
		/**
		 * An array of clipped vertices. Check the <code>isClipped</code>  
property first to see if this array will contain the useful data.
		 */
		public var cvertices:Array;
		
		/**
		 * An array of the polygon's original vertices.
		 */
		public var vertices:Array;
		
		/**
		 * An array of the polygon's vertex normals.
		 */
		public var vertexNormals:Array;
		
		public var aUVCoord:Array;

		/**
		 * An array of the polygon's edges.
		 */
		public var aEdges:Array;

		public var caUVCoord:Array;

		/**
		 * The texture bounds.
		 */
		public var uvBounds:Rectangle;
		
		/**
		 * An array of polygons that share an edge with this polygon.
		 */
		public var aNeighboors:Array = new Array();

		/**
		 * Specifies whether the face of the polygon is visible.
		 */
		public var visible:Boolean;
		
		/**
		 * Minimum depth value of that polygon in the camera space
		 */
		public var minZ:Number;
		
		
		public var a:Vertex, b:Vertex, c:Vertex, d:Vertex;
		
		/**
		 * Creates a new polygon.
		 *
		 * @param p_oShape			The shape the polygon belongs to.
		 * @param p_geometry		The geometry the polygon belongs to.
		 * @param p_aVertexID		An array of verticies of the polygon.
		 * @param p_aUVCoordsID		An array of UV coordinates of this polygon.
		 * @param p_nFaceNormalID	The faceNormalID of this polygon.
		 * @param p_nEdgesID		The edgesID of this polygon.
		 */
		public function Polygon( p_oOwner:Shape3D, p_geometry:Geometry3D,  
p_aVertexID:Array, p_aUVCoordsID:Array=null, p_nFaceNormalID:Number=0,  
p_nEdgesID:uint=0 )
		{
			shape = p_oOwner;
			m_oGeometry = p_geometry;
			// --
			__update( p_aVertexID, p_aUVCoordsID, p_nFaceNormalID, p_nEdgesID );
			m_oContainer = new Sprite();
			// --
			POLYGON_MAP[id] = this;
			m_oEB = new BubbleEventBroadcaster(this);
		}

		public function get changed():Boolean
		{
			return shape.changed;
		}
		
		/**
		 * A reference to the Scene3D object this polygon is in.
		 */
		public function set scene(p_oScene:Scene3D):void
		{
			if( p_oScene == null ) return;
			if( m_oScene != null )
			{
				m_oScene.removeEventListener(SandyEvent.SCENE_RENDER_FINISH,  
_finishMaterial );
				m_oScene.removeEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST,  
_beginMaterial );
			}
			// --
			m_oScene = p_oScene;
			// --
			m_oScene.addEventListener(SandyEvent.SCENE_RENDER_FINISH,  
_finishMaterial );
			m_oScene.addEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST,  
_beginMaterial );
		}
		
		public function get scene():Scene3D
		{
			return m_oScene;
		}
		private var m_oScene:Scene3D = null;
		
		/**
		 * Updates the vertices and normals for this polygon.
		 *
		 * <p>Calling this method make the polygon gets its vertice and normals  
by reference
		 * instead of accessing them by their ID.<br/>
		 * This method shall be called once the geometry created.</p>
		 *
		 * @param p_aVertexID		The vertexID array of this polygon
		 * @param p_aUVCoordsID		The UVCoordsID array of this polygon
		 * @param p_nFaceNormalID	The faceNormalID of this polygon
		 * @param p_nEdgesID		The edgesID of this polygon
		 */
		private function __update( p_aVertexID:Array, p_aUVCoordsID:Array,  
p_nFaceNormalID:uint, p_nEdgeListID:uint ):void
		{
			var i:int=0;
			// --
			vertexNormals = new Array();
			vertices = new Array();
			for each( var o:* in p_aVertexID )
			{
				vertices[i] = Vertex( m_oGeometry.aVertex[ p_aVertexID[i] ] );
				vertexNormals[i] = m_oGeometry.aVertexNormals[ p_aVertexID[i] ];
				i++;
			}
			// --
			a = vertices[0];
			b = vertices[1];
			c = vertices[2];
			d = vertices[3];
			// -- every polygon does not have some texture coordinates
			if( p_aUVCoordsID )
			{
				var l_nMinU:Number = Number.POSITIVE_INFINITY, l_nMinV:Number =  
Number.POSITIVE_INFINITY,
									l_nMaxU:Number = Number.NEGATIVE_INFINITY, l_nMaxV:Number =  
Number.NEGATIVE_INFINITY;
				// --
				aUVCoord = new Array();
				i = 0;
				if( p_aUVCoordsID )
				{
					for each( var p:* in p_aUVCoordsID )
					{
						var l_oUV:UVCoord = ( m_oGeometry.aUVCoords[ p_aUVCoordsID[i] ] as  
UVCoord);
						if( l_oUV == null ) l_oUV = new UVCoord(0,0);
						// --
						aUVCoord[i] = l_oUV;
						if( l_oUV.u < l_nMinU ) l_nMinU = l_oUV.u;
						else if( l_oUV.u > l_nMaxU ) l_nMaxU = l_oUV.u;
						// --
						if( l_oUV.v < l_nMinV ) l_nMinV = l_oUV.v;
						else if( l_oUV.v > l_nMaxV ) l_nMaxV = l_oUV.v;
						// --
						i++;
					}
					// --
					uvBounds = new Rectangle( l_nMinU, l_nMinV, l_nMaxU-l_nMinU,  
l_nMaxV-l_nMinV );
				}
				else
				{
					aUVCoord = [new UVCoord(), new UVCoord(), new UVCoord()];
					uvBounds = new Rectangle(0,0,0,0);
				}
			}
			// --
			m_nNormalId = p_nFaceNormalID;
			normal = Vertex( m_oGeometry.aFacesNormals[ p_nFaceNormalID ] );
			// If no normal has been given, we create it ourself.
			if( normal == null )
			{
				var l_oNormal:Point3D = createNormal();
				m_nNormalId = m_oGeometry.setFaceNormal(  
m_oGeometry.getNextFaceNormalID(), l_oNormal.x, l_oNormal.y, l_oNormal.z );
			}
			// --
			aEdges = new Array();
			for each( var l_nEdgeId:uint in  m_oGeometry.aFaceEdges[p_nEdgeListID] )
			{
				var l_oEdge:Edge3D = m_oGeometry.aEdges[ l_nEdgeId ];
				l_oEdge.vertex1 = m_oGeometry.aVertex[ l_oEdge.vertexId1 ];
				l_oEdge.vertex2 = m_oGeometry.aVertex[ l_oEdge.vertexId2 ];
				aEdges.push( l_oEdge );
			}
		}
		
		public function get normal():Vertex
		{
			return m_oGeometry.aFacesNormals[ m_nNormalId ];
		}
		
		public function set normal( p_oVertex:Vertex ):void
		{
			if( p_oVertex != null )
				m_oGeometry.aFacesNormals[ m_nNormalId ].copy( p_oVertex );
		}
		
		public function updateNormal():void
		{
			var x:Number = 	((a.y - b.y) * (c.z - b.z)) - ((a.z - b.z) * (c.y -  
b.y)) ;
			var y:Number =	((a.z - b.z) * (c.x - b.x)) - ((a.x - b.x) * (c.z -  
b.z)) ;
			var z:Number = 	((a.x - b.x) * (c.y - b.y)) - ((a.y - b.y) * (c.x -  
b.x)) ;
			normal.reset( x, y, z );
		}
		
		/**
		 * The depth of the polygon.
		 */
		public function get depth():Number
		{
			return m_nDepth;
		}
		
		/**
		 * @private
		 */
		public function set depth( p_nDepth:Number ):void
		{
			m_nDepth = p_nDepth;
		}
		
		/**
		 * The broadcaster of the polygon that sends events to listeners.
		 */
		public function get broadcaster():BubbleEventBroadcaster
		{
			return m_oEB;
		}

		/**
		 * Adds an event listener to the polygon.
		 *
		 * @param p_sEvent 	The name of the event to add.
		 * @param oL 		The listener object.
		 */
		public function addEventListener(p_sEvent:String, oL:*) : void
		{
			m_oEB.addEventListener.apply(m_oEB, arguments);
		}

		/**
		 * Removes an event listener to the polygon.
		 *
		 * @param p_sEvent 	The name of the event to remove.
		 * @param oL 		The listener object.
		 */
		public function removeEventListener(p_sEvent:String, oL:*) : void
		{
			m_oEB.removeEventListener(p_sEvent, oL);
		}

		/**
		 * Computes several properties of the polygon.
		 * <p>The computed properties are listed below:</p>
		 * <ul>
		 *  <li><code>visible</code></li>
		 *  <li><code>minZ</code></li>
		 *  <li><code>depth</code></li>
		 * </ul>
		 */
		public function precompute():void
		{
			isClipped = false;
			// --
			minZ = a.wz;
			if (b.wz < minZ) minZ = b.wz;
			m_nDepth = a.wz + b.wz;
			// --
			if (c != null)
			{
				if (c.wz < minZ) minZ = c.wz;
				m_nDepth += c.wz;
			}
			if (d != null)
			{
				if (d.wz < minZ) minZ = d.wz;
				m_nDepth += d.wz;
			}
			m_nDepth /= vertices.length;
		}
	
		/**
		 * Returns a Point3D (3D position) on the polygon relative to the  
specified point on the 2D screen.
		 *
		 * @example	Below is an example of how to get the 3D coordinate of the  
polygon under the position of the mouse:
		 * <listing version="3.1">
		 * var screenPoint:Point = new Point(myPolygon.container.mouseX,  
myPolygon.container.mouseY);
		 * var scenePosition:Point3D = myPolygon.get3DFrom2D(screenPoint);
          * </listing>
          *
          * @return A Point3D that corresponds to the specified point.
          */
		public function get3DFrom2D( p_oScreenPoint:Point ):Point3D
		{
     		/// NEW CODE ADDED BY MAX with the help of makc ///
			
			var m1:Matrix= new Matrix(
						vertices[1].sx-vertices[0].sx,
						vertices[2].sx-vertices[0].sx,
						vertices[1].sy-vertices[0].sy,
						vertices[2].sy-vertices[0].sy,
						0,
						0);
			m1.invert();
								
			var capA:Number = m1.a *(p_oScreenPoint.x-vertices[0].sx) + m1.b *  
(p_oScreenPoint.y -vertices[0].sy);
			var capB:Number = m1.c *(p_oScreenPoint.x-vertices[0].sx) + m1.d *  
(p_oScreenPoint.y -vertices[0].sy);
			
			var l_oPoint:Point3D = new Point3D(			
				vertices[0].x + capA*(vertices[1].x -vertices[0].x) + capB  
*(vertices[2].x - vertices[0].x),
				vertices[0].y + capA*(vertices[1].y -vertices[0].y) + capB  
*(vertices[2].y - vertices[0].y),
				vertices[0].z + capA*(vertices[1].z -vertices[0].z) + capB  
*(vertices[2].z - vertices[0].z)
				);
											
			// transform the vertex with the model Matrix
			this.shape.matrix.transform( l_oPoint );
			return l_oPoint;
		}
		
		/**
		 * Returns a UV coordinate elative to the specified point on the 2D  
screen.
		 *
		 * @example	Below is an example of how to get the UV coordinate under the  
position of the mouse:
		 * <listing version="3.1">
		 * var screenPoint:Point = new Point(myPolygon.container.mouseX,  
myPolygon.container.mouseY);
		 * var scenePosition:Point3D = myPolygon.getUVFrom2D(screenPoint);
          * </listing>
          *
          * @return A the UV coordinate that corresponds to the specified  
point.
          */
		public function getUVFrom2D( p_oScreenPoint:Point ):UVCoord
		{
			var p0:Point = new Point(vertices[0].sx, vertices[0].sy);
             var p1:Point = new Point(vertices[1].sx, vertices[1].sy);
             var p2:Point = new Point(vertices[2].sx, vertices[2].sy);

             var u0:UVCoord = aUVCoord[0];
             var u1:UVCoord = aUVCoord[1];
             var u2:UVCoord = aUVCoord[2];

             var v01:Point = new Point(p1.x - p0.x, p1.y - p0.y );

             var vn01:Point = v01.clone();
             vn01.normalize(1);

             var v02:Point = new Point(p2.x - p0.x, p2.y - p0.y );
             var vn02:Point = v02.clone(); vn02.normalize(1);

             // sub that from click point
             var v4:Point = new Point( p_oScreenPoint.x - v01.x,  
p_oScreenPoint.y - v01.y );

             // we now have everything to find 1 intersection
             var l_oInter:Point = IntersectionMath.intersectionLine2D( p0,  
p2, p_oScreenPoint, v4 );

             // find Point3Ds to intersection
             var vi02:Point = new Point( l_oInter.x - p0.x, l_oInter.y -  
p0.y );
             var vi01:Point = new Point( p_oScreenPoint.x - l_oInter.x ,  
p_oScreenPoint.y - l_oInter.y );

             // interpolation coeffs
             var d1:Number = vi01.length / v01.length ;
             var d2:Number = vi02.length / v02.length;

             // -- on interpole linéairement pour trouver la position du  
point dans repere de la texture (normalisé)
             return new UVCoord( u0.u + d1*(u1.u - u0.u) + d2*(u2.u - u0.u),
				                u0.v + d1*(u1.v - u0.v) + d2*(u2.v - u0.v));
		}
		
		/**
		 * Clips the polygon.
		 *
		 * @return An array of vertices clipped by the camera frustum.
		 */
		public function clip( p_oFrustum:Frustum ):Array
		{
			cvertices = null;
			caUVCoord = null;
			// --
			var l_oCull:CullingState = p_oFrustum.polygonInFrustum( this );
			if( l_oCull == CullingState.INSIDE )
				return vertices;
			else if( l_oCull == CullingState.OUTSIDE )
				return null;
			// For lines we only apply front plane clipping
			if( vertices.length < 3 )
			{
				clipFrontPlane( p_oFrustum );
			}
			else
			{
				cvertices = vertices.slice();
				caUVCoord = aUVCoord.slice();
				// --
				isClipped = p_oFrustum.clipFrustum( cvertices, caUVCoord );
			}
			return cvertices;
		}

		/**
		 * Perform a clipping against the camera frustum's front plane.
		 *
		 * @return An array of vertices clipped by the camera frustum's front  
plane.
		 */
		public function clipFrontPlane( p_oFrustum:Frustum ):Array
		{
			cvertices = vertices.slice();
			// If line
			if( vertices.length < 3 )
			{
				isClipped = p_oFrustum.clipLineFrontPlane( cvertices );
			}
			else
			{
				caUVCoord = aUVCoord.slice();
				isClipped = p_oFrustum.clipFrontPlane( cvertices, caUVCoord );
			}
			return cvertices;
		}

		/**
		 * Clears the polygon's container.
		 */
		public function clear():void
		{
			if (m_oContainer != null) m_oContainer.graphics.clear();
		}

		/**
		 * Draws the polygon on its container if visible.
		 *
		 * @param p_oScene		The scene this polygon is rendered in.
		 * @param p_oContainer	The container to draw on.
		 */
		public function display( p_oContainer:Sprite = null ):void
		{
			const lCont:Sprite = (p_oContainer)?p_oContainer:m_oContainer;
			if( visible )
			{
				m_oAppearance.frontMaterial.renderPolygon( scene, this, lCont );
			}
			else
			{
				m_oAppearance.backMaterial.renderPolygon( scene, this, lCont );
			}
		}
		
		/**
		 * Returns the material currently used by the renderer
		 * @return Material the material used to render
		 */
		public function get material():Material
		{
			return ( visible ) ? m_oAppearance.frontMaterial :  
m_oAppearance.backMaterial;
		}

		/**
		 * The polygon's container.
		 */
		public function get container():Sprite
		{
			return m_oContainer;
		}

		/**
		 * Returns a string representation of this object.
		 *
		 * @return	The fully qualified name of this object.
		 */
		public function toString():String
		{
			return "sandy.core.data.Polygon::id=" +id+ " [Points: " +  
vertices.length + "]";
		}

		/**
		 * Specifies whether mouse events are enabled for this polygon.
		 *
		 * <p>To apply events to a polygon, listeners must be added with the  
<code>addEventListener()</code> method.</p>
		 *
		 * @see #addEventListener()
		 */
		public function get enableEvents():Boolean
		{
			return mouseEvents;
		}
		
		/**
		 * @private
		 */
		public function set enableEvents( b:Boolean ):void
		{
	        if( b && !mouseEvents )
	        {
	        	container.addEventListener(MouseEvent.CLICK, _onInteraction);
	    		container.addEventListener(MouseEvent.MOUSE_UP, _onInteraction);
	    		container.addEventListener(MouseEvent.MOUSE_DOWN, _onInteraction);
	    		container.addEventListener(MouseEvent.ROLL_OVER, _onInteraction);
	    		container.addEventListener(MouseEvent.ROLL_OUT, _onInteraction);
	    		
				container.addEventListener(MouseEvent.DOUBLE_CLICK, _onInteraction);
				container.addEventListener(MouseEvent.MOUSE_MOVE, _onInteraction);
				container.addEventListener(MouseEvent.MOUSE_OVER, _onInteraction);
				container.addEventListener(MouseEvent.MOUSE_OUT, _onInteraction);
				container.addEventListener(MouseEvent.MOUSE_WHEEL, _onInteraction);

			}
			else if( !b && mouseEvents )
			{
				container.removeEventListener(MouseEvent.CLICK, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_UP, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_DOWN, _onInteraction);
				container.removeEventListener(MouseEvent.ROLL_OVER, _onInteraction);
				container.removeEventListener(MouseEvent.ROLL_OUT, _onInteraction);
				
				container.removeEventListener(MouseEvent.DOUBLE_CLICK, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_MOVE, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_OVER, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_OUT, _onInteraction);
				container.removeEventListener(MouseEvent.MOUSE_WHEEL, _onInteraction);
	    	}
	    	mouseEvents = b;
		}

		/**
		 * @private
		 */
		protected function _onInteraction( p_oEvt:Event ):void
		{
			var l_oClick:Point = new Point( m_oContainer.mouseX, m_oContainer.mouseY  
);
			var l_oUV:UVCoord = getUVFrom2D( l_oClick );
			var l_oPt3d:Point3D = get3DFrom2D( l_oClick );
			m_oEB.dispatchEvent( new Shape3DEvent( p_oEvt.type, shape, this, l_oUV,  
l_oPt3d, p_oEvt ) );
		}
		
		/**
		 * @private
		 */
		protected function _startMouseInteraction( e : MouseEvent = null ) : void
		{
			container.addEventListener(MouseEvent.CLICK, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_UP, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_DOWN, _onTextureInteraction);
			
			container.addEventListener(MouseEvent.DOUBLE_CLICK,  
_onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_MOVE, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_OVER, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_OUT, _onTextureInteraction);
			container.addEventListener(MouseEvent.MOUSE_WHEEL,  
_onTextureInteraction);
			
			container.addEventListener(KeyboardEvent.KEY_DOWN,  
_onTextureInteraction);
			container.addEventListener(KeyboardEvent.KEY_UP, _onTextureInteraction);
			
			m_oContainer.addEventListener( Event.ENTER_FRAME, _onTextureInteraction  
);
		}
		
		/**
		 * @private
		 */
		protected function _stopMouseInteraction( e : MouseEvent = null ) : void
		{
			container.removeEventListener(MouseEvent.CLICK, _onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_UP,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_DOWN,  
_onTextureInteraction);
			
			container.removeEventListener(MouseEvent.DOUBLE_CLICK,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_MOVE,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_OVER,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_OUT,  
_onTextureInteraction);
			container.removeEventListener(MouseEvent.MOUSE_WHEEL,  
_onTextureInteraction);
			m_oContainer.removeEventListener( Event.ENTER_FRAME,  
_onTextureInteraction );
			
			container.removeEventListener(KeyboardEvent.KEY_DOWN,  
_onTextureInteraction);
			container.removeEventListener(KeyboardEvent.KEY_UP,  
_onTextureInteraction);
			
		}
		
		/**
		 * Specifies whether <code>MouseEvent.ROLL_&#42;</code> events are  
enabled for this polygon.
		 *
		 * <p>To apply events to a polygon, listeners must be added with the  
<code>addEventListener()</code> method.</p>
		 *
		 * @see #addEventListener()
		 */
		public function get enableInteractivity():Boolean
		{
			return mouseInteractivity;
		}
		
		/**
		 * @private
		 */
		public function set enableInteractivity( p_bState:Boolean ):void
		{
			if( p_bState != mouseInteractivity )
			{
				if( p_bState )
				{
					container.addEventListener( MouseEvent.ROLL_OVER,  
_startMouseInteraction, false );
					container.addEventListener( MouseEvent.ROLL_OUT,  
_stopMouseInteraction, false );
				}
				else
				{
					_stopMouseInteraction();
				}
				// --
				mouseInteractivity = p_bState;
			}
		}
		
		/**
		 * @private
		 */
		protected function _onTextureInteraction( p_oEvt:Event = null ) : void
		{
			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);
			
		    //	get the position of the mouse on the poly
			var pt2D : Point = new Point( scene.container.mouseX,  
scene.container.mouseY );
			var uv : UVCoord = getUVFrom2D( pt2D );
			
			VirtualMouse.getInstance().interactWithTexture( this, uv, p_oEvt as  
MouseEvent );
			_onInteraction( p_oEvt );
		}
	
		/**
		 * Returns the transformed normal Point3D of the polygon.
		 *
		 * @return The transformed normal Point3D of the polygon.
		 */
		public function createTransformedNormal():Point3D
		{
			if( vertices.length > 2 )
			{
				var v:Point3D, w:Point3D;
				var a:Vertex = vertices[0], b:Vertex = vertices[1], c:Vertex =  
vertices[2];
				v = new Point3D( b.wx - a.wx, b.wy - a.wy, b.wz - a.wz );
				w = new Point3D( b.wx - c.wx, b.wy - c.wy, b.wz - c.wz );
				// we compute de cross product
				var l_normal:Point3D = Point3DMath.cross( v, w );
				// we normalize the resulting Point3D
				Point3DMath.normalize( l_normal ) ;
				// we return the resulting vertex
				return l_normal;
			}
			else
			{
				return new Point3D();
			}
		}

		/**
		 * Returns the normal Point3D of the polygon.
		 *
		 * @return The normal Point3D of the polygon.
		 */
		public function createNormal():Point3D
		{
			if( vertices.length > 2 )
			{
				var v:Point3D, w:Point3D;
				var a:Vertex = vertices[0], b:Vertex = vertices[1], c:Vertex =  
vertices[2];
				v = new Point3D( b.x - a.x, b.y - a.y, b.z - a.z );
				w = new Point3D( b.x - c.x, b.y - c.y, b.z - c.z );
				// we compute de cross product
				var l_normal:Point3D = Point3DMath.cross( v, w );
				// we normalize the resulting Point3D
				Point3DMath.normalize( l_normal ) ;
				// we return the resulting vertex
				return l_normal;
			}
			else
			{
				return new Point3D();
			}
		}
		
		/**
		 * The appearance of this polygon.
		 */
		public function get appearance():Appearance
		{
			return m_oAppearance;
		}
		
		/**
		 * @private
		 */
		public function set appearance( p_oApp:Appearance ):void
		{
			if( m_oAppearance != null )
			{
				m_oAppearance.frontMaterial.unlink( this );
				if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
				{
					m_oAppearance.backMaterial.unlink( this );
				}
				m_oAppearance = null;
			}
			// --
			if( p_oApp != null )
			{
				m_oAppearance = p_oApp;
				// --
				m_oAppearance.frontMaterial.init( this );
				if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
				{
					m_oAppearance.backMaterial.init( this );
				}
			}
		}
		
		private function _finishMaterial( pEvt:SandyEvent ):void
		{
			if( !m_oAppearance ) return;
			//if( !visible ) return;
			// --
			m_oAppearance.frontMaterial.finish( m_oScene );
			if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
			{
				m_oAppearance.backMaterial.finish( m_oScene );
			}
		}
		
		private function _beginMaterial( pEvt:SandyEvent ):void
		{
			if( !m_oAppearance ) return;
			//if( !visible ) return;
			// --
			m_oAppearance.frontMaterial.begin( m_oScene );
			if( m_oAppearance.backMaterial != m_oAppearance.frontMaterial )
			{
				m_oAppearance.backMaterial.begin( m_oScene );
			}
		}

		/**
		 * Changes which side is the "normal" culling side.
		 *
		 * <p>This method also swaps the front and back skins.</p>
		 */
		public function swapCulling():void
		{
			normal.negate();
		}

		/**
		 * Removes the polygon's container from the stage.
		 */
		public function destroy():void
		{
			clear();
			scene.removeEventListener(SandyEvent.SCENE_RENDER_FINISH,  
_finishMaterial );
			scene.removeEventListener(SandyEvent.SCENE_RENDER_DISPLAYLIST,  
_beginMaterial );
			// --
			enableEvents = false;
			enableInteractivity = false;
			if( appearance.backMaterial ) appearance.backMaterial.unlink( this );
			if( appearance.frontMaterial ) appearance.frontMaterial.unlink( this );
			appearance = null;
			if( m_oContainer.parent ) m_oContainer.parent.removeChild( m_oContainer  
);
			if( m_oContainer ) m_oContainer = null;
			// --
			cvertices = null;
			vertices = null;
			m_oEB = null;
			m_oGeometry = null;
			shape = null;
			scene = null;
			// -- memory leak fix from nopmb on mediabox forums
			delete POLYGON_MAP[id];
		}


	// _______
	// PRIVATE_______________________________________________________

		/** Reference to its owner geometry */
		private var m_oGeometry:Geometry3D;
		private var m_oAppearance:Appearance;
		private var m_nNormalId:uint;
		private var m_nDepth:Number;
		/**
		 * @private
		 */
		protected var m_oContainer:Sprite;

		/**
		 * @private
		 */
		protected var m_oEB:BubbleEventBroadcaster;

		/** Boolean representing the state of the event activation */
		private var mouseEvents:Boolean = false;
		private var mouseInteractivity:Boolean = false;
	}
}
\ No newline at end of file

Modified: trunk/sandy/as3/trunk/src/sandy/materials/BitmapMaterial.as
==============================================================================
--- trunk/sandy/as3/trunk/src/sandy/materials/BitmapMaterial.as	(original)
+++ trunk/sandy/as3/trunk/src/sandy/materials/BitmapMaterial.as	Mon Feb 23  
13:53:09 2009
@@ -374,7 +374,8 @@
  		 */
  		public function setTransparency( p_nValue:Number ):void
  		{
-			if (m_oTexture == null) {
+			if (m_oTexture == null)
+			{
  				throw new Error ("Setting transparency requires setting texture  
first.");
  			}
  			
@@ -382,15 +383,18 @@

  			if (p_nValue == 1) return;

-			if (m_oTextureClone != null) {
+			if (m_oTextureClone != null)
+			{
  				if ((m_oTextureClone.height != m_oTexture.height) ||
-					(m_oTextureClone.width != m_oTexture.width)) {
+					(m_oTextureClone.width != m_oTexture.width))
+				{
  						m_oTextureClone.dispose ();
  						m_oTextureClone = null;
  				}
  			}

-			if (m_oTextureClone == null) {
+			if (m_oTextureClone == null)
+			{
  				m_oTextureClone = new BitmapData (m_oTexture.width, m_oTexture.height,  
true, 0);
  			}

@@ -467,7 +471,7 @@
  		 */
  		public function toString():String
  		{
-			return 'sandy.materials.BitmapMaterial' ;
+			return this.id+'::sandy.materials.BitmapMaterial' ;
  		}

  		/**

Modified: trunk/sandy/as3/trunk/src/sandy/materials/Material.as
==============================================================================
--- trunk/sandy/as3/trunk/src/sandy/materials/Material.as	(original)
+++ trunk/sandy/as3/trunk/src/sandy/materials/Material.as	Mon Feb 23  
13:53:09 2009
@@ -1 +1 @@
-
package sandy.materials
{
	import flash.display.Sprite;
	
	import sandy.core.Scene3D;
	import sandy.core.data.Polygon;
	import sandy.core.scenegraph.Sprite2D;
	import sandy.materials.attributes.MaterialAttributes;
	
	/**
	 * The Material class is the base class for all materials.
	 *
	 * <p>Since the Material object is essentially a blank material, this  
class can be used
	 * to apply attributes without any material to a 3D object.</p>
	 *
	 * @author		Thomas Pfeiffer - kiroukou
	 * @version		3.1
	 * @date 		26.07.2007
	 *
	 * @see Appearance
	 */
	public class Material
	{
		/**
		 * The attributes of this material.
		 */
		public var attributes:MaterialAttributes;
		
		/**
		 * Specify if the material use the vertex normal information.
		 *
		 * @default false
		 */
		public var useVertexNormal:Boolean = false;
		
		/**
		 * Specifies if the material can receive light and have light attributes  
applied to it.
		 * Can be useful to rapidly disable light on the object when unneeded.
		 */
		public var lightingEnable:Boolean = false;
		
		/**
		 * Creates a material.
		 *
		 * <p>This constructor is never called directly - but by sub class  
constructors.</p>
		 * @param p_oAttr	The attributes for this material.
		 */
		public function Material( p_oAttr:MaterialAttributes = null )
		{
			_filters 	= [];
			_useLight 	= false;
			_id = _ID_++;
			attributes = (p_oAttr == null) ? new MaterialAttributes() : p_oAttr;
			m_bModified = true;
			m_oType = MaterialType.NONE;
		}
		
		/**
		 * The unique id of this material.
		 */
		public function get id():Number
		{	
			return _id;
		}
		
		/**
		 * Calls begin method of the MaterialAttributes associated with this  
material.
		 *
		 * @param p_oScene	The scene.
		 *
		 * @see sandy.materials.attributes.MaterialAttributes#begin()
		 */
		public function begin( p_oScene:Scene3D ):void
		{
			if( attributes )
				attributes.begin( p_oScene );
		}
		
		/**
		 * Calls finish method of the MaterialAttributes associated with this  
material.
		 *
		 * @param p_oScene	The scene.
		 *
		 * @see sandy.materials.attributes.MaterialAttributes#finish()
		 */
		public function finish( p_oScene:Scene3D ):void
		{
			if( attributes )
				attributes.finish(p_oScene );
			// --
			m_bModified = false;
		}
		
		/**
		 * Renders the polygon dress in this material.
		 *
		 * <p>Implemented by sub classes.</p>
		 *
		 * @see sandy.core.Scene3D
		 * @see sandy.core.data.Polygon
		 */
		public function renderPolygon( p_oScene:Scene3D, p_oPolygon:Polygon,  
p_mcContainer:Sprite ):void
		{
			if( attributes )
				attributes.draw( p_mcContainer.graphics, p_oPolygon, this, p_oScene );
			// --
			if( _filters.length > 0 )
				p_mcContainer.filters = _filters;
		}
			
		/**
		 * Renders the sprite dress in this material.
		 *
		 * <p>Basically only needed to apply attributes to sprites</p>
		 *
		 * @see sandy.core.scenegraph.Sprite2D
		 * @see sandy.core.Scene3D
		 */
		public function renderSprite( p_oSprite:Sprite2D, p_oMaterial:Material,  
p_oScene:Scene3D ):void
		{
			if( attributes )
			{
				attributes.drawOnSprite( p_oSprite, p_oMaterial, p_oScene );
			}
			// --
			if( _filters.length > 0 )
				p_oSprite.content.filters = _filters;
		}

		/**
		 * Calls init method of the MaterialAttributes associated with this  
material.
		 *
		 * @see sandy.materials.attributes.MaterialAttributes#init()
		 */
		public function init( p_oPolygon:Polygon ):void
		{
			if( attributes )
				attributes.init( p_oPolygon );
		}
	
		/**
		 * Calls unlink method of the MaterialAttributes associated with this  
material.
		 *
		 * @see sandy.materials.attributes.MaterialAttributes#unlink()
		 */
		public function unlink( p_oPolygon:Polygon ):void
		{
			if( attributes )
				attributes.unlink( p_oPolygon );
		}
		
		/**
		 * The material type of this material.
		 *
		 * @default MaterialType.NONE
		 *
		 * @see MaterialType
		 */
		public function get type():MaterialType
		{
			return m_oType;
		}
		
		/**
		 * @private
		 */
		public function set filters( a:Array ):void
		{
			_filters = a;
			m_bModified = true;
		}
		
		/**
		 * Contains specific material flags.
		 */
		public function get flags():uint
		{
			var l_nFlags:uint = m_nFlags;
			if( attributes )
				l_nFlags |= attributes.flags;
			return l_nFlags;
		}
		
		/**
		 * The array of filters for this material.
		 *
		 * <p>You use this property to add an array of filters you want to apply  
to this material<br>
		 * To remove the filters, just assign an empty array.</p>
		 */
		public function get filters():Array
		{
			return _filters;
		}
		
		/**
		 * The modified state of this material.
		 *
		 * <p>true if this material or its line attributes were modified since  
last rendered, false otherwise.</p>
		 */
		public function get modified():Boolean
		{
			return (m_bModified);// && ((lineAttributes) ? lineAttributes.modified :  
true));
		}
				
		/**
		 * The repeat property.
		 *
		 * This affects the way textured materials are mapped for U or V out of  
0-1 range.
		 */
		public var repeat:Boolean = true;
		
		//////////////////
		// PROPERTIES
		//////////////////
		/**
		 * DO NOT TOUCH THIS PROPERTY UNLESS YOU PERFECTLY KNOW WHAT YOU ARE  
DOING.
		 * this flag property contains the specific material flags.
		 *
		 * @private
		 */
		protected var m_nFlags:uint = 0;
		
		/**
		 * @private
		 */
		protected var m_bModified:Boolean;
		
		/**
		 * @private
		 */
		protected var _useLight : Boolean = false;
		
		/**
		 * @private
		 */
		protected var m_oType:MaterialType;
		
		
		private var _filters:Array;
		private var _id:Number;

		private static var _ID_:Number = 0;
		private static var create:Boolean;
	}
}
\ No newline at end of file
+
package sandy.materials
{
	import flash.display.Sprite;
	
	import sandy.core.Scene3D;
	import sandy.core.data.Polygon;
	import sandy.core.scenegraph.Sprite2D;
	import sandy.materials.attributes.MaterialAttributes;
	
	/**
	 * The Material class is the base class for all materials.
	 *
	 * <p>Since the Material object is essentially a blank material, this  
class can be used
	 * to apply attributes without any material to a 3D object.</p>
	 *
	 * @author		Thomas Pfeiffer - kiroukou
	 * @version		3.1
	 * @date 		26.07.2007
	 *
	 * @see Appearance
	 */
	public class Material
	{
		/**
		 * The attributes of this material.
		 */
		public var attributes:MaterialAttributes;
		
		/**
		 * Specify if the material use the vertex normal information.
		 *
		 * @default false
		 */
		public var useVertexNormal:Boolean = false;
		
		/**
		 * Specifies if the material can receive light and have light attributes  
applied to it.
		 * Can be useful to rapidly disable light on the object when unneeded.
		 */
		public var lightingEnable:Boolean = false;
		
		/**
		 * Creates a material.
		 *
		 * <p>This constructor is never called directly - but by sub class  
constructors.</p>
		 * @param p_oAttr	The attributes for this material.
		 */
		public function Material( p_oAttr:MaterialAttributes = null )
		{
			_filters 	= [];
			_useLight 	= false;
			_id = _ID_++;
			attributes = (p_oAttr == null) ? new MaterialAttributes() : p_oAttr;
			m_bModified = true;
			m_oType = MaterialType.NONE;
		}
		
		/**
		 * The unique id of this material.
		 */
		public function get id():Number
		{	
			return _id;
		}
		
		/**
		 * Calls begin method of the MaterialAttributes associated with this  
material.
		 *
		 * @param p_oScene	The scene.
		 *
		 * @see sandy.materials.attributes.MaterialAttributes#begin()
		 */
		public function begin( p_oScene:Scene3D ):void
		{
			if( attributes )
				attributes.begin( p_oScene );
		}
		
		/**
		 * Calls finish method of the MaterialAttributes associated with this  
material.
		 *
		 * @param p_oScene	The scene.
		 *
		 * @see sandy.materials.attributes.MaterialAttributes#finish()
		 */
		public function finish( p_oScene:Scene3D ):void
		{
			if( attributes )
				attributes.finish(p_oScene );
			// --
			m_bModified = false;
		}
		
		/**
		 * Renders the polygon dress in this material.
		 *
		 * <p>Implemented by sub classes.</p>
		 *
		 * @see sandy.core.Scene3D
		 * @see sandy.core.data.Polygon
		 */
		public function renderPolygon( p_oScene:Scene3D, p_oPolygon:Polygon,  
p_mcContainer:Sprite ):void
		{
			if( attributes )
				attributes.draw( p_mcContainer.graphics, p_oPolygon, this, p_oScene );
			// --
			if( _filters.length > 0 )
				p_mcContainer.filters = _filters;
		}
			
		/**
		 * Renders the sprite dress in this material.
		 *
		 * <p>Basically only needed to apply attributes to sprites</p>
		 *
		 * @see sandy.core.scenegraph.Sprite2D
		 * @see sandy.core.Scene3D
		 */
		public function renderSprite( p_oSprite:Sprite2D, p_oMaterial:Material,  
p_oScene:Scene3D ):void
		{
			if( attributes )
			{
				attributes.drawOnSprite( p_oSprite, p_oMaterial, p_oScene );
			}
			// --
			if( _filters.length > 0 )
				p_oSprite.content.filters = _filters;
		}

		/**
		 * Calls init method of the MaterialAttributes associated with this  
material.
		 *
		 * @see sandy.materials.attributes.MaterialAttributes#init()
		 */
		public function init( p_oPolygon:Polygon ):void
		{
			if( attributes )
				attributes.init( p_oPolygon );
		}
	
		/**
		 * Calls unlink method of the MaterialAttributes associated with this  
material.
		 *
		 * @see sandy.materials.attributes.MaterialAttributes#unlink()
		 */
		public function unlink( p_oPolygon:Polygon ):void
		{
			if( attributes )
				attributes.unlink( p_oPolygon );
		}
		
		/**
		 * The material type of this material.
		 *
		 * @default MaterialType.NONE
		 *
		 * @see MaterialType
		 */
		public function get type():MaterialType
		{
			return m_oType;
		}
		
		/**
		 * @private
		 */
		public function set filters( a:Array ):void
		{
			if( a != _filters )
			{
				_filters = a;
				m_bModified = true;
			}
		}
		
		/**
		 * Contains specific material flags.
		 */
		public function get flags():uint
		{
			var l_nFlags:uint = m_nFlags;
			if( attributes )
				l_nFlags |= attributes.flags;
			return l_nFlags;
		}
		
		/**
		 * The array of filters for this material.
		 *
		 * <p>You use this property to add an array of filters you want to apply  
to this material<br>
		 * To remove the filters, just assign an empty array.</p>
		 */
		public function get filters():Array
		{
			return _filters;
		}
		
		/**
		 * The modified state of this material.
		 *
		 * <p>true if this material or its line attributes were modified since  
last rendered, false otherwise.</p>
		 */
		public function get modified():Boolean
		{
			return m_bModified;// && ((lineAttributes) ? lineAttributes.modified :  
true));
		}
				
		/**
		 * The repeat property.
		 *
		 * This affects the way textured materials are mapped for U or V out of  
0-1 range.
		 */
		public var repeat:Boolean = true;
		
		//////////////////
		// PROPERTIES
		//////////////////
		/**
		 * DO NOT TOUCH THIS PROPERTY UNLESS YOU PERFECTLY KNOW WHAT YOU ARE  
DOING.
		 * this flag property contains the specific material flags.
		 *
		 * @private
		 */
		protected var m_nFlags:uint = 0;
		
		/**
		 * @private
		 */
		protected var m_bModified:Boolean;
		
		/**
		 * @private
		 */
		protected var _useLight : Boolean = false;
		
		/**
		 * @private
		 */
		protected var m_oType:MaterialType;
		
		
		private var _filters:Array;
		private var _id:Number;

		private static var _ID_:Number = 0;
		private static var create:Boolean;
	}
}
\ No newline at end of file

Added: trunk/sandy/as3/trunk/src/sandy/view/BasicView.as
==============================================================================
--- (empty file)
+++ trunk/sandy/as3/trunk/src/sandy/view/BasicView.as	Mon Feb 23 13:53:09  
2009
@@ -0,0 +1,151 @@
+package sandy.view
+{
+	import flash.display.BitmapData;
+	import flash.display.Sprite;
+	import flash.events.Event;
+	
+	import sandy.core.Scene3D;
+	import sandy.core.data.Point3D;
+	import sandy.core.scenegraph.Camera3D;
+	import sandy.core.scenegraph.Group;
+	import sandy.materials.Appearance;
+	import sandy.materials.BitmapMaterial;
+	import sandy.materials.ColorMaterial;
+	import sandy.materials.MovieMaterial;
+	import sandy.materials.attributes.MaterialAttributes;
+	import sandy.primitive.Box;
+	import sandy.primitive.Plane3D;
+	import sandy.primitive.Sphere;
+	
+	/**
+	 * Basic view to simplify Sandy scene setup.
+	 * You just have to extends it, and call init method with your settings.
+	 * Right after that you can use some utils methods to improve workflow.
+	 */
+	public class BasicView extends Sprite
+	{
+		public var useRenderingCache:Boolean = true;
+		public var camera:Camera3D;
+		public var scene:Scene3D;
+		public var rootNode:Group;
+		
+		public function BasicView()
+		{
+			super();
+		}
+		
+		public function init( p_nWidth:Number = 640, p_nHeight:Number = 480  
):void
+		{
+			rootNode = new Group("root");
+			camera = new Camera3D(p_nWidth, p_nHeight );
+			scene = new Scene3D("mainScene", this, camera, rootNode);
+		}
+		
+		public function render():void
+		{
+			this.addEventListener(Event.ENTER_FRAME, simpleRender );
+		}
+		
+		public function stop():void
+		{
+			this.removeEventListener(Event.ENTER_FRAME, simpleRender );
+		}
+		
+		public function simpleRender( pEvt:Event = null ):void
+		{
+			scene.render( useRenderingCache );
+		}
+		
+		public function makeBitmapAppearance( p_oTexture:BitmapData,  
p_oAttr:MaterialAttributes = null, p_nPrecision:Number = 0.0 ):Appearance
+		{
+			return new Appearance( new BitmapMaterial( p_oTexture, p_oAttr,  
p_nPrecision ) );
+		}
+		
+		public function makeMovieAppearance( p_oTexture:Sprite,  
p_oAttr:MaterialAttributes = null, p_nPrecision:Number = 0.0 ):Appearance
+		{
+			return new Appearance( new MovieMaterial( p_oTexture, 30, p_oAttr, true  
) );
+		}
+		
+		public function makeColorAppearance( p_nColor:uint = 0xFF,  
p_nAlpha:Number = 1.0, p_oAttr:MaterialAttributes = null ):Appearance
+		{
+			return new Appearance( new ColorMaterial(p_nColor, p_nAlpha, p_oAttr )  
);
+		}
+		
+		public function addBox( p_nWidth:Number=100, p_nHeight:Number=100,  
p_nDepth:Number=100, p_nQuality:uint = 1, p_oPosition:Point3D = null,  
p_oRotation:Point3D = null ):Box
+		{
+			var l_oBox:Box = new Box( null, p_nWidth, p_nHeight, p_nDepth, "tri",  
p_nQuality );
+			if( p_oPosition )
+			{
+				l_oBox.x = p_oPosition.x;
+				l_oBox.y = p_oPosition.y;
+				l_oBox.z = p_oPosition.z;
+			}
+			if( p_oRotation )
+			{
+				l_oBox.rotateX = p_oRotation.x;
+				l_oBox.rotateY = p_oRotation.y;
+				l_oBox.rotateZ = p_oRotation.z;
+			}
+			rootNode.addChild( l_oBox );
+			return l_oBox;
+		}
+		
+		public function addSphere( p_nRadius:Number=100, p_nQualityW:uint = 8,  
p_nQualityH:uint = 8, p_oPosition:Point3D = null, p_oRotation:Point3D =  
null ):Sphere
+		{
+			var l_oMesh:Sphere = new Sphere( null, p_nRadius, p_nQualityW,  
p_nQualityH );
+			if( p_oPosition )
+			{
+				l_oMesh.x = p_oPosition.x;
+				l_oMesh.y = p_oPosition.y;
+				l_oMesh.z = p_oPosition.z;
+			}
+			if( p_oRotation )
+			{
+				l_oMesh.rotateX = p_oRotation.x;
+				l_oMesh.rotateY = p_oRotation.y;
+				l_oMesh.rotateZ = p_oRotation.z;
+			}
+			rootNode.addChild( l_oMesh );
+			return l_oMesh;
+		}
+		
+		public function addHorizontalPlane( p_nWidth:Number=100,  
p_nHeight:Number=100, p_nQuality:uint = 3, p_oPosition:Point3D = null,  
p_oRotation:Point3D = null ):Plane3D
+		{
+			var l_oMesh:Plane3D = new Plane3D( null, p_nHeight, p_nWidth,  
p_nQuality, p_nQuality, Plane3D.ZX_ALIGNED, "tri" );
+			if( p_oPosition )
+			{
+				l_oMesh.x = p_oPosition.x;
+				l_oMesh.y = p_oPosition.y;
+				l_oMesh.z = p_oPosition.z;
+			}
+			if( p_oRotation )
+			{
+				l_oMesh.rotateX = p_oRotation.x;
+				l_oMesh.rotateY = p_oRotation.y;
+				l_oMesh.rotateZ = p_oRotation.z;
+			}
+			rootNode.addChild( l_oMesh );
+			return l_oMesh;
+		}
+		
+		public function addVerticalPlane( p_nWidth:Number=100,  
p_nHeight:Number=100, p_nQuality:uint = 3, p_oPosition:Point3D = null,  
p_oRotation:Point3D = null ):Plane3D
+		{
+			var l_oMesh:Plane3D = new Plane3D( null, p_nHeight, p_nWidth,  
p_nQuality, p_nQuality, Plane3D.XY_ALIGNED, "tri" );
+			if( p_oPosition )
+			{
+				l_oMesh.x = p_oPosition.x;
+				l_oMesh.y = p_oPosition.y;
+				l_oMesh.z = p_oPosition.z;
+			}
+			if( p_oRotation )
+			{
+				l_oMesh.rotateX = p_oRotation.x;
+				l_oMesh.rotateY = p_oRotation.y;
+				l_oMesh.rotateZ = p_oRotation.z;
+			}
+			rootNode.addChild( l_oMesh );
+			return l_oMesh;
+		}
+		
+	}
+}
\ No newline at end of file
_______________________________________________
Sandy mailing list
Sandy@osflash.org
http://osflash.org/mailman/listinfo/sandy_osflash.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic