Exemple #1
0
        /// <summary>
        /// Set the position of the object frame for this SO without moving the mesh in the scene.
        /// The input frame is the new object frame. So, this is a frame "in scene coordinates" unless
        /// this object has a parent SceneObject (ie is not a child of Scene directly). In that case
        /// the frame needs to be specified relative to that SO. An easy way to do this is to via
        ///   obj_pivot = GetLocalFrame(Object).FromFrame( SceneTransforms.SceneToObject(pivot_in_scene) )
        /// TODO: specify frame coordpace as input argument?
        /// </summary>
        public void RepositionPivot(Frame3f objFrame)
        {
            //if (Parent is FScene == false)
            //    throw new NotSupportedException("DMeshSO.RepositionMeshFrame: have not tested this!");

            Frame3f curFrame = this.GetLocalFrame(CoordSpace.ObjectCoords);
            bool    bNormals = mesh.HasVertexNormals;

            // map vertices to new frame
            foreach (int vid in mesh.VertexIndices())
            {
                Vector3f v = (Vector3f)mesh.GetVertex(vid);
                v = curFrame.FromFrameP(ref v);
                v = objFrame.ToFrameP(ref v);
                mesh.SetVertex(vid, v);

                if (bNormals)
                {
                    Vector3f n = mesh.GetVertexNormal(vid);
                    n = curFrame.FromFrameV(ref n);
                    n = objFrame.ToFrameV(ref n);
                    mesh.SetVertexNormal(vid, n);
                }
            }

            // set new object frame
            SetLocalFrame(objFrame, CoordSpace.ObjectCoords);

            fast_mesh_update(bNormals, false);
            post_mesh_modified();
        }
        public virtual void Update()
        {
            base.begin_update();

            if (MeshSource == null)
            {
                throw new Exception("MeshDeformationOp: must set valid MeshSource to compute!");
            }

            IMesh meshIn = MeshSource.GetIMesh();

            DMesh3 mesh = new DMesh3(meshIn, MeshHints.None);

            MeshNormals.QuickCompute(mesh);

            foreach (int vid in mesh.VertexIndices())
            {
                Vector3d v      = mesh.GetVertex(vid);
                Vector3f n      = mesh.GetVertexNormal(vid);
                Vector3d newPos = deformF(v, n, vid);
                mesh.SetVertex(vid, newPos);
            }

            MeshNormals.QuickCompute(mesh);

            DisplacedMesh = mesh;

            base.complete_update();
        }
        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));
        }
Exemple #4
0
        public void FastUpdateVertices(DMesh3 source, int[] source_vertices, bool bCopyNormals = false, bool bCopyColors = false)
        {
            int NV = source_vertices.Length;

            Vector3[] vertices = new Vector3[NV];
            for (int i = 0; i < NV; ++i)
            {
                vertices[i] = (Vector3)source.GetVertex(source_vertices[i]);
            }

            mesh.vertices = vertices;

            if (bCopyNormals && source.HasVertexNormals)
            {
                Vector3[] normals = new Vector3[NV];
                for (int i = 0; i < NV; ++i)
                {
                    normals[i] = (Vector3)source.GetVertexNormal(source_vertices[i]);
                }
                mesh.normals = normals;
            }

            if (bCopyColors && source.HasVertexColors)
            {
                Color[] colors = new Color[NV];
                for (int i = 0; i < NV; ++i)
                {
                    colors[i] = (Color)source.GetVertexColor(source_vertices[i]);
                }
                mesh.colors = colors;
            }
        }
Exemple #5
0
        public fMesh(int[] triangles, DMesh3 source, int[] source_vertices, bool bCopyNormals = false, bool bCopyColors = false, bool bCopyUVs = false)
        {
            int NV = source_vertices.Length;

            Vector3[] vertices = new Vector3[NV];
            for (int i = 0; i < NV; ++i)
            {
                vertices[i] = (Vector3)source.GetVertex(source_vertices[i]);
            }

            Mesh m = new Mesh();

            m.vertices = vertices;

            if (NV > 65000 || triangles.Length / 3 > 65000)
            {
                m.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
            }
            m.triangles = triangles;

            if (bCopyNormals && source.HasVertexNormals)
            {
                Vector3[] normals = new Vector3[NV];
                for (int i = 0; i < NV; ++i)
                {
                    normals[i] = (Vector3)source.GetVertexNormal(source_vertices[i]);
                }
                m.normals = normals;
            }
            else
            {
                m.RecalculateNormals();
            }

            if (bCopyColors && source.HasVertexColors)
            {
                Color[] colors = new Color[NV];
                for (int i = 0; i < NV; ++i)
                {
                    colors[i] = (Color)source.GetVertexColor(source_vertices[i]);
                }
                m.colors = colors;
            }

            if (bCopyUVs && source.HasVertexUVs)
            {
                Vector2[] uvs = new Vector2[NV];
                for (int i = 0; i < NV; ++i)
                {
                    uvs[i] = source.GetVertexUV(source_vertices[i]);
                }
                m.uv = uvs;
            }

            mesh = m;
        }
