protected override void OnPointUpdated(ControlPoint pt, Frame3f prevFrameS, bool isFirst)
        {
            Vector3f basePt  = GetPointPosition(BasePointID, CoordSpace.SceneCoords).Origin;
            Vector3f frontPt = GetPointPosition(FrontPointID, CoordSpace.SceneCoords).Origin;
            Vector3f topPt   = GetPointPosition(TopPointID, CoordSpace.SceneCoords).Origin;

            lastTargetFrameS = TargetSO.GetLocalFrame(CoordSpace.SceneCoords);

            Frame3f previewFrameS = lastTargetFrameS;

            // position next to original object
            previewFrameS = previewFrameS.Translated(1.1f * (float)meshBounds.Width * Vector3f.AxisX);

            Vector3f upAxis = (topPt - basePt).Normalized;

            // construct a frame perp to upAxis at midpoint, and project original and current fw points
            Frame3f  upFrame = new Frame3f((topPt + basePt) * 0.5f, upAxis);
            Vector3f origFW  = upFrame.ProjectToPlane(initialFrontPt, 2);

            origFW = (origFW - upFrame.Origin).Normalized;
            Vector3f curFW = upFrame.ProjectToPlane(frontPt, 2);

            curFW = (curFW - upFrame.Origin).Normalized;
            //float angle = MathUtil.PlaneAngleSignedD(origFW, curFW, upAxis);

            start_forward_pt_S   = upFrame.FromFrameP(origFW);
            current_forward_pt_S = upFrame.FromFrameP(curFW);

            // construct rotation that aligns up axis with y-up
            Quaternionf upRotate = Quaternionf.FromTo(upAxis, Vector3f.AxisY);

            previewFrameS.Rotate(upRotate);

            // now rotate so that forward dir points along -Z
            //Quaternionf fwRotate = Quaternionf.AxisAngleD(Vector3f.AxisY, angle);
            //curFW = upRotate * curFW;
            Quaternionf fwRotate = Quaternionf.FromToConstrained(curFW, -Vector3f.AxisZ, Vector3f.AxisY);

            previewFrameS.Rotate(fwRotate);

            previewSO.SetLocalFrame(previewFrameS, CoordSpace.SceneCoords);
            lastPreviewFrameS = previewFrameS;
        }
Пример #2
0
        DMesh3 compute_partial_hole(Vector3d start, Vector3d end, double tol)
        {
            DMesh3         origMesh    = MeshSource.GetDMeshUnsafe();
            DMeshAABBTree3 origSpatial = MeshSource.GetSpatial() as DMeshAABBTree3;

            DMesh3 cutMesh = new DMesh3(origMesh);

            Polygon2d polygon = Polygon2d.MakeCircle(hole_size / 2, hole_subdivisions);

            Vector3f axis = (Vector3f)(start - end).Normalized;

            int     start_tid   = origSpatial.FindNearestTriangle(start);
            Frame3f start_frame = origMesh.GetTriFrame(start_tid);

            start_frame.Origin = (Vector3f)start;
            start_frame.AlignAxis(2, axis);

            int end_tid = origSpatial.FindNearestTriangle(end);
            //Frame3f end_frame = origMesh.GetTriFrame(end_tid); end_frame.Origin = (Vector3f)end;
            Frame3f end_frame = start_frame; end_frame.Origin = (Vector3f)end;

            // [TODO] we don't need to Simplify here...is more robust?

            MeshInsertProjectedPolygon start_insert = new MeshInsertProjectedPolygon(cutMesh, polygon, start_frame, start_tid);
            bool start_ok = start_insert.Insert();

            if (start_ok == false)
            {
                throw new Exception("CutPolygonHoleOp.compute_partial_hole: start or end insertion failed!");
            }

            EdgeLoop outLoop = start_insert.InsertedLoop;

            MeshExtrudeLoop extrude = new MeshExtrudeLoop(cutMesh, outLoop);

            extrude.PositionF = (v, n, vid) => {
                cutMesh.GetVertex(vid);
                return(end_frame.ProjectToPlane((Vector3f)v, 2));
            };
            extrude.Extrude();

            SimpleHoleFiller filler = new SimpleHoleFiller(cutMesh, extrude.NewLoop);

            filler.Fill();

            return(cutMesh);
        }
