예제 #1
0
 public void MakeMesh(DMesh3 m)
 {
     int nV = vertices.Count;
     for (int i = 0; i < nV; ++i) {
         NewVertexInfo ni = new NewVertexInfo() { v = vertices[i] };
         if ( WantNormals ) {
             ni.bHaveN = true;
             ni.n = normals[i];
         }
         if ( WantUVs ) {
             ni.bHaveUV = true;
             ni.uv = uv[i];
         }
         int vID = m.AppendVertex(ni);
         Util.gDevAssert(vID == i);
     }
     int nT = triangles.Count;
     if (WantGroups && groups != null && groups.Length == nT) {
         for (int i = 0; i < nT; ++i)
             m.AppendTriangle(triangles[i], groups[i]);
     } else {
         for (int i = 0; i < nT; ++i)
             m.AppendTriangle(triangles[i]);
     }
 }
        public void Generate()
        {
            append_mesh();

            AxisAlignedBox3i bounds = Voxels.GridBounds;

            bounds.Max -= Vector3i.One;

            int[] vertices = new int[4];

            foreach (Vector3i nz in Voxels.NonZeros())
            {
                check_counts_or_append(6, 2);

                Box3d cube = Box3d.UnitZeroCentered;
                cube.Center = (Vector3d)nz;

                for (int fi = 0; fi < 6; ++fi)
                {
                    // checks dependent on neighbours
                    Index3i nbr = nz + gIndices.GridOffsets6[fi];
                    if (bounds.Contains(nbr))
                    {
                        if (SkipInteriorFaces && Voxels.Get(nbr))
                        {
                            continue;
                        }
                    }
                    else if (CapAtBoundary == false)
                    {
                        continue;
                    }


                    int           ni = gIndices.BoxFaceNormals[fi];
                    Vector3f      n  = (Vector3f)(Math.Sign(ni) * cube.Axis(Math.Abs(ni) - 1));
                    NewVertexInfo vi = new NewVertexInfo(Vector3d.Zero, n);
                    if (ColorSourceF != null)
                    {
                        vi.c      = ColorSourceF(nz);
                        vi.bHaveC = true;
                    }
                    for (int j = 0; j < 4; ++j)
                    {
                        vi.v        = cube.Corner(gIndices.BoxFaces[fi, j]);
                        vertices[j] = cur_mesh.AppendVertex(vi);
                    }

                    Index3i t0 = new Index3i(vertices[0], vertices[1], vertices[2], Clockwise);
                    Index3i t1 = new Index3i(vertices[0], vertices[2], vertices[3], Clockwise);
                    cur_mesh.AppendTriangle(t0);
                    cur_mesh.AppendTriangle(t1);
                }
            }
        }
예제 #3
0
        public virtual void MakeMesh(DMesh3 m)
        {
            int  nV           = vertices.Count;
            bool bWantNormals = WantNormals && normals != null && normals.Count == vertices.Count;

            if (bWantNormals)
            {
                m.EnableVertexNormals(Vector3f.AxisY);
            }

            bool bWantUVs = WantUVs && uv != null && uv.Count == vertices.Count;

            if (bWantUVs)
            {
                m.EnableVertexUVs(Vector2f.Zero);
            }

            for (int i = 0; i < nV; ++i)
            {
                var ni = new NewVertexInfo()
                {
                    v = vertices[i]
                };
                if (bWantNormals)
                {
                    ni.bHaveN = true;
                    ni.n      = normals[i];
                }
                if (bWantUVs)
                {
                    ni.bHaveUV = true;
                    ni.uv      = uv[i];
                }
                int vID = m.AppendVertex(ni);
                Util.gDevAssert(vID == i);
            }
            int nT = triangles.Count;

            if (WantGroups && groups != null && groups.Length == nT)
            {
                m.EnableTriangleGroups();
                for (int i = 0; i < nT; ++i)
                {
                    m.AppendTriangle(triangles[i], groups[i]);
                }
            }
            else
            {
                for (int i = 0; i < nT; ++i)
                {
                    m.AppendTriangle(triangles[i]);
                }
            }
        }
예제 #4
0
        public static g3.DMesh3 ConvertToD3Mesh(Rhino.Geometry.Mesh mesh)
        {
            g3.DMesh3 ret = new g3.DMesh3(true, false, false, false);

            if (mesh.Normals.Count < mesh.Vertices.Count)
            {
                mesh.Normals.ComputeNormals();
            }

            if (mesh.Normals.Count != mesh.Vertices.Count)
            {
                return(ret);
            }

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                var vertex = new g3.NewVertexInfo();
                vertex.n = new g3.Vector3f(mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z);
                vertex.v = new g3.Vector3d(mesh.Vertices[i].X, mesh.Vertices[i].Y, mesh.Vertices[i].Z);
                ret.AppendVertex(vertex);
            }


            foreach (var mf in mesh.Faces)
            {
                if (mf.IsQuad)
                {
                    double dist1 = mesh.Vertices[mf.A].DistanceTo(mesh.Vertices[mf.C]);
                    double dist2 = mesh.Vertices[mf.B].DistanceTo(mesh.Vertices[mf.D]);
                    if (dist1 > dist2)
                    {
                        ret.AppendTriangle(mf.A, mf.B, mf.D);
                        ret.AppendTriangle(mf.B, mf.C, mf.D);
                    }
                    else
                    {
                        ret.AppendTriangle(mf.A, mf.B, mf.C);
                        ret.AppendTriangle(mf.A, mf.C, mf.D);
                    }
                }
                else
                {
                    ret.AppendTriangle(mf.A, mf.B, mf.C);
                }
            }

            return(ret);
        }
예제 #5
0
        // [RMS] estimate can be zero
        void compute(IEnumerable <int> triangles, int tri_count_est)
        {
            int est_verts = tri_count_est / 2;

            SubMesh = new DMesh3(BaseMesh.Components & WantComponents);

            BaseSubmeshV = new IndexFlagSet(BaseMesh.MaxVertexID, est_verts);
            BaseToSubV   = new IndexMap(BaseMesh.MaxVertexID, est_verts);
            SubToBaseV   = new DVector <int>();

            if (ComputeTriMaps)
            {
                BaseToSubT = new IndexMap(BaseMesh.MaxTriangleID, tri_count_est);
                SubToBaseT = new DVector <int>();
            }

            foreach (int tid in triangles)
            {
                if (!BaseMesh.IsTriangle(tid))
                {
                    throw new Exception("DSubmesh3.compute: triangle " + tid + " does not exist in BaseMesh!");
                }

                Index3i base_t = BaseMesh.GetTriangle(tid);
                Index3i new_t  = Index3i.Zero;
                int     gid    = BaseMesh.GetTriangleGroup(tid);

                for (int j = 0; j < 3; ++j)
                {
                    int base_v = base_t[j];
                    int sub_v  = -1;
                    if (BaseSubmeshV[base_v] == false)
                    {
                        sub_v = SubMesh.AppendVertex(BaseMesh, base_v);
                        BaseSubmeshV[base_v] = true;
                        BaseToSubV[base_v]   = sub_v;
                        SubToBaseV.insert(base_v, sub_v);
                    }
                    else
                    {
                        sub_v = BaseToSubV[base_v];
                    }

                    new_t[j] = sub_v;
                }

                if (OverrideGroupID >= 0)
                {
                    gid = OverrideGroupID;
                }

                int sub_tid = SubMesh.AppendTriangle(new_t, gid);

                if (ComputeTriMaps)
                {
                    BaseToSubT[tid] = sub_tid;
                    SubToBaseT.insert(tid, sub_tid);
                }
            }
        }
        public virtual bool Fill(int group_id = -1)
        {
            if (Loop.Vertices.Length < 3)
            {
                return(false);
            }

            // this just needs one triangle
            if (Loop.Vertices.Length == 3)
            {
                Index3i tri     = new Index3i(Loop.Vertices[0], Loop.Vertices[2], Loop.Vertices[1]);
                int     new_tid = Mesh.AppendTriangle(tri, group_id);
                if (new_tid < 0)
                {
                    return(false);
                }
                NewTriangles = new int[1] {
                    new_tid
                };
                NewVertex = DMesh3.InvalidID;
                return(true);
            }

            // [TODO] 4-case? could check nbr normals to figure out best internal edge...


            // compute centroid
            Vector3d c = Vector3d.Zero;

            for (int i = 0; i < Loop.Vertices.Length; ++i)
            {
                c += Mesh.GetVertex(Loop.Vertices[i]);
            }
            c *= 1.0 / Loop.Vertices.Length;

            // add centroid vtx
            NewVertex = Mesh.AppendVertex(c);

            // stitch triangles
            MeshEditor editor = new MeshEditor(Mesh);

            try {
                NewTriangles = editor.AddTriangleFan_OrderedVertexLoop(NewVertex, Loop.Vertices, group_id);
            } catch {
                NewTriangles = null;
            }

            // if fill failed, back out vertex-add
            if (NewTriangles == null)
            {
                Mesh.RemoveVertex(NewVertex, true, false);
                NewVertex = DMesh3.InvalidID;
                return(false);
            }
            else
            {
                return(true);
            }
        }
예제 #7
0
        //
        // DMesh3 construction utilities
        //

        /// <summary>
        /// ultimate generic mesh-builder, pass it arrays of floats/doubles, or lists
        /// of Vector3d, or anything in-between. Will figure out how to interpret
        ///
        /// This static function attempts to retain a manifold mesh, if you need finer
        /// control use the concrete class.
        ///
        /// Number of issues encountered adding verices or triangls are stored in the
        /// mesh metadata. Metadata can be cleared once the returning object is evaluated.
        /// </summary>
        public static DMesh3 Build <VType, TType, NType>(IEnumerable <VType> Vertices,
                                                         IEnumerable <TType> Triangles,
                                                         IEnumerable <NType> Normals = null,
                                                         IEnumerable <int> TriGroups = null)
        {
            DMesh3 mesh = new DMesh3(Normals != null, false, false, TriGroups != null);

            // build outcomes are stored in the metadata to avoid changes to the function signature
            //
            int iAppendTriangleIssues = 0;

            Vector3d[] v = BufferUtil.ToVector3d(Vertices);
            for (int i = 0; i < v.Length; ++i)
            {
                mesh.AppendVertex(v[i]);
            }


            if (Normals != null)
            {
                Vector3f[] n = BufferUtil.ToVector3f(Normals);
                if (n.Length != v.Length)
                {
                    throw new Exception("DMesh3Builder.Build: incorrect number of normals provided");
                }
                for (int i = 0; i < n.Length; ++i)
                {
                    mesh.SetVertexNormal(i, n[i]);
                }
            }

            Index3i[] t = BufferUtil.ToIndex3i(Triangles);
            for (int i = 0; i < t.Length; ++i)
            {
                var last = mesh.AppendTriangle(t[i]);
                if (last == DMesh3.InvalidID || last == DMesh3.NonManifoldID)
                {
                    iAppendTriangleIssues++;
                }
            }

            if (TriGroups != null)
            {
                List <int> groups = new List <int>(TriGroups);
                if (groups.Count != t.Length)
                {
                    throw new Exception("DMesh3Builder.Build: incorect number of triangle groups");
                }
                for (int i = 0; i < t.Length; ++i)
                {
                    mesh.SetTriangleGroup(i, groups[i]);
                }
            }
            mesh.AttachMetadata("AppendTriangleIssues", iAppendTriangleIssues);

            return(mesh);
        }
예제 #8
0
        public virtual int[] AddTriangleFan_OrderedVertexLoop(int center, int[] vertex_loop, int group_id = -1)
        {
            int N = vertex_loop.Length;

            int[] new_tris = new int[N];

            int i = 0;

            for (i = 0; i < N; ++i)
            {
                int a = vertex_loop[i];
                int b = vertex_loop[(i + 1) % N];

                Index3i newT    = new Index3i(center, b, a);
                int     new_tid = Mesh.AppendTriangle(newT, group_id);
                if (new_tid == DMesh3.InvalidID)
                {
                    goto operation_failed;
                }

                new_tris[i] = new_tid;
            }

            return(new_tris);


operation_failed:
            // remove what we added so far
            if (i > 0)
            {
                if (remove_triangles(new_tris, i) == false)
                {
                    throw new Exception("MeshConstructor.AddTriangleFan_OrderedVertexLoop: failed to add fan, and also falied to back out changes.");
                }
            }
            return(null);
        }
예제 #9
0
        //
        // DMesh3 construction utilities
        //

        /// <summary>
        /// ultimate generic mesh-builder, pass it arrays of floats/doubles, or lists
        /// of Vector3d, or anything in-between. Will figure out how to interpret
        /// </summary>
        public static DMesh3 Build <VType, TType, NType>(IEnumerable <VType> Vertices,
                                                         IEnumerable <TType> Triangles,
                                                         IEnumerable <NType> Normals = null,
                                                         IEnumerable <int> TriGroups = null)
        {
            var mesh = new DMesh3(Normals != null, false, false, TriGroups != null);

            Vector3d[] v = BufferUtil.ToVector3d(Vertices);
            for (int i = 0; i < v.Length; ++i)
            {
                mesh.AppendVertex(v[i]);
            }

            if (Normals != null)
            {
                Vector3f[] n = BufferUtil.ToVector3f(Normals);
                if (n.Length != v.Length)
                {
                    throw new Exception("DMesh3Builder.Build: incorrect number of normals provided");
                }

                for (int i = 0; i < n.Length; ++i)
                {
                    mesh.SetVertexNormal(i, n[i]);
                }
            }

            Index3i[] t = BufferUtil.ToIndex3i(Triangles);
            for (int i = 0; i < t.Length; ++i)
            {
                mesh.AppendTriangle(t[i]);
            }

            if (TriGroups != null)
            {
                var groups = new List <int>(TriGroups);
                if (groups.Count != t.Length)
                {
                    throw new Exception("DMesh3Builder.Build: incorect number of triangle groups");
                }

                for (int i = 0; i < t.Length; ++i)
                {
                    mesh.SetTriangleGroup(i, groups[i]);
                }
            }

            return(mesh);
        }
예제 #10
0
        /// <summary>
        /// add triangle to mesh, with locking if we are computing in parallel
        /// </summary>
        int append_triangle(int a, int b, int c)
        {
            bool lock_taken = false;

            if (bParallel)
            {
                mesh_lock.Enter(ref lock_taken);
            }

            int tid = Mesh.AppendTriangle(a, b, c);

            if (lock_taken)
            {
                mesh_lock.Exit();
            }

            return(tid);
        }
예제 #11
0
        void compute(IEnumerable <int> triangles, int tri_count)
        {
            int est_verts = tri_count / 2;

            SubMesh = new DMesh3(BaseMesh.Components & WantComponents);

            BaseSubmeshV = new IndexFlagSet(BaseMesh.MaxVertexID, est_verts);
            BaseToSubV   = new IndexMap(BaseMesh.MaxVertexID, est_verts);
            SubToBaseV   = new DVector <int>();

            foreach (int ti in triangles)
            {
                Index3i base_t = BaseMesh.GetTriangle(ti);
                Index3i new_t  = Index3i.Zero;
                int     gid    = BaseMesh.GetTriangleGroup(ti);

                for (int j = 0; j < 3; ++j)
                {
                    int base_v = base_t[j];
                    int sub_v  = -1;
                    if (BaseSubmeshV[base_v] == false)
                    {
                        sub_v = SubMesh.AppendVertex(BaseMesh, base_v);
                        BaseSubmeshV[base_v] = true;
                        BaseToSubV[base_v]   = sub_v;
                        SubToBaseV.insert(base_v, sub_v);
                    }
                    else
                    {
                        sub_v = BaseToSubV[base_v];
                    }
                    new_t[j] = sub_v;
                }

                SubMesh.AppendTriangle(new_t, gid);
            }
        }
예제 #12
0
        protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            bool bHavePreselectedObjects = false;

            const ObjectType geometryFilter = ObjectType.MeshFace;

            OptionDouble  minEdgeLengthOption     = new OptionDouble(minEdgeLength, 0.001, 200);
            OptionDouble  maxEdgeLengthOption     = new OptionDouble(maxEdgeLength, 0.001, 200);
            OptionDouble  constriantAngleOption   = new OptionDouble(constriantAngle, 0.001, 360);
            OptionInteger smoothStepsOptions      = new OptionInteger(smoothSteps, 0, 100);
            OptionDouble  smoothSpeedOption       = new OptionDouble(smoothSpeed, 0.01, 1.0);
            OptionDouble  projectAmountOption     = new OptionDouble(projectedAmount, 0.01, 1.0);
            OptionDouble  projectedDistanceOption = new OptionDouble(projectedDistance, 0.01, 100000.0);

            GetObject go = new GetObject();

            go.SetCommandPrompt("Select mesh faces to project onto another mesh");
            go.GeometryFilter = geometryFilter;

            go.AddOptionDouble("ConstraintAngle", ref constriantAngleOption);
            go.AddOptionDouble("MinEdge", ref minEdgeLengthOption);
            go.AddOptionDouble("MaxEdge", ref maxEdgeLengthOption);
            go.AddOptionInteger("SmoothSteps", ref smoothStepsOptions);
            go.AddOptionDouble("SmoothSpeed", ref smoothSpeedOption);

            go.GroupSelect     = true;
            go.SubObjectSelect = true;

            for (; ;)
            {
                GetResult faceres = go.GetMultiple(1, 0);

                if (faceres == GetResult.Option)
                {
                    go.EnablePreSelect(false, true);
                    continue;
                }

                else if (go.CommandResult() != Result.Success)
                {
                    return(go.CommandResult());
                }

                if (go.ObjectsWerePreselected)
                {
                    bHavePreselectedObjects = true;
                    go.EnablePreSelect(false, true);
                    continue;
                }

                break;
            }

            minEdgeLength   = minEdgeLengthOption.CurrentValue;
            maxEdgeLength   = maxEdgeLengthOption.CurrentValue;
            constriantAngle = constriantAngleOption.CurrentValue;
            smoothSteps     = smoothStepsOptions.CurrentValue;
            smoothSpeed     = smoothSpeedOption.CurrentValue;

            //System.Collections.Generic.List<System.Guid> meshes = new System.Collections.Generic.List<System.Guid>();

            System.Guid rhinoMesh = System.Guid.Empty;

            System.Collections.Generic.List <int> removeFaces = new System.Collections.Generic.List <int>();

            g3.DMesh3 projectFaces = new g3.DMesh3(true, false, false, false);

            Rhino.Geometry.Mesh rhinoInputMesh = new Rhino.Geometry.Mesh();

            for (int i = 0; i < go.ObjectCount; i++)
            {
                ObjRef obj = go.Object(i);

                if (rhinoMesh == System.Guid.Empty)
                {
                    rhinoMesh      = obj.ObjectId;
                    rhinoInputMesh = obj.Mesh();

                    for (int j = 0; j < rhinoInputMesh.Vertices.Count; j++)
                    {
                        var vertex = new g3.NewVertexInfo();
                        vertex.n = new g3.Vector3f(rhinoInputMesh.Normals[j].X, rhinoInputMesh.Normals[j].Y, rhinoInputMesh.Normals[j].Z);
                        vertex.v = new g3.Vector3d(rhinoInputMesh.Vertices[j].X, rhinoInputMesh.Vertices[j].Y, rhinoInputMesh.Vertices[j].Z);
                        projectFaces.AppendVertex(vertex);
                    }
                }

                var m = rhinoInputMesh;

                if (rhinoMesh != obj.ObjectId)
                {
                    continue;
                }

                removeFaces.Add(obj.GeometryComponentIndex.Index);

                var mf = rhinoInputMesh.Faces[obj.GeometryComponentIndex.Index];


                if (mf.IsQuad)
                {
                    double dist1 = m.Vertices[mf.A].DistanceTo(m.Vertices[mf.C]);
                    double dist2 = m.Vertices[mf.B].DistanceTo(m.Vertices[mf.D]);
                    if (dist1 > dist2)
                    {
                        projectFaces.AppendTriangle(mf.A, mf.B, mf.D);
                        projectFaces.AppendTriangle(mf.B, mf.C, mf.D);
                    }
                    else
                    {
                        projectFaces.AppendTriangle(mf.A, mf.B, mf.C);
                        projectFaces.AppendTriangle(mf.A, mf.C, mf.D);
                    }
                }
                else
                {
                    projectFaces.AppendTriangle(mf.A, mf.B, mf.C);
                }
            }

            if (rhinoInputMesh == null)
            {
                return(Result.Failure);
            }

            removeFaces.Sort();
            removeFaces.Reverse();

            foreach (var removeFace in removeFaces)
            {
                rhinoInputMesh.Faces.RemoveAt(removeFace);
            }

            rhinoInputMesh.Compact();

            GetObject goProjected = new GetObject();

            goProjected.EnablePreSelect(false, true);
            goProjected.SetCommandPrompt("Select mesh to project to");
            goProjected.GeometryFilter = ObjectType.Mesh;
            goProjected.AddOptionDouble("ConstraintAngle", ref constriantAngleOption);
            goProjected.AddOptionDouble("MinEdge", ref minEdgeLengthOption);
            goProjected.AddOptionDouble("MaxEdge", ref maxEdgeLengthOption);
            goProjected.AddOptionInteger("SmoothSteps", ref smoothStepsOptions);
            goProjected.AddOptionDouble("SmoothSpeed", ref smoothSpeedOption);
            goProjected.AddOptionDouble("ProjectAmount", ref projectAmountOption);
            goProjected.AddOptionDouble("ProjectDistance", ref projectedDistanceOption);

            goProjected.GroupSelect     = true;
            goProjected.SubObjectSelect = false;
            goProjected.EnableClearObjectsOnEntry(false);
            goProjected.EnableUnselectObjectsOnExit(false);


            for (; ;)
            {
                GetResult resProject = goProjected.Get();

                if (resProject == GetResult.Option)
                {
                    continue;
                }
                else if (goProjected.CommandResult() != Result.Success)
                {
                    return(goProjected.CommandResult());
                }

                break;
            }


            minEdgeLength     = minEdgeLengthOption.CurrentValue;
            maxEdgeLength     = maxEdgeLengthOption.CurrentValue;
            constriantAngle   = constriantAngleOption.CurrentValue;
            smoothSteps       = smoothStepsOptions.CurrentValue;
            smoothSpeed       = smoothSpeedOption.CurrentValue;
            projectedAmount   = projectAmountOption.CurrentValue;
            projectedDistance = projectedDistanceOption.CurrentValue;

            if (bHavePreselectedObjects)
            {
                // Normally, pre-selected objects will remain selected, when a
                // command finishes, and post-selected objects will be unselected.
                // This this way of picking, it is possible to have a combination
                // of pre-selected and post-selected. So, to make sure everything
                // "looks the same", lets unselect everything before finishing
                // the command.
                for (int i = 0; i < go.ObjectCount; i++)
                {
                    RhinoObject rhinoObject = go.Object(i).Object();
                    if (null != rhinoObject)
                    {
                        rhinoObject.Select(false);
                    }
                }
                doc.Views.Redraw();
            }

            bool result = false;

            if (goProjected.ObjectCount < 1)
            {
                return(Result.Failure);
            }


            var rhinoMeshProject = goProjected.Object(0).Mesh();

            if (rhinoMeshProject == null || !rhinoMeshProject.IsValid)
            {
                return(Result.Failure);
            }

            var meshProjected = GopherUtil.ConvertToD3Mesh(rhinoMeshProject);

            var res = GopherUtil.RemeshMesh(projectFaces, (float)minEdgeLength, (float)maxEdgeLength, (float)constriantAngle, (float)smoothSpeed, smoothSteps, meshProjected, (float)projectedAmount, (float)projectedDistance);

            var newRhinoMesh = GopherUtil.ConvertToRhinoMesh(res);

            if (newRhinoMesh != null && newRhinoMesh.IsValid)
            {
                newRhinoMesh.Append(rhinoInputMesh);

                result |= doc.Objects.Replace(rhinoMesh, newRhinoMesh);
            }

            doc.Views.Redraw();

            return(Result.Success);
        }
예제 #13
0
        public virtual int[] AddTriangleStrip(IList <Frame3f> frames, IList <Interval1d> spans, int group_id = -1)
        {
            int N = frames.Count;

            if (N != spans.Count)
            {
                throw new Exception("MeshEditor.AddTriangleStrip: spans list is not the same size!");
            }
            int[] new_tris = new int[2 * (N - 1)];

            int prev_a = -1, prev_b = -1;
            int i = 0, ti = 0;

            for (i = 0; i < N; ++i)
            {
                Frame3f    f    = frames[i];
                Interval1d span = spans[i];

                Vector3d va = f.Origin + (float)span.a * f.Y;
                Vector3d vb = f.Origin + (float)span.b * f.Y;

                // [TODO] could compute normals here...

                int a = Mesh.AppendVertex(va);
                int b = Mesh.AppendVertex(vb);

                if (prev_a != -1)
                {
                    new_tris[ti++] = Mesh.AppendTriangle(prev_a, b, prev_b);
                    new_tris[ti++] = Mesh.AppendTriangle(prev_a, a, b);
                }
                prev_a = a; prev_b = b;
            }

            return(new_tris);
        }
예제 #14
0
        //public static void VoronoiMesh(List<g3.PolyLine3d> mesh, out List<g3.Line3d> listLines, out List<g3.PolyLine3d> listPolylines)
        //{
        //    System.Collections.Generic.SortedDictionary<int, MeshNode> faces = new System.Collections.Generic.SortedDictionary<int, MeshNode>();

        //    int index = 0;
        //    foreach (var meshFaceIndex in mesh.TriangleIndices())
        //    {
        //        var frame = mesh.GetTriFrame(meshFaceIndex);

        //        g3.Index3i neighbors = mesh.GetTriNeighbourTris(meshFaceIndex);
        //        g3.Index3i vertex_index = mesh.GetTriangle(meshFaceIndex);

        //        faces.Add(meshFaceIndex, new MeshNode(index++, meshFaceIndex, frame, neighbors, vertex_index));
        //    }


        //    foreach (var f in faces)
        //    {
        //        f.Value.neighbors.Clear();
        //        f.Value.neighbors.Capacity = 3;
        //        for (int i = 0; i < 3; ++i)
        //        {
        //            int fn = f.Value.neighbors_index[i];
        //            if (fn >= 0)
        //                f.Value.neighbors.Add(faces[fn]);
        //        }

        //        if (f.Value.neighbors.Count < 3)
        //        {
        //            f.Value.locked = true;

        //            foreach (var n in f.Value.neighbors)
        //                n.locked = true;
        //        }
        //    }

        //    outputMesh = new g3.DMesh3(g3.MeshComponents.None);
        //    listLines = new List<g3.Line3d>();
        //    listPolylines = new List<g3.PolyLine3d>();
        //    foreach (var f in faces)
        //    {
        //        outputMesh.AppendVertex(f.Value.frame.Origin);
        //    }

        //    HashSet<int> processedPoints = new HashSet<int>();

        //    foreach (var f in faces)
        //    {
        //        for (int i = 0; i < 3; i++)
        //        {
        //            List<int> outputLine = new List<int>();

        //            if (processedPoints.Contains(f.Value.vertex_index[i]))
        //                continue;

        //            int checkVertex = f.Value.vertex_index[i];

        //            MeshNode currentFaces = f.Value;
        //            MeshNode prevFace = null;

        //            bool fullLoop = false;

        //            while (true)
        //            {
        //                for (int j = 0; j < currentFaces.neighbors.Count; j++)
        //                {

        //                    var neighbor = currentFaces.neighbors[j];
        //                    if (neighbor.UsesVertex(checkVertex))
        //                    {

        //                        if (neighbor == prevFace)
        //                            continue;

        //                        if (neighbor == f.Value)
        //                        {
        //                            fullLoop = true;
        //                            break; // Found full loop
        //                        }

        //                        outputLine.Add(neighbor.index);

        //                        prevFace = currentFaces;
        //                        currentFaces = neighbor;
        //                        j = -1;
        //                    }
        //                }

        //                break;
        //            }

        //            if (fullLoop)
        //            {
        //                processedPoints.Add(checkVertex);

        //                var polyline = new g3.PolyLine3d();

        //                if (outputLine.Count > 2)
        //                {
        //                    g3.Vector3d centerPoint = f.Value.frame.Origin;

        //                    foreach (var p in outputLine)
        //                        centerPoint += outputMesh.GetVertex(p);

        //                    centerPoint /= (outputLine.Count + 1);

        //                    int center = outputMesh.AppendVertex(centerPoint);

        //                    var pS = outputMesh.GetVertex(f.Value.index);
        //                    var p0 = outputMesh.GetVertex(outputLine[0]);
        //                    var pE = outputMesh.GetVertex(outputLine[outputLine.Count - 1]);

        //                    var normal = mesh.GetTriNormal(f.Value.meshIndex);

        //                    polyline.AppendVertex(pS);
        //                    polyline.AppendVertex(p0);

        //                    listLines.Add(new g3.Line3d(pS, p0 - pS));

        //                    var n = MathUtil.Normal(centerPoint, pS, p0);

        //                    bool reverseTri = n.Dot(normal) < 0;

        //                    if (!reverseTri)
        //                        outputMesh.AppendTriangle(center, f.Value.index, outputLine[0]);
        //                    else
        //                        outputMesh.AppendTriangle(center, outputLine[0], f.Value.index);

        //                    for (int j = 0; j < outputLine.Count - 1; j++)
        //                    {
        //                        var p1 = outputMesh.GetVertex(outputLine[j]);
        //                        var p2 = outputMesh.GetVertex(outputLine[j + 1]);

        //                        listLines.Add(new g3.Line3d(p1, p2 - p1));
        //                        polyline.AppendVertex(p2);

        //                        if (!reverseTri)
        //                            outputMesh.AppendTriangle(center, outputLine[j], outputLine[j + 1]);
        //                        else
        //                            outputMesh.AppendTriangle(center, outputLine[j + 1], outputLine[j]);
        //                    }

        //                    polyline.AppendVertex(pS);
        //                    listLines.Add(new g3.Line3d(pE, pS - pE));

        //                    listPolylines.Add(polyline);

        //                    if (!reverseTri)
        //                        outputMesh.AppendTriangle(center, outputLine[outputLine.Count - 1], f.Value.index);
        //                    else
        //                        outputMesh.AppendTriangle(center, f.Value.index, outputLine[outputLine.Count - 1]);
        //                }
        //            }
        //        }

        //    }
        //}

        public static void VoronoiMesh(g3.DMesh3 mesh, out g3.DMesh3 outputMesh, out List <g3.Line3d> listLines, out List <g3.PolyLine3d> listPolylines)
        {
            System.Collections.Generic.SortedDictionary <int, MeshNode> faces = new System.Collections.Generic.SortedDictionary <int, MeshNode>();

            int index = 0;

            foreach (var meshFaceIndex in mesh.TriangleIndices())
            {
                var frame = mesh.GetTriFrame(meshFaceIndex);

                g3.Index3i neighbors    = mesh.GetTriNeighbourTris(meshFaceIndex);
                g3.Index3i vertex_index = mesh.GetTriangle(meshFaceIndex);

                faces.Add(meshFaceIndex, new MeshNode(index++, meshFaceIndex, frame, neighbors, vertex_index));
            }


            foreach (var f in faces)
            {
                f.Value.neighbors.Clear();
                f.Value.neighbors.Capacity = 3;
                for (int i = 0; i < 3; ++i)
                {
                    int fn = f.Value.neighbors_index[i];
                    if (fn >= 0)
                    {
                        f.Value.neighbors.Add(faces[fn]);
                    }
                }

                if (f.Value.neighbors.Count < 3)
                {
                    f.Value.locked = true;

                    foreach (var n in f.Value.neighbors)
                    {
                        n.locked = true;
                    }
                }
            }

            outputMesh    = new g3.DMesh3(g3.MeshComponents.None);
            listLines     = new List <g3.Line3d>();
            listPolylines = new List <g3.PolyLine3d>();
            foreach (var f in faces)
            {
                outputMesh.AppendVertex(f.Value.frame.Origin);
            }

            HashSet <int> processedPoints = new HashSet <int>();

            foreach (var f in faces)
            {
                for (int i = 0; i < 3; i++)
                {
                    List <int> outputLine = new List <int>();

                    if (processedPoints.Contains(f.Value.vertex_index[i]))
                    {
                        continue;
                    }

                    int checkVertex = f.Value.vertex_index[i];

                    MeshNode currentFaces = f.Value;
                    MeshNode prevFace     = null;

                    bool fullLoop = false;

                    while (true)
                    {
                        for (int j = 0; j < currentFaces.neighbors.Count; j++)
                        {
                            var neighbor = currentFaces.neighbors[j];
                            if (neighbor.UsesVertex(checkVertex))
                            {
                                if (neighbor == prevFace)
                                {
                                    continue;
                                }

                                if (neighbor == f.Value)
                                {
                                    fullLoop = true;
                                    break; // Found full loop
                                }

                                outputLine.Add(neighbor.index);

                                prevFace     = currentFaces;
                                currentFaces = neighbor;
                                j            = -1;
                            }
                        }

                        break;
                    }

                    if (fullLoop)
                    {
                        processedPoints.Add(checkVertex);

                        var polyline = new g3.PolyLine3d();

                        if (outputLine.Count > 2)
                        {
                            g3.Vector3d centerPoint = f.Value.frame.Origin;

                            foreach (var p in outputLine)
                            {
                                centerPoint += outputMesh.GetVertex(p);
                            }

                            centerPoint /= (outputLine.Count + 1);

                            int center = outputMesh.AppendVertex(centerPoint);

                            var pS = outputMesh.GetVertex(f.Value.index);
                            var p0 = outputMesh.GetVertex(outputLine[0]);
                            var pE = outputMesh.GetVertex(outputLine[outputLine.Count - 1]);

                            var normal = mesh.GetTriNormal(f.Value.meshIndex);

                            polyline.AppendVertex(pS);
                            polyline.AppendVertex(p0);

                            listLines.Add(new g3.Line3d(pS, p0 - pS));

                            var n = MathUtil.Normal(centerPoint, pS, p0);

                            bool reverseTri = n.Dot(normal) < 0;

                            if (!reverseTri)
                            {
                                outputMesh.AppendTriangle(center, f.Value.index, outputLine[0]);
                            }
                            else
                            {
                                outputMesh.AppendTriangle(center, outputLine[0], f.Value.index);
                            }

                            for (int j = 0; j < outputLine.Count - 1; j++)
                            {
                                var p1 = outputMesh.GetVertex(outputLine[j]);
                                var p2 = outputMesh.GetVertex(outputLine[j + 1]);

                                listLines.Add(new g3.Line3d(p1, p2 - p1));
                                polyline.AppendVertex(p2);

                                if (!reverseTri)
                                {
                                    outputMesh.AppendTriangle(center, outputLine[j], outputLine[j + 1]);
                                }
                                else
                                {
                                    outputMesh.AppendTriangle(center, outputLine[j + 1], outputLine[j]);
                                }
                            }

                            polyline.AppendVertex(pS);
                            listLines.Add(new g3.Line3d(pE, pS - pE));

                            listPolylines.Add(polyline);

                            if (!reverseTri)
                            {
                                outputMesh.AppendTriangle(center, outputLine[outputLine.Count - 1], f.Value.index);
                            }
                            else
                            {
                                outputMesh.AppendTriangle(center, f.Value.index, outputLine[outputLine.Count - 1]);
                            }
                        }
                    }
                }
            }
        }