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

Reply via email to