forked from blender/blender
Make object visibility and instancing creation to be calculated via depsgraph #57
@ -56,8 +56,9 @@ template<class T> const T IdData::get_data(pxr::TfToken const &key) const
|
||||
#define ID_LOG(level, msg, ...) \
|
||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, \
|
||||
level, \
|
||||
"%s: " msg, \
|
||||
"%s (%s): " msg, \
|
||||
prim_id.GetText(), \
|
||||
id ? id->name : "", \
|
||||
##__VA_ARGS__);
|
||||
|
||||
} // namespace blender::render::hydra
|
||||
|
@ -17,7 +17,7 @@ InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath
|
||||
{
|
||||
}
|
||||
|
||||
bool InstancerData::is_supported(Object *object)
|
||||
bool InstancerData::is_instance_supported(Object *object)
|
||||
{
|
||||
switch (object->type) {
|
||||
case OB_MESH:
|
||||
@ -34,29 +34,6 @@ 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()
|
||||
{
|
||||
ID_LOG(1, "");
|
||||
@ -179,99 +156,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()) {
|
||||
@ -279,13 +163,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()) {
|
||||
@ -293,22 +170,6 @@ void InstancerData::update_double_sided(MaterialData *mat_data)
|
||||
}
|
||||
}
|
||||
|
||||
bool InstancerData::is_instance_visible(Object *object)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
pxr::SdfPath InstancerData::object_prim_id(Object *object) const
|
||||
{
|
||||
/* Making id of object in form like <prefix>_<pointer in 16 hex digits format> */
|
||||
@ -361,7 +222,7 @@ void InstancerData::write_instances()
|
||||
}
|
||||
DupliObject *dupli = d.dupli_object_current;
|
||||
Object *ob = dupli->ob;
|
||||
if (!is_supported(ob)) {
|
||||
if (!is_instance_supported(ob)) {
|
||||
continue;
|
||||
}
|
||||
if (!ObjectData::is_visible(scene_delegate_, d.dupli_parent)) {
|
||||
|
@ -26,8 +26,7 @@ class InstancerData : public ObjectData {
|
||||
|
||||
public:
|
||||
InstancerData(BlenderSceneDelegate *scene_delegate, pxr::SdfPath const &prim_id);
|
||||
static bool is_supported(Object *object);
|
||||
static bool is_visible(BlenderSceneDelegate *scene_delegate, Object *object);
|
||||
static bool is_instance_supported(Object *object);
|
||||
|
||||
void init() override;
|
||||
void insert() override;
|
||||
@ -42,14 +41,10 @@ class InstancerData : public ObjectData {
|
||||
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);
|
||||
|
||||
|
||||
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;
|
||||
@ -63,6 +58,4 @@ class InstancerData : public ObjectData {
|
||||
pxr::VtMatrix4dArray mesh_transforms_;
|
||||
};
|
||||
|
||||
using InstancerDataMap = Map<pxr::SdfPath, std::unique_ptr<InstancerData>>;
|
||||
|
||||
} // namespace blender::render::hydra
|
||||
|
Loading…
Reference in New Issue
Block a user
Please add comment why this is done in this way