Make object visibility and instancing creation to be calculated via depsgraph #57

Merged
Bogdan Nagirniak merged 16 commits from BLEN-442 into hydra-render 2023-07-08 10:09:53 +02:00
13 changed files with 199 additions and 558 deletions

View File

@ -3,7 +3,6 @@
#include <bitset>
#include "BKE_object.h"
#include "BLI_set.hh"
#include "DEG_depsgraph_query.h"
#include "DNA_scene_types.h"
@ -32,6 +31,7 @@ BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
Engine *engine)
: HdSceneDelegate(parent_index, delegate_id), engine(engine)
{
instancer_data_ = std::make_unique<InstancerData>(this, instancer_prim_id());
}
pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id)
@ -164,7 +164,7 @@ bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
}
InstancerData *i_data = instancer_data(id, true);
if (i_data) {
return i_data->visible;
return true;
}
return object_data(id)->visible;
}
@ -210,7 +210,7 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", instancer_id.GetText());
InstancerData *i_data = instancer_data(instancer_id);
return i_data->transform;
return i_data->get_transform(instancer_id);
}
pxr::HdVolumeFieldDescriptorVector BlenderSceneDelegate::GetVolumeFieldDescriptors(
@ -236,7 +236,7 @@ void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
else {
set_light_shading_settings();
set_world_shading_settings();
add_new_objects();
update_collection();
update_world();
}
}
@ -246,15 +246,11 @@ void BlenderSceneDelegate::clear()
for (auto &obj_data : objects_.values()) {
obj_data->remove();
}
for (auto &i_data : instancers_.values()) {
i_data->remove();
}
objects_.clear();
instancer_data_->remove();
for (auto &mat_data : materials_.values()) {
mat_data->remove();
}
objects_.clear();
instancers_.clear();
materials_.clear();
depsgraph = nullptr;
@ -291,9 +287,9 @@ pxr::SdfPath BlenderSceneDelegate::material_prim_id(Material *mat) const
return prim_id((ID *)mat, "M");
}
pxr::SdfPath BlenderSceneDelegate::instancer_prim_id(Object *object) const
pxr::SdfPath BlenderSceneDelegate::instancer_prim_id() const
{
return prim_id((ID *)object, "I");
return GetDelegateID().AppendElementString("Instancer");
}
pxr::SdfPath BlenderSceneDelegate::world_prim_id() const
@ -327,6 +323,11 @@ CurvesData *BlenderSceneDelegate::curves_data(pxr::SdfPath const &id) const
return dynamic_cast<CurvesData *>(object_data(id));
}
VolumeData *BlenderSceneDelegate::volume_data(pxr::SdfPath const &id) const
{
return dynamic_cast<VolumeData *>(object_data(id));
}
LightData *BlenderSceneDelegate::light_data(pxr::SdfPath const &id) const
{
return dynamic_cast<LightData *>(object_data(id));
@ -359,82 +360,12 @@ InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id, bool
p_id = id;
}
auto i_data = instancers_.lookup_ptr(p_id);
if (i_data) {
return i_data->get();
if (instancer_data_ && p_id == instancer_data_->prim_id) {
return instancer_data_.get();
}
return nullptr;
}
VolumeData *BlenderSceneDelegate::volume_data(pxr::SdfPath const &id) const
{
return dynamic_cast<VolumeData *>(object_data(id));
}
void BlenderSceneDelegate::update_objects(Object *object)
{
if (!ObjectData::is_supported(object)) {
return;
}
if (!shading_settings.use_scene_lights && object->type == OB_LAMP) {
return;
}
pxr::SdfPath id = object_prim_id(object);
ObjectData *obj_data = object_data(id);
if (obj_data) {
obj_data->update_parent();
obj_data->update();
obj_data->update_visibility();
return;
}
if (!ObjectData::is_visible(this, object)) {
/* Do not export new object if it is invisible */
return;
}
objects_.add_new(id, ObjectData::create(this, object, id));
obj_data = object_data(id);
obj_data->update_parent();
obj_data->init();
obj_data->insert();
}
void BlenderSceneDelegate::update_instancers(Object *object)
{
/* Check object inside instancers */
for (auto &i_data : instancers_.values()) {
i_data->check_update(object);
}
pxr::SdfPath id = instancer_prim_id(object);
InstancerData *i_data = instancer_data(id);
if (i_data) {
if ((object->transflag & OB_DUPLI) == 0) {
/* Object isn't instancer anymore and should be removed */
i_data->remove();
instancers_.remove(id);
return;
}
i_data->update();
return;
}
if ((object->transflag & OB_DUPLI) == 0) {
return;
}
if (!InstancerData::is_visible(this, object)) {
/* Do not export new instancer if it is invisible */
return;
}
i_data = instancers_.lookup_or_add(id, std::make_unique<InstancerData>(this, object, id)).get();
i_data->init();
i_data->insert();
}
void BlenderSceneDelegate::update_world()
{
if (!world_data_) {
@ -458,7 +389,6 @@ void BlenderSceneDelegate::update_world()
void BlenderSceneDelegate::check_updates()
{
bool do_update_collection = false;
bool do_update_visibility = false;
bool do_update_world = false;
if (set_world_shading_settings()) {
@ -466,19 +396,12 @@ void BlenderSceneDelegate::check_updates()
}
if (set_light_shading_settings()) {
if (shading_settings.use_scene_lights) {
add_new_objects();
}
else {
do_update_collection = true;
}
do_update_collection = true;
}
DEGIDIterData data = {0};
data.graph = depsgraph;
data.only_updated = true;
eEvaluationMode deg_mode = DEG_get_mode(depsgraph);
ITER_BEGIN (DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id)
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
@ -489,14 +412,7 @@ void BlenderSceneDelegate::check_updates()
switch (GS(id->name)) {
case ID_OB: {
Object *object = (Object *)id;
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"Visibility: %s [%s]",
object->id.name,
std::bitset<3>(BKE_object_visibility(object, deg_mode)).to_string().c_str());
update_objects(object);
update_instancers(object);
do_update_collection = true;
} break;
case ID_MA: {
@ -513,20 +429,15 @@ void BlenderSceneDelegate::check_updates()
} break;
case ID_SCE: {
if (id->recalc & ID_RECALC_COPY_ON_WRITE && !(id->recalc & ID_RECALC_SELECT)) {
do_update_collection = true;
do_update_visibility = true;
}
if (id->recalc & ID_RECALC_BASE_FLAGS) {
do_update_visibility = true;
}
if (id->recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY)) {
if ((id->recalc & ID_RECALC_COPY_ON_WRITE && !(id->recalc & ID_RECALC_SELECT)) ||
id->recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_BASE_FLAGS))
{
do_update_collection = true;
}
if (id->recalc & ID_RECALC_AUDIO_VOLUME) {
if ((scene->world && !world_data_) || (!scene->world && world_data_)) {
do_update_world = true;
}
if (id->recalc & ID_RECALC_AUDIO_VOLUME &&
((scene->world && !world_data_) || (!scene->world && world_data_)))
{
do_update_world = true;
}

use macro DEG_OBJECT_ITER_FOR_RENDER_ENGINE_FLAGS here

use macro `DEG_OBJECT_ITER_FOR_RENDER_ENGINE_FLAGS` here
} break;
@ -540,58 +451,24 @@ void BlenderSceneDelegate::check_updates()
update_world();
}
if (do_update_collection) {
remove_unused_objects();
}
if (do_update_visibility) {
update_visibility();
update_collection();
}
}
void BlenderSceneDelegate::add_new_objects()
void BlenderSceneDelegate::update_collection()
{
DEGObjectIterSettings settings = {0};
settings.depsgraph = depsgraph;
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
DEGObjectIterData data = {0};
data.settings = &settings;
data.graph = settings.depsgraph;
data.flag = settings.flags;
eEvaluationMode deg_mode = DEG_get_mode(depsgraph);
ITER_BEGIN (DEG_iterator_objects_begin,
DEG_iterator_objects_next,
DEG_iterator_objects_end,
&data,
Object *,
object)
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"Visibility: %s [%s]",
object->id.name,
std::bitset<3>(BKE_object_visibility(object, deg_mode)).to_string().c_str());
if (object_data(object_prim_id(object))) {
continue;
}
update_objects(object);
update_instancers(object);
}
ITER_END;
}
void BlenderSceneDelegate::remove_unused_objects()
{
/* Get available objects */
Set<std::string> available_objects;
DEGObjectIterSettings settings = {0};
settings.depsgraph = depsgraph;
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
settings.flags = DEG_OBJECT_ITER_FOR_RENDER_ENGINE_FLAGS;
DEGObjectIterData data = {0};
data.settings = &settings;
data.graph = settings.depsgraph;
data.flag = settings.flags;
instancer_data_->pre_update();
ITER_BEGIN (DEG_iterator_objects_begin,
DEG_iterator_objects_next,
DEG_iterator_objects_end,
@ -599,27 +476,37 @@ void BlenderSceneDelegate::remove_unused_objects()
Object *,
object)
{
available_objects.add(instancer_prim_id(object).GetName());
if (ObjectData::is_supported(object)) {
if (!shading_settings.use_scene_lights && object->type == OB_LAMP) {
continue;
}
available_objects.add(object_prim_id(object).GetName());
if (data.dupli_object_current) {
instancer_data_->update_instance(data.dupli_parent, data.dupli_object_current);
continue;
}
if (!ObjectData::is_supported(object)) {
continue;
}
if (!ObjectData::is_visible(this, object)) {
continue;
}
if (!shading_settings.use_scene_lights && object->type == OB_LAMP) {
continue;
}
available_objects.add(object_prim_id(object).GetName());
pxr::SdfPath id = object_prim_id(object);
ObjectData *obj_data = object_data(id);
if (obj_data) {
obj_data->update();
}
else {
obj_data = objects_.lookup_or_add(id, ObjectData::create(this, object, id)).get();
obj_data->init();
obj_data->insert();
}
}
ITER_END;
/* Remove unused instancers */
instancers_.remove_if([&](auto item) {
bool ret = !available_objects.contains(item.key.GetName());
if (ret) {
item.value->remove();
}
else {
item.value->check_remove(available_objects);
}
return ret;
});
instancer_data_->post_update();
/* Remove unused objects */
objects_.remove_if([&](auto item) {
@ -646,9 +533,7 @@ void BlenderSceneDelegate::remove_unused_objects()
v_data->available_materials(available_materials);
}
}
for (auto &val : instancers_.values()) {
val->available_materials(available_materials);
}
instancer_data_->available_materials(available_materials);
materials_.remove_if([&](auto item) {
bool ret = !available_materials.contains(item.key);
@ -659,48 +544,6 @@ void BlenderSceneDelegate::remove_unused_objects()
});
}
void BlenderSceneDelegate::update_visibility()
{
/* Updating visibility of existing objects/instancers */
for (auto &val : objects_.values()) {
val->update_visibility();
}
for (auto &val : instancers_.values()) {
val->update_visibility();
}
/* Add objects/instancers which were invisible before and not added yet */
DEGObjectIterSettings settings = {0};
settings.depsgraph = depsgraph;
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
DEGObjectIterData data = {0};
data.settings = &settings;
data.graph = settings.depsgraph;
data.flag = settings.flags;
eEvaluationMode deg_mode = DEG_get_mode(depsgraph);
ITER_BEGIN (DEG_iterator_objects_begin,
DEG_iterator_objects_next,
DEG_iterator_objects_end,
&data,
Object *,
object)
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"Visibility: %s [%s]",
object->id.name,
std::bitset<3>(BKE_object_visibility(object, deg_mode)).to_string().c_str());
if (!object_data(object_prim_id(object))) {
update_objects(object);
}
if (!instancer_data(instancer_prim_id(object))) {
update_instancers(object);
}
}
ITER_END;
}
bool BlenderSceneDelegate::set_light_shading_settings()
{
if (!view3d) {

View File

@ -91,30 +91,26 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
pxr::SdfPath prim_id(ID *id, const char *prefix) const;
pxr::SdfPath object_prim_id(Object *object) const;
pxr::SdfPath material_prim_id(Material *mat) const;
pxr::SdfPath instancer_prim_id(Object *object) const;
pxr::SdfPath instancer_prim_id() const;
pxr::SdfPath world_prim_id() const;
ObjectData *object_data(pxr::SdfPath const &id) const;
MeshData *mesh_data(pxr::SdfPath const &id) const;
CurvesData *curves_data(pxr::SdfPath const &id) const;
VolumeData *volume_data(pxr::SdfPath const &id) const;
LightData *light_data(pxr::SdfPath const &id) const;
MaterialData *material_data(pxr::SdfPath const &id) const;
InstancerData *instancer_data(pxr::SdfPath const &id, bool child_id = false) const;
VolumeData *volume_data(pxr::SdfPath const &id) const;
void update_objects(Object *object);
void update_instancers(Object *object);
void update_world();
void check_updates();
void add_new_objects();
void remove_unused_objects();
void update_visibility();
void update_collection();
bool set_light_shading_settings();
bool set_world_shading_settings();
ObjectDataMap objects_;
MaterialDataMap materials_;
InstancerDataMap instancers_;
std::unique_ptr<InstancerData> instancer_data_;
std::unique_ptr<WorldData> world_data_;
};

View File

@ -6,7 +6,6 @@
#include "BKE_customdata.h"
#include "BKE_material.h"
#include "BKE_object.h"
#include "blender_scene_delegate.h"

View File

@ -58,7 +58,7 @@ template<class T> const T IdData::get_data(pxr::TfToken const &key) const
level, \
"%s (%s): " msg, \
prim_id.GetText(), \
id->name, \
id ? id->name : "", \
##__VA_ARGS__);
} // namespace blender::render::hydra

