diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2021-06-16 09:24:50 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2021-06-16 09:24:50 +0300 |
commit | 4f08591bf416a54da8363181343c373061001c87 (patch) | |
tree | 24b4c7c0dc1395f5a900bcc587f4be9dbc797665 /source/blender/io/alembic | |
parent | 05a3652edaf4bb1878fa60c658c95562e831b287 (diff) | |
parent | 3385c04598f210e0fb927845122d1fb5b3a8e81e (diff) |
Merge branch 'master' into cycles_procedural_api
Diffstat (limited to 'source/blender/io/alembic')
-rw-r--r-- | source/blender/io/alembic/intern/abc_customdata.cc | 84 | ||||
-rw-r--r-- | source/blender/io/alembic/intern/abc_customdata.h | 10 | ||||
-rw-r--r-- | source/blender/io/alembic/intern/abc_reader_mesh.cc | 39 |
3 files changed, 82 insertions, 51 deletions
diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index e58d9e30ace..acb21c9f0ad 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -44,6 +44,7 @@ * in the write code for the conventions. */ using Alembic::AbcGeom::kFacevaryingScope; +using Alembic::AbcGeom::kVaryingScope; using Alembic::AbcGeom::kVertexScope; using Alembic::AbcGeom::kVaryingScope; @@ -293,6 +294,7 @@ void write_custom_data(const OCompoundProperty &prop, using Alembic::Abc::C3fArraySamplePtr; using Alembic::Abc::C4fArraySamplePtr; using Alembic::Abc::PropertyHeader; +using Alembic::Abc::UInt32ArraySamplePtr; using Alembic::AbcGeom::IC3fGeomParam; using Alembic::AbcGeom::IC4fGeomParam; @@ -301,8 +303,9 @@ using Alembic::AbcGeom::IV3fGeomParam; static void read_uvs(const CDStreamConfig &config, void *data, + const AbcUvScope uv_scope, const Alembic::AbcGeom::V2fArraySamplePtr &uvs, - const Alembic::AbcGeom::UInt32ArraySamplePtr &indices) + const UInt32ArraySamplePtr &indices) { MPoly *mpolys = config.mpoly; MLoop *mloops = config.mloop; @@ -310,39 +313,22 @@ static void read_uvs(const CDStreamConfig &config, unsigned int uv_index, loop_index, rev_loop_index; - if (indices->size() == config.totloop) { - for (int i = 0; i < config.totpoly; i++) { - MPoly &poly = mpolys[i]; - unsigned int rev_loop_offset = poly.loopstart + poly.totloop - 1; - - for (int f = 0; f < poly.totloop; f++) { - loop_index = poly.loopstart + f; - rev_loop_index = rev_loop_offset - f; - uv_index = (*indices)[loop_index]; - const Imath::V2f &uv = (*uvs)[uv_index]; - - MLoopUV &loopuv = mloopuvs[rev_loop_index]; - loopuv.uv[0] = uv[0]; - loopuv.uv[1] = uv[1]; - } - } - } - else if (indices->size() == config.totvert) { - for (int i = 0; i < config.totpoly; i++) { - MPoly &poly = mpolys[i]; - unsigned int rev_loop_offset = poly.loopstart + poly.totloop - 1; - - for (int f = 0; f < poly.totloop; f++) { - rev_loop_index = rev_loop_offset - f; - - MLoop &loop = mloops[rev_loop_index]; - uv_index = (*indices)[loop.v]; - const Imath::V2f &uv = (*uvs)[uv_index]; + BLI_assert(uv_scope != ABC_UV_SCOPE_NONE); + const bool do_uvs_per_loop = (uv_scope == ABC_UV_SCOPE_LOOP); - MLoopUV &loopuv = mloopuvs[rev_loop_index]; - loopuv.uv[0] = uv[0]; - loopuv.uv[1] = uv[1]; - } + for (int i = 0; i < config.totpoly; i++) { + MPoly &poly = mpolys[i]; + unsigned int rev_loop_offset = poly.loopstart + poly.totloop - 1; + + for (int f = 0; f < poly.totloop; f++) { + rev_loop_index = rev_loop_offset - f; + loop_index = do_uvs_per_loop ? poly.loopstart + f : mloops[rev_loop_index].v; + uv_index = (*indices)[loop_index]; + const Imath::V2f &uv = (*uvs)[uv_index]; + + MLoopUV &loopuv = mloopuvs[rev_loop_index]; + loopuv.uv[0] = uv[0]; + loopuv.uv[1] = uv[1]; } } } @@ -495,13 +481,17 @@ static void read_custom_data_uvs(const ICompoundProperty &prop, IV2fGeomParam::Sample sample; uv_param.getIndexed(sample, iss); - if (uv_param.getScope() != kFacevaryingScope || uv_param.getScope() != kVaryingScope) { + UInt32ArraySamplePtr uvs_indices = sample.getIndices(); + + const AbcUvScope uv_scope = get_uv_scope(uv_param.getScope(), config, uvs_indices); + + if (uv_scope == ABC_UV_SCOPE_NONE) { return; } void *cd_data = config.add_customdata_cb(config.mesh, prop_header.getName().c_str(), CD_MLOOPUV); - read_uvs(config, cd_data, sample.getVals(), sample.getIndices()); + read_uvs(config, cd_data, uv_scope, sample.getVals(), uvs_indices); } void read_generated_coordinates(const ICompoundProperty &prop, @@ -581,4 +571,28 @@ void read_custom_data(const std::string &iobject_full_name, } } +/* UVs can be defined per-loop (one value per vertex per face), or per-vertex (one value per + * vertex). The first case is the most common, as this is the standard way of storing this data + * given that some vertices might be on UV seams and have multiple possible UV coordinates; the + * second case can happen when the mesh is split according to the UV islands, in which case storing + * a single UV value per vertex allows to deduplicate data and thus to reduce the file size since + * vertices are guaranteed to only have a single UV coordinate. */ +AbcUvScope get_uv_scope(const Alembic::AbcGeom::GeometryScope scope, + const CDStreamConfig &config, + const Alembic::AbcGeom::UInt32ArraySamplePtr &indices) +{ + if (scope == kFacevaryingScope && indices->size() == config.totloop) { + return ABC_UV_SCOPE_LOOP; + } + + /* kVaryingScope is sometimes used for vertex scopes as the values vary across the vertices. To + * be sure, one has to check the size of the data against the number of vertices, as it could + * also be a varying attribute across the faces (i.e. one value per face). */ + if ((scope == kVaryingScope || scope == kVertexScope) && indices->size() == config.totvert) { + return ABC_UV_SCOPE_VERTEX; + } + + return ABC_UV_SCOPE_NONE; +} + } // namespace blender::io::alembic diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h index 9ee964c0545..e9736555ead 100644 --- a/source/blender/io/alembic/intern/abc_customdata.h +++ b/source/blender/io/alembic/intern/abc_customdata.h @@ -122,4 +122,14 @@ void read_custom_data(const std::string &iobject_full_name, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss); +typedef enum { + ABC_UV_SCOPE_NONE, + ABC_UV_SCOPE_LOOP, + ABC_UV_SCOPE_VERTEX, +} AbcUvScope; + +AbcUvScope get_uv_scope(const Alembic::AbcGeom::GeometryScope scope, + const CDStreamConfig &config, + const Alembic::AbcGeom::UInt32ArraySamplePtr &indices); + } // namespace blender::io::alembic diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 6e8791c73a9..3c9eb7553e4 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -121,6 +121,7 @@ struct AbcMeshData { P3fArraySamplePtr positions; P3fArraySamplePtr ceil_positions; + AbcUvScope uv_scope; V2fArraySamplePtr uvs; UInt32ArraySamplePtr uvs_indices; }; @@ -194,8 +195,8 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) const UInt32ArraySamplePtr &uvs_indices = mesh_data.uvs_indices; const bool do_uvs = (mloopuvs && uvs && uvs_indices); - const bool do_uvs_per_loop = do_uvs && (uvs_indices->size() == face_indices->size()); - const bool do_uvs_per_vertex = do_uvs && (uvs_indices->size() == positions->size()); + const bool do_uvs_per_loop = do_uvs && mesh_data.uv_scope == ABC_UV_SCOPE_LOOP; + BLI_assert(!do_uvs || mesh_data.uv_scope != ABC_UV_SCOPE_NONE); unsigned int loop_index = 0; unsigned int rev_loop_index = 0; unsigned int uv_index = 0; @@ -229,8 +230,7 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) if (do_uvs_per_loop) { MLoopUV &loopuv = mloopuvs[rev_loop_index]; - - uv_index = (*uvs_indices)[loop_index]; + uv_index = (*uvs_indices)[do_uvs_per_loop ? loop_index : loop.v]; /* Some Alembic files are broken (or at least export UVs in a way we don't expect). */ if (uv_index >= uvs_size) { @@ -371,22 +371,29 @@ BLI_INLINE void read_uvs_params(CDStreamConfig &config, IV2fGeomParam::Sample uvsamp; uv.getIndexed(uvsamp, selector); - abc_data.uvs = uvsamp.getVals(); - abc_data.uvs_indices = uvsamp.getIndices(); + UInt32ArraySamplePtr uvs_indices = uvsamp.getIndices(); - if (abc_data.uvs_indices->size() == config.totloop || abc_data.uvs_indices->size() == config.totvert) { - std::string name = Alembic::Abc::GetSourceName(uv.getMetaData()); + const AbcUvScope uv_scope = get_uv_scope(uv.getScope(), config, uvs_indices); - /* According to the convention, primary UVs should have had their name - * set using Alembic::Abc::SetSourceName, but you can't expect everyone - * to follow it! :) */ - if (name.empty()) { - name = uv.getName(); - } + if (uv_scope == ABC_UV_SCOPE_NONE) { + return; + } - void *cd_ptr = config.add_customdata_cb(config.mesh, name.c_str(), CD_MLOOPUV); - config.mloopuv = static_cast<MLoopUV *>(cd_ptr); + abc_data.uv_scope = uv_scope; + abc_data.uvs = uvsamp.getVals(); + abc_data.uvs_indices = uvs_indices; + + std::string name = Alembic::Abc::GetSourceName(uv.getMetaData()); + + /* According to the convention, primary UVs should have had their name + * set using Alembic::Abc::SetSourceName, but you can't expect everyone + * to follow it! :) */ + if (name.empty()) { + name = uv.getName(); } + + void *cd_ptr = config.add_customdata_cb(config.mesh, name.c_str(), CD_MLOOPUV); + config.mloopuv = static_cast<MLoopUV *>(cd_ptr); } static void *add_customdata_cb(Mesh *mesh, const char *name, int data_type) |