Пример #3
0
        public void Close_Flat()
        {
            double minlen, maxlen, avglen;

            MeshQueries.EdgeLengthStats(Mesh, out minlen, out maxlen, out avglen, 1000);
            double target_edge_len = (TargetEdgeLen <= 0) ? avglen : TargetEdgeLen;

            // massage around boundary loop
            cleanup_boundary(Mesh, InitialBorderLoop, avglen, 3);

            // find new border loop
            // [TODO] this just assumes there is only one!!
            MeshBoundaryLoops loops     = new MeshBoundaryLoops(Mesh);
            EdgeLoop          fill_loop = loops.Loops[0];

            int extrude_group = (ExtrudeGroup == -1) ? Mesh.AllocateTriangleGroup() : ExtrudeGroup;
            int fill_group    = (FillGroup == -1) ? Mesh.AllocateTriangleGroup() : FillGroup;

            // decide on projection plane
            //AxisAlignedBox3d loopbox = fill_loop.GetBounds();
            //Vector3d topPt = loopbox.Center;
            //if ( bIsUpper ) {
            //    topPt.y = loopbox.Max.y + 0.25 * dims.y;
            //} else {
            //    topPt.y = loopbox.Min.y - 0.25 * dims.y;
            //}
            //Frame3f plane = new Frame3f((Vector3f)topPt);

            // extrude loop to this plane
            MeshExtrusion extrude = new MeshExtrusion(Mesh, fill_loop);

            extrude.PositionF = (v, n, i) => {
                return(FlatClosePlane.ProjectToPlane((Vector3F)v, 1));
            };
            extrude.Extrude(extrude_group);
            MeshValidation.IsBoundaryLoop(Mesh, extrude.NewLoop);

            Debug.Assert(Mesh.CheckValidity());

            // smooth the extrude loop
            MeshLoopSmooth loop_smooth = new MeshLoopSmooth(Mesh, extrude.NewLoop);

            loop_smooth.ProjectF = (v, i) => {
                return(FlatClosePlane.ProjectToPlane((Vector3F)v, 1));
            };
            loop_smooth.Alpha  = 0.5f;
            loop_smooth.Rounds = 100;
            loop_smooth.Smooth();

            Debug.Assert(Mesh.CheckValidity());

            // fill result
            SimpleHoleFiller filler = new SimpleHoleFiller(Mesh, extrude.NewLoop);

            filler.Fill(fill_group);

            Debug.Assert(Mesh.CheckValidity());

            // make selection for remesh region
            MeshFaceSelection remesh_roi = new MeshFaceSelection(Mesh);

            remesh_roi.Select(extrude.NewTriangles);
            remesh_roi.Select(filler.NewTriangles);
            remesh_roi.ExpandToOneRingNeighbours();
            remesh_roi.ExpandToOneRingNeighbours();
            remesh_roi.LocalOptimize(true, true);
            int[] new_roi = remesh_roi.ToArray();

            // get rid of extrude group
            FaceGroupUtil.SetGroupToGroup(Mesh, extrude_group, 0);

            /*  clean up via remesh
             *     - constrain loop we filled to itself
             */

            RegionRemesher r = new RegionRemesher(Mesh, new_roi);

            DCurve3 top_curve = mesh.MeshUtil.ExtractLoopV(Mesh, extrude.NewLoop.Vertices);
            DCurveProjectionTarget curve_target = new DCurveProjectionTarget(top_curve);

            int[] top_loop = (int[])extrude.NewLoop.Vertices.Clone();
            r.Region.MapVerticesToSubmesh(top_loop);
            MeshConstraintUtil.ConstrainVtxLoopTo(r.Constraints, r.Mesh, top_loop, curve_target);

            DMeshAABBTree3 spatial = new DMeshAABBTree3(Mesh);

            spatial.Build();
            MeshProjectionTarget target = new MeshProjectionTarget(Mesh, spatial);

            r.SetProjectionTarget(target);

            bool bRemesh = true;

            if (bRemesh)
            {
                r.Precompute();
                r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
                r.MinEdgeLength   = target_edge_len;
                r.MaxEdgeLength   = 2 * target_edge_len;
                r.EnableSmoothing = true;
                r.SmoothSpeedT    = 1.0f;
                for (int k = 0; k < 40; ++k)
                {
                    r.BasicRemeshPass();
                }
                r.SetProjectionTarget(null);
                r.SmoothSpeedT = 0.25f;
                for (int k = 0; k < 10; ++k)
                {
                    r.BasicRemeshPass();
                }
                Debug.Assert(Mesh.CheckValidity());

                r.BackPropropagate();
            }

            // smooth around the join region to clean up ugliness
            smooth_region(Mesh, r.Region.BaseBorderV, 3);
        }
