diff --git a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc index 264a8d43b6ec..a424b54e11e1 100644 --- a/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc +++ b/source/blender/render/hydra/scene_delegate/blender_scene_delegate.cc @@ -23,7 +23,7 @@ pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id { CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); 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) @@ -46,6 +46,10 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id) pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key) { CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", id.GetText(), key.GetText()); + MeshData *m_data = mesh_data(id); + if (m_data) { + return m_data->get_data(id, key); + } ObjectData *obj_data = object_data(id); if (obj_data) { return obj_data->get_data(key); @@ -93,7 +97,7 @@ pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors( pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id) { 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) @@ -122,7 +126,7 @@ bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id) bool BlenderSceneDelegate::GetDoubleSided(pxr::SdfPath const &id) { 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) @@ -134,7 +138,7 @@ pxr::HdCullStyle BlenderSceneDelegate::GetCullStyle(pxr::SdfPath const &id) pxr::SdfPath BlenderSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id) { CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", prim_id.GetText()); - InstancerData *i_data = instancer_data(prim_id.GetParentPath()); + InstancerData *i_data = instancer_data(prim_id, true); if (i_data) { return i_data->prim_id; } @@ -240,11 +244,12 @@ pxr::SdfPath BlenderSceneDelegate::world_prim_id() const ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id) const { - auto it = objects_.find(id); + pxr::SdfPath p_id = (id.GetName().find("SM_") == 0) ? id.GetParentPath() : id; + auto it = objects_.find(p_id); if (it != objects_.end()) { return it->second.get(); } - InstancerData *i_data = instancer_data(id, true); + InstancerData *i_data = instancer_data(p_id, true); if (i_data) { return i_data->object_data(id); } @@ -382,7 +387,6 @@ void BlenderSceneDelegate::check_updates() data.only_updated = true; ITER_BEGIN (DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) { - CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "Update: %s [%s]", @@ -516,12 +520,8 @@ void BlenderSceneDelegate::remove_unused_objects() std::set available_materials; for (auto &it : objects_) { MeshData *m_data = dynamic_cast(it.second.get()); - if (!m_data) { - continue; - } - pxr::SdfPath mat_id = m_data->material_id(); - if (!mat_id.IsEmpty()) { - available_materials.insert(mat_id); + if (m_data) { + m_data->available_materials(available_materials); } } for (auto &it : instancers_) { diff --git a/source/blender/render/hydra/scene_delegate/instancer.cc b/source/blender/render/hydra/scene_delegate/instancer.cc index 28198b3e630c..1a60741bb1b5 100644 --- a/source/blender/render/hydra/scene_delegate/instancer.cc +++ b/source/blender/render/hydra/scene_delegate/instancer.cc @@ -36,7 +36,7 @@ bool InstancerData::is_supported(Object *object) void InstancerData::init() { ID_LOG(2, ""); - set_instances(); + write_instances(); } void InstancerData::insert() @@ -68,7 +68,7 @@ void InstancerData::update() (object->data && ((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) || id->recalc & ID_RECALC_TRANSFORM) { - set_instances(); + write_instances(); scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty( prim_id, pxr::HdChangeTracker::AllDirty); } @@ -92,8 +92,9 @@ bool InstancerData::update_visibility() change_tracker.MarkInstancerDirty(prim_id, pxr::HdChangeTracker::DirtyVisibility); for (auto &it : mesh_instances_) { it.second.data->visible = visible; - change_tracker.MarkRprimDirty(it.second.data->prim_id, - pxr::HdChangeTracker::DirtyVisibility); + for (auto &p : it.second.data->submesh_paths()) { + change_tracker.MarkRprimDirty(p, pxr::HdChangeTracker::DirtyVisibility); + } } char name[16]; for (auto &it : light_instances_) { @@ -109,9 +110,9 @@ bool InstancerData::update_visibility() pxr::GfMatrix4d InstancerData::get_transform(pxr::SdfPath const &id) const { - if (id.GetPathElementCount() == 4) { - const auto &inst = light_instances_.find(id.GetParentPath())->second; - return inst.transforms[light_prim_id_index(id)]; + LightInstance *l_inst = light_instance(id); + if (l_inst) { + return l_inst->transforms[light_prim_id_index(id)]; } /* Mesh instance transform must be identity */ @@ -131,18 +132,18 @@ pxr::HdPrimvarDescriptorVector InstancerData::primvar_descriptors( pxr::VtIntArray InstancerData::indices(pxr::SdfPath const &id) const { - return mesh_instances_.find(id)->second.indices; + return mesh_instance(id)->indices; } ObjectData *InstancerData::object_data(pxr::SdfPath const &id) const { - auto m_it = mesh_instances_.find(id); - if (m_it != mesh_instances_.end()) { - return m_it->second.data.get(); + MeshInstance *m_inst = mesh_instance(id); + if (m_inst) { + return m_inst->data.get(); } - auto l_it = light_instances_.find(id.GetParentPath()); - if (l_it != light_instances_.end()) { - return l_it->second.data.get(); + LightInstance *l_inst = light_instance(id); + if (l_inst) { + return l_inst->data.get(); } return nullptr; } @@ -151,7 +152,9 @@ pxr::SdfPathVector InstancerData::prototypes() const { pxr::SdfPathVector paths; for (auto &it : mesh_instances_) { - paths.push_back(it.first); + for (auto &p : it.second.data->submesh_paths()) { + paths.push_back(p); + } } return paths; } @@ -159,25 +162,25 @@ pxr::SdfPathVector InstancerData::prototypes() const void InstancerData::check_update(Object *object) { pxr::SdfPath path = object_prim_id(object); - auto m_it = mesh_instances_.find(path); - if (m_it != mesh_instances_.end()) { - m_it->second.data->update(); + MeshInstance *m_inst = mesh_instance(path); + if (m_inst) { + m_inst->data->update(); - if (m_it->second.data->id->recalc & ID_RECALC_TRANSFORM) { - set_instances(); + if (m_inst->data->id->recalc & ID_RECALC_TRANSFORM) { + write_instances(); scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty( prim_id, pxr::HdChangeTracker::AllDirty); } return; } - auto l_it = light_instances_.find(path); - if (l_it != light_instances_.end()) { - Object *obj = (Object *)l_it->second.data->id; + LightInstance *l_inst = light_instance(path); + if (l_inst) { + Object *obj = (Object *)l_inst->data->id; if (obj->id.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY) || ((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY) { - set_instances(); + write_instances(); } return; } @@ -196,7 +199,7 @@ void InstancerData::check_remove(std::set &available_objects) ret = true; } if (ret) { - set_instances(); + write_instances(); scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty( prim_id, pxr::HdChangeTracker::AllDirty); } @@ -216,16 +219,13 @@ void InstancerData::check_remove(std::set &available_objects) void InstancerData::available_materials(std::set &paths) const { for (auto &it : mesh_instances_) { - pxr::SdfPath mat_id = ((MeshData *)it.second.data.get())->material_id(); - if (!mat_id.IsEmpty()) { - paths.insert(mat_id); - } + ((MeshData *)it.second.data.get())->available_materials(paths); } } void InstancerData::update_as_parent() { - set_instances(); + write_instances(); scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty( prim_id, pxr::HdChangeTracker::AllDirty); } @@ -259,7 +259,7 @@ int InstancerData::light_prim_id_index(pxr::SdfPath const &id) const return index; } -void InstancerData::set_instances() +void InstancerData::write_instances() { mesh_transforms_.clear(); for (auto &it : mesh_instances_) { @@ -279,31 +279,23 @@ void InstancerData::set_instances() pxr::SdfPath p_id = object_prim_id(ob); if (ob->type == OB_LAMP) { - LightInstance *inst; - auto it = light_instances_.find(p_id); - if (it == light_instances_.end()) { + LightInstance *inst = light_instance(p_id); + if (!inst) { inst = &light_instances_[p_id]; inst->data = std::make_unique(scene_delegate_, ob, p_id); inst->data->init(); } - else { - inst = &it->second; - } ID_LOG(2, "Light %s %d", inst->data->id->name, inst->transforms.size()); inst->transforms.push_back(gf_matrix_from_transform(dupli->mat)); } else { - MeshInstance *inst; - auto it = mesh_instances_.find(p_id); - if (it == mesh_instances_.end()) { + MeshInstance *inst = mesh_instance(p_id); + if (!inst) { inst = &mesh_instances_[p_id]; inst->data = std::make_unique(scene_delegate_, ob, p_id); inst->data->init(); inst->data->insert(); } - else { - inst = &it->second; - } ID_LOG(2, "Mesh %s %d", inst->data->id->name, mesh_transforms_.size()); inst->indices.push_back(mesh_transforms_.size()); mesh_transforms_.push_back(gf_matrix_from_transform(dupli->mat)); @@ -386,4 +378,22 @@ void InstancerData::update_light_instance(LightInstance &inst) } } +InstancerData::MeshInstance *InstancerData::mesh_instance(pxr::SdfPath const &id) const +{ + auto it = mesh_instances_.find(id.GetPathElementCount() == 4 ? id.GetParentPath() : id); + if (it == mesh_instances_.end()) { + return nullptr; + } + return const_cast(&it->second); +} + +InstancerData::LightInstance *InstancerData::light_instance(pxr::SdfPath const &id) const +{ + auto it = light_instances_.find(id.GetPathElementCount() == 4 ? id.GetParentPath() : id); + if (it == light_instances_.end()) { + return nullptr; + } + return const_cast(&it->second); +} + } // namespace blender::render::hydra diff --git a/source/blender/render/hydra/scene_delegate/instancer.h b/source/blender/render/hydra/scene_delegate/instancer.h index d0454903abf8..1dfb1e98c4b8 100644 --- a/source/blender/render/hydra/scene_delegate/instancer.h +++ b/source/blender/render/hydra/scene_delegate/instancer.h @@ -49,8 +49,10 @@ class InstancerData : public ObjectData { pxr::SdfPath object_prim_id(Object *object) const; pxr::SdfPath light_prim_id(LightInstance const &inst, int index) const; int light_prim_id_index(pxr::SdfPath const &id) const; - void set_instances(); + void write_instances(); void update_light_instance(LightInstance &inst); + MeshInstance *mesh_instance(pxr::SdfPath const &id) const; + LightInstance *light_instance(pxr::SdfPath const &id) const; pxr::TfHashMap mesh_instances_; pxr::TfHashMap light_instances_; diff --git a/source/blender/render/hydra/scene_delegate/mesh.cc b/source/blender/render/hydra/scene_delegate/mesh.cc index dcb47524b7d3..8c8ef8bb86f5 100644 --- a/source/blender/render/hydra/scene_delegate/mesh.cc +++ b/source/blender/render/hydra/scene_delegate/mesh.cc @@ -29,89 +29,72 @@ void MeshData::init() if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT && BLI_listbase_is_empty(&object->modifiers)) { - write_mesh((Mesh *)object->data); + write_submeshes((Mesh *)object->data); } else { Mesh *mesh = BKE_object_to_mesh(nullptr, object, false); if (mesh) { - write_mesh(mesh); + write_submeshes(mesh); } BKE_object_to_mesh_clear(object); } - write_material(); write_transform(); + write_materials(); } void MeshData::insert() { - if (face_vertex_counts_.empty()) { - return; - } - - ID_LOG(2, ""); - scene_delegate_->GetRenderIndex().InsertRprim( - pxr::HdPrimTypeTokens->mesh, scene_delegate_, prim_id); + /* Empty, because insertion of rprims happen in write_submeshes() */ } void MeshData::remove() { - if (!scene_delegate_->GetRenderIndex().HasRprim(prim_id)) { - return; + for (int i = 0; i < submeshes_.size(); ++i) { + scene_delegate_->GetRenderIndex().RemoveRprim(submesh_prim_id(i)); + CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s: %d", prim_id.GetText(), i); } - - CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", prim_id.GetText()); - scene_delegate_->GetRenderIndex().RemoveRprim(prim_id); } void MeshData::update() { Object *object = (Object *)id; - pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean; if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) { init(); - bits = pxr::HdChangeTracker::AllDirty; + return; } - else { - if (id->recalc & ID_RECALC_SHADING) { - write_material(); - bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided; - } - if (id->recalc & ID_RECALC_TRANSFORM) { - write_transform(); - bits |= pxr::HdChangeTracker::DirtyTransform; - } + + pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean; + if (id->recalc & ID_RECALC_SHADING) { + write_materials(); + bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided; + } + if (id->recalc & ID_RECALC_TRANSFORM) { + write_transform(); + bits |= pxr::HdChangeTracker::DirtyTransform; } if (bits == pxr::HdChangeTracker::Clean) { return; } - if (!scene_delegate_->GetRenderIndex().HasRprim(prim_id)) { - insert(); - return; + for (int i = 0; i < submeshes_.size(); ++i) { + scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(submesh_prim_id(i), bits); + ID_LOG(2, "%d", i); } - - if (face_vertex_counts_.empty()) { - /* Remove prim without faces */ - remove(); - return; - } - ID_LOG(2, ""); - scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(prim_id, bits); } -pxr::VtValue MeshData::get_data(pxr::TfToken const &key) const +pxr::VtValue MeshData::get_data(pxr::SdfPath const &id, pxr::TfToken const &key) const { pxr::VtValue ret; if (key == pxr::HdTokens->points) { ret = vertices_; } else if (key == pxr::HdTokens->normals) { - ret = normals_; + ret = submesh(id).normals; } else if (key == pxr::HdPrimvarRoleTokens->textureCoordinate) { - ret = uvs_; + ret = submesh(id).uvs; } return ret; } @@ -120,19 +103,22 @@ bool MeshData::update_visibility() { bool ret = ObjectData::update_visibility(); if (ret) { - ID_LOG(2, ""); - scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty( - prim_id, pxr::HdChangeTracker::DirtyVisibility); + for (int i = 0; i < submeshes_.size(); ++i) { + scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty( + submesh_prim_id(i), pxr::HdChangeTracker::DirtyVisibility); + ID_LOG(2, "%d", i); + } } return ret; } -pxr::HdMeshTopology MeshData::mesh_topology() const +pxr::HdMeshTopology MeshData::mesh_topology(pxr::SdfPath const &id) const { + const SubMesh &sm = submesh(id); return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none, pxr::HdTokens->rightHanded, - face_vertex_counts_, - face_vertex_indices_); + sm.face_vertex_counts, + sm.face_vertex_indices); } pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors( @@ -145,11 +131,11 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors( } } else if (interpolation == pxr::HdInterpolationFaceVarying) { - if (!normals_.empty()) { + if (!submeshes_[0].normals.empty()) { primvars.emplace_back( pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal); } - if (!uvs_.empty()) { + if (!submeshes_[0].uvs.empty()) { primvars.emplace_back(pxr::HdPrimvarRoleTokens->textureCoordinate, interpolation, pxr::HdPrimvarRoleTokens->textureCoordinate); @@ -158,116 +144,171 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors( return primvars; } -pxr::SdfPath MeshData::material_id() const +pxr::SdfPath MeshData::material_id(pxr::SdfPath const &id) const { - if (!mat_data_) { + const SubMesh &sm = submesh(id); + if (!sm.mat_data) { return pxr::SdfPath(); } - return mat_data_->prim_id; + return sm.mat_data->prim_id; } -bool MeshData::double_sided() const +bool MeshData::double_sided(pxr::SdfPath const &id) const { - if (mat_data_) { - return mat_data_->double_sided; + const SubMesh &sm = submesh(id); + if (sm.mat_data) { + return sm.mat_data->double_sided; } return true; } void MeshData::update_double_sided(MaterialData *mat_data) { - if (mat_data_ == mat_data) { - ID_LOG(2, ""); - scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty( - prim_id, pxr::HdChangeTracker::DirtyDoubleSided); - } -} - -void MeshData::write_mesh(Mesh *mesh) -{ - face_vertex_counts_.clear(); - face_vertex_indices_.clear(); - vertices_.clear(); - normals_.clear(); - uvs_.clear(); - - BKE_mesh_calc_normals_split(mesh); - int tris_len = BKE_mesh_runtime_looptri_len(mesh); - if (tris_len == 0) { - return; - } - - blender::Span loopTris = mesh->looptris(); - - /* face_vertex_counts */ - face_vertex_counts_ = pxr::VtIntArray(tris_len, 3); - - /* face_vertex_indices */ - blender::Span corner_verts = mesh->corner_verts(); - face_vertex_indices_.reserve(loopTris.size() * 3); - for (MLoopTri lt : loopTris) { - face_vertex_indices_.push_back(corner_verts[lt.tri[0]]); - face_vertex_indices_.push_back(corner_verts[lt.tri[1]]); - face_vertex_indices_.push_back(corner_verts[lt.tri[2]]); - } - - /* vertices */ - vertices_.reserve(mesh->totvert); - blender::Span verts = mesh->vert_positions(); - for (blender::float3 v : verts) { - vertices_.push_back(pxr::GfVec3f(v.x, v.y, v.z)); - } - - write_normals(mesh); - write_uv_maps(mesh); -} - -void MeshData::write_material() -{ - Object *object = (Object *)id; - Material *mat = nullptr; - if (BKE_object_material_count_eval(object) > 0) { - mat = BKE_object_material_get_eval(object, object->actcol); - } - - if (!mat) { - mat_data_ = nullptr; - return; - } - pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat); - mat_data_ = scene_delegate_->material_data(p_id); - if (!mat_data_) { - scene_delegate_->materials_[p_id] = std::make_unique(scene_delegate_, mat, p_id); - mat_data_ = scene_delegate_->material_data(p_id); - mat_data_->init(); - mat_data_->insert(); - } -} - -void MeshData::write_uv_maps(Mesh *mesh) -{ - blender::Span loopTris = mesh->looptris(); - const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2); - if (luvs) { - uvs_.reserve(loopTris.size() * 3); - for (MLoopTri lt : loopTris) { - uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[0]])); - uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[1]])); - uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[2]])); + for (int i = 0; i < submeshes_.size(); ++i) { + if (submeshes_[i].mat_data == mat_data) { + scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty( + submesh_prim_id(i), pxr::HdChangeTracker::DirtyDoubleSided); + ID_LOG(2, "%d", i); } } } -void MeshData::write_normals(Mesh *mesh) +void MeshData::available_materials(std::set &paths) const { - blender::Span loopTris = mesh->looptris(); + for (auto &sm : submeshes_) { + if (sm.mat_data && !sm.mat_data->prim_id.IsEmpty()) { + paths.insert(sm.mat_data->prim_id); + } + } +} + +pxr::SdfPathVector MeshData::submesh_paths() const +{ + pxr::SdfPathVector ret; + for (int i = 0; i < submeshes_.size(); ++i) { + ret.push_back(submesh_prim_id(i)); + } + return ret; +} + +pxr::SdfPath MeshData::submesh_prim_id(int index) const +{ + char name[16]; + snprintf(name, 16, "SM_%04x", index); + return prim_id.AppendElementString(name); +} + +const MeshData::SubMesh &MeshData::submesh(pxr::SdfPath const &id) const +{ + int index; + sscanf(id.GetName().c_str(), "SM_%x", &index); + return submeshes_[index]; +} + +void MeshData::write_submeshes(Mesh *mesh) +{ + int sub_meshes_prev_count = submeshes_.size(); + submeshes_.clear(); + vertices_.clear(); + + /* Insert base submeshes */ + int mat_count = BKE_object_material_count_eval((Object *)id); + for (int i = 0; i < std::max(mat_count, 1); ++i) { + SubMesh sm; + sm.mat_index = i; + submeshes_.push_back(sm); + } + + /* Fill submeshes data */ + const int *material_indices = BKE_mesh_material_indices(mesh); + const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(mesh); + blender::Span corner_verts = mesh->corner_verts(); + blender::Span looptris = mesh->looptris(); + + BKE_mesh_calc_normals_split(mesh); const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL); - if (lnors) { - normals_.reserve(loopTris.size() * 3); - for (MLoopTri lt : loopTris) { - normals_.push_back(pxr::GfVec3f(lnors[lt.tri[0]])); - normals_.push_back(pxr::GfVec3f(lnors[lt.tri[1]])); - normals_.push_back(pxr::GfVec3f(lnors[lt.tri[2]])); + const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2); + + for (size_t i = 0; i < looptris.size(); ++i) { + int mat_ind = material_indices ? material_indices[looptri_polys[i]] : 0; + const MLoopTri < = looptris[i]; + SubMesh &sm = submeshes_[mat_ind]; + + sm.face_vertex_counts.push_back(3); + sm.face_vertex_indices.push_back(corner_verts[lt.tri[0]]); + sm.face_vertex_indices.push_back(corner_verts[lt.tri[1]]); + sm.face_vertex_indices.push_back(corner_verts[lt.tri[2]]); + + if (lnors) { + sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[0]])); + sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[1]])); + sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[2]])); + } + + if (luvs) { + sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[0]])); + sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[1]])); + sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[2]])); + } + } + + /* Remove submeshes without faces */ + for (auto it = submeshes_.begin(); it != submeshes_.end();) { + if (it->face_vertex_counts.empty()) { + it = submeshes_.erase(it); + } + else { + ++it; + } + } + + if (!submeshes_.empty()) { + /* vertices */ + vertices_.reserve(mesh->totvert); + blender::Span verts = mesh->vert_positions(); + for (blender::float3 v : verts) { + vertices_.push_back(pxr::GfVec3f(v.x, v.y, v.z)); + } + } + + /* Update prims in render index */ + auto &render_index = scene_delegate_->GetRenderIndex(); + int i; + for (i = 0; i < submeshes_.size(); ++i) { + pxr::SdfPath p = submesh_prim_id(i); + if (i < sub_meshes_prev_count) { + render_index.GetChangeTracker().MarkRprimDirty(p, pxr::HdChangeTracker::AllDirty); + ID_LOG(2, "Update %d", i); + } + else { + render_index.InsertRprim(pxr::HdPrimTypeTokens->mesh, scene_delegate_, p); + ID_LOG(2, "Insert %d", i); + } + } + for (; i < sub_meshes_prev_count; ++i) { + render_index.RemoveRprim(submesh_prim_id(i)); + ID_LOG(2, "Remove %d", i); + } +} + +void MeshData::write_materials() +{ + Object *object = (Object *)id; + for (int i = 0; i < submeshes_.size(); ++i) { + SubMesh &m = submeshes_[i]; + Material *mat = BKE_object_material_get_eval(object, m.mat_index + 1); + if (!mat) { + m.mat_data = nullptr; + continue; + } + pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat); + m.mat_data = scene_delegate_->material_data(p_id); + if (!m.mat_data) { + scene_delegate_->materials_[p_id] = std::make_unique( + scene_delegate_, mat, p_id); + m.mat_data = scene_delegate_->material_data(p_id); + m.mat_data->init(); + m.mat_data->insert(); } } } diff --git a/source/blender/render/hydra/scene_delegate/mesh.h b/source/blender/render/hydra/scene_delegate/mesh.h index e9a66dd7bdcb..750e9c2bdf39 100644 --- a/source/blender/render/hydra/scene_delegate/mesh.h +++ b/source/blender/render/hydra/scene_delegate/mesh.h @@ -14,6 +14,15 @@ namespace blender::render::hydra { class MeshData : public ObjectData { + struct SubMesh { + pxr::VtIntArray face_vertex_counts; + pxr::VtIntArray face_vertex_indices; + pxr::VtVec3fArray normals; + pxr::VtVec2fArray uvs; + int mat_index = 0; + MaterialData *mat_data = nullptr; + }; + public: MeshData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id); @@ -22,30 +31,27 @@ class MeshData : public ObjectData { void remove() override; void update() override; - pxr::VtValue get_data(pxr::TfToken const &key) const override; + pxr::VtValue get_data(pxr::SdfPath const &id, pxr::TfToken const &key) const; 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::SdfPath material_id() const; - bool double_sided() const; + pxr::SdfPath material_id(pxr::SdfPath const &id) const; + bool double_sided(pxr::SdfPath const &id) const; void update_double_sided(MaterialData *mat_data); + void available_materials(std::set &paths) const; + pxr::SdfPathVector submesh_paths() const; pxr::HdCullStyle cull_style = pxr::HdCullStyleBackUnlessDoubleSided; private: - void write_mesh(Mesh *mesh); - void write_material(); - void write_uv_maps(Mesh *mesh); - void write_normals(Mesh *mesh); + pxr::SdfPath submesh_prim_id(int index) const; + const SubMesh &submesh(pxr::SdfPath const &id) const; + void write_submeshes(Mesh *mesh); + void write_materials(); - pxr::VtIntArray face_vertex_counts_; - pxr::VtIntArray face_vertex_indices_; pxr::VtVec3fArray vertices_; - pxr::VtVec2fArray uvs_; - pxr::VtVec3fArray normals_; - - MaterialData *mat_data_ = nullptr; + std::vector submeshes_; }; } // namespace blender::render::hydra