int[] get_tri_order_by_axis_sort()
        {
            int i = 0;

            int[] tri_order = new int[mesh.TriangleCount];

            int nT = mesh.MaxTriangleID;

            for (int ti = 0; ti < nT; ++ti)
            {
                if (mesh.IsTriangle(ti))
                {
                    tri_order[i++] = ti;
                }
            }

            // precompute triangle centroids - wildly expensive to
            // do it inline in sort (!)  I guess O(N) vs O(N log N)
            Vector3d[] centroids = new Vector3d[mesh.MaxTriangleID];
            gParallel.ForEach(mesh.TriangleIndices(), (ti) => {
                if (mesh.IsTriangle(ti))
                {
                    centroids[ti] = mesh.GetTriCentroid(ti);
                }
            });


            Array.Sort(tri_order, (t0, t1) => {
                double f0 = centroids[t0].x;
                double f1 = centroids[t1].x;
                return((f0 == f1) ? 0 : (f0 < f1) ? -1 : 1);
            });

            return(tri_order);
        }
 public void Select(int tid)
 {
     Debug.Assert(Mesh.IsTriangle(tid));
     if (Mesh.IsTriangle(tid))
     {
         add(tid);
     }
 }
        public void InitializeFromExisting(DMesh3 mesh, IEnumerable <int> added_v, IEnumerable <int> added_t)
        {
            initialize_buffers(mesh);
            bool has_groups = mesh.HasTriangleGroups;

            if (added_v != null)
            {
                foreach (int vid in added_v)
                {
                    Util.gDevAssert(mesh.IsVertex(vid));
                    append_vertex(mesh, vid);
                }
            }

            foreach (int tid in added_t)
            {
                Util.gDevAssert(mesh.IsTriangle(tid));

                Index3i tv  = mesh.GetTriangle(tid);
                Index4i tri = new Index4i(tv.a, tv.b, tv.c,
                                          has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID);
                AddedT.Add(tid);
                Triangles.Add(tri);
            }
        }
        public void Initialize(DMesh3 mesh, IEnumerable <int> triangles)
        {
            initialize_buffers(mesh);
            bool has_groups = mesh.HasTriangleGroups;


            foreach (int tid in triangles)
            {
                if (!mesh.IsTriangle(tid))
                {
                    continue;
                }

                Index3i tv = mesh.GetTriangle(tid);
                bool    va = save_vertex(mesh, tv.a);
                bool    vb = save_vertex(mesh, tv.b);
                bool    vc = save_vertex(mesh, tv.c);

                Index4i tri = new Index4i(tv.a, tv.b, tv.c,
                                          has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID);
                RemovedT.Add(tid);
                Triangles.Add(tri);

                MeshResult result = mesh.RemoveTriangle(tid, true, false);
                if (result != MeshResult.Ok)
                {
                    throw new Exception("RemoveTrianglesMeshChange.Initialize: exception in RemoveTriangle(" + tid.ToString() + "): " + result.ToString());
                }
                Util.gDevAssert(mesh.IsVertex(tv.a) == va && mesh.IsVertex(tv.b) == vb && mesh.IsVertex(tv.c) == vc);
            }
        }
Example #5
0
        // [RMS] estimate can be zero
        void compute(IEnumerable <int> triangles, int tri_count_est)
        {
            int est_verts = tri_count_est / 2;

            SubMesh = new DMesh3(BaseMesh.Components & WantComponents);

            BaseSubmeshV = new IndexFlagSet(BaseMesh.MaxVertexID, est_verts);
            BaseToSubV   = new IndexMap(BaseMesh.MaxVertexID, est_verts);
            SubToBaseV   = new DVector <int>();

            if (ComputeTriMaps)
            {
                BaseToSubT = new IndexMap(BaseMesh.MaxTriangleID, tri_count_est);
                SubToBaseT = new DVector <int>();
            }

            foreach (int tid in triangles)
            {
                if (!BaseMesh.IsTriangle(tid))
                {
                    throw new Exception("DSubmesh3.compute: triangle " + tid + " does not exist in BaseMesh!");
                }

                Index3i base_t = BaseMesh.GetTriangle(tid);
                Index3i new_t  = Index3i.Zero;
                int     gid    = BaseMesh.GetTriangleGroup(tid);

                for (int j = 0; j < 3; ++j)
                {
                    int base_v = base_t[j];
                    int sub_v  = -1;
                    if (BaseSubmeshV[base_v] == false)
                    {
                        sub_v = SubMesh.AppendVertex(BaseMesh, base_v);
                        BaseSubmeshV[base_v] = true;
                        BaseToSubV[base_v]   = sub_v;
                        SubToBaseV.insert(base_v, sub_v);
                    }
                    else
                    {
                        sub_v = BaseToSubV[base_v];
                    }

                    new_t[j] = sub_v;
                }

                if (OverrideGroupID >= 0)
                {
                    gid = OverrideGroupID;
                }

                int sub_tid = SubMesh.AppendTriangle(new_t, gid);

                if (ComputeTriMaps)
                {
                    BaseToSubT[tid] = sub_tid;
                    SubToBaseT.insert(tid, sub_tid);
                }
            }
        }
