Пример #1
0
        public void RemoveIfNonNeighbor(Vert v)
        {
            int i;
            int foundAt = -1;
            int n       = neighbor.Count;
            Tri f;

            for (i = 0; i < n; ++i)
            {
                if (neighbor[i] == v)
                {
                    foundAt = i; break;
                }
            }

            if (foundAt == -1)
            {
                return;
            }

            n = face.Count;
            for (i = 0; i < n; ++i)
            {
                f = face[i];
                if (f.HasVertex(v))
                {
                    return;
                }
            }

            neighbor.Remove(v);
        }
        private void SortLeft(Vert v)
        {
            int cacheIndex = cache.IndexOf(v);

            if (cacheIndex == searchIndex)
            {
                return;
            }

            float cost = v.cost;
            Vert  c2   = cache[cacheIndex - 1];

            if (cost == c2.cost)
            {
                return;
            }

            while (cost < c2.cost && cacheIndex > searchIndex + 2)
            {
                cache[cacheIndex--] = c2;
                c2 = cache[cacheIndex - 1];
            }
            if (cost < c2.cost)
            {
                cache[cacheIndex--] = c2;
            }
            cache[cacheIndex] = v;
        }
        private void SortRight(Vert v)
        {
            int cacheIndex = cache.IndexOf(v);

            if (cacheIndex == cacheSize - 1)
            {
                return;
            }

            float cost = v.cost;
            Vert  c2   = cache[cacheIndex + 1];

            if (cost == c2.cost)
            {
                return;
            }

            int maxIndex = cacheSize - 2;

            while (cost > c2.cost && cacheIndex < maxIndex)
            {
                cache[cacheIndex++] = c2;
                c2 = cache[cacheIndex + 1];
            }
            if (cost > c2.cost)
            {
                cache[cacheIndex++] = c2;
            }
            cache[cacheIndex] = v;
        }
        private void ComputeEdgeCostAtVertex(Vert v)
        {
            // compute the edge collapse cost for all edges that start
            // from vertex v.  Since we are only interested in reducing
            // the object by selecting the min cost edge at each step, we
            // only cache the cost of the least cost edge at this vertex
            // (in member variable collapse) as well as the value of the
            // cost (in member variable cost).
            if (v.neighbor.Count == 0)
            {
                // v doesn't have neighbors so it costs nothing to collapse
                v.collapse = null;
                v.cost     = 0;//-0.01f;
                return;
            }
            v.cost     = 65535;
            v.collapse = null;
            // search all neighboring edges for "least cost" edge
            int   neighborCount = v.neighbor.Count;
            float cost;

            for (int i = 0; i < neighborCount; ++i)
            {
                cost = ComputeEdgeCollapseCosts(v, v.neighbor[i]);
                if (cost < v.cost)
                {
                    v.collapse = v.neighbor[i]; // candidate for edge collapse
                    v.cost     = cost;          // cost of the collapse
                }
            }
        }
Пример #5
0
        public Vert(Vector3 position, int id, bool selected)
        {
            this.position = position;
            this.id       = id;
            this.selected = selected;

            cost     = 0f;
            collapse = null;
        }
