Commit: f3b94a54bc9dc2c93c350e67f4cf1bb048d32afa Author: Kévin Dietrich Date: Tue Sep 20 14:15:02 2016 +0200 Branches: master https://developer.blender.org/rBf3b94a54bc9dc2c93c350e67f4cf1bb048d32afa
Alembic: add support to interpolate transform matrices in-between frames. =================================================================== M source/blender/alembic/intern/abc_mesh.cc M source/blender/alembic/intern/abc_object.cc M source/blender/alembic/intern/abc_object.h M source/blender/alembic/intern/abc_util.cc M source/blender/alembic/intern/abc_util.h M source/blender/alembic/intern/alembic_capi.cc =================================================================== diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index 18b5dd9..5a60587 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -1104,44 +1104,20 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_star utils::assign_materials(bmain, m_object, mat_map); } -typedef std::pair<Alembic::AbcCoreAbstract::index_t, float> index_time_pair_t; - static void get_weight_and_index(CDStreamConfig &config, Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling, size_t samples_number) { - if (samples_number == 0) { - samples_number = 1; - } - - index_time_pair_t floor_index = time_sampling->getFloorIndex(config.time, samples_number); - - config.index = floor_index.first; - config.ceil_index = config.index; - - if (fabs(config.time - floor_index.second) < 0.0001f) { - config.weight = 0.0f; - return; - } + Alembic::AbcGeom::index_t i0, i1; - index_time_pair_t ceil_index = time_sampling->getCeilIndex(config.time, samples_number); - - if (config.index == ceil_index.first) { - config.weight = 0.0f; - return; - } - - config.ceil_index = ceil_index.first; - - float alpha = (config.time - floor_index.second) / (ceil_index.second - floor_index.second); - - /* Since we so closely match the ceiling, we'll just use it. */ - if (fabs(1.0f - alpha) < 0.0001f) { - config.index = config.ceil_index; - alpha = 0.0f; - } + config.weight = get_weight_and_index(config.time, + time_sampling, + samples_number, + i0, + i1); - config.weight = alpha; + config.index = i0; + config.ceil_index = i1; } void read_mesh_sample(ImportSettings *settings, diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index 5b7b85f..32468fd 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -153,6 +153,61 @@ Object *AbcObjectReader::object() const return m_object; } +static Imath::M44d blend_matrices(const Imath::M44d &m0, const Imath::M44d &m1, const float weight) +{ + float mat0[4][4], mat1[4][4], ret[4][4]; + + /* Cannot use Imath::M44d::getValue() since this returns a pointer to + * doubles and interp_m4_m4m4 expects pointers to floats. So need to convert + * the matrices manually. + */ + + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + mat0[i][j] = m0[i][j]; + } + } + + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + mat1[i][j] = m1[i][j]; + } + } + + interp_m4_m4m4(ret, mat0, mat1, weight); + + Imath::M44d m; + + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + m[i][j] = ret[i][j]; + } + } + + return m; +} + +Imath::M44d get_matrix(const IXformSchema &schema, const float time) +{ + Alembic::AbcGeom::index_t i0, i1; + Alembic::AbcGeom::XformSample s0, s1; + + const float weight = get_weight_and_index(time, + schema.getTimeSampling(), + schema.getNumSamples(), + i0, + i1); + + schema.get(s0, Alembic::AbcGeom::ISampleSelector(i0)); + + if (i0 != i1) { + schema.get(s1, Alembic::AbcGeom::ISampleSelector(i1)); + return blend_matrices(s0.getMatrix(), s1.getMatrix(), weight); + } + + return s0.getMatrix(); +} + void AbcObjectReader::readObjectMatrix(const float time) { IXform ixform; @@ -194,11 +249,8 @@ void AbcObjectReader::readObjectMatrix(const float time) return; } - Alembic::AbcGeom::ISampleSelector sample_sel(time); - Alembic::AbcGeom::XformSample xs; - schema.get(xs, sample_sel); - - create_input_transform(sample_sel, ixform, m_object, m_object->obmat, m_settings->scale, has_alembic_parent); + const Imath::M44d matrix = get_matrix(schema, time); + convert_matrix(matrix, m_object, m_object->obmat, m_settings->scale, has_alembic_parent); invert_m4_m4(m_object->imat, m_object->obmat); diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h index 2e885f2..a35faa3 100644 --- a/source/blender/alembic/intern/abc_object.h +++ b/source/blender/alembic/intern/abc_object.h @@ -166,4 +166,6 @@ public: chrono_t maxTime() const; }; +Imath::M44d get_matrix(const Alembic::AbcGeom::IXformSchema &schema, const float time); + #endif /* __ABC_OBJECT_H__ */ diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc index fbab0bc..60c66bc 100644 --- a/source/blender/alembic/intern/abc_util.cc +++ b/source/blender/alembic/intern/abc_util.cc @@ -201,16 +201,9 @@ void create_transform_matrix(float r_mat[4][4]) copy_m4_m4(r_mat, transform_mat); } -void create_input_transform(const Alembic::AbcGeom::ISampleSelector &sample_sel, - const Alembic::AbcGeom::IXform &ixform, Object *ob, - float r_mat[4][4], float scale, bool has_alembic_parent) +void convert_matrix(const Imath::M44d &xform, Object *ob, + float r_mat[4][4], float scale, bool has_alembic_parent) { - - const Alembic::AbcGeom::IXformSchema &ixform_schema = ixform.getSchema(); - Alembic::AbcGeom::XformSample xs; - ixform_schema.get(xs, sample_sel); - const Imath::M44d &xform = xs.getMatrix(); - for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { r_mat[i][j] = xform[i][j]; @@ -435,3 +428,37 @@ bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string return prop.getPropertyHeader(name) != NULL; } + +typedef std::pair<Alembic::AbcCoreAbstract::index_t, float> index_time_pair_t; + +float get_weight_and_index(float time, + const Alembic::AbcCoreAbstract::TimeSamplingPtr &time_sampling, + int samples_number, + Alembic::AbcGeom::index_t &i0, + Alembic::AbcGeom::index_t &i1) +{ + samples_number = std::max(samples_number, 1); + + index_time_pair_t t0 = time_sampling->getFloorIndex(time, samples_number); + i0 = i1 = t0.first; + + if (samples_number == 1 || (fabs(time - t0.second) < 0.0001f)) { + return 0.0f; + } + + index_time_pair_t t1 = time_sampling->getCeilIndex(time, samples_number); + i1 = t1.first; + + if (i0 == i1) { + return 0.0f; + } + + const float bias = (time - t0.second) / (t1.second - t0.second); + + if (fabs(1.0f - bias) < 0.0001f) { + i0 = i1; + return 0.0f; + } + + return bias; +} diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h index 648570f..9e9f0c3 100644 --- a/source/blender/alembic/intern/abc_util.h +++ b/source/blender/alembic/intern/abc_util.h @@ -59,9 +59,8 @@ bool begins_with(const TContainer &input, const TContainer &match) && std::equal(match.begin(), match.end(), input.begin()); } -void create_input_transform(const Alembic::AbcGeom::ISampleSelector &sample_sel, - const Alembic::AbcGeom::IXform &ixform, Object *ob, - float r_mat[4][4], float scale, bool has_alembic_parent = false); +void convert_matrix(const Imath::M44d &xform, Object *ob, + float r_mat[4][4], float scale, bool has_alembic_parent = false); template <typename Schema> void get_min_max_time_ex(const Schema &schema, chrono_t &min, chrono_t &max) @@ -95,6 +94,12 @@ void get_min_max_time(const Alembic::AbcGeom::IObject &object, const Schema &sch bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name); +float get_weight_and_index(float time, + const Alembic::AbcCoreAbstract::TimeSamplingPtr &time_sampling, + int samples_number, + Alembic::AbcGeom::index_t &i0, + Alembic::AbcGeom::index_t &i1); + /* ************************** */ /* TODO(kevin): for now keeping these transformations hardcoded to make sure diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 3cc5493..c698835 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -799,9 +799,8 @@ void ABC_get_transform(AbcArchiveHandle *handle, Object *ob, const char *object_ return; } - ISampleSelector sample_sel(time); - - create_input_transform(sample_sel, ixform, ob, r_mat, scale); + const Imath::M44d matrix = get_matrix(schema, time); + convert_matrix(matrix, ob, r_mat, scale); } /* ***************************************** */ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs