Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-09-06 19:22:24 +0300
committerJacques Lucke <jacques@blender.org>2021-09-06 19:31:25 +0300
commit5a9a16334c573c4566dc9b2a314cf0d0ccdcb54f (patch)
tree35f765d48f478c04c2bbc92df77d388efa3ac1c8 /intern/cycles
parentd9ad77fa58eb6301e3fedc709c946b7349c057b2 (diff)
Geometry Nodes: support for geometry instancing
Previously, the Point Instance node in geometry nodes could only instance existing objects or collections. The reason was that large parts of Blender worked under the assumption that objects are the main unit of instancing. Now we also want to instance geometry within an object, so a slightly larger refactor was necessary. This should not affect files that do not use the new kind of instances. The main change is a redefinition of what "instanced data" is. Now, an instances is a cow-object + object-data (the geometry). This can be nicely seen in `struct DupliObject`. This allows the same object to generate multiple geometries of different types which can be instanced individually. A nice side effect of this refactor is that having multiple geometry components is not a special case in the depsgraph object iterator anymore, because those components are integrated with the `DupliObject` system. Unfortunately, different systems that work with instances in Blender (e.g. render engines and exporters) often work under the assumption that objects are the main unit of instancing. So those have to be updated as well to be able to handle the new instances. This patch updates Cycles, EEVEE and other viewport engines. Exporters have not been updated yet. Some minimal (not master-ready) changes to update the obj and alembic exporters can be found in P2336 and P2335. Different file formats may want to handle these new instances in different ways. For users, the only thing that changed is that the Point Instance node now has a geometry mode. This also fixes T88454. Differential Revision: https://developer.blender.org/D11841
Diffstat (limited to 'intern/cycles')
-rw-r--r--intern/cycles/blender/blender_curves.cpp42
-rw-r--r--intern/cycles/blender/blender_geometry.cpp42
-rw-r--r--intern/cycles/blender/blender_light.cpp15
-rw-r--r--intern/cycles/blender/blender_mesh.cpp61
-rw-r--r--intern/cycles/blender/blender_object.cpp26
-rw-r--r--intern/cycles/blender/blender_sync.h29
-rw-r--r--intern/cycles/blender/blender_util.h49
-rw-r--r--intern/cycles/blender/blender_volume.cpp21
8 files changed, 165 insertions, 120 deletions
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 85d886fd850..6fe5ea41fff 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -526,8 +526,13 @@ bool BlenderSync::object_has_particle_hair(BL::Object b_ob)
/* Old particle hair. */
void BlenderSync::sync_particle_hair(
- Hair *hair, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step)
+ Hair *hair, BL::Mesh &b_mesh, BObjectInfo &b_ob_info, bool motion, int motion_step)
{
+ if (!b_ob_info.is_real_object_data()) {
+ return;
+ }
+ BL::Object b_ob = b_ob_info.real_object;
+
/* obtain general settings */
if (b_ob.mode() == b_ob.mode_PARTICLE_EDIT || b_ob.mode() == b_ob.mode_EDIT) {
return;
@@ -788,10 +793,10 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
}
/* Hair object. */
-void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step)
+void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step)
{
/* Convert Blender hair to Cycles curves. */
- BL::Hair b_hair(b_ob.data());
+ BL::Hair b_hair(b_ob_info.object_data);
if (motion) {
export_hair_curves_motion(hair, b_hair, motion_step);
}
@@ -800,16 +805,16 @@ void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motio
}
}
#else
-void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step)
+void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step)
{
(void)hair;
- (void)b_ob;
+ (void)b_ob_info;
(void)motion;
(void)motion_step;
}
#endif
-void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair)
+void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Hair *hair)
{
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
* attributes */
@@ -819,19 +824,19 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *ha
new_hair.set_used_shaders(used_shaders);
if (view_layer.use_hair) {
- if (b_ob.type() == BL::Object::type_HAIR) {
+ if (b_ob_info.object_data.is_a(&RNA_Hair)) {
/* Hair object. */
- sync_hair(&new_hair, b_ob, false);
+ sync_hair(&new_hair, b_ob_info, false);
}
else {
/* Particle hair. */
bool need_undeformed = new_hair.need_attribute(scene, ATTR_STD_GENERATED);
BL::Mesh b_mesh = object_to_mesh(
- b_data, b_ob, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE);
+ b_data, b_ob_info, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE);
if (b_mesh) {
- sync_particle_hair(&new_hair, b_mesh, b_ob, false);
- free_object_to_mesh(b_data, b_ob, b_mesh);
+ sync_particle_hair(&new_hair, b_mesh, b_ob_info, false);
+ free_object_to_mesh(b_data, b_ob_info, b_mesh);
}
}
}
@@ -859,7 +864,7 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *ha
}
void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph,
- BL::Object b_ob,
+ BObjectInfo &b_ob_info,
Hair *hair,
int motion_step)
{
@@ -869,18 +874,19 @@ void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph,
}
/* Export deformed coordinates. */
- if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
- if (b_ob.type() == BL::Object::type_HAIR) {
+ if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
+ if (b_ob_info.object_data.is_a(&RNA_Hair)) {
/* Hair object. */
- sync_hair(hair, b_ob, true, motion_step);
+ sync_hair(hair, b_ob_info, true, motion_step);
return;
}
else {
/* Particle hair. */
- BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
+ BL::Mesh b_mesh = object_to_mesh(
+ b_data, b_ob_info, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
if (b_mesh) {
- sync_particle_hair(hair, b_mesh, b_ob, true, motion_step);
- free_object_to_mesh(b_data, b_ob, b_mesh);
+ sync_particle_hair(hair, b_mesh, b_ob_info, true, motion_step);
+ free_object_to_mesh(b_data, b_ob_info, b_mesh);
return;
}
}
diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp
index a009018f357..acc089a286c 100644
--- a/intern/cycles/blender/blender_geometry.cpp
+++ b/intern/cycles/blender/blender_geometry.cpp
@@ -29,13 +29,15 @@
CCL_NAMESPACE_BEGIN
-static Geometry::Type determine_geom_type(BL::Object &b_ob, bool use_particle_hair)
+static Geometry::Type determine_geom_type(BObjectInfo &b_ob_info, bool use_particle_hair)
{
- if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
+ if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) {
return Geometry::HAIR;
}
- if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
+ if (b_ob_info.object_data.is_a(&RNA_Volume) ||
+ (b_ob_info.object_data == b_ob_info.real_object.data() &&
+ object_fluid_gas_domain_find(b_ob_info.real_object))) {
return Geometry::VOLUME;
}
@@ -71,20 +73,17 @@ array<Node *> BlenderSync::find_used_shaders(BL::Object &b_ob)
}
Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
- BL::Object &b_ob,
- BL::Object &b_ob_instance,
+ BObjectInfo &b_ob_info,
bool object_updated,
bool use_particle_hair,
TaskPool *task_pool)
{
/* Test if we can instance or if the object is modified. */
- BL::ID b_ob_data = b_ob.data();
- BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data;
- Geometry::Type geom_type = determine_geom_type(b_ob, use_particle_hair);
- GeometryKey key(b_key_id.ptr.data, geom_type);
+ Geometry::Type geom_type = determine_geom_type(b_ob_info, use_particle_hair);
+ GeometryKey key(b_ob_info.object_data, geom_type);
/* Find shader indices. */
- array<Node *> used_shaders = find_used_shaders(b_ob);
+ array<Node *> used_shaders = find_used_shaders(b_ob_info.iter_object);
/* Ensure we only sync instanced geometry once. */
Geometry *geom = geometry_map.find(key);
@@ -111,7 +110,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
}
else {
/* Test if we need to update existing geometry. */
- sync = geometry_map.update(geom, b_key_id);
+ sync = geometry_map.update(geom, b_ob_info.object_data);
}
if (!sync) {
@@ -144,7 +143,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
geometry_synced.insert(geom);
- geom->name = ustring(b_ob_data.name().c_str());
+ geom->name = ustring(b_ob_info.object_data.name().c_str());
/* Store the shaders immediately for the object attribute code. */
geom->set_used_shaders(used_shaders);
@@ -153,19 +152,19 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
if (progress.get_cancel())
return;
- progress.set_sync_status("Synchronizing object", b_ob.name());
+ progress.set_sync_status("Synchronizing object", b_ob_info.real_object.name());
if (geom_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
- sync_hair(b_depsgraph, b_ob, hair);
+ sync_hair(b_depsgraph, b_ob_info, hair);
}
else if (geom_type == Geometry::VOLUME) {
Volume *volume = static_cast<Volume *>(geom);
- sync_volume(b_ob, volume);
+ sync_volume(b_ob_info, volume);
}
else {
Mesh *mesh = static_cast<Mesh *>(geom);
- sync_mesh(b_depsgraph, b_ob, mesh);
+ sync_mesh(b_depsgraph, b_ob_info, mesh);
}
};
@@ -181,7 +180,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
}
void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
- BL::Object &b_ob,
+ BObjectInfo &b_ob_info,
Object *object,
float motion_time,
bool use_particle_hair,
@@ -210,16 +209,17 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
if (progress.get_cancel())
return;
- if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
+ if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) {
Hair *hair = static_cast<Hair *>(geom);
- sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
+ sync_hair_motion(b_depsgraph, b_ob_info, hair, motion_step);
}
- else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
+ else if (b_ob_info.object_data.is_a(&RNA_Volume) ||
+ object_fluid_gas_domain_find(b_ob_info.real_object)) {
/* No volume motion blur support yet. */
}
else {
Mesh *mesh = static_cast<Mesh *>(geom);
- sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
+ sync_mesh_motion(b_depsgraph, b_ob_info, mesh, motion_step);
}
};
diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp
index 50cd9e3db5c..542028f4b2f 100644
--- a/intern/cycles/blender/blender_light.cpp
+++ b/intern/cycles/blender/blender_light.cpp
@@ -27,15 +27,14 @@ CCL_NAMESPACE_BEGIN
void BlenderSync::sync_light(BL::Object &b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
- BL::Object &b_ob,
- BL::Object &b_ob_instance,
+ BObjectInfo &b_ob_info,
int random_id,
Transform &tfm,
bool *use_portal)
{
/* test if we need to sync */
- ObjectKey key(b_parent, persistent_id, b_ob_instance, false);
- BL::Light b_light(b_ob.data());
+ ObjectKey key(b_parent, persistent_id, b_ob_info.real_object, false);
+ BL::Light b_light(b_ob_info.object_data);
Light *light = light_map.find(key);
@@ -44,7 +43,7 @@ void BlenderSync::sync_light(BL::Object &b_parent,
const bool tfm_updated = (light && light->get_tfm() != tfm);
/* Update if either object or light data changed. */
- if (!light_map.add_or_update(&light, b_ob, b_parent, key) && !tfm_updated) {
+ if (!light_map.add_or_update(&light, b_ob_info.real_object, b_parent, key) && !tfm_updated) {
Shader *shader;
if (!shader_map.add_or_update(&shader, b_light)) {
if (light->get_is_portal())
@@ -139,11 +138,11 @@ void BlenderSync::sync_light(BL::Object &b_parent,
light->set_max_bounces(get_int(clight, "max_bounces"));
- if (b_ob != b_ob_instance) {
+ if (b_ob_info.real_object != b_ob_info.iter_object) {
light->set_random_id(random_id);
}
else {
- light->set_random_id(hash_uint2(hash_string(b_ob.name().c_str()), 0));
+ light->set_random_id(hash_uint2(hash_string(b_ob_info.real_object.name().c_str()), 0));
}
if (light->get_light_type() == LIGHT_AREA)
@@ -155,7 +154,7 @@ void BlenderSync::sync_light(BL::Object &b_parent,
*use_portal = true;
/* visibility */
- uint visibility = object_ray_visibility(b_ob);
+ uint visibility = object_ray_visibility(b_ob_info.real_object);
light->set_use_diffuse((visibility & PATH_RAY_DIFFUSE) != 0);
light->set_use_glossy((visibility & PATH_RAY_GLOSSY) != 0);
light->set_use_transmission((visibility & PATH_RAY_TRANSMIT) != 0);
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index ebba6981502..9bb3447f56b 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -999,12 +999,14 @@ static void create_mesh(Scene *scene,
static void create_subd_mesh(Scene *scene,
Mesh *mesh,
- BL::Object &b_ob,
+ BObjectInfo &b_ob_info,
BL::Mesh &b_mesh,
const array<Node *> &used_shaders,
float dicing_rate,
int max_subdivisions)
{
+ BL::Object b_ob = b_ob_info.real_object;
+
BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]);
bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE;
@@ -1043,7 +1045,7 @@ static void create_subd_mesh(Scene *scene,
*
* NOTE: This code is run prior to object motion blur initialization. so can not access properties
* set by `sync_object_motion_init()`. */
-static bool mesh_need_motion_attribute(BL::Object &b_ob, Scene *scene)
+static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
{
const Scene::MotionType need_motion = scene->need_motion();
if (need_motion == Scene::MOTION_NONE) {
@@ -1060,7 +1062,7 @@ static bool mesh_need_motion_attribute(BL::Object &b_ob, Scene *scene)
* - Motion attribute expects non-zero time steps.
*
* Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */
- PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles");
const bool use_motion = get_boolean(cobject, "use_motion_blur");
if (!use_motion) {
return false;
@@ -1072,12 +1074,13 @@ static bool mesh_need_motion_attribute(BL::Object &b_ob, Scene *scene)
return true;
}
-static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *mesh)
+static void sync_mesh_cached_velocities(BObjectInfo &b_ob_info, Scene *scene, Mesh *mesh)
{
- if (!mesh_need_motion_attribute(b_ob, scene)) {
+ if (!mesh_need_motion_attribute(b_ob_info, scene)) {
return;
}
+ BL::Object b_ob = b_ob_info.real_object;
BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob, true, nullptr);
if (!b_mesh_cache) {
@@ -1118,12 +1121,16 @@ static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *me
}
}
-static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
+static void sync_mesh_fluid_motion(BObjectInfo &b_ob_info, Scene *scene, Mesh *mesh)
{
- if (!mesh_need_motion_attribute(b_ob, scene)) {
+ if (!b_ob_info.is_real_object_data()) {
+ return;
+ }
+ if (!mesh_need_motion_attribute(b_ob_info, scene)) {
return;
}
+ BL::Object b_ob = b_ob_info.real_object;
BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob);
if (!b_fluid_domain)
@@ -1157,7 +1164,7 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
}
}
-void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh)
+void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
{
/* make a copy of the shaders as the caller in the main thread still need them for syncing the
* attributes */
@@ -1170,20 +1177,21 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me
/* Adaptive subdivision setup. Not for baking since that requires
* exact mapping to the Blender mesh. */
if (!scene->bake_manager->get_baking()) {
- new_mesh.set_subdivision_type(object_subdivision_type(b_ob, preview, experimental));
+ new_mesh.set_subdivision_type(
+ object_subdivision_type(b_ob_info.real_object, preview, experimental));
}
/* For some reason, meshes do not need this... */
bool need_undeformed = new_mesh.need_attribute(scene, ATTR_STD_GENERATED);
BL::Mesh b_mesh = object_to_mesh(
- b_data, b_ob, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type());
+ b_data, b_ob_info, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type());
if (b_mesh) {
/* Sync mesh itself. */
if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE)
create_subd_mesh(scene,
&new_mesh,
- b_ob,
+ b_ob_info,
b_mesh,
new_mesh.get_used_shaders(),
dicing_rate,
@@ -1191,15 +1199,15 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me
else
create_mesh(scene, &new_mesh, b_mesh, new_mesh.get_used_shaders(), false);
- free_object_to_mesh(b_data, b_ob, b_mesh);
+ free_object_to_mesh(b_data, b_ob_info, b_mesh);
}
}
/* cached velocities (e.g. from alembic archive) */
- sync_mesh_cached_velocities(b_ob, scene, &new_mesh);
+ sync_mesh_cached_velocities(b_ob_info, scene, &new_mesh);
/* mesh fluid motion mantaflow */
- sync_mesh_fluid_motion(b_ob, scene, &new_mesh);
+ sync_mesh_fluid_motion(b_ob_info, scene, &new_mesh);
/* update original sockets */
@@ -1230,18 +1238,19 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me
}
void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
- BL::Object b_ob,
+ BObjectInfo &b_ob_info,
Mesh *mesh,
int motion_step)
{
/* Fluid motion blur already exported. */
- BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob);
+ BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob_info.real_object);
if (b_fluid_domain) {
return;
}
/* Cached motion blur already exported. */
- BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(b_ob, true, nullptr);
+ BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(
+ b_ob_info.real_object, true, nullptr);
if (mesh_cache) {
return;
}
@@ -1255,11 +1264,13 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
/* Skip objects without deforming modifiers. this is not totally reliable,
* would need a more extensive check to see which objects are animated. */
BL::Mesh b_mesh(PointerRNA_NULL);
- if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
+ if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
/* get derived mesh */
- b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
+ b_mesh = object_to_mesh(b_data, b_ob_info, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
}
+ const std::string ob_name = b_ob_info.real_object.name();
+
/* TODO(sergey): Perform preliminary check for number of vertices. */
if (b_mesh) {
/* Export deformed coordinates. */
@@ -1295,17 +1306,17 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
memcmp(mP, &mesh->get_verts()[0], sizeof(float3) * numverts) == 0) {
/* no motion, remove attributes again */
if (b_mesh.vertices.length() != numverts) {
- VLOG(1) << "Topology differs, disabling motion blur for object " << b_ob.name();
+ VLOG(1) << "Topology differs, disabling motion blur for object " << ob_name;
}
else {
- VLOG(1) << "No actual deformation motion for object " << b_ob.name();
+ VLOG(1) << "No actual deformation motion for object " << ob_name;
}
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
if (attr_mN)
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
}
else if (motion_step > 0) {
- VLOG(1) << "Filling deformation motion for object " << b_ob.name();
+ VLOG(1) << "Filling deformation motion for object " << ob_name;
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
float3 *P = &mesh->get_verts()[0];
@@ -1319,8 +1330,8 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
}
else {
if (b_mesh.vertices.length() != numverts) {
- VLOG(1) << "Topology differs, discarding motion blur for object " << b_ob.name()
- << " at time " << motion_step;
+ VLOG(1) << "Topology differs, discarding motion blur for object " << ob_name << " at time "
+ << motion_step;
memcpy(mP, &mesh->get_verts()[0], sizeof(float3) * numverts);
if (mN != NULL) {
memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts);
@@ -1328,7 +1339,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
}
}
- free_object_to_mesh(b_data, b_ob, b_mesh);
+ free_object_to_mesh(b_data, b_ob_info, b_mesh);
return;
}
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 5d98b61b409..2243baca0b2 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -154,7 +154,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
const bool is_instance = b_instance.is_instance();
BL::Object b_ob = b_instance.object();
BL::Object b_parent = is_instance ? b_instance.parent() : b_instance.object();
- BL::Object b_ob_instance = is_instance ? b_instance.instance_object() : b_ob;
+ BObjectInfo b_ob_info{b_ob, is_instance ? b_instance.instance_object() : b_ob, b_ob.data()};
const bool motion = motion_time != 0.0f;
/*const*/ Transform tfm = get_transform(b_ob.matrix_world());
int *persistent_id = NULL;
@@ -178,8 +178,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
{
sync_light(b_parent,
persistent_id,
- b_ob,
- b_ob_instance,
+ b_ob_info,
is_instance ? b_instance.random_id() : 0,
tfm,
use_portal);
@@ -231,7 +230,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
TaskPool *object_geom_task_pool = (is_instance) ? NULL : geom_task_pool;
/* key to lookup object */
- ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair);
+ ObjectKey key(b_parent, persistent_id, b_ob_info.real_object, use_particle_hair);
Object *object;
/* motion vector case */
@@ -249,12 +248,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* mesh deformation */
if (object->get_geometry())
- sync_geometry_motion(b_depsgraph,
- b_ob_instance,
- object,
- motion_time,
- use_particle_hair,
- object_geom_task_pool);
+ sync_geometry_motion(
+ b_depsgraph, b_ob_info, object, motion_time, use_particle_hair, object_geom_task_pool);
}
return object;
@@ -265,15 +260,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
(tfm != object->get_tfm());
/* mesh sync */
- /* b_ob is owned by the iterator and will go out of scope at the end of the block.
- * b_ob_instance is the original object and will remain valid for deferred geometry
- * sync. */
- Geometry *geometry = sync_geometry(b_depsgraph,
- b_ob_instance,
- b_ob_instance,
- object_updated,
- use_particle_hair,
- object_geom_task_pool);
+ Geometry *geometry = sync_geometry(
+ b_depsgraph, b_ob_info, object_updated, use_particle_hair, object_geom_task_pool);
object->set_geometry(geometry);
/* special case not tracked by object update flags */
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 44322dda6b9..76e8f23864c 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -23,6 +23,7 @@
#include "RNA_types.h"
#include "blender/blender_id_map.h"
+#include "blender/blender_util.h"
#include "blender/blender_viewport.h"
#include "render/scene.h"
@@ -158,18 +159,24 @@ class BlenderSync {
bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object);
/* Volume */
- void sync_volume(BL::Object &b_ob, Volume *volume);
+ void sync_volume(BObjectInfo &b_ob_info, Volume *volume);
/* Mesh */
- void sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh);
- void sync_mesh_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh, int motion_step);
+ void sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh);
+ void sync_mesh_motion(BL::Depsgraph b_depsgraph,
+ BObjectInfo &b_ob_info,
+ Mesh *mesh,
+ int motion_step);
/* Hair */
- void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair);
- void sync_hair_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair, int motion_step);
- void sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step = 0);
+ void sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Hair *hair);
+ void sync_hair_motion(BL::Depsgraph b_depsgraph,
+ BObjectInfo &b_ob_info,
+ Hair *hair,
+ int motion_step);
+ void sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step = 0);
void sync_particle_hair(
- Hair *hair, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0);
+ Hair *hair, BL::Mesh &b_mesh, BObjectInfo &b_ob_info, bool motion, int motion_step = 0);
bool object_has_particle_hair(BL::Object b_ob);
/* Camera */
@@ -178,14 +185,13 @@ class BlenderSync {
/* Geometry */
Geometry *sync_geometry(BL::Depsgraph &b_depsgrpah,
- BL::Object &b_ob,
- BL::Object &b_ob_instance,
+ BObjectInfo &b_ob_info,
bool object_updated,
bool use_particle_hair,
TaskPool *task_pool);
void sync_geometry_motion(BL::Depsgraph &b_depsgraph,
- BL::Object &b_ob,
+ BObjectInfo &b_ob_info,
Object *object,
float motion_time,
bool use_particle_hair,
@@ -194,8 +200,7 @@ class BlenderSync {
/* Light */
void sync_light(BL::Object &b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
- BL::Object &b_ob,
- BL::Object &b_ob_instance,
+ BObjectInfo &b_ob_info,
int random_id,
Transform &tfm,
bool *use_portal);
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index f6824f31b7b..e69531ea707 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -40,6 +40,28 @@ float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
CCL_NAMESPACE_BEGIN
+struct BObjectInfo {
+ /* Object directly provided by the depsgraph iterator. This object is only valid during one
+ * iteration and must not be accessed afterwards. Transforms and visibility should be checked on
+ * this object. */
+ BL::Object iter_object;
+
+ /* This object remains alive even after the object iterator is done. It corresponds to one
+ * original object. It is the object that owns the object data below. */
+ BL::Object real_object;
+
+ /* The object-data referenced by the iter object. This is still valid after the depsgraph
+ * iterator is done. It might have a different type compared to real_object.data(). */
+ BL::ID object_data;
+
+ /* True when the current geometry is the data of the referenced object. False when it is a
+ * geometry instance that does not have a 1-to-1 relationship with an object. */
+ bool is_real_object_data() const
+ {
+ return const_cast<BL::Object &>(real_object).data() == object_data;
+ }
+};
+
typedef BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType;
BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name);
@@ -47,7 +69,7 @@ void python_thread_state_save(void **python_thread_state);
void python_thread_state_restore(void **python_thread_state);
static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
- BL::Object &object,
+ BObjectInfo &b_ob_info,
BL::Depsgraph & /*depsgraph*/,
bool /*calc_undeformed*/,
Mesh::SubdivisionType subdivision_type)
@@ -69,9 +91,9 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
#endif
BL::Mesh mesh(PointerRNA_NULL);
- if (object.type() == BL::Object::type_MESH) {
+ if (b_ob_info.object_data.is_a(&RNA_Mesh)) {
/* TODO: calc_undeformed is not used. */
- mesh = BL::Mesh(object.data());
+ mesh = BL::Mesh(b_ob_info.object_data);
/* Make a copy to split faces if we use autosmooth, otherwise not needed.
* Also in edit mode do we need to make a copy, to ensure data layers like
@@ -79,12 +101,15 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
if (mesh.is_editmode() ||
(mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE)) {
BL::Depsgraph depsgraph(PointerRNA_NULL);
- mesh = object.to_mesh(false, depsgraph);
+ assert(b_ob_info.is_real_object_data());
+ mesh = b_ob_info.real_object.to_mesh(false, depsgraph);
}
}
else {
BL::Depsgraph depsgraph(PointerRNA_NULL);
- mesh = object.to_mesh(false, depsgraph);
+ if (b_ob_info.is_real_object_data()) {
+ mesh = b_ob_info.real_object.to_mesh(false, depsgraph);
+ }
}
#if 0
@@ -108,10 +133,14 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/,
}
static inline void free_object_to_mesh(BL::BlendData & /*data*/,
- BL::Object &object,
+ BObjectInfo &b_ob_info,
BL::Mesh &mesh)
{
+ if (!b_ob_info.is_real_object_data()) {
+ return;
+ }
/* Free mesh if we didn't just use the existing one. */
+ BL::Object object = b_ob_info.real_object;
if (object.data().ptr.data != mesh.ptr.data) {
object.to_mesh_clear();
}
@@ -219,9 +248,13 @@ static inline bool BKE_object_is_modified(BL::Object &self, BL::Scene &scene, bo
return self.is_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false;
}
-static inline bool BKE_object_is_deform_modified(BL::Object &self, BL::Scene &scene, bool preview)
+static inline bool BKE_object_is_deform_modified(BObjectInfo &self, BL::Scene &scene, bool preview)
{
- return self.is_deform_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false;
+ if (!self.is_real_object_data()) {
+ return false;
+ }
+ return self.real_object.is_deform_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true :
+ false;
}
static inline int render_resolution_x(BL::RenderSettings &b_render)
diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp
index 772ab9f5c8a..0a5b19d7d4c 100644
--- a/intern/cycles/blender/blender_volume.cpp
+++ b/intern/cycles/blender/blender_volume.cpp
@@ -181,9 +181,12 @@ class BlenderSmokeLoader : public ImageLoader {
AttributeStandard attribute;
};
-static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, float frame)
+static void sync_smoke_volume(Scene *scene, BObjectInfo &b_ob_info, Volume *volume, float frame)
{
- BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob);
+ if (!b_ob_info.is_real_object_data()) {
+ return;
+ }
+ BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob_info.real_object);
if (!b_domain) {
return;
}
@@ -206,7 +209,7 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, fl
Attribute *attr = volume->attributes.add(std);
- ImageLoader *loader = new BlenderSmokeLoader(b_ob, std);
+ ImageLoader *loader = new BlenderSmokeLoader(b_ob_info.real_object, std);
ImageParams params;
params.frame = frame;
@@ -244,11 +247,11 @@ class BlenderVolumeLoader : public VDBImageLoader {
};
static void sync_volume_object(BL::BlendData &b_data,
- BL::Object &b_ob,
+ BObjectInfo &b_ob_info,
Scene *scene,
Volume *volume)
{
- BL::Volume b_volume(b_ob.data());
+ BL::Volume b_volume(b_ob_info.object_data);
b_volume.grids.load(b_data.ptr.data);
BL::VolumeRender b_render(b_volume.render());
@@ -296,19 +299,19 @@ static void sync_volume_object(BL::BlendData &b_data,
}
}
-void BlenderSync::sync_volume(BL::Object &b_ob, Volume *volume)
+void BlenderSync::sync_volume(BObjectInfo &b_ob_info, Volume *volume)
{
volume->clear(true);
if (view_layer.use_volumes) {
- if (b_ob.type() == BL::Object::type_VOLUME) {
+ if (b_ob_info.object_data.is_a(&RNA_Volume)) {
/* Volume object. Create only attributes, bounding mesh will then
* be automatically generated later. */
- sync_volume_object(b_data, b_ob, scene, volume);
+ sync_volume_object(b_data, b_ob_info, scene, volume);
}
else {
/* Smoke domain. */
- sync_smoke_volume(scene, b_ob, volume, b_scene.frame_current());
+ sync_smoke_volume(scene, b_ob_info, volume, b_scene.frame_current());
}
}