forked from: flash on 2009-5-30
forked from flash on 2009-5-30 (diff: 170)
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/41Bh
*/
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="0x000000", 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 = 0xffffff;
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 b0 :int;
private var b1 :int;
private var b2 :int;
private var i0 :int;
private var i1 :int;
private var i2 :int;
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;
b0 = int(x0 > l) | int(y0 > t) << 1 | int (x0 > r) << 2 | int (y0 > b) << 3;
if (b0 == 3) return true;
b1 = int(x1 > l) | int(y1 > t) << 1 | int (x1 > r) << 2 | int (y1 > b) << 3;
if (b1 == 3) return true;
b2 = int(x2 > l) | int(y2 > t) << 1 | int (x2 > r) << 2 | int (y2 > b) << 3;
if (b2 == 3) return true;
i0 = b0 ^ b1
if (i0 != 0)
{
m = (y1-y0) / (x1-x0);
c = y0 -(m * x0);
if (Boolean(i0 & 1)) { s = m * l + c; if ( s > t && s < b) return true; }
if (Boolean(i0 & 2)) { s = (t - c) / m; if ( s > l && s < r) return true; }
if (Boolean(i0 & 4)) { s = m * r + c; if ( s > t && s < b) return true; }
if (Boolean(i0 & 8)) { s = (b - c) / m; if ( s > l && s < r) return true; }
}
i1 = b1 ^ b2
if (i1 != 0)
{
m = (y2-y1) / (x2-x1);
c = y1 -(m * x1);
if (Boolean(i1 & 1)) { s = m * l + c; if ( s > t && s < b) return true; }
if (Boolean(i1 & 2)) { s = (t - c) / m; if ( s > l && s < r) return true; }
if (Boolean(i1 & 4)) { s = m * r + c; if ( s > t && s < b) return true; }
if (Boolean(i1 & 8)) { s = (b - c) / m; if ( s > l && s < r) return true; }
}
i2 = b0 ^ b2
if (i2 != 0)
{
m = (y2-y0) / (x2-x0);
c = y0 -(m * x0);
if (Boolean(i2 & 1)) { s = m * l + c; if ( s > t && s < b) return true; }
if (Boolean(i2 & 2)) { s = (t - c) / m; if ( s > l && s < r) return true; }
if (Boolean(i2 & 4)) { s = m * r + c; if ( s > t && s < b) return true; }
if (Boolean(i2 & 8)) { s = (b - c) / m; if ( s > l && s < r) 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));
}
}
}
