public override bool BuildOnMesh(DMesh3Builder meshBuilder) { var doorCopy = new DMesh3(Mesh, bCompact: true); if (FrontNormal == -Vector3d.AxisZ) { // trick to prevent 180 rotation FrontNormal += new Vector3d(0.0000001, 0.0, 0.0); } var meshWidth = doorCopy.GetBounds().Width; var meshHeight = doorCopy.GetBounds().Height; var widthScale = WidthLimit / meshWidth; var heightScale = HeightLimit / meshHeight; Quaterniond orientingQuaternion = new Quaterniond(Vector3d.AxisZ, FrontNormal); MeshTransforms.Rotate(doorCopy, Vector3d.Zero, orientingQuaternion); MeshTransforms.Scale(doorCopy, Math.Min(widthScale, heightScale)); MeshTransforms.Translate(doorCopy, Origin); meshBuilder.AppendNewMesh(doorCopy); meshBuilder.SetActiveMesh(0); return(true); }
//experimental public List <DMesh3> SliceMold(DMesh3 mesh_to_slice, int number_of_slices) { var meshes = new List <MeshGeometry3D>(); //convert mesh to DMesh DMesh3 mesh = mesh_to_slice; //create cube for slicing double z_height = mesh.GetBounds().Max.z - mesh.GetBounds().Min.z; double slice_interval = (double)(z_height / number_of_slices); double x_size = mesh.GetBounds().Depth; double y_size = mesh.GetBounds().Width; double low_z = mesh.GetBounds().Min.z; //boolean intersection each mesh var sliced_meshes = new List <DMesh3>(); for (int i = 0; i < number_of_slices; i++) { //create box Vector3d centre = new Vector3d(0, 0, low_z + slice_interval / 2 + i * (slice_interval)); Vector3d extend = new Vector3d( x_size, y_size, slice_interval / 2); ImplicitBox3d box = new ImplicitBox3d() { Box = new Box3d(centre, extend) }; //boolean overlap BoundedImplicitFunction3d meshA = meshToImplicitF(mesh, 64, 0.2f); //take the difference of the bolus mesh minus the tools ImplicitIntersection3d mesh_result = new ImplicitIntersection3d { A = meshA, B = box }; //calculate the boolean mesh MarchingCubes c = new MarchingCubes(); c.Implicit = mesh_result; c.RootMode = MarchingCubes.RootfindingModes.LerpSteps; c.RootModeSteps = 5; c.Bounds = mesh_result.Bounds(); c.CubeSize = c.Bounds.MaxDim / 256; c.Bounds.Expand(3 * c.CubeSize); c.Generate(); MeshNormals.QuickCompute(c.Mesh); int triangleCount = c.Mesh.TriangleCount / 3; Reducer r = new Reducer(c.Mesh); r.ReduceToTriangleCount(triangleCount); sliced_meshes.Add(c.Mesh); } return(sliced_meshes); }
public void MyInit(DMesh3 mesh, bool isImported = false) { this.mesh = mesh; spatial = new DMeshAABBTree3(mesh); spatial.Build(); this.isImported = isImported; if (isImported) { originalMesh = new DMesh3(mesh); } center = transform.TransformPoint(mesh.GetBounds().Center.toVector3()); }
public override bool BuildOnMesh(DMesh3Builder meshBuilder) { DMesh3 windowCopy = null; BuildingTask = Task.Run(() => { windowCopy = new DMesh3(Mesh, bCompact: true); //var windowCopy = Mesh; if (FrontNormal == -Vector3d.AxisZ) { // trick to prevent 180 rotation FrontNormal += new Vector3d(0.0000001, 0.0, 0.0); } var meshWidth = windowCopy.GetBounds().Width; var meshHeight = windowCopy.GetBounds().Height; var widthScale = WidthLimit / meshWidth; var heightScale = HeightLimit / meshHeight; var selectedScale = Math.Min(widthScale, heightScale); Quaterniond orientingQuaternion = new Quaterniond(Vector3d.AxisZ, FrontNormal); MeshTransforms.Rotate(windowCopy, Vector3d.Zero, orientingQuaternion); MeshTransforms.Scale(windowCopy, selectedScale); MeshTransforms.Translate(windowCopy, Origin); //MeshTransforms.Translate(windowCopy, Origin + Vector3d.AxisY * meshHeight * selectedScale * 0.6); }).ContinueWith(t => { lock (meshBuilder) { meshBuilder.AppendNewMesh(windowCopy); meshBuilder.SetActiveMesh(0); } }); return(true); }
// [RMS] this only tests some basic cases... public static void test_Laplacian_deformer() { // compact version DMesh3 mesh = new DMesh3(TestUtil.MakeRemeshedCappedCylinder(1.0), true); Debug.Assert(mesh.IsCompact); AxisAlignedBox3d bounds = mesh.GetBounds(); TestUtil.WriteTestOutputMesh(mesh, "laplacian_deformer_before.obj"); List <IMesh> result_meshes = new List <IMesh>(); LaplacianMeshDeformer deformer = new LaplacianMeshDeformer(mesh); int ti = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new Vector3d(2, 5, 2)); int v_pin = mesh.GetTriangle(ti).a; List <int> constraints = new List <int>() { v_pin }; double consPin = 10; double consBottom = 10; foreach (int vid in constraints) { result_meshes.Add(TestUtil.MakeMarker(mesh.GetVertex(vid), (vid == 0) ? 0.2f : 0.1f, Colorf.Red)); } foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); bool bottom = (v.y - bounds.Min.y) < 0.01f; if (constraints.Contains(vid)) { deformer.SetConstraint(vid, v + Vector3f.AxisY, consPin, false); } if (bottom) { deformer.SetConstraint(vid, v, consBottom, false); } } deformer.SolveAndUpdateMesh(); result_meshes.Add(mesh); TestUtil.WriteTestOutputMeshes(result_meshes, "laplacian_deformer_after.obj"); }
public Task BuildTreeAsync(Vector3[] positions, Vector3[] normals, int[] indices) { return(Task.Run(() => { var norm = ConvertToVector3f(normals); DMeshLocal = DMesh3Builder.Build(ConvertToVector3f(positions), indices, norm); TreeLocal = new DMeshAABBTree3(DMeshLocal); TreeLocal.Build(); box = new BoundingBox(DMeshLocal.GetBounds()); IsBuilt = true; return this; })); }
protected override Result RunCommand(RhinoDoc doc, RunMode mode) { DMesh3 mesh = new DMesh3(MakeRemeshedCappedCylinder(1.0), true); AxisAlignedBox3d bounds = mesh.GetBounds(); List <IMesh> result_meshes = new List <IMesh>(); LaplacianMeshDeformer deformer = new LaplacianMeshDeformer(mesh); // constrain bottom points foreach (int vid in mesh.VertexIndices()) { g3.Vector3d v = mesh.GetVertex(vid); bool bottom = (v.y - bounds.Min.y) < 0.01f; if (bottom) { deformer.SetConstraint(vid, v, 10); } } // constrain one other vtx int ti = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new g3.Vector3d(2, 5, 2)); int v_pin = mesh.GetTriangle(ti).a; g3.Vector3d cons_pos = mesh.GetVertex(v_pin); cons_pos += new g3.Vector3d(0.5, 0.5, 0.5); deformer.SetConstraint(v_pin, cons_pos, 10); deformer.Initialize(); g3.Vector3d[] resultV = new g3.Vector3d[mesh.MaxVertexID]; deformer.Solve(resultV); foreach (int vid in mesh.VertexIndices()) { mesh.SetVertex(vid, resultV[vid]); } var rhinoMesh = GopherUtil.ConvertToRhinoMesh(mesh); doc.Objects.AddMesh(rhinoMesh); return(Result.Success); }
// [RMS] this only tests some basic cases... public static void test_LaplacianDeformation() { // compact version DMesh3 mesh = new DMesh3(TestUtil.MakeRemeshedCappedCylinder(1.0), true); Debug.Assert(mesh.IsCompact); AxisAlignedBox3d bounds = mesh.GetBounds(); List <IMesh> result_meshes = new List <IMesh>(); LaplacianMeshDeformer deformer = new LaplacianMeshDeformer(mesh); // constrain bottom points foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); bool bottom = (v.y - bounds.Min.y) < 0.01f; if (bottom) { deformer.SetConstraint(vid, v, 10); } } // constrain one other vtx int ti = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new Vector3d(2, 5, 2)); int v_pin = mesh.GetTriangle(ti).a; Vector3d cons_pos = mesh.GetVertex(v_pin); cons_pos += new Vector3d(0.5, 0.5, 0.5); deformer.SetConstraint(v_pin, cons_pos, 10); result_meshes.Add(TestUtil.MakeMarker(mesh.GetVertex(v_pin), 0.2f, Colorf.Red)); deformer.Initialize(); Vector3d[] resultV = new Vector3d[mesh.MaxVertexID]; deformer.Solve(resultV); foreach (int vid in mesh.VertexIndices()) { mesh.SetVertex(vid, resultV[vid]); } result_meshes.Add(mesh); TestUtil.WriteDebugMeshes(result_meshes, "___LAPLACIAN_result.obj"); }
protected override void SolveInstance(IGH_DataAccess DA) { int num_cells = 128; DMesh3_goo dMsh_goo = null; DA.GetData(0, ref dMsh_goo); DA.GetData(1, ref num_cells); DMesh3 dMsh_copy = new DMesh3(dMsh_goo.Value); double cell_size = dMsh_copy.CachedBounds.MaxDim / num_cells; DMeshAABBTree3 spatial = new DMeshAABBTree3(dMsh_copy, autoBuild: true); AxisAlignedBox3d bounds = dMsh_copy.CachedBounds; double cellsize = bounds.MaxDim / num_cells; ShiftGridIndexer3 indexer = new ShiftGridIndexer3(bounds.Min, cellsize); Bitmap3 bmp = new Bitmap3(new Vector3i(num_cells, num_cells, num_cells)); foreach (Vector3i idx in bmp.Indices()) { g3.Vector3d v = indexer.FromGrid(idx); bmp.Set(idx, spatial.IsInside(v)); } VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator(); voxGen.Voxels = bmp; voxGen.Generate(); DMesh3 voxMesh = voxGen.Meshes[0]; var vecSize = dMsh_copy.CachedBounds.Extents; var box = dMsh_copy.GetBounds(); // Scale voxel mesh //MeshTransforms.Scale(voxMesh,) DA.SetData(0, voxMesh); }
public Task BuildTreeAsync(IGeometryComponent geo) { if (!geo.IsValid) { return(Task.FromResult(0)); } return(Task.Run(() => { var norm = geo.Normals.IsDefaultOrEmpty ? null : ConvertToVector3f(geo.Normals); DMeshLocal = DMesh3Builder.Build(ConvertToVector3f(geo.Positions), geo.Indices, norm); //var sm = new LaplacianMeshSmoother(DMesh); //sm.Initialize(); //sm.SolveAndUpdateMesh(); //DMesh = sm.Mesh; TreeLocal = new DMeshAABBTree3(DMeshLocal); TreeLocal.Build(); box = new BoundingBox(DMeshLocal.GetBounds()); IsBuilt = true; return this; })); }
// [RMS] this only tests some basic cases... public static void test_Laplacian() { // compact version DMesh3 mesh = new DMesh3(TestUtil.MakeRemeshedCappedCylinder(1.0), true); Debug.Assert(mesh.IsCompact); AxisAlignedBox3d bounds = mesh.GetBounds(); TestUtil.WriteDebugMesh(mesh, "___CG_before.obj"); List <IMesh> result_meshes = new List <IMesh>(); // make uniform laplacian matrix int N = mesh.VertexCount; SymmetricSparseMatrix M = new SymmetricSparseMatrix(); //DenseMatrix M = new DenseMatrix(N, N); double[] Px = new double[N], Py = new double[N], Pz = new double[N]; int[] nbr_counts = new int[N]; for (int vid = 0; vid < N; ++vid) { nbr_counts[vid] = mesh.GetVtxEdgeCount(vid); } int ti = MeshQueries.FindNearestTriangle_LinearSearch(mesh, new Vector3d(2, 5, 2)); int v_pin = mesh.GetTriangle(ti).a; List <int> constraints = new List <int>() { v_pin }; double consW = 10; double consBottom = 10; foreach (int vid in constraints) { result_meshes.Add(TestUtil.MakeMarker(mesh.GetVertex(vid), (vid == 0) ? 0.2f : 0.1f, Colorf.Red)); } for (int vid = 0; vid < N; ++vid) { int n = nbr_counts[vid]; Vector3d v = mesh.GetVertex(vid), c = Vector3d.Zero; Px[vid] = v.x; Py[vid] = v.y; Pz[vid] = v.z; bool bottom = (v.y - bounds.Min.y) < 0.01f; double sum_w = 0; foreach (int nbrvid in mesh.VtxVerticesItr(vid)) { int n2 = nbr_counts[nbrvid]; // weight options //double w = -1; double w = -1.0 / Math.Sqrt(n + n2); //double w = -1.0 / n; M.Set(vid, nbrvid, w); c += w * mesh.GetVertex(nbrvid); sum_w += w; } sum_w = -sum_w; M.Set(vid, vid, sum_w); // add soft constraints if (constraints.Contains(vid)) { M.Set(vid, vid, sum_w + consW); } else if (bottom) { M.Set(vid, vid, sum_w + consBottom); } } // compute laplacians double[] MLx = new double[N], MLy = new double[N], MLz = new double[N]; M.Multiply(Px, MLx); M.Multiply(Py, MLy); M.Multiply(Pz, MLz); DiagonalMatrix Preconditioner = new DiagonalMatrix(N); for (int i = 0; i < N; i++) { Preconditioner.Set(i, i, 1.0 / M[i, i]); } MLy[v_pin] += consW * 0.5f; MLx[v_pin] += consW * 0.5f; MLz[v_pin] += consW * 0.5f; bool useXAsGuess = true; // preconditioned SparseSymmetricCG SolverX = new SparseSymmetricCG() { B = MLx, X = Px, MultiplyF = M.Multiply, PreconditionMultiplyF = Preconditioner.Multiply, UseXAsInitialGuess = useXAsGuess }; // initial solution SparseSymmetricCG SolverY = new SparseSymmetricCG() { B = MLy, X = Py, MultiplyF = M.Multiply, UseXAsInitialGuess = useXAsGuess }; // neither of those SparseSymmetricCG SolverZ = new SparseSymmetricCG() { B = MLz, MultiplyF = M.Multiply }; bool bx = SolverX.Solve(); bool by = SolverY.Solve(); bool bz = SolverZ.Solve(); for (int vid = 0; vid < mesh.VertexCount; ++vid) { Vector3d newV = new Vector3d(SolverX.X[vid], SolverY.X[vid], SolverZ.X[vid]); mesh.SetVertex(vid, newV); } result_meshes.Add(mesh); TestUtil.WriteDebugMeshes(result_meshes, "___CG_result.obj"); }