View File

@ -45,7 +45,7 @@ static std::string cache_image_file(Image *image,
BKE_image_path_ext_from_imformat(&scene->r.im_format, &r_ext);
opts.im_format = scene->r.im_format;
}
snprintf(file_name, sizeof(file_name), "img_%016llx%s", (uintptr_t)image, r_ext);
file_path = get_cache_file(file_name);
@ -64,8 +64,6 @@ static std::string cache_image_file(Image *image,
}
}
BKE_image_save_options_free(&opts);
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s -> %s", image->id.name, file_path.c_str());
return file_path;
}
@ -98,7 +96,7 @@ std::string cache_image_color(float color[4])
char name[128];
snprintf(name,
sizeof(name),
"color_%02x-%02x-%02x.hdr",
"color_%02x%02x%02x.hdr",
int(color[0] * 255),
int(color[1] * 255),
int(color[2] * 255));

View File

@ -4,7 +4,6 @@
#include <pxr/base/gf/vec2f.h>
#include <pxr/imaging/hd/light.h>
#include "BKE_object.h"
#include "DEG_depsgraph_query.h"
#include "blender_scene_delegate.h"
@ -12,14 +11,12 @@
namespace blender::render::hydra {
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate,
Object *object,
pxr::SdfPath const &prim_id)
: ObjectData(scene_delegate, object, prim_id)
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id)
: IdData(scene_delegate, nullptr, prim_id)
{
}
bool InstancerData::is_supported(Object *object)
bool InstancerData::is_instance_supported(Object *object)
{
switch (object->type) {
case OB_MESH:
@ -36,40 +33,9 @@ bool InstancerData::is_supported(Object *object)
return false;
}
bool InstancerData::is_visible(BlenderSceneDelegate *scene_delegate, Object *object)
{
eEvaluationMode deg_mode = DEG_get_mode(scene_delegate->depsgraph);
int vis = BKE_object_visibility(object, deg_mode);
bool ret = vis & OB_VISIBLE_INSTANCES;
if (deg_mode == DAG_EVAL_VIEWPORT) {
ret &= BKE_object_is_visible_in_viewport(scene_delegate->view3d, object);
}
else {
if (ret) {
/* If some of parent object is instancer, then currenct object as instancer
* is invisible in Final render */
for (Object *ob = object->parent; ob != nullptr; ob = ob->parent) {
if (ob->transflag & OB_DUPLI) {
ret = false;
break;
}
}
}
}
return ret;
}
void InstancerData::init() {}
void InstancerData::init()
{
ID_LOG(1, "");
write_instances();
}
void InstancerData::insert()
{
ID_LOG(1, "");
scene_delegate_->GetRenderIndex().InsertInstancer(scene_delegate_, prim_id);
}
void InstancerData::insert() {}
void InstancerData::remove()
{
@ -77,27 +43,19 @@ void InstancerData::remove()
for (auto &m_inst : mesh_instances_.values()) {
m_inst.data->remove();
}
scene_delegate_->GetRenderIndex().RemoveInstancer(prim_id);
if (!mesh_instances_.is_empty()) {
scene_delegate_->GetRenderIndex().RemoveInstancer(prim_id);
}
mesh_instances_.clear();
for (auto &l_inst : light_instances_.values()) {
l_inst.transforms.clear();
update_light_instance(l_inst);
}
light_instances_.clear();
}
void InstancerData::update()
{
ID_LOG(1, "");
Object *object = (Object *)id;
if (id->recalc & ID_RECALC_GEOMETRY ||
(object->data && ((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) ||
id->recalc & ID_RECALC_TRANSFORM)
{
write_instances();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
prim_id, pxr::HdChangeTracker::AllDirty);
}
}
void InstancerData::update() {}
pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
{
@ -108,34 +66,6 @@ pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
return pxr::VtValue();
}
bool InstancerData::update_visibility()
{
bool prev_visible = visible;
visible = is_visible(scene_delegate_, (Object *)id);
bool ret = visible != prev_visible;
if (ret) {
ID_LOG(1, "");
auto &change_tracker = scene_delegate_->GetRenderIndex().GetChangeTracker();
change_tracker.MarkInstancerDirty(prim_id, pxr::HdChangeTracker::DirtyVisibility);
for (auto &m_inst : mesh_instances_.values()) {
m_inst.data->visible = visible;
for (auto &p : m_inst.data->submesh_paths()) {
change_tracker.MarkRprimDirty(p, pxr::HdChangeTracker::DirtyVisibility);
}
}
char name[16];
for (auto &l_inst : light_instances_.values()) {
for (int i = 0; i < l_inst.count; ++i) {
snprintf(name, sizeof(name), "L_%08x", i);
change_tracker.MarkRprimDirty(l_inst.data->prim_id.AppendElementString(name),
pxr::HdChangeTracker::DirtyVisibility);
}
}
}
return ret;
}
pxr::GfMatrix4d InstancerData::get_transform(pxr::SdfPath const &id) const
{
LightInstance *l_inst = light_instance(id);
@ -187,99 +117,6 @@ pxr::SdfPathVector InstancerData::prototypes() const
return paths;
}
void InstancerData::check_update(Object *object)
{
pxr::SdfPath path = object_prim_id(object);
MeshInstance *m_inst = mesh_instance(path);
if (m_inst) {
if (!is_instance_visible(object)) {
m_inst->data->remove();
mesh_instances_.remove(path);
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
prim_id, pxr::HdChangeTracker::AllDirty);
return;
}
m_inst->data->update();
if (m_inst->data->id->recalc & ID_RECALC_TRANSFORM) {
write_instances();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
prim_id, pxr::HdChangeTracker::AllDirty);
}
return;
}
LightInstance *l_inst = light_instance(path);
if (l_inst) {
if (!is_instance_visible(object)) {
l_inst->transforms.clear();
update_light_instance(*l_inst);
light_instances_.remove(path);
return;
}
Object *obj = (Object *)l_inst->data->id;
if (obj->id.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY) ||
((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY)
{
write_instances();
}
return;
}
/* Checking if object wasn't added to instances before */
if (is_supported(object) && is_instance_visible(object)) {
bool do_write_instances = false;
ListBase *lb = object_duplilist(
scene_delegate_->depsgraph, scene_delegate_->scene, (Object *)id);
LISTBASE_FOREACH (DupliObject *, dupli, lb) {
if (dupli->ob == object) {
do_write_instances = true;
break;
}
}
free_object_duplilist(lb);
if (do_write_instances) {
write_instances();
if (!mesh_instances_.is_empty()) {
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
prim_id, pxr::HdChangeTracker::AllDirty);
}
}
}
}
void InstancerData::check_remove(Set<std::string> &available_objects)
{
bool ret = false;
mesh_instances_.remove_if([&](auto item) {
bool res = !available_objects.contains(item.key.GetName());
if (res) {
item.value.data->remove();
ret = true;
};
return res;
});
if (ret) {
write_instances();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
prim_id, pxr::HdChangeTracker::AllDirty);
}
light_instances_.remove_if([&](auto item) {
bool res = !available_objects.contains(item.key.GetName());
if (res) {
item.value.transforms.clear();
update_light_instance(item.value);
};
return res;
});
}
void InstancerData::available_materials(Set<pxr::SdfPath> &paths) const
{
for (auto &m_inst : mesh_instances_.values()) {
@ -287,13 +124,6 @@ void InstancerData::available_materials(Set<pxr::SdfPath> &paths) const
}
}
void InstancerData::update_as_parent()
{
write_instances();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
prim_id, pxr::HdChangeTracker::AllDirty);
}
void InstancerData::update_double_sided(MaterialData *mat_data)
{
for (auto &m_inst : mesh_instances_.values()) {
@ -301,20 +131,94 @@ void InstancerData::update_double_sided(MaterialData *mat_data)
}
}
bool InstancerData::is_instance_visible(Object *object)
void InstancerData::pre_update()
{
eEvaluationMode deg_mode = DEG_get_mode(scene_delegate_->depsgraph);
int vis = BKE_object_visibility(object, deg_mode);
bool ret = vis & OB_VISIBLE_SELF;
if (deg_mode == DAG_EVAL_VIEWPORT) {
if (!ret && ((object->transflag & OB_DUPLI) == 0 ||
(object->transflag & OB_DUPLI &&
object->duplicator_visibility_flag & OB_DUPLI_FLAG_VIEWPORT)))
{
ret = true;
mesh_transforms_.clear();
for (auto &m_inst : mesh_instances_.values()) {
m_inst.indices.clear();
}
for (auto &l_inst : light_instances_.values()) {
l_inst.transforms.clear();
}
}
void InstancerData::update_instance(Object *parent_ob, DupliObject *dupli)
{
if (!ObjectData::is_visible(scene_delegate_, parent_ob, OB_VISIBLE_INSTANCES)) {
return;
}
Object *ob = dupli->ob;
if (!is_instance_supported(ob)) {
return;
}
if (!scene_delegate_->shading_settings.use_scene_lights && ob->type == OB_LAMP) {
return;
}
pxr::SdfPath p_id = object_prim_id(ob);
if (ob->type == OB_LAMP) {
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();
}
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 = mesh_instance(p_id);
if (!inst) {
inst = &mesh_instances_.lookup_or_add_default(p_id);
inst->data = std::make_unique<MeshData>(scene_delegate_, ob, p_id);
inst->data->init();
inst->data->insert();
}
else {
inst->data->update();
}
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));
}
}
void InstancerData::post_update()
{
/* Remove mesh intances without indices */
mesh_instances_.remove_if([&](auto item) {
bool res = item.value.indices.empty();
if (res) {
item.value.data->remove();
}
return res;
});
/* Update light intances and remove instances without transforms */
for (auto &l_inst : light_instances_.values()) {
update_light_instance(l_inst);
}
light_instances_.remove_if([&](auto item) { return item.value.transforms.empty(); });
/* Insert/remove/update instancer in RenderIndex */
pxr::HdRenderIndex &index = scene_delegate_->GetRenderIndex();
if (mesh_instances_.is_empty()) {
/* Important: removing instancer when light_instances_ are empty too */
if (index.HasInstancer(prim_id) && light_instances_.is_empty()) {
index.RemoveInstancer(prim_id);
ID_LOG(1, "Remove instancer");
}
}
else {
if (index.HasInstancer(prim_id)) {
index.GetChangeTracker().MarkInstancerDirty(prim_id, pxr::HdChangeTracker::AllDirty);
ID_LOG(1, "Update instancer");
}
else {
index.InsertInstancer(scene_delegate_, prim_id);
ID_LOG(1, "Insert instancer");
}
}
return ret;
}
pxr::SdfPath InstancerData::object_prim_id(Object *object) const
@ -339,69 +243,6 @@ int InstancerData::light_prim_id_index(pxr::SdfPath const &id) const
return index;
}
void InstancerData::write_instances()
{
mesh_transforms_.clear();
for (auto &m_inst : mesh_instances_.values()) {
m_inst.indices.clear();
}
for (auto &l_inst : light_instances_.values()) {
l_inst.transforms.clear();
}
ListBase *lb = object_duplilist(
scene_delegate_->depsgraph, scene_delegate_->scene, (Object *)id);
LISTBASE_FOREACH (DupliObject *, dupli, lb) {
Object *ob = dupli->ob;
if (!scene_delegate_->shading_settings.use_scene_lights && ob->type == OB_LAMP) {
continue;
}
if (!is_supported(ob) || !is_instance_visible(ob)) {
continue;
}
pxr::SdfPath p_id = object_prim_id(ob);
if (ob->type == OB_LAMP) {
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();
}
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 = mesh_instance(p_id);
if (!inst) {
inst = &mesh_instances_.lookup_or_add_default(p_id);
inst->data = std::make_unique<MeshData>(scene_delegate_, ob, p_id);
inst->data->init();
inst->data->insert();
}
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));
}
}
free_object_duplilist(lb);
/* Remove mesh intances without indices */
mesh_instances_.remove_if([&](auto item) {
bool res = item.value.indices.empty();
if (res) {
item.value.data->remove();
}
return res;
});
/* Update light intances and remove instances without transforms */
light_instances_.remove_if([&](auto item) {
update_light_instance(item.value);
return item.value.transforms.empty();
});
}
void InstancerData::update_light_instance(LightInstance &inst)
{
auto &render_index = scene_delegate_->GetRenderIndex();

View File

@ -12,7 +12,7 @@
namespace blender::render::hydra {
class InstancerData : public ObjectData {
class InstancerData : public IdData {
struct MeshInstance {
std::unique_ptr<MeshData> data;
pxr::VtIntArray indices;
@ -25,9 +25,8 @@ class InstancerData : public ObjectData {
};
public:
InstancerData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
static bool is_supported(Object *object);
static bool is_visible(BlenderSceneDelegate *scene_delegate, Object *object);
InstancerData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id);
static bool is_instance_supported(Object *object);
void init() override;
void insert() override;
@ -35,25 +34,28 @@ class InstancerData : public ObjectData {
void update() override;
pxr::VtValue get_data(pxr::TfToken const &key) const override;
bool update_visibility() override;
pxr::GfMatrix4d get_transform(pxr::SdfPath const &id) const;
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const;
pxr::VtIntArray indices(pxr::SdfPath const &id) const;
ObjectData *object_data(pxr::SdfPath const &id) const;
pxr::SdfPathVector prototypes() const;
void check_update(Object *object);
void check_remove(Set<std::string> &available_objects);
void available_materials(Set<pxr::SdfPath> &paths) const;
void update_as_parent();
void update_double_sided(MaterialData *mat_data);
/* Following update functions are working together:

Please add comment why this is done in this way

Please add comment why this is done in this way
pre_update()
update_instance()
update_instance()
...
post_update() */
void pre_update();
void update_instance(Object *parent_ob, DupliObject *dupli);
void post_update();
private:
bool is_instance_visible(Object *object);
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 write_instances();
void update_light_instance(LightInstance &inst);
MeshInstance *mesh_instance(pxr::SdfPath const &id) const;
LightInstance *light_instance(pxr::SdfPath const &id) const;
@ -63,6 +65,4 @@ class InstancerData : public ObjectData {
pxr::VtMatrix4dArray mesh_transforms_;
};
using InstancerDataMap = Map<pxr::SdfPath, std::unique_ptr<InstancerData>>;
} // namespace blender::render::hydra

View File

@ -111,19 +111,16 @@ void LightData::remove()
void LightData::update()
{
ID_LOG(1, "");
Object *object = (Object *)id;
Light *light = (Light *)object->data;
if (prim_type(light) != prim_type_) {
remove();
init();
insert();
return;
}
pxr::HdDirtyBits bits = pxr::HdLight::Clean;
if (id->recalc & ID_RECALC_GEOMETRY || light->id.recalc & ID_RECALC_GEOMETRY) {
if (prim_type(light) != prim_type_) {
remove();
init();
insert();
return;
}
init();
bits = pxr::HdLight::AllDirty;
}
@ -133,6 +130,7 @@ void LightData::update()
}
if (bits != pxr::HdChangeTracker::Clean) {
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(prim_id, bits);
ID_LOG(1, "");
}
}

View File

@ -67,9 +67,7 @@ void MaterialData::update()
m_data->update_double_sided(this);
}
}
for (auto &i_data : scene_delegate_->instancers_.values()) {
i_data->update_double_sided(this);
}
scene_delegate_->instancer_data_->update_double_sided(this);
}
}

