Hello,
I have just started using OpenNURBS to read 3dm models into my (C++) application. Naturally, getting started with a new library takes some time, but I am currently trying to figure out how to properly read the instanced geometry.
I am able to read non-instanced geometry, but the instances do not receive the correct transform; they remain at the origin. I started from this example: Rhino - Traversing Instance Definitions and used the m_xform in the ON_InstanceRef, but I must be doing something wrong. Does the transform need to be applied recursively, or is it already in world space?
And the geometry is not a problem, I am getting the geometry (although it is hard to tell whether I get the X instances, or only get the shape once, since they are not transformed.).
This is (a part of) my code for dealing with the instances:
void ProcessInstances(...)
{
ONX_ModelComponentIterator it(model, ON_ModelComponent::Type::InstanceDefinition);
for(ON_ModelComponentReference mcr = it.FirstComponentReference(); false == mcr.IsEmpty(); mcr = it.NextComponentReference())
{
const ON_ModelComponent* modelComponent = mcr.ModelComponent();
if(CheckComponent(modelComponent, ...))
{
const ON_InstanceDefinition* idef = ON_InstanceDefinition::Cast(modelComponent);
if(nullptr != idef)
{
ProcessInstanceDefinition(idef->Id(), ON_Xform::IdentityTransformation);
}
}
}
}
void ProcessInstanceDefinition(const ON_UUID& idef_id, ON_Xform transform)
{
const ON_ModelComponentReference& idef_component_ref = model.ComponentFromId(ON_ModelComponent::Type::InstanceDefinition, idef_id);
const ON_InstanceDefinition* idef = ON_InstanceDefinition::Cast(idef_component_ref.ModelComponent());
if(idef)
{
const ON_SimpleArray<ON_UUID>& geometry_id_list = idef->InstanceGeometryIdList();
const int geometry_id_count = geometry_id_list.Count();
for(int i = 0; i < geometry_id_count; i++)
{
const ON_ModelComponentReference& model_component_ref = model.ComponentFromId(ON_ModelComponent::Type::ModelGeometry, geometry_id_list[i]);
const ON_ModelGeometryComponent* model_geometry = ON_ModelGeometryComponent::Cast(model_component_ref.ModelComponent());
if(nullptr != model_geometry)
{
const ON_Geometry* geometry = model_geometry->Geometry(nullptr);
if(nullptr != geometry)
{
const ON_InstanceRef* iref = ON_InstanceRef::Cast(geometry);
if(iref)
{
ProcessInstanceDefinition(iref->m_instance_definition_uuid, iref->m_xform);
}
else
{
ProcessGeometryComponent(geometry, transform);
}
}
}
}
}
}
void ProcessGeometryComponent(const ON_Geometry* geom, ON_Xform transform)
{
// Only handle BREPs for now... Other types later
ON_Brep* brep = geom->BrepForm();
if(brep)
{
brep->Transform(transform);
brep->ShrinkSurfaces();
int numFaces = brep->m_F.Count();
for(int f = 0; f < numFaces; ++f)
{
// Process faces...
}
}
}
What I would like, is to just get all the geometry for now and instanced at the correct transform, I don’t need to use instancing in my application yet, and right now it is really about understanding the transforms OpenNURBS uses as well as the instancing mechanic.
EDIT: It seems that some transforms are being applied, but not all. I think it has to do with nesting (not sure what this is called in Rhino). So, for example, I have some instanced objects that are transformed into place w.r.t. their parent, but then this group (which is also instanced) is not transformed.
Thank you!
Nathaniël