Example #6
0
        // dictionary pairs are [group_id, tri_count]
        public static Dictionary <int, int> CountAllGroups(DMesh3 mesh)
        {
            Dictionary <int, int> GroupCounts = new Dictionary <int, int>();

            if (mesh.HasTriangleGroups)
            {
                int NT = mesh.MaxTriangleID;
                for (int tid = 0; tid < NT; ++tid)
                {
                    if (mesh.IsTriangle(tid))
                    {
                        int gid = mesh.GetTriangleGroup(tid);
                        if (GroupCounts.ContainsKey(gid) == false)
                        {
                            GroupCounts[gid] = 1;
                        }
                        else
                        {
                            GroupCounts[gid]++;
                        }
                    }
                }
            }
            return(GroupCounts);
        }
Example #7
0
        // [TODO] cannot back-out this operation right now
        //
        // Remove list of triangles. Values of triangles[] set to InvalidID are ignored.
        public bool RemoveTriangles(IEnumerable <int> triangles, bool bRemoveIsolatedVerts)
        {
            bool bAllOK = true;

            foreach (int tid in triangles)
            {
                if (!Mesh.IsTriangle(tid))
                {
                    bAllOK = false;
                    continue;
                }
                MeshResult result = Mesh.RemoveTriangle(tid, bRemoveIsolatedVerts, false);
                if (result != MeshResult.Ok)
                {
                    bAllOK = false;
                }
            }
            return(bAllOK);
        }
Example #8
0
        /// <summary>
        /// Get barycentric coords of point in triangle
        /// </summary>
        public static Vector3d BaryCoords(DMesh3 mesh, int tID, Vector3d point)
        {
            if (!mesh.IsTriangle(tID))
            {
                throw new Exception("MeshQueries.SurfaceFrame: triangle " + tID + " does not exist!");
            }
            Triangle3d tri = new Triangle3d();

            mesh.GetTriVertices(tID, ref tri.V0, ref tri.V1, ref tri.V2);
            return(tri.BarycentricCoords(point));
        }
Example #9
0
        /// <summary>
        /// collect triangles by group id. Returns array of triangle lists (stored as arrays).
        /// This requires 2 passes over mesh, but each pass is linear
        /// </summary>
        public static int[][] FindTriangleSetsByGroup(DMesh3 mesh, int ignoreGID = int.MinValue)
        {
            if (!mesh.HasTriangleGroups)
            {
                return(new int[0][]);
            }

            // find # of groups and triangle count for each
            SparseList <int> counts   = CountAllGroups(mesh);
            List <int>       GroupIDs = new List <int>();

            foreach (var idxval in counts.Values())
            {
                if (idxval.Key != ignoreGID && idxval.Value > 0)
                {
                    GroupIDs.Add(idxval.Key);
                }
            }
            GroupIDs.Sort();        // might as well sort ascending...
            SparseList <int> groupMap = new SparseList <int>(mesh.MaxGroupID, GroupIDs.Count, -1);

            // allocate sets
            int[][] sets     = new int[GroupIDs.Count][];
            int[]   counters = new int[GroupIDs.Count];
            for (int i = 0; i < GroupIDs.Count; ++i)
            {
                int gid = GroupIDs[i];
                sets[i]       = new int[counts[gid]];
                counters[i]   = 0;
                groupMap[gid] = i;
            }

            // accumulate triangles
            int NT = mesh.MaxTriangleID;

            for (int tid = 0; tid < NT; ++tid)
            {
                if (mesh.IsTriangle(tid))
                {
                    int gid = mesh.GetTriangleGroup(tid);
                    int i   = groupMap[gid];
                    if (i >= 0)
                    {
                        int k = counters[i]++;
                        sets[i][k] = tid;
                    }
                }
            }

            return(sets);
        }