Пример #6
0
        public void ReplaceVertex(Vert vo, Vert vnew, Vector2 newUV, Vector3 newVN, History his)
        {
            Vector3 vec             = vo.position;
            Vert    changedVertex   = v2;
            int     changedVertexId = 2;
            Vector3 changedNormal   = vn2;
            Vector2 changedUV       = uv2;

            if (vec == v0.position)
            {
                changedVertex   = v0;
                changedVertexId = 0;
                changedNormal   = vn0;
                changedUV       = uv0;
                v0  = vnew;
                vn0 = newVN;
                uv0 = newUV;
            }
            else if (vec == v1.position)
            {
                changedVertex   = v1;
                changedVertexId = 1;
                changedNormal   = vn1;
                changedUV       = uv1;
                v1  = vnew;
                vn1 = newVN;
                uv1 = newUV;
            }
            else
            {
                v2  = vnew;
                vn2 = newVN;
                uv2 = newUV;
            }

            vo.RemoveFace(this);
            vnew.AddFace(this);

            vo.RemoveIfNonNeighbor(v0);
            v0.RemoveIfNonNeighbor(vo);
            vo.RemoveIfNonNeighbor(v1);
            v1.RemoveIfNonNeighbor(vo);
            vo.RemoveIfNonNeighbor(v2);
            v2.RemoveIfNonNeighbor(vo);

            v0.AddNeighbor(v1);
            v0.AddNeighbor(v2);
            v1.AddNeighbor(v0);
            v1.AddNeighbor(v2);
            v2.AddNeighbor(v0);
            v2.AddNeighbor(v1);

            RecalculateNormal();

            his.ReplaceVertex(id, changedVertexId, changedVertex.id, changedNormal, changedUV, vnew.id, newVN, newUV);
        }
        private void ComputeAllEdgeCollapseCosts()
        {
            // For all the edges, compute the difference it would make
            // to the model if it was collapsed.  The least of these
            // per vertex is cached in each vertex object.
            int count = myLODVertices.Length;

            for (int i = 0; i < count; ++i)
            {
                Vert v = myLODVertices[i];
                ComputeEdgeCostAtVertex(v);
                cache.Insert(i, v);
            }
        }
Пример #8
0
 public int Compare(System.Object x, System.Object y)
 {
     vx = (Vert)x;
     vy = (Vert)y;
     if (vx == vy)
     {
         return(0);
     }
     else if (vx.cost < vy.cost)
     {
         return(-1);
     }
     return(1);
 }
Пример #9
0
        public void setVN(Vert v, Vector3 newNormal)
        {
            Vector3 vec = v.position;

            if (vec == v0.position)
            {
                vn0 = newNormal;
            }
            else if (vec == v1.position)
            {
                vn1 = newNormal;
            }
            else if (vec == v2.position)
            {
                vn2 = newNormal;
            }
        }
Пример #10
0
        public void setUV(Vert v, Vector2 newuv)
        {
            Vector3 vec = v.position;

            if (vec == v0.position)
            {
                uv0 = newuv;
            }
            else if (vec == v1.position)
            {
                uv1 = newuv;
            }
            else if (vec == v2.position)
            {
                uv2 = newuv;
            }
        }
Пример #11
0
        public Vector3 normalAt(Vert v)
        {
            Vector3 vec = v.position;

            if (vec == v0.position)
            {
                return(vn0);
            }
            else if (vec == v1.position)
            {
                return(vn1);
            }
            else if (vec == v2.position)
            {
                return(vn2);
            }
            return(new Vector3());
        }
Пример #12
0
        public Vector2 uvAt(Vert v)
        {
            Vector3 vec = v.position;

            if (vec == v0.position)
            {
                return(uv0);
            }
            else if (vec == v1.position)
            {
                return(uv1);
            }
            else if (vec == v2.position)
            {
                return(uv2);
            }
            return(new Vector2());
        }
Пример #13
0
        public void AddNeighbor(Vert v)
        {
            int i;
            int foundAt = -1;
            int n       = neighbor.Count;

            for (i = 0; i < n; ++i)
            {
                if (neighbor[i] == v)
                {
                    foundAt = i; break;
                }
            }

            if (foundAt == -1)
            {
                neighbor.Add(v);
            }
        }
