diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2016-09-09 06:59:20 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2016-09-09 06:59:20 +0300 |
commit | 0053a9116553c516d7a3e5ccd16d8ffd6a27da3b (patch) | |
tree | d8e3373efc11e91bc00ea3e606b6500ca85534f4 /source/blender/alembic | |
parent | 631af9f930d2fd2c76751204ff22239aa95f761d (diff) |
Alembic streaming: initial support to interpolate data between frames.
Pretty self-explanatory, allows to get some slow motion type of playback
and animations.
Diffstat (limited to 'source/blender/alembic')
-rw-r--r-- | source/blender/alembic/intern/abc_customdata.h | 9 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_mesh.cc | 77 | ||||
-rw-r--r-- | source/blender/alembic/intern/alembic_capi.cc | 2 |
3 files changed, 88 insertions, 0 deletions
diff --git a/source/blender/alembic/intern/abc_customdata.h b/source/blender/alembic/intern/abc_customdata.h index 3b16c0d9796..bc42e24eba1 100644 --- a/source/blender/alembic/intern/abc_customdata.h +++ b/source/blender/alembic/intern/abc_customdata.h @@ -63,6 +63,11 @@ struct CDStreamConfig { void *user_data; void *(*add_customdata_cb)(void *user_data, const char *name, int data_type); + float weight; + float time; + int index; + int ceil_index; + CDStreamConfig() : mloop(NULL) , totloop(0) @@ -72,6 +77,10 @@ struct CDStreamConfig { , pack_uvs(false) , user_data(NULL) , add_customdata_cb(NULL) + , weight(0.0f) + , time(0.0f) + , index(0) + , ceil_index(0) {} }; diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index 70af6af0827..18b5dd9d1e0 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -804,6 +804,7 @@ struct AbcMeshData { Int32ArraySamplePtr face_counts; P3fArraySamplePtr positions; + P3fArraySamplePtr ceil_positions; N3fArraySamplePtr vertex_normals; N3fArraySamplePtr face_normals; @@ -851,12 +852,32 @@ CDStreamConfig create_config(Mesh *mesh) return config; } +static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions, const P3fArraySamplePtr &ceil_positions, const float weight) +{ + float tmp[3]; + for (int i = 0; i < positions->size(); ++i) { + MVert &mvert = mverts[i]; + const Imath::V3f &floor_pos = (*positions)[i]; + const Imath::V3f &ceil_pos = (*ceil_positions)[i]; + + interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight); + copy_yup_zup(mvert.co, tmp); + + mvert.bweight = 0; + } +} + static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data) { MVert *mverts = config.mvert; const P3fArraySamplePtr &positions = mesh_data.positions; const N3fArraySamplePtr &normals = mesh_data.vertex_normals; + if (config.weight != 0.0f && mesh_data.ceil_positions) { + read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight); + return; + } + read_mverts(mverts, positions, normals); } @@ -1083,6 +1104,46 @@ 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; + } + + 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 = alpha; +} + void read_mesh_sample(ImportSettings *settings, const IPolyMeshSchema &schema, const ISampleSelector &selector, @@ -1100,6 +1161,14 @@ void read_mesh_sample(ImportSettings *settings, do_normals = (abc_mesh_data.face_normals != NULL); + get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); + + if (config.weight != 0.0f) { + Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample; + schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index))); + abc_mesh_data.ceil_positions = ceil_sample.getPositions(); + } + if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); } @@ -1215,6 +1284,14 @@ void read_subd_sample(ImportSettings *settings, abc_mesh_data.face_normals = N3fArraySamplePtr(); abc_mesh_data.positions = sample.getPositions(); + get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); + + if (config.weight != 0.0f) { + Alembic::AbcGeom::ISubDSchema::Sample ceil_sample; + schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index))); + abc_mesh_data.ceil_positions = ceil_sample.getPositions(); + } + if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); } diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 04ea8e82f52..3cc549350ea 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -898,6 +898,7 @@ static DerivedMesh *read_mesh_sample(DerivedMesh *dm, const IObject &iobject, co } CDStreamConfig config = get_config(new_dm ? new_dm : dm); + config.time = time; bool do_normals = false; read_mesh_sample(&settings, schema, sample_sel, config, do_normals); @@ -952,6 +953,7 @@ static DerivedMesh *read_subd_sample(DerivedMesh *dm, const IObject &iobject, co /* Only read point data when streaming meshes, unless we need to create new ones. */ CDStreamConfig config = get_config(new_dm ? new_dm : dm); + config.time = time; read_subd_sample(&settings, schema, sample_sel, config); if (new_dm) { |