예제 #1
0
        void update_curvature(int vid)
        {
            double angle_sum = 0;

            exterior_angle_sums.TryGetValue(vid, out angle_sum);
            foreach (int tid in fillmesh.VtxTrianglesItr(vid))
            {
                Index3i et  = fillmesh.GetTriangle(tid);
                int     idx = IndexUtil.find_tri_index(vid, ref et);
                angle_sum += fillmesh.GetTriInternalAngleR(tid, idx);
            }
            curvatures[vid] = angle_sum - MathUtil.TwoPI;
        }
예제 #2
0
        // TODO:
        //  - (in merge coincident) don't merge tris with same/opposite normals (option)
        //  - after orienting components, try to find adjacent open components and
        //    transfer orientation between them
        //  - orient via nesting


        public void OrientComponents()
        {
            Components = new List <Component>();

            HashSet <int> remaining = new HashSet <int>(Mesh.TriangleIndices());
            List <int>    stack     = new List <int>();

            while (remaining.Count > 0)
            {
                Component c = new Component();
                c.triangles = new List <int>();

                stack.Clear();
                int start = remaining.First();
                remaining.Remove(start);
                c.triangles.Add(start);
                stack.Add(start);
                while (stack.Count > 0)
                {
                    int cur = stack[stack.Count - 1];
                    stack.RemoveAt(stack.Count - 1);
                    Index3i tcur = Mesh.GetTriangle(cur);

                    Index3i nbrs = Mesh.GetTriNeighbourTris(cur);
                    for (int j = 0; j < 3; ++j)
                    {
                        int nbr = nbrs[j];
                        if (remaining.Contains(nbr) == false)
                        {
                            continue;
                        }

                        int a = tcur[j];
                        int b = tcur[(j + 1) % 3];

                        Index3i tnbr = Mesh.GetTriangle(nbr);
                        if (IndexUtil.find_tri_ordered_edge(b, a, ref tnbr) == DMesh3.InvalidID)
                        {
                            Mesh.ReverseTriOrientation(nbr);
                        }
                        stack.Add(nbr);
                        remaining.Remove(nbr);
                        c.triangles.Add(nbr);
                    }
                }

                Components.Add(c);
            }
        }
예제 #3
0
        protected override void update_vertices(FScene s)
        {
            if (Target.Timestamp == target_timestamp)
            {
                return;
            }

            target_timestamp = Target.Timestamp;

            DMesh3 Mesh = Target.Mesh;

            for (int i = 0; i < VertexCount; ++i)
            {
                SurfaceVertexRef r    = SurfacePoints[i];
                Vector3d         vSum = Vector3d.Zero;
                Frame3f          f    = Mesh.GetTriFrame(r.tid);
                Index3i          tv   = Mesh.GetTriangle(r.tid);
                for (int j = 0; j < 3; ++j)
                {
                    f.Origin = (Vector3f)Mesh.GetVertex(tv[j]);
                    Vector3d v = f.FromFrameP(r.offsets[j]);
                    vSum += v;
                }
                vSum   /= 3;
                this[i] = SceneTransforms.ObjectToSceneP(Target, vSum);
            }
        }
예제 #4
0
        public override void AppendVertex(Vector3d v)
        {
            base.AppendVertex(v);

            // map v to mesh
            v = SceneTransforms.SceneToObjectP(Target, v);

            // TODO encode vertices by normals ??
            DMesh3           Mesh    = Target.Mesh;
            DMeshAABBTree3   Spatial = Target.Spatial;
            SurfaceVertexRef r       = new SurfaceVertexRef();

            r.tid = Spatial.FindNearestTriangle(v);
            Frame3f f  = Mesh.GetTriFrame(r.tid);
            Index3i tv = Mesh.GetTriangle(r.tid);

            for (int j = 0; j < 3; ++j)
            {
                f.Origin = (Vector3f)Mesh.GetVertex(tv[j]);
                Vector3d dv = f.ToFrameP(v);
                r.offsets[j] = dv;
            }
            SurfacePoints.Add(r);
            if (Curve.VertexCount != SurfacePoints.Count)
            {
                throw new Exception("SurfaceCurvePreview: counts are out of sync!!");
            }
        }
예제 #5
0
        public static Mesh ToMesh(this DMesh3 mesh)
        {
            var outMesh = new Mesh();

            int[] mapV         = new int[mesh.MaxVertexID];
            int   nAccumCountV = 0;

            foreach (int vi in mesh.VertexIndices())
            {
                mapV[vi] = nAccumCountV++;
                Vector3d v = mesh.GetVertex(vi);
                outMesh.Vertices.Add(new Vector3(v[0], v[1], v[2]));
            }

            foreach (int ti in mesh.TriangleIndices())
            {
                Index3i t = mesh.GetTriangle(ti);
                t[0] = mapV[t[0]];
                t[1] = mapV[t[1]];
                t[2] = mapV[t[2]];
                outMesh.Faces.Add(t[0], t[1], t[2], outMesh.Vertices);
            }

            return(outMesh);
        }
