Example #1
0
        List <int> find_neighbour_groups(DMesh3 mesh, int gid, HashSet <int> group_tris)
        {
            List <int> result = new List <int>();

            foreach (int tid in group_tris)
            {
                foreach (int ntid in mesh.TriTrianglesItr(tid))
                {
                    int ngid = mesh.GetTriangleGroup(ntid);
                    if (ngid != gid && result.Contains(ngid) == false)
                    {
                        result.Add(ngid);
                    }
                }
            }
            return(result);
        }
Example #2
0
    internal bool CheckPositionValid(DMesh3 mesh, Vector3d position, int colorToExclude)
    {
        var spatial = new DMeshAABBTree3(mesh);

        spatial.Build();

        spatial.TriangleFilterF = i => mesh.GetTriangleGroup(i) != colorToExclude;

        int near_tid = spatial.FindNearestTriangle(position, 9f);

        if (near_tid != DMesh3.InvalidID)
        {
            return(false);
        }

        return(true);
    }
        public static void test_region_boundary()
        {
            List<int> cases = new List<int>() { 0, 1, 2, 3 };

            foreach ( int num in cases ) { 

                string name;
                DMesh3 mesh = MakeBoundaryTestMesh(num, out name);

                int[][] groups = FaceGroupUtil.FindTriangleSetsByGroup(mesh, 0);

                System.Console.WriteLine("case {0}:", name);
                for (int k = 0; k < groups.Length; ++k) {
                    int gid = mesh.GetTriangleGroup(groups[k][0]);
                    MeshRegionBoundaryLoops loops = new MeshRegionBoundaryLoops(mesh, groups[k]);
                    System.Console.WriteLine("  gid {0} : found {1} loops", gid, loops.Loops.Count);
                }

            }
        }