Example #10
0
        /// <summary>
        /// convenience function to construct a IntrRay3Triangle3 object for a mesh triangle
        /// </summary>
        public static IntrRay3Triangle3 TriangleIntersection(DMesh3 mesh, int ti, Ray3d ray)
        {
            if (!mesh.IsTriangle(ti))
            {
                return(null);
            }
            Triangle3d tri = new Triangle3d();

            mesh.GetTriVertices(ti, ref tri.V0, ref tri.V1, ref tri.V2);
            IntrRay3Triangle3 q = new IntrRay3Triangle3(ray, tri);

            q.Find();
            return(q);
        }
Example #11
0
        /// <summary>
        /// construct a DistPoint3Triangle3 object for a mesh triangle
        /// </summary>
        public static DistPoint3Triangle3 TriangleDistance(DMesh3 mesh, int ti, Vector3d point)
        {
            if (!mesh.IsTriangle(ti))
            {
                return(null);
            }
            Triangle3d tri = new Triangle3d();

            mesh.GetTriVertices(ti, ref tri.V0, ref tri.V1, ref tri.V2);
            DistPoint3Triangle3 q = new DistPoint3Triangle3(point, tri);

            q.GetSquared();
            return(q);
        }
Example #12
0
        /// <summary>
        /// shortcut to construct graph for mesh triangles
        /// </summary>
        public static DijkstraGraphDistance MeshTriangles(DMesh3 mesh, bool bSparse = false)
        {
            Func <int, int, float> tri_dist_f = (a, b) => {
                return((float)mesh.GetTriCentroid(a).Distance(mesh.GetTriCentroid(b)));
            };

            return((bSparse) ?
                   new DijkstraGraphDistance(mesh.MaxTriangleID, true,
                                             (id) => { return mesh.IsTriangle(id); }, tri_dist_f,
                                             mesh.TriTrianglesItr, null)
                        : new DijkstraGraphDistance(mesh.MaxTriangleID, false,
                                                    (id) => { return true; }, tri_dist_f,
                                                    mesh.TriTrianglesItr, null));
        }
Example #13
0
        public static IEnumerable <int> FilteredTriangles(DMesh3 mesh, Func <DMesh3, int, bool> FilterF)
        {
            int N = mesh.MaxTriangleID;

            for (int i = 0; i < N; ++i)
            {
                if (mesh.IsTriangle(i))
                {
                    if (FilterF(mesh, i))
                    {
                        yield return(i);
                    }
                }
            }
        }
Example #14
0
        /// <summary>
        /// find the set of group ids used in mesh
        /// </summary>
        public static HashSet <int> FindAllGroups(DMesh3 mesh)
        {
            HashSet <int> Groups = new HashSet <int>();

            if (mesh.HasTriangleGroups)
            {
                int NT = mesh.MaxTriangleID;
                for (int tid = 0; tid < NT; ++tid)
                {
                    if (mesh.IsTriangle(tid))
                    {
                        int gid = mesh.GetTriangleGroup(tid);
                        Groups.Add(gid);
                    }
                }
            }
            return(Groups);
        }
Example #15
0
        /// <summary>
        /// count number of tris in each group in mesh
        /// returned pairs are [group_id, tri_count]
        /// </summary>
        public static SparseList <int> CountAllGroups(DMesh3 mesh)
        {
            SparseList <int> GroupCounts = new SparseList <int>(mesh.MaxGroupID, 0, 0);

            if (mesh.HasTriangleGroups)
            {
                int NT = mesh.MaxTriangleID;
                for (int tid = 0; tid < NT; ++tid)
                {
                    if (mesh.IsTriangle(tid))
                    {
                        int gid = mesh.GetTriangleGroup(tid);
                        GroupCounts[gid] = GroupCounts[gid] + 1;
                    }
                }
            }
            return(GroupCounts);
        }
        public void InitializeFromExisting(DMesh3 mesh, IEnumerable <int> remove_t)
        {
            initialize_buffers(mesh);
            bool has_groups = mesh.HasTriangleGroups;

            HashSet <int> triangles = new HashSet <int>(remove_t);
            HashSet <int> vertices  = new HashSet <int>();

            IndexUtil.TrianglesToVertices(mesh, remove_t, vertices);
            List <int> save_v = new List <int>();

            foreach (int vid in vertices)
            {
                bool all_contained = true;
                foreach (int tid in mesh.VtxTrianglesItr(vid))
                {
                    if (triangles.Contains(tid) == false)
                    {
                        all_contained = false;
                        break;
                    }
                }
                if (all_contained)
                {
                    save_v.Add(vid);
                }
            }

            foreach (int vid in save_v)
            {
                save_vertex(mesh, vid, true);
            }

            foreach (int tid in remove_t)
            {
                Util.gDevAssert(mesh.IsTriangle(tid));
                Index3i tv  = mesh.GetTriangle(tid);
                Index4i tri = new Index4i(tv.a, tv.b, tv.c,
                                          has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID);
                RemovedT.Add(tid);
                Triangles.Add(tri);
            }
        }
