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)
{
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();
}
InstancerData *i_data = instancer_data(id);
if (i_data) {
return i_data->transform();
}
return pxr::GfMatrix4d();
}
@ -200,7 +89,7 @@ pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(
InstancerData *i_data = instancer_data(id);
if (i_data) {
return i_data->instancer_primvar_descriptors(interpolation);
return i_data->primvar_descriptors(interpolation);
}
return pxr::HdPrimvarDescriptorVector();
@ -232,9 +121,9 @@ bool BlenderSceneDelegate::GetVisible(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);
InstancerData *i_data = instancer_data(prim_id.GetParentPath());
if (i_data) {
return i_data->instancer_id;
return i_data->p_id_;
}
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)
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", instancer_id.GetText());
pxr::SdfPathVector paths;
paths.push_back(instancer_id.GetParentPath());
return paths;
InstancerData *i_data = instancer_data(instancer_id);
return i_data->prototypes();
}
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());
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)
@ -262,13 +150,54 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &
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)
{
auto it = objects_.find(id);
if (it == objects_.end()) {
return nullptr;
if (it != objects_.end()) {
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)
@ -290,36 +219,20 @@ MaterialData *BlenderSceneDelegate::material_data(pxr::SdfPath const &id)
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) {
return dynamic_cast<InstancerData *>(object_data(id));
}
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;
}
auto it = instancers_.find(id);
if (it != instancers_.end()) {
return it->second.get();
}
return nullptr;
}
void BlenderSceneDelegate::add_update_object(Object *object)
void BlenderSceneDelegate::update_objects(Object *object)
{
if ((object->transflag & OB_DUPLI) && InstancerData::is_supported(object)) {
add_update_instancer(object);
if (!ObjectData::is_supported(object)) {
return;
}
InstancerData *i_data = instancer_data(object);
if (i_data) {
i_data->update();
}
pxr::SdfPath id = ObjectData::prim_id(this, object);
ObjectData *obj_data = object_data(id);
if (obj_data) {
@ -334,16 +247,33 @@ void BlenderSceneDelegate::add_update_object(Object *object)
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);
InstancerData *i_data = instancer_data(id, true);
InstancerData *i_data = instancer_data(id);
if (i_data) {
i_data->update();
if (object->transflag & OB_DUPLI) {
i_data->update();
}
else {
i_data->remove();
instancers_.erase(id);
}
return;
}
objects_[id] = InstancerData::create(this, object);
i_data = instancer_data(id, true);
if ((object->transflag & OB_DUPLI) == 0) {
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_);
}
@ -366,19 +296,87 @@ void BlenderSceneDelegate::update_world()
}
}
void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
void BlenderSceneDelegate::check_updates()
{
if (visibility) {
/* Check and update visibility */
for (auto &obj : objects_) {
obj.second->update_visibility(view3d_);
/* Working with updates */
bool do_update_collection = false;
bool do_update_visibility = false;
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 */
std::set<pxr::SdfPath> available_objects;
pxr::SdfPath id;
/* 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) {
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};
settings.depsgraph = depsgraph_;
settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
@ -394,57 +392,126 @@ void BlenderSceneDelegate::update_collection(bool remove, bool visibility)
Object *,
object) {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "Add %s", ((ID *)object)->name);
if (!ObjectData::is_supported(object)) {
continue;
}
id = ObjectData::prim_id(this, object);
if (remove) {
available_objects.insert(id);
if ((object->transflag & OB_DUPLI) && InstancerData::is_supported(object)) {
available_objects.insert(InstancerData::prim_id(this, object));
}
}
update_objects(object);
update_instancers(object);
}
ITER_END;
}
if (!object_data(id)) {
add_update_object(object);
void BlenderSceneDelegate::remove_unused_objects()
{
/* 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;
if (remove) {
/* remove unused objects */
for (auto it = objects_.begin(); it != objects_.end(); ++it) {
if (available_objects.find(it->first) != available_objects.end()) {
continue;
}
it->second->remove();
objects_.erase(it);
it = objects_.begin();
/* Remove unused instancers */
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 materials */
std::set<pxr::SdfPath> available_materials;
for (auto &obj : objects_) {
MeshData *m_data = dynamic_cast<MeshData *>(obj.second.get());
if (!m_data) {
continue;
}
pxr::SdfPath mat_id = m_data->material_id();
if (!mat_id.IsEmpty()) {
available_materials.insert(mat_id);
}
/* Remove unused objects */
for (auto it = objects_.begin(); it != objects_.end(); ++it) {
if (available_objects.find(it->first.GetName()) != available_objects.end()) {
continue;
}
for (auto it = materials_.begin(); it != materials_.end(); ++it) {
if (available_materials.find(it->first) != available_materials.end()) {
continue;
}
it->second->remove();
materials_.erase(it);
it = materials_.begin();
it->second->remove();
objects_.erase(it);
it = objects_.begin();
}
/* Remove unused materials */
std::set<pxr::SdfPath> available_materials;
for (auto &it : objects_) {
MeshData *m_data = dynamic_cast<MeshData *>(it.second.get());
if (!m_data) {
continue;
}
pxr::SdfPath mat_id = m_data->material_id();
if (!mat_id.IsEmpty()) {
available_materials.insert(mat_id);
}
}
for (auto &it : instancers_) {
it.second->available_materials(available_materials);
}
for (auto it = materials_.begin(); it != materials_.end(); ++it) {
if (available_materials.find(it->first) != available_materials.end()) {
continue;
}
it->second->remove();
materials_.erase(it);
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

View File

@ -32,9 +32,6 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
BlenderSceneDelegate::EngineType engine_type);
~BlenderSceneDelegate() override = default;
void populate(Depsgraph *depsgraph, bContext *context);
void clear();
/* Delegate methods */
pxr::HdMeshTopology GetMeshTopology(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::GfMatrix4d GetInstancerTransform(pxr::SdfPath const &instancer_id) override;
void populate(Depsgraph *depsgraph, bContext *context);
void clear();
EngineType engine_type;
private:
@ -58,13 +58,15 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
MeshData *mesh_data(pxr::SdfPath const &id);
LightData *light_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(Object *object);
InstancerData *instancer_data(pxr::SdfPath const &id);
void add_update_object(Object *object);
void add_update_instancer(Object *object);
void update_objects(Object *object);
void update_instancers(Object *object);
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;
bContext *context_ = nullptr;
@ -73,6 +75,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
ObjectDataMap objects_;
MaterialDataMap materials_;
InstancerDataMap instancers_;
std::unique_ptr<WorldData> world_data_;
};

View File

@ -12,8 +12,11 @@
namespace blender::render::hydra {
class BlenderSceneDelegate;
class InstancerData;
class IdData {
friend InstancerData;
public:
IdData(BlenderSceneDelegate *scene_delegate, ID *id);
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>();
}
#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

View File

@ -10,16 +10,10 @@
namespace blender::render::hydra {
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);
instancer_id = p_id_.AppendElementString("Instancer");
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"%s, instancer_id=%s",
((ID *)parent_obj_)->name,
instancer_id.GetText());
ID_LOG(2, "");
}
bool InstancerData::is_supported(Object *object)
@ -58,71 +52,56 @@ pxr::SdfPath InstancerData::prim_id(BlenderSceneDelegate *scene_delegate, Object
void InstancerData::init()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", ((ID *)parent_obj_)->name);
ID_LOG(2, "");
set_instances();
MeshData::init();
}
void InstancerData::insert()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", ((ID *)parent_obj_)->name);
MeshData::insert();
if (face_vertex_counts_.empty()) {
return;
ID_LOG(2, "");
scene_delegate_->GetRenderIndex().InsertInstancer(scene_delegate_, p_id_);
for (auto &it : instances_) {
it.second.obj_data->insert();
}
scene_delegate_->GetRenderIndex().InsertInstancer(scene_delegate_, instancer_id);
}
void InstancerData::remove()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", ((ID *)parent_obj_)->name);
if (!scene_delegate_->GetRenderIndex().HasInstancer(instancer_id)) {
return;
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", p_id_.GetText());
for (auto &it : instances_) {
it.second.obj_data->remove();
}
scene_delegate_->GetRenderIndex().RemoveInstancer(instancer_id);
MeshData::remove();
scene_delegate_->GetRenderIndex().RemoveInstancer(p_id_);
}
void InstancerData::update()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", ((ID *)parent_obj_)->name);
ID_LOG(2, "");
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
unsigned int recalc = ((ID *)parent_obj_)->recalc;
Object *object = (Object *)id_;
if ((id_->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
init();
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();
set_instances();
bits |= pxr::HdChangeTracker::AllDirty;
}
else if (recalc & ID_RECALC_TRANSFORM || id_->recalc & ID_RECALC_TRANSFORM) {
else if (id_->recalc & ID_RECALC_TRANSFORM) {
set_instances();
bits |= pxr::HdChangeTracker::DirtyTransform;
}
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
{
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) {
return pxr::VtValue(transforms_);
ret = transforms_;
}
return MeshData::get_data(key);
return ret;
}
pxr::GfMatrix4d InstancerData::transform()
@ -136,18 +115,20 @@ bool InstancerData::update_visibility(View3D *view3d)
return false;
}
bool prev_visible = visible;
visible = BKE_object_is_visible_in_viewport(view3d, parent_obj_);
bool ret = visible != prev_visible;
bool ret = ObjectData::update_visibility(view3d);
if (ret) {
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
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;
}
pxr::HdPrimvarDescriptorVector InstancerData::instancer_primvar_descriptors(
pxr::HdInterpolation interpolation)
pxr::HdPrimvarDescriptorVector InstancerData::primvar_descriptors(pxr::HdInterpolation interpolation)
{
pxr::HdPrimvarDescriptorVector primvars;
if (interpolation == pxr::HdInterpolationInstance) {
@ -157,47 +138,131 @@ pxr::HdPrimvarDescriptorVector InstancerData::instancer_primvar_descriptors(
return primvars;
}
pxr::VtIntArray InstancerData::instance_indices()
pxr::VtIntArray InstancerData::indices(pxr::SdfPath const &id)
{
pxr::VtIntArray ret(transforms_.size());
for (size_t i = 0; i < ret.size(); ++i) {
ret[i] = i;
return instances_[id].indices;
}
ObjectData *InstancerData::object_data(pxr::SdfPath const &id)
{
return instances_[id].obj_data.get();
}
pxr::SdfPathVector InstancerData::prototypes()
{
pxr::SdfPathVector paths;
for (auto &it : instances_) {
paths.push_back(it.first);
}
return ret;
return paths;
}
bool InstancerData::is_base(Object *object) const
void InstancerData::check_update(Object *object)
{
return (ID *)object == id_;
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);
}
}
bool InstancerData::set_instances()
void InstancerData::check_remove(std::set<std::string> &available_objects)
{
ID *prev_id = id_;
id_ = nullptr;
transforms_.clear();
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) {
bool ret = false;
for (auto it = instances_.begin(); it != instances_.end(); ++it) {
if (available_objects.find(it->first.GetName()) != available_objects.end()) {
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));
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
2,
"Instance %s (%s) %d",
id_->name,
((ID *)dupli->ob)->name,
dupli->random_id);
inst->indices.push_back(index);
ID_LOG(2, "Instance %s %d", inst->obj_data->id_->name, index);
++index;
}
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

View File

@ -9,7 +9,14 @@
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:
InstancerData(BlenderSceneDelegate *scene_delegate, Object *object);
@ -27,17 +34,28 @@ class InstancerData : public MeshData {
pxr::GfMatrix4d transform() override;
bool update_visibility(View3D *view3d) override;
pxr::HdPrimvarDescriptorVector instancer_primvar_descriptors(pxr::HdInterpolation interpolation);
pxr::VtIntArray instance_indices();
bool is_base(Object *object) const;
pxr::SdfPath instancer_id;
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation);
pxr::VtIntArray indices(pxr::SdfPath const &id);
ObjectData *object_data(pxr::SdfPath const &id);
pxr::SdfPathVector prototypes();
void check_update(Object *object);
void check_remove(std::set<std::string> &available_objects);
void available_materials(std::set<pxr::SdfPath> &paths);
private:
bool set_instances();
void set_instances();
Object *parent_obj_;
pxr::TfHashMap<pxr::SdfPath, Instance, pxr::SdfPath::Hash> instances_;
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

View File

@ -17,12 +17,12 @@ namespace blender::render::hydra {
LightData::LightData(BlenderSceneDelegate *scene_delegate, Object *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()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", id_->name);
ID_LOG(2, "");
Light *light = (Light *)((Object *)id_)->data;
data_.clear();

View File

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

View File

@ -18,7 +18,7 @@ namespace blender::render::hydra {
MeshData::MeshData(BlenderSceneDelegate *scene_delegate, Object *object)
: 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()

View File

@ -84,7 +84,11 @@ bool ObjectData::update_visibility(View3D *view3d)
bool prev_visible = visible;
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

View File

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