Fix review comments #27

Merged
Bogdan Nagirniak merged 14 commits from BLEN-392 into hydra-render 2023-04-21 15:02:44 +02:00
10 changed files with 458 additions and 299 deletions
Showing only changes of commit 395fbf9d53 - Show all commits

View File

@ -20,112 +20,6 @@ BlenderSceneDelegate::BlenderSceneDelegate(pxr::HdRenderIndex *parent_index,
{ {
} }
void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
{
bool is_populated = depsgraph_ != nullptr;
depsgraph_ = deps;
context_ = cont;
scene_ = DEG_get_input_scene(depsgraph_);
view3d_ = CTX_wm_view3d(context_);
if (!is_populated) {
/* Export initial objects */
update_collection(false, false);
update_world();
return;
}
/* Working with updates */
bool do_update_collection = false;
bool do_update_visibility = false;
bool do_update_world = false;
unsigned int scene_recalc = ((ID *)scene_)->recalc;
if (scene_recalc) {
/* Checking scene updates */
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"Update: %s [%s]",
((ID *)scene_)->name,
std::bitset<32>(scene_recalc).to_string().c_str());
if (scene_recalc & ID_RECALC_BASE_FLAGS) {
do_update_visibility = true;
}
if (scene_recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY)) {
do_update_collection = true;
}
if (scene_recalc & ID_RECALC_AUDIO_VOLUME) {
if ((scene_->world && !world_data_) || (!scene_->world && world_data_)) {
do_update_world = true;
}
}
if (do_update_collection || do_update_visibility) {
update_collection(do_update_collection, do_update_visibility);
}
}
/* Checking other objects updates */
DEGIDIterData data = {0};
data.graph = depsgraph_;
data.only_updated = true;
ITER_BEGIN (
DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"Update: %s [%s]",
id->name,
std::bitset<32>(id->recalc).to_string().c_str());
switch (GS(id->name)) {
case ID_OB: {
Object *object = (Object *)id;
if (!ObjectData::is_supported(object)) {
break;
}
add_update_object(object);
} break;
case ID_MA: {
MaterialData *mat_data = material_data(MaterialData::prim_id(this, (Material *)id));
if (mat_data) {
mat_data->update();
}
} break;
case ID_WO: {
if (id->recalc & ID_RECALC_SHADING) {
do_update_world = true;
}
} break;
default:
break;
}
}
ITER_END;
if (do_update_world) {
update_world();
}
}
void BlenderSceneDelegate::clear()
{
for (auto &it : materials_) {
it.second->remove();
}
for (auto &it : objects_) {
it.second->remove();
}
materials_.clear();
objects_.clear();
}
pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id) pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
@ -145,11 +39,6 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id)
return world_data_->transform(); return world_data_->transform();
} }
InstancerData *i_data = instancer_data(id);
if (i_data) {
return i_data->transform();
}
return pxr::GfMatrix4d(); return pxr::GfMatrix4d();
} }
@ -200,7 +89,7 @@ pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(
InstancerData *i_data = instancer_data(id); InstancerData *i_data = instancer_data(id);
if (i_data) { if (i_data) {
return i_data->instancer_primvar_descriptors(interpolation); return i_data->primvar_descriptors(interpolation);
} }
return pxr::HdPrimvarDescriptorVector(); return pxr::HdPrimvarDescriptorVector();
@ -232,9 +121,9 @@ bool BlenderSceneDelegate::GetVisible(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());
InstancerData *i_data = instancer_data(prim_id, true); InstancerData *i_data = instancer_data(prim_id.GetParentPath());
if (i_data) { if (i_data) {
return i_data->instancer_id; return i_data->p_id_;
} }
return pxr::SdfPath(); return pxr::SdfPath();
} }
@ -242,9 +131,8 @@ pxr::SdfPath BlenderSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id)
pxr::SdfPathVector BlenderSceneDelegate::GetInstancerPrototypes(pxr::SdfPath const &instancer_id) pxr::SdfPathVector BlenderSceneDelegate::GetInstancerPrototypes(pxr::SdfPath const &instancer_id)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", instancer_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", instancer_id.GetText());
pxr::SdfPathVector paths; InstancerData *i_data = instancer_data(instancer_id);
paths.push_back(instancer_id.GetParentPath()); return i_data->prototypes();
return paths;
} }
pxr::VtIntArray BlenderSceneDelegate::GetInstanceIndices(pxr::SdfPath const &instancer_id, pxr::VtIntArray BlenderSceneDelegate::GetInstanceIndices(pxr::SdfPath const &instancer_id,
@ -252,7 +140,7 @@ pxr::VtIntArray BlenderSceneDelegate::GetInstanceIndices(pxr::SdfPath const &ins
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", instancer_id.GetText(), prototype_id.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", instancer_id.GetText(), prototype_id.GetText());
InstancerData *i_data = instancer_data(instancer_id); InstancerData *i_data = instancer_data(instancer_id);
return i_data->instance_indices(); return i_data->indices(prototype_id);
} }
pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &instancer_id) pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &instancer_id)
@ -262,14 +150,55 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &
return i_data->transform(); return i_data->transform();
} }
void BlenderSceneDelegate::populate(Depsgraph * deps, bContext * cont)
{
bool is_populated = depsgraph_ != nullptr;
depsgraph_ = deps;
context_ = cont;
scene_ = DEG_get_input_scene(depsgraph_);
view3d_ = CTX_wm_view3d(context_);
if (is_populated) {
check_updates();
}
else {
add_new_objects();
update_world();
}
}
void BlenderSceneDelegate::clear()
{
for (auto &it : objects_) {
it.second->remove();
}
for (auto &it : instancers_) {
it.second->remove();
}
for (auto &it : materials_) {
it.second->remove();
}
objects_.clear();
instancers_.clear();
materials_.clear();
}
ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id) ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id)
{ {
auto it = objects_.find(id); auto it = objects_.find(id);
if (it == objects_.end()) { if (it != objects_.end()) {
return nullptr;
}
return it->second.get(); return it->second.get();
} }
InstancerData *i_data = instancer_data(id.GetParentPath());
if (i_data) {
return i_data->object_data(id);
}
return nullptr;
}
MeshData *BlenderSceneDelegate::mesh_data(pxr::SdfPath const &id) MeshData *BlenderSceneDelegate::mesh_data(pxr::SdfPath const &id)
{ {
@ -290,36 +219,20 @@ MaterialData *BlenderSceneDelegate::material_data(pxr::SdfPath const &id)
return it->second.get(); return it->second.get();
} }
InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id, bool base_prim) InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id)
{ {
if (base_prim) { auto it = instancers_.find(id);
return dynamic_cast<InstancerData *>(object_data(id)); if (it != instancers_.end()) {
} return it->second.get();
return dynamic_cast<InstancerData *>(object_data(id.GetParentPath()));
}
InstancerData *BlenderSceneDelegate::instancer_data(Object *object)
{
InstancerData *i_data;
for (auto &it : objects_) {
i_data = dynamic_cast<InstancerData *>(it.second.get());
if (i_data && i_data->is_base(object)) {
return i_data;
}
} }
return nullptr; return nullptr;
} }
void BlenderSceneDelegate::add_update_object(Object *object) void BlenderSceneDelegate::update_objects(Object *object)
{ {
if ((object->transflag & OB_DUPLI) && InstancerData::is_supported(object)) { if (!ObjectData::is_supported(object)) {
add_update_instancer(object); return;
} }
InstancerData *i_data = instancer_data(object);
if (i_data) {
i_data->update();
}
pxr::SdfPath id = ObjectData::prim_id(this, object); pxr::SdfPath id = ObjectData::prim_id(this, object);
ObjectData *obj_data = object_data(id); ObjectData *obj_data = object_data(id);
if (obj_data) { if (obj_data) {
@ -334,16 +247,33 @@ void BlenderSceneDelegate::add_update_object(Object *object)
obj_data->update_visibility(view3d_); obj_data->update_visibility(view3d_);
} }
void BlenderSceneDelegate::add_update_instancer(Object *object) void BlenderSceneDelegate::update_instancers(Object *object)
{ {
/* Check object inside instancers */
for (auto &it : instancers_) {
it.second->check_update(object);
}
pxr::SdfPath id = InstancerData::prim_id(this, object); pxr::SdfPath id = InstancerData::prim_id(this, object);
InstancerData *i_data = instancer_data(id, true); InstancerData *i_data = instancer_data(id);
if (i_data) { if (i_data) {
if (object->transflag & OB_DUPLI) {
i_data->update(); i_data->update();
}
else {
i_data->remove();
instancers_.erase(id);
}
return; return;
} }
objects_[id] = InstancerData::create(this, object); if ((object->transflag & OB_DUPLI) == 0) {
i_data = instancer_data(id, true); return;
}
if (view3d_ && !BKE_object_is_visible_in_viewport(view3d_, object)) {
return;
}
instancers_[id] = InstancerData::create(this, object);
i_data = instancer_data(id);
i_data->update_visibility(view3d_); i_data->update_visibility(view3d_);
} }
@ -366,19 +296,87 @@ void BlenderSceneDelegate::update_world()
} }
} }
void BlenderSceneDelegate::update_collection(bool remove, bool visibility) void BlenderSceneDelegate::check_updates()
{ {
if (visibility) { /* Working with updates */
/* Check and update visibility */ bool do_update_collection = false;
for (auto &obj : objects_) { bool do_update_visibility = false;
obj.second->update_visibility(view3d_); bool do_update_world = false;
unsigned int scene_recalc = scene_->id.recalc;
if (scene_recalc) {
/* Checking scene updates */
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"Update: %s [%s]",
((ID *)scene_)->name,
std::bitset<32>(scene_recalc).to_string().c_str());
if (scene_recalc & ID_RECALC_BASE_FLAGS) {
do_update_visibility = true;
}
if (scene_recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY)) {
do_update_collection = true;
}
if (scene_recalc & ID_RECALC_AUDIO_VOLUME) {
if ((scene_->world && !world_data_) || (!scene_->world && world_data_)) {
do_update_world = true;
}
} }
} }
/* Export of new visible objects which were not exported before */ /* Checking other objects updates */
std::set<pxr::SdfPath> available_objects; DEGIDIterData data = {0};
pxr::SdfPath id; data.graph = depsgraph_;
data.only_updated = true;
ITER_BEGIN (
DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) {
BogdanNagirniak marked this conversation as resolved Outdated

This block need to remove. It was moved below in earlier commit

This block need to remove. It was moved below in earlier commit
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"Update: %s [%s]",
id->name,
std::bitset<32>(id->recalc).to_string().c_str());
switch (GS(id->name)) {
case ID_OB: {
Object *object = (Object *)id;
update_objects(object);
update_instancers(object);
} break;
case ID_MA: {
MaterialData *mat_data = material_data(MaterialData::prim_id(this, (Material *)id));
if (mat_data) {
mat_data->update();
}
} break;
case ID_WO: {
if (id->recalc & ID_RECALC_SHADING) {
do_update_world = true;
}
} break;
default:
break;
}
}
ITER_END;
if (do_update_world) {
update_world();
}
if (do_update_collection) {
remove_unused_objects();
}
if (do_update_visibility) {
update_visibility();
}
}
void BlenderSceneDelegate::add_new_objects()
{
DEGObjectIterSettings settings = {0}; DEGObjectIterSettings settings = {0};
settings.depsgraph = depsgraph_; settings.depsgraph = depsgraph_;
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE | settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
@ -394,29 +392,57 @@ void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
Object *, Object *,
object) { object) {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "Add %s", ((ID *)object)->name);
if (!ObjectData::is_supported(object)) { if (!ObjectData::is_supported(object)) {
continue; continue;
} }
id = ObjectData::prim_id(this, object); update_objects(object);
if (remove) { update_instancers(object);
available_objects.insert(id);
if ((object->transflag & OB_DUPLI) && InstancerData::is_supported(object)) {
available_objects.insert(InstancerData::prim_id(this, object));
} }
ITER_END;
} }
if (!object_data(id)) { void BlenderSceneDelegate::remove_unused_objects()
add_update_object(object); {
/* Get available objects */
std::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;
DEGObjectIterData data = {0};
data.settings = &settings;
data.graph = settings.depsgraph;
data.flag = settings.flags;
ITER_BEGIN (DEG_iterator_objects_begin,
DEG_iterator_objects_next,
DEG_iterator_objects_end,
&data,
Object *,
object) {
if (!ObjectData::is_supported(object)) {
continue;
} }
available_objects.insert(ObjectData::prim_id(this, object).GetName());
available_objects.insert(InstancerData::prim_id(this, object).GetName());
} }
ITER_END; ITER_END;
if (remove) { /* Remove unused instancers */
/* remove unused objects */ for (auto it = instancers_.begin(); it != instancers_.end(); ++it) {
if (available_objects.find(it->first.GetName()) != available_objects.end()) {
/* Remove objects from instancers */
it->second->check_remove(available_objects);
continue;
}
it->second->remove();
instancers_.erase(it);
it = instancers_.begin();
}
/* Remove unused objects */
for (auto it = objects_.begin(); it != objects_.end(); ++it) { for (auto it = objects_.begin(); it != objects_.end(); ++it) {
if (available_objects.find(it->first) != available_objects.end()) { if (available_objects.find(it->first.GetName()) != available_objects.end()) {
continue; continue;
} }
it->second->remove(); it->second->remove();
@ -424,10 +450,10 @@ void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
it = objects_.begin(); it = objects_.begin();
} }
/* remove unused materials */ /* Remove unused materials */
std::set<pxr::SdfPath> available_materials; std::set<pxr::SdfPath> available_materials;
for (auto &obj : objects_) { for (auto &it : objects_) {
MeshData *m_data = dynamic_cast<MeshData *>(obj.second.get()); MeshData *m_data = dynamic_cast<MeshData *>(it.second.get());
if (!m_data) { if (!m_data) {
continue; continue;
} }
@ -436,6 +462,9 @@ void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
available_materials.insert(mat_id); available_materials.insert(mat_id);
} }
} }
for (auto &it : instancers_) {
it.second->available_materials(available_materials);
}
for (auto it = materials_.begin(); it != materials_.end(); ++it) { for (auto it = materials_.begin(); it != materials_.end(); ++it) {
if (available_materials.find(it->first) != available_materials.end()) { if (available_materials.find(it->first) != available_materials.end()) {
continue; continue;
@ -445,6 +474,44 @@ void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
it = materials_.begin(); it = materials_.begin();
} }
} }
void BlenderSceneDelegate::update_visibility()
{
for (auto &it : objects_) {
it.second->update_visibility(view3d_);
}
for (auto &it : instancers_) {
it.second->update_visibility(view3d_);
}
/* Add objects 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_VISIBLE |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
DEGObjectIterData data = {0};
data.settings = &settings;
data.graph = settings.depsgraph;
data.flag = settings.flags;
ITER_BEGIN (DEG_iterator_objects_begin,
DEG_iterator_objects_next,
DEG_iterator_objects_end,
&data,
Object *,
object) {
if (!ObjectData::is_supported(object)) {
continue;
}
if (!object_data(ObjectData::prim_id(this, object))) {
update_objects(object);
}
if (!instancer_data(InstancerData::prim_id(this, object))) {
update_instancers(object);
}
}
ITER_END;
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -32,9 +32,6 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
BlenderSceneDelegate::EngineType engine_type); BlenderSceneDelegate::EngineType engine_type);
~BlenderSceneDelegate() override = default; ~BlenderSceneDelegate() override = default;
void populate(Depsgraph *depsgraph, bContext *context);
void clear();
/* Delegate methods */ /* Delegate methods */
pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override; pxr::HdMeshTopology GetMeshTopology(pxr::SdfPath const &id) override;
pxr::GfMatrix4d GetTransform(pxr::SdfPath const &id) override; pxr::GfMatrix4d GetTransform(pxr::SdfPath const &id) override;
@ -51,6 +48,9 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
pxr::SdfPath const &prototype_id) override; pxr::SdfPath const &prototype_id) override;
pxr::GfMatrix4d GetInstancerTransform(pxr::SdfPath const &instancer_id) override; pxr::GfMatrix4d GetInstancerTransform(pxr::SdfPath const &instancer_id) override;
void populate(Depsgraph *depsgraph, bContext *context);
void clear();
EngineType engine_type; EngineType engine_type;
private: private:
@ -58,13 +58,15 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
MeshData *mesh_data(pxr::SdfPath const &id); MeshData *mesh_data(pxr::SdfPath const &id);
LightData *light_data(pxr::SdfPath const &id); LightData *light_data(pxr::SdfPath const &id);
MaterialData *material_data(pxr::SdfPath const &id); MaterialData *material_data(pxr::SdfPath const &id);
InstancerData *instancer_data(pxr::SdfPath const &id, bool base_prim = false); InstancerData *instancer_data(pxr::SdfPath const &id);
InstancerData *instancer_data(Object *object);
void add_update_object(Object *object); void update_objects(Object *object);
void add_update_instancer(Object *object); void update_instancers(Object *object);
void update_world(); void update_world();
void update_collection(bool remove, bool visibility); void check_updates();
void add_new_objects();
void remove_unused_objects();
void update_visibility();
Depsgraph *depsgraph_ = nullptr; Depsgraph *depsgraph_ = nullptr;
bContext *context_ = nullptr; bContext *context_ = nullptr;
@ -73,6 +75,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
ObjectDataMap objects_; ObjectDataMap objects_;
MaterialDataMap materials_; MaterialDataMap materials_;
InstancerDataMap instancers_;
std::unique_ptr<WorldData> world_data_; std::unique_ptr<WorldData> world_data_;
}; };

