Beispiel #1
0
        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);
        }
Beispiel #2
0
        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];
     }
 }
Beispiel #6
0
        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());
        }
Beispiel #7
0
        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);
                }
            }
        }
Beispiel #8
0
        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);
            }
        }