Пример #4
0
        protected void do_flatten(DMesh3 mesh)
        {
            double   BAND_HEIGHT = flatten_band_height;
            Vector3d down_axis   = -Vector3d.AxisY;
            double   dot_thresh  = 0.2;

            AxisAlignedBox3d bounds  = mesh.CachedBounds;
            DMeshAABBTree3   spatial = new DMeshAABBTree3(mesh, true);

            Ray3d   ray     = new Ray3d(bounds.Center - 2 * bounds.Height * Vector3d.AxisY, Vector3d.AxisY);
            int     hit_tid = spatial.FindNearestHitTriangle(ray);
            Frame3f hitF;

            MeshQueries.RayHitPointFrame(mesh, spatial, ray, out hitF);
            Vector3d basePt = hitF.Origin;

            Frame3f basePlane = new Frame3f(basePt, Vector3f.AxisY);

            MeshConnectedComponents components = new MeshConnectedComponents(mesh)
            {
                FilterF = (tid) => {
                    if (mesh.GetTriangleGroup(tid) != LastExtrudeOuterGroupID)
                    {
                        return(false);
                    }
                    Vector3d n, c; double a;
                    mesh.GetTriInfo(tid, out n, out a, out c);
                    double h = Math.Abs(c.y - basePt.y);
                    if (h > BAND_HEIGHT)
                    {
                        return(false);
                    }
                    if (n.Dot(down_axis) < dot_thresh)
                    {
                        return(false);
                    }
                    return(true);
                },
                SeedFilterF = (tid) => {
                    return(tid == hit_tid);
                }
            };

            components.FindConnectedT();

            MeshFaceSelection all_faces = new MeshFaceSelection(mesh);

            foreach (var comp in components)
            {
                MeshVertexSelection vertices = new MeshVertexSelection(mesh);
                vertices.SelectTriangleVertices(comp.Indices);
                foreach (int vid in vertices)
                {
                    Vector3d v = mesh.GetVertex(vid);
                    v = basePlane.ProjectToPlane((Vector3f)v, 2);
                    mesh.SetVertex(vid, v);
                }
                all_faces.SelectVertexOneRings(vertices);
            }

            all_faces.ExpandToOneRingNeighbours(3, (tid) => {
                return(mesh.GetTriangleGroup(tid) == LastExtrudeOuterGroupID);
            });

            RegionRemesher r = new RegionRemesher(mesh, all_faces);

            r.SetProjectionTarget(MeshProjectionTarget.Auto(mesh));
            r.SetTargetEdgeLength(2.0f);
            r.SmoothSpeedT = 1.0f;
            for (int k = 0; k < 10; ++k)
            {
                r.BasicRemeshPass();
            }
            r.SetProjectionTarget(null);
            r.SmoothSpeedT = 1.0f;
            for (int k = 0; k < 10; ++k)
            {
                r.BasicRemeshPass();
            }
            r.BackPropropagate();
        }
