/// <summary> /// Converts the provided double vector from g3 into the OpenTK variant. /// </summary> /// <param name="vector">The vector to convert from its current double variant. /// </param> /// <returns>An OpenTK vector to use in all calculations.</returns> public static Vector3 VectorConvert(g3.Vector3d vector) { return(new Vector3( Convert.ToSingle(vector.x), Convert.ToSingle(vector.y), Convert.ToSingle(vector.z) )); }
double GetNormalQuality(g3.DMesh3 mesh, g3.Vector3d target, int depth) { if (depth == 0) { return(1 - (mesh.GetTriNormal(meshIndex).Dot(target))); } double amount = GetNormalQuality(mesh, target, 0); foreach (var n in neighbors) { amount += GetNormalQuality(mesh, target, depth - 1); } return(amount); }
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); }
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 static DMesh3 MineCraft(DMesh3 mesh, int num_cells, out double scalefactor) { DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, autoBuild: true); AxisAlignedBox3d bounds = mesh.CachedBounds; double cellsize = bounds.MaxDim / num_cells; scalefactor = cellsize; 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); if (spatial.IsInside(v)) { bmp.Set(idx, true); } else { bmp.Set(idx, false); } } VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator(); voxGen.Voxels = bmp; voxGen.Generate(); DMesh3 voxMesh = voxGen.Meshes[0]; return(voxMesh); }
public static Point3d ToRhinoPoint(this g3.Vector3d v) { return(new Point3d(v.x, v.y, v.z)); }
public static Vector3d ToRhinoVector(this g3.Vector3d v) { return(new Vector3d(v.x, v.y, v.z)); }
//public static void VoronoiMesh(List<g3.PolyLine3d> mesh, out List<g3.Line3d> listLines, out List<g3.PolyLine3d> listPolylines) //{ // System.Collections.Generic.SortedDictionary<int, MeshNode> faces = new System.Collections.Generic.SortedDictionary<int, MeshNode>(); // int index = 0; // foreach (var meshFaceIndex in mesh.TriangleIndices()) // { // var frame = mesh.GetTriFrame(meshFaceIndex); // g3.Index3i neighbors = mesh.GetTriNeighbourTris(meshFaceIndex); // g3.Index3i vertex_index = mesh.GetTriangle(meshFaceIndex); // faces.Add(meshFaceIndex, new MeshNode(index++, meshFaceIndex, frame, neighbors, vertex_index)); // } // foreach (var f in faces) // { // f.Value.neighbors.Clear(); // f.Value.neighbors.Capacity = 3; // for (int i = 0; i < 3; ++i) // { // int fn = f.Value.neighbors_index[i]; // if (fn >= 0) // f.Value.neighbors.Add(faces[fn]); // } // if (f.Value.neighbors.Count < 3) // { // f.Value.locked = true; // foreach (var n in f.Value.neighbors) // n.locked = true; // } // } // outputMesh = new g3.DMesh3(g3.MeshComponents.None); // listLines = new List<g3.Line3d>(); // listPolylines = new List<g3.PolyLine3d>(); // foreach (var f in faces) // { // outputMesh.AppendVertex(f.Value.frame.Origin); // } // HashSet<int> processedPoints = new HashSet<int>(); // foreach (var f in faces) // { // for (int i = 0; i < 3; i++) // { // List<int> outputLine = new List<int>(); // if (processedPoints.Contains(f.Value.vertex_index[i])) // continue; // int checkVertex = f.Value.vertex_index[i]; // MeshNode currentFaces = f.Value; // MeshNode prevFace = null; // bool fullLoop = false; // while (true) // { // for (int j = 0; j < currentFaces.neighbors.Count; j++) // { // var neighbor = currentFaces.neighbors[j]; // if (neighbor.UsesVertex(checkVertex)) // { // if (neighbor == prevFace) // continue; // if (neighbor == f.Value) // { // fullLoop = true; // break; // Found full loop // } // outputLine.Add(neighbor.index); // prevFace = currentFaces; // currentFaces = neighbor; // j = -1; // } // } // break; // } // if (fullLoop) // { // processedPoints.Add(checkVertex); // var polyline = new g3.PolyLine3d(); // if (outputLine.Count > 2) // { // g3.Vector3d centerPoint = f.Value.frame.Origin; // foreach (var p in outputLine) // centerPoint += outputMesh.GetVertex(p); // centerPoint /= (outputLine.Count + 1); // int center = outputMesh.AppendVertex(centerPoint); // var pS = outputMesh.GetVertex(f.Value.index); // var p0 = outputMesh.GetVertex(outputLine[0]); // var pE = outputMesh.GetVertex(outputLine[outputLine.Count - 1]); // var normal = mesh.GetTriNormal(f.Value.meshIndex); // polyline.AppendVertex(pS); // polyline.AppendVertex(p0); // listLines.Add(new g3.Line3d(pS, p0 - pS)); // var n = MathUtil.Normal(centerPoint, pS, p0); // bool reverseTri = n.Dot(normal) < 0; // if (!reverseTri) // outputMesh.AppendTriangle(center, f.Value.index, outputLine[0]); // else // outputMesh.AppendTriangle(center, outputLine[0], f.Value.index); // for (int j = 0; j < outputLine.Count - 1; j++) // { // var p1 = outputMesh.GetVertex(outputLine[j]); // var p2 = outputMesh.GetVertex(outputLine[j + 1]); // listLines.Add(new g3.Line3d(p1, p2 - p1)); // polyline.AppendVertex(p2); // if (!reverseTri) // outputMesh.AppendTriangle(center, outputLine[j], outputLine[j + 1]); // else // outputMesh.AppendTriangle(center, outputLine[j + 1], outputLine[j]); // } // polyline.AppendVertex(pS); // listLines.Add(new g3.Line3d(pE, pS - pE)); // listPolylines.Add(polyline); // if (!reverseTri) // outputMesh.AppendTriangle(center, outputLine[outputLine.Count - 1], f.Value.index); // else // outputMesh.AppendTriangle(center, f.Value.index, outputLine[outputLine.Count - 1]); // } // } // } // } //} public static void VoronoiMesh(g3.DMesh3 mesh, out g3.DMesh3 outputMesh, out List <g3.Line3d> listLines, out List <g3.PolyLine3d> listPolylines) { System.Collections.Generic.SortedDictionary <int, MeshNode> faces = new System.Collections.Generic.SortedDictionary <int, MeshNode>(); int index = 0; foreach (var meshFaceIndex in mesh.TriangleIndices()) { var frame = mesh.GetTriFrame(meshFaceIndex); g3.Index3i neighbors = mesh.GetTriNeighbourTris(meshFaceIndex); g3.Index3i vertex_index = mesh.GetTriangle(meshFaceIndex); faces.Add(meshFaceIndex, new MeshNode(index++, meshFaceIndex, frame, neighbors, vertex_index)); } foreach (var f in faces) { f.Value.neighbors.Clear(); f.Value.neighbors.Capacity = 3; for (int i = 0; i < 3; ++i) { int fn = f.Value.neighbors_index[i]; if (fn >= 0) { f.Value.neighbors.Add(faces[fn]); } } if (f.Value.neighbors.Count < 3) { f.Value.locked = true; foreach (var n in f.Value.neighbors) { n.locked = true; } } } outputMesh = new g3.DMesh3(g3.MeshComponents.None); listLines = new List <g3.Line3d>(); listPolylines = new List <g3.PolyLine3d>(); foreach (var f in faces) { outputMesh.AppendVertex(f.Value.frame.Origin); } HashSet <int> processedPoints = new HashSet <int>(); foreach (var f in faces) { for (int i = 0; i < 3; i++) { List <int> outputLine = new List <int>(); if (processedPoints.Contains(f.Value.vertex_index[i])) { continue; } int checkVertex = f.Value.vertex_index[i]; MeshNode currentFaces = f.Value; MeshNode prevFace = null; bool fullLoop = false; while (true) { for (int j = 0; j < currentFaces.neighbors.Count; j++) { var neighbor = currentFaces.neighbors[j]; if (neighbor.UsesVertex(checkVertex)) { if (neighbor == prevFace) { continue; } if (neighbor == f.Value) { fullLoop = true; break; // Found full loop } outputLine.Add(neighbor.index); prevFace = currentFaces; currentFaces = neighbor; j = -1; } } break; } if (fullLoop) { processedPoints.Add(checkVertex); var polyline = new g3.PolyLine3d(); if (outputLine.Count > 2) { g3.Vector3d centerPoint = f.Value.frame.Origin; foreach (var p in outputLine) { centerPoint += outputMesh.GetVertex(p); } centerPoint /= (outputLine.Count + 1); int center = outputMesh.AppendVertex(centerPoint); var pS = outputMesh.GetVertex(f.Value.index); var p0 = outputMesh.GetVertex(outputLine[0]); var pE = outputMesh.GetVertex(outputLine[outputLine.Count - 1]); var normal = mesh.GetTriNormal(f.Value.meshIndex); polyline.AppendVertex(pS); polyline.AppendVertex(p0); listLines.Add(new g3.Line3d(pS, p0 - pS)); var n = MathUtil.Normal(centerPoint, pS, p0); bool reverseTri = n.Dot(normal) < 0; if (!reverseTri) { outputMesh.AppendTriangle(center, f.Value.index, outputLine[0]); } else { outputMesh.AppendTriangle(center, outputLine[0], f.Value.index); } for (int j = 0; j < outputLine.Count - 1; j++) { var p1 = outputMesh.GetVertex(outputLine[j]); var p2 = outputMesh.GetVertex(outputLine[j + 1]); listLines.Add(new g3.Line3d(p1, p2 - p1)); polyline.AppendVertex(p2); if (!reverseTri) { outputMesh.AppendTriangle(center, outputLine[j], outputLine[j + 1]); } else { outputMesh.AppendTriangle(center, outputLine[j + 1], outputLine[j]); } } polyline.AppendVertex(pS); listLines.Add(new g3.Line3d(pE, pS - pE)); listPolylines.Add(polyline); if (!reverseTri) { outputMesh.AppendTriangle(center, outputLine[outputLine.Count - 1], f.Value.index); } else { outputMesh.AppendTriangle(center, f.Value.index, outputLine[outputLine.Count - 1]); } } } } } }
protected virtual ProcessResult CollapseEdge(int edgeID, Vector3d vNewPos, out int collapseToV) { collapseToV = DMesh3.InvalidID; RuntimeDebugCheck(edgeID); EdgeConstraint constraint = (constraints == null) ? EdgeConstraint.Unconstrained : constraints.GetEdgeConstraint(edgeID); if (constraint.NoModifications) { return(ProcessResult.Ignored_EdgeIsFullyConstrained); } if (constraint.CanCollapse == false) { return(ProcessResult.Ignored_EdgeIsFullyConstrained); } // look up verts and tris for this edge int a = 0, b = 0, t0 = 0, t1 = 0; if (mesh.GetEdge(edgeID, ref a, ref b, ref t0, ref t1) == false) { return(ProcessResult.Failed_NotAnEdge); } bool bIsBoundaryEdge = (t1 == DMesh3.InvalidID); // look up 'other' verts c (from t0) and d (from t1, if it exists) Index3i T0tv = mesh.GetTriangle(t0); int c = IndexUtil.find_tri_other_vtx(a, b, T0tv); Index3i T1tv = (bIsBoundaryEdge) ? DMesh3.InvalidTriangle : mesh.GetTriangle(t1); int d = (bIsBoundaryEdge) ? DMesh3.InvalidID : IndexUtil.find_tri_other_vtx(a, b, T1tv); Vector3d vA = mesh.GetVertex(a); Vector3d vB = mesh.GetVertex(b); double edge_len_sqr = (vA - vB).LengthSquared; if (edge_len_sqr > MinEdgeLength * MinEdgeLength) { return(ProcessResult.Ignored_EdgeTooLong); } begin_collapse(); // check if we should collapse, and also find which vertex we should collapse to, // in cases where we have constraints/etc int collapse_to = -1; bool bCanCollapse = can_collapse_constraints(edgeID, a, b, c, d, t0, t1, out collapse_to); if (bCanCollapse == false) { return(ProcessResult.Ignored_Constrained); } // if we have a boundary, we want to collapse to boundary if (PreserveBoundary && HaveBoundary) { if (collapse_to != -1) { if ((IsBoundaryV(b) && collapse_to != b) || (IsBoundaryV(a) && collapse_to != a)) { return(ProcessResult.Ignored_Constrained); } } if (IsBoundaryV(b)) { collapse_to = b; } else if (IsBoundaryV(a)) { collapse_to = a; } } // optimization: if edge cd exists, we cannot collapse or flip. look that up here? // funcs will do it internally... // (or maybe we can collapse if cd exists? edge-collapse doesn't check for it explicitly...) ProcessResult retVal = ProcessResult.Failed_OpNotSuccessful; int iKeep = b, iCollapse = a; // if either vtx is fixed, collapse to that position if (collapse_to == b) { vNewPos = vB; } else if (collapse_to == a) { iKeep = a; iCollapse = b; vNewPos = vA; } else { vNewPos = get_projected_collapse_position(iKeep, vNewPos); } // check if this collapse will create a normal flip. Also checks // for invalid collapse nbrhood, since we are doing one-ring iter anyway. // [TODO] could we skip this one-ring check in CollapseEdge? pass in hints? if (creates_flip_or_invalid(a, b, vNewPos, t0, t1) || creates_flip_or_invalid(b, a, vNewPos, t0, t1)) { retVal = ProcessResult.Ignored_CreatesFlip; goto skip_to_end; } // lots of cases where we cannot collapse, but we should just let // mesh sort that out, right? COUNT_COLLAPSES++; DMesh3.EdgeCollapseInfo collapseInfo; MeshResult result = mesh.CollapseEdge(iKeep, iCollapse, out collapseInfo); if (result == MeshResult.Ok) { collapseToV = iKeep; mesh.SetVertex(iKeep, vNewPos); if (constraints != null) { constraints.ClearEdgeConstraint(edgeID); constraints.ClearEdgeConstraint(collapseInfo.eRemoved0); if (collapseInfo.eRemoved1 != DMesh3.InvalidID) { constraints.ClearEdgeConstraint(collapseInfo.eRemoved1); } constraints.ClearVertexConstraint(iCollapse); } OnEdgeCollapse(edgeID, iKeep, iCollapse, collapseInfo); DoDebugChecks(); retVal = ProcessResult.Ok_Collapsed; } skip_to_end: end_collapse(); return(retVal); }
public QEdge(int edge_id, QuadricError qin, Vector3d pt) { eid = edge_id; q = qin; collapse_pt = pt; }