Beispiel #1
0
        public AppendInfo AppendConnectorTo(DMesh3 mesh, Vector3d translate)
        {
            validate_geometry();

            AppendInfo info = new AppendInfo();

            MeshEditor editor = new MeshEditor(mesh);

            int[] mapV;

            if (HasInner)
            {
                info.InnerGID = mesh.AllocateTriangleGroup();
                editor.AppendMesh(InnerMesh, out mapV, info.InnerGID);
                info.InnerLoop = EdgeLoop.FromVertices(mesh, new MappedList(InnerLoop.Vertices, mapV));

                MeshTransforms.PerVertexTransform(mesh, InnerMesh.VertexIndices(),
                                                  (vid) => { return(mapV[vid]); },
                                                  (v, old_vid, new_vid) => { return(v + translate); });
            }
            else
            {
                info.InnerGID  = -1;
                info.InnerLoop = null;
            }

            info.OuterGID = mesh.AllocateTriangleGroup();
            editor.AppendMesh(OuterMesh, out mapV, info.OuterGID);
            info.OuterLoop = EdgeLoop.FromVertices(mesh, new MappedList(OuterLoop.Vertices, mapV));

            MeshTransforms.PerVertexTransform(mesh, OuterMesh.VertexIndices(),
                                              (vid) => { return(mapV[vid]); },
                                              (v, old_vid, new_vid) => { return(v + translate); });

            return(info);
        }
Beispiel #2
0
        public override DMesh3 Cut(CuttingInfo info)
        {
            var painted = FindPaintedTriangles(info.mesh, info.data.ColorNum);

            if (painted.Count <= 0)
            {
                return(info.mesh);
            }

            var components = FindConnectedComponents(info, painted);
            var subMeshes  = new List <DMesh3>();

            foreach (var component in components.Components)
            {
                DSubmesh3 subMesh = new DSubmesh3(info.mesh, component.Indices);
                var       newMesh = subMesh.SubMesh;
                newMesh.EnableTriangleGroups();
                newMesh.EnableVertexColors(ColorManager.Instance.GetColorForId(info.data.ColorNum).toVector3f());

                foreach (var componentIndex in component.Indices)
                {
                    info.mesh.RemoveTriangle(componentIndex);
                }

                var loops             = new MeshBoundaryLoops(newMesh, true);
                var meshEditorNewMesh = new MeshEditor(newMesh);
                var meshEditorOldMesh = new MeshEditor(info.mesh);
                foreach (var meshBoundaryLoop in loops)
                {
                    var offsettedVerticesNewMesh = new List <int>();
                    var offsettedVerticesOldMesh = new List <int>();
                    foreach (var vertex in meshBoundaryLoop.Vertices)
                    {
                        var normal          = newMesh.GetVertexNormal(vertex);
                        var vertextPosition = newMesh.GetVertex(vertex);
                        var newVertex       = newMesh.AppendVertex(vertextPosition - normal.toVector3d() * info.data.depth);
                        offsettedVerticesNewMesh.Add(newVertex);
                        var newVertexOldMesh =
                            info.mesh.AppendVertex(vertextPosition - normal.toVector3d() * info.data.depth);
                        offsettedVerticesOldMesh.Add(newVertexOldMesh);
                    }

                    var boundaryLoopOfOldMesh = meshBoundaryLoop.Vertices
                                                .Select(subv => subMesh.MapVertexToBaseMesh(subv)).ToArray();
                    var loopNewMesh = meshEditorNewMesh.StitchLoop(meshBoundaryLoop.Vertices,
                                                                   offsettedVerticesNewMesh.ToArray(), info.data.ColorNum);
                    var loopOldMesh = meshEditorOldMesh.StitchLoop(boundaryLoopOfOldMesh,
                                                                   offsettedVerticesOldMesh.ToArray(), info.data.mainColorId);

                    for (var index = 0; index < offsettedVerticesNewMesh.Count; index++)
                    {
                        info.PointToPoint.Add(offsettedVerticesNewMesh[index], offsettedVerticesOldMesh[index]);
                    }

                    var offsettedLoop = EdgeLoop.FromVertices(newMesh, offsettedVerticesNewMesh);
                    var holeFiller    = new SimpleHoleFiller(newMesh, offsettedLoop);
                    var valid         = holeFiller.Validate();
                    if (valid == ValidationStatus.Ok)
                    {
                        var res = holeFiller.Fill(info.data.ColorNum);
                        if (res)
                        {
                            var newVertex    = holeFiller.NewVertex;
                            var newTriangles = holeFiller.NewTriangles;

                            //Add the same triangles to old mesh.
                            if (newVertex == -1) //case where it added only one tri
                            {
                                var vertices     = newMesh.GetTriangle(newTriangles.First());
                                var edgeAOldMesh = info.PointToPoint[vertices.a];
                                var edgeBOldMesh = info.PointToPoint[vertices.b];
                                var edgeCOldMesh = info.PointToPoint[vertices.c];
                                info.mesh.AppendTriangle(edgeAOldMesh, edgeCOldMesh, edgeBOldMesh, info.data.mainColorId);
                            }
                            else //case where multiple tris and a middle vertex were added
                            {
                                var newVertexOldMesh = info.mesh.AppendVertex(newMesh.GetVertex(newVertex));
                                foreach (var newTriangle in newTriangles)
                                {
                                    //the center is always the first vertex in newTriangle
                                    var edgeVertices = newMesh.GetTriangle(newTriangle);
                                    var edgeBOldMesh = info.PointToPoint[edgeVertices.b];
                                    var edgeCOldMesh = info.PointToPoint[edgeVertices.c];
                                    info.mesh.AppendTriangle(newVertexOldMesh, edgeCOldMesh, edgeBOldMesh,
                                                             info.data.mainColorId);
                                }

                                if (info.PointToPoint.ContainsKey(newVertex))
                                {
                                    Debug.Log($"Double insertion from HF: {newVertex}, {newVertexOldMesh}");
                                }
                                else
                                {
                                    info.PointToPoint.Add(newVertex, newVertexOldMesh);
                                }
                            }
                        }
                    }
                }
                subMeshes.Add(newMesh);
            }

            InstantiateNewObjects(info, subMeshes);


            return(info.mesh);
        }
Beispiel #3
0
        /// <summary>
        /// This function tries to remove vertices from loop to hit TargetVtxCount. We call this
        /// when polygon-insertion returns more vertices than polygon. Strategy is to try to find
        /// co-linear vertices, ie that can be removed without changing shape. If that fails,
        /// we remove vertices that result in smallest length change (probably should do proper simplification
        /// here instead).
        ///
        /// Basically this is to handle failures in MeshInsertUVPolyCurve.Simplify(), which sometimes
        /// fails to remove extra vertices because it would case triangle flips. Here we don't
        /// care about triangle flips.
        ///
        /// Note that if the input polygon had splits on edges, this function would remove those
        /// vertices. Which is not ideal.
        /// </summary>
        protected EdgeLoop simplify_loop(DMesh3 mesh, EdgeLoop loop, int TargetVtxCount)
        {
            while (loop.VertexCount > TargetVtxCount)
            {
                DCurve3 curve = loop.ToCurve();

                DMesh3.EdgeCollapseInfo cinfo;

                int NV = loop.VertexCount;
                for (int k = 1; k <= NV; ++k)
                {
                    int prevv = k - 1;
                    int curv  = k % NV;
                    int nextv = (k + 1) % NV;
                    //if (curve[prevv].Distance(curve[curv]) < 0.0001 ||
                    //        curve[nextv].Distance(curve[curv]) < 0.0001)
                    //    f3.DebugUtil.Log("DEGENERATE!!");
                    double angle = curve.OpeningAngleDeg(curv);
                    if (angle > 179)
                    {
                        MeshResult r = mesh.CollapseEdge(loop.Vertices[prevv], loop.Vertices[curv], out cinfo);
                        mesh.SetVertex(loop.Vertices[prevv], curve[prevv]);
                        if (r == MeshResult.Ok)
                        {
                            goto done_this_iter;
                        }
                        else
                        {
                            f3.DebugUtil.Log("collinear collapse failed!");
                        }
                    }
                }
                f3.DebugUtil.Log("Did not find collinear vert...");

                int i_shortest = -1; double shortest_len = double.MaxValue;
                for (int k = 1; k <= NV; ++k)
                {
                    int      prevv   = k - 1;
                    int      curv    = k % NV;
                    int      nextv   = (k + 1) % NV;
                    Vector3d pc      = curve[curv] - curve[prevv];
                    Vector3d pn      = curve[nextv] - curve[curv];
                    double   len_sum = pc.Length + pn.Length;
                    if (len_sum < shortest_len)
                    {
                        i_shortest   = curv;
                        shortest_len = len_sum;
                    }
                }
                if (i_shortest != -1)
                {
                    int        curv   = i_shortest;
                    int        prevv  = (curv == 0) ? NV - 1 : curv - 1;
                    int        nextv  = (curv + 1) % NV;
                    Vector3d   pc     = curve[curv] - curve[prevv];
                    Vector3d   pn     = curve[nextv] - curve[curv];
                    int        iWhich = (pc.Length < pn.Length) ? prevv : nextv;
                    MeshResult r      = mesh.CollapseEdge(loop.Vertices[iWhich], loop.Vertices[curv], out cinfo);
                    if (r == MeshResult.Ok)
                    {
                        goto done_this_iter;
                    }
                    else
                    {
                        f3.DebugUtil.Log("shortest failed!");
                    }
                }
                f3.DebugUtil.Log("Did not find shortest vert...");

                // if we didn't find a vert to remove yet, just arbitrarily remove first one
                int        v0 = loop.Vertices[0], v1 = loop.Vertices[1];
                MeshResult result = mesh.CollapseEdge(v1, v0, out cinfo);

done_this_iter:
                List <int> new_verts = new List <int>();
                for (int k = 0; k < loop.Vertices.Count(); ++k)
                {
                    if (mesh.IsVertex(loop.Vertices[k]))
                    {
                        new_verts.Add(loop.Vertices[k]);
                    }
                }
                loop = EdgeLoop.FromVertices(mesh, new_verts);
            }

            return(loop);
        }
Beispiel #4
0
        public static void quick_test_2()
        {
            DMesh3         target        = TestUtil.LoadTestInputMesh("cylinder_orig.obj");
            DMeshAABBTree3 targetSpatial = new DMeshAABBTree3(target, true);

            DMesh3         mesh        = TestUtil.LoadTestInputMesh("cylinder_approx.obj");
            DMeshAABBTree3 meshSpatial = new DMeshAABBTree3(mesh, true);

            double search_dist = 10.0;

            MeshTopology topo = new MeshTopology(target);

            topo.Compute();

            RemesherPro r = new RemesherPro(mesh);

            r.SetTargetEdgeLength(2.0);
            r.SmoothSpeedT = 0.5;
            r.SetProjectionTarget(MeshProjectionTarget.Auto(target));
            MeshConstraints cons = new MeshConstraints();

            r.SetExternalConstraints(cons);


            int set_id = 1;

            foreach (var loop in topo.Loops)
            {
                DCurveProjectionTarget curveTarget = new DCurveProjectionTarget(loop.ToCurve(target));
                set_id++;

                // pick a set of points we will find paths between. We will chain
                // up those paths and constrain them to target loops.
                // (this part is the hack!)
                List <int> target_verts = new List <int>();
                List <int> mesh_verts   = new List <int>();
                for (int k = 0; k < loop.VertexCount; k += 5)
                {
                    target_verts.Add(loop.Vertices[k]);

                    Vector3d vCurve   = target.GetVertex(loop.Vertices[k]);
                    int      mesh_vid = meshSpatial.FindNearestVertex(vCurve, search_dist);
                    mesh_verts.Add(mesh_vid);
                }
                int NT = target_verts.Count;

                // find the paths to assemble the edge chain
                // [TODO] need to filter out junction vertices? or will they just handle themselves
                //   because they can be collapsed away?
                List <int> vert_seq = new List <int>();
                for (int k = 0; k < NT; k++)
                {
                    EdgeSpan e = find_edge_path(mesh, mesh_verts[k], mesh_verts[(k + 1) % NT]);
                    int      n = e.Vertices.Length;
                    for (int i = 0; i < n - 1; ++i)
                    {
                        vert_seq.Add(e.Vertices[i]);
                    }
                }

                // now it's easy, just add the loop constraint
                EdgeLoop full_loop = EdgeLoop.FromVertices(mesh, vert_seq);
                MeshConstraintUtil.ConstrainVtxLoopTo(cons, mesh, full_loop.Vertices, curveTarget, set_id);
            }


            r.FastestRemesh();

            TestUtil.WriteTestOutputMesh(mesh, "curves_test_out.obj");
        }