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
path: root/intern
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2021-03-12 03:30:12 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2021-03-12 03:30:12 +0300
commitd72fc36ec5c632cafa2f9e2c8897ce81fc83a372 (patch)
tree540a2adb5519f1eda7d429fb0a76b0776916783a /intern
parent7017844c5eca72046654b27ceee2f9528edbe488 (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')
-rw-r--r--intern/cycles/render/alembic.cpp102
-rw-r--r--intern/cycles/render/alembic.h2
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;