Exemple #6
0
        public IEnumerator RunMainThreadProcessing(bool bSpawnBackgroundWrite = true)
        {
            int N = ExportMeshSOs.Count;

            ExportMeshes = new DMesh3[N];
            MeshFrames   = new Frame3f[N];

            for (int k = 0; k < N; ++k)
            {
                DMeshSO so   = ExportMeshSOs[k];
                DMesh3  copy = new DMesh3(so.Mesh, false, MeshComponents.VertexColors | MeshComponents.VertexNormals);

                // if we have scaling or parent hierarchy, need to transform to scene in main
                // thread, because we have no way of storing transform stack currently
                if (so.GetLocalScale() != Vector3f.One || so.Parent != so.GetScene())
                {
                    foreach (int vid in copy.VertexIndices())
                    {
                        Vector3d v = copy.GetVertex(vid);
                        Vector3f n = copy.GetVertexNormal(vid);
                        Frame3f  f = new Frame3f(v, n);
                        f = SceneTransforms.ObjectToScene(so, f);
                        copy.SetVertex(vid, f.Origin);
                        copy.SetVertexNormal(vid, f.Z);
                    }
                    MeshFrames[k] = Frame3f.Identity;
                }
                else
                {
                    MeshFrames[k] = ExportMeshSOs[k].GetLocalFrame(CoordSpace.ObjectCoords);
                }

                ExportMeshes[k] = copy;

                yield return(null);
            }

            if (MainThreadWorkCompletedF != null)
            {
                MainThreadWorkCompletedF();
            }
            DebugUtil.Log("MeshExporter: completed main thread processing");

            if (bSpawnBackgroundWrite)
            {
                ThreadPool.QueueUserWorkItem((state) => {
                    var result = RunBackgroundWrite();
                    if (OnCompletedF != null)
                    {
                        OnCompletedF(result);
                    }
                });
            }
        }
        void compute_inner_wall()
        {
            if (DebugStep <= 0)
            {
                SocketMesh = new DMesh3(TrimmedMesh);
                return;
            }

            InnerMesh = new DMesh3(TrimmedMesh);

            // compute flare band
            Func <int, double> flareOffsetF = (vid) => { return(0); };

            if (flare_offset > 0 && flare_band_width > 0)
            {
                MeshBoundaryLoops loops = new MeshBoundaryLoops(InnerMesh);
                if (loops.Count != 1)
                {
                    goto done_inner_wall;
                }

                DijkstraGraphDistance dist = DijkstraGraphDistance.MeshVertices(InnerMesh);
                dist.TrackOrder = true;
                foreach (int vid in loops[0].Vertices)
                {
                    dist.AddSeed(vid, 0);
                }
                dist.ComputeToMaxDistance(1.25f * (float)flare_band_width);

                flareOffsetF = (viD) => {
                    float d = dist.GetDistance(viD);
                    if (d < flare_band_width)
                    {
                        double t = d / flare_band_width;
                        t = 1 - t * t;
                        t = t * t * t;
                        return(t * flare_offset);
                    }
                    return(0);
                };
            }


            gParallel.ForEach(InnerMesh.VertexIndices(), (vid) => {
                Vector3d v    = InnerMesh.GetVertex(vid);
                Vector3d n    = InnerMesh.GetVertexNormal(vid);
                double offset = inner_offset + flareOffsetF(vid);
                InnerMesh.SetVertex(vid, v + offset * n);
            });


done_inner_wall:
            MeshNormals.QuickCompute(InnerMesh);
        }
 virtual public void Apply()
 {
     TargetSO.EditAndUpdateMesh((mesh) => {
         DMesh3 fromMesh = PreviewSO.Mesh;
         foreach (int vid in mesh.VertexIndices())
         {
             mesh.SetVertex(vid, fromMesh.GetVertex(vid));
             mesh.SetVertexNormal(vid, fromMesh.GetVertexNormal(vid));
         }
     }, GeometryEditTypes.VertexDeformation);
 }
 public void SaveCurrentNormals()
 {
     if (ActiveChange.NewNormals != null)
     {
         foreach (var pair in ModifiedV)
         {
             Vector3f normal = Mesh.GetVertexNormal(pair.Key);
             ActiveChange.NewNormals[pair.Value] = normal;
         }
     }
 }
