Ejemplo n.º 1
0
 /// <summary>
 /// Creates g3.DCurve from Vector3[]
 /// </summary>
 /// <param name="curve">DCurve</param>
 /// <param name="verteces">Vextor3[]</param>
 /// <param name="bClosed">whether the line is closed</param>
 public static DCurve3 Vector3(this DCurve3 curve, Vector3[] verteces, bool bClosed)
 {
     curve.ClearVertices();
     curve.Closed = bClosed;
     foreach (Vector3 vertex in verteces)
     {
         curve.AppendVertex(vertex);
     }
     return(curve);
 }
Ejemplo n.º 2
0
        public static DCurve3 ExtractLoopV(IMesh mesh, int[] vertices)
        {
            DCurve3 curve = new DCurve3();

            for (int i = 0; i < vertices.Length; ++i)
            {
                curve.AppendVertex(mesh.GetVertex(vertices[i]));
            }
            curve.Closed = true;
            return(curve);
        }
Ejemplo n.º 3
0
        public static DCurve3 ExtractLoopV(IMesh mesh, IEnumerable <int> vertices)
        {
            DCurve3 curve = new DCurve3();

            foreach (int vid in vertices)
            {
                curve.AppendVertex(mesh.GetVertex(vid));
            }
            curve.Closed = true;
            return(curve);
        }
Ejemplo n.º 4
0
        public static void Restore(DCurve3 curve, BinaryReader reader)
        {
            curve.Closed = reader.ReadBoolean();
            int count = reader.ReadInt32();

            for (int i = 0; i < count; ++i)
            {
                double x = reader.ReadDouble();
                double y = reader.ReadDouble();
                double z = reader.ReadDouble();
                curve.AppendVertex(new Vector3D(x, y, z));
            }
        }
Ejemplo n.º 5
0
        public void smooth_append(DCurve3 curve, Vector3f newPos, float fDistThresh)
        {
            // empty curve, always append
            if (curve.VertexCount == 0)
            {
                curve.AppendVertex(newPos);
                last_append          = newPos;
                appended_last_update = true;
                have_temp_append     = false;
                return;
            }
            else if (curve.VertexCount == 1)
            {
                curve.AppendVertex(newPos);
                last_append          = newPos;
                appended_last_update = true;
                have_temp_append     = true;
                return;
            }
            else if (curve.VertexCount <= 3)
            {
                curve[curve.VertexCount - 1] = newPos;
            }

            double d = (newPos - last_append).Length;

            if (d < fDistThresh)
            {
                // have not gone far enough for a real new vertex!

                Vector3f usePos = new Vector3f(newPos);
                bool     bValid = false;

                // do we have enough vertices to do a good job?
                if (curve.VertexCount > 3)
                {
                    int      nLast = (have_temp_append) ? curve.VertexCount - 2 : curve.VertexCount - 1;
                    Vector3d tan   = curve.Tangent(nLast);
                    double   fDot  = tan.Dot((usePos - curve[nLast]).Normalized);
                    if (fDot > 0.9f)        // cos(25) ~= 0.9f
                    // new vtx is aligned with tangent of last "real" vertex
                    {
                        bValid = true;
                    }
                    else
                    {
                        // not aligned, try projection onto tangent
                        Line3d l = new Line3d(curve[nLast], tan);
                        double t = l.Project(newPos);
                        if (t > 0)
                        {
                            // projection of new vtx is 'ahead' so we can use it
                            usePos = (Vector3f)l.PointAt(t);
                            bValid = true;
                        }
                    }
                }

                if (bValid)
                {
                    if (appended_last_update)
                    {
                        curve.AppendVertex(usePos);
                        have_temp_append = true;
                    }
                    else if (have_temp_append)
                    {
                        curve[curve.VertexCount - 1] = usePos;
                    }
                }

                appended_last_update = false;
            }
            else
            {
                // ok we drew far enough, add this position

                if (have_temp_append)
                {
                    // re-use temp vertex
                    curve[curve.VertexCount - 1] = newPos;
                    have_temp_append             = false;
                }
                else
                {
                    curve.AppendVertex(newPos);
                }
                last_append          = newPos;
                appended_last_update = true;

                // do smoothing pass
                smoother.End   = curve.VertexCount - 1;
                smoother.Start = MathUtil.Clamp(smoother.End - 5, 0, smoother.End);
                smoother.UpdateDeformation(2);
            }
        }
Ejemplo n.º 6
0
 public virtual void AppendVertex(Vector3d v)
 {
     curve.AppendVertex(v);
 }
        protected void merge_loops(DMesh3 mesh, EdgeLoop cutLoop, EdgeLoop connectorLoop, bool is_outer)
        {
            /*
             * To join the loops, we are going to first make a circle, then snap both
             * open loops to that circle. Then we sample a set of vertices on the circle
             * and remesh the loops while also snapping them to the circle vertices.
             * The result is two perfectly-matching edge loops.
             */

            //AxisAlignedBox3d cutLoopBounds =
            //    BoundsUtil.Bounds(cutLoop.Vertices, (vid) => { return mesh.GetVertex(vid); });

            AxisAlignedBox3d cutLoopBounds       = cutLoop.GetBounds();
            AxisAlignedBox3d connectorLoopBounds = connectorLoop.GetBounds();
            Vector3d         midPt = (cutLoopBounds.Center + connectorLoopBounds.Center) * 0.5;
            double           midY  = midPt.y;

            // this mess construcst the circle and the sampled version
            Frame3f           circFrame       = new Frame3f(midPt);
            Circle3d          circ            = new Circle3d(circFrame, connectorLoopBounds.Width * 0.5, 1);
            DistPoint3Circle3 dist            = new DistPoint3Circle3(Vector3d.Zero, circ);
            DCurve3           sampled         = new DCurve3();
            double            target_edge_len = TargetMeshEdgeLength;
            int N = (int)(circ.ArcLength / target_edge_len);

            for (int k = 0; k < N; ++k)
            {
                sampled.AppendVertex(circ.SampleT((double)k / (double)N));
            }

            MergeProjectionTarget circleTarget = new MergeProjectionTarget()
            {
                Mesh = mesh, CircleDist = dist, CircleLoop = sampled
            };

            EdgeLoop[] loops = new EdgeLoop[2] {
                cutLoop, connectorLoop
            };
            EdgeLoop[] outputLoops = new EdgeLoop[2];   // loops after this remeshing/etc (but might be missing some verts/edges!)
            for (int li = 0; li < 2; ++li)
            {
                EdgeLoop loop = loops[li];

                // snap the loop verts onto the analytic circle
                foreach (int vid in loop.Vertices)
                {
                    Vector3d v = mesh.GetVertex(vid);
                    dist.Point = new Vector3d(v.x, midY, v.z);
                    mesh.SetVertex(vid, dist.Compute().CircleClosest);
                }

                if (DebugStep <= 5)
                {
                    continue;
                }

                // remesh around the edge loop while we snap it to the sampled circle verts
                EdgeLoopRemesher loopRemesh = new EdgeLoopRemesher(mesh, loop)
                {
                    LocalSmoothingRings = 3
                };
                loopRemesh.EnableParallelProjection = false;
                loopRemesh.SetProjectionTarget(circleTarget);
                loopRemesh.SetTargetEdgeLength(TargetMeshEdgeLength);
                loopRemesh.SmoothSpeedT = 0.5f;
                for (int k = 0; k < 5; ++k)
                {
                    loopRemesh.BasicRemeshPass();
                }
                loopRemesh.SmoothSpeedT = 0;
                for (int k = 0; k < 2; ++k)
                {
                    loopRemesh.BasicRemeshPass();
                }
                EdgeLoop newLoop = loopRemesh.OutputLoop;
                outputLoops[li] = newLoop;

                if (DebugStep <= 6)
                {
                    continue;
                }

                // hard snap the loop vertices to the sampled circle verts
                foreach (int vid in newLoop.Vertices)
                {
                    Vector3d v = mesh.GetVertex(vid);
                    v = circleTarget.Project(v, vid);
                    mesh.SetVertex(vid, v);
                }

                // [TODO] we could re-order newLoop verts/edges to match the sampled verts order,
                // then the pair of loops would be consistently ordered (currently no guarantee)

                if (DebugStep <= 7)
                {
                    continue;
                }

                // collapse any degenerate edges on loop (just in case)
                // DANGER: if this actually happens, then outputLoops[li] has some invalid verts/edges!
                foreach (int eid in newLoop.Edges)
                {
                    if (mesh.IsEdge(eid))
                    {
                        Index2i  ev = mesh.GetEdgeV(eid);
                        Vector3d a = mesh.GetVertex(ev.a), b = mesh.GetVertex(ev.b);
                        if (a.Distance(b) < TargetMeshEdgeLength * 0.001)
                        {
                            DMesh3.EdgeCollapseInfo collapse;
                            mesh.CollapseEdge(ev.a, ev.b, out collapse);
                        }
                    }
                }
            }

            if (DebugStep <= 7)
            {
                return;
            }


            /*
             * Ok now we want to merge the loops and make them nice
             */

            // would be more efficient to find loops and stitch them...
            MergeCoincidentEdges merge = new MergeCoincidentEdges(mesh);

            merge.Apply();

            // fill any fail-holes??

            // remesh merge region
            MeshVertexSelection remesh_roi_v = new MeshVertexSelection(mesh);

            remesh_roi_v.Select(outputLoops[0].Vertices);
            remesh_roi_v.Select(outputLoops[1].Vertices);
            remesh_roi_v.ExpandToOneRingNeighbours(5);
            MeshFaceSelection remesh_roi = new MeshFaceSelection(mesh, remesh_roi_v, 1);

            remesh_roi.LocalOptimize(true, true);

            IProjectionTarget projTarget = null;

            if (is_outer)
            {
                projTarget = new NoPenetrationProjectionTarget()
                {
                    Spatial = this.OuterOffsetMeshSpatial
                };
            }
            else
            {
                projTarget = new NoPenetrationProjectionTarget()
                {
                    Spatial = this.InnerOffsetMeshSpatial
                };
            }

            RegionRemesher join_remesh =
                RegionRemesher.QuickRemesh(mesh, remesh_roi.ToArray(), TargetMeshEdgeLength, 0.5, 5, projTarget);

            if (DebugStep <= 8)
            {
                return;
            }


            if (false && is_outer)
            {
                Func <int, bool> filterF = (tid) => {
                    return(mesh.GetTriCentroid(tid).y > connectorLoopBounds.Max.y);
                };

                MeshFaceSelection tris = new MeshFaceSelection(mesh);
                foreach (int tid in join_remesh.CurrentBaseTriangles)
                {
                    if (filterF(tid))
                    {
                        tris.Select(tid);
                    }
                }
                tris.ExpandToOneRingNeighbours(5, filterF);

                MeshVertexSelection verts  = new MeshVertexSelection(mesh, tris);
                MeshIterativeSmooth smooth = new MeshIterativeSmooth(mesh, verts.ToArray(), true);
                smooth.Alpha    = 1.0f;
                smooth.Rounds   = 25;
                smooth.ProjectF = (v, n, vid) => { return(projTarget.Project(v)); };
                smooth.Smooth();
            }


            // [RMS] this smooths too far. we basically only want to smooth 'up' from top of socket...
            //LaplacianMeshSmoother.RegionSmooth(mesh, join_remesh.CurrentBaseTriangles, 1, 10);

            // need to post-enforce thickness, which we aren't doing above - we could though
        }