예제 #6
0
        public static void test_mesh_builders()
        {
            // test mesh builder
            DMesh3 origMesh = TestUtil.LoadTestMesh(Program.TEST_FILES_PATH + "bunny_open_base.obj");

            float[]         Vf = new float[origMesh.VertexCount * 3];
            List <Vector3f> Vl = new List <Vector3f>();
            int             k  = 0;

            foreach (Vector3d v in origMesh.Vertices())
            {
                Vf[k++] = (float)v.x; Vf[k++] = (float)v.y; Vf[k++] = (float)v.z;
                Vl.Add((Vector3f)v);
            }
            double[]   Nd = origMesh.NormalsBuffer.GetBufferCast <double>();
            Vector3d[] Nl = new Vector3d[origMesh.VertexCount];
            foreach (int vid in origMesh.VertexIndices())
            {
                Nl[vid] = origMesh.GetVertexNormal(vid);
            }

            int[]     Ti = origMesh.TrianglesBuffer.GetBuffer();
            Index3i[] Tl = new Index3i[origMesh.TriangleCount];
            foreach (int tid in origMesh.TriangleIndices())
            {
                Tl[tid] = origMesh.GetTriangle(tid);
            }

            DMesh3 m1 = DMesh3Builder.Build(Vf, Ti, Nd);
            DMesh3 m2 = DMesh3Builder.Build(Vl, Tl, Nl);

            Util.gDevAssert(origMesh.IsSameMesh(m1, true));
            Util.gDevAssert(origMesh.IsSameMesh(m2, true));
        }
예제 #7
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            DMesh3_goo goo = null;

            DA.GetData(0, ref goo);

            DMesh3 mesh = new DMesh3(goo.Value);

            List <Point3d>  vertices = new List <Point3d>();
            List <MeshFace> faces    = new List <MeshFace>();
            List <Color>    cols     = new List <Color>();

            List <int> v_i = new List <int>();
            List <int> f_i = new List <int>();

            foreach (var ind in mesh.VertexIndices())
            {
                v_i.Add(ind);
                vertices.Add(mesh.GetVertex(ind).ToRhinoPt());
                var col = mesh.GetVertexColor(ind);
                cols.Add(Color.FromArgb((int)(col.x * 255), (int)(col.y * 255), (int)(col.z * 255)));
            }
            foreach (var ind in mesh.TriangleIndices())
            {
                f_i.Add(ind);
                var tri = mesh.GetTriangle(ind);
                faces.Add(new MeshFace(tri.a, tri.b, tri.c));
            }

            DA.SetDataList(0, v_i);
            DA.SetDataList(1, vertices);
            DA.SetDataList(2, f_i);
            DA.SetDataList(3, faces);
            DA.SetDataList(4, cols);
        }
예제 #8
0
        // [RMS] this only tests some basic cases...
        public static void test_Laplacian_deformer()
        {
            // compact version
            DMesh3 mesh = new DMesh3(TestUtil.MakeRemeshedCappedCylinder(1.0), true);

            Debug.Assert(mesh.IsCompact);

            AxisAlignedBox3d bounds = mesh.GetBounds();

            TestUtil.WriteTestOutputMesh(mesh, "laplacian_deformer_before.obj");

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

            LaplacianMeshDeformer deformer = new LaplacianMeshDeformer(mesh);


            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 consPin    = 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));
            }

            foreach (int vid in mesh.VertexIndices())
            {
                Vector3d v      = mesh.GetVertex(vid);
                bool     bottom = (v.y - bounds.Min.y) < 0.01f;
                if (constraints.Contains(vid))
                {
                    deformer.SetConstraint(vid, v + Vector3f.AxisY, consPin, false);
                }
                if (bottom)
                {
                    deformer.SetConstraint(vid, v, consBottom, false);
                }
            }

            deformer.SolveAndUpdateMesh();

            result_meshes.Add(mesh);
            TestUtil.WriteTestOutputMeshes(result_meshes, "laplacian_deformer_after.obj");
        }
예제 #9
0
        public void Precompute_NearestTriangleNormals()
        {
            int N = DisplaceMesh.MaxTriangleID;

            TriVtxNormalDisplacements = new TriVtxNormalsDisplace[N];

            update_vertex_frames();

            //foreach ( int vid in DisplaceMesh.VertexIndices() ) {
            gParallel.ForEach <int>(DisplaceMesh.VertexIndices(), (vid) => {
                Vector3f pos = (Vector3f)DisplaceMesh.GetVertex(vid);
                int tid      = BaseSpatial.FindNearestTriangle(pos);
                Index3i tri  = BaseMesh.GetTriangle(tid);

                Vector3f dv0 = VtxFrames[tri.a].ToFrameP(pos);
                Vector3f dv1 = VtxFrames[tri.b].ToFrameP(pos);
                Vector3f dv2 = VtxFrames[tri.c].ToFrameP(pos);

                TriVtxNormalDisplacements[vid] = new TriVtxNormalsDisplace()
                {
                    tID = tid, dv0 = dv0, dv1 = dv1, dv2 = dv2
                };
            });
        }
예제 #10
0
        public static void test_local_param()
        {
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("plane_250v.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("hemisphere_nicemesh_3k.obj");
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_open_base.obj");

            mesh.EnableVertexUVs(Vector2f.Zero);

            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh);

            spatial.Build();

            //int tid = spatial.FindNearestTriangle(Vector3d.Zero);
            //Frame3f seedF = new Frame3f(Vector3d.Zero, Vector3d.AxisY);
            int     tid   = 3137;
            Frame3f seedF = mesh.GetTriFrame(tid);

            Index3i seedNbrs = mesh.GetTriangle(tid);

            MeshLocalParam param = new MeshLocalParam(mesh.MaxVertexID,
                                                      mesh.GetVertexf, mesh.GetVertexNormal, mesh.VtxVerticesItr);

            param.ComputeToMaxDistance(seedF, seedNbrs, float.MaxValue);

            float fR = param.MaxUVDistance;

            param.TransformUV(0.5f / fR, 0.5f * Vector2f.One);

            param.ApplyUVs((vid, uv) => { mesh.SetVertexUV(vid, uv); });

            TestUtil.SetColorsFromScalarF(mesh, (vid) => { return(param.GetUV(vid).Distance(0.5f * Vector2f.One)); }, new Vector2f(0, 0.5f));

            OBJWriter        writer = new OBJWriter();
            var              s      = new System.IO.StreamWriter(Program.TEST_OUTPUT_PATH + "mesh_local_param.obj", false);
            List <WriteMesh> wm     = new List <WriteMesh>()
            {
                new WriteMesh(mesh)
            };
            WriteOptions opt = new WriteOptions()
            {
                bCombineMeshes  = false, bWriteGroups = false, bPerVertexColors = true, bPerVertexUVs = true,
                AsciiHeaderFunc = () => { return("mttllib checkerboard.mtl\r\nusemtl checkerboard\r\n"); }
            };

            writer.Write(s, wm, opt);
            s.Close();
        }
예제 #11
0
        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            DMesh3           mesh   = new DMesh3(MakeRemeshedCappedCylinder(1.0), true);
            AxisAlignedBox3d bounds = mesh.GetBounds();

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

            LaplacianMeshDeformer deformer = new LaplacianMeshDeformer(mesh);

            // constrain bottom points
            foreach (int vid in mesh.VertexIndices())
            {
                g3.Vector3d v      = mesh.GetVertex(vid);
                bool        bottom = (v.y - bounds.Min.y) < 0.01f;
                if (bottom)
                {
                    deformer.SetConstraint(vid, v, 10);
                }
            }

            // constrain one other vtx
            int ti    = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new g3.Vector3d(2, 5, 2));
            int v_pin = mesh.GetTriangle(ti).a;

            g3.Vector3d cons_pos = mesh.GetVertex(v_pin);
            cons_pos += new g3.Vector3d(0.5, 0.5, 0.5);
            deformer.SetConstraint(v_pin, cons_pos, 10);


            deformer.Initialize();
            g3.Vector3d[] resultV = new g3.Vector3d[mesh.MaxVertexID];
            deformer.Solve(resultV);

            foreach (int vid in mesh.VertexIndices())
            {
                mesh.SetVertex(vid, resultV[vid]);
            }


            var rhinoMesh = GopherUtil.ConvertToRhinoMesh(mesh);

            doc.Objects.AddMesh(rhinoMesh);

            return(Result.Success);
        }
예제 #12
0
        // [RMS] this only tests some basic cases...
        public static void test_LaplacianDeformation()
        {
            // compact version
            DMesh3 mesh = new DMesh3(TestUtil.MakeRemeshedCappedCylinder(1.0), true);

            Debug.Assert(mesh.IsCompact);
            AxisAlignedBox3d bounds = mesh.GetBounds();

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

            LaplacianMeshDeformer deformer = new LaplacianMeshDeformer(mesh);

            // constrain bottom points
            foreach (int vid in mesh.VertexIndices())
            {
                Vector3d v      = mesh.GetVertex(vid);
                bool     bottom = (v.y - bounds.Min.y) < 0.01f;
                if (bottom)
                {
                    deformer.SetConstraint(vid, v, 10);
                }
            }

            // constrain one other vtx
            int      ti       = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new Vector3d(2, 5, 2));
            int      v_pin    = mesh.GetTriangle(ti).a;
            Vector3d cons_pos = mesh.GetVertex(v_pin);

            cons_pos += new Vector3d(0.5, 0.5, 0.5);
            deformer.SetConstraint(v_pin, cons_pos, 10);
            result_meshes.Add(TestUtil.MakeMarker(mesh.GetVertex(v_pin), 0.2f, Colorf.Red));

            deformer.Initialize();
            Vector3d[] resultV = new Vector3d[mesh.MaxVertexID];
            deformer.Solve(resultV);

            foreach (int vid in mesh.VertexIndices())
            {
                mesh.SetVertex(vid, resultV[vid]);
            }

            result_meshes.Add(mesh);
            TestUtil.WriteDebugMeshes(result_meshes, "___LAPLACIAN_result.obj");
        }
예제 #13
0
        private bool IsInRange(DMesh3 mesh, int triIndexOriginal, int triIndex, double rangeSquared)
        {
            var triOriginal = mesh.GetTriCentroid(triIndexOriginal);
            var tri         = mesh.GetTriangle(triIndex);
            var v1          = mesh.GetVertex(tri.a);
            var v2          = mesh.GetVertex(tri.b);
            var v3          = mesh.GetVertex(tri.c);

            if (v1.DistanceSquared(triOriginal) < rangeSquared)
            {
                return(true);
            }
            if (v2.DistanceSquared(triOriginal) < rangeSquared)
            {
                return(true);
            }
            if (v3.DistanceSquared(triOriginal) < rangeSquared)
            {
                return(true);
            }
            return(false);
        }
예제 #14
0
        IntrRay3Triangle3 find_added_hit(ref Ray3d ray, out int hit_tid)
        {
            hit_tid = DMesh3.InvalidID;
            IntrRay3Triangle3 nearest = null;
            double            dNearT  = double.MaxValue;

            Triangle3d tri = new Triangle3d();

            foreach (int tid in AddedT)
            {
                Index3i tv = EditMesh.GetTriangle(tid);
                tri.V0 = EditMesh.GetVertex(tv.a);
                tri.V1 = EditMesh.GetVertex(tv.b);
                tri.V2 = EditMesh.GetVertex(tv.c);
                IntrRay3Triangle3 intr = new IntrRay3Triangle3(ray, tri);
                if (intr.Find() && intr.RayParameter < dNearT)
                {
                    dNearT  = intr.RayParameter;
                    hit_tid = tid;
                    nearest = intr;
                }
            }
            return(nearest);
        }
예제 #15
0
    int[] insert_points(Vector3d[] points, DMesh3 mesh)
    {
        int[]         MapV = new int[points.Length];
        HashSet <int> newV = new HashSet <int>();

        for (int i = 0; i < points.Length; ++i)
        {
            MapV[i] = DMesh3.InvalidID;

            Vector3d pt = points[i];
            pt.Normalize();
            Ray3d ray = new Ray3d(Vector3d.Zero, pt);

            int hit_tid =
                MeshQueries.FindHitTriangle_LinearSearch(mesh, ray);
            if (hit_tid == DMesh3.InvalidID)
            {
                continue;
            }
            Index3i hit_tri = mesh.GetTriangle(hit_tid);

            IntrRay3Triangle3 intr =
                MeshQueries.TriangleIntersection(mesh, hit_tid, ray);
            Vector3d bary = intr.TriangleBaryCoords;
            bool     done = false;
            for (int j = 0; j < 3 && done == false; ++j)
            {
                if (bary[j] > 0.9)
                {
                    // hit-vertex case
                    if (newV.Contains(hit_tri[j]) == false)
                    {
                        MapV[i] = hit_tri[j];
                        newV.Add(MapV[i]);
                        done = true;
                    }
                }
                else if (bary[j] < 0.1)
                {
                    // hit-edge case
                    DMesh3.EdgeSplitInfo split_info;
                    MeshResult           splitResult = mesh.SplitEdge(hit_tri[(j + 1) % 3], hit_tri[(j + 2) % 3], out split_info);
                    if (splitResult == MeshResult.Ok)
                    {
                        MapV[i] = split_info.vNew;
                        newV.Add(MapV[i]);
                        mesh.SetVertex(split_info.vNew, points[i]);
                        done = true;
                    }
                }
            }
            if (done)
            {
                continue;
            }

            DMesh3.PokeTriangleInfo poke_info;
            MeshResult result = mesh.PokeTriangle(hit_tid, out poke_info);
            if (result == MeshResult.Ok)
            {
                MapV[i] = poke_info.new_vid;
                newV.Add(MapV[i]);
                mesh.SetVertex(poke_info.new_vid, points[i]);
            }
        }

        return(MapV);
    }
        // [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");
        }
예제 #17
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));
        }
예제 #18
0
        public static UnityMesh ToUnityMesh(this DMesh3 dMesh,
                                            bool bNorm = true,
                                            bool bUV   = false,
                                            bool bCol  = false)
        {
            bNorm &= dMesh.HasVertexNormals;
            bUV   &= dMesh.HasVertexUVs;
            bCol  &= dMesh.HasVertexColors;

            int[] vertexMap   = new int[dMesh.VerticesBuffer.Length];
            int[] triangleMap = new int[dMesh.TrianglesBuffer.Length];
            int[] triangles   = new int[dMesh.TriangleCount * 3];

            List <Vector3d> vertices       = new List <Vector3d>();
            List <Vector3f> normals        = new List <Vector3f>();
            List <Vector2f> uv             = new List <Vector2f>();
            List <Colorf>   colors         = new List <Colorf>();
            List <int>      vertexUseCount = new List <int>();

            NewVertexInfo vInfo = new NewVertexInfo(new Vector3d(),
                                                    new Vector3f(),
                                                    new Vector3f(),
                                                    new Vector2f());

            IEnumerator e  = dMesh.TrianglesRefCounts.GetEnumerator();
            int         ti = 0;

            while (e.MoveNext())
            {
                int     iRef     = (int)e.Current;
                Index3i triangle = dMesh.GetTriangle(iRef);
                triangleMap[iRef] = ti;

                for (int i = 0; i < 3; i++)
                {
                    int vertIndex = triangle[i];
                    if (vertexMap[vertIndex] == 0)
                    {
                        vertexUseCount.Add(1);
                        dMesh.GetVertex(vertIndex, ref vInfo, bNorm, bCol, bUV);
                        vertices.Add(new Vector3f((float)vInfo.v.x,
                                                  (float)vInfo.v.y,
                                                  (float)vInfo.v.z));
                        vertexMap[vertIndex] = vertices.Count - 1;

                        if (bNorm)
                        {
                            normals.Add(vInfo.n);
                        }
                        if (bUV)
                        {
                            uv.Add(vInfo.uv);
                        }
                        if (bCol)
                        {
                            colors.Add(new Colorf(vInfo.c.x, vInfo.c.y, vInfo.c.z));
                        }
                    }
                    else
                    {
                        vertexUseCount[vertexMap[vertIndex]]++;
                    }

                    triangles[ti * 3 + i] = vertexMap[vertIndex];
                }
                ti++;
            }

            UnityMesh uMesh = new UnityMesh(vertexUseCount.ToArray(),
                                            triangles,
                                            vertices,
                                            normals,
                                            uv,
                                            colors);

            // Triangle normals and neighbors.
            e = dMesh.TrianglesRefCounts.GetEnumerator();
            while (e.MoveNext())
            {
                int   iRef      = (int)e.Current;
                int[] nb        = dMesh.GetTriNeighbourTris(iRef).array;
                int[] neighbors = new int[3];

                for (int i = 0; i < 3; i++)
                {
                    neighbors[i] = (nb[i] != -1) ? triangleMap[nb[i]] : -1;
                }
                uMesh.AddTriangleInfo(triangleMap[iRef],
                                      (Vector3f)dMesh.GetTriNormal(iRef),
                                      neighbors);
            }

            return(uMesh);
        }
예제 #19
0
        public virtual bool Apply()
        {
            DMesh3 testAgainstMesh = Mesh;

            if (InsideMode == CalculationMode.RayParity)
            {
                MeshBoundaryLoops loops = new MeshBoundaryLoops(testAgainstMesh);
                if (loops.Count > 0)
                {
                    testAgainstMesh = new DMesh3(Mesh);
                    foreach (var loop in loops)
                    {
                        if (Cancelled())
                        {
                            return(false);
                        }
                        SimpleHoleFiller filler = new SimpleHoleFiller(testAgainstMesh, loop);
                        filler.Fill();
                    }
                }
            }

            DMeshAABBTree3 spatial = (Spatial != null && testAgainstMesh == Mesh) ?
                                     Spatial : new DMeshAABBTree3(testAgainstMesh, true);

            if (InsideMode == CalculationMode.AnalyticWindingNumber)
            {
                spatial.WindingNumber(Vector3d.Zero);
            }
            else if (InsideMode == CalculationMode.FastWindingNumber)
            {
                spatial.FastWindingNumber(Vector3d.Zero);
            }

            if (Cancelled())
            {
                return(false);
            }

            // ray directions
            List <Vector3d> ray_dirs = null; int NR = 0;

            if (InsideMode == CalculationMode.SimpleOcclusionTest)
            {
                ray_dirs = new List <Vector3d>();
                ray_dirs.Add(Vector3d.AxisX); ray_dirs.Add(-Vector3d.AxisX);
                ray_dirs.Add(Vector3d.AxisY); ray_dirs.Add(-Vector3d.AxisY);
                ray_dirs.Add(Vector3d.AxisZ); ray_dirs.Add(-Vector3d.AxisZ);
                NR = ray_dirs.Count;
            }

            Func <Vector3d, bool> isOccludedF = (pt) => {
                if (InsideMode == CalculationMode.RayParity)
                {
                    return(spatial.IsInside(pt));
                }
                else if (InsideMode == CalculationMode.AnalyticWindingNumber)
                {
                    return(spatial.WindingNumber(pt) > WindingIsoValue);
                }
                else if (InsideMode == CalculationMode.FastWindingNumber)
                {
                    return(spatial.FastWindingNumber(pt) > WindingIsoValue);
                }
                else
                {
                    for (int k = 0; k < NR; ++k)
                    {
                        int hit_tid = spatial.FindNearestHitTriangle(new Ray3d(pt, ray_dirs[k]));
                        if (hit_tid == DMesh3.InvalidID)
                        {
                            return(false);
                        }
                    }
                    return(true);
                }
            };

            bool cancel = false;

            BitArray vertices = null;

            if (PerVertex)
            {
                vertices = new BitArray(Mesh.MaxVertexID);

                MeshNormals normals = null;
                if (Mesh.HasVertexNormals == false)
                {
                    normals = new MeshNormals(Mesh);
                    normals.Compute();
                }

                gParallel.ForEach(Mesh.VertexIndices(), (vid) => {
                    if (cancel)
                    {
                        return;
                    }
                    if (vid % 10 == 0)
                    {
                        cancel = Cancelled();
                    }

                    Vector3d c    = Mesh.GetVertex(vid);
                    Vector3d n    = (normals == null) ? Mesh.GetVertexNormal(vid) : normals[vid];
                    c            += n * NormalOffset;
                    vertices[vid] = isOccludedF(c);
                });
            }
            if (Cancelled())
            {
                return(false);
            }

            RemovedT = new List <int>();
            SpinLock removeLock = new SpinLock();

            gParallel.ForEach(Mesh.TriangleIndices(), (tid) => {
                if (cancel)
                {
                    return;
                }
                if (tid % 10 == 0)
                {
                    cancel = Cancelled();
                }

                bool inside = false;
                if (PerVertex)
                {
                    Index3i tri = Mesh.GetTriangle(tid);
                    inside      = vertices[tri.a] || vertices[tri.b] || vertices[tri.c];
                }
                else
                {
                    Vector3d c = Mesh.GetTriCentroid(tid);
                    Vector3d n = Mesh.GetTriNormal(tid);
                    c         += n * NormalOffset;
                    inside     = isOccludedF(c);
                }

                if (inside)
                {
                    bool taken = false;
                    removeLock.Enter(ref taken);
                    RemovedT.Add(tid);
                    removeLock.Exit();
                }
            });

            if (Cancelled())
            {
                return(false);
            }

            if (RemovedT.Count > 0)
            {
                MeshEditor editor = new MeshEditor(Mesh);
                bool       bOK    = editor.RemoveTriangles(RemovedT, true);
                RemoveFailed = (bOK == false);
            }

            return(true);
        }
예제 #20
0
        public bool Insert()
        {
            Func <int, bool> is_contained_v = (vid) => {
                Vector3d v   = Mesh.GetVertex(vid);
                Vector2f vf2 = ProjectFrame.ToPlaneUV((Vector3f)v, 2);
                return(Polygon.Contains(vf2));
            };

            MeshVertexSelection vertexROI = new MeshVertexSelection(Mesh);
            Index3i             seedT     = Mesh.GetTriangle(SeedTriangle);

            // if a seed vert of seed triangle is containd in polygon, we will
            // flood-fill out from there, this gives a better ROI.
            // If not, we will try flood-fill from the seed triangles.
            List <int> seed_verts = new List <int>();

            for (int j = 0; j < 3; ++j)
            {
                if (is_contained_v(seedT[j]))
                {
                    seed_verts.Add(seedT[j]);
                }
            }
            if (seed_verts.Count == 0)
            {
                seed_verts.Add(seedT.a);
                seed_verts.Add(seedT.b);
                seed_verts.Add(seedT.c);
            }

            // flood-fill out from seed vertices until we have found all vertices
            // contained in polygon
            vertexROI.FloodFill(seed_verts.ToArray(), is_contained_v);

            // convert vertex ROI to face ROI
            MeshFaceSelection faceROI = new MeshFaceSelection(Mesh, vertexROI, 1);

            faceROI.ExpandToOneRingNeighbours();
            faceROI.FillEars(true);    // this might be a good idea...

            // construct submesh
            RegionOperator regionOp   = new RegionOperator(Mesh, faceROI);
            DSubmesh3      roiSubmesh = regionOp.Region;
            DMesh3         roiMesh    = roiSubmesh.SubMesh;

            // save 3D positions of unmodified mesh
            Vector3d[] initialPositions = new Vector3d[roiMesh.MaxVertexID];

            // map roi mesh to plane
            MeshTransforms.PerVertexTransform(roiMesh, roiMesh.VertexIndices(), (v, vid) => {
                Vector2f uv           = ProjectFrame.ToPlaneUV((Vector3f)v, 2);
                initialPositions[vid] = v;
                return(new Vector3d(uv.x, uv.y, 0));
            });

            // save a copy of 2D mesh and construct bvtree. we will use
            // this later to project back to 3d
            // [TODO] can we use a better spatial DS here, that takes advantage of 2D?
            DMesh3         projectMesh = new DMesh3(roiMesh);
            DMeshAABBTree3 projecter   = new DMeshAABBTree3(projectMesh, true);

            MeshInsertUVPolyCurve insertUV = new MeshInsertUVPolyCurve(roiMesh, Polygon);
            //insertUV.Validate()
            bool bOK = insertUV.Apply();

            if (!bOK)
            {
                throw new Exception("insertUV.Apply() failed");
            }

            if (SimplifyInsertion)
            {
                insertUV.Simplify();
            }

            int[] insertedPolyVerts = insertUV.CurveVertices;

            // grab inserted loop, assuming it worked
            EdgeLoop insertedLoop = null;

            if (insertUV.Loops.Count == 1)
            {
                insertedLoop = insertUV.Loops[0];
            }

            // find interior triangles
            List <int> interiorT = new List <int>();

            foreach (int tid in roiMesh.TriangleIndices())
            {
                Vector3d centroid = roiMesh.GetTriCentroid(tid);
                if (Polygon.Contains(centroid.xy))
                {
                    interiorT.Add(tid);
                }
            }
            if (RemovePolygonInterior)
            {
                MeshEditor editor = new MeshEditor(roiMesh);
                editor.RemoveTriangles(interiorT, true);
                InteriorTriangles = null;
            }
            else
            {
                InteriorTriangles = interiorT.ToArray();
            }


            // map back to 3d
            Vector3d a = Vector3d.Zero, b = Vector3d.Zero, c = Vector3d.Zero;

            foreach (int vid in roiMesh.VertexIndices())
            {
                // [TODO] somehow re-use exact positions from regionOp maps?

                // construct new 3D pos w/ barycentric interpolation
                Vector3d v   = roiMesh.GetVertex(vid);
                int      tid = projecter.FindNearestTriangle(v);
                Index3i  tri = projectMesh.GetTriangle(tid);
                projectMesh.GetTriVertices(tid, ref a, ref b, ref c);
                Vector3d bary = MathUtil.BarycentricCoords(ref v, ref a, ref b, ref c);
                Vector3d pos  = bary.x * initialPositions[tri.a] + bary.y * initialPositions[tri.b] + bary.z * initialPositions[tri.c];

                roiMesh.SetVertex(vid, pos);
            }

            bOK = BackPropagate(regionOp, insertedPolyVerts, insertedLoop);

            return(bOK);
        }
예제 #21
0
    public override void Selected(SelectionType button)
    {
        nullifyHitPos = true;
        transform.parent.SendMessage("Selected", button, SendMessageOptions.DontRequireReceiver);
        if (button == SelectionType.SELECTALL)
        {
            BlockMove = true;
        }
        else
        {
            MeshFilter mf   = GetComponent <MeshFilter>();
            Mesh       mesh = mf.sharedMesh;
            currentHit = transform.InverseTransformPoint(AppState.instance.lastHitPosition);
            Vector3d      target = currentHit;
            System.Random rand   = new System.Random();
            int           count  = 0;
            //
            // The algorithm will find local optima - repeat until you get the tru optima
            // but limit the interation using a count
            //
            Int32 current = 0;
            while (count < dmesh.VertexCount)
            {
                count++;
                //
                // choose a random starting point
                //
                current = rand.Next(0, dmesh.VertexCount);
                Vector3d vtx         = dmesh.GetVertex(current);
                double   currentDist = vtx.DistanceSquared(target);
                //
                // find the ring of triangles around the current point
                //
                int iter = 0;
                while (true)
                {
                    iter++;
                    //    throw new InvalidOperationException("Meh One Ring operation invalid : " + res.ToString());
                    //
                    // Interate through the vertices in the one Ring and find the clost to the target point
                    //
                    bool flag = false;
                    foreach (Int32 v in dmesh.VtxVerticesItr(current))
                    {
                        Vector3d thisVtx  = dmesh.GetVertex(v);
                        double   thisDist = thisVtx.DistanceSquared(target);
                        if (thisDist < currentDist)
                        {
                            flag        = true;
                            current     = v;
                            vtx         = thisVtx;
                            currentDist = thisDist;
                        }
                    }
                    //
                    // if the current point as closest - then  have a local optima
                    //
                    if (!flag)
                    {
                        break;
                    }
                }
                //
                // we now have a local optima
                // to check for a global optima look to see if hit is contained by one of the triangles in the one ring
                //
                bool f2 = false;
                foreach (Int32 t in dmesh.VtxTrianglesItr(current))
                {
                    Index3i    tri      = dmesh.GetTriangle(t);
                    Triangle3d triangle = new Triangle3d(
                        dmesh.GetVertex(tri.a),
                        dmesh.GetVertex(tri.b),
                        dmesh.GetVertex(tri.c)
                        );
                    double[] xs = new double[3] {
                        triangle.V0.x, triangle.V1.x, triangle.V2.x
                    };
                    double[] ys = new double[3] {
                        triangle.V0.y, triangle.V1.y, triangle.V2.y
                    };
                    double[] zs = new double[3] {
                        triangle.V0.z, triangle.V1.z, triangle.V2.z
                    };

                    if (
                        target.x >= xs.Min() &&
                        target.x <= xs.Max() &&
                        target.y >= ys.Min() &&
                        target.y <= ys.Max() &&
                        target.z >= zs.Min() &&
                        target.z <= zs.Max()
                        )
                    {
                        f2            = true;
                        currentHitTri = tri;
                    }
                }
                //
                // if we found on triamgle that contain the current hit then we have finished
                //
                if (f2)
                {
                    break;
                }
            }
            if (count >= dmesh.VertexCount)
            {
                //
                // This is the unoptimized verion but it is guaranteed to find a solution if one exits
                //

                current = -1;
                float currentDist = float.MaxValue;
                if (currentHit != null)
                {
                    for (int i = 0; i < mesh.vertices.Length; i++)
                    {
                        Vector3 vtx  = mesh.vertices[i];
                        float   dist = (currentHit - vtx).sqrMagnitude;
                        if (dist < currentDist)
                        {
                            current     = i;
                            currentDist = dist;
                        }
                    }
                }
                //
                // Check that the closet vertex to the point is an actual solution
                //
                bool f2 = false;
                foreach (Int32 t in dmesh.VtxTrianglesItr(current))
                {
                    Index3i    tri      = dmesh.GetTriangle(t);
                    Triangle3d triangle = new Triangle3d(
                        dmesh.GetVertex(tri.a),
                        dmesh.GetVertex(tri.b),
                        dmesh.GetVertex(tri.c)
                        );
                    double[] xs = new double[3] {
                        triangle.V0.x, triangle.V1.x, triangle.V2.x
                    };
                    double[] ys = new double[3] {
                        triangle.V0.y, triangle.V1.y, triangle.V2.y
                    };
                    double[] zs = new double[3] {
                        triangle.V0.z, triangle.V1.z, triangle.V2.z
                    };

                    if (
                        target.x >= xs.Min() &&
                        target.x <= xs.Max() &&
                        target.y >= ys.Min() &&
                        target.y <= ys.Max() &&
                        target.z >= zs.Min() &&
                        target.z <= zs.Max()
                        )
                    {
                        f2            = true;
                        currentHitTri = tri;
                    }
                }
                //
                // if we found on triamgle that contain the current hit then we have finished
                //
                if (!f2)
                {
                    Debug.LogError(" Mesh Vertex Search : No Solution Found");
                    return;
                }
            }
            selectedVertex              = current;
            sphere                      = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            sphere.transform.position   = transform.TransformPoint(mesh.vertices[current]);
            sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            sphere.transform.parent     = transform;
        }
    }
예제 #22
0
 public MeshData(DMesh3 _mesh) : this()
 {
     _mesh     = new DMesh3(_mesh, true);
     vertices  = _mesh.VertexIndices().Select(vID => { var vertex = _mesh.GetVertexf(vID); return(new Vector3(vertex.x, vertex.y, vertex.z)); }).ToArray();
     triangles = _mesh.TriangleIndices().SelectMany(tID => _mesh.GetTriangle(tID).array).ToArray();
 }
예제 #23
0
        // [RMS] This doesn't work because I did something stupid when
        //   making unwrap meshes. The set of triangles aren't the same. argh.
        public static DMesh3 ConvertUnwrapToUVs(RemoteControl rc, out DenseMeshUVSet UVSet, string mainName = "main")
        {
            int mainID = rc.FindObjectByName(mainName);

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

            Debug.Assert(mainMesh.IsCompact);

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

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


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

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


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

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

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

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

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

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

                UVSet.TriangleUVs[ti] = sub_tri;
            }

            return(mainMesh);
        }