int ComputeNormal(ref double nx, ref double ny, ref double nz)
/*
* Check that each triangle in the fan from v0 has a
* consistent orientation with respect to norm3[]. If triangles are
* consistently oriented CCW, return 1; if CW, return -1; if all triangles
* are degenerate return 0; otherwise (no consistent orientation) return
* SIGN_INCONSISTENT.
*/
{
var vCache = this.simpleVertexCache;
Vertex v0 = vCache[0];
int vcIndex;
double dot, xc, yc, xp, yp;
double n0;
double n1;
double n2;
int sign = 0;
/* Find the polygon normal. It is important to get a reasonable
* normal even when the polygon is self-intersecting (eg. a bowtie).
* Otherwise, the computed normal could be very tiny, but perpendicular
* to the true plane of the polygon due to numerical noise. Then all
* the triangles would appear to be degenerate and we would incorrectly
* decompose the polygon as a fan (or simply not render it at all).
*
* We use a sum-of-triangles normal algorithm rather than the more
* efficient sum-of-trapezoids method (used in CheckOrientation()
* in normal.c). This lets us explicitly reverse the signed area
* of some triangles to get a reasonable normal in the self-intersecting
* case.
*/
vcIndex = 1;
var v = vCache[vcIndex];
xc = v.x - v0.x;
yc = v.y - v0.y;
int c_count = this.cacheCount;
while (++vcIndex < c_count)
{
xp = xc; yp = yc;
v = vCache[vcIndex];
xc = v.x - v0.x;
yc = v.y - v0.y;
/* Compute (vp - v0) cross (vc - v0) */
n0 = 0;
n1 = 0;
n2 = xp * yc - yp * xc;
dot = n0 * nx + n1 * ny + n2 * nz;
if (dot != 0)
{
/* Check the new orientation for consistency with previous triangles */
if (dot > 0)
{
if (sign < 0)
{
return SIGN_INCONSISTENT;
}
sign = 1;
}
else
{
if (sign > 0)
{
return SIGN_INCONSISTENT;
}
sign = -1;
}
}
}
return sign;
}