bool _determineEdgeContraintForEdge(int edgeIndex, ref PlaneDistanceError pde) { float weight = 0.0f; if (mesh.IsEdgeBorder(edgeIndex)) { weight = _parameters.borderWeight; } else { if (mesh.edges[edgeIndex].crease == 1.0f) { weight = Mathf.Max(weight, _parameters.creaseWeight); } if (mesh.numMaterials > 1 && mesh.isEdgeMaterialSeam(edgeIndex)) { weight = Mathf.Max(weight, _parameters.materialSeamWeight); } if (mesh.hasUV1 && mesh.IsEdgeUV1Seam(edgeIndex)) { weight = Mathf.Max(weight, _parameters.uvSeamWeight); } if (mesh.hasUV2 && mesh.IsEdgeUV2Seam(edgeIndex)) { weight = Mathf.Max(weight, _parameters.uv2SeamWeight); } } if (weight > 0.0f) { _determinePdeToConstrainEdge(mesh.edges[edgeIndex], weight, ref pde); return(true); } return(false); }
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); } }
public static PlaneDistanceError operator +(PlaneDistanceError a, PlaneDistanceError b) { PlaneDistanceError res = new PlaneDistanceError(a); res.OpAdd(b); return(res); }
public void OpAdd(PlaneDistanceError b) { _fact += b._fact; for (int i = 0; i < 10; ++i) { cf[i] += b.cf[i]; } }
public PlaneDistanceError(PlaneDistanceError b) { _fact = b._fact; for (int i = 0; i < 10; ++i) { cf[i] = b.cf[i]; } }
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 _calculatePdePerVertex() { // This constructs a error term for every vertex based on the surrounding faces // The value of this term is a sum of the squared distances to all the planes if (mesh == null) { Debug.LogError("Mesh is not initialized. Could not calculate plane distance errors."); return; } int numVerts = mesh.vertCount(); int numFaces = mesh.faceCount(); // Initialize pdes pdePerVertex = new PlaneDistanceError[numVerts]; for (int i = 0; i < numVerts; ++i) { pdePerVertex[i] = new PlaneDistanceError(); } PlaneDistanceError pde = new PlaneDistanceError(); for (int faceIndex = 0; faceIndex < numFaces; ++faceIndex) { _determinePdeForFace(faceIndex, ref pde); // Add to all point errors of the face KrablMesh.Face face = mesh.faces[faceIndex]; for (int i = 0; i < face.cornerCount; ++i) { pdePerVertex[face.v[i]].OpAdd(pde); } } // Mesh constrains int numEdges = mesh.edgeCount(); // Look for border vertices and mesh discontinuities for (int edgeIndex = 0; edgeIndex < numEdges; ++edgeIndex) { if (_determineEdgeContraintForEdge(edgeIndex, ref pde)) { Edge edge = mesh.edges[edgeIndex]; pdePerVertex[edge.v[0]].OpAdd(pde); pdePerVertex[edge.v[1]].OpAdd(pde); } } }
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); } }