I’m doing a cpp + c# mixed programming to import some cpp code into Grasshopper plugins.
It is a bit painful that I always need to convert the list of vertices in Point3d first and then to a C array.
There’s a .ToFloatArray methods in Mesh.Vertices which convert the vertices into float array directly, is it possible to add a similar one for double?
I know that I can set mesh properties to store double for mesh vertices. What I want is a conversion methods.
If you have a C++ DLL called CPlusPlus.dll with the following code
extern "C" // use this to prevent C++ name mangling: C# needs to call the function by its unmangled name
{
__declspec(dllexport) void CallCFunction(ON_Mesh* pMesh)
{
// do something in C++ with the mesh's double precision verts
if (m->HasDoublePrecisionVertices())
{
ON_3dPointArray& doublePrecisionVerts = pMesh->m_dV;
}
}
}
public static class MeshExtensions
{
public static double[] ToDoubleArray(this Mesh mesh)
{
if (!mesh.Vertices.UseDoublePrecisionVertices)
return new double[0];
var rc = new double[mesh.Vertices.Count * 3];
int index = 0;
for (var i = 0; i < mesh.Vertices.Count; i++)
{
var pt = mesh.Vertices.Point3dAt(i);
rc[index++] = pt.X;
rc[index++] = pt.Y;
rc[index++] = pt.Z;
}
return rc;
}
}
You can use like this:
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
var filter = ObjectType.Mesh;
var rc = RhinoGet.GetOneObject("Select mesh", false, filter, out var objref);
if (rc != Rhino.Commands.Result.Success || null == objref)
return rc;
var mesh = objref.Mesh();
if (null == mesh || !mesh.Vertices.UseDoublePrecisionVertices)
return Result.Cancel;
var doubles = mesh.ToDoubleArray();
foreach (var d in doubles)
RhinoApp.WriteLine(d.ToString());
return Result.Success;
}
I tried to put it outside my namespace where the conversion of mesh vertices happens, but it doesn’t work.
BTW, I guess you’re the man who is in charge of the opennurbs?
I tried to build it and use it in my project somehow, but the compilation works in debug mode, not the release mode, saying
LNK1181 cannot open input file '<OPENNURBS_PUBLIC_LIBS_DIR>\bin\x64\Debug.obj'
Not sure why the release mode will try to find a Debug.obj file…
I’d put the extension class inside your namespace.
More on extension methods:
If this is the case, then you must link with the version of openNURBS that comes with Rhino, not build and link some other version into your DLL. The easiest way to do this is to build a Rhino-dependent DLL.
Mesh msh = .......; // Some mesh
using var meshRawData = msh.GetUnsafeLock();
var ptrToP3d = meshRawData.VertexPoint3dArray(out var verticeCnt);
...
But pay attention ptrToP3d is a Point3d* rather than Point3d[]. You probably want to memcpy later.
Pay attention on what you want to do here. Raw memory manipulation is quite dangerous in C# and may be slow than expected. I’d recommend C++/CLI if you are unfamliar with C#.
This will require to integrate opennurbs into my cpp project, which after trying yesterday, didn’t succeed…
The doc on the website is not very clearly written and if I follow the process, differen’t kinds of errors always occur. For instance, this:
To be honest, I don’t exactly know. Maybe you can get a pointer, but you need to make sure that the garbage collector doesn’t touch it, so you need to pin the pointer until you ar done in c++.
If you search for terms like marshalling and pointer pinning, maybe something useful turns up.
Another thing to look at is what rhino provides in the Rhino.Runtime.Interop class and the interop wrappers