void _determinePdeToConstrainEdge(Edge edge, float weight, ref PlaneDistanceError pde) { int vi0 = edge.v[0]; int vi1 = edge.v[1]; Vector3 v0 = mesh.vertices[vi0].coords; Vector3 vEdge = mesh.vertices[vi1].coords - v0; Vector3 edgeNormal; pde.Clear(); float mag = vEdge.sqrMagnitude; for (int i = 0; i < edge.linkedFaces.Count; ++i) { edgeNormal = mesh.faces[edge.linkedFaces[i]].normal; Vector3 n = Vector3.Cross(vEdge, edgeNormal); // normal to edge and face UnityUtils.NormalizeSmallVector(ref n); float d = -Vector3.Dot(n, v0); pde2.Set(n.x, n.y, n.z, d, mag); // Multiply by face area (factor) for weighting pde2.OpMul(pde2.Factor() * weight * 0.5f); pde.OpAdd(pde2); } }
void _determinePdeForFace(int faceIndex, ref PlaneDistanceError pde) { KrablMesh.Face face = mesh.faces[faceIndex]; Vector3 n = mesh.CalculateFaceNormal(faceIndex); // Create error struct from the plane of the face (using face normal) float offset = -Vector3.Dot(n, mesh.vertices[face.v[0]].coords); pde.Set(n.x, n.y, n.z, offset, mesh.CalculateFaceArea(faceIndex)); // Multiply by face area (factor) for weighting pde.OpMul(pde.Factor()); }
void _calculateEdgeCost(int edgeIndex, CollapseInfo cinfo) { Edge edge = mesh.edges[edgeIndex]; int vindex0 = edge.v[0]; int vindex1 = edge.v[1]; Vertex v0 = mesh.vertices[vindex0]; Vertex v1 = mesh.vertices[vindex1]; cinfo.vp = edge; PlaneDistanceError pde = pdePerVertex[edge.v[0]] + pdePerVertex[edge.v[1]]; if (_parameters.recalculateVertexPositions) { if (mesh.IsEdgeBorder(edgeIndex) == false && pde.OptimalVertex(ref cinfo.targetPosition)) { cinfo.cost = (float)pde.CalculateError(cinfo.targetPosition); // Debug.Log(">optimal placement"); } else if (pde.OptimalVertexLinear(ref cinfo.targetPosition, v0.coords, v1.coords)) { // the error term is not solvable // Try to find a vert on the line going from v0 to v1 cinfo.cost = (float)pde.CalculateError(cinfo.targetPosition); // Debug.Log(">line placement"); } else { // Choose vert from the two endpoints and the midpoint Vector3 tp = 0.5f * (v0.coords + v1.coords); double error0 = pde.CalculateError(v0.coords); double error1 = pde.CalculateError(v1.coords); double error2 = pde.CalculateError(tp); if (error0 < error1) { if (error0 < error2) { cinfo.targetPosition = v0.coords; cinfo.cost = (float)error0; } else { cinfo.targetPosition = tp; cinfo.cost = (float)error2; } } else { if (error1 < error2) { cinfo.targetPosition = v1.coords; cinfo.cost = (float)error1; } else { cinfo.targetPosition = tp; cinfo.cost = (float)error2; } } } } else { double error0 = pde.CalculateError(v0.coords); double error1 = pde.CalculateError(v1.coords); if (error0 < error1) { cinfo.targetPosition = v0.coords; cinfo.cost = (float)error0; } else { cinfo.targetPosition = v1.coords; cinfo.cost = (float)error1; } } // Choose minimal error point -> bad for border edges which are underdefined if (localizeErrors) { cinfo.cost *= 1.0f / ((float)pde.Factor()); } cinfo.positionCost = cinfo.cost; if (noPenalties == false) { _updateEdgePenalties(edgeIndex, cinfo, -1); } }