Exemple #10
0
        public static void AppendMeshSO(DMeshSO appendTo, DMeshSO append)
        {
            FScene scene = appendTo.GetScene();

            if (scene.IsSelected(appendTo))
            {
                scene.Deselect(appendTo);
            }
            if (scene.IsSelected(append))
            {
                scene.Deselect(append);
            }

            Frame3f  f1     = appendTo.GetLocalFrame(CoordSpace.ObjectCoords);
            Vector3f scale1 = appendTo.GetLocalScale();
            Frame3f  f2     = append.GetLocalFrame(CoordSpace.ObjectCoords);
            Vector3f scale2 = append.GetLocalScale();

            DMesh3 mesh1 = appendTo.Mesh;

            DMesh3 mesh2 = append.Mesh;

            foreach (int vid in mesh2.VertexIndices())
            {
                // convert point in mesh2 to scene coords
                Vector3f v2 = (Vector3f)mesh2.GetVertex(vid);
                v2 *= scale2;
                Vector3f v2s = f2.FromFrameP(v2);

                // transfer that scene coord into local coords of mesh1
                Vector3f v2in1 = f1.ToFrameP(v2s);
                v2in1 /= scale1;
                mesh2.SetVertex(vid, v2in1);

                if (mesh1.HasVertexNormals && mesh2.HasVertexNormals)
                {
                    Vector3f n   = mesh2.GetVertexNormal(vid);
                    Vector3f ns  = f2.FromFrameV(n);
                    Vector3f ns2 = f1.ToFrameV(ns);
                    mesh2.SetVertexNormal(vid, ns2);
                }
            }

            MeshEditor editor = new MeshEditor(mesh1);

            editor.AppendMesh(mesh2);

            appendTo.NotifyMeshEdited();

            // [TODO] change record!

            scene.RemoveSceneObject(append, false);
        }
Exemple #11
0
        public static void test_points()
        {
            string filename = "c:\\scratch\\bunny_solid.obj";
            DMesh3 mesh     = StandardMeshReader.ReadMesh(filename);

            PointSplatsGenerator pointgen = new PointSplatsGenerator()
            {
                PointIndices = IntSequence.Range(mesh.VertexCount),
                PointF       = mesh.GetVertex,
                NormalF      = (vid) => { return((Vector3d)mesh.GetVertexNormal(vid)); },
                Radius       = mesh.CachedBounds.DiagonalLength * 0.01
            };
            DMesh3 pointMesh = pointgen.Generate().MakeDMesh();

            StandardMeshWriter.WriteMesh("c:\\scratch\\POINTS.obj", pointMesh, WriteOptions.Defaults);
        }
Exemple #12
0
        public static void test_normals()
        {
            // check that frames are ok
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");

            foreach (int tid in mesh.TriangleIndices())
            {
                Vector3f n = (Vector3f)mesh.GetTriNormal(tid);
                for (int j = 0; j < 3; ++j)
                {
                    Frame3f f = mesh.GetTriFrame(tid, j);
                    if (Math.Abs(f.X.Dot(f.Y)) > MathUtil.ZeroTolerancef ||
                        Math.Abs(f.X.Dot(f.Z)) > MathUtil.ZeroTolerancef ||
                        Math.Abs(f.Y.Dot(f.Z)) > MathUtil.ZeroTolerancef)
                    {
                        throw new Exception("argh");
                    }
                    Vector3f fn = f.Z;
                    if (fn.Dot(n) < 0.99)
                    {
                        throw new Exception("shit");
                    }
                }
            }

            MeshNormals.QuickCompute(mesh);

            foreach (int vid in mesh.VertexIndices())
            {
                Vector3f n = mesh.GetVertexNormal(vid);
                for (int j = 1; j <= 2; ++j)
                {
                    Frame3f  f  = mesh.GetVertexFrame(vid, (j == 1) ? true : false);
                    Vector3f fn = f.GetAxis(j);
                    if (Math.Abs(f.X.Dot(f.Y)) > MathUtil.ZeroTolerancef ||
                        Math.Abs(f.X.Dot(f.Z)) > MathUtil.ZeroTolerancef ||
                        Math.Abs(f.Y.Dot(f.Z)) > MathUtil.ZeroTolerancef)
                    {
                        throw new Exception("argh");
                    }
                    if (fn.Dot(n) < 0.99)
                    {
                        throw new Exception("shit2");
                    }
                }
            }
        }
        protected override void Recompute(DGArguments args)
        {
            OffsetMesh.Copy(CachedValue <DMesh3>(0, args));
            double dist = CachedValue <double>(1, args);

            if (!OffsetMesh.HasVertexNormals)
            {
                MeshNormals.QuickCompute(OffsetMesh);
            }

            foreach (int vid in OffsetMesh.VertexIndices())
            {
                Vector3d v = OffsetMesh.GetVertex(vid);
                Vector3d n = OffsetMesh.GetVertexNormal(vid);
                v += dist * n;
                OffsetMesh.SetVertex(vid, v);
            }
        }
