Support multimaterials on one mesh #44

Merged
Bogdan Nagirniak merged 11 commits from BLEN-417 into hydra-render 2023-05-24 07:07:39 +02:00
4 changed files with 46 additions and 31 deletions
Showing only changes of commit fc4da28bb9 - Show all commits

View File

@ -26,7 +26,7 @@ pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
MeshData *m_data = mesh_data(id); MeshData *m_data = mesh_data(id);
return m_data->mesh_topology(); return m_data->mesh_topology(id);
} }
pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id) pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id)
@ -96,7 +96,7 @@ pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(
pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id) pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", rprim_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", rprim_id.GetText());
return mesh_data(rprim_id)->material_id(); return mesh_data(rprim_id)->material_id(rprim_id);
} }
pxr::VtValue BlenderSceneDelegate::GetMaterialResource(pxr::SdfPath const &id) pxr::VtValue BlenderSceneDelegate::GetMaterialResource(pxr::SdfPath const &id)
@ -125,7 +125,7 @@ bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
bool BlenderSceneDelegate::GetDoubleSided(pxr::SdfPath const &id) bool BlenderSceneDelegate::GetDoubleSided(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
return mesh_data(id)->double_sided(); return mesh_data(id)->double_sided(id);
} }
pxr::HdCullStyle BlenderSceneDelegate::GetCullStyle(pxr::SdfPath const &id) pxr::HdCullStyle BlenderSceneDelegate::GetCullStyle(pxr::SdfPath const &id)
@ -510,12 +510,8 @@ void BlenderSceneDelegate::remove_unused_objects()
std::set<pxr::SdfPath> available_materials; std::set<pxr::SdfPath> available_materials;
for (auto &it : objects_) { for (auto &it : objects_) {
MeshData *m_data = dynamic_cast<MeshData *>(it.second.get()); MeshData *m_data = dynamic_cast<MeshData *>(it.second.get());
if (!m_data) { if (m_data) {
continue; m_data->available_materials(available_materials);
}
pxr::SdfPath mat_id = m_data->material_id();
if (!mat_id.IsEmpty()) {
available_materials.insert(mat_id);
} }
} }
for (auto &it : instancers_) { for (auto &it : instancers_) {

View File

@ -214,10 +214,7 @@ void InstancerData::check_remove(std::set<std::string> &available_objects)
void InstancerData::available_materials(std::set<pxr::SdfPath> &paths) const void InstancerData::available_materials(std::set<pxr::SdfPath> &paths) const
{ {
for (auto &it : mesh_instances_) { for (auto &it : mesh_instances_) {
pxr::SdfPath mat_id = ((MeshData *)it.second.data.get())->material_id(); ((MeshData *)it.second.data.get())->available_materials(paths);
if (!mat_id.IsEmpty()) {
paths.insert(mat_id);
}
} }
} }

View File

@ -125,9 +125,9 @@ bool MeshData::update_visibility()
return ret; return ret;
} }
pxr::HdMeshTopology MeshData::mesh_topology() const pxr::HdMeshTopology MeshData::mesh_topology(pxr::SdfPath const &id) const
{ {
const MaterialMesh &m = material_meshes_[0]; const SubMesh &m = sub_meshes_[0];
return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none, return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
pxr::HdTokens->rightHanded, pxr::HdTokens->rightHanded,
m.face_vertex_counts, m.face_vertex_counts,
@ -157,18 +157,18 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(
return primvars; return primvars;
} }
pxr::SdfPath MeshData::material_id() const pxr::SdfPath MeshData::material_id(pxr::SdfPath const &id) const
{ {
const MaterialMesh &m = material_meshes_[0]; const SubMesh &m = sub_meshes_[0];
if (!m.mat_data) { if (!m.mat_data) {
return pxr::SdfPath(); return pxr::SdfPath();
} }
return m.mat_data->prim_id; return m.mat_data->prim_id;
} }
bool MeshData::double_sided() const bool MeshData::double_sided(pxr::SdfPath const &id) const
{ {
const MaterialMesh &m = material_meshes_[0]; const SubMesh &m = sub_meshes_[0];
if (m.mat_data) { if (m.mat_data) {
return m.mat_data->double_sided; return m.mat_data->double_sided;
} }
@ -177,7 +177,7 @@ bool MeshData::double_sided() const
void MeshData::update_double_sided(MaterialData *mat_data) void MeshData::update_double_sided(MaterialData *mat_data)
{ {
MaterialMesh &m = material_meshes_[0]; SubMesh &m = sub_meshes_[0];
if (m.mat_data == mat_data) { if (m.mat_data == mat_data) {
ID_LOG(2, ""); ID_LOG(2, "");
@ -186,6 +186,15 @@ void MeshData::update_double_sided(MaterialData *mat_data)
} }
} }
void MeshData::available_materials(std::set<pxr::SdfPath> &paths) const
{
for (auto &m : sub_meshes_) {
if (m.mat_data && !m.mat_data->prim_id.IsEmpty()) {
paths.insert(m.mat_data->prim_id);
}
}
}
void MeshData::write_mesh(Mesh *mesh) void MeshData::write_mesh(Mesh *mesh)
{ {
vertices_.clear(); vertices_.clear();
@ -206,10 +215,12 @@ void MeshData::write_mesh(Mesh *mesh)
} }
/* material meshes */ /* material meshes */
material_meshes_.clear(); sub_meshes_.clear();
int mat_count = BKE_object_material_count_eval((Object *)id); int mat_count = BKE_object_material_count_eval((Object *)id);
for (int i = 0; i < std::max(mat_count, 1); ++i) { for (int i = 0; i < std::max(mat_count, 1); ++i) {
material_meshes_.push_back(MaterialMesh()); SubMesh m;
m.mat_index = i;
sub_meshes_.push_back(m);
} }
const int *material_indices = BKE_mesh_material_indices(mesh); const int *material_indices = BKE_mesh_material_indices(mesh);
@ -220,13 +231,22 @@ void MeshData::write_mesh(Mesh *mesh)
int mat_ind = material_indices ? material_indices[looptri_polys[i]] : 0; int mat_ind = material_indices ? material_indices[looptri_polys[i]] : 0;
const MLoopTri &lt = looptris[i]; const MLoopTri &lt = looptris[i];
MaterialMesh &m = material_meshes_[mat_ind]; SubMesh &m = sub_meshes_[mat_ind];
m.face_vertex_counts.push_back(3); m.face_vertex_counts.push_back(3);
m.face_vertex_indices.push_back(corner_verts[lt.tri[0]]); m.face_vertex_indices.push_back(corner_verts[lt.tri[0]]);
m.face_vertex_indices.push_back(corner_verts[lt.tri[1]]); m.face_vertex_indices.push_back(corner_verts[lt.tri[1]]);
m.face_vertex_indices.push_back(corner_verts[lt.tri[2]]); m.face_vertex_indices.push_back(corner_verts[lt.tri[2]]);
} }
for (auto it = sub_meshes_.begin(); it != sub_meshes_.end();) {
if (it->face_vertex_counts.empty()) {
it = sub_meshes_.erase(it);
}
else {
++it;
}
}
write_normals(mesh); write_normals(mesh);
write_uv_maps(mesh); write_uv_maps(mesh);
write_material(); write_material();
@ -235,12 +255,12 @@ void MeshData::write_mesh(Mesh *mesh)
void MeshData::write_material() void MeshData::write_material()
{ {
Object *object = (Object *)id; Object *object = (Object *)id;
for (int i = 0; i < material_meshes_.size(); ++i) { for (int i = 0; i < sub_meshes_.size(); ++i) {
MaterialMesh &m = material_meshes_[i]; SubMesh &m = sub_meshes_[i];
if (m.face_vertex_counts.empty()) { if (m.face_vertex_counts.empty()) {
continue; continue;
} }
Material *mat = BKE_object_material_get_eval(object, i); Material *mat = BKE_object_material_get_eval(object, m.mat_index);
if (!mat) { if (!mat) {
m.mat_data = nullptr; m.mat_data = nullptr;
continue; continue;

View File

@ -14,9 +14,10 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class MeshData : public ObjectData { class MeshData : public ObjectData {
struct MaterialMesh { struct SubMesh {
pxr::VtIntArray face_vertex_counts; pxr::VtIntArray face_vertex_counts;
pxr::VtIntArray face_vertex_indices; pxr::VtIntArray face_vertex_indices;
int mat_index = 0;
MaterialData *mat_data = nullptr; MaterialData *mat_data = nullptr;
}; };
@ -31,11 +32,12 @@ class MeshData : public ObjectData {
pxr::VtValue get_data(pxr::TfToken const &key) const override; pxr::VtValue get_data(pxr::TfToken const &key) const override;
bool update_visibility() override; bool update_visibility() override;
pxr::HdMeshTopology mesh_topology() const; pxr::HdMeshTopology mesh_topology(pxr::SdfPath const &id) const;
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const; pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const;
pxr::SdfPath material_id() const; pxr::SdfPath material_id(pxr::SdfPath const &id) const;
bool double_sided() const; bool double_sided(pxr::SdfPath const &id) const;
void update_double_sided(MaterialData *mat_data); void update_double_sided(MaterialData *mat_data);
void available_materials(std::set<pxr::SdfPath> &paths) const;
pxr::HdCullStyle cull_style = pxr::HdCullStyleBackUnlessDoubleSided; pxr::HdCullStyle cull_style = pxr::HdCullStyleBackUnlessDoubleSided;
@ -49,7 +51,7 @@ class MeshData : public ObjectData {
pxr::VtVec2fArray uvs_; pxr::VtVec2fArray uvs_;
pxr::VtVec3fArray normals_; pxr::VtVec3fArray normals_;
std::vector<MaterialMesh> material_meshes_; std::vector<SubMesh> sub_meshes_;
}; };
} // namespace blender::render::hydra } // namespace blender::render::hydra