Beispiel #1
0
        /*
         * Support for slicing mesh
         */

        protected bool ComputeSlicePlaneCurves(DMesh3 mesh, DMeshAABBTree3 spatial,
                                               double z, bool is_solid,
                                               out Polygon2d[] loops, out PolyLine2d[] curves)
        {
            Func <Vector3d, double> planeF = (v) =>
            {
                return(v.z - z);
            };

            // find list of triangles that intersect this z-value
            PlaneIntersectionTraversal planeIntr = new PlaneIntersectionTraversal(mesh, z);

            spatial.DoTraversal(planeIntr);
            List <int> triangles = planeIntr.triangles;

            // compute intersection iso-curves, which produces a 3D graph of undirected edges
            MeshIsoCurves iso = new MeshIsoCurves(mesh, planeF)
            {
                WantGraphEdgeInfo = true
            };

            iso.Compute(triangles);
            DGraph3 graph = iso.Graph;

            if (graph.EdgeCount == 0)
            {
                loops  = new Polygon2d[0];
                curves = new PolyLine2d[0];
                return(false);
            }

            // if this is a closed solid, any open spurs in the graph are errors
            if (is_solid)
            {
                DGraph3Util.ErodeOpenSpurs(graph);
            }

            // [RMS] debug visualization
            //DGraph2 graph2 = new DGraph2();
            //Dictionary<int, int> mapV = new Dictionary<int, int>();
            //foreach (int vid in graph.VertexIndices())
            //    mapV[vid] = graph2.AppendVertex(graph.GetVertex(vid).xy);
            //foreach (int eid in graph.EdgeIndices())
            //    graph2.AppendEdge(mapV[graph.GetEdge(eid).a], mapV[graph.GetEdge(eid).b]);
            //SVGWriter svg = new SVGWriter();
            //svg.AddGraph(graph2, SVGWriter.Style.Outline("black", 0.05f));
            //foreach (int vid in graph2.VertexIndices()) {
            //    if (graph2.IsJunctionVertex(vid))
            //        svg.AddCircle(new Circle2d(graph2.GetVertex(vid), 0.25f), SVGWriter.Style.Outline("red", 0.1f));
            //    else if (graph2.IsBoundaryVertex(vid))
            //        svg.AddCircle(new Circle2d(graph2.GetVertex(vid), 0.25f), SVGWriter.Style.Outline("blue", 0.1f));
            //}
            //svg.Write(string.Format("c:\\meshes\\EXPORT_SLICE_{0}.svg", z));

            // extract loops and open curves from graph
            DGraph3Util.Curves c = DGraph3Util.ExtractCurves(graph, false, iso.ShouldReverseGraphEdge);
            loops = new Polygon2d[c.Loops.Count];
            for (int li = 0; li < loops.Length; ++li)
            {
                DCurve3 loop = c.Loops[li];
                loops[li] = new Polygon2d();
                foreach (Vector3d v in loop.Vertices)
                {
                    loops[li].AppendVertex(v.xy);
                }
            }

            curves = new PolyLine2d[c.Paths.Count];
            for (int pi = 0; pi < curves.Length; ++pi)
            {
                DCurve3 span = c.Paths[pi];
                curves[pi] = new PolyLine2d();
                foreach (Vector3d v in span.Vertices)
                {
                    curves[pi].AppendVertex(v.xy);
                }
            }

            return(true);
        }
 public MeshRepairOrientation(DMesh3 mesh3, DMeshAABBTree3 spatial = null)
 {
     Mesh         = mesh3;
     this.spatial = spatial;
 }
Beispiel #3
0
        public static DMesh3 UnityMeshToDMesh(Mesh mesh, bool bSwapLeftright)
        {
            Vector3[] vertices = mesh.vertices;
            Vector3[] normals  = mesh.normals;
            Color32[] colors32 = mesh.colors32;
            Color[]   colors   = mesh.colors;
            Vector2[] uv       = mesh.uv;

            bool bNormals    = (normals.Length == mesh.vertexCount);
            bool bColors     = (colors.Length == mesh.vertexCount || colors32.Length == mesh.vertexCount);
            bool bByteColors = (colors32.Length == mesh.vertexCount);
            bool bUVs        = (uv.Length == mesh.vertexCount);

            DMesh3 dmesh = new DMesh3(bNormals, bColors, bUVs, false);

            for (int i = 0; i < mesh.vertexCount; ++i)
            {
                Vector3d v = vertices[i];
                if (bSwapLeftright)
                {
                    v.x = -v.x;
                    v.z = -v.z;
                }
                NewVertexInfo vInfo = new NewVertexInfo(v);
                if (bNormals)
                {
                    vInfo.bHaveN = true;
                    vInfo.n      = normals[i];
                    if (bSwapLeftright)
                    {
                        vInfo.n.x = -vInfo.n.x;
                        vInfo.n.z = -vInfo.n.z;
                    }
                }
                if (bColors)
                {
                    vInfo.bHaveC = true;
                    if (bByteColors)
                    {
                        vInfo.c = new Colorf(colors32[i].r, colors32[i].g, colors32[i].b, 255);
                    }
                    else
                    {
                        vInfo.c = colors[i];
                    }
                }
                if (bUVs)
                {
                    vInfo.bHaveUV = true;
                    vInfo.uv      = uv[i];
                }

                int vid = dmesh.AppendVertex(vInfo);
                if (vid != i)
                {
                    throw new InvalidOperationException("UnityUtil.UnityMeshToDMesh: indices weirdness...");
                }
            }

            int[] triangles = mesh.triangles;
            for (int i = 0; i < triangles.Length / 3; ++i)
            {
                dmesh.AppendTriangle(triangles[3 * i], triangles[3 * i + 1], triangles[3 * i + 2]);
            }

            return(dmesh);
        }
Beispiel #4
0
 public AutoHoleFill(DMesh3 mesh, EdgeLoop fillLoop)
 {
     this.Mesh     = mesh;
     this.FillLoop = fillLoop;
 }
 public void AddMesh(DMesh3 mesh)
 {
     AddMesh(mesh, PrintMeshOptions.Default());
 }
Beispiel #6
0
        // Ctor
        public TerrainChunk(int _arrX, int _arrY, int terrainSize)
        {
            //this can be done here because it wont ever need to be modified.
            List <int> inds = new List <int>();

            #region Init
            xPos   = _arrX * (numXVerts - 1);
            yPos   = _arrY * (numXVerts - 1);
            arrayX = _arrX;
            arrayY = _arrY;

            dMesh = new DMesh3(MeshComponents.VertexNormals | MeshComponents.VertexColors);

            int indexTracker = 0;
            for (int i = 0; i < numXVerts; i++)
            {
                for (int j = 0; j < numXVerts; j++)
                {
                    Vector3d v = new Vector3d((float)i + xPos, 0, (float)j + yPos);
                    //vertices.Add(new BasicVertex(Convert.ToV3(v), new Vector3(0, 0, 0), new Vector3(0, 1, 0)));
                    dMesh.AppendVertex(new NewVertexInfo(v, new Vector3f(0, 1, 0)));

                    //fancy uv stuff.
                    float uvu, uvv;
                    uvu = ((1f / (numXVerts - 1)) * i);
                    uvv = 1 - ((1f / (numXVerts - 1)) * j);


                    Vertex vert = new Vertex()
                    {
                        x     = (float)v.x,
                        y     = (float)v.y,
                        z     = (float)v.z,
                        u     = uvu,
                        v     = uvv,
                        n1    = 0.0f,
                        n2    = 1.0f,
                        n3    = 0.0f,
                        index = indexTracker
                    };
                    vertices.Add(vert);
                    vertNeedsCollisionUpdate.Add(false);

                    indexTracker++;
                }
            }
            for (int j = 0; j < numXVerts - 1; j++)
            {
                for (int i = 0; i < numXVerts - 1; i++)
                {
                    int i1, i2, i3, i4, i5, i6;

                    int row1 = i * numXVerts;
                    int row2 = (i + 1) * numXVerts;

                    i1 = row1 + j;
                    i2 = row1 + j + 1;
                    i3 = row2 + j;

                    i4 = row2 + j + 1;
                    i5 = row2 + j;
                    i6 = row1 + j + 1;

                    if (i == numXVerts - 1 && j == numXVerts - 1)
                    {
                        Console.Write(i4 + " " + i5 + " " + i6);
                    }

                    dMesh.AppendTriangle(i1, i2, i3);
                    dMesh.AppendTriangle(i4, i5, i6);
                    inds.Add(i1);
                    inds.Add(i2);
                    inds.Add(i3);
                    inds.Add(i4);
                    inds.Add(i5);
                    inds.Add(i6);
                }
            }
            dMesh.EnableVertexNormals(new Vector3f(0, 1, 0));

            dMeshAABB = new DMeshAABBTree3(dMesh);
            dMeshAABB.Build();
            #endregion
            //
            //
            InitRendering(inds);
        }
        public static void test_remesh_constraints_vertcurves()
        {
            int    Slices = 16;
            DMesh3 mesh   = TestUtil.MakeCappedCylinder(false, Slices);

            MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1));
            //DMesh3 mesh = TestUtil.MakeRemeshedCappedCylinder(0.25);
            //DMesh3 mesh = TestUtil.MakeRemeshedCappedCylinder(1.0);
            mesh.CheckValidity();
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            // construct mesh projection target
            DMesh3 meshCopy = new DMesh3(mesh);

            meshCopy.CheckValidity();
            DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget mesh_target = new MeshProjectionTarget()
            {
                Mesh = meshCopy, Spatial = tree
            };

            // cylinder projection target
            CylinderProjectionTarget cyl_target = new CylinderProjectionTarget()
            {
                Cylinder = new Cylinder3d(new Vector3d(0, 1, 0), Vector3d.AxisY, 1, 2)
            };

            //IProjectionTarget target = mesh_target;
            IProjectionTarget target = cyl_target;

            // construct projection target circles
            CircleProjectionTarget bottomCons = new CircleProjectionTarget()
            {
                Circle = new Circle3d(bounds.Center, 1.0)
            };

            bottomCons.Circle.Center.y = bounds.Min.y;
            CircleProjectionTarget topCons = new CircleProjectionTarget()
            {
                Circle = new Circle3d(bounds.Center, 1.0)
            };

            topCons.Circle.Center.y = bounds.Max.y;


            if (WriteDebugMeshes)
            {
                TestUtil.WriteDebugMesh(mesh, "remesh_analytic_constraints_test_before.obj");
            }

            // construct constraint set
            MeshConstraints cons = new MeshConstraints();

            //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse;
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            bool bConstrainVertices = true;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0f)
                {
                    Index2i  ev  = mesh.GetEdgeV(eid);
                    Vector3d ev0 = mesh.GetVertex(ev[0]);
                    Vector3d ev1 = mesh.GetVertex(ev[1]);
                    CircleProjectionTarget loopTarget = null;
                    if (ev0.y > bounds.Center.y && ev1.y > bounds.Center.y)
                    {
                        loopTarget = topCons;
                    }
                    else if (ev0.y < bounds.Center.y && ev1.y < bounds.Center.y)
                    {
                        loopTarget = bottomCons;
                    }

                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags, loopTarget));
                    if (bConstrainVertices && loopTarget != null)
                    {
                        cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(loopTarget));
                        cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(loopTarget));
                    }
                }
            }


            Remesher r = new Remesher(mesh);

            //r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);
            r.Precompute();
            r.ENABLE_PROFILING = true;

            var stopwatch = Stopwatch.StartNew();

            //double fResScale = 1.0f;
            double fResScale = 0.5f;

            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = 0.1f * fResScale;
            r.MaxEdgeLength   = 0.2f * fResScale;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = 1.0f;

            try {
                for (int k = 0; k < 20; ++k)
                {
                    r.BasicRemeshPass();
                    mesh.CheckValidity();
                }
            } catch {
                // continue;
            }
            stopwatch.Stop();
            System.Console.WriteLine("Second Pass Timing: " + stopwatch.Elapsed);

            if (WriteDebugMeshes)
            {
                TestUtil.WriteDebugMesh(mesh, "remesh_analytic_constraints_test_after.obj");
            }
        }
