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; }
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); }
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); }
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(); }
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"); } }