Пример #14
0
        public Tri(int id, Vert v0, Vert v1, Vert v2, Vector2 uv0, Vector2 uv1, Vector2 uv2)
        {
            this.id  = id;
            this.v0  = v0;
            this.v1  = v1;
            this.v2  = v2;
            this.uv0 = uv0;
            this.uv1 = uv1;
            this.uv2 = uv2;

            RecalculateNormal();

            v0.AddFace(this);
            v1.AddFace(this);
            v2.AddFace(this);

            v0.AddNeighbor(v1);
            v0.AddNeighbor(v2);
            v1.AddNeighbor(v0);
            v1.AddNeighbor(v2);
            v2.AddNeighbor(v0);
            v2.AddNeighbor(v1);
        }
        private void ComputeProgressiveMesh()
        {
            int i;
            int j;
            int n;
            Tri t;

            int vertexCount   = sharedVertices.Length;
            int triangleCount = sharedTriangles.Length;

            System.Array.Clear(myLODVertices, 0, myLODVertices.Length);
            for (i = 0; i < vertexCount; ++i)
            {
                Vector3 dv  = sharedVertices[i];
                bool    sel = false;

                n = selectedVertices.Count;
                for (j = 0; j < n; ++j)
                {
                    if (selectedVertices[j] == dv)
                    {
                        sel = true;
                        break;
                    }
                }
                myLODVertices[i] = new Vert(dv, i, sel);
            }

            // new myTris
            System.Array.Clear(myTriangles, 0, myTriangles.Length);
            int cnt = 0;

            for (i = 0; i < triangleCount; i += 3)
            {
                t = new Tri(cnt,
                            myLODVertices[sharedTriangles[i]],
                            myLODVertices[sharedTriangles[i + 1]],
                            myLODVertices[sharedTriangles[i + 2]],
                            originalUVs[originalTriangles[i]],
                            originalUVs[originalTriangles[i + 1]],
                            originalUVs[originalTriangles[i + 2]]);

                t.SetDefaultIndices(originalTriangles[i], originalTriangles[i + 1], originalTriangles[i + 2]);
                if (bRecalculateNormals)
                {
                    t.vn0 = t.vn1 = t.vn2 = t.normal;
                }
                else
                {
                    t.vn0 = originalNormals[originalTriangles[i]];
                    t.vn1 = originalNormals[originalTriangles[i + 1]];
                    t.vn2 = originalNormals[originalTriangles[i + 2]];
                }

                myTriangles[cnt] = t;
                ++cnt;
            }

            cache     = new List <Vert>();
            cacheSize = vertexCount;

            if (bRecalculateNormals)
            {
                RecalculateNormal();       // set normals for vertex.
            }
            ComputeAllEdgeCollapseCosts(); // cache all edge collapse costs
            //System.Array.Sort(cache, myComparer); // lower cost to the left.
            cache = cache.OrderBy(p => p.cost).ToList();

            collapseHistory = new History[vertexCount];

            currentcnt  = myLODVertices.Length + 1;
            searchIndex = 0;
            while (--currentcnt > 0)
            {
                CollapseTest();
            }


            // LOD Data size calculation
            n = collapseHistory.Length;
            int     tmpBytes = 0;
            History tmpHis;

            for (i = 0; i < n; ++i)
            {
                tmpHis    = collapseHistory[i];
                tmpBytes += (
                    tmpHis.removedTriangles.Count * 2 +
                    tmpHis.replacedVertex.Count * 14
                    ) * 4;
            }
            lodDataSize = tmpBytes;
        }
        public void Calculate(Mesh tmpMesh)
        {
            ProgressiveMesh(ratio);

            int     i;
            int     j;
            int     foundAt = -1;
            Vector3 v       = new Vector3();
            Vector3 vn      = new Vector3();
            Vector3 dvn     = new Vector3();
            Vector2 vuv     = new Vector2();
            //History his = new History();

            int cnt        = 0;
            int vertsCount = myLODVertices.Length;
            int trisCount  = myTriangles.Length;

            int reducedTriCount = 0;

            foreach (Tri t in myTriangles)
            {
                if (t.deleted)
                {
                    continue;
                }
                ++reducedTriCount;
            }

            int minTriCount = reducedTriCount * 3;

            int[]     tris    = new int[minTriCount];
            Vector3[] verts   = new Vector3[minTriCount];
            Vector2[] uvs     = new Vector2[minTriCount];
            Vector3[] norms   = new Vector3[minTriCount];
            int[]     indices = new int[minTriCount];

            for (i = 0; i < reducedTriCount; ++i)
            {
                Tri tri = myTriangles[triOrder[i]];

                int  cnt1 = cnt + 1;
                int  cnt2 = cnt + 2;
                Vert v0   = tri.v0;
                Vert v1   = tri.v1;
                Vert v2   = tri.v2;

                verts[cnt]  = v0.position;
                verts[cnt1] = v1.position;
                verts[cnt2] = v2.position;
                tris[cnt]   = cnt;
                tris[cnt1]  = cnt1;
                tris[cnt2]  = cnt2;
                uvs[cnt]    = tri.uv0;
                uvs[cnt1]   = tri.uv1;
                uvs[cnt2]   = tri.uv2;
                norms[cnt]  = tri.vn0;
                norms[cnt1] = tri.vn1;
                norms[cnt2] = tri.vn2;

                indices[cnt]  = tri.defaultIndex0;
                indices[cnt1] = tri.defaultIndex1;
                indices[cnt2] = tri.defaultIndex2;

                cnt += 3;
            }

            int            triNum      = tris.Length;
            List <Vector3> newVertices = new List <Vector3>();
            List <Vector2> newUVs      = new List <Vector2>();
            List <Vector3> newNormals  = new List <Vector3>();
            List <Vector3> newDNormals = new List <Vector3>();

            if (bRecalculateNormals)
            {
                for (i = 0; i < triNum; ++i)
                {
                    v   = verts[i];
                    vuv = uvs[i];
                    vn  = norms[i];
                    var n = newVertices.Count;
                    foundAt = -1;
                    for (j = 0; j < n; ++j)
                    {
                        if (newVertices[j] == v && newUVs[j] == vuv &&
                            Vector3.Dot(newNormals[j], vn) > smoothAngleDot)
                        {
                            foundAt = j; break;
                        }
                    }

                    if (foundAt != -1)
                    {
                        tris[i] = foundAt;
                    }
                    else
                    {
                        tris[i]        = n;
                        newVertices[n] = v;
                        newUVs[n]      = vuv;
                        newNormals[n]  = vn;
                        newDNormals[n] = dvn;
                    }
                }
            }
            else
            {
                for (i = 0; i < triNum; ++i)
                {
                    v   = verts[i];
                    vuv = uvs[i];
                    vn  = norms[i];
                    dvn = originalNormals[indices[i]];
                    int n = newVertices.Count;
                    foundAt = -1;
                    for (j = 0; j < n; ++j)
                    {
                        if (newVertices[j] == v && newUVs[j] == vuv && newDNormals[j] == dvn)
                        {
                            foundAt = j; break;
                        }
                    }

                    if (foundAt != -1)
                    {
                        tris[i] = foundAt;
                    }
                    else
                    {
                        tris[i] = n;
                        newVertices.Insert(n, v);
                        newUVs.Insert(n, vuv);
                        newNormals.Insert(n, vn);
                        newDNormals.Insert(n, dvn);
                    }
                }
            }

            finalVertices  = newVertices.ToArray();
            finalNormals   = newNormals.ToArray();
            finalUVs       = newUVs.ToArray();
            finalTriangles = tris;
        }
        private float ComputeEdgeCollapseCosts(Vert u, Vert v)
        {
            int i;
            int j;
            Tri faceU;
            Tri faceV;

            float edgelength = (v.position - u.position).sqrMagnitude;
            float cost       = 0;

            // find the "vFaces" triangles that are on the edge uv
            List <Tri> vFaces     = new List <Tri>();
            int        uFaceCount = u.face.Count;

            for (i = 0; i < uFaceCount; ++i)
            {
                faceU = u.face[i];

                if (faceU.HasVertex(v))
                {
                    vFaces.Add(faceU);
                }
            }

            // use the triangle facing most away from the sides
            // to determine our curvature term
            int vFaceCount = vFaces.Count;

            for (i = 0; i < uFaceCount; ++i)
            {
                float mindot = 1; // curve for face i and closer side to it
                faceU = u.face[i];
                Vector3 faceN = faceU.normal;
                for (j = 0; j < vFaceCount; ++j)
                {
                    // use dot product of face normals. '^' defined in vector
                    faceV = vFaces[j];
                    Vector3 ns  = faceV.normal;
                    float   dot = (1 - (faceN.x * ns.x + faceN.y * ns.y + faceN.z * ns.z)) * 0.5f;
                    if (dot < mindot)
                    {
                        mindot = dot;
                    }
                }
                if (mindot > cost)
                {
                    cost = mindot;
                }
            }

            if (u.IsBorder() && vFaceCount > 1)
            {
                cost = 1.0f;
            }

            // texture UV check
            // if neighbor face has different uv
            // means that shouldn't be collapsed.
            // set its priority as higher cost.
            int found = 0;

            for (i = 0; i < uFaceCount; ++i)
            {
                faceU = u.face[i];
                Vector2 uv = faceU.uvAt(u);
                for (j = 0; j < vFaceCount; ++j)
                {
                    faceV = vFaces[j];
                    if (uv == faceV.uvAt(u))
                    {
                        break;
                    }
                }
                if (j == vFaceCount)
                {
                    ++found;
                }
            }
            // all neighbor faces share same uv
            // so set u as higher cost.
            if (found > 0)
            {
                cost = 1.0f;
            }

            if (u.selected && lockSelPoint)
            {
                cost = 6553.5f;
            }

            // the more coplanar the lower the curvature term
            // cost 0 means u and v are on the same plane.
            return(edgelength * cost);
        }
