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); computedNormal = true; } int i = Vec3.LongAxis(ref norm); _sUnit [i] = 0.0f; _sUnit [(i + 1) % 3] = SUnitX; _sUnit [(i + 2) % 3] = SUnitY; _tUnit [i] = 0.0f; _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 float[3] { v._coords.X, v._coords.Y, v._coords.Z }; var minVert = new MeshUtils.Vertex[3] { v, v, v }; var maxVal = new float[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.0f, Y = 0.0f, Z = 1.0f }; return; } // Look for a third vertex which forms the triangle with maximum area // (Length of normal == twice the triangle area) float maxLen2 = 0.0f, 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.0f; } }