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,9 +161,11 @@ 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, true);
if (i_data) {
return i_data->prim_id;
if (mesh_data(prim_id)) {
InstancerData *i_data = instancer_data(prim_id, true);
if (i_data) {
return i_data->prim_id;
}
}
return pxr::SdfPath();
}

View File

@ -25,6 +25,8 @@ bool InstancerData::is_instance_supported(Object *object)
case OB_CURVES_LEGACY:
case OB_MBALL:
case OB_LAMP:
case OB_CURVES:
case OB_VOLUME:
return true;
default:
@ -120,7 +122,10 @@ pxr::SdfPathVector InstancerData::prototypes() const
void InstancerData::available_materials(Set<pxr::SdfPath> &paths) const
{
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);
if (ob->type == OB_LAMP) {
if (ELEM(ob->type, OB_LAMP, OB_VOLUME, OB_CURVES)) {
LightInstance *inst = light_instance(p_id);
if (!inst) {
inst = &light_instances_.lookup_or_add_default(p_id);
inst->data = std::make_unique<LightData>(scene_delegate_, ob, p_id);
inst->data->init();
inst->data = ObjectData::create(scene_delegate_, ob, p_id);
}
ID_LOG(2, "Light %s %d", inst->data->id->name, (int)inst->transforms.size());
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);
}
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];
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
@ -245,57 +249,46 @@ int InstancerData::light_prim_id_index(pxr::SdfPath const &id) const
void InstancerData::update_light_instance(LightInstance &inst)
{
auto &render_index = scene_delegate_->GetRenderIndex();
LightData &l_data = *inst.data;
ObjectData *obj_data = inst.data.get();
pxr::SdfPath prev_id = inst.data->prim_id;
int i;
pxr::SdfPath p;
/* Remove old light instances */
while (inst.count > inst.transforms.size()) {
--inst.count;
p = light_prim_id(inst, inst.count);
render_index.RemoveSprim(l_data.prim_type_, p);
ID_LOG(2, "Remove %s", p.GetText());
obj_data->prim_id = light_prim_id(prev_id, inst.count);
obj_data->remove();
}
/* Update current light instances */
if (inst.data->prim_type((Light *)((Object *)l_data.id)->data) != l_data.prim_type_) {
/* Recreate instances when prim_type was changed */
LightData *l_data = dynamic_cast<LightData *>(obj_data);
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) {
p = light_prim_id(inst, i);
render_index.RemoveSprim(l_data.prim_type_, p);
ID_LOG(2, "Remove %s", p.GetText());
obj_data->prim_id = light_prim_id(prev_id, i);
obj_data->remove();
}
inst.data->init();
l_data->init();
for (i = 0; i < inst.count; ++i) {
p = light_prim_id(inst, i);
render_index.InsertSprim(l_data.prim_type_, scene_delegate_, p);
ID_LOG(2, "Insert %s (%s)", p.GetText(), l_data.id->name);
obj_data->prim_id = light_prim_id(prev_id, i);
obj_data->insert();
}
}
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) {
p = light_prim_id(inst, i);
render_index.GetChangeTracker().MarkSprimDirty(p, bits);
ID_LOG(2, "Update %s (%s)", p.GetText(), l_data.id->name);
obj_data->prim_id = light_prim_id(prev_id, i);
obj_data->update();
}
}
/* Add new light instances */
while (inst.count < inst.transforms.size()) {
p = light_prim_id(inst, inst.count);
render_index.InsertSprim(l_data.prim_type_, scene_delegate_, p);
ID_LOG(2, "Insert %s (%s)", p.GetText(), l_data.id->name);
obj_data->prim_id = light_prim_id(prev_id, inst.count);
obj_data->insert();
++inst.count;
}
obj_data->prim_id = prev_id;
}
InstancerData::MeshInstance *InstancerData::mesh_instance(pxr::SdfPath const &id) const

View File

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