Пример #18
0
        public bool HasVertex(Vert v)
        {
            Vector3 vec = v.position;

            return(vec == v0.position || vec == v1.position || vec == v2.position);
        }
        private void CollapseTest()
        {
            Vert u = cache[searchIndex++];
            Vert v = u.collapse;

            // which Vert will be collapsed.
            History his = new History();

            collapseHistory[currentcnt - 1] = his;

            // u is a vertex all by itself so just delete it
            if (v != null && v.deleted)
            {
                u.RemoveVert();
                return;
            }
            else if (v == null)
            {
                u.RemoveVert();
                return;
            }

            int i;
            int j;
            Tri uFace;
            Tri vFace;
            int vFaceCount;
            int neighborCount = u.neighbor.Count;

            Vert[] neighbors = new Vert[neighborCount];
            int    count     = u.face.Count;

            // make tmp a list of all the neighbors of u
            for (i = 0; i < neighborCount; ++i)
            {
                neighbors[i] = u.neighbor[i];
            }

            // make a list and add face to the list if it has v.
            List <Tri> vFaces = new List <Tri>();

            for (i = 0; i < count; ++i)
            {
                uFace = u.face[i];
                if (uFace.HasVertex(v))
                {
                    vFaces.Add(uFace);
                }
            }
            vFaceCount = vFaces.Count;

            // delete triangles on edge uv:
            for (i = u.face.Count - 1; i >= 0; --i)
            {
                try
                {
                    uFace = u.face[i];
                    if (uFace.HasVertex(v))
                    {
                        uFace.RemoveTriangle(his);
                    }
                }
                catch { }
            }

            // update remaining triangles to have v instead of u
            Vector2 u_uv;
            Vector2 foundUV = new Vector2();
            Vector3 foundVN = new Vector3();

            for (i = u.face.Count - 1; i >= 0; --i)
            {
                uFace = u.face[i];
                if (!uFace.deleted)
                {
                    u_uv = uFace.uvAt(u);

                    for (j = 0; j < vFaceCount; ++j)
                    {
                        vFace = vFaces[j];
                        if (u_uv == vFace.uvAt(u))
                        {
                            foundUV = vFace.uvAt(v);
                            foundVN = vFace.normalAt(v);
                            break;
                        }
                    }
                    uFace.ReplaceVertex(u, v, foundUV, foundVN, his);
                }
            }
            u.RemoveVert();

            // recompute the edge collapse costs in neighborhood
            Vert  neighbor;
            float oldCost;

            for (i = 0; i < neighborCount; ++i)
            {
                neighbor = neighbors[i];
                oldCost  = neighbor.cost;
                ComputeEdgeCostAtVertex(neighbor);

                if (oldCost > neighbor.cost)
                {
                    SortLeft(neighbor);
                }
                else
                {
                    SortRight(neighbor);
                }
            }
        }