public virtual void Update() { base.begin_update(); if (MeshSource == null) { throw new Exception("ExtrudeMeshOp: must set valid MeshSource to compute!"); } IMesh meshIn = MeshSource.GetIMesh(); //ISpatial spatialIn = MeshSource.GetSpatial(); ExtrudedMesh = new DMesh3(meshIn, MeshHints.None); MeshExtrudeMesh extrude = new MeshExtrudeMesh(ExtrudedMesh); extrude.ExtrudedPositionF = (v, n, vid) => { return(v + extrude_dist * (Vector3d)n); }; extrude.Extrude(); ApplyModifiers(ExtrudedMesh); base.complete_update(); }
public virtual void Update() { base.begin_update(); if (MeshSource == null) { throw new Exception("TrimMeshFromCurveOp: must set valid MeshSource to compute!"); } if (CurveSource == null) { throw new Exception("TrimMeshFromCurveOp: must set valid CurveSource to compute!"); } IMesh meshIn = MeshSource.GetIMesh(); //ISpatial spatialIn = MeshSource.GetSpatial(); DCurve3 curve = new DCurve3(CurveSource.GetICurve()); TrimmedMesh = new DMesh3(meshIn, MeshHints.None); AxisAlignedBox3d bounds = TrimmedMesh.CachedBounds; Vector3d seed = bounds.Center + bounds.Extents.y * Vector3d.AxisY; MeshTrimLoop trim = new MeshTrimLoop(TrimmedMesh, curve, seed, null); trim.Trim(); ApplyModifiers(TrimmedMesh); base.complete_update(); }
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 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; }
/// <summary> /// compute SDF for the scan object, and then compute offset iso-contours /// </summary> void compute_offset_meshes() { int sdf_cells = 128; int mesh_cells = 128; double max_offset = inner_offset + thickness; if (max_offset > cached_sdf_max_offset) { DMesh3 meshIn = new DMesh3(MeshSource.GetIMesh(), MeshHints.IsCompact, MeshComponents.None); MeshTransforms.FromFrame(meshIn, cachedInputsTransform); // [RMS] reduce this mesh? speeds up SDF quite a bit... Reducer r = new Reducer(meshIn); r.ReduceToTriangleCount(2500); double cell_size = meshIn.CachedBounds.MaxDim / sdf_cells; int exact_cells = (int)((max_offset) / cell_size) + 1; MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(meshIn, cell_size) { ExactBandWidth = exact_cells }; sdf.Compute(); cached_sdf = sdf; cached_sdf_max_offset = max_offset; cached_sdf_bounds = meshIn.CachedBounds; cached_inner_sdf_offset = 0; cached_outer_sdf_offset = 0; } if (cached_inner_sdf_offset != inner_offset || cached_outer_sdf_offset != max_offset) { var iso = new DenseGridTrilinearImplicit(cached_sdf.Grid, cached_sdf.GridOrigin, cached_sdf.CellSize); MarchingCubes c = new MarchingCubes() { Implicit = iso }; c.Bounds = cached_sdf_bounds; c.CubeSize = c.Bounds.MaxDim / mesh_cells; c.Bounds.Expand(max_offset + 3 * c.CubeSize); if (cached_inner_sdf_offset != inner_offset) { c.IsoValue = inner_offset; c.Generate(); InnerOffsetMesh = c.Mesh; Reducer reducer = new Reducer(InnerOffsetMesh); reducer.ReduceToEdgeLength(c.CubeSize / 2); InnerOffsetMeshSpatial = new DMeshAABBTree3(InnerOffsetMesh, true); cached_inner_sdf_offset = inner_offset; } if (cached_outer_sdf_offset != max_offset) { c.IsoValue = inner_offset + thickness; c.Generate(); OuterOffsetMesh = c.Mesh; Reducer reducer = new Reducer(OuterOffsetMesh); reducer.ReduceToEdgeLength(c.CubeSize / 2); OuterOffsetMeshSpatial = new DMeshAABBTree3(OuterOffsetMesh, true); cached_outer_sdf_offset = max_offset; } } //Util.WriteDebugMesh(MeshSource.GetIMesh(), "c:\\scratch\\__OFFESTS_orig.obj"); //Util.WriteDebugMesh(InnerOffsetMesh, "c:\\scratch\\__OFFESTS_inner.obj"); //Util.WriteDebugMesh(OuterOffsetMesh, "c:\\scratch\\__OFFESTS_outer.obj"); }
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; }
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(); }