View File

@ -12,8 +12,11 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class BlenderSceneDelegate; class BlenderSceneDelegate;
class InstancerData;
class IdData { class IdData {
friend InstancerData;
public: public:
IdData(BlenderSceneDelegate *scene_delegate, ID *id); IdData(BlenderSceneDelegate *scene_delegate, ID *id);
virtual ~IdData() = default; virtual ~IdData() = default;
@ -37,4 +40,7 @@ template<class T> const T IdData::get_data(pxr::TfToken const &key) const
return get_data(key).Get<T>(); return get_data(key).Get<T>();
} }
#define ID_LOG(level, msg, ...) \
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, level, "%s (%s): " msg, p_id_.GetText(), id_->name, __VA_ARGS__);
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -10,16 +10,10 @@
namespace blender::render::hydra { namespace blender::render::hydra {
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, Object *object) InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, Object *object)
: MeshData(scene_delegate, object), parent_obj_(object) : ObjectData(scene_delegate, object)
{ {
id_ = nullptr;
p_id_ = prim_id(scene_delegate, object); p_id_ = prim_id(scene_delegate, object);
instancer_id = p_id_.AppendElementString("Instancer"); ID_LOG(2, "");
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"%s, instancer_id=%s",
((ID *)parent_obj_)->name,
instancer_id.GetText());
} }
bool InstancerData::is_supported(Object *object) bool InstancerData::is_supported(Object *object)
@ -58,71 +52,56 @@ pxr::SdfPath InstancerData::prim_id(BlenderSceneDelegate *scene_delegate, Object
void InstancerData::init() void InstancerData::init()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", ((ID *)parent_obj_)->name); ID_LOG(2, "");
set_instances(); set_instances();
MeshData::init();
} }
void InstancerData::insert() void InstancerData::insert()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", ((ID *)parent_obj_)->name); ID_LOG(2, "");
MeshData::insert(); scene_delegate_->GetRenderIndex().InsertInstancer(scene_delegate_, p_id_);
for (auto &it : instances_) {
if (face_vertex_counts_.empty()) { it.second.obj_data->insert();
return;
} }
scene_delegate_->GetRenderIndex().InsertInstancer(scene_delegate_, instancer_id);
} }
void InstancerData::remove() void InstancerData::remove()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", ((ID *)parent_obj_)->name); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", p_id_.GetText());
for (auto &it : instances_) {
if (!scene_delegate_->GetRenderIndex().HasInstancer(instancer_id)) { it.second.obj_data->remove();
return;
} }
scene_delegate_->GetRenderIndex().RemoveInstancer(instancer_id); scene_delegate_->GetRenderIndex().RemoveInstancer(p_id_);
MeshData::remove();
} }
void InstancerData::update() void InstancerData::update()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", ((ID *)parent_obj_)->name); ID_LOG(2, "");
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean; pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
unsigned int recalc = ((ID *)parent_obj_)->recalc;
Object *object = (Object *)id_; Object *object = (Object *)id_;
if ((id_->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) { if ((id_->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
init(); set_instances();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
p_id_, pxr::HdChangeTracker::AllDirty);
return;
}
if ((recalc & ID_RECALC_GEOMETRY) || (((ID *)parent_obj_->data)->recalc & ID_RECALC_GEOMETRY)) {
init();
bits |= pxr::HdChangeTracker::AllDirty; bits |= pxr::HdChangeTracker::AllDirty;
} }
else if (recalc & ID_RECALC_TRANSFORM || id_->recalc & ID_RECALC_TRANSFORM) { else if (id_->recalc & ID_RECALC_TRANSFORM) {
set_instances(); set_instances();
bits |= pxr::HdChangeTracker::DirtyTransform; bits |= pxr::HdChangeTracker::DirtyTransform;
} }
if (bits != pxr::HdChangeTracker::Clean) { if (bits != pxr::HdChangeTracker::Clean) {
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(instancer_id, bits); scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(p_id_, bits);
} }
} }
pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const pxr::VtValue InstancerData::get_data(pxr::TfToken const &key) const
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s [%s]", id_->name, key.GetText()); ID_LOG(3, "%s", key.GetText());
pxr::VtValue ret;
if (key == pxr::HdInstancerTokens->instanceTransform) { if (key == pxr::HdInstancerTokens->instanceTransform) {
return pxr::VtValue(transforms_); ret = transforms_;
} }
return MeshData::get_data(key); return ret;
} }
pxr::GfMatrix4d InstancerData::transform() pxr::GfMatrix4d InstancerData::transform()
@ -136,18 +115,20 @@ bool InstancerData::update_visibility(View3D *view3d)
return false; return false;
} }
bool prev_visible = visible; bool ret = ObjectData::update_visibility(view3d);
visible = BKE_object_is_visible_in_viewport(view3d, parent_obj_);
bool ret = visible != prev_visible;
if (ret) { if (ret) {
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty( scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
p_id_, pxr::HdChangeTracker::DirtyVisibility); p_id_, pxr::HdChangeTracker::DirtyVisibility);
for (auto &it : instances_) {
it.second.obj_data->visible = visible;
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
it.second.obj_data->p_id_, pxr::HdChangeTracker::DirtyVisibility);
}
} }
return ret; return ret;
} }
pxr::HdPrimvarDescriptorVector InstancerData::instancer_primvar_descriptors( pxr::HdPrimvarDescriptorVector InstancerData::primvar_descriptors(pxr::HdInterpolation interpolation)
pxr::HdInterpolation interpolation)
{ {
pxr::HdPrimvarDescriptorVector primvars; pxr::HdPrimvarDescriptorVector primvars;
if (interpolation == pxr::HdInterpolationInstance) { if (interpolation == pxr::HdInterpolationInstance) {
@ -157,47 +138,131 @@ pxr::HdPrimvarDescriptorVector InstancerData::instancer_primvar_descriptors(
return primvars; return primvars;
} }
pxr::VtIntArray InstancerData::instance_indices() pxr::VtIntArray InstancerData::indices(pxr::SdfPath const &id)
{ {
pxr::VtIntArray ret(transforms_.size()); return instances_[id].indices;
for (size_t i = 0; i < ret.size(); ++i) {
ret[i] = i;
}
return ret;
} }
bool InstancerData::is_base(Object *object) const ObjectData *InstancerData::object_data(pxr::SdfPath const &id)
{ {
return (ID *)object == id_; return instances_[id].obj_data.get();
} }
bool InstancerData::set_instances() pxr::SdfPathVector InstancerData::prototypes()
{ {
ID *prev_id = id_; pxr::SdfPathVector paths;
id_ = nullptr; for (auto &it : instances_) {
transforms_.clear(); paths.push_back(it.first);
ListBase *lb = object_duplilist(
scene_delegate_->depsgraph_, scene_delegate_->scene_, parent_obj_);
LISTBASE_FOREACH (DupliObject *, dupli, lb) {
if (!id_) {
/* TODO: We create instances only for object in first dupli.
Instances should be created for all objects */
id_ = (ID *)dupli->ob;
} }
if (id_ != (ID *)dupli->ob) { return paths;
}
void InstancerData::check_update(Object *object)
{
pxr::SdfPath path = ObjectData::prim_id(scene_delegate_, object);
path = p_id_.AppendElementString(path.GetName());
auto it = instances_.find(path);
if (it == instances_.end()) {
return;
}
ObjectData *obj_data = it->second.obj_data.get();
obj_data->update();
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
if (object->id.recalc & ID_RECALC_TRANSFORM) {
set_instances();
bits |= pxr::HdChangeTracker::DirtyTransform;
}
if (bits != pxr::HdChangeTracker::Clean) {
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(p_id_, bits);
}
}
void InstancerData::check_remove(std::set<std::string> &available_objects)
{
bool ret = false;
for (auto it = instances_.begin(); it != instances_.end(); ++it) {
if (available_objects.find(it->first.GetName()) != available_objects.end()) {
continue; continue;
} }
it->second.obj_data->remove();
instances_.erase(it);
it = instances_.begin();
ret = true;
}
if (ret) {
set_instances();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(p_id_,
pxr::HdChangeTracker::AllDirty);
}
}
void InstancerData::available_materials(std::set<pxr::SdfPath> &paths)
{
for (auto &it : instances_) {
pxr::SdfPath mat_id = ((MeshData *)it.second.obj_data.get())->material_id();
if (!mat_id.IsEmpty()) {
paths.insert(mat_id);
}
}
}
void InstancerData::set_instances()
{
transforms_.clear();
for (auto &it : instances_) {
it.second.indices.clear();
}
int index = 0;
Instance *inst;
pxr::SdfPath path;
ListBase *lb = object_duplilist(scene_delegate_->depsgraph_, scene_delegate_->scene_, (Object *)id_);
LISTBASE_FOREACH (DupliObject *, dupli, lb) {
path = ObjectData::prim_id(scene_delegate_, dupli->ob);
path = p_id_.AppendElementString(path.GetName());
auto it = instances_.find(path);
if (it == instances_.end()) {
inst = &instances_[path];
if (!is_supported(dupli->ob)) {
continue;
}
inst->obj_data = std::make_unique<InstanceMeshData>(scene_delegate_, dupli->ob, path);
inst->obj_data->init();
inst->obj_data->insert();
}
else {
inst = &it->second;
}
transforms_.push_back(gf_matrix_from_transform(dupli->mat)); transforms_.push_back(gf_matrix_from_transform(dupli->mat));
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, inst->indices.push_back(index);
2, ID_LOG(2, "Instance %s %d", inst->obj_data->id_->name, index);
"Instance %s (%s) %d", ++index;
id_->name,
((ID *)dupli->ob)->name,
dupli->random_id);
} }
free_object_duplilist(lb); free_object_duplilist(lb);
return id_ != prev_id; /* Remove intances without indices */
for (auto it = instances_.begin(); it != instances_.end(); ++it) {
if (!it->second.indices.empty()) {
continue;
}
it->second.obj_data->remove();
instances_.erase(it);
it = instances_.begin();
}
}
InstanceMeshData::InstanceMeshData(BlenderSceneDelegate *scene_delegate,
Object *object,
pxr::SdfPath const &p_id)
: MeshData(scene_delegate, object)
{
this->p_id_ = p_id;
}
pxr::GfMatrix4d InstanceMeshData::transform()
{
return pxr::GfMatrix4d(1.0);
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -9,7 +9,14 @@
namespace blender::render::hydra { namespace blender::render::hydra {
class InstancerData : public MeshData { class InstancerData : public ObjectData {
friend BlenderSceneDelegate;
struct Instance {
std::unique_ptr<ObjectData> obj_data;
pxr::VtIntArray indices;
};
public: public:
InstancerData(BlenderSceneDelegate *scene_delegate, Object *object); InstancerData(BlenderSceneDelegate *scene_delegate, Object *object);
@ -27,17 +34,28 @@ class InstancerData : public MeshData {
pxr::GfMatrix4d transform() override; pxr::GfMatrix4d transform() override;
bool update_visibility(View3D *view3d) override; bool update_visibility(View3D *view3d) override;
pxr::HdPrimvarDescriptorVector instancer_primvar_descriptors(pxr::HdInterpolation interpolation); pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation);
pxr::VtIntArray instance_indices(); pxr::VtIntArray indices(pxr::SdfPath const &id);
bool is_base(Object *object) const; ObjectData *object_data(pxr::SdfPath const &id);
pxr::SdfPathVector prototypes();
pxr::SdfPath instancer_id; void check_update(Object *object);
void check_remove(std::set<std::string> &available_objects);
void available_materials(std::set<pxr::SdfPath> &paths);
private: private:
bool set_instances(); void set_instances();
Object *parent_obj_; pxr::TfHashMap<pxr::SdfPath, Instance, pxr::SdfPath::Hash> instances_;
pxr::VtMatrix4dArray transforms_; pxr::VtMatrix4dArray transforms_;
}; };
using InstancerDataMap =
pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<InstancerData>, pxr::SdfPath::Hash>;
class InstanceMeshData : public MeshData {
public:
InstanceMeshData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &p_id);
pxr::GfMatrix4d transform() override;
};
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -17,12 +17,12 @@ namespace blender::render::hydra {
LightData::LightData(BlenderSceneDelegate *scene_delegate, Object *object) LightData::LightData(BlenderSceneDelegate *scene_delegate, Object *object)
: ObjectData(scene_delegate, object) : ObjectData(scene_delegate, object)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s id=%s", id_->name, p_id_.GetText()); ID_LOG(2, "");
} }
void LightData::init() void LightData::init()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", id_->name); ID_LOG(2, "");
Light *light = (Light *)((Object *)id_)->data; Light *light = (Light *)((Object *)id_)->data;
data_.clear(); data_.clear();

View File

@ -24,7 +24,7 @@ MaterialData::MaterialData(BlenderSceneDelegate *scene_delegate, Material *mater
: IdData(scene_delegate, (ID *)material) : IdData(scene_delegate, (ID *)material)
{ {
p_id_ = prim_id(scene_delegate, material); p_id_ = prim_id(scene_delegate, material);
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s, id=%s", id_->name, p_id_.GetText()); ID_LOG(2, "");
} }
std::unique_ptr<MaterialData> MaterialData::create(BlenderSceneDelegate *scene_delegate, std::unique_ptr<MaterialData> MaterialData::create(BlenderSceneDelegate *scene_delegate,
@ -47,7 +47,7 @@ pxr::SdfPath MaterialData::prim_id(BlenderSceneDelegate *scene_delegate, Materia
void MaterialData::init() void MaterialData::init()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", id_->name); ID_LOG(2, "");
material_network_map_ = pxr::VtValue(); material_network_map_ = pxr::VtValue();
@ -84,11 +84,7 @@ void MaterialData::init()
PyGILState_Release(gstate); PyGILState_Release(gstate);
mtlx_path_ = pxr::SdfAssetPath(path, path); mtlx_path_ = pxr::SdfAssetPath(path, path);
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, ID_LOG(2, "mtlx=%s", mtlx_path_.GetResolvedPath().c_str());
2,
"Export: %s, mtlx=%s",
id_->name,
mtlx_path_.GetResolvedPath().c_str());
} }
void MaterialData::insert() void MaterialData::insert()
@ -119,7 +115,7 @@ pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
if (!mtlx_path_.GetResolvedPath().empty()) { if (!mtlx_path_.GetResolvedPath().empty()) {
ret = mtlx_path_; ret = mtlx_path_;
} }
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", key.GetText()); ID_LOG(3, "%s", key.GetText());
} }
return ret; return ret;
} }

View File

@ -18,7 +18,7 @@ namespace blender::render::hydra {
MeshData::MeshData(BlenderSceneDelegate *scene_delegate, Object *object) MeshData::MeshData(BlenderSceneDelegate *scene_delegate, Object *object)
: ObjectData(scene_delegate, object), mat_data_(nullptr) : ObjectData(scene_delegate, object), mat_data_(nullptr)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s, id=%s", id_->name, p_id_.GetText()); ID_LOG(2, "");
} }
void MeshData::init() void MeshData::init()

