public static void CalculateTargetPositionForPairContraction(ref MeshPairContraction pair, Vector3[] verts, Quadric[] vertQuadrics) { Vector3 v0 = verts[pair.v0], v1 = verts[pair.v1]; Quadric Q0 = vertQuadrics[pair.v0], Q1 = vertQuadrics[pair.v1]; Quadric Q = Q0 + Q1; if (Q.Optimize(ref pair.contractedPosition, 1e-12)) { pair.error = Q.Evaluate(pair.contractedPosition); } else { double ei = Q.Evaluate(v0), ej = Q.Evaluate(v1); if (ei < ej) { pair.error = ei; pair.contractedPosition = v0; } else { pair.error = ej; pair.contractedPosition = v1; } } }
//Returns an array of quadrics for evaluating the error of each possible contraction public static Quadric[] CalculateVertQuadrics(Vector3[] verts, MeshIndexTriangle[] indexTris) { Quadric[] vertQuadrics = new Quadric[verts.Length]; for (int i = 0; i < vertQuadrics.Length; i++) { vertQuadrics[i] = new Quadric(); } foreach (MeshIndexTriangle tri in indexTris) { Vector3 v0, v1, v2; v0 = verts[tri.v0]; v1 = verts[tri.v1]; v2 = verts[tri.v2]; double area = PANELFARTriangleUtils.triangle_area(v0, v1, v2); Vector4 p; if (area > 0) { p = PANELFARTriangleUtils.triangle_plane(v0, v1, v2); } else { p = PANELFARTriangleUtils.triangle_plane(v2, v1, v0); area = -area; } Quadric Q = new Quadric(p.x, p.y, p.z, p.w, area); // Area-weight quadric and add it into the three quadrics for the corners Q *= Q.area; vertQuadrics[tri.v0] += Q; vertQuadrics[tri.v1] += Q; vertQuadrics[tri.v2] += Q; } return(vertQuadrics); }