forked from: forked from: forked from: flash on 2009-5-30

by lab9 forked from forked from: forked from: flash on 2009-5-30 (diff: 81)
♥0 | Line 176 | Modified 2009-05-31 19:33:01 | MIT License
play

ActionScript3 source code

/**
 * Copyright lab9 ( http://wonderfl.net/user/lab9 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9e9V
 */

package
{
   import flash.display.Graphics;
   import flash.display.Sprite;
   import flash.events.MouseEvent;
   import flash.geom.Point;
   import flash.geom.Rectangle;
   import flash.text.TextField;
   import flash.text.TextFormat;
   import flash.utils.getTimer;
   [SWF(frameRate="100", backgroundColor="0xFFFFFF", width="500", height="500")]
 
   public class TriangleSpeedTest2 extends Sprite
   {
 
 
      public var outputText : TextField;
 
      public function TriangleSpeedTest2()
      {
         super();
         outputText = new TextField(); 
         x = y = 250; 
         outputText.defaultTextFormat = new TextFormat("Arial"); 
         outputText.textColor = 0x0000FF; 
         outputText.text = "Click to start test"; 
         outputText.x = outputText.y = -250; 
         outputText.width = 500; 
 
         addChild(outputText); 
 
         stage.addEventListener(MouseEvent.MOUSE_DOWN, startTest); 
 
      }
 
      // I'm thinking that storing these values as properties rather than declaring them as local vars 
      // should be faster...
 
      private  var x0 : Number; 
      private  var y0 : Number; 
      private  var x1 : Number; 
      private  var y1 : Number; 
      private  var x2 : Number; 
      private  var y2 : Number; 
      private  var l : Number; 
      private  var r : Number; 
      private  var t : Number; 
      private  var b : Number; 
	  
	  private var t0 : int;
	  private var t1 : int;
	  private var t2 : int;
	  
	  private var s : Number
	  
	   private var lm0 : Number
	  private var lm1 : Number
	  private var lm2 : Number
	  

	   private var rm0 : Number
	  private var rm1 : Number
	  private var rm2 : Number
	  
      private  var top_intersection:Number ;
      private  var bottom_intersection : Number; 
      private  var toptrianglepoint : Number; 
      private  var bottomtrianglepoint : Number; 
 
	   private  var m: Number;
      private var c : Number  
      private  var m0: Number;
      private var c0 : Number  
	  private  var m1: Number;
      private var c1 : Number  
	  private  var m2: Number;
      private var c2 : Number  
 
 
      // THESE ARE THE TWO FUNCTIONS YOU CAN OPTIMISE. 
      // I realise that you could inline the lineRectangleIntersect method, but I'd rather not do that just yet... 
      // I'm looking for maths/logic improvements. 
 
      public function triangleTest(rect:Rectangle,  vertex0:Point, vertex1:Point, vertex2:Point ) : Boolean
      {
         // YOU MUST LEAVE THESE DECLARATIONS; they simulate necessary data exchange within PV3D
         l = rect.left; 
         r = rect.right; 
         t = rect.top; 
         b = rect.bottom; 
 
         x0 = vertex0.x; 
         y0 = vertex0.y; 
         x1 = vertex1.x; 
         y1 = vertex1.y; 
         x2 = vertex2.x; 
         y2 = vertex2.y; 
		 
		if (x0 > l) if(x0 < r) if(y0 > t) if(y0 < b) return true;
		if (x1 > l) if( x1 < r ) if( y1 > t ) if( y1 < b) return true;
		if (x2 > l ) if( x2 < r ) if( y2 > t ) if( y2 < b) return true;
		
		
		//if (isInsideTriangle(x0, y0, x1, y1, x2, y2)) return true;
		 
		 return (isIntersecting(x0, y0, x1, y1) || isIntersecting(x1, y1, x2, y2) || isIntersecting(x0, y0, x2, y2));
      }
	  
	  public function isInsideTriangle(x0: Number,y0: Number,x1: Number,y1: Number,x2: Number,y2: Number):Boolean
      { 
            // Calculate m and c for the equation for the line (y = mx+c)
            m0 = (y2-y1) / (x2-x1); 
            c0 = y2 -(m0 * x2);
			
			m1 = (y2-y0) / (x2-x0); 
            c1 = y0 -(m1 * x0);
			
			m2 = (y1-y0) / (x1-x0); 
            c2 = y0 -(m2 * x0);
			
			t0 = int(x0 * m0 + c0 > y0);
			t1 = int(x1 * m1 + c1 > y1);
			t2 = int(x2 * m2 + c2 > y2);
			
			lm0 = l * m0 + c0;
			lm1 = l * m1 + c1;
			lm2 = l * m2 + c2;
			
			rm0 = r * m0 + c0;
			rm1 = r * m1 + c1;
			rm2 = r * m2 + c2;
			
			if ( !(t0 ^ int( lm0 > t)) && !(t1 ^ int(lm1 > t)) && !(t2 ^ int(lm2 > t))) return true;
			
			if (!(t0 ^ int( lm0 > b)) && !(t1 ^ int(lm1 > b)) && !(t2 ^ int(lm2 > b))) return true;
			
			if ( !(t0 ^ int( rm0 > t)) && !(t1 ^ int(rm1 > t)) && !(t2 ^ int(rm2 > t))) return true;
			
			if (!(t0 ^ int( rm0 > b)) && !(t1 ^ int(rm1 > b)) && !(t2 ^ int(rm2 > b))) return true;
			
			return false;
 
      }
 
      public function isIntersecting(xa: Number,ya: Number,xb: Number,yb: Number):Boolean
      { 
            // Calculate m and c for the equation for the line (y = mx+c)
            m = (yb-ya) / (xb-xa); 
            c = ya -(m * xa);
			
			if ((ya - t) * (yb - t) < 0)
			{
				s = (t - c) / m;
				if ( s > l && s < r) return true;	
			}
			
			if ((ya - b) * (yb - b) < 0)
			{
				s = (b - c) / m;
				if ( s > l && s < r) return true;	
			}
			
			if ((xa - l) * (xb - l) < 0)
			{
				s = m * l + c;
				if ( s > t && s < b) return true
			}
			
			if ((xa - r) * (xb - r) < 0)
			{
				s = m * r + c
				if ( s > t && s < b) return true;
			}
			
			
			
			return false;
 
      }
 
      public function startTest(e:MouseEvent = null) : void
      {
         var g : Graphics = graphics; 
         g.clear(); 
         var cullingRect : Rectangle = new Rectangle(-100,-75,200,150); 
 
         var iterations : int = 100000; 
         var timerIntersecting : int = 0 ; 
         var timerNotIntersecting : int = 0 ; 
                        var intersectCount : int = 0; 
 
         var v0 : Point = new Point(); 
         var v1 : Point = new Point(); 
         var v2 : Point = new Point(); 
 
         var i : int = iterations; 
 
         while(--i>-1)
         {
            v0.x = Math.random()*400 - 200; 
            v0.y = Math.random()*400 - 200; 
            v1.x = v0.x+ (Math.random()*300 -150); 
            v1.y = v0.y+ (Math.random()*300 -150); 
            v2.x = v0.x+ (Math.random()*300 -150); 
            v2.y = v0.y+ (Math.random()*300 -150);             
 
            var startTimer : int = getTimer(); 
            var intersecting : Boolean = triangleTest(cullingRect, v0, v1, v2); 
            if(intersecting)
            {
               timerIntersecting += (getTimer() - startTimer);
               intersectCount++; 
            }
            else 
            {
               timerNotIntersecting += (getTimer() - startTimer);
            }
            if(i<300)
            {
               g.lineStyle(0,0x000000); 
               g.beginFill(intersecting ? 0x006600 : 0x660000,0.5); 
               g.moveTo(x0,y0); 
               g.lineTo(x1,y1); 
               g.lineTo(x2,y2); 
               g.lineTo(x0,y0); 
               g.endFill(); 
            }
         }
 
         g.lineStyle(0,0xffffff,0.5); 
         g.drawRect(cullingRect.x, cullingRect.y, cullingRect.width, cullingRect.height); 
         outputText.text = "Average time per triangle : "+(timerIntersecting+timerNotIntersecting)/iterations; 
         outputText.appendText("\nAverage time per intersecting triangle : "+(timerIntersecting)/intersectCount); 
         outputText.appendText("\nAverage time per non-intersecting triangle : "+(timerNotIntersecting)/(iterations-intersectCount)); 
 
      }
 
   }
}