Example #4
0
        /// <summary>
        /// Cut through-hole either vertically or horizontally.
        ///
        /// One current failure mode is if we get more than two ray-hits, which
        /// can happen due pathological cases or unexpected mesh shape. Currently
        /// trying to handle the pathological cases (ie ray hits adjacent triangles cases)
        /// via sorting, not sure if this works spectacularly well.
        ///
        /// </summary>
        protected bool CutThroughHole(DMesh3 mesh, HoleInfo hi, Vector3d translate)
        {
            Vector3d basePoint = CombinedBounds.Center - CombinedBounds.Extents.y * Vector3d.AxisY + translate;

            // do we need to compute spatial DS for each hole? not super efficient...
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            Vector3d origin    = Vector3d.Zero;
            Vector3d direction = Vector3d.One;

            if (hi.IsVertical)
            {
                direction = Vector3d.AxisY;
                origin    = basePoint + new Vector3d(hi.XZOffset.x, 0, hi.XZOffset.y) - 100 * direction;
            }
            else
            {
                origin    = basePoint + hi.Height * Vector3d.AxisY;
                direction = Quaterniond.AxisAngleD(Vector3d.AxisY, hi.AroundAngle) * Vector3d.AxisX;
            }

            // Find upper and lower triangles that contain center-points of
            // holes we want to cut. This is the most error-prone part
            // because we depend on ray-hits, which is not very reliable...

            Ray3d ray1 = new Ray3d(origin, direction);
            Ray3d ray2 = new Ray3d(origin + 10000 * direction, -direction);

            if (hi.GroupIDFilters.a > 0)
            {
                spatial.TriangleFilterF = (tid) => {
                    return(mesh.GetTriangleGroup(tid) == hi.GroupIDFilters.a);
                };
            }
            int hit_1 = spatial.FindNearestHitTriangle(ray1);

            spatial.TriangleFilterF = null;

            if (hi.GroupIDFilters.b > 0)
            {
                spatial.TriangleFilterF = (tid) => {
                    return(mesh.GetTriangleGroup(tid) == hi.GroupIDFilters.b);
                };
            }
            int hit_2 = spatial.FindNearestHitTriangle(ray2);

            spatial.TriangleFilterF = null;

            if (hit_1 == DMesh3.InvalidID || hit_2 == DMesh3.InvalidID)
            {
                return(false);
            }
            if (hit_1 == hit_2)
            {
                return(false);
            }

            List <int> hitTris = new List <int>()
            {
                hit_1, hit_2
            };


            Frame3f projectFrame = new Frame3f(ray1.Origin, ray1.Direction);

            int nVerts = 32;

            if (hi.Vertices != 0)
            {
                nVerts = hi.Vertices;
            }
            double    angleShiftRad = hi.AxisAngleD * MathUtil.Deg2Rad;
            Polygon2d circle        = Polygon2d.MakeCircle(hi.Radius, nVerts, angleShiftRad);


            List <EdgeLoop> edgeLoops = new List <EdgeLoop>();

            foreach (int hit_tid in hitTris)
            {
                try {
                    MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(mesh, circle, projectFrame, hit_tid)
                    {
                        SimplifyInsertion = true
                    };
                    if (insert.Insert())
                    {
                        // if we have extra edges just randomly collapse
                        EdgeLoop loop = insert.InsertedLoop;

                        if (loop.VertexCount > circle.VertexCount)
                        {
                            loop = simplify_loop(mesh, loop, circle.VertexCount);
                        }

                        edgeLoops.Add(loop);
                    }
                    else
                    {
                        f3.DebugUtil.Log("insert.Insert() failed!!");
                        return(false);
                    }
                } catch (Exception e) {
                    // ignore this loop but we might already be in trouble...
                    f3.DebugUtil.Log("insert.Insert() threw exception for hole {0}!!", hi.nHole);
                    f3.DebugUtil.Log(e.Message);
                }
            }
            if (edgeLoops.Count != 2)
            {
                return(false);
            }

            try {
                MeshEditor editor = new MeshEditor(mesh);
                EdgeLoop   l0     = edgeLoops[0];
                EdgeLoop   l1     = edgeLoops[1];
                l1.Reverse();
                editor.StitchVertexLoops_NearestV(l0.Vertices, l1.Vertices);

                // split edges around the holes we cut. This is helpful
                // if we are going to do additional operations in these areas,
                // as it gives us extra rings to work with
                //MeshEdgeSelection edges = new MeshEdgeSelection(mesh);
                //edges.SelectVertexEdges(l0.Vertices);
                //edges.SelectVertexEdges(l1.Vertices);
                //DMesh3.EdgeSplitInfo splitInfo;
                //foreach ( int eid in edges )
                //    mesh.SplitEdge(eid, out splitInfo);

                return(true);
            } catch {
                f3.DebugUtil.Log("stitch threw exception!");
                return(false);
            }
        }
Example #5
0
        List <Polygon2d> decompose_cluster_up(DMesh3 mesh)
        {
            optimize_mesh(mesh);
            mesh.CompactInPlace();
            mesh.DiscardTriangleGroups(); mesh.EnableTriangleGroups(0);

            double minLength = Settings.MaxBridgeWidthMM * 0.75;
            double minArea   = minLength * minLength;

            Dictionary <int, double>         areas   = new Dictionary <int, double>();
            Dictionary <int, HashSet <int> > trisets = new Dictionary <int, HashSet <int> >();
            HashSet <int> active_groups = new HashSet <int>();

            Action <int, int> add_tri_to_group = (tid, gid) => {
                mesh.SetTriangleGroup(tid, gid);
                areas[gid] = areas[gid] + mesh.GetTriArea(tid);
                trisets[gid].Add(tid);
            };
            Action <int, int> add_group_to_group = (gid, togid) => {
                var set = trisets[togid];
                foreach (int tid in trisets[gid])
                {
                    mesh.SetTriangleGroup(tid, togid);
                    set.Add(tid);
                }
                areas[togid] += areas[gid];
                active_groups.Remove(gid);
            };
            Func <IEnumerable <int>, int> find_min_area_group = (tri_itr) => {
                int min_gid = -1; double min_area = double.MaxValue;
                foreach (int tid in tri_itr)
                {
                    int    gid = mesh.GetTriangleGroup(tid);
                    double a   = areas[gid];
                    if (a < min_area)
                    {
                        min_area = a;
                        min_gid  = gid;
                    }
                }
                return(min_gid);
            };


            foreach (int eid in MeshIterators.InteriorEdges(mesh))
            {
                Index2i et = mesh.GetEdgeT(eid);
                if (mesh.GetTriangleGroup(et.a) != 0 || mesh.GetTriangleGroup(et.b) != 0)
                {
                    continue;
                }
                int gid = mesh.AllocateTriangleGroup();
                areas[gid]   = 0;
                trisets[gid] = new HashSet <int>();
                active_groups.Add(gid);
                add_tri_to_group(et.a, gid);
                add_tri_to_group(et.b, gid);
            }
            foreach (int tid in mesh.TriangleIndices())
            {
                if (mesh.GetTriangleGroup(tid) != 0)
                {
                    continue;
                }
                int gid = find_min_area_group(mesh.TriTrianglesItr(tid));
                add_tri_to_group(tid, gid);
            }


            IndexPriorityQueue pq = new IndexPriorityQueue(mesh.MaxGroupID);

            foreach (var pair in areas)
            {
                pq.Insert(pair.Key, (float)pair.Value);
            }
            while (pq.Count > 0)
            {
                int gid = pq.First;
                pq.Remove(gid);
                if (areas[gid] > minArea)                    // ??
                {
                    break;
                }

                List <int> nbr_groups = find_neighbour_groups(mesh, gid, trisets[gid]);
                int        min_gid = -1; double min_area = double.MaxValue;
                foreach (int ngid in nbr_groups)
                {
                    double a = areas[ngid];
                    if (a < min_area)
                    {
                        min_area = a;
                        min_gid  = ngid;
                    }
                }
                if (min_gid != -1)
                {
                    add_group_to_group(gid, min_gid);
                    pq.Remove(min_gid);
                    pq.Insert(min_gid, (float)areas[min_gid]);
                }
            }



            List <Polygon2d> result = new List <Polygon2d>();

            int[][] sets = FaceGroupUtil.FindTriangleSetsByGroup(mesh);
            foreach (var set in sets)
            {
                result.Add(make_poly(mesh, set));
            }
            return(result);
        }
Example #6
0
        // [RMS] This doesn't work because I did something stupid when
        //   making unwrap meshes. The set of triangles aren't the same. argh.
        public static DMesh3 ConvertUnwrapToUVs(RemoteControl rc, out DenseMeshUVSet UVSet, string mainName = "main")
        {
            int mainID = rc.FindObjectByName(mainName);

            rc.CompactMesh(mainID);
            DMesh3 mainMesh = ReadMeshFromMM(rc, mainID);

            Debug.Assert(mainMesh.IsCompact);

            List <int> all       = rc.ListObjects();
            List <int> unwrapIDs = new List <int>();

            foreach (int id in all)
            {
                string sName = rc.GetObjectName(id);
                if (sName.StartsWith("unwrap", StringComparison.OrdinalIgnoreCase))
                {
                    unwrapIDs.Add(id);
                }
            }
            int[] AllGroups = FaceGroupUtil.FindAllGroups(mainMesh).ToArray();


            Dictionary <int, DMesh3> Unwraps = new Dictionary <int, DMesh3>();

            foreach (int id in unwrapIDs)
            {
                DMesh3        mesh      = ReadMeshFromMM(rc, id);
                HashSet <int> subGroups = FaceGroupUtil.FindAllGroups(mesh);
                Debug.Assert(subGroups.Count == 1);
                int gid = subGroups.ToArray()[0];
                Unwraps[gid] = mesh;
            }


            UVSet = new DenseMeshUVSet();
            UVSet.TriangleUVs.resize(mainMesh.TriangleCount);
            Dictionary <Index2i, int> UVSetMap = new Dictionary <Index2i, int>();

            Dictionary <int, int> GroupCounters = new Dictionary <int, int>();

            for (int i = 0; i < AllGroups.Length; ++i)
            {
                GroupCounters[AllGroups[i]] = 0;
            }

            for (int ti = 0; ti < mainMesh.TriangleCount; ++ti)
            {
                Index3i main_tri = mainMesh.GetTriangle(ti);
                int     gid      = mainMesh.GetTriangleGroup(ti);
                int     sub_tid  = GroupCounters[gid];
                GroupCounters[gid]++;

                DMesh3  SubMesh = Unwraps[gid];
                Index3i sub_tri = SubMesh.GetTriangle(sub_tid);

                for (int j = 0; j < 3; ++j)
                {
                    int     sub_vid = sub_tri[j];
                    Index2i key     = new Index2i(gid, sub_vid);
                    int     uvset_idx;
                    if (UVSetMap.TryGetValue(key, out uvset_idx) == false)
                    {
                        Vector3d v  = SubMesh.GetVertex(sub_vid);
                        Vector2f uv = new Vector2f((float)v.x, (float)v.z);
                        uvset_idx     = UVSet.AppendUV(uv);
                        UVSetMap[key] = uvset_idx;
                    }
                    sub_tri[j] = uvset_idx;
                }

                UVSet.TriangleUVs[ti] = sub_tri;
            }

            return(mainMesh);
        }
Example #7
0
        protected void do_flatten(DMesh3 mesh)
        {
            double   BAND_HEIGHT = flatten_band_height;
            Vector3d down_axis   = -Vector3d.AxisY;
            double   dot_thresh  = 0.2;

            AxisAlignedBox3d bounds  = mesh.CachedBounds;
            DMeshAABBTree3   spatial = new DMeshAABBTree3(mesh, true);

            Ray3d   ray     = new Ray3d(bounds.Center - 2 * bounds.Height * Vector3d.AxisY, Vector3d.AxisY);
            int     hit_tid = spatial.FindNearestHitTriangle(ray);
            Frame3f hitF;

            MeshQueries.RayHitPointFrame(mesh, spatial, ray, out hitF);
            Vector3d basePt = hitF.Origin;

            Frame3f basePlane = new Frame3f(basePt, Vector3f.AxisY);

            MeshConnectedComponents components = new MeshConnectedComponents(mesh)
            {
                FilterF = (tid) => {
                    if (mesh.GetTriangleGroup(tid) != LastExtrudeOuterGroupID)
                    {
                        return(false);
                    }
                    Vector3d n, c; double a;
                    mesh.GetTriInfo(tid, out n, out a, out c);
                    double h = Math.Abs(c.y - basePt.y);
                    if (h > BAND_HEIGHT)
                    {
                        return(false);
                    }
                    if (n.Dot(down_axis) < dot_thresh)
                    {
                        return(false);
                    }
                    return(true);
                },
                SeedFilterF = (tid) => {
                    return(tid == hit_tid);
                }
            };

            components.FindConnectedT();

            MeshFaceSelection all_faces = new MeshFaceSelection(mesh);

            foreach (var comp in components)
            {
                MeshVertexSelection vertices = new MeshVertexSelection(mesh);
                vertices.SelectTriangleVertices(comp.Indices);
                foreach (int vid in vertices)
                {
                    Vector3d v = mesh.GetVertex(vid);
                    v = basePlane.ProjectToPlane((Vector3f)v, 2);
                    mesh.SetVertex(vid, v);
                }
                all_faces.SelectVertexOneRings(vertices);
            }

            all_faces.ExpandToOneRingNeighbours(3, (tid) => {
                return(mesh.GetTriangleGroup(tid) == LastExtrudeOuterGroupID);
            });

            RegionRemesher r = new RegionRemesher(mesh, all_faces);

            r.SetProjectionTarget(MeshProjectionTarget.Auto(mesh));
            r.SetTargetEdgeLength(2.0f);
            r.SmoothSpeedT = 1.0f;
            for (int k = 0; k < 10; ++k)
            {
                r.BasicRemeshPass();
            }
            r.SetProjectionTarget(null);
            r.SmoothSpeedT = 1.0f;
            for (int k = 0; k < 10; ++k)
            {
                r.BasicRemeshPass();
            }
            r.BackPropropagate();
        }