Exemple #14
0
        public bool Compute()
        {
            DMesh3 copy = new DMesh3(Mesh);

            //Frame3f PlaneO = SceneTransforms.SceneToObject(TargetSO, PlaneS);
            Vector3f PlaneNormal = Plane.GetAxis(nPlaneAxis);

            MeshPlaneCut cut = new MeshPlaneCut(copy, Plane.Origin, PlaneNormal);

            cut.Cut();

            Loops = new DCurve3[cut.CutLoops.Count];
            for (int li = 0; li < cut.CutLoops.Count; ++li)
            {
                EdgeLoop edgeloop = cut.CutLoops[li];
                DCurve3  loop     = MeshUtil.ExtractLoopV(copy, edgeloop.Vertices);

                // [TODO] collapse degenerate points...

                if (NormalOffset > 0)
                {
                    for (int i = 0; i < loop.VertexCount; ++i)
                    {
                        Vector3f n = Vector3f.Zero;
                        if (copy.HasVertexNormals)
                        {
                            n = (Vector3f)copy.GetVertexNormal(edgeloop.Vertices[i]);
                        }
                        else
                        {
                            n = (Vector3f)MeshNormals.QuickCompute(Mesh, edgeloop.Vertices[i]);
                        }

                        n -= n.Dot(PlaneNormal) * PlaneNormal;
                        n.Normalize();
                        loop[i] += NormalOffset * (Vector3d)n;
                    }
                }

                Loops[li] = loop;
            }

            return(Loops.Length > 0);
        }
Exemple #15
0
        public fMesh(int[] triangles, DMesh3 source, int[] source_vertices, bool bCopyNormals = false, bool bCopyColors = false)
        {
            int NV = source_vertices.Length;

            Vector3[] vertices = new Vector3[NV];
            for (int i = 0; i < NV; ++i)
            {
                vertices[i] = (Vector3)source.GetVertex(source_vertices[i]);
            }

            Mesh m = new Mesh();

            m.vertices  = vertices;
            m.triangles = triangles;

            if (bCopyNormals && source.HasVertexNormals)
            {
                Vector3[] normals = new Vector3[NV];
                for (int i = 0; i < NV; ++i)
                {
                    normals[i] = (Vector3)source.GetVertexNormal(source_vertices[i]);
                }
                m.normals = normals;
            }
            else
            {
                m.RecalculateNormals();
            }

            if (bCopyColors && source.HasVertexColors)
            {
                Color[] colors = new Color[NV];
                for (int i = 0; i < NV; ++i)
                {
                    colors[i] = (Color)source.GetVertexColor(source_vertices[i]);
                }
                m.colors = colors;
            }

            unitymesh = m;
        }
Exemple #16
0
        /// <summary>
        /// copy vertex positions from sourceMesh.
        /// [TODO] perhaps can refactor into a call to EditAndUpdateMesh() ?
        /// </summary>
        public void UpdateVertices(DMesh3 sourceMesh, bool bNormals = true, bool bColors = true)
        {
            if (sourceMesh.MaxVertexID != mesh.MaxVertexID)
            {
                throw new Exception("DMeshSO.UpdateVertexPositions: not enough positions provided!");
            }

            bNormals &= sourceMesh.HasVertexNormals;
            if (bNormals && mesh.HasVertexNormals == false)
            {
                mesh.EnableVertexNormals(Vector3f.AxisY);
            }
            bColors &= sourceMesh.HasVertexColors;
            if (bColors && mesh.HasVertexColors == false)
            {
                mesh.EnableVertexColors(Colorf.White);
            }

            lock (mesh_write_lock) {
                foreach (int vid in mesh.VertexIndices())
                {
                    Vector3d sourceV = sourceMesh.GetVertex(vid);
                    mesh.SetVertex(vid, sourceV);
                    if (bNormals)
                    {
                        Vector3f sourceN = sourceMesh.GetVertexNormal(vid);
                        mesh.SetVertexNormal(vid, sourceN);
                    }
                    if (bColors)
                    {
                        Vector3f sourceC = sourceMesh.GetVertexColor(vid);
                        mesh.SetVertexColor(vid, sourceC);
                    }
                }
            }

            fast_mesh_update(bNormals, bColors);
            post_mesh_modified();
        }
Exemple #17
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            DMesh3_goo goo = null;

            DA.GetData(0, ref goo);

            DMesh3 mesh = new DMesh3(goo.Value);

            List <Rhino.Geometry.Vector3d> vecs = new List <Rhino.Geometry.Vector3d>();

            if (!mesh.HasVertexNormals)
            {
                var normals = new MeshNormals(mesh);
                normals.Compute();
            }

            foreach (var ind in mesh.VertexIndices())
            {
                vecs.Add(mesh.GetVertexNormal(ind).ToRhinoVec());
            }

            DA.SetDataList(0, vecs);
        }
        public virtual void Update()
        {
            if (MeshSource == null)
            {
                throw new Exception("PlaneBandExpansionOp: must set valid MeshSource to compute!");
            }

            IMesh imesh = MeshSource.GetIMesh();

            if (imesh.HasVertexNormals == false)
            {
                throw new Exception("PlaneBandExpansionOp: input mesh does not have surface normals...");
            }
            if (imesh is DMesh3 == false)
            {
                throw new Exception("RegionOffsetOp: in current implementation, input mesh must be a DMesh3. Ugh.");
            }
            DMesh3 mesh = imesh as DMesh3;

            IList <int> faces = IndexSource.GetIndices();

            // [RMS] this is all f'n ugly!

            MeshVertexSelection selection = new MeshVertexSelection(mesh);

            selection.SelectTriangleVertices(faces);

            // ugly
            List <Vector2d> seeds = new List <Vector2d>();

            foreach (int vid in selection)
            {
                foreach (int nbrvid in mesh.VtxVerticesItr(vid))
                {
                    if (selection.IsSelected(nbrvid) == false)
                    {
                        seeds.Add(new Vector2d(vid, 0));
                        break;
                    }
                }
            }
            Func <int, int, float> distanceF = (a, b) => { return((float)mesh.GetVertex(a).Distance(mesh.GetVertex(b))); };
            Func <int, bool>       nodeF     = (vid) => { return(selection.IsSelected(vid)); };
            DijkstraGraphDistance  dijkstra  = new DijkstraGraphDistance(mesh.MaxVertexID, true, nodeF, distanceF, mesh.VtxVerticesItr, seeds);

            dijkstra.Compute();
            float maxDist = dijkstra.MaxDistance;


            Displacement.Clear();
            Displacement.Resize(mesh.MaxVertexID);


            // todo: can do this in parallel...
            foreach (int vid in selection)
            {
                //Vector3d v = mesh.GetVertex(vid);

                // [TODO]...
                double dist    = maxDist - dijkstra.GetDistance(vid);
                double falloff = MathUtil.WyvillFalloff(dist, maxDist * 0.0, maxDist);

                Vector3d n = mesh.GetVertexNormal(vid);
                n = n - n.Dot(normal) * normal;
                n.Normalize();

                Displacement[vid] = falloff * offset_distance * n;
            }

            // smooth it?

            result_valid = true;
        }
        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);
        }
        protected override void Update_GenerateMap()
        {
            base.begin_update();

            if (MeshSource == null)
            {
                throw new Exception("EnclosedRegionOffsetOp: must set valid MeshSource to compute!");
            }
            if (MeshSource.HasSpatial == false)
            {
                throw new Exception("EnclosedRegionOffsetOp: MeshSource must have spatial data structure!");
            }

            IMesh imesh = MeshSource.GetIMesh();

            if (imesh.HasVertexNormals == false)
            {
                throw new Exception("EnclosedRegionOffsetOp: input mesh does not have surface normals...");
            }
            if (imesh is DMesh3 == false)
            {
                throw new Exception("EnclosedRegionOffsetOp: in current implementation, input mesh must be a DMesh3. Ugh.");
            }
            DMesh3   mesh    = imesh as DMesh3;
            ISpatial spatial = MeshSource.GetSpatial();

            DCurve3           curve = new DCurve3(CurveSource.GetICurve());
            MeshFacesFromLoop loop  = new MeshFacesFromLoop(mesh, curve, spatial);

            // [RMS] this is all f'n ugly!

            MeshVertexSelection selection = new MeshVertexSelection(mesh);

            selection.SelectTriangleVertices(loop.InteriorTriangles);


            // [TODO] do this inline w/ loop below? but then no maxdist!
            Dictionary <int, double> dists = new Dictionary <int, double>();
            double max_dist = 0;

            foreach (int vid in selection)
            {
                Vector3d v = mesh.GetVertex(vid);
                int      inearseg; double nearsegt;
                double   min_dist_sqr = curve.DistanceSquared(v, out inearseg, out nearsegt);
                min_dist_sqr = Math.Sqrt(min_dist_sqr);
                max_dist     = Math.Max(min_dist_sqr, max_dist);
                dists[vid]   = min_dist_sqr;
            }


            lock (Displacement) {
                Displacement.Clear();
                Displacement.Resize(mesh.MaxVertexID);

                // todo: can do this in parallel...
                foreach (int vid in selection)
                {
                    //Vector3d v = mesh.GetVertex(vid);

                    // [TODO]...
                    double dist    = max_dist - dists[vid];
                    double falloff = Falloff.FalloffT(dist / max_dist);

                    Vector3d n = mesh.GetVertexNormal(vid);
                    n = n - n.Dot(normal) * normal;
                    n.Normalize();

                    Displacement[vid] = falloff * offset_distance * n;
                }
            }

            // smooth it?

            base.complete_update();
        }
Exemple #21
0
        public virtual void Update()
        {
            if (MeshSource == null)
            {
                throw new Exception("EnclosedRegionOffsetOp: must set valid MeshSource to compute!");
            }
            if (MeshSource.HasSpatial == false)
            {
                throw new Exception("EnclosedRegionOffsetOp: MeshSource must have spatial data structure!");
            }

            IMesh imesh = MeshSource.GetIMesh();

            if (imesh.HasVertexNormals == false)
            {
                throw new Exception("EnclosedRegionOffsetOp: input mesh does not have surface normals...");
            }
            if (imesh is DMesh3 == false)
            {
                throw new Exception("RegionOffsetOp: in current implementation, input mesh must be a DMesh3. Ugh.");
            }
            DMesh3   mesh    = imesh as DMesh3;
            ISpatial spatial = MeshSource.GetSpatial();

            DCurve3           curve = new DCurve3(CurveSource.GetICurve());
            MeshFacesFromLoop loop  = new MeshFacesFromLoop(mesh, curve, spatial);

            // extract submesh
            RegionOperator op      = new RegionOperator(mesh, loop.InteriorTriangles);
            DMesh3         submesh = op.Region.SubMesh;

            // find boundary verts and nbr ring
            HashSet <int> boundaryV    = new HashSet <int>(MeshIterators.BoundaryEdgeVertices(submesh));
            HashSet <int> boundaryNbrs = new HashSet <int>();

            foreach (int vid in boundaryV)
            {
                foreach (int nbrvid in submesh.VtxVerticesItr(vid))
                {
                    if (boundaryV.Contains(nbrvid) == false)
                    {
                        boundaryNbrs.Add(nbrvid);
                    }
                }
            }

            // [TODO] maybe should be not using vertex normal here?
            // use an averaged normal, or a constant for patch?

            // offset mesh if requested
            if (Math.Abs(offset_distance) > 0.0001)
            {
                foreach (int vid in submesh.VertexIndices())
                {
                    if (boundaryV.Contains(vid))
                    {
                        continue;
                    }
                    // if inner ring is non-zero, then it gets preserved below, and
                    // creates a crease...
                    //double dist = boundaryNbrs.Contains(vid) ? (offset_distance / 2) : offset_distance;
                    double dist = boundaryNbrs.Contains(vid) ? 0 : offset_distance;
                    submesh.SetVertex(vid,
                                      submesh.GetVertex(vid) + (float)dist * submesh.GetVertexNormal(vid));
                }
            }


            //double t = MathUtil.Clamp(1.0 - SmoothAlpha, 0.1, 1.0);
            double t = 1.0 - SmoothAlpha;

            t = t * t;
            double boundary_t = 5.0;
            double ring_t     = 1.0;

            // smooth submesh, with boundary-ring constraints
            LaplacianMeshSmoother smoother = new LaplacianMeshSmoother(submesh);

            foreach (int vid in submesh.VertexIndices())
            {
                if (boundaryV.Contains(vid))
                {
                    smoother.SetConstraint(vid, submesh.GetVertex(vid), boundary_t, true);
                }
                else if (boundaryNbrs.Contains(vid))
                {
                    smoother.SetConstraint(vid, submesh.GetVertex(vid), ring_t);
                }
                else
                {
                    smoother.SetConstraint(vid, submesh.GetVertex(vid), t);
                }
            }
            smoother.SolveAndUpdateMesh();


            // turn into displacement vectors
            Displacement.Clear();
            Displacement.Resize(mesh.MaxVertexID);
            foreach (int subvid in op.Region.SubMesh.VertexIndices())
            {
                Vector3d subv    = op.Region.SubMesh.GetVertex(subvid);
                int      basevid = op.Region.SubToBaseV[subvid];
                Vector3d basev   = op.Region.BaseMesh.GetVertex(basevid);
                Displacement[basevid] = subv - basev;
            }


            result_valid = true;
        }
        public virtual void Update()
        {
            base.begin_update();

            if (MeshSource == null)
            {
                throw new Exception("MeshVertexDisplacementOp: must set valid MeshSource to compute!");
            }
            if (DisplacementSource == null)
            {
                throw new Exception("MeshVertexDisplacementOp: must set valid DisplacementSource to compute!");
            }

            DMesh3 meshIn = MeshSource.GetDMeshUnsafe();
            IVectorDisplacement displace = DisplacementSource.GetDisplacement();

            if (displace.Count != 0 && displace.Count != meshIn.MaxVertexID)
            {
                throw new Exception("MeshVertexDisplacementOp: inconsistent counts " + displace.Count.ToString() + " != " + meshIn.MaxVertexID.ToString());
            }

            DMesh3 mesh = new DMesh3(meshIn, MeshHints.None);

            //if (!mesh.HasVertexNormals)
            //    MeshNormals.QuickCompute(mesh);
            if (displace.Count > 0)
            {
                gParallel.ForEach(mesh.VertexIndices(), (vid) => {
                    Vector3d dv = displace.GetDisplacementForIndex(vid);

                    //Vector3f n = mesh.GetVertexNormal(vid);
                    Vector3d v = mesh.GetVertex(vid);

                    v += dv;

                    mesh.SetVertex(vid, v);
                });

                if (enable_heat_map)
                {
                    // compute max displace len
                    ColorMap map = new ColorMap();
                    map.AddPoint(0, Colorf.CornflowerBlue);
                    float d = (float)HeatMapMaxDistance;
                    map.AddPoint(d, Colorf.Orange);
                    map.AddPoint(2 * d, Colorf.VideoYellow);
                    map.AddPoint(4 * d, Colorf.VideoRed);
                    map.AddPoint(-d, Colorf.VideoMagenta);

                    float max_displace = d;
                    gParallel.ForEach(mesh.VertexIndices(), (vid) => {
                        Vector3f dv = (Vector3f)displace.GetDisplacementForIndex(vid);

                        Vector3f n = mesh.GetVertexNormal(vid);
                        float sign = n.Dot(dv) > 0 ? 1 : -1;

                        Colorf c = map.Linear(dv.Length * sign);

                        Colorf existing_c   = mesh.GetVertexColor(vid);
                        float preserve__max = max_displace / 2;
                        float t             = MathUtil.Clamp(dv.Length / preserve__max, 0.0f, 1.0f);
                        c = (1.0f - t) * existing_c + (t) * c;

                        mesh.SetVertexColor(vid, c);

                        //float t = MathUtil.Clamp(dv.Length / max_displace, -1.0f, 1.0f);
                        //mesh.SetVertexColor(vid, t * Colorf.Orange);
                    });
                }
            }

            MeshNormals.QuickCompute(mesh);

            DisplacedMesh = mesh;
            base.complete_update();
        }