ON_SubD conversion to ON_Mesh

Dear all,

I would need of a c++ example capable to convert an ON_SubD object to an ON_Mesh object, using the ON_MeshParameters.

At the moment I discovered function

CRhinoCommand::result RhinoMeshObjects( 
          const ON_SimpleArray< const CRhinoObject* >& objects,
          ON_MeshParameters& mp,
          int& ui_style,
          ON_ClassArray< CRhinoObjectMesh >& meshes
          );

but it doesn’t suit well to me.
It correctly works on main thread (e.g. into a Rhino command) but it does not in working threads.
It freezes the application.

It would be nice to have a single function capable to convert any type of geometry supported by Rhino into an ON_Mesh, but also a specific function for SubD would be fine.

Best regards,
Alberto

Hi @margari,

Use ON_SubD::GetSurfaceMesh.

– Dale

Hello @dale,
thank you.

  1. How can I convert a specific ON_MeshParameters into a ON_SubDDisplayParameters?
  2. Doesn’t exist a single generic function capable to convert any type of geometry supported by Rhino into an ON_Mesh?
  3. I wrote the following piece of code, but I would need a review please.
    – What are the pros and cons of my solution and yours?
    – Can you confirm that CRhinoObjectRef::Brep() returns a brep pointer also for any subd, and not only for breps, a surfaces, or edges?
    – Where is stored the brep pointed by its returned value? Into the CRhinoObject? I need to know how long the returned pointer will remain valid.
    – Since CRhinoObjectRef::Brep() is const, I suppose the brep is not computed by that function. Does it mean that any subd, brep, surface and edge internally contain a brep representation?
    – What is a proxy brep? extrusions and subds return always a proxy brep?
// Input parameters
const ON_MeshParameters in_mesh_params;
const CRhinoObject* in_object = nullptr;
ON_SimpleArray<ON_Mesh*> out_mesh_list;

const CRhinoObjRef obj_ref(in_object);

/*
Description:
  If the referenced geometry is a brep, a surface, or an edge,
  this returns the brep.
Returns:
  brep or NULL.
See Also:
  CRhinoObjectRef::Geometry
  CRhinoObjectRef::GeometryType
Remarks:
  Note that the brep may be a proxy brep from an extrusion or subds.
  This has been the case since 2010 for extrusions and always
  has happened for subds.
*/
const ON_Brep* brep = obj_ref.Brep();
if (brep != nullptr)
{
	obj_ref.Brep()->CreateMesh(in_mesh_params, out_mesh_list);
}

Thank you,
@margari

Hi @margari,

ON_MeshParameters mp;
ON_SubDDisplayParameters subd_mp = mp.SubDDisplayParameters();

RhinoMeshObjects will mesh any Rhino object. But it is not thread-safe as you’ve determined.

I’m more inclined to do something like this:

ON_MeshParameters mp;
ON_SimpleArray<ON_Mesh*> meshes;

const CRhinoObject* in_object = GetMyMeshableObject();
const ON_Geometry* geometry = in_object->Geometry();

for (;;)
{
  const ON_Brep* brep = ON_Brep::Cast(geometry);
  if (nullptr != brep)
  {
    brep->CreateMesh(mp, meshes);
    break;
  }

  const ON_Surface* surface = ON_Surface::Cast(geometry);
  if (nullptr != surface)
  {
    ON_Mesh* mesh = surface->CreateMesh(mp);
    if (nullptr != mesh)
      meshes.Append(mesh);
    break;
  }

  const ON_Extrusion* extrusion = ON_Extrusion::Cast(geometry);
  if (nullptr != extrusion)
  {
    ON_Mesh* mesh = extrusion->CreateMesh(mp);
    if (nullptr != mesh)
      meshes.Append(mesh);
    break;
  }

  const ON_SubD* subd = ON_SubD::Cast(geometry);
  if (nullptr != subd)
  {
    ON_SubDDisplayParameters subd_mp = mp.SubDDisplayParameters();
    ON_Mesh* mesh = subd->GetSurfaceMesh(subd_mp, nullptr);
    if (nullptr != mesh)
    {
      if (1 == mp.FaceType())
        mesh->ConvertQuadsToTriangles();
      meshes.Append(mesh);
    }
    break;
  }

  break;
}

– Dale