public static int LongAxis(ref Vec3 v) { int i = 0; if (Math.Abs(v.Y) > Math.Abs(v.X)) i = 1; if (Math.Abs(v.Z) > Math.Abs(i == 0 ? v.X : v.Y)) i = 2; return i; }
public static void Normalize(ref Vec3 v) { float len = v.X * v.X + v.Y * v.Y + v.Z * v.Z; Debug.Assert(len >= 0.0f); len = 1.0f / (float)Math.Sqrt(len); v.X *= len; v.Y *= len; v.Z *= len; }
// The data array contains 4 values, it's the associated data of the vertices that resulted in an intersection. private static object VertexCombine(LibTessDotNet.Vec3 position, object[] data, float[] weights) { // Fetch the vertex data. var colors = new Color[] { (Color)data[0], (Color)data[1], (Color)data[2], (Color)data[3] }; // Interpolate with the 4 weights. var rgba = new float[] { (float)colors[0].R * weights[0] + (float)colors[1].R * weights[1] + (float)colors[2].R * weights[2] + (float)colors[3].R * weights[3], (float)colors[0].G * weights[0] + (float)colors[1].G * weights[1] + (float)colors[2].G * weights[2] + (float)colors[3].G * weights[3], (float)colors[0].B * weights[0] + (float)colors[1].B * weights[1] + (float)colors[2].B * weights[2] + (float)colors[3].B * weights[3], (float)colors[0].A * weights[0] + (float)colors[1].A * weights[1] + (float)colors[2].A * weights[2] + (float)colors[3].A * weights[3] }; // Return interpolated data for the new vertex. return(Color.FromArgb((int)rgba[3], (int)rgba[0], (int)rgba[1], (int)rgba[2])); }
private object VertexCombine(Vec3 position, object[] data, float[] weights) { var colors = new Color[] { (Color)data[0], (Color)data[1], (Color)data[2], (Color)data[3] }; var rgba = new float[] { colors[0].R * weights[0] + colors[1].R * weights[1] + colors[2].R * weights[2] + colors[3].R * weights[3], colors[0].G * weights[0] + colors[1].G * weights[1] + colors[2].G * weights[2] + colors[3].G * weights[3], colors[0].B * weights[0] + colors[1].B * weights[1] + colors[2].B * weights[2] + colors[3].B * weights[3], colors[0].A * weights[0] + colors[1].A * weights[1] + colors[2].A * weights[2] + colors[3].A * weights[3] }; return Color.FromArgb((int)rgba[3], (int)rgba[0], (int)rgba[1], (int)rgba[2]); }
public static void Neg(ref Vec3 v) { v.X = -v.X; v.Y = -v.Y; v.Z = -v.Z; }
public static void Dot(ref Vec3 u, ref Vec3 v, out float dot) { dot = u.X * v.X + u.Y * v.Y + u.Z * v.Z; }
public static void Sub(ref Vec3 lhs, ref Vec3 rhs, out Vec3 result) { result.X = lhs.X - rhs.X; result.Y = lhs.Y - rhs.Y; result.Z = lhs.Z - rhs.Z; }
private Vec3 Project(Vec3 v) { Vec3 norm = _tess.Normal; int i = Vec3.LongAxis(ref norm); Vec3 sUnit = Vec3.Zero; sUnit[i] = 0.0f; sUnit[(i + 1) % 3] = _tess.SUnitX; sUnit[(i + 2) % 3] = _tess.SUnitY; Vec3 tUnit = Vec3.Zero; tUnit[i] = 0.0f; tUnit[(i + 1) % 3] = norm[i] > 0.0f ? -_tess.SUnitY : _tess.SUnitY; tUnit[(i + 2) % 3] = norm[i] > 0.0f ? _tess.SUnitX : -_tess.SUnitX; Vec3 result = Vec3.Zero; // Project the vertices onto the sweep plane Vec3.Dot(ref v, ref sUnit, out result.X); Vec3.Dot(ref v, ref tUnit, out result.Y); return result; }
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; } }
public Tess() { _normal = Vec3.Zero; _bminX = _bminY = _bmaxX = _bmaxY = 0.0f; _windingRule = WindingRule.EvenOdd; _mesh = null; _vertices = null; _vertexCount = 0; _elements = null; _elementCount = 0; }
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; } }
public static void Dot(ref Vec3 u, ref Vec3 v, out float dot) { dot = u.X * v.X + u.Y * v.Y + u.Z * v.Z; }
public static void Neg(ref Vec3 v) { v.X = 0f - v.X; v.Y = 0f - v.Y; v.Z = 0f - v.Z; }
public static void Sub(ref Vec3 lhs, ref Vec3 rhs, out Vec3 result) { result.X = lhs.X - rhs.X; result.Y = lhs.Y - rhs.Y; result.Z = lhs.Z - rhs.Z; }