Example #17
0
        // Returns array of triangle lists (stored as arrays)
        // This requires 2 passes over mesh, but each pass is linear
        public static int[][] FindTriangleSetsByGroup(DMesh3 mesh)
        {
            if (!mesh.HasTriangleGroups)
            {
                return(new int[0][]);
            }

            // find # of groups and triangle count for each
            Dictionary <int, int> counts   = CountAllGroups(mesh);
            List <int>            GroupIDs = new List <int>(counts.Keys);

            GroupIDs.Sort();        // might as well sort ascending...
            Dictionary <int, int> groupMap = new Dictionary <int, int>();

            // allocate sets
            int[][] sets     = new int[GroupIDs.Count][];
            int[]   counters = new int[GroupIDs.Count];
            for (int i = 0; i < GroupIDs.Count; ++i)
            {
                int gid = GroupIDs[i];
                sets[i]       = new int[counts[gid]];
                counters[i]   = 0;
                groupMap[gid] = i;
            }

            // accumulate triangles
            int NT = mesh.MaxTriangleID;

            for (int tid = 0; tid < NT; ++tid)
            {
                if (mesh.IsTriangle(tid))
                {
                    int gid = mesh.GetTriangleGroup(tid);
                    int i   = groupMap[gid];
                    int k   = counters[i]++;
                    sets[i][k] = tid;
                }
            }

            return(sets);
        }
Example #18
0
        /// <summary>
        /// convenience function to construct a DistTriangle3Triangle3 object for two mesh triangles
        /// </summary>
        public static DistTriangle3Triangle3 TrianglesDistance(DMesh3 mesh1, int ti, DMesh3 mesh2, int tj, Func <Vector3d, Vector3d> TransformF = null)
        {
            if (mesh1.IsTriangle(ti) == false || mesh2.IsTriangle(tj) == false)
            {
                return(null);
            }
            Triangle3d tri1 = new Triangle3d(), tri2 = new Triangle3d();

            mesh1.GetTriVertices(ti, ref tri1.V0, ref tri1.V1, ref tri1.V2);
            mesh2.GetTriVertices(tj, ref tri2.V0, ref tri2.V1, ref tri2.V2);
            if (TransformF != null)
            {
                tri2.V0 = TransformF(tri2.V0);
                tri2.V1 = TransformF(tri2.V1);
                tri2.V2 = TransformF(tri2.V2);
            }
            DistTriangle3Triangle3 dist = new DistTriangle3Triangle3(tri1, tri2);

            dist.GetSquared();
            return(dist);
        }
Example #19
0
        /// <summary>
        /// convenience function to construct a IntrTriangle3Triangle3 object for two mesh triangles
        /// </summary>
        public static IntrTriangle3Triangle3 TrianglesIntersection(DMesh3 mesh1, int ti, DMesh3 mesh2, int tj, Func <Vector3d, Vector3d> TransformF = null)
        {
            if (mesh1.IsTriangle(ti) == false || mesh2.IsTriangle(tj) == false)
            {
                return(null);
            }
            Triangle3d tri1 = new Triangle3d(), tri2 = new Triangle3d();

            mesh1.GetTriVertices(ti, ref tri1.V0, ref tri1.V1, ref tri1.V2);
            mesh2.GetTriVertices(tj, ref tri2.V0, ref tri2.V1, ref tri2.V2);
            if (TransformF != null)
            {
                tri2.V0 = TransformF(tri2.V0);
                tri2.V1 = TransformF(tri2.V1);
                tri2.V2 = TransformF(tri2.V2);
            }
            IntrTriangle3Triangle3 intr = new IntrTriangle3Triangle3(tri1, tri2);

            intr.Find();
            return(intr);
        }
Example #20
0
        /// <summary>
        /// replace group id in mesh
        /// </summary>
        public static void SetGroupToGroup(DMesh3 mesh, int from, int to)
        {
            if (mesh.HasTriangleGroups == false)
            {
                return;
            }

            int NT = mesh.MaxTriangleID;

            for (int tid = 0; tid < NT; ++tid)
            {
                if (mesh.IsTriangle(tid))
                {
                    int gid = mesh.GetTriangleGroup(tid);
                    if (gid == from)
                    {
                        mesh.SetTriangleGroup(tid, to);
                    }
                }
            }
        }
Example #21
0
        /// <summary>
        /// Get point-normal frame on surface of mesh. Assumption is that point lies in tID.
        /// returns interpolated vertex-normal frame if available, otherwise tri-normal frame.
        /// </summary>
        public static Frame3f SurfaceFrame(DMesh3 mesh, int tID, Vector3d point)
        {
            if (!mesh.IsTriangle(tID))
            {
                throw new Exception("MeshQueries.SurfaceFrame: triangle " + tID + " does not exist!");
            }
            Triangle3d tri = new Triangle3d();

            mesh.GetTriVertices(tID, ref tri.V0, ref tri.V1, ref tri.V2);
            Vector3d bary = tri.BarycentricCoords(point);

            point = tri.PointAt(bary);
            if (mesh.HasVertexNormals)
            {
                Vector3d normal = mesh.GetTriBaryNormal(tID, bary.x, bary.y, bary.z);
                return(new Frame3f(point, normal));
            }
            else
            {
                return(new Frame3f(point, mesh.GetTriNormal(tID)));
            }
        }
Example #22
0
        protected virtual void InitializeVertexQuadrics()
        {
            int NT = mesh.MaxTriangleID;

            QuadricError[] triQuadrics = new QuadricError[NT];
            double[]       triAreas    = new double[NT];
            gParallel.BlockStartEnd(0, mesh.MaxTriangleID - 1, (start_tid, end_tid) => {
                Vector3d c, n;
                for (int tid = start_tid; tid <= end_tid; tid++)
                {
                    if (mesh.IsTriangle(tid))
                    {
                        mesh.GetTriInfo(tid, out n, out triAreas[tid], out c);
                        triQuadrics[tid] = new QuadricError(ref n, ref c);
                    }
                }
            });


            int NV = mesh.MaxVertexID;

            vertQuadrics = new QuadricError[NV];
            gParallel.BlockStartEnd(0, mesh.MaxVertexID - 1, (start_vid, end_vid) => {
                for (int vid = start_vid; vid <= end_vid; vid++)
                {
                    vertQuadrics[vid] = QuadricError.Zero;
                    if (mesh.IsVertex(vid))
                    {
                        foreach (int tid in mesh.VtxTrianglesItr(vid))
                        {
                            vertQuadrics[vid].Add(triAreas[tid], ref triQuadrics[tid]);
                        }
                        //Util.gDevAssert(MathUtil.EpsilonEqual(0, vertQuadrics[i].Evaluate(mesh.GetVertex(i)), MathUtil.Epsilon * 10));
                    }
                }
            });
        }
        int[] get_tri_order_by_axis_sort()
        {
            int i = 0;

            int[] tri_order = new int[mesh.TriangleCount];

            int nT = mesh.MaxTriangleID;

            for (int ti = 0; ti < nT; ++ti)
            {
                if (mesh.IsTriangle(ti))
                {
                    tri_order[i++] = ti;
                }
            }

            Array.Sort(tri_order, (t0, t1) => {
                double f0 = mesh.GetTriCentroid(t0).x;
                double f1 = mesh.GetTriCentroid(t1).x;
                return((f0 == f1) ? 0 : (f0 < f1) ? -1 : 1);
            });

            return(tri_order);
        }
