private void ProjectPolygon() { var norm = _normal; bool computedNormal = false; if (norm.X == 0.0f && norm.Y == 0.0f && norm.Z == 0.0f) { ComputeNormal(ref norm); _normal = norm; computedNormal = true; } int i = Vec3.LongAxis(ref norm); _sUnit[i] = 0; _sUnit[(i + 1) % 3] = SUnitX; _sUnit[(i + 2) % 3] = SUnitY; _tUnit[i] = 0; _tUnit[(i + 1) % 3] = norm[i] > 0.0f ? -SUnitY : SUnitY; _tUnit[(i + 2) % 3] = norm[i] > 0.0f ? SUnitX : -SUnitX; // Project the vertices onto the sweep plane for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next) { Vec3.Dot(ref v._coords, ref _sUnit, out v._s); Vec3.Dot(ref v._coords, ref _tUnit, out v._t); } if (computedNormal) { CheckOrientation(); } // Compute ST bounds. bool first = true; for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next) { if (first) { _bminX = _bmaxX = v._s; _bminY = _bmaxY = v._t; first = false; } else { if (v._s < _bminX) { _bminX = v._s; } if (v._s > _bmaxX) { _bmaxX = v._s; } if (v._t < _bminY) { _bminY = v._t; } if (v._t > _bmaxY) { _bmaxY = v._t; } } } }
private void ComputeNormal(ref Vec3 norm) { var v = _mesh._vHead._next; var minVal = new Real[3] { v._coords.X, v._coords.Y, v._coords.Z }; var minVert = new MeshUtils.Vertex[3] { v, v, v }; var maxVal = new Real[3] { v._coords.X, v._coords.Y, v._coords.Z }; var maxVert = new MeshUtils.Vertex[3] { v, v, v }; for (; v != _mesh._vHead; v = v._next) { if (v._coords.X < minVal[0]) { minVal[0] = v._coords.X; minVert[0] = v; } if (v._coords.Y < minVal[1]) { minVal[1] = v._coords.Y; minVert[1] = v; } if (v._coords.Z < minVal[2]) { minVal[2] = v._coords.Z; minVert[2] = v; } if (v._coords.X > maxVal[0]) { maxVal[0] = v._coords.X; maxVert[0] = v; } if (v._coords.Y > maxVal[1]) { maxVal[1] = v._coords.Y; maxVert[1] = v; } if (v._coords.Z > maxVal[2]) { maxVal[2] = v._coords.Z; maxVert[2] = v; } } // Find two vertices separated by at least 1/sqrt(3) of the maximum // distance between any two vertices int i = 0; if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0]) { i = 1; } if (maxVal[2] - minVal[2] > maxVal[i] - minVal[i]) { i = 2; } if (minVal[i] >= maxVal[i]) { // All vertices are the same -- normal doesn't matter norm = new Vec3 { X = 0, Y = 0, Z = 1 }; return; } // Look for a third vertex which forms the triangle with maximum area // (Length of normal == twice the triangle area) Real maxLen2 = 0, tLen2; var v1 = minVert[i]; var v2 = maxVert[i]; Vec3 d1, d2, tNorm; Vec3.Sub(ref v1._coords, ref v2._coords, out d1); for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next) { Vec3.Sub(ref v._coords, ref v2._coords, out d2); tNorm.X = d1.Y * d2.Z - d1.Z * d2.Y; tNorm.Y = d1.Z * d2.X - d1.X * d2.Z; tNorm.Z = d1.X * d2.Y - d1.Y * d2.X; tLen2 = tNorm.X * tNorm.X + tNorm.Y * tNorm.Y + tNorm.Z * tNorm.Z; if (tLen2 > maxLen2) { maxLen2 = tLen2; norm = tNorm; } } if (maxLen2 <= 0.0f) { // All points lie on a single line -- any decent normal will do norm = Vec3.Zero; i = Vec3.LongAxis(ref d1); norm[i] = 1; } }