Пример #5
0
        public void UpdateDraw_Spatial(Ray3f ray, Frame3f handFrame, int nStep)
        {
            // scene xform may have changed during steps (eg view rotation), so we
            // need to reconstruct our local frame
            Frame3f primCurW = scene.ToWorldFrame(primStartS);

            // try snap points
            SnapResult snap      = Snaps.FindHitSnapPoint(ray);
            bool       bHaveSnap = (snap != null);
            Frame3f    snapF     = (bHaveSnap) ? scene.ToWorldFrame(snap.FrameS) : Frame3f.Identity;

            // step 1: find radius in plane
            if (nStep == 0)
            {
                if (bHaveSnap)
                {
                    plane_hit_local = primCurW.ToFrameP(
                        primCurW.ProjectToPlane(snapF.Origin, 1));
                }
                else
                {
                    Vector3f forwardDir = ray.Direction;
                    Vector3f plane_hit  = VRUtil.SafeRayPlaneIntersection(ray, forwardDir, primCurW.Origin, primCurW.Y);
                    plane_hit_local = primCurW.ToFrameP(plane_hit);
                }
            }
            float fX       = MathUtil.SignedClamp(plane_hit_local[0], MinDimension, MaxDimension);
            float fY       = MinDimension;
            float fZ       = MathUtil.SignedClamp(plane_hit_local[2], MinDimension, MaxDimension);
            float fR_plane = MathUtil.Clamp(plane_hit_local.Length, MinDimension / 2, MaxDimension / 2);

            // step 2: find height from plane
            if (nStep == 1)
            {
                Vector3f plane_hit = primCurW.FromFrameP(plane_hit_local);
                Line3d   l         = new Line3d(plane_hit, primCurW.Y);
                if (bHaveSnap)
                {
                    fY = (float)l.Project(snapF.Origin);
                }
                else
                {
                    Vector3f handTip   = handFrame.Origin + SceneGraphConfig.HandTipOffset * handFrame.Z;
                    float    fHandDist = (float)l.DistanceSquared(handTip);
                    if (fHandDist < fR_plane * 1.5f)
                    {
                        fY = (float)l.Project(handTip);
                    }
                    else
                    {
                        fY = (float)DistLine3Ray3.MinDistanceLineParam(ray, l);
                    }
                }
            }

            // figure out possible dimensions, clamp to ranges
            fY = MathUtil.SignedClamp(fY, MinDimension, MaxDimension);

            // update frame
            primitive.Frame = primCurW;

            // update dimensions
            bool  bIsCorner = (primitive.Center == CenterModes.Corner);
            float fScale    = 1.0f;     // object is not in scene coordinates!

            if (primitive.Type == MeshPrimitivePreview.PrimType.Cylinder)
            {
                primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale;
                primitive.Depth = primitive.Width;
                //primitive.Depth = Mathf.Sign(fZ) * primitive.Width;
                //primitive.Width = Mathf.Sign(fX) * primitive.Width;
                primitive.Height = fY * fScale;
            }
            else if (primitive.Type == MeshPrimitivePreview.PrimType.Box)
            {
                primitive.Width  = (bIsCorner) ? fX : 2 * fX * fScale;
                primitive.Depth  = (bIsCorner) ? fZ : 2 * fZ * fScale;
                primitive.Height = fY * fScale;
            }
            else if (primitive.Type == MeshPrimitivePreview.PrimType.Sphere)
            {
                primitive.Width = (bIsCorner) ? fR_plane * fScale : 2 * fR_plane * fScale;
                primitive.Depth = primitive.Height = primitive.Width;
                //primitive.Depth = Mathf.Sign(fZ) * primitive.Width;
                //primitive.Width = Mathf.Sign(fX) * primitive.Width;
                //primitive.Height = Mathf.Sign(fY) * primitive.Width;
            }
            else
            {
                throw new NotImplementedException("SnapDrawPrimitivesTool.UpdateDraw_Ray - type not supported");
            }
        }