Alembic streaming: initial support to interpolate data between frames.
Pretty self-explanatory, allows to get some slow motion type of playback and animations.
This commit is contained in:
parent
631af9f930
commit
0053a91165
|
@ -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)
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue