public virtual void Update() { if (MeshSource == null) { throw new Exception("LengthenOp: must set valid MeshSource to compute!"); } IMesh mesh = MeshSource.GetIMesh(); if (mesh.HasVertexNormals == false) { throw new Exception("LengthenOp: input mesh does not have surface normals..."); } Displacement.Resize(mesh.MaxVertexID); // todo: can do this in parallel foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); double dist = (v - basePt).Dot(direction); if (dist < -band_distance) { continue; } dist = Math.Abs(Math.Min(0, dist)); double falloff_dist = falloff_rate * band_distance; double t = MathUtil.WyvillFalloff(dist, falloff_dist, band_distance); Displacement[vid] = t * distance * direction; } result_valid = true; }
public virtual void Update() { base.begin_update(); int Nd = Displacements.Count; if (Nd == 0) { for (int i = 0; i < CombinedDisplacement.Count; ++i) { CombinedDisplacement[i] = Vector3d.Zero; } base.complete_update(); return; } IVectorDisplacement[] children = new IVectorDisplacement[Nd]; for (int i = 0; i < Nd; ++i) { children[i] = Displacements[i].GetDisplacement(); if (children[i].Count != children[0].Count) { throw new Exception("DisplacementCombinerOp.Update: child " + i.ToString() + " Count inconsistent: " + children[i].Count + " != " + children[0].Count); } } int Nv = children[0].Count; CombinedDisplacement.Resize(Nv); for (int vi = 0; vi < Nv; ++vi) { Vector3d sum = Vector3d.Zero; for (int di = 0; di < Nd; ++di) { sum += children[di].GetDisplacementForIndex(vi); } CombinedDisplacement[vi] = sum; } base.complete_update(); }
public virtual void Update() { base.begin_update(); if (MeshSource == null) { throw new Exception("VectorDisplacementMapOp: must set valid MeshSource to compute!"); } IMesh imesh = MeshSource.GetIMesh(); if (imesh.HasVertexNormals == false) { throw new Exception("VectorDisplacementMapOp: input mesh does not have surface normals..."); } if (imesh is DMesh3 == false) { throw new Exception("VectorDisplacementMapOp: in current implementation, input mesh must be a DMesh3. Ugh."); } DMesh3 mesh = imesh as DMesh3; lock (Displacement) { if (have_set_displacement) { lock (set_displacement) { if (set_displacement.Count == mesh.MaxVertexID) { Displacement.Set(set_displacement); } have_set_displacement = false; } } else if (Displacement.Count != mesh.MaxVertexID) { Displacement.Clear(); Displacement.Resize(mesh.MaxVertexID); } } base.complete_update(); }
public virtual void Update() { if (MeshSource == null) { throw new Exception("PlaneBandExpansionOp: must set valid MeshSource to compute!"); } IMesh mesh = MeshSource.GetIMesh(); if (mesh.HasVertexNormals == false) { throw new Exception("PlaneBandExpansionOp: input mesh does not have surface normals..."); } Displacement.Resize(mesh.MaxVertexID); // todo: can do this in parallel foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); double dist = (v - origin).Dot(normal); dist = Math.Abs(dist); if (dist > band_distance) { continue; } double falloff = MathUtil.WyvillFalloff(dist, band_distance * 0.1, band_distance); Vector3d n = mesh.GetVertexNormal(vid); n = n - n.Dot(normal) * normal; n.Normalize(); Displacement[vid] = falloff * offset_distance * n; } result_valid = true; }
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 void Update() { if (MeshSource == null) { throw new Exception("LegSqueezeOp: must set valid MeshSource to compute!"); } IMesh mesh = MeshSource.GetIMesh(); if (mesh.HasVertexNormals == false) { throw new Exception("LegSqueezeOp: input mesh does not have surface normals..."); } Displacement.Resize(mesh.MaxVertexID); // compute extents along axis double upper_t = UpperPoint.Dot(Axis); Interval1d axis_extents = MeshMeasurements.ExtentsOnAxis(mesh, axis); double lower_t = axis_extents.a; // compute approximate skeleton int nVertices = midPoints.Count + 2; Vector3d[] centers = new Vector3d[nVertices]; int[] counts = new int[nVertices]; foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); double t = v.Dot(ref axis); int iBin = 0; if (t > upper_t) { iBin = nVertices - 1; } else if (t > lower_t) { double unit_t = (t - lower_t) / (upper_t - lower_t); iBin = 1; for (int k = 0; k < midPoints.Count; ++k) { if (unit_t > midPoints[k].x) { iBin++; } } } // else iBin = 0, as initialized centers[iBin] += v; counts[iBin]++; } for (int k = 0; k < centers.Length; ++k) { centers[k] /= counts[k]; } // todo: can do this in parallel foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); double t = v.Dot(axis); if (t > upper_t) { continue; } Vector3d center = centers[0]; double percent = 0; if (t >= upper_t) { percent = reduce_percent_top; center = centers[nVertices - 1]; } else if (t <= lower_t) { percent = reduce_percent_bottom; center = centers[0]; } else if (midPoints.Count == 0) { double unit_t = (t - lower_t) / (upper_t - lower_t); unit_t = MathUtil.WyvillRise01(unit_t); percent = MathUtil.Lerp(reduce_percent_bottom, reduce_percent_top, unit_t); } else { double unit_t = (t - lower_t) / (upper_t - lower_t); double low_percent = reduce_percent_bottom; double high_percent = reduce_percent_top; Vector3d low_center = centers[0]; Vector3d high_center = centers[0]; double low_t = 0.0, high_t = 0; for (int i = 0; i < midPoints.Count; ++i) { if (unit_t < midPoints[i].x) { high_t = midPoints[i].x; high_percent = midPoints[i].y; high_center = centers[i + 1]; break; } low_t = midPoints[i].x; low_percent = midPoints[i].y; low_center = centers[i + 1]; } if (high_t == 0) { high_t = 1.0; high_percent = reduce_percent_top; high_center = centers[nVertices - 1]; } double a = (unit_t - low_t) / (high_t - low_t); a = MathUtil.WyvillRise01(a); percent = MathUtil.Lerp(low_percent, high_percent, a); center = Vector3d.Lerp(low_center, high_center, a); } percent = percent / 100; double scale = 1.0 - percent; Vector3d v_scaled = (v - center) * new Vector3d(scale, 1, scale) + center; Displacement[vid] = v_scaled - v; } result_valid = true; }
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; }