Reading material texture using OpenNURBS

Dear Sir / Madame,

While iterating through the objects of a 3dm file, I’m trying to obtain the texture associated with a material assigned to some object, but I don’t see a way to achieve this.

The code I’m using is:

auto file = ON::OpenFile("...", "rb");
auto archive = ON_BinaryFile{ON::archive_mode::read3dm, file};
auto model = ONX_Model{};

auto it = ONX_ModelComponentIterator{model, ON_ModelComponent::Type::ModelGeometry};
for (const auto *model_component = it.FirstComponent(); model_component; model_component = it.NextComponent()) {
    const auto geometry = ON_ModelGeometryComponent::Cast(model_component)->Geometry();
    const auto attributes = model_geometry->Attributes(nullptr);
    const auto mesh = ON_Mesh::Cast(geometry);

    if (!mesh) continue;
    if (attributes->m_name.CompareNoCase(id) != 0) continue;

    const auto pMaterial = model.RenderMaterialFromAttributes(*attributes);
    const auto material = ON_Material::Cast(pMaterial.ModelComponent());

    const auto texture_id = material->FindTexture(0, ON_Texture::TYPE::bitmap_texture);
    assert(texture_id >= 0);

In the above piece of code, the assertion fails, indicating it couldn’t find any textures, whereas the object being iterated does have a texture assigned. Also, the m_textures table seems to be empty.

Is there another way how I can access the texture information while reading a 3dm file?

Kind regards,
Erik Valkering

Hi @e.valkering,

This seems to work here. Let me know if you find otherwise.

ONX_ModelComponentIterator it(model, ON_ModelComponent::Type::ModelGeometry);
const ON_ModelComponent* model_component = nullptr;
for (model_component = it.FirstComponent(); nullptr != model_component; model_component = it.NextComponent())
  const ON_ModelGeometryComponent* model_geometry = ON_ModelGeometryComponent::Cast(model_component);
  if (nullptr != model_geometry)
    const ON_3dmObjectAttributes* attributes = model_geometry->Attributes(nullptr);
    if (nullptr != attributes)
      const ON_ModelComponentReference& render_material_ref = model.RenderMaterialFromAttributes(*attributes);
      const ON_Material* material = ON_Material::FromModelComponentRef(render_material_ref, nullptr);
      if (nullptr != material)
        const int texture_index = material->FindTexture(nullptr, ON_Texture::TYPE::bitmap_texture, ON_UNSET_INT_INDEX);
        if (texture_index >= 0)
          ON_wString texture_path = material->m_textures[texture_index].m_image_file_reference.FullPath();
          // TODO...

– Dale

Hi @dale, that works like a charm. Thanks a lot!