Changeset View
Changeset View
Standalone View
Standalone View
source/blender/alembic/intern/abc_mesh.cc
| Show First 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | |||||
| using Alembic::AbcGeom::OV2fGeomParam; | using Alembic::AbcGeom::OV2fGeomParam; | ||||
| using Alembic::AbcGeom::OV3fGeomParam; | using Alembic::AbcGeom::OV3fGeomParam; | ||||
| using Alembic::AbcGeom::IN3fGeomParam; | using Alembic::AbcGeom::IN3fGeomParam; | ||||
| using Alembic::AbcGeom::kFacevaryingScope; | using Alembic::AbcGeom::kFacevaryingScope; | ||||
| using Alembic::AbcGeom::kVaryingScope; | using Alembic::AbcGeom::kVaryingScope; | ||||
| using Alembic::AbcGeom::kVertexScope; | using Alembic::AbcGeom::kVertexScope; | ||||
| using Alembic::AbcGeom::kWrapExisting; | using Alembic::AbcGeom::kWrapExisting; | ||||
| using Alembic::AbcGeom::N3fArraySample; | |||||
| using Alembic::AbcGeom::N3fArraySamplePtr; | using Alembic::AbcGeom::N3fArraySamplePtr; | ||||
| using Alembic::AbcGeom::UInt32ArraySample; | using Alembic::AbcGeom::UInt32ArraySample; | ||||
| /* ************************************************************************** */ | /* ************************************************************************** */ | ||||
| /* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */ | /* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */ | ||||
| static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points) | static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points) | ||||
| { | { | ||||
| points.clear(); | points.clear(); | ||||
| points.resize(mesh->totvert); | points.resize(mesh->totvert); | ||||
| MVert *verts = mesh->mvert; | MVert *verts = mesh->mvert; | ||||
| for (int i = 0, e = mesh->totvert; i < e; i++) { | for (int i = 0, e = mesh->totvert; i < e; i++) { | ||||
| copy_yup_from_zup(points[i].getValue(), verts[i].co); | copy_yup_from_zup(points[i].getValue(), verts[i].co); | ||||
| } | } | ||||
| } | } | ||||
| static void get_topology(struct Mesh *mesh, | static void get_topology(struct Mesh *mesh, | ||||
| std::vector<int32_t> &poly_verts, | std::vector<int32_t> &poly_verts, | ||||
| std::vector<int32_t> &loop_counts, | std::vector<int32_t> &loop_counts, | ||||
| bool &r_export_loop_normals) | bool &r_has_flat_shaded_poly) | ||||
| { | { | ||||
| const int num_poly = mesh->totpoly; | const int num_poly = mesh->totpoly; | ||||
| const int num_loops = mesh->totloop; | const int num_loops = mesh->totloop; | ||||
| MLoop *mloop = mesh->mloop; | MLoop *mloop = mesh->mloop; | ||||
| MPoly *mpoly = mesh->mpoly; | MPoly *mpoly = mesh->mpoly; | ||||
| r_has_flat_shaded_poly = false; | |||||
| poly_verts.clear(); | poly_verts.clear(); | ||||
| loop_counts.clear(); | loop_counts.clear(); | ||||
| poly_verts.reserve(num_loops); | poly_verts.reserve(num_loops); | ||||
| loop_counts.reserve(num_poly); | loop_counts.reserve(num_poly); | ||||
| /* NOTE: data needs to be written in the reverse order. */ | /* NOTE: data needs to be written in the reverse order. */ | ||||
| for (int i = 0; i < num_poly; i++) { | for (int i = 0; i < num_poly; i++) { | ||||
| MPoly &poly = mpoly[i]; | MPoly &poly = mpoly[i]; | ||||
| loop_counts.push_back(poly.totloop); | loop_counts.push_back(poly.totloop); | ||||
| r_export_loop_normals |= (poly.flag & ME_SMOOTH) != 0; | r_has_flat_shaded_poly |= (poly.flag & ME_SMOOTH) == 0; | ||||
| MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1); | MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1); | ||||
| for (int j = 0; j < poly.totloop; j++, loop--) { | for (int j = 0; j < poly.totloop; j++, loop--) { | ||||
| poly_verts.push_back(loop->v); | poly_verts.push_back(loop->v); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 19 Lines | if (sharpness != 0.0f) { | ||||
| indices.push_back(edge[i].v2); | indices.push_back(edge[i].v2); | ||||
| sharpnesses.push_back(sharpness); | sharpnesses.push_back(sharpness); | ||||
| } | } | ||||
| } | } | ||||
| lengths.resize(sharpnesses.size(), 2); | lengths.resize(sharpnesses.size(), 2); | ||||
| } | } | ||||
| static void get_vertex_normals(struct Mesh *mesh, std::vector<Imath::V3f> &normals) | static void get_loop_normals(struct Mesh *mesh, | ||||
| std::vector<Imath::V3f> &normals, | |||||
| bool has_flat_shaded_poly) | |||||
| { | { | ||||
| normals.clear(); | normals.clear(); | ||||
| normals.resize(mesh->totvert); | |||||
| MVert *verts = mesh->mvert; | /* If all polygons are smooth shaded, and there are no custom normals, we don't need to export | ||||
| float no[3]; | * normals at all. This is also done by other software, see T71246. */ | ||||
| if (!has_flat_shaded_poly && !CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL)) { | |||||
| for (int i = 0, e = mesh->totvert; i < e; i++) { | return; | ||||
| normal_short_to_float_v3(no, verts[i].no); | |||||
| copy_yup_from_zup(normals[i].getValue(), no); | |||||
| } | |||||
| } | } | ||||
| static void get_loop_normals(struct Mesh *mesh, std::vector<Imath::V3f> &normals) | BKE_mesh_calc_normals_split(mesh); | ||||
| { | |||||
| MPoly *mp = mesh->mpoly; | |||||
| MLoop *mloop = mesh->mloop; | |||||
| MLoop *ml = mloop; | |||||
| MVert *verts = mesh->mvert; | |||||
| const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL)); | const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL)); | ||||
| BLI_assert(lnors != NULL || !"BKE_mesh_calc_normals_split() should have computed CD_NORMAL"); | |||||
| normals.clear(); | |||||
| normals.resize(mesh->totloop); | normals.resize(mesh->totloop); | ||||
| /* NOTE: data needs to be written in the reverse order. */ | /* NOTE: data needs to be written in the reverse order. */ | ||||
| int abc_index = 0; | int abc_index = 0; | ||||
| MPoly *mp = mesh->mpoly; | |||||
| if (lnors) { | |||||
| for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) { | for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) { | ||||
| for (int j = mp->totloop - 1; j >= 0; j--, abc_index++) { | for (int j = mp->totloop - 1; j >= 0; j--, abc_index++) { | ||||
| int blender_index = mp->loopstart + j; | int blender_index = mp->loopstart + j; | ||||
| copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]); | copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | |||||
| float no[3]; | |||||
| for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) { | |||||
| ml = mloop + mp->loopstart + (mp->totloop - 1); | |||||
| /* Flat shaded, use common normal for all verts. */ | |||||
| if ((mp->flag & ME_SMOOTH) == 0) { | |||||
| BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no); | |||||
| for (int j = 0; j < mp->totloop; ml--, j++, abc_index++) { | |||||
| copy_yup_from_zup(normals[abc_index].getValue(), no); | |||||
| } | |||||
| } | |||||
| else { | |||||
| /* Smooth shaded, use individual vert normals. */ | |||||
| for (int j = 0; j < mp->totloop; ml--, j++, abc_index++) { | |||||
| normal_short_to_float_v3(no, verts[ml->v].no); | |||||
| copy_yup_from_zup(normals[abc_index].getValue(), no); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /* *************** Modifiers *************** */ | /* *************** Modifiers *************** */ | ||||
| /* check if the mesh is a subsurf, ignoring disabled modifiers and | /* check if the mesh is a subsurf, ignoring disabled modifiers and | ||||
| * displace if it's after subsurf. */ | * displace if it's after subsurf. */ | ||||
| static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob) | static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob) | ||||
| { | { | ||||
| ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last); | ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last); | ||||
| ▲ Show 20 Lines • Show All 153 Lines • ▼ Show 20 Lines | void AbcGenericMeshWriter::freeEvaluatedMesh(struct Mesh *mesh) | ||||
| BKE_id_free(NULL, mesh); | BKE_id_free(NULL, mesh); | ||||
| } | } | ||||
| void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh) | void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh) | ||||
| { | { | ||||
| std::vector<Imath::V3f> points, normals; | std::vector<Imath::V3f> points, normals; | ||||
| std::vector<int32_t> poly_verts, loop_counts; | std::vector<int32_t> poly_verts, loop_counts; | ||||
| std::vector<Imath::V3f> velocities; | std::vector<Imath::V3f> velocities; | ||||
| bool has_flat_shaded_poly = false; | |||||
| bool export_loop_normals = (mesh->flag & ME_AUTOSMOOTH) != 0; | |||||
| get_vertices(mesh, points); | get_vertices(mesh, points); | ||||
| get_topology(mesh, poly_verts, loop_counts, export_loop_normals); | get_topology(mesh, poly_verts, loop_counts, has_flat_shaded_poly); | ||||
| if (m_first_frame && m_settings.export_face_sets) { | if (m_first_frame && m_settings.export_face_sets) { | ||||
| writeFaceSets(mesh, m_mesh_schema); | writeFaceSets(mesh, m_mesh_schema); | ||||
| } | } | ||||
| m_mesh_sample = OPolyMeshSchema::Sample( | m_mesh_sample = OPolyMeshSchema::Sample( | ||||
| V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts)); | V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts)); | ||||
| Show All 11 Lines | if (!sample.indices.empty() && !sample.uvs.empty()) { | ||||
| m_mesh_sample.setUVs(uv_sample); | m_mesh_sample.setUVs(uv_sample); | ||||
| } | } | ||||
| write_custom_data( | write_custom_data( | ||||
| m_mesh_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV); | m_mesh_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV); | ||||
| } | } | ||||
| if (m_settings.export_normals) { | if (m_settings.export_normals) { | ||||
| if (export_loop_normals) { | get_loop_normals(mesh, normals, has_flat_shaded_poly); | ||||
| get_loop_normals(mesh, normals); | |||||
| } | |||||
| else { | |||||
| get_vertex_normals(mesh, normals); | |||||
| } | |||||
| ON3fGeomParam::Sample normals_sample; | ON3fGeomParam::Sample normals_sample; | ||||
| if (!normals.empty()) { | if (!normals.empty()) { | ||||
| normals_sample.setScope(export_loop_normals ? kFacevaryingScope : kVertexScope); | normals_sample.setScope(kFacevaryingScope); | ||||
| normals_sample.setVals(V3fArraySample(normals)); | normals_sample.setVals(V3fArraySample(normals)); | ||||
| } | } | ||||
| m_mesh_sample.setNormals(normals_sample); | m_mesh_sample.setNormals(normals_sample); | ||||
| } | } | ||||
| if (m_is_liquid) { | if (m_is_liquid) { | ||||
| getVelocities(mesh, velocities); | getVelocities(mesh, velocities); | ||||
| m_mesh_sample.setVelocities(V3fArraySample(velocities)); | m_mesh_sample.setVelocities(V3fArraySample(velocities)); | ||||
| } | } | ||||
| m_mesh_sample.setSelfBounds(bounds()); | m_mesh_sample.setSelfBounds(bounds()); | ||||
| m_mesh_schema.set(m_mesh_sample); | m_mesh_schema.set(m_mesh_sample); | ||||
| writeArbGeoParams(mesh); | writeArbGeoParams(mesh); | ||||
| } | } | ||||
| void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh) | void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh) | ||||
| { | { | ||||
| std::vector<float> crease_sharpness; | std::vector<float> crease_sharpness; | ||||
| std::vector<Imath::V3f> points; | std::vector<Imath::V3f> points; | ||||
| std::vector<int32_t> poly_verts, loop_counts; | std::vector<int32_t> poly_verts, loop_counts; | ||||
| std::vector<int32_t> crease_indices, crease_lengths; | std::vector<int32_t> crease_indices, crease_lengths; | ||||
| bool has_flat_poly = false; | |||||
| bool export_loop_normals = false; | |||||
| get_vertices(mesh, points); | get_vertices(mesh, points); | ||||
| get_topology(mesh, poly_verts, loop_counts, export_loop_normals); | get_topology(mesh, poly_verts, loop_counts, has_flat_poly); | ||||
| get_creases(mesh, crease_indices, crease_lengths, crease_sharpness); | get_creases(mesh, crease_indices, crease_lengths, crease_sharpness); | ||||
| if (m_first_frame && m_settings.export_face_sets) { | if (m_first_frame && m_settings.export_face_sets) { | ||||
| writeFaceSets(mesh, m_subdiv_schema); | writeFaceSets(mesh, m_subdiv_schema); | ||||
| } | } | ||||
| m_subdiv_sample = OSubDSchema::Sample( | m_subdiv_sample = OSubDSchema::Sample( | ||||
| V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts)); | V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts)); | ||||
| ▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | |||||
| struct AbcMeshData { | struct AbcMeshData { | ||||
| Int32ArraySamplePtr face_indices; | Int32ArraySamplePtr face_indices; | ||||
| Int32ArraySamplePtr face_counts; | Int32ArraySamplePtr face_counts; | ||||
| P3fArraySamplePtr positions; | P3fArraySamplePtr positions; | ||||
| P3fArraySamplePtr ceil_positions; | P3fArraySamplePtr ceil_positions; | ||||
| N3fArraySamplePtr vertex_normals; | |||||
| N3fArraySamplePtr loop_normals; | |||||
| bool poly_flag_smooth; | |||||
| V2fArraySamplePtr uvs; | V2fArraySamplePtr uvs; | ||||
| UInt32ArraySamplePtr uvs_indices; | UInt32ArraySamplePtr uvs_indices; | ||||
| }; | }; | ||||
| static void read_mverts_interp(MVert *mverts, | static void read_mverts_interp(MVert *mverts, | ||||
| const P3fArraySamplePtr &positions, | const P3fArraySamplePtr &positions, | ||||
| const P3fArraySamplePtr &ceil_positions, | const P3fArraySamplePtr &ceil_positions, | ||||
| const float weight) | const float weight) | ||||
| Show All 10 Lines | for (int i = 0; i < positions->size(); i++) { | ||||
| mvert.bweight = 0; | mvert.bweight = 0; | ||||
| } | } | ||||
| } | } | ||||
| static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data) | static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data) | ||||
| { | { | ||||
| MVert *mverts = config.mvert; | MVert *mverts = config.mvert; | ||||
| const P3fArraySamplePtr &positions = mesh_data.positions; | const P3fArraySamplePtr &positions = mesh_data.positions; | ||||
| const N3fArraySamplePtr &normals = mesh_data.vertex_normals; | |||||
| if (config.weight != 0.0f && mesh_data.ceil_positions != NULL && | if (config.weight != 0.0f && mesh_data.ceil_positions != NULL && | ||||
| mesh_data.ceil_positions->size() == positions->size()) { | mesh_data.ceil_positions->size() == positions->size()) { | ||||
| read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight); | read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight); | ||||
| return; | return; | ||||
| } | } | ||||
| read_mverts(mverts, positions, normals); | read_mverts(mverts, positions, nullptr); | ||||
| } | } | ||||
| void read_mverts(MVert *mverts, | void read_mverts(MVert *mverts, const P3fArraySamplePtr positions, const N3fArraySamplePtr normals) | ||||
| const P3fArraySamplePtr &positions, | |||||
| const N3fArraySamplePtr &normals) | |||||
| { | { | ||||
| for (int i = 0; i < positions->size(); i++) { | for (int i = 0; i < positions->size(); i++) { | ||||
| MVert &mvert = mverts[i]; | MVert &mvert = mverts[i]; | ||||
| Imath::V3f pos_in = (*positions)[i]; | Imath::V3f pos_in = (*positions)[i]; | ||||
| copy_zup_from_yup(mvert.co, pos_in.getValue()); | copy_zup_from_yup(mvert.co, pos_in.getValue()); | ||||
| mvert.bweight = 0; | mvert.bweight = 0; | ||||
| Show All 30 Lines | static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) | ||||
| for (int i = 0; i < face_counts->size(); i++) { | for (int i = 0; i < face_counts->size(); i++) { | ||||
| const int face_size = (*face_counts)[i]; | const int face_size = (*face_counts)[i]; | ||||
| MPoly &poly = mpolys[i]; | MPoly &poly = mpolys[i]; | ||||
| poly.loopstart = loop_index; | poly.loopstart = loop_index; | ||||
| poly.totloop = face_size; | poly.totloop = face_size; | ||||
| if (mesh_data.poly_flag_smooth) { | /* Polygons are always assumed to be smooth-shaded. If the Alembic mesh should be flat-shaded, | ||||
| * this is encoded in custom loop normals. See T71246. */ | |||||
| poly.flag |= ME_SMOOTH; | poly.flag |= ME_SMOOTH; | ||||
| } | |||||
| else { | |||||
| poly.flag &= ~ME_SMOOTH; | |||||
| } | |||||
| /* NOTE: Alembic data is stored in the reverse order. */ | /* NOTE: Alembic data is stored in the reverse order. */ | ||||
| rev_loop_index = loop_index + (face_size - 1); | rev_loop_index = loop_index + (face_size - 1); | ||||
| for (int f = 0; f < face_size; f++, loop_index++, rev_loop_index--) { | for (int f = 0; f < face_size; f++, loop_index++, rev_loop_index--) { | ||||
| MLoop &loop = mloops[rev_loop_index]; | MLoop &loop = mloops[rev_loop_index]; | ||||
| loop.v = (*face_indices)[loop_index]; | loop.v = (*face_indices)[loop_index]; | ||||
| Show All 11 Lines | for (int f = 0; f < face_size; f++, loop_index++, rev_loop_index--) { | ||||
| loopuv.uv[1] = (*uvs)[uv_index][1]; | loopuv.uv[1] = (*uvs)[uv_index][1]; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BKE_mesh_calc_edges(config.mesh, false, false); | BKE_mesh_calc_edges(config.mesh, false, false); | ||||
| } | } | ||||
| static void process_normals(CDStreamConfig &config, const AbcMeshData &mesh_data) | static void process_no_normals(CDStreamConfig &config) | ||||
| { | { | ||||
| Mesh *mesh = config.mesh; | /* Absense of normals in the Alembic mesh is interpreted as 'smooth'. */ | ||||
| if (!mesh_data.loop_normals) { | |||||
| BKE_mesh_calc_normals(config.mesh); | BKE_mesh_calc_normals(config.mesh); | ||||
| } | |||||
| static void process_loop_normals(CDStreamConfig &config, const N3fArraySamplePtr loop_normals_ptr) | |||||
| { | |||||
| size_t loop_count = loop_normals_ptr->size(); | |||||
| if (loop_count == 0) { | |||||
| process_no_normals(config); | |||||
| /* Don't touch the ME_AUTOSMOOTH flag in this case. It can be used by artists to toggle between | /* Don't touch the ME_AUTOSMOOTH flag in this case. It can be used by artists to toggle between | ||||
| * flat/smooth shaded when the Alembic mesh doesn't contain loop normals. */ | * flat/smooth shaded when the Alembic mesh doesn't contain loop normals. */ | ||||
| return; | 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]>( | float(*lnors)[3] = static_cast<float(*)[3]>( | ||||
| MEM_malloc_arrayN(loop_count, sizeof(float[3]), "ABC::FaceNormals")); | MEM_malloc_arrayN(loop_count, sizeof(float[3]), "ABC::FaceNormals")); | ||||
| Mesh *mesh = config.mesh; | |||||
| MPoly *mpoly = mesh->mpoly; | MPoly *mpoly = mesh->mpoly; | ||||
| const N3fArraySample &loop_normals = *loop_normals_ptr; | |||||
| int abc_index = 0; | int abc_index = 0; | ||||
| for (int i = 0, e = mesh->totpoly; i < e; i++, mpoly++) { | for (int i = 0, e = mesh->totpoly; i < e; i++, mpoly++) { | ||||
| /* As usual, ABC orders the loops in reverse. */ | /* As usual, ABC orders the loops in reverse. */ | ||||
| for (int j = mpoly->totloop - 1; j >= 0; j--, abc_index++) { | for (int j = mpoly->totloop - 1; j >= 0; j--, abc_index++) { | ||||
| int blender_index = mpoly->loopstart + j; | int blender_index = mpoly->loopstart + j; | ||||
| copy_zup_from_yup(lnors[blender_index], loop_normals[abc_index].getValue()); | copy_zup_from_yup(lnors[blender_index], loop_normals[abc_index].getValue()); | ||||
| } | } | ||||
| } | } | ||||
| BKE_mesh_set_custom_normals(config.mesh, lnors); | |||||
| mesh->flag |= ME_AUTOSMOOTH; | |||||
| BKE_mesh_set_custom_normals(mesh, lnors); | |||||
| MEM_freeN(lnors); | MEM_freeN(lnors); | ||||
| } | } | ||||
| ABC_INLINE void read_uvs_params(CDStreamConfig &config, | static void process_vertex_normals(CDStreamConfig &config, | ||||
| AbcMeshData &abc_data, | const N3fArraySamplePtr vertex_normals_ptr) | ||||
| const IV2fGeomParam &uv, | |||||
| const ISampleSelector &selector) | |||||
| { | { | ||||
| if (!uv.valid()) { | size_t normals_count = vertex_normals_ptr->size(); | ||||
| if (normals_count == 0) { | |||||
| process_no_normals(config); | |||||
| return; | return; | ||||
| } | } | ||||
| IV2fGeomParam::Sample uvsamp; | float(*vnors)[3] = static_cast<float(*)[3]>( | ||||
| uv.getIndexed(uvsamp, selector); | MEM_malloc_arrayN(normals_count, sizeof(float[3]), "ABC::VertexNormals")); | ||||
| abc_data.uvs = uvsamp.getVals(); | |||||
| abc_data.uvs_indices = uvsamp.getIndices(); | |||||
| if (abc_data.uvs_indices->size() == config.totloop) { | |||||
| std::string name = Alembic::Abc::GetSourceName(uv.getMetaData()); | |||||
| /* According to the convention, primary UVs should have had their name | const N3fArraySample &vertex_normals = *vertex_normals_ptr; | ||||
| * set using Alembic::Abc::SetSourceName, but you can't expect everyone | for (int index = 0; index < normals_count; index++) { | ||||
| * to follow it! :) */ | copy_zup_from_yup(vnors[index], vertex_normals[index].getValue()); | ||||
| if (name.empty()) { | |||||
| name = uv.getName(); | |||||
| } | } | ||||
| void *cd_ptr = config.add_customdata_cb(config.mesh, name.c_str(), CD_MLOOPUV); | config.mesh->flag |= ME_AUTOSMOOTH; | ||||
| config.mloopuv = static_cast<MLoopUV *>(cd_ptr); | BKE_mesh_set_custom_normals_from_vertices(config.mesh, vnors); | ||||
| } | MEM_freeN(vnors); | ||||
| } | } | ||||
| ABC_INLINE void read_normals_params(AbcMeshData &abc_data, | static void process_normals(CDStreamConfig &config, | ||||
| const IN3fGeomParam &normals, | const IN3fGeomParam &normals, | ||||
| const ISampleSelector &selector) | const ISampleSelector &selector) | ||||
| { | { | ||||
| if (!normals.valid()) { | if (!normals.valid()) { | ||||
| process_no_normals(config); | |||||
| return; | return; | ||||
| } | } | ||||
| IN3fGeomParam::Sample normsamp = normals.getExpandedValue(selector); | IN3fGeomParam::Sample normsamp = normals.getExpandedValue(selector); | ||||
| Alembic::AbcGeom::GeometryScope scope = normals.getScope(); | Alembic::AbcGeom::GeometryScope scope = normals.getScope(); | ||||
| switch (scope) { | switch (scope) { | ||||
| case Alembic::AbcGeom::kFacevaryingScope: | case Alembic::AbcGeom::kFacevaryingScope: | ||||
| abc_data.loop_normals = normsamp.getVals(); | process_loop_normals(config, normsamp.getVals()); | ||||
| break; | break; | ||||
| case Alembic::AbcGeom::kVertexScope: | case Alembic::AbcGeom::kVertexScope: | ||||
| case Alembic::AbcGeom::kVaryingScope: | case Alembic::AbcGeom::kVaryingScope: | ||||
| /* Vertex normals from ABC aren't handled for now. */ | process_vertex_normals(config, normsamp.getVals()); | ||||
| abc_data.poly_flag_smooth = true; | |||||
| abc_data.vertex_normals = N3fArraySamplePtr(); | |||||
| break; | break; | ||||
| case Alembic::AbcGeom::kConstantScope: | case Alembic::AbcGeom::kConstantScope: | ||||
| case Alembic::AbcGeom::kUniformScope: | case Alembic::AbcGeom::kUniformScope: | ||||
| case Alembic::AbcGeom::kUnknownScope: | case Alembic::AbcGeom::kUnknownScope: | ||||
| process_no_normals(config); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| ABC_INLINE void read_uvs_params(CDStreamConfig &config, | |||||
| AbcMeshData &abc_data, | |||||
| const IV2fGeomParam &uv, | |||||
| const ISampleSelector &selector) | |||||
| { | |||||
| if (!uv.valid()) { | |||||
| return; | |||||
| } | |||||
| IV2fGeomParam::Sample uvsamp; | |||||
| uv.getIndexed(uvsamp, selector); | |||||
| abc_data.uvs = uvsamp.getVals(); | |||||
| abc_data.uvs_indices = uvsamp.getIndices(); | |||||
| if (abc_data.uvs_indices->size() == config.totloop) { | |||||
| 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) | static void *add_customdata_cb(Mesh *mesh, const char *name, int data_type) | ||||
| { | { | ||||
| CustomDataType cd_data_type = static_cast<CustomDataType>(data_type); | CustomDataType cd_data_type = static_cast<CustomDataType>(data_type); | ||||
| void *cd_ptr; | void *cd_ptr; | ||||
| CustomData *loopdata; | CustomData *loopdata; | ||||
| int numloops; | int numloops; | ||||
| /* unsupported custom data type -- don't do anything. */ | /* unsupported custom data type -- don't do anything. */ | ||||
| Show All 34 Lines | |||||
| { | { | ||||
| const IPolyMeshSchema::Sample sample = schema.getValue(selector); | const IPolyMeshSchema::Sample sample = schema.getValue(selector); | ||||
| AbcMeshData abc_mesh_data; | AbcMeshData abc_mesh_data; | ||||
| abc_mesh_data.face_counts = sample.getFaceCounts(); | abc_mesh_data.face_counts = sample.getFaceCounts(); | ||||
| abc_mesh_data.face_indices = sample.getFaceIndices(); | abc_mesh_data.face_indices = sample.getFaceIndices(); | ||||
| abc_mesh_data.positions = sample.getPositions(); | abc_mesh_data.positions = sample.getPositions(); | ||||
| /* The auto-smoothing flag can be used by artists when the Alembic file does not contain custom | |||||
| * loop normals. Auto-smoothing only works when polys are marked as smooth. */ | |||||
| abc_mesh_data.poly_flag_smooth = (config.mesh->flag & ME_AUTOSMOOTH); | |||||
| read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector); | |||||
| get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); | get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); | ||||
| if (config.weight != 0.0f) { | if (config.weight != 0.0f) { | ||||
| Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample; | Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample; | ||||
| schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index)); | schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index)); | ||||
| abc_mesh_data.ceil_positions = ceil_sample.getPositions(); | abc_mesh_data.ceil_positions = ceil_sample.getPositions(); | ||||
| } | } | ||||
| if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { | if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { | ||||
| read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); | read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); | ||||
| } | } | ||||
| if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { | if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { | ||||
| read_mverts(config, abc_mesh_data); | read_mverts(config, abc_mesh_data); | ||||
| } | } | ||||
| if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { | if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { | ||||
| read_mpolys(config, abc_mesh_data); | read_mpolys(config, abc_mesh_data); | ||||
| process_normals(config, abc_mesh_data); | process_normals(config, schema.getNormalsParam(), selector); | ||||
| } | } | ||||
| if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { | if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { | ||||
| read_custom_data(iobject_full_name, schema.getArbGeomParams(), config, selector); | read_custom_data(iobject_full_name, schema.getArbGeomParams(), config, selector); | ||||
| } | } | ||||
| } | } | ||||
| CDStreamConfig get_config(Mesh *mesh) | CDStreamConfig get_config(Mesh *mesh) | ||||
| ▲ Show 20 Lines • Show All 255 Lines • ▼ Show 20 Lines | static void read_subd_sample(const std::string &iobject_full_name, | ||||
| const ISampleSelector &selector, | const ISampleSelector &selector, | ||||
| CDStreamConfig &config) | CDStreamConfig &config) | ||||
| { | { | ||||
| const ISubDSchema::Sample sample = schema.getValue(selector); | const ISubDSchema::Sample sample = schema.getValue(selector); | ||||
| AbcMeshData abc_mesh_data; | AbcMeshData abc_mesh_data; | ||||
| abc_mesh_data.face_counts = sample.getFaceCounts(); | abc_mesh_data.face_counts = sample.getFaceCounts(); | ||||
| abc_mesh_data.face_indices = sample.getFaceIndices(); | abc_mesh_data.face_indices = sample.getFaceIndices(); | ||||
| abc_mesh_data.vertex_normals = N3fArraySamplePtr(); | |||||
| abc_mesh_data.loop_normals = N3fArraySamplePtr(); | |||||
| abc_mesh_data.positions = sample.getPositions(); | abc_mesh_data.positions = sample.getPositions(); | ||||
| get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); | get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); | ||||
| if (config.weight != 0.0f) { | if (config.weight != 0.0f) { | ||||
| Alembic::AbcGeom::ISubDSchema::Sample ceil_sample; | Alembic::AbcGeom::ISubDSchema::Sample ceil_sample; | ||||
| schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index)); | schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index)); | ||||
| abc_mesh_data.ceil_positions = ceil_sample.getPositions(); | abc_mesh_data.ceil_positions = ceil_sample.getPositions(); | ||||
| } | } | ||||
| if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { | if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { | ||||
| read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); | read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); | ||||
| } | } | ||||
| if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { | if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { | ||||
| read_mverts(config, abc_mesh_data); | read_mverts(config, abc_mesh_data); | ||||
| } | } | ||||
| if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { | if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { | ||||
| /* Alembic's 'SubD' scheme is used to store subdivision surfaces, i.e. the pre-subdivision | /* Alembic's 'SubD' scheme is used to store subdivision surfaces, i.e. the pre-subdivision | ||||
| * mesh. Currently we don't add a subdivision modifier when we load such data. This code is | * mesh. Currently we don't add a subdivision modifier when we load such data. This code is | ||||
| * assuming that the subdivided surface should be smooth, and sets a flag that will eventually | * assuming that the subdivided surface should be smooth. */ | ||||
| * mark all polygons as such. */ | |||||
| abc_mesh_data.poly_flag_smooth = true; | |||||
| read_mpolys(config, abc_mesh_data); | read_mpolys(config, abc_mesh_data); | ||||
| process_normals(config, abc_mesh_data); | process_no_normals(config); | ||||
| } | } | ||||
| if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { | if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { | ||||
| read_custom_data(iobject_full_name, schema.getArbGeomParams(), config, selector); | read_custom_data(iobject_full_name, schema.getArbGeomParams(), config, selector); | ||||
| } | } | ||||
| } | } | ||||
| /* ************************************************************************** */ | /* ************************************************************************** */ | ||||
| ▲ Show 20 Lines • Show All 160 Lines • Show Last 20 Lines | |||||