Beispiel #8
0
 public MeshTopology(DMesh3 mesh)
 {
     Mesh = mesh;
 }
        // [RMS] this only tests some basic cases...
        public static void test_Laplacian()
        {
            // compact version
            DMesh3 mesh = new DMesh3(TestUtil.MakeRemeshedCappedCylinder(1.0), true);

            Debug.Assert(mesh.IsCompact);

            AxisAlignedBox3d bounds = mesh.GetBounds();

            TestUtil.WriteDebugMesh(mesh, "___CG_before.obj");

            List <IMesh> result_meshes = new List <IMesh>();

            // make uniform laplacian matrix
            int N = mesh.VertexCount;
            SymmetricSparseMatrix M = new SymmetricSparseMatrix();

            //DenseMatrix M = new DenseMatrix(N, N);
            double[] Px = new double[N], Py = new double[N], Pz = new double[N];

            int[] nbr_counts = new int[N];
            for (int vid = 0; vid < N; ++vid)
            {
                nbr_counts[vid] = mesh.GetVtxEdgeCount(vid);
            }

            int        ti          = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new Vector3d(2, 5, 2));
            int        v_pin       = mesh.GetTriangle(ti).a;
            List <int> constraints = new List <int>()
            {
                v_pin
            };
            double consW      = 10;
            double consBottom = 10;

            foreach (int vid in constraints)
            {
                result_meshes.Add(TestUtil.MakeMarker(mesh.GetVertex(vid), (vid == 0) ? 0.2f : 0.1f, Colorf.Red));
            }

            for (int vid = 0; vid < N; ++vid)
            {
                int      n = nbr_counts[vid];
                Vector3d v = mesh.GetVertex(vid), c = Vector3d.Zero;

                Px[vid] = v.x; Py[vid] = v.y; Pz[vid] = v.z;

                bool bottom = (v.y - bounds.Min.y) < 0.01f;

                double sum_w = 0;
                foreach (int nbrvid in mesh.VtxVerticesItr(vid))
                {
                    int n2 = nbr_counts[nbrvid];

                    // weight options
                    //double w = -1;
                    double w = -1.0 / Math.Sqrt(n + n2);
                    //double w = -1.0 / n;

                    M.Set(vid, nbrvid, w);

                    c     += w * mesh.GetVertex(nbrvid);
                    sum_w += w;
                }
                sum_w = -sum_w;

                M.Set(vid, vid, sum_w);

                // add soft constraints
                if (constraints.Contains(vid))
                {
                    M.Set(vid, vid, sum_w + consW);
                }
                else if (bottom)
                {
                    M.Set(vid, vid, sum_w + consBottom);
                }
            }

            // compute laplacians
            double[] MLx = new double[N], MLy = new double[N], MLz = new double[N];
            M.Multiply(Px, MLx);
            M.Multiply(Py, MLy);
            M.Multiply(Pz, MLz);


            DiagonalMatrix Preconditioner = new DiagonalMatrix(N);

            for (int i = 0; i < N; i++)
            {
                Preconditioner.Set(i, i, 1.0 / M[i, i]);
            }


            MLy[v_pin] += consW * 0.5f;
            MLx[v_pin] += consW * 0.5f;
            MLz[v_pin] += consW * 0.5f;

            bool useXAsGuess = true;
            // preconditioned
            SparseSymmetricCG SolverX = new SparseSymmetricCG()
            {
                B = MLx, X = Px, MultiplyF = M.Multiply, PreconditionMultiplyF = Preconditioner.Multiply, UseXAsInitialGuess = useXAsGuess
            };
            // initial solution
            SparseSymmetricCG SolverY = new SparseSymmetricCG()
            {
                B = MLy, X = Py, MultiplyF = M.Multiply, UseXAsInitialGuess = useXAsGuess
            };
            // neither of those
            SparseSymmetricCG SolverZ = new SparseSymmetricCG()
            {
                B = MLz, MultiplyF = M.Multiply
            };

            bool bx = SolverX.Solve();
            bool by = SolverY.Solve();
            bool bz = SolverZ.Solve();

            for (int vid = 0; vid < mesh.VertexCount; ++vid)
            {
                Vector3d newV = new Vector3d(SolverX.X[vid], SolverY.X[vid], SolverZ.X[vid]);
                mesh.SetVertex(vid, newV);
            }

            result_meshes.Add(mesh);
            TestUtil.WriteDebugMeshes(result_meshes, "___CG_result.obj");
        }
Beispiel #10
0
        static void Main(string[] args)
        {
            CommandArgumentSet arguments = new CommandArgumentSet();

            arguments.Register("-tcount", int.MaxValue);
            arguments.Register("-percent", 50.0f);
            arguments.Register("-v", false);
            arguments.Register("-output", "");
            if (arguments.Parse(args) == false)
            {
                return;
            }

            if (arguments.Filenames.Count != 1)
            {
                print_usage();
                return;
            }
            string inputFilename = arguments.Filenames[0];

            if (!File.Exists(inputFilename))
            {
                System.Console.WriteLine("File {0} does not exist", inputFilename);
                return;
            }


            string outputFilename = Path.GetFileNameWithoutExtension(inputFilename);
            string format         = Path.GetExtension(inputFilename);

            outputFilename = outputFilename + ".reduced" + format;
            if (arguments.Saw("-output"))
            {
                outputFilename = arguments.Strings["-output"];
            }


            int triCount = int.MaxValue;

            if (arguments.Saw("-tcount"))
            {
                triCount = arguments.Integers["-tcount"];
            }

            float percent = 50.0f;

            if (arguments.Saw("-percent"))
            {
                percent = arguments.Floats["-percent"];
            }

            bool verbose = false;

            if (arguments.Saw("-v"))
            {
                verbose = arguments.Flags["-v"];
            }


            List <DMesh3> meshes;

            try {
                DMesh3Builder builder = new DMesh3Builder();
                IOReadResult  result  = StandardMeshReader.ReadFile(inputFilename, ReadOptions.Defaults, builder);
                if (result.code != IOCode.Ok)
                {
                    System.Console.WriteLine("Error reading {0} : {1}", inputFilename, result.message);
                    return;
                }
                meshes = builder.Meshes;
            } catch (Exception e) {
                System.Console.WriteLine("Exception reading {0} : {1}", inputFilename, e.Message);
                return;
            }
            if (meshes.Count == 0)
            {
                System.Console.WriteLine("file did not contain any valid meshes");
                return;
            }

            DMesh3 mesh = meshes[0];

            for (int k = 1; k < meshes.Count; ++k)
            {
                MeshEditor.Append(mesh, meshes[k]);
            }
            if (mesh.TriangleCount == 0)
            {
                System.Console.WriteLine("mesh does not contain any triangles");
                return;
            }

            if (verbose)
            {
                System.Console.WriteLine("initial mesh contains {0} triangles", mesh.TriangleCount);
            }

            Reducer r = new Reducer(mesh);

            if (triCount < int.MaxValue)
            {
                if (verbose)
                {
                    System.Console.Write("reducing to {0} triangles...", triCount);
                }
                r.ReduceToTriangleCount(triCount);
            }
            else
            {
                int nT = (int)((float)mesh.TriangleCount * percent / 100.0f);
                nT = MathUtil.Clamp(nT, 1, mesh.TriangleCount);
                if (verbose)
                {
                    System.Console.Write("reducing to {0} triangles...", nT);
                }
                r.ReduceToTriangleCount(nT);
            }

            if (verbose)
            {
                System.Console.WriteLine("done!");
            }

            try {
                IOWriteResult wresult =
                    StandardMeshWriter.WriteMesh(outputFilename, mesh, WriteOptions.Defaults);
                if (wresult.code != IOCode.Ok)
                {
                    System.Console.WriteLine("Error writing {0} : {1}", inputFilename, wresult.message);
                    return;
                }
            } catch (Exception e) {
                System.Console.WriteLine("Exception reading {0} : {1}", inputFilename, e.Message);
                return;
            }

            return;
        }
Beispiel #11
0
 public fMesh(DMesh3 source)
 {
     mesh = UnityUtil.DMeshToUnityMesh(source, false);
 }
        private static List <Polygon2d> decompose_cluster_up(DMesh3 mesh, double minArea)
        {
            optimize_mesh(mesh);
            mesh.CompactInPlace();
            mesh.DiscardTriangleGroups();
            mesh.EnableTriangleGroups(0);

            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);
        }
Beispiel #13
0
            public void Compute(PrintSettings printSettings)
            {
                int N = meshCopies.Count();

                slicer = new MeshPlanarSlicerPro()
                {
                    LayerHeightMM = printSettings.LayerHeightMM,
                    // [RMS] 1.5 here is a hack. If we don't leave a bit of space then often the filament gets squeezed right at
                    //   inside/outside transitions, which is bad. Need a better way to handle.
                    OpenPathDefaultWidthMM = printSettings.NozzleDiameterMM * 1.5,
                    SetMinZValue           = 0,
                    SliceFactoryF          = PlanarSlicePro.FactoryF
                };

                if (printSettings.OpenMode == PrintSettings.OpenMeshMode.Clipped)
                {
                    slicer.DefaultOpenPathMode = PrintMeshOptions.OpenPathsModes.Clipped;
                }
                else if (printSettings.OpenMode == PrintSettings.OpenMeshMode.Embedded)
                {
                    slicer.DefaultOpenPathMode = PrintMeshOptions.OpenPathsModes.Embedded;
                }
                else if (printSettings.OpenMode == PrintSettings.OpenMeshMode.Ignored)
                {
                    slicer.DefaultOpenPathMode = PrintMeshOptions.OpenPathsModes.Ignored;
                }

                if (printSettings.StartLayers > 0)
                {
                    int    start_layers       = printSettings.StartLayers;
                    double std_layer_height   = printSettings.LayerHeightMM;
                    double start_layer_height = printSettings.StartLayerHeightMM;
                    slicer.LayerHeightF = (layer_i) =>
                    {
                        return((layer_i < start_layers) ? start_layer_height : std_layer_height);
                    };
                }

                try
                {
                    MeshAssembly = new PrintMeshAssembly();

                    for (int k = 0; k < N; ++k)
                    {
                        DMesh3 mesh = meshCopies[k];
                        //Frame3f mapF = meshToScene[k];
                        PrintMeshSettings settings = new PrintMeshSettings();

                        var options = new PrintMeshOptions
                        {
                            IsSupport    = (settings.ObjectType == PrintMeshSettings.ObjectTypes.Support),
                            IsCavity     = (settings.ObjectType == PrintMeshSettings.ObjectTypes.Cavity),
                            IsCropRegion = (settings.ObjectType == PrintMeshSettings.ObjectTypes.CropRegion),
                            IsOpen       = settings.OuterShellOnly,
                            OpenPathMode = PrintMeshSettings.Convert(settings.OpenMeshMode),
                            Extended     = new ExtendedPrintMeshOptions()
                            {
                                ClearanceXY = settings.Clearance,
                                OffsetXY    = settings.OffsetXY
                            }
                        };

                        //Vector3f scale = localScale[k];
                        //MeshTransforms.Scale(mesh, scale.x, scale.y, scale.z);
                        //MeshTransforms.FromFrame(mesh, mapF);
                        //MeshTransforms.FlipLeftRightCoordSystems(mesh);
                        //MeshTransforms.ConvertYUpToZUp(mesh);

                        var decomposer = new MeshAssembly(mesh)
                        {
                            HasNoVoids = settings.NoVoids
                        };
                        decomposer.Decompose();

                        MeshAssembly.AddMeshes(decomposer.ClosedSolids, options);

                        PrintMeshOptions openOptions = options.Clone();
                        MeshAssembly.AddMeshes(decomposer.OpenMeshes, openOptions);
                    }

                    if (slicer.Add(MeshAssembly) == false)
                    {
                        throw new Exception("error adding PrintMeshAssembly to Slicer!!");
                    }

                    // set clip box
                    Box2d clip_box = new Box2d(
                        Vector2d.Zero,
                        new Vector2d(printSettings.BedSizeXMM / 2, printSettings.BedSizeYMM / 2));

                    slicer.ValidRegions = new List <GeneralPolygon2d>()
                    {
                        new GeneralPolygon2d(new Polygon2d(clip_box.ComputeVertices()))
                    };

                    SliceStack = slicer.Compute();

                    Success = true;
                }
                catch (Exception e)
                {
                    //DebugUtil.Log("GeometrySlicer.Compute: exception: " + e.Message);
                    System.Diagnostics.Debugger.Break();
                    Success = false;
                }

                Finished = true;
            }
Beispiel #14
0
        static string GenerateGCodeForMeshes(PrintMeshAssembly meshes)
        {
            AxisAlignedBox3d bounds = meshes.TotalBounds;
            double           top_z  = bounds.Depth;

            // configure settings
            RepRapSettings settings = new RepRapSettings(RepRap.Models.Unknown);

            settings.GenerateSupport = false;
            settings.EnableBridging  = false;

            int nSpeed = 1200;  // foam

            //int nSpeed = 700;   // wood

            settings.RapidTravelSpeed     = nSpeed;
            settings.RapidExtrudeSpeed    = nSpeed;
            settings.CarefulExtrudeSpeed  = nSpeed;
            settings.OuterPerimeterSpeedX = 1.0;
            settings.ZTravelSpeed         = nSpeed;
            settings.RetractSpeed         = nSpeed;

            settings.LayerHeightMM        = 4.0;
            settings.Machine.NozzleDiamMM = 6.35;

            settings.Machine.BedSizeXMM = 240;
            settings.Machine.BedSizeYMM = 190;

            settings.RetractDistanceMM = 1;
            settings.EnableRetraction  = true;

            settings.ShellsFillNozzleDiamStepX = 0.5;
            settings.SolidFillNozzleDiamStepX  = 0.9;
            settings.SolidFillBorderOverlapX   = 0.5;

            LastSettings = settings.CloneAs <SingleMaterialFFFSettings>();

            System.Console.WriteLine("Slicing...");

            // slice meshes
            MeshPlanarMillSlicer slicer = new MeshPlanarMillSlicer()
            {
                LayerHeightMM     = settings.LayerHeightMM,
                ToolDiameter      = settings.Machine.NozzleDiamMM,
                ExpandStockAmount = 0.4 * settings.Machine.NozzleDiamMM
            };

            slicer.Add(meshes);
            MeshPlanarMillSlicer.Result sliceResult = slicer.Compute();
            PlanarSliceStack            slices      = sliceResult.Clearing;

            System.Console.WriteLine("Generating GCode...");

            ToolpathSet accumPaths;
            GCodeFile   genGCode = generate_cnc_test(sliceResult, settings, out accumPaths);

            System.Console.WriteLine("Writing GCode...");

            string sWritePath          = "../../../sample_output/generated.nc";
            StandardGCodeWriter writer = new StandardGCodeWriter()
            {
                CommentStyle = StandardGCodeWriter.CommentStyles.Bracket
            };

            using (StreamWriter w = new StreamWriter(sWritePath)) {
                writer.WriteFile(genGCode, w);
            }

            //DMesh3 tube_mesh = GenerateTubeMeshesForGCode(sWritePath, settings.Machine.NozzleDiamMM);
            DMesh3 tube_mesh = GenerateTubeMeshesForGCode(sWritePath, 0.4);

            StandardMeshWriter.WriteMesh("../../../sample_output/generated_tubes.obj", tube_mesh, WriteOptions.Defaults);

            if (SHOW_RELOADED_GCODE_PATHS == false)
            {
                View.SetPaths(accumPaths, settings);
                View.PathDiameterMM = (float)settings.Machine.NozzleDiamMM;
            }


            slices.Add(sliceResult.HorizontalFinish.Slices);
            slices.Slices.Sort((a, b) => { return(a.Z.CompareTo(b.Z)); });
            View.SetSlices(slices);
            View.CurrentLayer = slices.Slices.Count - 1;

            return(sWritePath);
        }
        public override Schematic WriteSchematic()
        {
            DMesh3           mesh   = StandardMeshReader.ReadMesh(_path);
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            DMeshAABBTree3    spatial  = new DMeshAABBTree3(mesh, autoBuild: true);
            double            cellsize = mesh.CachedBounds.MaxDim / mGridSize;
            ShiftGridIndexer3 indexer  = new ShiftGridIndexer3(bounds.Min, cellsize);

            MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(mesh, cellsize);

            sdf.Compute();

            Bitmap3 bmp = new Bitmap3(sdf.Dimensions);

            Schematic schematic = new Schematic();

            if (mWindingNumber != 0)
            {
                spatial.WindingNumber(Vector3d.Zero);  // seed cache outside of parallel eval

                using (ProgressBar progressbar = new ProgressBar())
                {
                    List <Vector3i> list  = bmp.Indices().ToList();
                    int             count = 0;
                    gParallel.ForEach(bmp.Indices(), (idx) =>
                    {
                        Vector3d v = indexer.FromGrid(idx);
                        bmp.SafeSet(idx, spatial.WindingNumber(v) > mWindingNumber);
                        count++;
                        progressbar.Report(count / (float)list.Count);
                    });
                }
                if (!mExcavate)
                {
                    foreach (Vector3i idx in bmp.Indices())
                    {
                        if (bmp.Get(idx))
                        {
                            schematic.Blocks.Add(new Voxel((ushort)idx.x, (ushort)idx.y, (ushort)idx.z, Color.White.ColorToUInt()));
                        }
                    }
                }
            }
            else
            {
                using (ProgressBar progressbar = new ProgressBar())
                {
                    int             count = bmp.Indices().Count();
                    List <Vector3i> list  = bmp.Indices().ToList();
                    for (int i = 0; i < count; i++)
                    {
                        Vector3i idx      = list[i];
                        float    f        = sdf[idx.x, idx.y, idx.z];
                        bool     isInside = f < 0;
                        bmp.Set(idx, (f < 0));

                        if (!mExcavate && isInside)
                        {
                            schematic.Blocks.Add(new Voxel((ushort)idx.x, (ushort)idx.y, (ushort)idx.z, Color.White.ColorToUInt()));
                        }
                        progressbar.Report((i / (float)count));
                    }
                }
            }



            if (mExcavate)
            {
                foreach (Vector3i idx in bmp.Indices())
                {
                    if (bmp.Get(idx) && IsBlockConnectedToAir(bmp, idx))
                    {
                        schematic.Blocks.Add(new Voxel((ushort)idx.x, (ushort)idx.y, (ushort)idx.z, Color.White.ColorToUInt()));
                    }
                }
            }

            return(schematic);
        }
Beispiel #16
0
        public static fMesh DMeshToUnityMesh(DMesh3 m, bool bSwapLeftRight, bool bAllowLargeMeshes = false)
        {
            if (bSwapLeftRight)
            {
                throw new Exception("[RMSNOTE] I think this conversion is wrong, see MeshTransforms.SwapLeftRight. Just want to know if this code is ever hit.");
            }

            if (bAllowLargeMeshes == false)
            {
                if (m.MaxVertexID > 65000 || m.MaxTriangleID > 65000)
                {
                    Debug.Log("[UnityUtil.DMeshToUnityMesh] attempted to import object larger than 65000 verts/tris, not supported by Unity!");
                    return(null);
                }
            }

            Mesh unityMesh = new Mesh();

            Vector3[] vertices = dvector_to_vector3(m.VerticesBuffer);
            Vector3[] normals  = (m.HasVertexNormals) ? dvector_to_vector3(m.NormalsBuffer) : null;

            unityMesh.vertices = vertices;
            if (m.HasVertexNormals)
            {
                unityMesh.normals = normals;
            }
            if (m.HasVertexColors)
            {
                unityMesh.colors = dvector_to_color(m.ColorsBuffer);
            }
            if (m.HasVertexUVs)
            {
                unityMesh.uv = dvector_to_vector2(m.UVBuffer);
            }

            if (bAllowLargeMeshes && (m.MaxVertexID > 65000 || m.TriangleCount > 65000))
            {
                unityMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
            }

            if (m.IsCompactT)
            {
                unityMesh.triangles = dvector_to_int(m.TrianglesBuffer);
            }
            else
            {
                int[] triangles = new int[m.TriangleCount * 3];
                int   ti        = 0;
                for (int k = 0; k < m.MaxTriangleID; ++k)
                {
                    if (m.IsTriangle(k))
                    {
                        Index3i t = m.GetTriangle(k);
                        int     j = 3 * ti;
                        triangles[j]     = t.a;
                        triangles[j + 1] = t.b;
                        triangles[j + 2] = t.c;
                        ti++;
                    }
                }
                unityMesh.triangles = triangles;
            }

            if (m.HasVertexNormals == false)
            {
                unityMesh.RecalculateNormals();
            }

            return(new fMesh(unityMesh));
        }
Beispiel #17
0
        static void HandleGenColOptions(string[] args)
        {
            CommandLine.Parse <GenColOptions>(args, (opts, gOpts) =>
            {
                if (opts.InputFile == null)
                {
                    Console.WriteLine("Please provide input file with -i --input");
                    return;
                }

                if (opts.OutputFile == null)
                {
                    Console.WriteLine("Please provide output file with -o --output");
                    return;
                }

                var inputFileInfos  = new FileInfo(opts.InputFile);
                var outputFileInfos = new FileInfo(opts.OutputFile);

                if (!inputFileInfos.Exists)
                {
                    Console.WriteLine("Input file does not exists");
                    return;
                }

                if (inputFileInfos.Extension == ".ydr")
                {
                    var ydr = new YdrFile();

                    ydr.Load(inputFileInfos.FullName);

                    var modelData  = GenCol_GetModelData(ydr.Drawable.DrawableModelsX);
                    var bComposite = GenCol_CreateBoundComposite(modelData);

                    DMesh3 mesh;

                    if (opts.Mode == "copy")
                    {
                        mesh = new DMesh3();

                        var triangles = new List <DefaultConvexFace <VertexVector3> >();

                        for (int g = 0; g < modelData.Geometries.Count; g++)
                        {
                            var mGeometry = modelData.Geometries[g];

                            for (int i = 0; i < mGeometry.Indices.Count - 2; i += 3)
                            {
                                var vert1 = mGeometry.Vertices[mGeometry.Indices[i + 0]];
                                var vert2 = mGeometry.Vertices[mGeometry.Indices[i + 1]];
                                var vert3 = mGeometry.Vertices[mGeometry.Indices[i + 2]];

                                var triangle = new DefaultConvexFace <VertexVector3>()
                                {
                                    Vertices = new VertexVector3[]
                                    {
                                        vert1,
                                        vert2,
                                        vert3,
                                    }
                                };

                                triangles.Add(triangle);
                            }
                        }

                        mesh = GenCol_CreateMesh(triangles);
                    }
                    else
                    {
                        var hull          = ConvexHull.Create(modelData.Vertices);
                        var hullTriangles = hull.Result.Faces.ToList();

                        mesh = GenCol_CreateMesh(hullTriangles);
                    }

                    GenCol_Reshape(mesh, opts.Smooth, opts.TriangleCount);

                    mesh = GenCol_CleanVertices(mesh);

                    var quantum = (modelData.BbMax - modelData.BbMin) / (2 ^ opts.Qantum);

                    var bGeometry = new BoundGeometry
                    {
                        Type                   = 4,
                        Vertices               = new ResourceSimpleArray <BoundVertex>(),
                        BoundingBoxCenter      = (RAGE_Vector3)modelData.BsCenter,
                        BoundingSphereRadius   = modelData.BsRadius,
                        BoundingBoxMin         = (RAGE_Vector3)modelData.BbMin,
                        BoundingBoxMax         = (RAGE_Vector3)modelData.BbMax,
                        CenterGravity          = new RAGE_Vector3(0.0f, 0.0f, 0.0f),
                        CenterGeometry         = new RAGE_Vector3(0.0f, 0.0f, 0.0f),
                        Margin                 = 0.04f,
                        Quantum                = new RAGE_Vector3(quantum.X, quantum.Y, quantum.Z),
                        Polygons               = new ResourceSimpleArray <BoundPolygon>(),
                        Materials              = new ResourceSimpleArray <BoundMaterial>(),
                        MaterialColours        = new ResourceSimpleArray <uint_r>(),
                        PolygonMaterialIndices = new ResourceSimpleArray <byte_r>(),
                        Unknown_78h_Data       = new ResourceSimpleArray <BoundVertex>(),
                    };

                    var material = new BoundMaterial();

                    bGeometry.Materials.Add(material);

                    var matColour = new uint_r {
                        Value = 0
                    };

                    bGeometry.MaterialColours.Add(matColour);

                    var meshVertices = mesh.Vertices().ToList();

                    for (int i = 0; i < meshVertices.Count; i++)
                    {
                        var vertex  = meshVertices[i];
                        var bVertex = new BoundVertex
                        {
                            X = Convert.ToInt16(vertex.x / quantum.X),
                            Y = Convert.ToInt16(vertex.y / quantum.Y),
                            Z = Convert.ToInt16(vertex.z / quantum.Z),
                        };

                        bGeometry.Vertices.Add(bVertex);
                        bGeometry.Unknown_78h_Data.Add(bVertex);
                    }

                    var meshTriangles = mesh.Triangles().ToList();

                    for (int i = 0; i < meshTriangles.Count; i++)
                    {
                        var polygon  = new BoundPolygon();
                        var triangle = new BoundPolygonTriangle();

                        triangle.TriArea = 0.0f;

                        int vidx1 = meshTriangles[i].a;
                        int vidx2 = meshTriangles[i].b;
                        int vidx3 = meshTriangles[i].c;

                        if (vidx1 == -1 || vidx2 == -1 || vidx3 == -1)
                        {
                            continue;
                        }

                        triangle.TriIndex1 = (ushort)((triangle.TriIndex1 & ~0x7FFF) | (vidx1 & 0x7FFF));
                        triangle.TriIndex2 = (ushort)((triangle.TriIndex2 & ~0x7FFF) | (vidx2 & 0x7FFF));
                        triangle.TriIndex3 = (ushort)((triangle.TriIndex3 & ~0x7FFF) | (vidx3 & 0x7FFF));

                        triangle.EdgeIndex1 = 0;
                        triangle.EdgeIndex2 = 1;
                        triangle.EdgeIndex3 = 2;

                        polygon.data = new byte[16];

                        int offset = 0;

                        byte[] bytes = BitConverter.GetBytes(triangle.TriArea);
                        Buffer.BlockCopy(bytes, 0, polygon.data, offset, bytes.Length);
                        offset += bytes.Length;

                        bytes = BitConverter.GetBytes(triangle.TriIndex1);
                        Buffer.BlockCopy(bytes, 0, polygon.data, offset, bytes.Length);
                        offset += bytes.Length;

                        bytes = BitConverter.GetBytes(triangle.TriIndex2);
                        Buffer.BlockCopy(bytes, 0, polygon.data, offset, bytes.Length);
                        offset += bytes.Length;

                        bytes = BitConverter.GetBytes(triangle.TriIndex3);
                        Buffer.BlockCopy(bytes, 0, polygon.data, offset, bytes.Length);
                        offset += bytes.Length;

                        bytes = BitConverter.GetBytes(triangle.EdgeIndex1);
                        Buffer.BlockCopy(bytes, 0, polygon.data, offset, bytes.Length);
                        offset += bytes.Length;

                        bytes = BitConverter.GetBytes(triangle.EdgeIndex2);
                        Buffer.BlockCopy(bytes, 0, polygon.data, offset, bytes.Length);
                        offset += bytes.Length;

                        bytes = BitConverter.GetBytes(triangle.EdgeIndex3);
                        Buffer.BlockCopy(bytes, 0, polygon.data, offset, bytes.Length);
                        offset += bytes.Length;

                        bGeometry.Polygons.Add(polygon);

                        var matIndex = new byte_r {
                            Value = 0
                        };

                        bGeometry.PolygonMaterialIndices.Add(matIndex);
                    }

                    bComposite.Children.Add(bGeometry);

                    if (outputFileInfos.Extension == ".ybn")
                    {
                        var ybn = new YbnFile
                        {
                            Bound = bComposite
                        };

                        ybn.Save(opts.OutputFile);
                    }
                    else if (outputFileInfos.Extension == ".ydr")
                    {
                        ydr.Drawable.Bound = bComposite;
                        ydr.Save(opts.OutputFile);
                    }
                    else
                    {
                        Console.WriteLine("Output file type not valid");
                    }
                }
                else
                {
                    Console.WriteLine("Input file type not valid");
                }
            });
        }
Beispiel #18
0
        public bool ImportAutoUpdate(PrintMeshSO so)
        {
            SourceFilePath = so.SourceFilePath;
            if (!File.Exists(SourceFilePath))
            {
                ErrorMessage = "MeshImporter.ImportAutoUpdate: file does not exist";
                return(false);
            }

            DMesh3Builder      builder = new DMesh3Builder();
            StandardMeshReader reader  = new StandardMeshReader()
            {
                MeshBuilder = builder
            };

            long timestamp = File.GetLastWriteTime(SourceFilePath).Ticks;

            IOReadResult result = reader.Read(SourceFilePath, ReadOptions.Defaults);

            if (result.code != IOCode.Ok)
            {
                ErrorMessage = "MeshImporter.ImportAutoUpdate: failed with message " + result.message;
                return(false);
            }
            if (builder.Meshes.Count == 0)
            {
                ErrorMessage = "MeshImporter.ImportAutoUpdate: no meshes in file!";
                return(false);
            }
            if (builder.Meshes.Count != 1)
            {
                ErrorMessage = "MeshImporter.ImportAutoUpdate: can only auto-update from file with single mesh!";
                return(false);
            }
            DMesh3 mesh = builder.Meshes[0];

            // unity xforms
            MeshTransforms.ConvertZUpToYUp(mesh);
            MeshTransforms.FlipLeftRightCoordSystems(mesh);

            // wait for any active tools to finish
            // [TODO] do we need to do this?
            while (CC.ActiveContext.ToolManager.HasActiveTool())
            {
                Thread.Sleep(1000);
            }

            if (CC.ActiveScene.SceneObjects.Contains(so) == false)
            {
                ErrorMessage = "MeshImporter.ImportAutoUpdate: SO no longer exists";
                return(false);
            }

            // change event??

            so.LastReadFileTimestamp = timestamp;
            ThreadMailbox.PostToMainThread(() => {
                so.ReplaceMesh(mesh, true);
            });
            return(true);
        }
        public static void test_remesh_constraints_fixedverts()
        {
            int    Slices = 128;
            DMesh3 mesh   = TestUtil.MakeCappedCylinder(false, Slices);

            MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new Vector3f(1, 2, 1));
            mesh.CheckValidity();
            AxisAlignedBox3d bounds = mesh.CachedBounds;

            // construct mesh projection target
            DMesh3 meshCopy = new DMesh3(mesh);

            meshCopy.CheckValidity();
            DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget target = new MeshProjectionTarget()
            {
                Mesh = meshCopy, Spatial = tree
            };

            if (WriteDebugMeshes)
            {
                TestUtil.WriteDebugMesh(mesh, "remesh_fixed_constraints_test_before.obj");
            }

            // construct constraint set
            MeshConstraints cons = new MeshConstraints();

            //EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse;
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0f)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));
                    Index2i ev      = mesh.GetEdgeV(eid);
                    int     nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2;
                    int     nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
                }
            }

            Remesher r = new Remesher(mesh);

            r.Precompute();
            r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);

            var stopwatch = Stopwatch.StartNew();

            //double fResScale = 1.0f;
            double fResScale = 0.5f;

            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = 0.1f * fResScale;
            r.MaxEdgeLength   = 0.2f * fResScale;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = 0.5f;

            try {
                for (int k = 0; k < 20; ++k)
                {
                    r.BasicRemeshPass();
                    mesh.CheckValidity();
                }
            } catch {
                // ignore
            }

            stopwatch.Stop();
            System.Console.WriteLine("Second Pass Timing: " + stopwatch.Elapsed);

            if (WriteDebugMeshes)
            {
                TestUtil.WriteDebugMesh(mesh, "remesh_fixed_constraints_test_after.obj");
            }
        }
Beispiel #20
0
 public MinimalHoleFill(DMesh3 mesh, EdgeLoop fillLoop)
 {
     this.Mesh     = mesh;
     this.FillLoop = fillLoop;
 }
Beispiel #21
0
        // NO DOES NOT WORK. DOES NOT FIND EDGE SPANS THAT ARE IN PLANE BUT HAVE DIFFERENT NORMAL!
        // NEED TO COLLECT UP SPANS USING NORMAL HISTOGRAM NORMALS!
        // ALSO NEED TO ACTUALLY CHECK FOR COPLANARITY, NOT JUST SAME NORMAL!!

        Dictionary <Vector3d, List <EdgeSpan> > find_coplanar_span_sets(DMesh3 mesh, EdgeLoop loop)
        {
            double dot_thresh = 0.999;

            Dictionary <Vector3d, List <EdgeSpan> > span_sets = new Dictionary <Vector3d, List <EdgeSpan> >();

            int NV = loop.Vertices.Length;
            int NE = loop.Edges.Length;

            Vector3d[] edge_normals = new Vector3d[NE];
            for (int k = 0; k < NE; ++k)
            {
                edge_normals[k] = mesh.GetTriNormal(mesh.GetEdgeT(loop.Edges[k]).a);
            }

            // find coplanar verts
            // [RMS] this is wrong, if normals vary smoothly enough we will mark non-coplanar spans as coplanar
            bool[] vert_coplanar = new bool[NV];
            int    nc            = 0;

            for (int k = 0; k < NV; ++k)
            {
                int prev = (k == 0) ? NV - 1 : k - 1;
                if (edge_normals[k].Dot(ref edge_normals[prev]) > dot_thresh)
                {
                    vert_coplanar[k] = true;
                    nc++;
                }
            }
            if (nc < 2)
            {
                return(null);
            }

            int iStart = 0;

            while (vert_coplanar[iStart])
            {
                iStart++;
            }

            int iPrev = iStart;
            int iCur  = iStart + 1;

            while (iCur != iStart)
            {
                if (vert_coplanar[iCur] == false)
                {
                    iPrev = iCur;
                    iCur  = (iCur + 1) % NV;
                    continue;
                }

                List <int> edges = new List <int>()
                {
                    loop.Edges[iPrev]
                };
                int span_start_idx = iCur;
                while (vert_coplanar[iCur])
                {
                    edges.Add(loop.Edges[iCur]);
                    iCur = (iCur + 1) % NV;
                }

                if (edges.Count > 1)
                {
                    Vector3d span_n = edge_normals[span_start_idx];
                    EdgeSpan span   = EdgeSpan.FromEdges(mesh, edges);
                    span.CheckValidity();
                    foreach (var pair in span_sets)
                    {
                        if (pair.Key.Dot(ref span_n) > dot_thresh)
                        {
                            span_n = pair.Key;
                            break;
                        }
                    }
                    List <EdgeSpan> found;
                    if (span_sets.TryGetValue(span_n, out found) == false)
                    {
                        span_sets[span_n] = new List <EdgeSpan>()
                        {
                            span
                        }
                    }
                    ;
                    else
                    {
                        found.Add(span);
                    }
                }
            }



            return(span_sets);
        }
Beispiel #22
0
        public bool Apply()
        {
            // do a simple fill
            SimpleHoleFiller simplefill = new SimpleHoleFiller(Mesh, FillLoop);
            int  fill_gid = Mesh.AllocateTriangleGroup();
            bool bOK      = simplefill.Fill(fill_gid);

            if (bOK == false)
            {
                return(false);
            }

            if (FillLoop.Vertices.Length <= 3)
            {
                FillTriangles = simplefill.NewTriangles;
                FillVertices  = new int[0];
                return(true);
            }

            // extract the simple fill mesh as a submesh, via RegionOperator, so we can backsub later
            HashSet <int> intial_fill_tris = new HashSet <int>(simplefill.NewTriangles);

            regionop = new RegionOperator(Mesh, simplefill.NewTriangles,
                                          (submesh) => { submesh.ComputeTriMaps = true; });
            fillmesh = regionop.Region.SubMesh;

            // for each boundary vertex, compute the exterior angle sum
            // we will use this to compute gaussian curvature later
            boundaryv           = new HashSet <int>(MeshIterators.BoundaryEdgeVertices(fillmesh));
            exterior_angle_sums = new Dictionary <int, double>();
            if (IgnoreBoundaryTriangles == false)
            {
                foreach (int sub_vid in boundaryv)
                {
                    double angle_sum = 0;
                    int    base_vid  = regionop.Region.MapVertexToBaseMesh(sub_vid);
                    foreach (int tid in regionop.BaseMesh.VtxTrianglesItr(base_vid))
                    {
                        if (intial_fill_tris.Contains(tid) == false)
                        {
                            Index3i et  = regionop.BaseMesh.GetTriangle(tid);
                            int     idx = IndexUtil.find_tri_index(base_vid, ref et);
                            angle_sum += regionop.BaseMesh.GetTriInternalAngleR(tid, idx);
                        }
                    }
                    exterior_angle_sums[sub_vid] = angle_sum;
                }
            }


            // try to guess a reasonable edge length that will give us enough geometry to work with in simplify pass
            double loop_mine, loop_maxe, loop_avge, fill_mine, fill_maxe, fill_avge;

            MeshQueries.EdgeLengthStatsFromEdges(Mesh, FillLoop.Edges, out loop_mine, out loop_maxe, out loop_avge);
            MeshQueries.EdgeLengthStats(fillmesh, out fill_mine, out fill_maxe, out fill_avge);
            double remesh_target_len = loop_avge;

            if (fill_maxe / remesh_target_len > 10)
            {
                remesh_target_len = fill_maxe / 10;
            }
            //double remesh_target_len = Math.Min(loop_avge, fill_avge / 4);

            // remesh up to target edge length, ideally gives us some triangles to work with
            RemesherPro remesh1 = new RemesherPro(fillmesh);

            remesh1.SmoothSpeedT = 1.0;
            MeshConstraintUtil.FixAllBoundaryEdges(remesh1);
            //remesh1.SetTargetEdgeLength(remesh_target_len / 2);       // would this speed things up? on large regions?
            //remesh1.FastestRemesh();
            remesh1.SetTargetEdgeLength(remesh_target_len);
            remesh1.FastestRemesh();

            /*
             * first round: collapse to minimal mesh, while flipping to try to
             * get to ballpark minimal mesh. We stop these passes as soon as
             * we have done two rounds where we couldn't do another collapse
             *
             * This is the most unstable part of the algorithm because there
             * are strong ordering effects. maybe we could sort the edges somehow??
             */

            int zero_collapse_passes = 0;
            int collapse_passes      = 0;

            while (collapse_passes++ < 20 && zero_collapse_passes < 2)
            {
                // collapse pass
                int NE        = fillmesh.MaxEdgeID;
                int collapses = 0;
                for (int ei = 0; ei < NE; ++ei)
                {
                    if (fillmesh.IsEdge(ei) == false || fillmesh.IsBoundaryEdge(ei))
                    {
                        continue;
                    }
                    Index2i ev = fillmesh.GetEdgeV(ei);
                    bool    a_bdry = boundaryv.Contains(ev.a), b_bdry = boundaryv.Contains(ev.b);
                    if (a_bdry && b_bdry)
                    {
                        continue;
                    }
                    int      keepv  = (a_bdry) ? ev.a : ev.b;
                    int      otherv = (keepv == ev.a) ? ev.b : ev.a;
                    Vector3d newv   = fillmesh.GetVertex(keepv);
                    if (MeshUtil.CheckIfCollapseCreatesFlip(fillmesh, ei, newv))
                    {
                        continue;
                    }
                    DMesh3.EdgeCollapseInfo info;
                    MeshResult result = fillmesh.CollapseEdge(keepv, otherv, out info);
                    if (result == MeshResult.Ok)
                    {
                        collapses++;
                    }
                }
                if (collapses == 0)
                {
                    zero_collapse_passes++;
                }
                else
                {
                    zero_collapse_passes = 0;
                }

                // flip pass. we flip in these cases:
                //  1) if angle between current triangles is too small (slightly more than 90 degrees, currently)
                //  2) if angle between flipped triangles is smaller than between current triangles
                //  3) if flipped edge length is shorter *and* such a flip won't flip the normal
                NE = fillmesh.MaxEdgeID;
                Vector3d n1, n2, on1, on2;
                for (int ei = 0; ei < NE; ++ei)
                {
                    if (fillmesh.IsEdge(ei) == false || fillmesh.IsBoundaryEdge(ei))
                    {
                        continue;
                    }
                    bool do_flip = false;

                    Index2i ev = fillmesh.GetEdgeV(ei);
                    MeshUtil.GetEdgeFlipNormals(fillmesh, ei, out n1, out n2, out on1, out on2);
                    double dot_cur  = n1.Dot(n2);
                    double dot_flip = on1.Dot(on2);
                    if (n1.Dot(n2) < 0.1 || dot_flip > dot_cur + MathUtil.Epsilonf)
                    {
                        do_flip = true;
                    }

                    if (do_flip == false)
                    {
                        Index2i otherv   = fillmesh.GetEdgeOpposingV(ei);
                        double  len_e    = fillmesh.GetVertex(ev.a).Distance(fillmesh.GetVertex(ev.b));
                        double  len_flip = fillmesh.GetVertex(otherv.a).Distance(fillmesh.GetVertex(otherv.b));
                        if (len_flip < len_e)
                        {
                            if (MeshUtil.CheckIfEdgeFlipCreatesFlip(fillmesh, ei) == false)
                            {
                                do_flip = true;
                            }
                        }
                    }

                    if (do_flip)
                    {
                        DMesh3.EdgeFlipInfo info;
                        MeshResult          result = fillmesh.FlipEdge(ei, out info);
                    }
                }
            }

            // Sometimes, for some reason, we have a remaining interior vertex (have only ever seen one?)
            // Try to force removal of such vertices, even if it makes ugly mesh
            remove_remaining_interior_verts();


            // enable/disable passes.
            bool DO_FLATTER_PASS   = true;
            bool DO_CURVATURE_PASS = OptimizeDevelopability && true;
            bool DO_AREA_PASS      = OptimizeDevelopability && OptimizeTriangles && true;


            /*
             * In this pass we repeat the flipping iterations from the previous pass.
             *
             * Note that because of the always-flip-if-dot-is-small case (commented),
             * this pass will frequently not converge, as some number of edges will
             * be able to flip back and forth (because neither has large enough dot).
             * This is not ideal, but also, if we remove this behavior, then we
             * generally get worse fills. This case basically introduces a sort of
             * randomization factor that lets us escape local minima...
             *
             */

            HashSet <int> remaining_edges = new HashSet <int>(fillmesh.EdgeIndices());
            HashSet <int> updated_edges   = new HashSet <int>();

            int flatter_passes    = 0;
            int zero_flips_passes = 0;

            while (flatter_passes++ < 40 && zero_flips_passes < 2 && remaining_edges.Count() > 0 && DO_FLATTER_PASS)
            {
                zero_flips_passes++;
                foreach (int ei in remaining_edges)
                {
                    if (fillmesh.IsBoundaryEdge(ei))
                    {
                        continue;
                    }

                    bool do_flip = false;

                    Index2i  ev = fillmesh.GetEdgeV(ei);
                    Vector3d n1, n2, on1, on2;
                    MeshUtil.GetEdgeFlipNormals(fillmesh, ei, out n1, out n2, out on1, out on2);
                    double dot_cur  = n1.Dot(n2);
                    double dot_flip = on1.Dot(on2);
                    if (flatter_passes < 20 && dot_cur < 0.1)   // this check causes oscillatory behavior
                    {
                        do_flip = true;
                    }
                    if (dot_flip > dot_cur + MathUtil.Epsilonf)
                    {
                        do_flip = true;
                    }

                    if (do_flip)
                    {
                        DMesh3.EdgeFlipInfo info;
                        MeshResult          result = fillmesh.FlipEdge(ei, out info);
                        if (result == MeshResult.Ok)
                        {
                            zero_flips_passes = 0;
                            add_all_edges(ei, updated_edges);
                        }
                    }
                }

                var tmp = remaining_edges;
                remaining_edges = updated_edges;
                updated_edges   = tmp; updated_edges.Clear();
            }


            int curvature_passes = 0;

            if (DO_CURVATURE_PASS)
            {
                curvatures = new double[fillmesh.MaxVertexID];
                foreach (int vid in fillmesh.VertexIndices())
                {
                    update_curvature(vid);
                }

                remaining_edges = new HashSet <int>(fillmesh.EdgeIndices());
                updated_edges   = new HashSet <int>();

                /*
                 *  In this pass we try to minimize gaussian curvature at all the vertices.
                 *  This will recover sharp edges, etc, and do lots of good stuff.
                 *  However, this pass will not make much progress if we are not already
                 *  relatively close to a minimal mesh, so it really relies on the previous
                 *  passes getting us in the ballpark.
                 */
                while (curvature_passes++ < 40 && remaining_edges.Count() > 0 && DO_CURVATURE_PASS)
                {
                    foreach (int ei in remaining_edges)
                    {
                        if (fillmesh.IsBoundaryEdge(ei))
                        {
                            continue;
                        }

                        Index2i ev = fillmesh.GetEdgeV(ei);
                        Index2i ov = fillmesh.GetEdgeOpposingV(ei);

                        int find_other = fillmesh.FindEdge(ov.a, ov.b);
                        if (find_other != DMesh3.InvalidID)
                        {
                            continue;
                        }

                        double total_curv_cur = curvature_metric_cached(ev.a, ev.b, ov.a, ov.b);
                        if (total_curv_cur < MathUtil.ZeroTolerancef)
                        {
                            continue;
                        }

                        DMesh3.EdgeFlipInfo info;
                        MeshResult          result = fillmesh.FlipEdge(ei, out info);
                        if (result != MeshResult.Ok)
                        {
                            continue;
                        }

                        double total_curv_flip = curvature_metric_eval(ev.a, ev.b, ov.a, ov.b);

                        bool keep_flip = total_curv_flip < total_curv_cur - MathUtil.ZeroTolerancef;
                        if (keep_flip == false)
                        {
                            result = fillmesh.FlipEdge(ei, out info);
                        }
                        else
                        {
                            update_curvature(ev.a); update_curvature(ev.b);
                            update_curvature(ov.a); update_curvature(ov.b);
                            add_all_edges(ei, updated_edges);
                        }
                    }
                    var tmp = remaining_edges;
                    remaining_edges = updated_edges;
                    updated_edges   = tmp; updated_edges.Clear();
                }
            }
            //System.Console.WriteLine("collapse {0}   flatter {1}   curvature {2}", collapse_passes, flatter_passes, curvature_passes);

            /*
             * In this final pass, we try to improve triangle quality. We flip if
             * the flipped triangles have better total aspect ratio, and the
             * curvature doesn't change **too** much. The .DevelopabilityTolerance
             * parameter determines what is "too much" curvature change.
             */
            if (DO_AREA_PASS)
            {
                remaining_edges = new HashSet <int>(fillmesh.EdgeIndices());
                updated_edges   = new HashSet <int>();
                int area_passes = 0;
                while (remaining_edges.Count() > 0 && area_passes < 20)
                {
                    area_passes++;
                    foreach (int ei in remaining_edges)
                    {
                        if (fillmesh.IsBoundaryEdge(ei))
                        {
                            continue;
                        }

                        Index2i ev = fillmesh.GetEdgeV(ei);
                        Index2i ov = fillmesh.GetEdgeOpposingV(ei);

                        int find_other = fillmesh.FindEdge(ov.a, ov.b);
                        if (find_other != DMesh3.InvalidID)
                        {
                            continue;
                        }

                        double total_curv_cur = curvature_metric_cached(ev.a, ev.b, ov.a, ov.b);

                        double a = aspect_metric(ei);
                        if (a > 1)
                        {
                            continue;
                        }

                        DMesh3.EdgeFlipInfo info;
                        MeshResult          result = fillmesh.FlipEdge(ei, out info);
                        if (result != MeshResult.Ok)
                        {
                            continue;
                        }

                        double total_curv_flip = curvature_metric_eval(ev.a, ev.b, ov.a, ov.b);

                        bool keep_flip = Math.Abs(total_curv_cur - total_curv_flip) < DevelopabilityTolerance;
                        if (keep_flip == false)
                        {
                            result = fillmesh.FlipEdge(ei, out info);
                        }
                        else
                        {
                            update_curvature(ev.a); update_curvature(ev.b);
                            update_curvature(ov.a); update_curvature(ov.b);
                            add_all_edges(ei, updated_edges);
                        }
                    }
                    var tmp = remaining_edges;
                    remaining_edges = updated_edges;
                    updated_edges   = tmp; updated_edges.Clear();
                }
            }


            regionop.BackPropropagate();
            FillTriangles = regionop.CurrentBaseTriangles;
            FillVertices  = regionop.CurrentBaseInteriorVertices().ToArray();

            return(true);
        }
Beispiel #23
0
    // Use this for initialization
    public override void Awake()
    {
        // if we need to auto-configure Rift vs Vive vs (?) VR, we need
        // to do this before any other F3 setup, because MainCamera will change
        // and we are caching that in a lot of places...
        if (AutoConfigVR)
        {
            VRCameraRig = gs.VRPlatform.AutoConfigureVR();
        }

        // restore any settings
        SceneGraphConfig.RestorePreferences();

        // set up some defaults
        // this will move the ground plane down, but the bunnies will be floating...
        //SceneGraphConfig.InitialSceneTranslate = -4.0f * Vector3f.AxisY;
        SceneGraphConfig.DefaultSceneCurveVisualDegrees = 0.5f;
        SceneGraphConfig.DefaultPivotVisualDegrees      = 2.3f;
        SceneGraphConfig.DefaultAxisGizmoVisualDegrees  = 25.0f;
        PolyCurveSO.DefaultHitWidthMultiplier           = 2.5f;

        SceneOptions options = new SceneOptions();

        options.UseSystemMouseCursor  = false;
        options.Use2DCockpit          = false;
        options.EnableTransforms      = true;
        options.EnableCockpit         = true;
        options.EnableDefaultLighting = false;
        options.CockpitInitializer    = new SetupOrthoVRCockpit();

        options.MouseCameraControls = new MayaCameraHotkeys()
        {
            MousePanSpeed = 5.0f, MouseZoomSpeed = 5.0f
        };
        options.SpatialCameraRig = VRCameraRig;

        // very verbose
        options.LogLevel = 2;

        // hacks for stuff
#if F3_ENABLE_TEXT_MESH_PRO
        SceneGraphConfig.TextLabelZOffset = -0.01f;
#else
        SceneGraphConfig.TextLabelZOffset = -0.3f;
#endif


        context    = new FContext();
        OG.Context = context;
        OrthogenUI.ActiveContext = context;
        context.Start(options);


        // Set up standard scene lighting if enabled
        if (options.EnableDefaultLighting)
        {
            GameObject lighting = GameObject.Find("SceneLighting");
            if (lighting == null)
            {
                lighting = new GameObject("SceneLighting");
            }
            SceneLightingSetup setup = lighting.AddComponent <SceneLightingSetup>();
            setup.Context              = context;
            setup.ShadowLightCount     = 0;
            setup.AdjustShadowDistance = false;
            setup.LightDistance        = 1000.0f; // related to total scene scale...
        }

        // override sun so that it doesn't stick to one of the scene lights
        RenderSettings.sun = GameObject.Find("SunLight").GetComponent <Light>();

        //GameObjectFactory.CurveRendererSource = new VectrosityCurveRendererFactory();

        // set up ground plane geometry (optional)
        GameObject boundsObject = GameObject.Find("Bounds");
        if (boundsObject != null)
        {
            context.Scene.AddWorldBoundsObject(boundsObject);
        }


        /*
         * ORTHOGEN-SPECIFIC SETUP STARTS HERE
         */

        // set up scene and tools like Orthogen wants them
        OGActions.InitializeVRUsageContext();
        OrthogenMaterials.InitializeMaterials();
        OrthogenMaterials.ScanMaterial = new UnitySOMaterial(MaterialUtil.SafeLoadMaterial("scan_material"));
        //OrthogenMaterials.RectifiedLegMaterial = OrthogenMaterials.ScanMaterial;
        OGActions.InitializeF3Scene(context);
        OGActions.InitializeF3Tools(context);
        OGActions.InitializeF3VRTools(context);
        OGActions.PostConfigureTools_Demo();
        OGActions.ConfigurePlatformInput_VR();


        /*
         * optional things specific to demo app
         */

        // ground plane stays below socket as it is updated
        DemoActions.AddRepositionGroundPlaneOnSocketEdit();


        /*
         * import sample mesh
         */
        bool do_scan_demo = true;

        // load sample mesh
        string assetPath   = Application.dataPath;
        string samplesPath = Path.Combine(assetPath, "..", "sample_files");
        //string sampleFile = Path.Combine(samplesPath, "sample_socket_off.obj");
        string sampleFile = Path.Combine(samplesPath, "sample_socket_1.obj");
        if (do_scan_demo)
        {
            sampleFile = Path.Combine(samplesPath, "scan_1_remesh.obj");
        }
        if (File.Exists(sampleFile) == false)
        {
            sampleFile = Path.Combine(samplesPath, "sample_socket_1.obj");
        }
        DMesh3 mesh = StandardMeshReader.ReadMesh(sampleFile);
        // read sample file from Resources instead
        //MemoryStream sampleFileStream = FResources.LoadBinary("sample_socket_1");
        //DMesh3 mesh = StandardMeshReader.ReadMesh(sampleFileStream, "obj");
        if (mesh.HasVertexColors == false)
        {
            mesh.EnableVertexColors(Colorf.Silver);
        }

        // transform to our coordinate system
        double scale = Units.MetersTo(Units.Linear.Millimeters); // this mesh is in meters, so scale to mm
        MeshTransforms.FlipLeftRightCoordSystems(mesh);          // convert to unity coordinate system
        MeshTransforms.Scale(mesh, scale);

        if (do_scan_demo)
        {
            OGActions.SetSizeMode(OGActions.SizeModes.RealSize);
        }
        else
        {
            OGActions.SetSizeMode(OGActions.SizeModes.DemoSize);
        }

        // initialize the datamodel
        OGActions.BeginSocketDesignFromScan(Context, mesh);

        // set up my UI tests/etc
        configure_unity_ui();

        // [RMS] do this next frame because SteamVR needs a chance to set up and position the cockpit
        OGActions.RecenterVRView(true);

        add_vr_head(context);

        // dgraph tests
        //DGTest.test(Debug.Log);
    }
Beispiel #24
0
 Vector3d get_tri_normal(DMesh3 mesh, Index3i tri)
 {
     return(MathUtil.Normal(mesh.GetVertex(tri.a), mesh.GetVertex(tri.b), mesh.GetVertex(tri.c)));
 }
Beispiel #25
0
        /// <summary>
        /// Converts g3.DMesh3 to UnityEngine.Mesh.
        /// The DMesh3 must be compact. If neccesary - run Compactify first.
        /// </summary>
        /// <param name="mesh">Dmesh3</param>
        /// <param name="project"> Should the mesh be projected into virgis projection DEFAULT true</param>
        /// <returns>UnityEngine.Mesh</returns>
        public static Mesh ToMesh(this DMesh3 mesh, Boolean project = true)
        {
            Mesh unityMesh = new Mesh();

            unityMesh.MarkDynamic();
            unityMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
            if (project && !mesh.Transform(AppState.instance.mapProj))
            {
                throw new Exception("Mesh Projection Failed");
            }
            Vector3[]     vertices = new Vector3[mesh.VertexCount];
            Color[]       colors   = new Color[mesh.VertexCount];
            Vector2[]     uvs      = new Vector2[mesh.VertexCount];
            Vector3[]     normals  = new Vector3[mesh.VertexCount];
            NewVertexInfo data;

            for (int i = 0; i < mesh.VertexCount; i++)
            {
                if (mesh.IsVertex(i))
                {
                    data        = mesh.GetVertexAll(i);
                    vertices[i] = (Vector3)data.v;
                    if (data.bHaveC)
                    {
                        colors[i] = (Color)data.c;
                    }
                    if (data.bHaveUV)
                    {
                        uvs[i] = (Vector2)data.uv;
                    }
                    if (data.bHaveN)
                    {
                        normals[i] = (Vector3)data.n;
                    }
                }
            }
            unityMesh.vertices = vertices;
            if (mesh.HasVertexColors)
            {
                unityMesh.SetColors(colors);
            }
            if (mesh.HasVertexUVs)
            {
                unityMesh.SetUVs(0, uvs);
            }
            if (mesh.HasVertexNormals)
            {
                unityMesh.SetNormals(normals);
            }
            int[] triangles = new int[mesh.TriangleCount * 3];
            int   j         = 0;

            foreach (Index3i tri in mesh.Triangles())
            {
                triangles[j * 3]     = tri.a;
                triangles[j * 3 + 1] = tri.b;
                triangles[j * 3 + 2] = tri.c;
                j++;
            }
            unityMesh.triangles = triangles;
            return(unityMesh);
        }
Beispiel #26
0
 double get_tri_area(DMesh3 mesh, ref Index3i tri)
 {
     return(MathUtil.Area(mesh.GetVertex(tri.a), mesh.GetVertex(tri.b), mesh.GetVertex(tri.c)));
 }
Beispiel #27
0
        void process()
        {
            DMesh3 useSourceMesh = SourceMesh;

            // try to do simple mesh repairs
            if (useSourceMesh.CachedIsClosed == false)
            {
                useSourceMesh = new DMesh3(SourceMesh);

                // [TODO] should remove duplicate triangles here?
                RemoveDuplicateTriangles dupes = new RemoveDuplicateTriangles(useSourceMesh);
                dupes.Apply();

                // close cracks
                MergeCoincidentEdges merge = new MergeCoincidentEdges(useSourceMesh);
                //merge.OnlyUniquePairs = true;
                merge.Apply();
            }

            //Util.WriteDebugMesh(useSourceMesh, "c:\\scratch\\__FIRST_MERGE.obj");


            DMesh3[] components = MeshConnectedComponents.Separate(useSourceMesh);

            List <DMesh3> solidComps = new List <DMesh3>();

            foreach (DMesh3 mesh in components)
            {
                // [TODO] check if this is a mesh w/ cracks, in which case we
                // can do other processing?

                bool closed = mesh.CachedIsClosed;
                if (closed == false)
                {
                    OpenMeshes.Add(mesh);
                    continue;
                }

                solidComps.Add(mesh);
            }


            if (solidComps.Count == 0)
            {
                return;
            }
            if (solidComps.Count == 1)
            {
                ClosedSolids = new List <DMesh3>()
                {
                    solidComps[0]
                };
            }


            if (HasNoVoids)
            {
                // each solid is a separate solid
                ClosedSolids = process_solids_novoid(solidComps);
            }
            else
            {
                ClosedSolids = process_solids(solidComps);
            }
        }
Beispiel #28
0
 double get_tri_aspect(DMesh3 mesh, ref Index3i tri)
 {
     return(MathUtil.AspectRatio(mesh.GetVertex(tri.a), mesh.GetVertex(tri.b), mesh.GetVertex(tri.c)));
 }
Beispiel #29
0
 public static void TagAsFailureMesh(DMesh3 mesh)
 {
     mesh.AttachMetadata("DMESHOP_FAILURE_MESH", new object());
 }
Beispiel #30
0
        /// <summary>
        /// Find regions of the input meshes that are horizontal, returns binned by Z-value.
        /// Currently only finds upward-facing regions.
        /// </summary>
        protected Dictionary <double, List <PlanarRegion> > FindPlanarZRegions(double minDimension, double dotNormalTol = 0.999)
        {
            Dictionary <double, List <PlanarRegion> > Regions = new Dictionary <double, List <PlanarRegion> >();
            SpinLock region_lock = new SpinLock();

            gParallel.ForEach(Meshes, (sliceMesh) =>
            {
                if (sliceMesh.options.IsCavity == false)
                {
                    return;
                }
                DMesh3 mesh = sliceMesh.mesh;

                HashSet <int> planar_tris = new HashSet <int>();
                foreach (int tid in mesh.TriangleIndices())
                {
                    Vector3d n = mesh.GetTriNormal(tid);
                    double dot = n.Dot(Vector3d.AxisZ);
                    if (dot > dotNormalTol)
                    {
                        planar_tris.Add(tid);
                    }
                }

                MeshConnectedComponents regions = new MeshConnectedComponents(mesh);
                regions.FilterF = planar_tris.Contains;
                regions.FindConnectedT();
                foreach (var c in regions)
                {
                    AxisAlignedBox3d bounds = MeshMeasurements.BoundsT(mesh, c.Indices);
                    if (bounds.Width > minDimension && bounds.Height > minDimension)
                    {
                        double z = Math.Round(bounds.Center.z, PrecisionDigits);

                        PlanarRegion planar = new PlanarRegion()
                        {
                            Mesh = mesh, Z = z, Triangles = c.Indices
                        };

                        bool taken = false;
                        region_lock.Enter(ref taken);
                        List <PlanarRegion> zregions;
                        if (Regions.TryGetValue(z, out zregions))
                        {
                            zregions.Add(planar);
                        }
                        else
                        {
                            zregions = new List <PlanarRegion>()
                            {
                                planar
                            };
                            Regions[z] = zregions;
                        }
                        region_lock.Exit();
                    }
                }
            });

            return(Regions);
        }