diff options
Diffstat (limited to 'source/blender/alembic')
-rw-r--r-- | source/blender/alembic/intern/abc_mesh.cc | 131 |
1 files changed, 63 insertions, 68 deletions
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index e4431bde2f6..1b5ae0b7adc 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -46,6 +46,8 @@ extern "C" { #include "BKE_modifier.h" #include "BKE_object.h" +#include "MEM_guardedalloc.h" + #include "WM_api.h" #include "WM_types.h" @@ -758,7 +760,8 @@ struct AbcMeshData { P3fArraySamplePtr ceil_positions; N3fArraySamplePtr vertex_normals; - N3fArraySamplePtr face_normals; + N3fArraySamplePtr loop_normals; + bool poly_flag_smooth; V2fArraySamplePtr uvs; UInt32ArraySamplePtr uvs_indices; @@ -832,7 +835,6 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) const size_t uvs_size = uvs == nullptr ? 0 : uvs->size(); const UInt32ArraySamplePtr &uvs_indices = mesh_data.uvs_indices; - const N3fArraySamplePtr &normals = mesh_data.face_normals; const bool do_uvs = (mloopuvs && uvs && uvs_indices) && (uvs_indices->size() == face_indices->size()); @@ -847,9 +849,12 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) poly.loopstart = loop_index; poly.totloop = face_size; - if (normals != NULL) { + if (mesh_data.poly_flag_smooth) { poly.flag |= ME_SMOOTH; } + else { + poly.flag &= ~ME_SMOOTH; + } /* NOTE: Alembic data is stored in the reverse order. */ rev_loop_index = loop_index + (face_size - 1); @@ -873,6 +878,40 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) } } } + + BKE_mesh_calc_edges(config.mesh, false, false); +} + +static void process_normals(CDStreamConfig &config, const AbcMeshData &mesh_data) +{ + Mesh *mesh = config.mesh; + + if (!mesh_data.loop_normals) { + BKE_mesh_calc_normals(config.mesh); + config.mesh->flag &= ~ME_AUTOSMOOTH; + return; + } + + config.mesh->flag |= ME_AUTOSMOOTH; + + const Alembic::AbcGeom::N3fArraySample &loop_normals = *mesh_data.loop_normals; + long int loop_count = loop_normals.size(); + + float(*lnors)[3] = static_cast<float(*)[3]>( + MEM_malloc_arrayN(loop_count, sizeof(float[3]), "ABC::FaceNormals")); + + MPoly *mpoly = mesh->mpoly; + int abc_index = 0; + for (int i = 0, e = mesh->totpoly; i < e; ++i, ++mpoly) { + /* As usual, ABC orders the loops in reverse. */ + for (int j = mpoly->totloop - 1; j >= 0; --j, ++abc_index) { + int blender_index = mpoly->loopstart + j; + copy_zup_from_yup(lnors[blender_index], loop_normals[abc_index].getValue()); + } + } + BKE_mesh_set_custom_normals(config.mesh, lnors); + + MEM_freeN(lnors); } ABC_INLINE void read_uvs_params(CDStreamConfig &config, @@ -905,10 +944,6 @@ ABC_INLINE void read_uvs_params(CDStreamConfig &config, } } -/* TODO(kevin): normals from Alembic files are not read in anymore, this is due - * to the fact that there are many issues that are not so easy to solve, mainly - * regarding the way normals are handled in Blender (MPoly.flag vs loop normals). - */ ABC_INLINE void read_normals_params(AbcMeshData &abc_data, const IN3fGeomParam &normals, const ISampleSelector &selector) @@ -922,10 +957,12 @@ ABC_INLINE void read_normals_params(AbcMeshData &abc_data, Alembic::AbcGeom::GeometryScope scope = normals.getScope(); switch (scope) { case Alembic::AbcGeom::kFacevaryingScope: - abc_data.face_normals = normsamp.getVals(); + abc_data.loop_normals = normsamp.getVals(); break; case Alembic::AbcGeom::kVertexScope: case Alembic::AbcGeom::kVaryingScope: + /* Vertex normals from ABC aren't handled for now. */ + abc_data.poly_flag_smooth = true; abc_data.vertex_normals = N3fArraySamplePtr(); break; case Alembic::AbcGeom::kConstantScope: @@ -935,31 +972,6 @@ ABC_INLINE void read_normals_params(AbcMeshData &abc_data, } } -static bool check_smooth_poly_flag(Mesh *mesh) -{ - MPoly *mpolys = mesh->mpoly; - - for (int i = 0, e = mesh->totpoly; i < e; ++i) { - MPoly &poly = mpolys[i]; - - if ((poly.flag & ME_SMOOTH) != 0) { - return true; - } - } - - return false; -} - -static void set_smooth_poly_flag(Mesh *mesh) -{ - MPoly *mpolys = mesh->mpoly; - - for (int i = 0, e = mesh->totpoly; i < e; ++i) { - MPoly &poly = mpolys[i]; - poly.flag |= ME_SMOOTH; - } -} - static void *add_customdata_cb(Mesh *mesh, const char *name, int data_type) { CustomDataType cd_data_type = static_cast<CustomDataType>(data_type); @@ -1001,8 +1013,7 @@ static void read_mesh_sample(const std::string &iobject_full_name, ImportSettings *settings, const IPolyMeshSchema &schema, const ISampleSelector &selector, - CDStreamConfig &config, - bool &r_do_normals) + CDStreamConfig &config) { const IPolyMeshSchema::Sample sample = schema.getValue(selector); @@ -1010,11 +1021,10 @@ static void read_mesh_sample(const std::string &iobject_full_name, abc_mesh_data.face_counts = sample.getFaceCounts(); abc_mesh_data.face_indices = sample.getFaceIndices(); abc_mesh_data.positions = sample.getPositions(); + abc_mesh_data.poly_flag_smooth = false; read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector); - r_do_normals = (abc_mesh_data.face_normals != NULL); - get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); if (config.weight != 0.0f) { @@ -1033,6 +1043,7 @@ static void read_mesh_sample(const std::string &iobject_full_name, if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { read_mpolys(config, abc_mesh_data); + process_normals(config, abc_mesh_data); } if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { @@ -1086,6 +1097,9 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, NULL); if (read_mesh != mesh) { BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true); + + /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_nomain_to_mesh() */ + mesh->flag |= (read_mesh->flag & ME_AUTOSMOOTH); } if (m_settings->validate_meshes) { @@ -1158,6 +1172,8 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, existing_mesh, positions->size(), 0, 0, face_indices->size(), face_counts->size()); settings.read_flag |= MOD_MESHSEQ_READ_ALL; + /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_new_nomain_from_template() */ + new_mesh->flag |= (existing_mesh->flag & ME_AUTOSMOOTH); } else { /* If the face count changed (e.g. by triangulation), only read points. @@ -1178,18 +1194,9 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, CDStreamConfig config = get_config(new_mesh ? new_mesh : existing_mesh); config.time = sample_sel.getRequestedTime(); - bool do_normals = false; - read_mesh_sample(m_iobject.getFullName(), &settings, m_schema, sample_sel, config, do_normals); + read_mesh_sample(m_iobject.getFullName(), &settings, m_schema, sample_sel, config); if (new_mesh) { - /* Check if we had ME_SMOOTH flag set to restore it. */ - if (!do_normals && check_smooth_poly_flag(existing_mesh)) { - set_smooth_poly_flag(new_mesh); - } - - BKE_mesh_calc_normals(new_mesh); - BKE_mesh_calc_edges(new_mesh, false, false); - /* Here we assume that the number of materials doesn't change, i.e. that * the material slots that were created when the object was loaded from * Alembic are still valid now. */ @@ -1202,10 +1209,6 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, return new_mesh; } - if (do_normals) { - BKE_mesh_calc_normals(existing_mesh); - } - return existing_mesh; } @@ -1292,7 +1295,7 @@ static void read_subd_sample(const std::string &iobject_full_name, abc_mesh_data.face_counts = sample.getFaceCounts(); abc_mesh_data.face_indices = sample.getFaceIndices(); abc_mesh_data.vertex_normals = N3fArraySamplePtr(); - abc_mesh_data.face_normals = N3fArraySamplePtr(); + abc_mesh_data.loop_normals = N3fArraySamplePtr(); abc_mesh_data.positions = sample.getPositions(); get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); @@ -1312,7 +1315,14 @@ static void read_subd_sample(const std::string &iobject_full_name, } if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { + /* Alembic's 'SubD' scheme is used to store subdivision surfaces, i.e. the pre-subdivision + * mesh. Currently we don't add a subdivison modifier when we load such data. This code is + * assuming that the subdivided surface should be smooth, and sets a flag that will eventually + * mark all polygons as such. */ + abc_mesh_data.poly_flag_smooth = true; + read_mpolys(config, abc_mesh_data); + process_normals(config, abc_mesh_data); } if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { @@ -1400,9 +1410,6 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; } - BKE_mesh_calc_normals(mesh); - BKE_mesh_calc_edges(mesh, false, false); - if (m_settings->validate_meshes) { BKE_mesh_validate(mesh, false, false); } @@ -1469,17 +1476,5 @@ Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh, config.time = sample_sel.getRequestedTime(); read_subd_sample(m_iobject.getFullName(), &settings, m_schema, sample_sel, config); - if (new_mesh) { - /* Check if we had ME_SMOOTH flag set to restore it. */ - if (check_smooth_poly_flag(existing_mesh)) { - set_smooth_poly_flag(new_mesh); - } - - BKE_mesh_calc_normals(new_mesh); - BKE_mesh_calc_edges(new_mesh, false, false); - - return new_mesh; - } - - return existing_mesh; + return config.mesh; } |