Example #24
0
 /// <summary>
 /// Check if this m2 is the same as this mesh. By default only checks
 /// vertices and triangles, turn on other parameters w/ flags
 /// </summary>
 public bool IsSameMesh(DMesh3 m2, bool bCheckEdges = false,
                        bool bCheckNormals          = false, bool bCheckColors = false, bool bCheckUVs = false,
                        bool bCheckGroups           = false,
                        float Epsilon = MathUtil.Epsilonf)
 {
     if (VertexCount != m2.VertexCount)
     {
         return(false);
     }
     if (TriangleCount != m2.TriangleCount)
     {
         return(false);
     }
     foreach (int vid in VertexIndices())
     {
         if (m2.IsVertex(vid) == false || GetVertex(vid).EpsilonEqual(m2.GetVertex(vid), Epsilon) == false)
         {
             return(false);
         }
     }
     foreach (int tid in TriangleIndices())
     {
         if (m2.IsTriangle(tid) == false || GetTriangle(tid).Equals(m2.GetTriangle(tid)) == false)
         {
             return(false);
         }
     }
     if (bCheckEdges)
     {
         if (EdgeCount != m2.EdgeCount)
         {
             return(false);
         }
         foreach (int eid in EdgeIndices())
         {
             if (m2.IsEdge(eid) == false || GetEdge(eid).Equals(m2.GetEdge(eid)) == false)
             {
                 return(false);
             }
         }
     }
     if (bCheckNormals)
     {
         if (HasVertexNormals != m2.HasVertexNormals)
         {
             return(false);
         }
         if (HasVertexNormals)
         {
             foreach (int vid in VertexIndices())
             {
                 if (GetVertexNormal(vid).EpsilonEqual(m2.GetVertexNormal(vid), Epsilon) == false)
                 {
                     return(false);
                 }
             }
         }
     }
     if (bCheckColors)
     {
         if (HasVertexColors != m2.HasVertexColors)
         {
             return(false);
         }
         if (HasVertexColors)
         {
             foreach (int vid in VertexIndices())
             {
                 if (GetVertexColor(vid).EpsilonEqual(m2.GetVertexColor(vid), Epsilon) == false)
                 {
                     return(false);
                 }
             }
         }
     }
     if (bCheckUVs)
     {
         if (HasVertexUVs != m2.HasVertexUVs)
         {
             return(false);
         }
         if (HasVertexUVs)
         {
             foreach (int vid in VertexIndices())
             {
                 if (GetVertexUV(vid).EpsilonEqual(m2.GetVertexUV(vid), Epsilon) == false)
                 {
                     return(false);
                 }
             }
         }
     }
     if (bCheckGroups)
     {
         if (HasTriangleGroups != m2.HasTriangleGroups)
         {
             return(false);
         }
         if (HasTriangleGroups)
         {
             foreach (int tid in TriangleIndices())
             {
                 if (GetTriangleGroup(tid) != m2.GetTriangleGroup(tid))
                 {
                     return(false);
                 }
             }
         }
     }
     return(true);
 }
Example #25
0
        // Assumption here is that Submesh has been modified, but boundary loop has
        // been preserved, and that old submesh has already been removed from this mesh.
        // So, we just have to append new vertices and then rewrite triangles
        // If new_tris or new_verts is non-null, we will return this info.
        // new_tris should be set to TriangleCount (ie it is not necessarily a map)
        // For new_verts, if we used an existing bdry vtx instead, we set the value to -(existing_index+1),
        // otherwise the value is new_index (+1 is to handle 0)
        //
        // Returns true if submesh successfully inserted, false if any triangles failed
        // (which happens if triangle would result in non-manifold mesh)
        public bool ReinsertSubmesh(DSubmesh3 sub, ref int[] new_tris, out IndexMap SubToNewV)
        {
            if (sub.BaseBorderV == null)
            {
                throw new Exception("MeshEditor.ReinsertSubmesh: Submesh does not have required boundary info. Call ComputeBoundaryInfo()!");
            }

            DMesh3 submesh = sub.SubMesh;
            bool   bAllOK  = true;

            IndexFlagSet done_v = new IndexFlagSet(submesh.MaxVertexID, submesh.TriangleCount / 2);

            SubToNewV = new IndexMap(submesh.MaxVertexID, submesh.VertexCount);

            int nti = 0;
            int NT  = submesh.MaxTriangleID;

            for (int ti = 0; ti < NT; ++ti)
            {
                if (submesh.IsTriangle(ti) == false)
                {
                    continue;
                }

                Index3i sub_t = submesh.GetTriangle(ti);
                int     gid   = submesh.GetTriangleGroup(ti);

                Index3i new_t = Index3i.Zero;
                for (int j = 0; j < 3; ++j)
                {
                    int sub_v = sub_t[j];
                    int new_v = -1;
                    if (done_v[sub_v] == false)
                    {
                        // first check if this is a boundary vtx on submesh and maps to a bdry vtx on base mesh
                        if (submesh.vertex_is_boundary(sub_v))
                        {
                            int base_v = (sub_v < sub.SubToBaseV.size) ? sub.SubToBaseV[sub_v] : -1;
                            if (base_v >= 0 && Mesh.IsVertex(base_v) && sub.BaseBorderV[base_v] == true)
                            {
                                // [RMS] this should always be true, but assert in tests to find out
                                Debug.Assert(Mesh.vertex_is_boundary(base_v));
                                if (Mesh.vertex_is_boundary(base_v))
                                {
                                    new_v = base_v;
                                }
                            }
                        }

                        // if that didn't happen, append new vtx
                        if (new_v == -1)
                        {
                            new_v = Mesh.AppendVertex(submesh, sub_v);
                        }

                        SubToNewV[sub_v] = new_v;
                        done_v[sub_v]    = true;
                    }
                    else
                    {
                        new_v = SubToNewV[sub_v];
                    }

                    new_t[j] = new_v;
                }

                Debug.Assert(Mesh.FindTriangle(new_t.a, new_t.b, new_t.c) == DMesh3.InvalidID);

                int new_tid = Mesh.AppendTriangle(new_t, gid);
                Debug.Assert(new_tid != DMesh3.InvalidID && new_tid != DMesh3.NonManifoldID);
                if (!Mesh.IsTriangle(new_tid))
                {
                    bAllOK = false;
                }

                if (new_tris != null)
                {
                    new_tris[nti++] = new_tid;
                }
            }

            return(bAllOK);
        }
