Any reliable polygon normal calculation code?
Posted
by
Jenko
on Game Development
See other posts from Game Development
or by Jenko
Published on 2011-02-06T05:38:51Z
Indexed on
2011/02/06
7:33 UTC
Read the original article
Hit count: 380
Do you have any reliable face normal calculation code?
I'm using this but it fails when faces are 90 degrees upright or similar.
// the normal point
var x:Number = 0;
var y:Number = 0;
var z:Number = 0;
// if is a triangle with 3 points
if (points.length == 3) {
// read vertices of triangle
var Ax:Number, Bx:Number, Cx:Number;
var Ay:Number, By:Number, Cy:Number;
var Az:Number, Bz:Number, Cz:Number;
Ax = points[0].x; Bx = points[1].x; Cx = points[2].x;
Ay = points[0].y; By = points[1].y; Cy = points[2].y;
Az = points[0].z; Bz = points[1].z; Cz = points[2].z;
// calculate normal of a triangle
x = (By - Ay) * (Cz - Az) - (Bz - Az) * (Cy - Ay);
y = (Bz - Az) * (Cx - Ax) - (Bx - Ax) * (Cz - Az);
z = (Bx - Ax) * (Cy - Ay) - (By - Ay) * (Cx - Ax);
// if is a polygon with 4+ points
}else if (points.length > 3){
// calculate normal of a polygon using all points
var n:int = points.length;
x = 0;
y = 0;
z = 0
// ensure all points above 0
var minx:Number = 0, miny:Number = 0, minz:Number = 0;
for (var p:int = 0, pl:int = points.length; p < pl; p++) {
var po:_Point3D = points[p] = points[p].clone();
if (po.x < minx) { minx = po.x; }
if (po.y < miny) { miny = po.y; }
if (po.z < minz) { minz = po.z; }
}
if (minx > 0 || miny > 0 || minz > 0){
for (p = 0; p < pl; p++) {
po = points[p];
po.x -= minx;
po.y -= miny;
po.z -= minz;
}
}
var cur:int = 1, prev:int = 0, next:int = 2;
for (var i:int = 1; i <= n; i++) {
// using Newell method
x += points[cur].y * (points[next].z - points[prev].z);
y += points[cur].z * (points[next].x - points[prev].x);
z += points[cur].x * (points[next].y - points[prev].y);
cur = (cur+1) % n;
next = (next+1) % n;
prev = (prev+1) % n;
}
}
// length of the normal
var length:Number = Math.sqrt(x * x + y * y + z * z);
// if area is 0
if (length == 0) {
return null;
}else{
// turn large values into a unit vector
x = x / length;
y = y / length;
z = z / length;
}
© Game Development or respective owner