diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2021-03-12 03:30:12 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2021-03-12 03:30:12 +0300 |
commit | d72fc36ec5c632cafa2f9e2c8897ce81fc83a372 (patch) | |
tree | 540a2adb5519f1eda7d429fb0a76b0776916783a /intern/cycles/render | |
parent | 7017844c5eca72046654b27ceee2f9528edbe488 (diff) |
Alembic procedural: add support for instancing
Inside of the procedural, instances are AlembicObjects which point to
the AlembicObject that they instance.
In Alembic, an instance is an untyped Object pointing to the original
(instanced) one through its source path. During the archive traversal we
detect such instances and, only if the instanced object is asked to be
rendered, set the instance's AlembicObject to point to the original's
AlembicObject.
Cycles Object Nodes are created for each AlembicObject, but only for
non-instances are Geometries created, which are then shared between
Object Nodes. It is supposed, and expected, that all instances share the
same shaders, which will be set to be the ones found on the original
object.
As for caching, the data cache for an AlembicObject is only valid for
non-instances and should not be read to or from as it is implicitly
shared.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/alembic.cpp | 102 | ||||
-rw-r--r-- | intern/cycles/render/alembic.h | 2 |
2 files changed, 89 insertions, 15 deletions
diff --git a/intern/cycles/render/alembic.cpp b/intern/cycles/render/alembic.cpp index de51e6fe0ac..59454eac8a5 100644 --- a/intern/cycles/render/alembic.cpp +++ b/intern/cycles/render/alembic.cpp @@ -719,6 +719,11 @@ void AlembicObject::load_all_data(AlembicProcedural *proc, { cached_data.clear(); + /* Only load data for the original Geometry. */ + if (instance_of) { + return; + } + const TimeSamplingPtr time_sampling = schema.getTimeSampling(); cached_data.set_time_sampling(*time_sampling); @@ -784,6 +789,11 @@ void AlembicObject::load_all_data(AlembicProcedural *proc, ISubDSchema &schema, { cached_data.clear(); + /* Only load data for the original Geometry. */ + if (instance_of) { + return; + } + AttributeRequestSet requested_attributes = get_requested_attributes(); const TimeSamplingPtr time_sampling = schema.getTimeSampling(); @@ -918,6 +928,11 @@ void AlembicObject::load_all_data(AlembicProcedural *proc, { cached_data.clear(); + /* Only load data for the original Geometry. */ + if (instance_of) { + return; + } + const TimeSamplingPtr time_sampling = schema.getTimeSampling(); cached_data.set_time_sampling(*time_sampling); @@ -1480,22 +1495,24 @@ void AlembicProcedural::load_objects(Progress &progress) Geometry *geometry = nullptr; - if (abc_object->schema_type == AlembicObject::CURVES) { - geometry = scene_->create_node<Hair>(); - } - else if (abc_object->schema_type == AlembicObject::POLY_MESH || - abc_object->schema_type == AlembicObject::SUBD) { - geometry = scene_->create_node<Mesh>(); - } - else { - continue; - } + if (!abc_object->instance_of) { + if (abc_object->schema_type == AlembicObject::CURVES) { + geometry = scene_->create_node<Hair>(); + } + else if (abc_object->schema_type == AlembicObject::POLY_MESH || + abc_object->schema_type == AlembicObject::SUBD) { + geometry = scene_->create_node<Mesh>(); + } + else { + continue; + } - geometry->set_owner(this); - geometry->name = abc_object->iobject.getName(); + geometry->set_owner(this); + geometry->name = abc_object->iobject.getName(); - array<Node *> used_shaders = abc_object->get_used_shaders(); - geometry->set_used_shaders(used_shaders); + array<Node *> used_shaders = abc_object->get_used_shaders(); + geometry->set_used_shaders(used_shaders); + } Object *object = scene_->create_node<Object>(); object->set_owner(this); @@ -1504,6 +1521,17 @@ void AlembicProcedural::load_objects(Progress &progress) abc_object->set_object(object); } + + /* Share geometries between instances. */ + foreach (Node *node, objects) { + AlembicObject *abc_object = static_cast<AlembicObject *>(node); + + if (abc_object->instance_of) { + abc_object->get_object()->set_geometry( + abc_object->instance_of->get_object()->get_geometry()); + abc_object->schema_type = abc_object->instance_of->schema_type; + } + } } void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame_time) @@ -1519,6 +1547,11 @@ void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame object->tag_update(scene_); } + /* Only update sockets for the original Geometry. */ + if (abc_object->instance_of) { + return; + } + Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket()); @@ -1581,6 +1614,11 @@ void AlembicProcedural::read_subd(AlembicObject *abc_object, Abc::chrono_t frame object->tag_update(scene_); } + /* Only update sockets for the original Geometry. */ + if (abc_object->instance_of) { + return; + } + Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); /* Cycles overwrites the original triangles when computing displacement, so we always have to @@ -1666,6 +1704,11 @@ void AlembicProcedural::read_curves(AlembicObject *abc_object, Abc::chrono_t fra object->tag_update(scene_); } + /* Only update sockets for the original Geometry. */ + if (abc_object->instance_of) { + return; + } + Hair *hair = static_cast<Hair *>(object->get_geometry()); cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket()); @@ -1806,9 +1849,38 @@ void AlembicProcedural::walk_hierarchy( else if (IFaceSet::matches(header)) { // ignore the face set, it will be read along with the data } + else if (IPoints::matches(header)) { + // unsupported for now + } + else if (INuPatch::matches(header)) { + // unsupported for now + } else { - // unsupported type for now (Points, NuPatch) next_object = parent.getChild(header.getName()); + + if (next_object.isInstanceRoot()) { + unordered_map<std::string, AlembicObject *>::const_iterator iter; + + /* Was this object asked to be rendered? */ + iter = object_map.find(next_object.getFullName()); + + if (iter != object_map.end()) { + AlembicObject *abc_object = iter->second; + + /* Only try to render an instance if the original object is also rendered. */ + iter = object_map.find(next_object.instanceSourcePath()); + + if (iter != object_map.end()) { + abc_object->iobject = next_object; + abc_object->instance_of = iter->second; + + if (matrix_samples_data.samples) { + abc_object->xform_samples = *matrix_samples_data.samples; + abc_object->xform_time_sampling = matrix_samples_data.time_sampling; + } + } + } + } } if (next_object.valid()) { diff --git a/intern/cycles/render/alembic.h b/intern/cycles/render/alembic.h index a84e97f551b..6552336e6ab 100644 --- a/intern/cycles/render/alembic.h +++ b/intern/cycles/render/alembic.h @@ -276,6 +276,8 @@ class AlembicObject : public Node { bool need_shader_update = true; + AlembicObject *instance_of = nullptr; + Alembic::AbcCoreAbstract::TimeSamplingPtr xform_time_sampling; MatrixSampleMap xform_samples; Alembic::AbcGeom::IObject iobject; |