forked from blender/blender
Implement instancing for light objects #35
@ -2,17 +2,13 @@
|
|||||||
* Copyright 2011-2022 Blender Foundation */
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
#include <pxr/base/gf/vec2f.h>
|
#include <pxr/base/gf/vec2f.h>
|
||||||
|
#include <pxr/imaging/hd/light.h>
|
||||||
|
|
||||||
#include "blender_scene_delegate.h"
|
#include "blender_scene_delegate.h"
|
||||||
#include "instancer.h"
|
#include "instancer.h"
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
void InstancerData::LightInstance::update()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate,
|
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate,
|
||||||
Object *object,
|
Object *object,
|
||||||
pxr::SdfPath const &prim_id)
|
pxr::SdfPath const &prim_id)
|
||||||
@ -135,7 +131,15 @@ pxr::VtIntArray InstancerData::indices(pxr::SdfPath const &id) const
|
|||||||
|
|
||||||
ObjectData *InstancerData::object_data(pxr::SdfPath const &id) const
|
ObjectData *InstancerData::object_data(pxr::SdfPath const &id) const
|
||||||
{
|
{
|
||||||
return mesh_instances_.find(id)->second.obj_data.get();
|
auto m_it = mesh_instances_.find(id);
|
||||||
|
if (m_it != mesh_instances_.end()) {
|
||||||
|
return m_it->second.obj_data.get();
|
||||||
|
}
|
||||||
|
auto l_it = light_instances_.find(id);
|
||||||
|
if (l_it != light_instances_.end()) {
|
||||||
|
return l_it->second.data.get();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::SdfPathVector InstancerData::prototypes() const
|
pxr::SdfPathVector InstancerData::prototypes() const
|
||||||
@ -241,7 +245,7 @@ void InstancerData::set_instances()
|
|||||||
else {
|
else {
|
||||||
inst = &it->second;
|
inst = &it->second;
|
||||||
}
|
}
|
||||||
ID_LOG(2, "%s %d", inst->data->id->name, inst->transforms.size());
|
ID_LOG(2, "Light %s %d", inst->data->id->name, inst->transforms.size());
|
||||||
inst->transforms.push_back(gf_matrix_from_transform(dupli->mat));
|
inst->transforms.push_back(gf_matrix_from_transform(dupli->mat));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -254,7 +258,7 @@ void InstancerData::set_instances()
|
|||||||
else {
|
else {
|
||||||
inst = &it->second;
|
inst = &it->second;
|
||||||
}
|
}
|
||||||
ID_LOG(2, "%s %d", inst->obj_data->id->name, mesh_transforms_.size());
|
ID_LOG(2, "Mesh %s %d", inst->obj_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));
|
||||||
}
|
}
|
||||||
@ -273,7 +277,7 @@ void InstancerData::set_instances()
|
|||||||
|
|
||||||
/* Update light intances and remove instances without transforms */
|
/* Update light intances and remove instances without transforms */
|
||||||
for (auto it = light_instances_.begin(); it != light_instances_.end(); ++it) {
|
for (auto it = light_instances_.begin(); it != light_instances_.end(); ++it) {
|
||||||
it->second.update();
|
update_light_instance(it->second);
|
||||||
if (it->second.transforms.empty()) {
|
if (it->second.transforms.empty()) {
|
||||||
light_instances_.erase(it);
|
light_instances_.erase(it);
|
||||||
it = light_instances_.begin();
|
it = light_instances_.begin();
|
||||||
@ -281,4 +285,64 @@ void InstancerData::set_instances()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstancerData::update_light_instance(LightInstance &inst)
|
||||||
|
{
|
||||||
|
auto &render_index = scene_delegate_->GetRenderIndex();
|
||||||
|
LightData &l_data = *inst.data;
|
||||||
|
|
||||||
|
char name[16];
|
||||||
|
int i;
|
||||||
|
pxr::SdfPath p;
|
||||||
|
|
||||||
|
/* Remove old light instances */
|
||||||
|
while (inst.count > inst.transforms.size()) {
|
||||||
|
--inst.count;
|
||||||
|
snprintf(name, 16, "L_%08x", inst.count);
|
||||||
|
p = l_data.prim_id.AppendElementString(name);
|
||||||
|
render_index.RemoveSprim(l_data.prim_type_, p);
|
||||||
|
ID_LOG(2, "Remove %s", p.GetText());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
for (i = 0; i < inst.count; ++i) {
|
||||||
|
snprintf(name, 16, "L_%08x", i);
|
||||||
|
p = l_data.prim_id.AppendElementString(name);
|
||||||
|
render_index.RemoveSprim(l_data.prim_type_, p);
|
||||||
|
ID_LOG(2, "Remove %s", p.GetText());
|
||||||
|
}
|
||||||
|
inst.data->init();
|
||||||
|
for (i = 0; i < inst.count; ++i) {
|
||||||
|
snprintf(name, 16, "L_%08x", i);
|
||||||
|
p = l_data.prim_id.AppendElementString(name);
|
||||||
|
render_index.InsertSprim(l_data.prim_type_, scene_delegate_, p);
|
||||||
|
ID_LOG(2, "Insert %s (%s)", p.GetText(), l_data.id->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Update light instances*/
|
||||||
|
pxr::HdDirtyBits bits = pxr::HdLight::DirtyTransform;
|
||||||
|
if (id->recalc & ID_RECALC_GEOMETRY) {
|
||||||
|
l_data.init();
|
||||||
|
bits = pxr::HdLight::AllDirty;
|
||||||
|
}
|
||||||
|
for (i = 0; i < inst.count; ++i) {
|
||||||
|
snprintf(name, 16, "L_%08x", i);
|
||||||
|
p = l_data.prim_id.AppendElementString(name);
|
||||||
|
render_index.GetChangeTracker().MarkSprimDirty(p, bits);
|
||||||
|
ID_LOG(2, "Update %s (%s)", p.GetText(), l_data.id->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add new light instances */
|
||||||
|
while (inst.count < inst.transforms.size()) {
|
||||||
|
snprintf(name, 16, "L_%08x", inst.count);
|
||||||
|
p = inst.data->prim_id.AppendElementString(name);
|
||||||
|
render_index.InsertSprim(l_data.prim_type_, scene_delegate_, p);
|
||||||
|
ID_LOG(2, "Insert %s (%s)", p.GetText(), l_data.id->name);
|
||||||
|
++inst.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -19,11 +19,7 @@ class InstancerData : public ObjectData {
|
|||||||
struct LightInstance {
|
struct LightInstance {
|
||||||
std::unique_ptr<LightData> data;
|
std::unique_ptr<LightData> data;
|
||||||
pxr::VtMatrix4dArray transforms;
|
pxr::VtMatrix4dArray transforms;
|
||||||
|
int count = 0;
|
||||||
void update();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int count_ = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -55,6 +51,7 @@ class InstancerData : public ObjectData {
|
|||||||
private:
|
private:
|
||||||
pxr::SdfPath object_prim_id(Object *object) const;
|
pxr::SdfPath object_prim_id(Object *object) const;
|
||||||
void set_instances();
|
void set_instances();
|
||||||
|
void update_light_instance(LightInstance &inst);
|
||||||
|
|
||||||
pxr::TfHashMap<pxr::SdfPath, MeshInstance, pxr::SdfPath::Hash> mesh_instances_;
|
pxr::TfHashMap<pxr::SdfPath, MeshInstance, pxr::SdfPath::Hash> mesh_instances_;
|
||||||
pxr::TfHashMap<pxr::SdfPath, LightInstance, pxr::SdfPath::Hash> light_instances_;
|
pxr::TfHashMap<pxr::SdfPath, LightInstance, pxr::SdfPath::Hash> light_instances_;
|
||||||
|
@ -13,7 +13,11 @@
|
|||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
class InstancerData;
|
||||||
|
|
||||||
class LightData : public ObjectData {
|
class LightData : public ObjectData {
|
||||||
|
friend InstancerData;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LightData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
|
LightData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user