Example #26
0
        /// <summary>
        /// Check if this m2 is the same as this mesh. By default only checks
        /// vertices and triangles, turn on other parameters w/ flags
        /// </summary>
        public bool IsSameMesh(DMesh3 m2, bool bCheckConnectivity, bool bCheckEdgeIDs = false,
                               bool bCheckNormals = false, bool bCheckColors = false, bool bCheckUVs = false,
                               bool bCheckGroups  = false,
                               float Epsilon      = MathUtil.Epsilonf)
        {
            if (VertexCount != m2.VertexCount)
            {
                return(false);
            }

            if (TriangleCount != m2.TriangleCount)
            {
                return(false);
            }

            foreach (int vid in VertexIndices())
            {
                if (m2.IsVertex(vid) == false || GetVertex(vid).EpsilonEqual(m2.GetVertex(vid), Epsilon) == false)
                {
                    return(false);
                }
            }
            foreach (int tid in TriangleIndices())
            {
                if (m2.IsTriangle(tid) == false || GetTriangle(tid).Equals(m2.GetTriangle(tid)) == false)
                {
                    return(false);
                }
            }
            if (bCheckConnectivity)
            {
                foreach (int eid in EdgeIndices())
                {
                    Index4i e         = GetEdge(eid);
                    int     other_eid = m2.FindEdge(e.a, e.b);
                    if (other_eid == InvalidID)
                    {
                        return(false);
                    }

                    Index4i oe = m2.GetEdge(other_eid);
                    if (Math.Min(e.c, e.d) != Math.Min(oe.c, oe.d) || Math.Max(e.c, e.d) != Math.Max(oe.c, oe.d))
                    {
                        return(false);
                    }
                }
            }
            if (bCheckEdgeIDs)
            {
                if (EdgeCount != m2.EdgeCount)
                {
                    return(false);
                }

                foreach (int eid in EdgeIndices())
                {
                    if (m2.IsEdge(eid) == false || GetEdge(eid).Equals(m2.GetEdge(eid)) == false)
                    {
                        return(false);
                    }
                }
            }
            if (bCheckNormals)
            {
                if (HasVertexNormals != m2.HasVertexNormals)
                {
                    return(false);
                }

                if (HasVertexNormals)
                {
                    foreach (int vid in VertexIndices())
                    {
                        if (GetVertexNormal(vid).EpsilonEqual(m2.GetVertexNormal(vid), Epsilon) == false)
                        {
                            return(false);
                        }
                    }
                }
            }
            if (bCheckColors)
            {
                if (HasVertexColors != m2.HasVertexColors)
                {
                    return(false);
                }

                if (HasVertexColors)
                {
                    foreach (int vid in VertexIndices())
                    {
                        if (GetVertexColor(vid).EpsilonEqual(m2.GetVertexColor(vid), Epsilon) == false)
                        {
                            return(false);
                        }
                    }
                }
            }
            if (bCheckUVs)
            {
                if (HasVertexUVs != m2.HasVertexUVs)
                {
                    return(false);
                }

                if (HasVertexUVs)
                {
                    foreach (int vid in VertexIndices())
                    {
                        if (GetVertexUV(vid).EpsilonEqual(m2.GetVertexUV(vid), Epsilon) == false)
                        {
                            return(false);
                        }
                    }
                }
            }
            if (bCheckGroups)
            {
                if (HasTriangleGroups != m2.HasTriangleGroups)
                {
                    return(false);
                }

                if (HasTriangleGroups)
                {
                    foreach (int tid in TriangleIndices())
                    {
                        if (GetTriangleGroup(tid) != m2.GetTriangleGroup(tid))
                        {
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }
Example #27
0
        public void FindConnectedT()
        {
            Components = new List <Component>();

            int NT = Mesh.MaxTriangleID;

            // [TODO] could use Euler formula to determine if mesh is closed genus-0...

            Func <int, bool> filter_func = (i) => { return(Mesh.IsTriangle(i)); };

            if (FilterF != null)
            {
                filter_func = (i) => { return(Mesh.IsTriangle(i) && FilterF(i)); }
            }
            ;



            // initial active set contains all valid triangles
            byte[]     active      = new byte[Mesh.MaxTriangleID];
            Interval1i activeRange = Interval1i.Empty;

            if (FilterSet != null)
            {
                for (int i = 0; i < NT; ++i)
                {
                    active[i] = 255;
                }
                foreach (int tid in FilterSet)
                {
                    bool bValid = filter_func(tid);
                    if (bValid)
                    {
                        active[tid] = 0;
                        activeRange.Contain(tid);
                    }
                }
            }
            else
            {
                for (int i = 0; i < NT; ++i)
                {
                    bool bValid = filter_func(i);
                    if (bValid)
                    {
                        active[i] = 0;
                        activeRange.Contain(i);
                    }
                    else
                    {
                        active[i] = 255;
                    }
                }
            }

            // temporary buffers
            List <int> queue    = new List <int>(NT / 10);
            List <int> cur_comp = new List <int>(NT / 10);

            // keep finding valid seed triangles and growing connected components
            // until we are done
            IEnumerable <int> range = (FilterSet != null) ? FilterSet : activeRange;

            foreach (int i in range)
            {
                //for ( int i = 0; i < NT; ++i ) {
                if (active[i] == 255)
                {
                    continue;
                }

                int seed_t = i;
                if (SeedFilterF != null && SeedFilterF(seed_t) == false)
                {
                    continue;
                }

                queue.Add(seed_t);
                active[seed_t] = 1;      // in queue

                while (queue.Count > 0)
                {
                    int cur_t = queue[queue.Count - 1];
                    queue.RemoveAt(queue.Count - 1);

                    active[cur_t] = 2;   // tri has been processed
                    cur_comp.Add(cur_t);

                    Index3i nbrs = Mesh.GetTriNeighbourTris(cur_t);
                    for (int j = 0; j < 3; ++j)
                    {
                        int nbr_t = nbrs[j];
                        if (nbr_t != DMesh3.InvalidID && active[nbr_t] == 0)
                        {
                            queue.Add(nbr_t);
                            active[nbr_t] = 1;           // in queue
                        }
                    }
                }


                Component comp = new Component()
                {
                    Indices = cur_comp.ToArray()
                };
                Components.Add(comp);

                // remove tris in this component from active set
                for (int j = 0; j < comp.Indices.Length; ++j)
                {
                    active[comp.Indices[j]] = 255;
                }

                cur_comp.Clear();
                queue.Clear();
            }
        }
Example #28
0
        public void FindConnectedT()
        {
            Components = new List <Component>();

            int NT = Mesh.MaxTriangleID;

            // [TODO] could use Euler formula to determine if mesh is closed genus-0...

            // initial active set contains all triangles
            byte[] active = new byte[Mesh.MaxTriangleID];
            for (int i = 0; i < NT; ++i)
            {
                if (Mesh.IsTriangle(i))
                {
                    active[i] = 0;
                }
                else
                {
                    active[i] = 255;
                }
            }

            // temporary buffers
            List <int> queue    = new List <int>(NT / 10);
            List <int> cur_comp = new List <int>(NT / 10);

            // keep finding valid seed triangles and growing connected components
            // until we are done
            for (int i = 0; i < NT; ++i)
            {
                if (active[i] == 255)
                {
                    continue;
                }

                int seed_t = i;
                queue.Add(seed_t);
                active[seed_t] = 1;      // in queue

                while (queue.Count > 0)
                {
                    int cur_t = queue[queue.Count - 1];
                    queue.RemoveAt(queue.Count - 1);

                    active[cur_t] = 2;   // tri has been processed
                    cur_comp.Add(cur_t);

                    Index3i nbrs = Mesh.GetTriNeighbourTris(cur_t);
                    for (int j = 0; j < 3; ++j)
                    {
                        int nbr_t = nbrs[j];
                        if (nbr_t != DMesh3.InvalidID && active[nbr_t] == 0)
                        {
                            queue.Add(nbr_t);
                            active[nbr_t] = 1;           // in queue
                        }
                    }
                }


                Component comp = new Component()
                {
                    Indices = cur_comp.ToArray()
                };
                Components.Add(comp);

                // remove tris in this component from active set
                for (int j = 0; j < comp.Indices.Length; ++j)
                {
                    active[comp.Indices[j]] = 255;
                }

                cur_comp.Clear();
                queue.Clear();
            }
        }