diff options
Diffstat (limited to 'source/blender/io/alembic/intern/abc_reader_mesh.cc')
-rw-r--r-- | source/blender/io/alembic/intern/abc_reader_mesh.cc | 130 |
1 files changed, 88 insertions, 42 deletions
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index eab94139f55..43581ad48d9 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -34,6 +34,7 @@ #include "DNA_object_types.h" #include "BLI_compiler_compat.h" +#include "BLI_index_range.hh" #include "BLI_listbase.h" #include "BLI_math_geom.h" @@ -44,6 +45,7 @@ #include "BKE_modifier.h" #include "BKE_object.h" +using Alembic::Abc::FloatArraySamplePtr; using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::IV3fArrayProperty; using Alembic::Abc::P3fArraySamplePtr; @@ -160,27 +162,26 @@ static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data) return; } - read_mverts(mverts, positions, nullptr); + read_mverts(*config.mesh, positions, nullptr); } -void read_mverts(MVert *mverts, const P3fArraySamplePtr positions, const N3fArraySamplePtr normals) +void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySamplePtr normals) { for (int i = 0; i < positions->size(); i++) { - MVert &mvert = mverts[i]; + MVert &mvert = mesh.mvert[i]; Imath::V3f pos_in = (*positions)[i]; copy_zup_from_yup(mvert.co, pos_in.getValue()); mvert.bweight = 0; - - if (normals) { + } + if (normals) { + float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh); + for (const int i : IndexRange(normals->size())) { Imath::V3f nor_in = (*normals)[i]; - - short no[3]; - normal_float_to_short_v3(no, nor_in.getValue()); - - copy_zup_from_yup(mvert.no, no); + copy_zup_from_yup(vert_normals[i], nor_in.getValue()); } + BKE_mesh_vertex_normals_clear_dirty(&mesh); } } @@ -435,6 +436,13 @@ static V3fArraySamplePtr get_velocity_prop(const ICompoundProperty &schema, const ICompoundProperty &prop = ICompoundProperty(schema, header.getName()); if (has_property(prop, name)) { + /* Header cannot be null here, as its presence is checked via has_property, so it is safe + * to dereference. */ + const PropertyHeader *header = prop.getPropertyHeader(name); + if (!IV3fArrayProperty::matches(*header)) { + continue; + } + const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0); if (velocity_prop) { return velocity_prop.getValue(selector); @@ -442,7 +450,7 @@ static V3fArraySamplePtr get_velocity_prop(const ICompoundProperty &schema, } } else if (header.isArray()) { - if (header.getName() == name) { + if (header.getName() == name && IV3fArrayProperty::matches(header)) { const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0); return velocity_prop.getValue(selector); } @@ -456,13 +464,17 @@ static void read_velocity(const V3fArraySamplePtr &velocities, const CDStreamConfig &config, const float velocity_scale) { + const int num_velocity_vectors = static_cast<int>(velocities->size()); + if (num_velocity_vectors != config.mesh->totvert) { + /* Files containing videogrammetry data may be malformed and export velocity data on missing + * frames (most likely by copying the last valid data). */ + return; + } + CustomDataLayer *velocity_layer = BKE_id_attribute_new( &config.mesh->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT, nullptr); float(*velocity)[3] = (float(*)[3])velocity_layer->data; - const int num_velocity_vectors = static_cast<int>(velocities->size()); - BLI_assert(num_velocity_vectors == config.mesh->totvert); - for (int i = 0; i < num_velocity_vectors; i++) { const Imath::V3f &vel_in = (*velocities)[i]; copy_zup_from_yup(velocity[i], vel_in.getValue()); @@ -899,6 +911,66 @@ static void read_subd_sample(const std::string &iobject_full_name, } } +static void read_vertex_creases(Mesh *mesh, + const Int32ArraySamplePtr &indices, + const FloatArraySamplePtr &sharpnesses) +{ + if (!(indices && sharpnesses && indices->size() == sharpnesses->size() && + indices->size() != 0)) { + return; + } + + float *vertex_crease_data = (float *)CustomData_add_layer( + &mesh->vdata, CD_CREASE, CD_DEFAULT, nullptr, mesh->totvert); + const int totvert = mesh->totvert; + + for (int i = 0, v = indices->size(); i < v; ++i) { + const int idx = (*indices)[i]; + + if (idx >= totvert) { + continue; + } + + vertex_crease_data[idx] = (*sharpnesses)[i]; + } + + mesh->cd_flag |= ME_CDFLAG_VERT_CREASE; +} + +static void read_edge_creases(Mesh *mesh, + const Int32ArraySamplePtr &indices, + const FloatArraySamplePtr &sharpnesses) +{ + if (!(indices && sharpnesses)) { + return; + } + + MEdge *edges = mesh->medge; + int totedge = mesh->totedge; + + for (int i = 0, s = 0, e = indices->size(); i < e; i += 2, s++) { + int v1 = (*indices)[i]; + int v2 = (*indices)[i + 1]; + + if (v2 < v1) { + /* It appears to be common to store edges with the smallest index first, in which case this + * prevents us from doing the second search below. */ + std::swap(v1, v2); + } + + MEdge *edge = find_edge(edges, totedge, v1, v2); + if (edge == nullptr) { + edge = find_edge(edges, totedge, v2, v1); + } + + if (edge) { + edge->crease = unit_float_to_uchar_clamp((*sharpnesses)[s]); + } + } + + mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; +} + /* ************************************************************************** */ AbcSubDReader::AbcSubDReader(const IObject &object, ImportSettings &settings) @@ -962,35 +1034,9 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec return; } - Int32ArraySamplePtr indices = sample.getCreaseIndices(); - Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses(); - - if (indices && sharpnesses) { - MEdge *edges = mesh->medge; - int totedge = mesh->totedge; - - for (int i = 0, s = 0, e = indices->size(); i < e; i += 2, s++) { - int v1 = (*indices)[i]; - int v2 = (*indices)[i + 1]; - - if (v2 < v1) { - /* It appears to be common to store edges with the smallest index first, in which case this - * prevents us from doing the second search below. */ - std::swap(v1, v2); - } + read_edge_creases(mesh, sample.getCreaseIndices(), sample.getCreaseSharpnesses()); - MEdge *edge = find_edge(edges, totedge, v1, v2); - if (edge == nullptr) { - edge = find_edge(edges, totedge, v2, v1); - } - - if (edge) { - edge->crease = unit_float_to_uchar_clamp((*sharpnesses)[s]); - } - } - - mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; - } + read_vertex_creases(mesh, sample.getCornerIndices(), sample.getCornerSharpnesses()); if (m_settings->validate_meshes) { BKE_mesh_validate(mesh, false, false); |