Implement instancing for light objects #35

Merged
Bogdan Nagirniak merged 18 commits from BLEN-395 into hydra-render 2023-05-04 15:12:27 +02:00
3 changed files with 31 additions and 11 deletions
Showing only changes of commit 278f4d7175 - Show all commits

View File

@ -115,6 +115,10 @@ bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
if (id == world_prim_id()) { if (id == world_prim_id()) {
return true; return true;
} }
InstancerData *i_data = instancer_data(id, true);
if (i_data) {
return i_data->visible;
}
return object_data(id)->visible; return object_data(id)->visible;
} }

View File

@ -34,6 +34,7 @@ bool InstancerData::is_supported(Object *object)
case OB_FONT: case OB_FONT:
case OB_CURVES_LEGACY: case OB_CURVES_LEGACY:
case OB_MBALL: case OB_MBALL:
case OB_LAMP:
return true; return true;
default: default:
@ -58,9 +59,14 @@ void InstancerData::remove()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", prim_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", prim_id.GetText());
for (auto &it : mesh_instances_) { for (auto &it : mesh_instances_) {
it.second.obj_data->remove(); it.second.data->remove();
} }
scene_delegate_->GetRenderIndex().RemoveInstancer(prim_id); scene_delegate_->GetRenderIndex().RemoveInstancer(prim_id);
for (auto &it : light_instances_) {
it.second.transforms.clear();
update_light_instance(it.second);
}
} }
void InstancerData::update() void InstancerData::update()
@ -100,9 +106,9 @@ bool InstancerData::update_visibility()
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty( scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
prim_id, pxr::HdChangeTracker::DirtyVisibility); prim_id, pxr::HdChangeTracker::DirtyVisibility);
for (auto &it : mesh_instances_) { for (auto &it : mesh_instances_) {
it.second.obj_data->visible = visible; it.second.data->visible = visible;
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty( scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
it.second.obj_data->prim_id, pxr::HdChangeTracker::DirtyVisibility); it.second.data->prim_id, pxr::HdChangeTracker::DirtyVisibility);
} }
} }
return ret; return ret;
@ -110,6 +116,14 @@ bool InstancerData::update_visibility()
pxr::GfMatrix4d InstancerData::get_transform(pxr::SdfPath const &id) const pxr::GfMatrix4d InstancerData::get_transform(pxr::SdfPath const &id) const
{ {
if (id.GetPathElementCount() == 4) {
const auto &inst = light_instances_.find(id.GetParentPath())->second;
std::string name = id.GetName();
int index;
sscanf_s(name.c_str(), "L_%x", &index);
return inst.transforms[index];
}
return pxr::GfMatrix4d(1.0); return pxr::GfMatrix4d(1.0);
} }
@ -133,7 +147,7 @@ ObjectData *InstancerData::object_data(pxr::SdfPath const &id) const
{ {
auto m_it = mesh_instances_.find(id); auto m_it = mesh_instances_.find(id);
if (m_it != mesh_instances_.end()) { if (m_it != mesh_instances_.end()) {
return m_it->second.obj_data.get(); return m_it->second.data.get();
} }
auto l_it = light_instances_.find(id); auto l_it = light_instances_.find(id);
if (l_it != light_instances_.end()) { if (l_it != light_instances_.end()) {
@ -158,7 +172,7 @@ void InstancerData::check_update(Object *object)
if (it == mesh_instances_.end()) { if (it == mesh_instances_.end()) {
return; return;
} }
ObjectData *obj_data = it->second.obj_data.get(); ObjectData *obj_data = it->second.data.get();
obj_data->update(); obj_data->update();
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean; pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
@ -178,7 +192,7 @@ void InstancerData::check_remove(std::set<std::string> &available_objects)
if (available_objects.find(it->first.GetName()) != available_objects.end()) { if (available_objects.find(it->first.GetName()) != available_objects.end()) {
continue; continue;
} }
it->second.obj_data->remove(); it->second.data->remove();
mesh_instances_.erase(it); mesh_instances_.erase(it);
it = mesh_instances_.begin(); it = mesh_instances_.begin();
ret = true; ret = true;
@ -193,7 +207,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.obj_data.get())->material_id(); pxr::SdfPath mat_id = ((MeshData *)it.second.data.get())->material_id();
if (!mat_id.IsEmpty()) { if (!mat_id.IsEmpty()) {
paths.insert(mat_id); paths.insert(mat_id);
} }
@ -253,12 +267,14 @@ void InstancerData::set_instances()
auto it = mesh_instances_.find(p_id); auto it = mesh_instances_.find(p_id);
if (it == mesh_instances_.end()) { if (it == mesh_instances_.end()) {
inst = &mesh_instances_[p_id]; inst = &mesh_instances_[p_id];
inst->obj_data = ObjectData::create(scene_delegate_, ob, p_id); inst->data = std::make_unique<MeshData>(scene_delegate_, ob, p_id);
inst->data->init();
inst->data->insert();
} }
else { else {
inst = &it->second; inst = &it->second;
} }
ID_LOG(2, "Mesh %s %d", inst->obj_data->id->name, mesh_transforms_.size()); ID_LOG(2, "Mesh %s %d", inst->data->id->name, mesh_transforms_.size());
inst->indices.push_back(mesh_transforms_.size()); inst->indices.push_back(mesh_transforms_.size());
mesh_transforms_.push_back(gf_matrix_from_transform(dupli->mat)); mesh_transforms_.push_back(gf_matrix_from_transform(dupli->mat));
} }
@ -270,7 +286,7 @@ void InstancerData::set_instances()
if (!it->second.indices.empty()) { if (!it->second.indices.empty()) {
continue; continue;
} }
it->second.obj_data->remove(); it->second.data->remove();
mesh_instances_.erase(it); mesh_instances_.erase(it);
it = mesh_instances_.begin(); it = mesh_instances_.begin();
} }

View File

@ -12,7 +12,7 @@ namespace blender::render::hydra {
class InstancerData : public ObjectData { class InstancerData : public ObjectData {
struct MeshInstance { struct MeshInstance {
std::unique_ptr<ObjectData> obj_data; std::unique_ptr<MeshData> data;
pxr::VtIntArray indices; pxr::VtIntArray indices;
}; };