Hi…,
is there an option for the Rhino mesher to have the mesh everywhere inside the solid without overshooting, see picture and file:
concave_meshing_request.3dm (848.2 KB)
Or does anybody know another mesher for this task?
Thanks
Michael
Hi…,
is there an option for the Rhino mesher to have the mesh everywhere inside the solid without overshooting, see picture and file:
concave_meshing_request.3dm (848.2 KB)
Or does anybody know another mesher for this task?
Thanks
Michael
I expected someone might offer a grasshopper solution for this, someone still might …?
Is this intended as a general case, rather than specifically the extruded arc section presented?
I would be interested in a solution as well.
My wish is for the general case (concave surfaces in solids), the picture and file are just for explanation.
I do not know of any mesher that does this, as mesh vertices are always exactly on the geometry being approximated with the mesh, and edges may be off the geometry.
Why do you need this, what problem are you hoping to solve?
Hi @menno,
thank you for asking. I need it for low poly meshes in a game engine. In the engine I draw further meshes on the nurbs surfaces. When the low poly meshes overshoot, my further meshes vanish or interfere with the overshooting meshes, what I don’t want.
Cheers
Michael
I think I may have an idea how to do this, but I’ll only be able to get to it next week at the earliest.
Hi Micheal, I hope you’re OK with running a script from the script editor. Please find attached the C# script that will place mesh vertices behind a surface/polysurface so that the mesh edges do not show.
Let me know if this is what you were looking for, or if you have any questions.
// #! csharp
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using Rhino;
using Rhino.Geometry;
using Rhino.Geometry.Collections;
using Rhino.Input;
using Rhino.Input.Custom;
using Rhino.DocObjects;
using Rhino.Commands;
var doc = RhinoDoc.ActiveDoc;
var tol = doc.ModelAbsoluteTolerance;
// get the input mesh
var res = RhinoGet.GetOneObject("Select mesh", false, ObjectType.Mesh, out var mRef);
if (res != Result.Success)
return;
Mesh m = mRef.Mesh();
// get the background brep
res = RhinoGet.GetOneObject("Select background (poly)surface", false, ObjectType.PolysrfFilter | ObjectType.Surface, out var sRef);
if (res != Result.Success)
return;
Brep b = sRef.Brep();
// create vertex offset array
Vector3f[] vertexOffsets = new Vector3f[m.TopologyVertices.Count];
for(int i = 0; i < m.TopologyVertices.Count; ++i)
{
vertexOffsets[i] = Vector3f.Zero; // initialize offsets to zero
}
for(int i = 0; i < m.TopologyEdges.Count; ++i)
{
// get the closest point on the Brep for the edge mid point
IndexPair ij = m.TopologyEdges.GetTopologyVertices(i);
Point3f vi = m.TopologyVertices[ij.I];
Point3f vj = m.TopologyVertices[ij.J];
Point3d mid = (new Point3d(vi) + new Point3d(vj))/2.0;
if (!b.ClosestPoint(mid, out Point3d cp, out ComponentIndex ci, out double s, out double t, double.MaxValue, out _))
return;
// determine if the edge falls outside the brep. The brep may not be closed, so
// use a comparison of local normal vector with the offset vector
bool mustOffset = false;
Vector3d offsetDirection = Vector3d.Zero;
Vector3d ni = Vector3d.Zero, nj = Vector3d.Zero;
// hit a single face:
if (ci.ComponentIndexType == ComponentIndexType.BrepFace)
{
BrepFace f= b.Faces[ci.Index];
Point3d closest = f.PointAt(s, t);
Vector3d offset = mid - closest;
Vector3d normal = f.NormalAt(s, t);
if (offset*normal > tol) // if normal and offset direction are pointing more or less in the same direction
{
mustOffset = true;
offsetDirection = -offset*(1+tol);
f.ClosestPoint(vi, out s, out t);
ni = f.NormalAt(s, t);
f.ClosestPoint(vj, out s, out t);
nj = f.NormalAt(s, t);
}
}
else if (ci.ComponentIndexType == ComponentIndexType.BrepEdge)
{
// hit an edge, compare the faces adjacent to the edge
BrepEdge edge = b.Edges[ci.Index];
int[] adjacentFaces = edge.AdjacentFaces();
for(int j = 0; j < adjacentFaces.Length; ++j)
{
BrepFace f = b.Faces[adjacentFaces[j]];
if (f.ClosestPoint(mid, out double u, out double v))
{
Point3d closest = f.PointAt(u, v);
Vector3d offset = mid - closest;
Vector3d normal = f.NormalAt(u, v);
if (offset*normal > tol)
{
mustOffset = true;
offsetDirection = -offset*(1+tol);
f.ClosestPoint(vi, out u, out v);
ni = f.NormalAt(u, v);
f.ClosestPoint(vj, out u, out v);
nj = f.NormalAt(u, v);
}
}
}
}
// reverse the normals on the surface at the vertices i and j
// so that their direction is pointing in the correct direction
ni.Reverse();
nj.Reverse();
if (mustOffset)
{
if (ni.Length > 0)
{
// determine the length to offset the vertex along its local normal
// to ensure that the edge mid is behind the surface
double alpha = Vector3d.VectorAngle(ni, offsetDirection);
ni.Unitize();
ni *= offsetDirection.Length/Math.Cos(alpha);
if (vertexOffsets[ij.I].Length < ni.Length){
vertexOffsets[ij.I] = new Vector3f((float)ni.X, (float)ni.Y, (float)ni.Z);
}
}
if (nj.Length > 0)
{
double alpha = Vector3d.VectorAngle(nj, offsetDirection);
nj.Unitize();
nj *= offsetDirection.Length/Math.Cos(alpha);
if (vertexOffsets[ij.J].Length < nj.Length){
vertexOffsets[ij.J] = new Vector3f((float)nj.X, (float)nj.Y, (float)nj.Z);
}
}
}
}
for(int i = 0; i < m.TopologyVertices.Count; ++i)
{
int[] vis = m.TopologyVertices.MeshVertexIndices(i);
for(int j = 0; j < vis.Length; ++j)
{
Vector3f o = vertexOffsets[i];
m.Vertices[vis[j]] += o;
}
}
doc.Objects.Replace(mRef, m);
Hi @menno,
wow, thank you very much.
I’ve tried a torus segment. It pulls the mesh, but not enough. Please take a look:
concave_meshing_request.3dm (187.8 KB)
Thanks again
Michael
Ah, I see. Can you first try to triangulate your mesh - I think that shoud go a long way in making it better. In the mean time I’ll try to see if I can improve this a bit to get double curved surface working better.
Hi @menno,
_TriangulateMesh did it. Perfect, this is a great solution for my needs.
Thank you very much again
Michael
P.S.: When you are in Munich, visit us, I owe you something.
Great that it worked with triangulated mesh. I’ll keep in mind next time I’m in Munich, would be nice to drop by and see what you’re working on