Alembic procedural: fix missing update when only the transforms change

The missing update has two sources:

The TimeSampling used for looking up transformations in the cache was
uninitialized. To fix this, simply use the TimeSampling from the last
transformation in the hierarchy (that is the object's parent), which
should also contain the time information for all of its parents.

The objects are not tagged for update when their trasformations change.
This commit is contained in:
Kévin Dietrich 2021-03-07 16:17:59 +01:00
parent ac4d45dbf1
commit 00f218602d
2 changed files with 41 additions and 14 deletions

View File

@ -1017,6 +1017,10 @@ void AlembicObject::setup_transform_cache(float scale)
cached_data.transforms.clear();
cached_data.transforms.invalidate_last_loaded_time();
if (xform_time_sampling) {
cached_data.transforms.set_time_sampling(*xform_time_sampling);
}
if (xform_samples.size() == 0) {
Transform tfm = transform_scale(make_float3(scale));
cached_data.transforms.add_data(tfm, 0.0);
@ -1476,7 +1480,7 @@ void AlembicProcedural::load_objects(Progress &progress)
IObject root = archive.getTop();
for (size_t i = 0; i < root.getNumChildren(); ++i) {
walk_hierarchy(root, root.getChildHeader(i), nullptr, object_map, progress);
walk_hierarchy(root, root.getChildHeader(i), {}, object_map, progress);
}
/* Create nodes in the scene. */
@ -1541,6 +1545,10 @@ void AlembicProcedural::read_mesh(Scene *scene,
Object *object = abc_object->get_object();
cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket());
if (object->is_modified()) {
object->tag_update(scene_);
}
cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket());
@ -1636,6 +1644,10 @@ void AlembicProcedural::read_subd(Scene *scene,
Object *object = abc_object->get_object();
cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket());
if (object->is_modified()) {
object->tag_update(scene_);
}
cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
/* cached_data.shader is also used for subd_shader */
@ -1716,6 +1728,10 @@ void AlembicProcedural::read_curves(Scene *scene,
Object *object = abc_object->get_object();
cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket());
if (object->is_modified()) {
object->tag_update(scene_);
}
cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket());
cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket());
@ -1746,7 +1762,7 @@ void AlembicProcedural::read_curves(Scene *scene,
void AlembicProcedural::walk_hierarchy(
IObject parent,
const ObjectHeader &header,
MatrixSampleMap *xform_samples,
MatrixSamplesData matrix_samples_data,
const unordered_map<std::string, AlembicObject *> &object_map,
Progress &progress)
{
@ -1768,7 +1784,7 @@ void AlembicProcedural::walk_hierarchy(
MatrixSampleMap local_xform_samples;
MatrixSampleMap *temp_xform_samples = nullptr;
if (xform_samples == nullptr) {
if (matrix_samples_data.samples == nullptr) {
/* If there is no parent transforms, fill the map directly. */
temp_xform_samples = &concatenated_xform_samples;
}
@ -1783,11 +1799,13 @@ void AlembicProcedural::walk_hierarchy(
temp_xform_samples->insert({sample_time, sample.getMatrix()});
}
if (xform_samples != nullptr) {
concatenate_xform_samples(*xform_samples, local_xform_samples, concatenated_xform_samples);
if (matrix_samples_data.samples != nullptr) {
concatenate_xform_samples(
*matrix_samples_data.samples, local_xform_samples, concatenated_xform_samples);
}
xform_samples = &concatenated_xform_samples;
matrix_samples_data.samples = &concatenated_xform_samples;
matrix_samples_data.time_sampling = ts;
}
next_object = xform;
@ -1803,8 +1821,9 @@ void AlembicProcedural::walk_hierarchy(
abc_object->iobject = subd;
abc_object->schema_type = AlembicObject::SUBD;
if (xform_samples) {
abc_object->xform_samples = *xform_samples;
if (matrix_samples_data.samples) {
abc_object->xform_samples = *matrix_samples_data.samples;
abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
}
}
@ -1821,8 +1840,9 @@ void AlembicProcedural::walk_hierarchy(
abc_object->iobject = mesh;
abc_object->schema_type = AlembicObject::POLY_MESH;
if (xform_samples) {
abc_object->xform_samples = *xform_samples;
if (matrix_samples_data.samples) {
abc_object->xform_samples = *matrix_samples_data.samples;
abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
}
}
@ -1839,8 +1859,9 @@ void AlembicProcedural::walk_hierarchy(
abc_object->iobject = curves;
abc_object->schema_type = AlembicObject::CURVES;
if (xform_samples) {
abc_object->xform_samples = *xform_samples;
if (matrix_samples_data.samples) {
abc_object->xform_samples = *matrix_samples_data.samples;
abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
}
}
@ -1857,7 +1878,7 @@ void AlembicProcedural::walk_hierarchy(
if (next_object.valid()) {
for (size_t i = 0; i < next_object.getNumChildren(); ++i) {
walk_hierarchy(
next_object, next_object.getChildHeader(i), xform_samples, object_map, progress);
next_object, next_object.getChildHeader(i), matrix_samples_data, object_map, progress);
}
}
}

View File

@ -38,6 +38,11 @@ class Shader;
using MatrixSampleMap = std::map<Alembic::Abc::chrono_t, Alembic::Abc::M44d>;
struct MatrixSamplesData {
MatrixSampleMap *samples = nullptr;
Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling;
};
/* Helpers to detect if some type is a ccl::array. */
template<typename> struct is_array : public std::false_type {
};
@ -274,6 +279,7 @@ class AlembicObject : public Node {
bool need_shader_update = true;
Alembic::AbcCoreAbstract::TimeSamplingPtr xform_time_sampling;
MatrixSampleMap xform_samples;
Alembic::AbcGeom::IObject iobject;
@ -384,7 +390,7 @@ class AlembicProcedural : public Procedural {
* way for each IObject. */
void walk_hierarchy(Alembic::AbcGeom::IObject parent,
const Alembic::AbcGeom::ObjectHeader &ohead,
MatrixSampleMap *xform_samples,
MatrixSamplesData matrix_samples_data,
const unordered_map<string, AlembicObject *> &object_map,
Progress &progress);