Support instancing for other objects: curves and volumes #74

Merged
Bogdan Nagirniak merged 4 commits from BLEN-449 into hydra-render 2023-07-26 10:27:51 +02:00
3 changed files with 35 additions and 40 deletions
Showing only changes of commit bf42e1a01e - Show all commits

View File

@ -161,10 +161,12 @@ pxr::HdCullStyle BlenderSceneDelegate::GetCullStyle(pxr::SdfPath const &id)
pxr::SdfPath BlenderSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id) pxr::SdfPath BlenderSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", prim_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", prim_id.GetText());
if (mesh_data(prim_id)) {
InstancerData *i_data = instancer_data(prim_id, true); InstancerData *i_data = instancer_data(prim_id, true);
if (i_data) { if (i_data) {
return i_data->prim_id; return i_data->prim_id;
} }
}
return pxr::SdfPath(); return pxr::SdfPath();
} }

View File

@ -25,6 +25,8 @@ bool InstancerData::is_instance_supported(Object *object)
case OB_CURVES_LEGACY: case OB_CURVES_LEGACY:
case OB_MBALL: case OB_MBALL:
case OB_LAMP: case OB_LAMP:
case OB_CURVES:
case OB_VOLUME:
return true; return true;
default: default:
@ -120,7 +122,10 @@ pxr::SdfPathVector InstancerData::prototypes() const
void InstancerData::available_materials(Set<pxr::SdfPath> &paths) const void InstancerData::available_materials(Set<pxr::SdfPath> &paths) const
{ {
for (auto &m_inst : mesh_instances_.values()) { for (auto &m_inst : mesh_instances_.values()) {
((MeshData *)m_inst.data.get())->available_materials(paths); m_inst.data->available_materials(paths);
}
for (auto &l_inst : light_instances_.values()) {
l_inst.data->available_materials(paths);
} }
} }
@ -156,12 +161,11 @@ void InstancerData::update_instance(Object *parent_ob, DupliObject *dupli)
} }
pxr::SdfPath p_id = object_prim_id(ob); pxr::SdfPath p_id = object_prim_id(ob);
if (ob->type == OB_LAMP) { if (ELEM(ob->type, OB_LAMP, OB_VOLUME, OB_CURVES)) {
LightInstance *inst = light_instance(p_id); LightInstance *inst = light_instance(p_id);
if (!inst) { if (!inst) {
inst = &light_instances_.lookup_or_add_default(p_id); inst = &light_instances_.lookup_or_add_default(p_id);
inst->data = std::make_unique<LightData>(scene_delegate_, ob, p_id); inst->data = ObjectData::create(scene_delegate_, ob, p_id);
inst->data->init();
} }
ID_LOG(2, "Light %s %d", inst->data->id->name, (int)inst->transforms.size()); ID_LOG(2, "Light %s %d", inst->data->id->name, (int)inst->transforms.size());
inst->transforms.push_back(gf_matrix_from_transform(dupli->mat)); inst->transforms.push_back(gf_matrix_from_transform(dupli->mat));
@ -229,11 +233,11 @@ pxr::SdfPath InstancerData::object_prim_id(Object *object) const
return prim_id.AppendElementString(name); return prim_id.AppendElementString(name);
} }
pxr::SdfPath InstancerData::light_prim_id(LightInstance const &inst, int index) const pxr::SdfPath InstancerData::light_prim_id(pxr::SdfPath const &prim_id, int index) const
{ {
char name[16]; char name[16];
snprintf(name, sizeof(name), "L_%08x", index); snprintf(name, sizeof(name), "L_%08x", index);
return inst.data->prim_id.AppendElementString(name); return prim_id.AppendElementString(name);
} }
int InstancerData::light_prim_id_index(pxr::SdfPath const &id) const int InstancerData::light_prim_id_index(pxr::SdfPath const &id) const
@ -245,57 +249,46 @@ int InstancerData::light_prim_id_index(pxr::SdfPath const &id) const
void InstancerData::update_light_instance(LightInstance &inst) void InstancerData::update_light_instance(LightInstance &inst)
{ {
auto &render_index = scene_delegate_->GetRenderIndex(); ObjectData *obj_data = inst.data.get();
LightData &l_data = *inst.data; pxr::SdfPath prev_id = inst.data->prim_id;
int i; int i;
pxr::SdfPath p;
/* Remove old light instances */ /* Remove old light instances */
while (inst.count > inst.transforms.size()) { while (inst.count > inst.transforms.size()) {
--inst.count; --inst.count;
p = light_prim_id(inst, inst.count); obj_data->prim_id = light_prim_id(prev_id, inst.count);
render_index.RemoveSprim(l_data.prim_type_, p); obj_data->remove();
ID_LOG(2, "Remove %s", p.GetText());
} }
/* Update current light instances */ /* Update current light instances */
if (inst.data->prim_type((Light *)((Object *)l_data.id)->data) != l_data.prim_type_) { LightData *l_data = dynamic_cast<LightData *>(obj_data);
/* Recreate instances when prim_type was changed */ if (l_data && l_data->prim_type((Light *)((Object *)l_data->id)->data) != l_data->prim_type_) {
/* Special case: recreate instances when prim_type was changed */
for (i = 0; i < inst.count; ++i) { for (i = 0; i < inst.count; ++i) {
p = light_prim_id(inst, i); obj_data->prim_id = light_prim_id(prev_id, i);
render_index.RemoveSprim(l_data.prim_type_, p); obj_data->remove();
ID_LOG(2, "Remove %s", p.GetText());
} }
inst.data->init(); l_data->init();
for (i = 0; i < inst.count; ++i) { for (i = 0; i < inst.count; ++i) {
p = light_prim_id(inst, i); obj_data->prim_id = light_prim_id(prev_id, i);
render_index.InsertSprim(l_data.prim_type_, scene_delegate_, p); obj_data->insert();
ID_LOG(2, "Insert %s (%s)", p.GetText(), l_data.id->name);
} }
} }
else { else {
/* Update light instances*/
pxr::HdDirtyBits bits = pxr::HdLight::DirtyTransform;
Object *obj = (Object *)inst.data->id;
if (obj->id.recalc & ID_RECALC_GEOMETRY || ((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY) {
l_data.init();
bits = pxr::HdLight::AllDirty;
}
for (i = 0; i < inst.count; ++i) { for (i = 0; i < inst.count; ++i) {
p = light_prim_id(inst, i); obj_data->prim_id = light_prim_id(prev_id, i);
render_index.GetChangeTracker().MarkSprimDirty(p, bits); obj_data->update();
ID_LOG(2, "Update %s (%s)", p.GetText(), l_data.id->name);
} }
} }
/* Add new light instances */ /* Add new light instances */
while (inst.count < inst.transforms.size()) { while (inst.count < inst.transforms.size()) {
p = light_prim_id(inst, inst.count); obj_data->prim_id = light_prim_id(prev_id, inst.count);
render_index.InsertSprim(l_data.prim_type_, scene_delegate_, p); obj_data->insert();
ID_LOG(2, "Insert %s (%s)", p.GetText(), l_data.id->name);
++inst.count; ++inst.count;
} }
obj_data->prim_id = prev_id;
} }
InstancerData::MeshInstance *InstancerData::mesh_instance(pxr::SdfPath const &id) const InstancerData::MeshInstance *InstancerData::mesh_instance(pxr::SdfPath const &id) const

View File

@ -19,7 +19,7 @@ class InstancerData : public IdData {
}; };
struct LightInstance { struct LightInstance {
std::unique_ptr<LightData> data; std::unique_ptr<ObjectData> data;
pxr::VtMatrix4dArray transforms; pxr::VtMatrix4dArray transforms;
int count = 0; int count = 0;
}; };
@ -54,7 +54,7 @@ class InstancerData : public IdData {
private: private:
pxr::SdfPath object_prim_id(Object *object) const; pxr::SdfPath object_prim_id(Object *object) const;
pxr::SdfPath light_prim_id(LightInstance const &inst, int index) const; pxr::SdfPath light_prim_id(pxr::SdfPath const &prim_id, int index) const;
int light_prim_id_index(pxr::SdfPath const &id) const; int light_prim_id_index(pxr::SdfPath const &id) const;
void update_light_instance(LightInstance &inst); void update_light_instance(LightInstance &inst);
MeshInstance *mesh_instance(pxr::SdfPath const &id) const; MeshInstance *mesh_instance(pxr::SdfPath const &id) const;