View File

@ -84,7 +84,11 @@ bool ObjectData::update_visibility(View3D *view3d)
bool prev_visible = visible; bool prev_visible = visible;
visible = BKE_object_is_visible_in_viewport(view3d, (Object *)id_); visible = BKE_object_is_visible_in_viewport(view3d, (Object *)id_);
return visible != prev_visible; bool ret = visible != prev_visible;
if (ret) {
ID_LOG(2, "");
}
return ret;
} }
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -32,7 +32,7 @@ WorldData::WorldData(BlenderSceneDelegate *scene_delegate, World *world, bContex
: IdData(scene_delegate, (ID *)world), context_(context) : IdData(scene_delegate, (ID *)world), context_(context)
{ {
p_id_ = prim_id(scene_delegate); p_id_ = prim_id(scene_delegate);
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s, id=%s", id_->name, p_id_.GetText()); ID_LOG(2, "");
} }
std::unique_ptr<WorldData> WorldData::create(BlenderSceneDelegate *scene_delegate, std::unique_ptr<WorldData> WorldData::create(BlenderSceneDelegate *scene_delegate,
@ -52,7 +52,7 @@ pxr::SdfPath WorldData::prim_id(BlenderSceneDelegate *scene_delegate)
void WorldData::init() void WorldData::init()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", id_->name); ID_LOG(2, "");
World *world = (World *)id_; World *world = (World *)id_;
data_.clear(); data_.clear();
@ -125,7 +125,7 @@ void WorldData::init()
void WorldData::insert() void WorldData::insert()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", id_->name); ID_LOG(2, "");
scene_delegate_->GetRenderIndex().InsertSprim( scene_delegate_->GetRenderIndex().InsertSprim(
pxr::HdPrimTypeTokens->domeLight, scene_delegate_, p_id_); pxr::HdPrimTypeTokens->domeLight, scene_delegate_, p_id_);
} }
@ -138,7 +138,7 @@ void WorldData::remove()
void WorldData::update() void WorldData::update()
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", id_->name); ID_LOG(2, "");
init(); init();
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_, scene_delegate_->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id_,
pxr::HdLight::AllDirty); pxr::HdLight::AllDirty);