View File

@ -8,7 +8,6 @@
#include "BKE_material.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h"
#include "BKE_object.h"
#include "blender_scene_delegate.h"
#include "mesh.h"
@ -299,12 +298,15 @@ void MeshData::write_materials()
}
pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat);
m.mat_data = scene_delegate_->materials_
.lookup_or_add(p_id,
std::make_unique<MaterialData>(scene_delegate_, mat, p_id))
.get();
m.mat_data->init();
m.mat_data->insert();
m.mat_data = scene_delegate_->material_data(p_id);
if (!m.mat_data) {
m.mat_data = scene_delegate_->materials_
.lookup_or_add(p_id,
std::make_unique<MaterialData>(scene_delegate_, mat, p_id))
.get();
m.mat_data->init();
m.mat_data->insert();
}
}
}

View File

@ -1,7 +1,6 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "BKE_object.h"
#include "DEG_depsgraph_query.h"
#include "blender_scene_delegate.h"
@ -68,26 +67,14 @@ bool ObjectData::is_supported(Object *object)
return false;
}
bool ObjectData::is_visible(BlenderSceneDelegate *scene_delegate, Object *object)
bool ObjectData::is_visible(BlenderSceneDelegate *scene_delegate, Object *object, int mode)
{
eEvaluationMode deg_mode = DEG_get_mode(scene_delegate->depsgraph);
int vis = BKE_object_visibility(object, deg_mode);
bool ret = vis & OB_VISIBLE_SELF;
bool ret = BKE_object_visibility(object, deg_mode) & mode;
if (deg_mode == DAG_EVAL_VIEWPORT) {
ret &= BKE_object_is_visible_in_viewport(scene_delegate->view3d, object);
}
else {
if (ret) {
/* If some of parent object is instancer, then currenct object
* is invisible in Final render */
for (Object *ob = object->parent; ob != nullptr; ob = ob->parent) {
if (ob->transflag & OB_DUPLI) {
ret = false;
break;
}
}
}
}
/* Note: visibility for final render we are taking from depsgraph */
return ret;
}
@ -98,24 +85,6 @@ bool ObjectData::update_visibility()
return visible != prev_visible;
}
void ObjectData::update_parent()
{
Object *object = (Object *)id;
if (parent_ != object->parent) {
ID_LOG(1, "");
parent_ = object->parent;
/* Looking for corresponded instancer and update it as parent */
for (Object *ob = parent_; ob != nullptr; ob = ob->parent) {
InstancerData *i_data = scene_delegate_->instancer_data(
scene_delegate_->instancer_prim_id(ob));
if (i_data) {
i_data->update_as_parent();
}
}
}
}
void ObjectData::write_transform()
{
transform = gf_matrix_from_transform(((Object *)id)->object_to_world);

View File

@ -7,6 +7,7 @@
#include <pxr/base/gf/matrix4d.h>
#include "BKE_layer.h"
#include "BKE_object.h"
#include "BLI_map.hh"
#include "DNA_object_types.h"
@ -23,18 +24,17 @@ class ObjectData : public IdData {
Object *object,
pxr::SdfPath const &prim_id);
static bool is_supported(Object *object);
static bool is_visible(BlenderSceneDelegate *scene_delegate, Object *object);
static bool is_visible(BlenderSceneDelegate *scene_delegate,
Object *object,
int mode = OB_VISIBLE_SELF);
virtual bool update_visibility();
void update_parent();
pxr::GfMatrix4d transform;
bool visible = true;
protected:
void write_transform();
Object *parent_ = nullptr;
};
using ObjectDataMap = Map<pxr::SdfPath, std::unique_ptr<ObjectData>>;

View File

@ -176,11 +176,8 @@ void WorldData::write_transform()
{
transform = pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -90), pxr::GfVec3d());
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -180),
pxr::GfVec3d());
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), 90.0),
pxr::GfVec3d());
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(1.0, 0.0, 0.0), -180), pxr::GfVec3d());
transform *= pxr::GfMatrix4d(pxr::GfRotation(pxr::GfVec3d(0.0, 0.0, 1.0), 90.0), pxr::GfVec3d());
}
} // namespace blender::render::hydra