Skip to content

Commit

Permalink
Fix for Issue #5924:
Browse files Browse the repository at this point in the history
Changed TriangleMesh::materials_ to be a std::vector<std::pair<std::string, Material>> so that the order of materials when loading a mesh is respected.
Using the unordered map caused issues when a Default Material and a texture were loaded and the texture would end up as the second material in the iterator.
Now TriangleMesh::triangle_material_ids_ will indicate what material index should be used.
A warning is given when passing a TriangleMesh to the visualizer and more than one material index is found, and the minimum value found in TriangleMesh::triangle_material_ids_ is used.
If no triangle_material_ids_ exist then the first material in the order they are loaded will be used.
  • Loading branch information
dbs4261 committed Apr 20, 2023
1 parent a5be78c commit a09c8bc
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 13 deletions.
2 changes: 1 addition & 1 deletion cpp/open3d/geometry/TriangleMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,7 @@ class TriangleMesh : public MeshBase {
std::unordered_map<std::string, Image> additionalMaps;
};

std::unordered_map<std::string, Material> materials_;
std::vector<std::pair<std::string, Material>> materials_;

/// List of material ids.
std::vector<int> triangle_material_ids_;
Expand Down
11 changes: 6 additions & 5 deletions cpp/open3d/io/file_format/FileASSIMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,13 @@ bool ReadTriangleMeshUsingASSIMP(
}

// Now load the materials
mesh.materials_.resize(scene->mNumMaterials);
for (size_t i = 0; i < scene->mNumMaterials; ++i) {
auto* mat = scene->mMaterials[i];

// create material structure to match this name
auto& mesh_material =
mesh.materials_[std::string(mat->GetName().C_Str())];
// Set the material structure to match this name
auto& mesh_material = mesh.materials_[i].second;
mesh.materials_[i].first = mat->GetName().C_Str();

using MaterialParameter =
geometry::TriangleMesh::Material::MaterialParameter;
Expand Down Expand Up @@ -277,9 +278,9 @@ bool ReadTriangleMeshUsingASSIMP(

// For legacy visualization support
if (mesh_material.albedo) {
mesh.textures_.push_back(*mesh_material.albedo->FlipVertical());
mesh.textures_.emplace_back(*mesh_material.albedo->FlipVertical());
} else {
mesh.textures_.push_back(geometry::Image());
mesh.textures_.emplace_back();
}
}

Expand Down
7 changes: 5 additions & 2 deletions cpp/open3d/io/file_format/FileOBJ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,11 @@ bool ReadTriangleMeshFromOBJ(const std::string& filename,
using MaterialParameter =
geometry::TriangleMesh::Material::MaterialParameter;

for (auto& material : materials) {
auto& meshMaterial = mesh.materials_[material.name];
mesh.materials_.resize(materials.size());
for (std::size_t i = 0; i < materials.size(); ++i) {
auto& material = materials[i];
mesh.materials_[i].first = material.name;
auto& meshMaterial = mesh.materials_[i].second;

meshMaterial.baseColor = MaterialParameter::CreateRGB(
material.diffuse[0], material.diffuse[1], material.diffuse[2]);
Expand Down
23 changes: 18 additions & 5 deletions cpp/open3d/visualization/visualizer/O3DVisualizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -941,11 +941,24 @@ struct O3DVisualizer::Impl {

// Finally assign material properties if geometry is a triangle mesh
if (tmesh && tmesh->materials_.size() > 0) {
// Only a single material is supported for TriangleMesh so we
// just grab the first one we find. Users should be using
// TriangleMeshModel if they have a model with multiple
// materials.
auto &mesh_material = tmesh->materials_.begin()->second;
std::size_t material_index;
if (tmesh->HasTriangleMaterialIds()) {
auto minmax_it = std::minmax_element(
tmesh->triangle_material_ids_.begin(),
tmesh->triangle_material_ids_.end());
if (*minmax_it.first != *minmax_it.second) {
utility::LogWarning(
"Only a single material is "
"supported for TriangleMesh visualization, "
"only the first referenced material will be "
"used. Use TriangleMeshModel if more than one "
"material is required.");
}
material_index = *minmax_it.first;
} else {
material_index = 0;
}
auto &mesh_material = tmesh->materials_[material_index].second;
mat.base_color = {mesh_material.baseColor.r(),
mesh_material.baseColor.g(),
mesh_material.baseColor.b(),
Expand Down

0 comments on commit a09c8bc

Please sign in to comment.