diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/alembic/ABC_alembic.h | 6 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_mesh.cc | 30 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_mesh.h | 2 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_object.cc | 8 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_object.h | 2 | ||||
-rw-r--r-- | source/blender/alembic/intern/alembic_capi.cc | 41 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_meshsequencecache.c | 10 |
7 files changed, 88 insertions, 11 deletions
diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h index 653382017d6..696e0ff1810 100644 --- a/source/blender/alembic/ABC_alembic.h +++ b/source/blender/alembic/ABC_alembic.h @@ -117,6 +117,12 @@ struct Mesh *ABC_read_mesh(struct CacheReader *reader, const char **err_str, int flags); +bool ABC_mesh_topology_changed(struct CacheReader *reader, + struct Object *ob, + struct Mesh *existing_mesh, + const float time, + const char **err_str); + void CacheReader_incref(struct CacheReader *reader); void CacheReader_free(struct CacheReader *reader); diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index 6647ca83bd6..be2793e38f7 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -1131,6 +1131,31 @@ bool AbcMeshReader::accepts_object_type( return true; } +bool AbcMeshReader::topology_changed(Mesh *existing_mesh, const ISampleSelector &sample_sel) +{ + IPolyMeshSchema::Sample sample; + try { + sample = m_schema.getValue(sample_sel); + } + catch (Alembic::Util::Exception &ex) { + printf("Alembic: error reading mesh sample for '%s/%s' at time %f: %s\n", + m_iobject.getFullName().c_str(), + m_schema.getName().c_str(), + sample_sel.getRequestedTime(), + ex.what()); + // A similar error in read_mesh() would just return existing_mesh. + return false; + } + + const P3fArraySamplePtr &positions = sample.getPositions(); + const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices(); + const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts(); + + return positions->size() != existing_mesh->totvert || + face_counts->size() != existing_mesh->totpoly || + face_indices->size() != existing_mesh->totloop; +} + Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, const ISampleSelector &sample_sel, int read_flag, @@ -1162,10 +1187,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, ImportSettings settings; settings.read_flag |= read_flag; - bool topology_changed = positions->size() != existing_mesh->totvert || - face_counts->size() != existing_mesh->totpoly || - face_indices->size() != existing_mesh->totloop; - if (topology_changed) { + if (topology_changed(existing_mesh, sample_sel)) { new_mesh = BKE_mesh_new_nomain_from_template( existing_mesh, positions->size(), 0, 0, face_indices->size(), face_counts->size()); diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h index 859ab121eb6..77686a0204e 100644 --- a/source/blender/alembic/intern/abc_mesh.h +++ b/source/blender/alembic/intern/abc_mesh.h @@ -110,6 +110,8 @@ class AbcMeshReader : public AbcObjectReader { const Alembic::Abc::ISampleSelector &sample_sel, int read_flag, const char **err_str); + bool topology_changed(Mesh *existing_mesh, + const Alembic::Abc::ISampleSelector &sample_sel) override; private: void readFaceSetsSample(Main *bmain, diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index f863fe4fee7..ebebbc0da1e 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -246,6 +246,14 @@ struct Mesh *AbcObjectReader::read_mesh(struct Mesh *existing_mesh, return existing_mesh; } +bool AbcObjectReader::topology_changed(Mesh * /*existing_mesh*/, + const Alembic::Abc::ISampleSelector & /*sample_sel*/) +{ + /* The default implementation of read_mesh() just returns the original mesh, so never changes the + * topology. */ + return false; +} + void AbcObjectReader::setupObjectTransform(const float time) { bool is_constant = false; diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h index 537f24ab7d6..efe78b9017c 100644 --- a/source/blender/alembic/intern/abc_object.h +++ b/source/blender/alembic/intern/abc_object.h @@ -190,6 +190,8 @@ class AbcObjectReader { const Alembic::Abc::ISampleSelector &sample_sel, int read_flag, const char **err_str); + virtual bool topology_changed(Mesh *existing_mesh, + const Alembic::Abc::ISampleSelector &sample_sel); /** Reads the object matrix and sets up an object transform if animated. */ void setupObjectTransform(const float time); diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index d63b310fef7..f7ba925530b 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -937,12 +937,7 @@ void ABC_get_transform(CacheReader *reader, float r_mat[4][4], float time, float /* ************************************************************************** */ -Mesh *ABC_read_mesh(CacheReader *reader, - Object *ob, - Mesh *existing_mesh, - const float time, - const char **err_str, - int read_flag) +static AbcObjectReader *get_abc_reader(CacheReader *reader, Object *ob, const char **err_str) { AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader); IObject iobject = abc_reader->iobject(); @@ -958,12 +953,44 @@ Mesh *ABC_read_mesh(CacheReader *reader, return NULL; } + return abc_reader; +} + +static ISampleSelector sample_selector_for_time(float time) +{ /* kFloorIndex is used to be compatible with non-interpolating * properties; they use the floor. */ - ISampleSelector sample_sel(time, ISampleSelector::kFloorIndex); + return ISampleSelector(time, ISampleSelector::kFloorIndex); +} + +Mesh *ABC_read_mesh(CacheReader *reader, + Object *ob, + Mesh *existing_mesh, + const float time, + const char **err_str, + int read_flag) +{ + AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str); + if (abc_reader == NULL) { + return NULL; + } + + ISampleSelector sample_sel = sample_selector_for_time(time); return abc_reader->read_mesh(existing_mesh, sample_sel, read_flag, err_str); } +bool ABC_mesh_topology_changed( + CacheReader *reader, Object *ob, Mesh *existing_mesh, const float time, const char **err_str) +{ + AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str); + if (abc_reader == NULL) { + return NULL; + } + + ISampleSelector sample_sel = sample_selector_for_time(time); + return abc_reader->topology_changed(existing_mesh, sample_sel); +} + /* ************************************************************************** */ void CacheReader_free(CacheReader *reader) diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 760830ffb24..0f57b759e38 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -114,10 +114,20 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes } } + /* If this invocation is for the ORCO mesh, and the mesh in Alembic hasn't changed topology, we + * must return the mesh as-is instead of deforming it. */ + if (ctx->flag & MOD_APPLY_ORCO && + !ABC_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) { + return mesh; + } + if (me != NULL) { MVert *mvert = mesh->mvert; MEdge *medge = mesh->medge; MPoly *mpoly = mesh->mpoly; + + /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on + * flags) and duplicate those too. */ if ((me->mvert == mvert) || (me->medge == medge) || (me->mpoly == mpoly)) { /* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */ BKE_id_copy_ex(NULL, |