diff options
author | Ray Molenkamp <github@lazydodo.com> | 2022-10-05 18:46:18 +0300 |
---|---|---|
committer | Ray Molenkamp <github@lazydodo.com> | 2022-10-05 18:46:18 +0300 |
commit | 42736e0b3f85dc248186dd6dc5349a99addc8c84 (patch) | |
tree | d0768a91d8ebfb50642034fdf8437199a5e420b7 /source/blender/io | |
parent | 42ce93a2cbc28836d22b7fa47e99aa3df76e1acc (diff) | |
parent | b47a234f98dd7e6e0b53ad96b5b4d278635874d8 (diff) |
Merge remote-tracking branch 'origin/master' into tmp-vfx-platform-2023
Diffstat (limited to 'source/blender/io')
99 files changed, 1820 insertions, 1657 deletions
diff --git a/source/blender/io/alembic/exporter/abc_archive.cc b/source/blender/io/alembic/exporter/abc_archive.cc index 9c8a36958d5..55e172db241 100644 --- a/source/blender/io/alembic/exporter/abc_archive.cc +++ b/source/blender/io/alembic/exporter/abc_archive.cc @@ -130,13 +130,13 @@ static TimeSamplingPtr create_time_sampling(double scene_fps, get_shutter_samples(scene_fps, params, nr_of_samples, true, samples); - TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / scene_fps); + TimeSamplingType ts(uint32_t(samples.size()), 1.0 / scene_fps); return TimeSamplingPtr(new TimeSampling(ts, samples)); // NOLINT: modernize-make-shared } static void get_frames(double scene_fps, const AlembicExportParams ¶ms, - unsigned int nr_of_samples, + uint nr_of_samples, std::set<double> &r_frames) { /* Get one set of shutter samples, then add those around each frame to export. */ diff --git a/source/blender/io/alembic/exporter/abc_export_capi.cc b/source/blender/io/alembic/exporter/abc_export_capi.cc index dfca89e2c6d..546bc9d49cc 100644 --- a/source/blender/io/alembic/exporter/abc_export_capi.cc +++ b/source/blender/io/alembic/exporter/abc_export_capi.cc @@ -144,8 +144,8 @@ static void export_startjob(void *customdata, } /* Update the scene for the next frame to render. */ - scene->r.cfra = static_cast<int>(frame); - scene->r.subframe = static_cast<float>(frame - scene->r.cfra); + scene->r.cfra = int(frame); + scene->r.subframe = float(frame - scene->r.cfra); BKE_scene_graph_update_for_newframe(data->depsgraph); CLOG_INFO(&LOG, 2, "Exporting frame %.2f", frame); diff --git a/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc b/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc index 514ce389e36..712b04f3992 100644 --- a/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc +++ b/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc @@ -14,6 +14,7 @@ #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "BKE_layer.h" #include "BKE_modifier.h" namespace blender::io::alembic { @@ -34,7 +35,8 @@ void SubdivModifierDisabler::disable_modifiers() Scene *scene = DEG_get_input_scene(depsgraph_); ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph_); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *object = base->object; if (object->type != OB_MESH) { diff --git a/source/blender/io/alembic/exporter/abc_writer_curves.cc b/source/blender/io/alembic/exporter/abc_writer_curves.cc index 4717d3ec26e..e5e8053d7d3 100644 --- a/source/blender/io/alembic/exporter/abc_writer_curves.cc +++ b/source/blender/io/alembic/exporter/abc_writer_curves.cc @@ -142,7 +142,7 @@ void ABCCurveWriter::do_write(HierarchyContext &context) } } - orders.push_back(static_cast<uint8_t>(nurbs->orderu)); + orders.push_back(uint8_t(nurbs->orderu)); vert_counts.push_back(verts.size() - current_point_count); } diff --git a/source/blender/io/alembic/exporter/abc_writer_hair.cc b/source/blender/io/alembic/exporter/abc_writer_hair.cc index 99c609b0235..f872943ad5c 100644 --- a/source/blender/io/alembic/exporter/abc_writer_hair.cc +++ b/source/blender/io/alembic/exporter/abc_writer_hair.cc @@ -120,9 +120,9 @@ void ABCHairWriter::write_hair_sample(const HierarchyContext &context, float inv_mat[4][4]; invert_m4_m4_safe(inv_mat, context.object->obmat); - MTFace *mtface = mesh->mtface; - MFace *mface = mesh->mface; - MVert *mverts = mesh->mvert; + MTFace *mtface = (MTFace *)CustomData_get_layer(&mesh->fdata, CD_MTFACE); + MFace *mface = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE); + const MVert *mverts = BKE_mesh_verts(mesh); const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh); if ((!mtface || !mface) && !uv_warning_shown_) { @@ -190,7 +190,7 @@ void ABCHairWriter::write_hair_sample(const HierarchyContext &context, for (int n = 0; n < mesh->totface; n++) { MFace *face = &mface[n]; MTFace *tface = mtface + n; - unsigned int vtx[4]; + uint vtx[4]; vtx[0] = face->v1; vtx[1] = face->v2; vtx[2] = face->v3; @@ -243,8 +243,9 @@ void ABCHairWriter::write_hair_child_sample(const HierarchyContext &context, float inv_mat[4][4]; invert_m4_m4_safe(inv_mat, context.object->obmat); - MTFace *mtface = mesh->mtface; - MVert *mverts = mesh->mvert; + MFace *mface = (MFace *)CustomData_get_layer(&mesh->fdata, CD_MFACE); + MTFace *mtface = (MTFace *)CustomData_get_layer(&mesh->fdata, CD_MTFACE); + const MVert *mverts = BKE_mesh_verts(mesh); const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh); ParticleSystem *psys = context.particle_system; @@ -269,7 +270,7 @@ void ABCHairWriter::write_hair_child_sample(const HierarchyContext &context, continue; } - MFace *face = &mesh->mface[num]; + MFace *face = &mface[num]; MTFace *tface = mtface + num; float r_uv[2], tmpnor[3], mapfw[4], vec[3]; diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 07b185ffd64..084d26198bc 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -12,6 +12,7 @@ #include "BLI_math_vector.h" #include "BKE_attribute.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_lib_id.h" #include "BKE_material.h" @@ -175,8 +176,8 @@ void ABCGenericMeshWriter::do_write(HierarchyContext &context) m_custom_data_config.pack_uvs = args_.export_params->packuv; m_custom_data_config.mesh = mesh; - m_custom_data_config.mpoly = mesh->mpoly; - m_custom_data_config.mloop = mesh->mloop; + m_custom_data_config.mpoly = mesh->polys_for_write().data(); + m_custom_data_config.mloop = mesh->loops_for_write().data(); m_custom_data_config.totpoly = mesh->totpoly; m_custom_data_config.totloop = mesh->totloop; m_custom_data_config.totvert = mesh->totvert; @@ -366,7 +367,7 @@ bool ABCGenericMeshWriter::get_velocities(struct Mesh *mesh, std::vector<Imath:: { /* Export velocity attribute output by fluid sim, sequence cache modifier * and geometry nodes. */ - CustomDataLayer *velocity_layer = BKE_id_attribute_find( + const CustomDataLayer *velocity_layer = BKE_id_attribute_find( &mesh->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT); if (velocity_layer == nullptr) { @@ -390,12 +391,12 @@ void ABCGenericMeshWriter::get_geo_groups(Object *object, struct Mesh *mesh, std::map<std::string, std::vector<int32_t>> &geo_groups) { - const int num_poly = mesh->totpoly; - MPoly *polygons = mesh->mpoly; + const bke::AttributeAccessor attributes = mesh->attributes(); + const VArraySpan<int> material_indices = attributes.lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); - for (int i = 0; i < num_poly; i++) { - MPoly ¤t_poly = polygons[i]; - short mnr = current_poly.mat_nr; + for (const int i : material_indices.index_range()) { + short mnr = material_indices[i]; Material *mat = BKE_object_material_get(object, mnr + 1); @@ -435,8 +436,7 @@ static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points) points.clear(); points.resize(mesh->totvert); - MVert *verts = mesh->mvert; - + const Span<MVert> verts = mesh->verts(); for (int i = 0, e = mesh->totvert; i < e; i++) { copy_yup_from_zup(points[i].getValue(), verts[i].co); } @@ -447,25 +447,23 @@ static void get_topology(struct Mesh *mesh, std::vector<int32_t> &loop_counts, bool &r_has_flat_shaded_poly) { - const int num_poly = mesh->totpoly; - const int num_loops = mesh->totloop; - MLoop *mloop = mesh->mloop; - MPoly *mpoly = mesh->mpoly; + const Span<MPoly> polys = mesh->polys(); + const Span<MLoop> loops = mesh->loops(); r_has_flat_shaded_poly = false; poly_verts.clear(); loop_counts.clear(); - poly_verts.reserve(num_loops); - loop_counts.reserve(num_poly); + poly_verts.reserve(loops.size()); + loop_counts.reserve(polys.size()); /* NOTE: data needs to be written in the reverse order. */ - for (int i = 0; i < num_poly; i++) { - MPoly &poly = mpoly[i]; + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; loop_counts.push_back(poly.totloop); r_has_flat_shaded_poly |= (poly.flag & ME_SMOOTH) == 0; - MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1); + const MLoop *loop = &loops[poly.loopstart + (poly.totloop - 1)]; for (int j = 0; j < poly.totloop; j++, loop--) { poly_verts.push_back(loop->v); @@ -478,20 +476,21 @@ static void get_edge_creases(struct Mesh *mesh, std::vector<int32_t> &lengths, std::vector<float> &sharpnesses) { - const float factor = 1.0f / 255.0f; - indices.clear(); lengths.clear(); sharpnesses.clear(); - MEdge *edge = mesh->medge; - - for (int i = 0, e = mesh->totedge; i < e; i++) { - const float sharpness = static_cast<float>(edge[i].crease) * factor; + const float *creases = static_cast<const float *>(CustomData_get_layer(&mesh->edata, CD_CREASE)); + if (!creases) { + return; + } + const Span<MEdge> edges = mesh->edges(); + for (const int i : edges.index_range()) { + const float sharpness = creases[i]; if (sharpness != 0.0f) { - indices.push_back(edge[i].v1); - indices.push_back(edge[i].v2); + indices.push_back(edges[i].v1); + indices.push_back(edges[i].v2); sharpnesses.push_back(sharpness); } } @@ -543,8 +542,10 @@ static void get_loop_normals(struct Mesh *mesh, /* NOTE: data needs to be written in the reverse order. */ int abc_index = 0; - MPoly *mp = mesh->mpoly; - for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) { + const Span<MPoly> polys = mesh->polys(); + + for (const int i : polys.index_range()) { + const MPoly *mp = &polys[i]; for (int j = mp->totloop - 1; j >= 0; j--, abc_index++) { int blender_index = mp->loopstart + j; copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]); diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index 2820a128072..3349f9fc30b 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -57,7 +57,7 @@ static void get_uvs(const CDStreamConfig &config, } const int num_poly = config.totpoly; - MPoly *polygons = config.mpoly; + MPoly *mpoly = config.mpoly; MLoop *mloop = config.mloop; if (!config.pack_uvs) { @@ -67,7 +67,7 @@ static void get_uvs(const CDStreamConfig &config, /* Iterate in reverse order to match exported polygons. */ for (int i = 0; i < num_poly; i++) { - MPoly ¤t_poly = polygons[i]; + MPoly ¤t_poly = mpoly[i]; const MLoopUV *loopuv = mloopuv_array + current_poly.loopstart + current_poly.totloop; for (int j = 0; j < current_poly.totloop; j++, count++) { @@ -85,7 +85,7 @@ static void get_uvs(const CDStreamConfig &config, int idx_count = 0; for (int i = 0; i < num_poly; i++) { - MPoly ¤t_poly = polygons[i]; + MPoly ¤t_poly = mpoly[i]; MLoop *looppoly = mloop + current_poly.loopstart + current_poly.totloop; const MLoopUV *loopuv = mloopuv_array + current_poly.loopstart + current_poly.totloop; @@ -322,14 +322,14 @@ static void read_uvs(const CDStreamConfig &config, MLoop *mloops = config.mloop; MLoopUV *mloopuvs = static_cast<MLoopUV *>(data); - unsigned int uv_index, loop_index, rev_loop_index; + uint uv_index, loop_index, rev_loop_index; BLI_assert(uv_scope != ABC_UV_SCOPE_NONE); const bool do_uvs_per_loop = (uv_scope == ABC_UV_SCOPE_LOOP); for (int i = 0; i < config.totpoly; i++) { MPoly &poly = mpolys[i]; - unsigned int rev_loop_offset = poly.loopstart + poly.totloop - 1; + uint rev_loop_offset = poly.loopstart + poly.totloop - 1; for (int f = 0; f < poly.totloop; f++) { rev_loop_index = rev_loop_offset - f; @@ -540,7 +540,7 @@ void read_generated_coordinates(const ICompoundProperty &prop, cd_data = CustomData_get_layer(&mesh->vdata, CD_ORCO); } else { - cd_data = CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_CALLOC, nullptr, totvert); + cd_data = CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_CONSTRUCT, nullptr, totvert); } float(*orcodata)[3] = static_cast<float(*)[3]>(cd_data); @@ -564,7 +564,6 @@ void read_custom_data(const std::string &iobject_full_name, } int num_uvs = 0; - int num_colors = 0; const size_t num_props = prop.getNumProperties(); @@ -583,10 +582,6 @@ void read_custom_data(const std::string &iobject_full_name, /* Read vertex colors according to convention. */ if (IC3fGeomParam::matches(prop_header) || IC4fGeomParam::matches(prop_header)) { - if (++num_colors > MAX_MCOL) { - continue; - } - read_custom_data_mcols(iobject_full_name, prop, prop_header, config, iss); continue; } diff --git a/source/blender/io/alembic/intern/abc_reader_camera.cc b/source/blender/io/alembic/intern/abc_reader_camera.cc index 830526a11ac..e7a319730b6 100644 --- a/source/blender/io/alembic/intern/abc_reader_camera.cc +++ b/source/blender/io/alembic/intern/abc_reader_camera.cc @@ -77,11 +77,11 @@ void AbcCameraReader::readObjectData(Main *bmain, const ISampleSelector &sample_ bcam->stereo.convergence_distance = convergence_plane.getValue(sample_sel); } - const float lens = static_cast<float>(cam_sample.getFocalLength()); - const float apperture_x = static_cast<float>(cam_sample.getHorizontalAperture()); - const float apperture_y = static_cast<float>(cam_sample.getVerticalAperture()); - const float h_film_offset = static_cast<float>(cam_sample.getHorizontalFilmOffset()); - const float v_film_offset = static_cast<float>(cam_sample.getVerticalFilmOffset()); + const float lens = float(cam_sample.getFocalLength()); + const float apperture_x = float(cam_sample.getHorizontalAperture()); + const float apperture_y = float(cam_sample.getVerticalAperture()); + const float h_film_offset = float(cam_sample.getHorizontalFilmOffset()); + const float v_film_offset = float(cam_sample.getVerticalFilmOffset()); const float film_aspect = apperture_x / apperture_y; bcam->lens = lens; @@ -89,10 +89,10 @@ void AbcCameraReader::readObjectData(Main *bmain, const ISampleSelector &sample_ bcam->sensor_y = apperture_y * 10; bcam->shiftx = h_film_offset / apperture_x; bcam->shifty = v_film_offset / apperture_y / film_aspect; - bcam->clip_start = max_ff(0.1f, static_cast<float>(cam_sample.getNearClippingPlane())); - bcam->clip_end = static_cast<float>(cam_sample.getFarClippingPlane()); - bcam->dof.focus_distance = static_cast<float>(cam_sample.getFocusDistance()); - bcam->dof.aperture_fstop = static_cast<float>(cam_sample.getFStop()); + bcam->clip_start = max_ff(0.1f, float(cam_sample.getNearClippingPlane())); + bcam->clip_end = float(cam_sample.getFarClippingPlane()); + bcam->dof.focus_distance = float(cam_sample.getFocusDistance()); + bcam->dof.aperture_fstop = float(cam_sample.getFStop()); m_object = BKE_object_add_only_object(bmain, OB_CAMERA, m_object_name.c_str()); m_object->data = bcam; diff --git a/source/blender/io/alembic/intern/abc_reader_curves.cc b/source/blender/io/alembic/intern/abc_reader_curves.cc index d8859acdf5f..24bdae3ac50 100644 --- a/source/blender/io/alembic/intern/abc_reader_curves.cc +++ b/source/blender/io/alembic/intern/abc_reader_curves.cc @@ -152,7 +152,7 @@ void AbcCurveReader::read_curve_sample(Curve *cu, break; case Alembic::AbcGeom::kVariableOrder: if (orders && orders->size() > i) { - nu->orderu = static_cast<short>((*orders)[i]); + nu->orderu = short((*orders)[i]); break; } ATTR_FALLTHROUGH; diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index bacc1f06599..f08514dc45c 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -25,7 +25,8 @@ #include "BLI_listbase.h" #include "BLI_math_geom.h" -#include "BKE_attribute.h" +#include "BKE_attribute.hh" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -93,6 +94,7 @@ static void assign_materials(Main *bmain, mat_iter = matname_to_material.find(mat_name); if (mat_iter == matname_to_material.end()) { assigned_mat = BKE_material_add(bmain, mat_name.c_str()); + id_us_min(&assigned_mat->id); matname_to_material[mat_name] = assigned_mat; } else { @@ -101,6 +103,9 @@ static void assign_materials(Main *bmain, BKE_object_material_assign_single_obdata(bmain, ob, assigned_mat, mat_index); } + if (ob->totcol > 0) { + ob->actcol = 1; + } } } /* namespace utils */ @@ -128,10 +133,8 @@ static void read_mverts_interp(MVert *mverts, 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(), static_cast<float>(weight)); + interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), float(weight)); copy_zup_from_yup(mvert.co, tmp); - - mvert.bweight = 0; } } @@ -152,13 +155,12 @@ static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data) void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySamplePtr normals) { + MutableSpan<MVert> verts = mesh.verts_for_write(); for (int i = 0; i < positions->size(); i++) { - MVert &mvert = mesh.mvert[i]; + MVert &mvert = verts[i]; Imath::V3f pos_in = (*positions)[i]; copy_zup_from_yup(mvert.co, pos_in.getValue()); - - mvert.bweight = 0; } if (normals) { float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh); @@ -186,9 +188,9 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) const bool do_uvs = (mloopuvs && uvs && uvs_indices); 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; + uint loop_index = 0; + uint rev_loop_index = 0; + uint uv_index = 0; bool seen_invalid_geometry = false; for (int i = 0; i < face_counts->size(); i++) { @@ -269,7 +271,7 @@ static void process_loop_normals(CDStreamConfig &config, const N3fArraySamplePtr float(*lnors)[3] = static_cast<float(*)[3]>( MEM_malloc_arrayN(loop_count, sizeof(float[3]), "ABC::FaceNormals")); - MPoly *mpoly = mesh->mpoly; + MPoly *mpoly = mesh->polys_for_write().data(); const N3fArraySample &loop_normals = *loop_normals_ptr; int abc_index = 0; for (int i = 0, e = mesh->totpoly; i < e; i++, mpoly++) { @@ -304,7 +306,7 @@ static void process_vertex_normals(CDStreamConfig &config, } config.mesh->flag |= ME_AUTOSMOOTH; - BKE_mesh_set_custom_normals_from_vertices(config.mesh, vnors); + BKE_mesh_set_custom_normals_from_verts(config.mesh, vnors); MEM_freeN(vnors); } @@ -391,7 +393,7 @@ static void *add_customdata_cb(Mesh *mesh, const char *name, int data_type) /* Create a new layer. */ int numloops = mesh->totloop; cd_ptr = CustomData_add_layer_named( - &mesh->ldata, cd_data_type, CD_DEFAULT, nullptr, numloops, name); + &mesh->ldata, cd_data_type, CD_SET_DEFAULT, nullptr, numloops, name); return cd_ptr; } @@ -446,7 +448,7 @@ static void read_velocity(const V3fArraySamplePtr &velocities, const CDStreamConfig &config, const float velocity_scale) { - const int num_velocity_vectors = static_cast<int>(velocities->size()); + const int num_velocity_vectors = 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). */ @@ -514,13 +516,10 @@ static void read_mesh_sample(const std::string &iobject_full_name, CDStreamConfig get_config(Mesh *mesh, const bool use_vertex_interpolation) { CDStreamConfig config; - - BLI_assert(mesh->mvert || mesh->totvert == 0); - config.mesh = mesh; - config.mvert = mesh->mvert; - config.mloop = mesh->mloop; - config.mpoly = mesh->mpoly; + config.mvert = mesh->verts_for_write().data(); + config.mloop = mesh->loops_for_write().data(); + config.mpoly = mesh->polys_for_write().data(); config.totvert = mesh->totvert; config.totloop = mesh->totloop; config.totpoly = mesh->totpoly; @@ -616,11 +615,7 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr); if (read_mesh != mesh) { - /* XXX FIXME: after 2.80; mesh->flag isn't copied by #BKE_mesh_nomain_to_mesh(). */ - /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ - uint16_t autosmooth = (read_mesh->flag & ME_AUTOSMOOTH); - BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true); - mesh->flag |= autosmooth; + BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object); } if (m_settings->validate_meshes) { @@ -766,7 +761,11 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, size_t num_polys = new_mesh->totpoly; if (num_polys > 0) { std::map<std::string, int> mat_map; - assign_facesets_to_mpoly(sample_sel, new_mesh->mpoly, num_polys, mat_map); + bke::MutableAttributeAccessor attributes = new_mesh->attributes_for_write(); + bke::SpanAttributeWriter<int> material_indices = + attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE); + assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map); + material_indices.finish(); } return new_mesh; @@ -775,10 +774,9 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, return existing_mesh; } -void AbcMeshReader::assign_facesets_to_mpoly(const ISampleSelector &sample_sel, - MPoly *mpoly, - int totpoly, - std::map<std::string, int> &r_mat_map) +void AbcMeshReader::assign_facesets_to_material_indices(const ISampleSelector &sample_sel, + MutableSpan<int> material_indices, + std::map<std::string, int> &r_mat_map) { std::vector<std::string> face_sets; m_schema.getFaceSetNames(face_sets); @@ -811,13 +809,12 @@ void AbcMeshReader::assign_facesets_to_mpoly(const ISampleSelector &sample_sel, for (size_t l = 0; l < num_group_faces; l++) { size_t pos = (*group_faces)[l]; - if (pos >= totpoly) { + if (pos >= material_indices.size()) { std::cerr << "Faceset overflow on " << faceset.getName() << '\n'; break; } - MPoly &poly = mpoly[pos]; - poly.mat_nr = assigned_mat - 1; + material_indices[pos] = assigned_mat - 1; } } } @@ -825,7 +822,11 @@ void AbcMeshReader::assign_facesets_to_mpoly(const ISampleSelector &sample_sel, void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const ISampleSelector &sample_sel) { std::map<std::string, int> mat_map; - assign_facesets_to_mpoly(sample_sel, mesh->mpoly, mesh->totpoly, mat_map); + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); + bke::SpanAttributeWriter<int> material_indices = + attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE); + assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map); + material_indices.finish(); utils::assign_materials(bmain, m_object, mat_map); } @@ -890,7 +891,7 @@ static void read_vertex_creases(Mesh *mesh, } float *vertex_crease_data = (float *)CustomData_add_layer( - &mesh->vdata, CD_CREASE, CD_DEFAULT, nullptr, mesh->totvert); + &mesh->vdata, CD_CREASE, CD_SET_DEFAULT, nullptr, mesh->totvert); const int totvert = mesh->totvert; for (int i = 0, v = indices->size(); i < v; ++i) { @@ -902,8 +903,6 @@ static void read_vertex_creases(Mesh *mesh, vertex_crease_data[idx] = (*sharpnesses)[i]; } - - mesh->cd_flag |= ME_CDFLAG_VERT_CREASE; } static void read_edge_creases(Mesh *mesh, @@ -914,12 +913,13 @@ static void read_edge_creases(Mesh *mesh, return; } - MEdge *edges = mesh->medge; - const int totedge = mesh->totedge; + MutableSpan<MEdge> edges = mesh->edges_for_write(); + EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, edges.size()); - EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, mesh->totedge); + float *creases = static_cast<float *>( + CustomData_add_layer(&mesh->edata, CD_CREASE, CD_SET_DEFAULT, nullptr, edges.size())); - for (int i = 0; i < totedge; i++) { + for (const int i : edges.index_range()) { MEdge *edge = &edges[i]; BLI_edgehash_insert(edge_hash, edge->v1, edge->v2, edge); } @@ -940,13 +940,11 @@ static void read_edge_creases(Mesh *mesh, } if (edge) { - edge->crease = unit_float_to_uchar_clamp((*sharpnesses)[s]); + creases[edge - edges.data()] = unit_float_to_uchar_clamp((*sharpnesses)[s]); } } BLI_edgehash_free(edge_hash, nullptr); - - mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; } /* ************************************************************************** */ @@ -996,7 +994,7 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr); if (read_mesh != mesh) { - BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true); + BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object); } ISubDSchema::Sample sample; diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.h b/source/blender/io/alembic/intern/abc_reader_mesh.h index f97525297b7..151f4d82226 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.h +++ b/source/blender/io/alembic/intern/abc_reader_mesh.h @@ -5,6 +5,8 @@ * \ingroup balembic */ +#include "BLI_span.hh" + #include "abc_customdata.h" #include "abc_reader_object.h" @@ -38,10 +40,9 @@ class AbcMeshReader final : public AbcObjectReader { Mesh *mesh, const Alembic::AbcGeom::ISampleSelector &sample_sel); - void assign_facesets_to_mpoly(const Alembic::Abc::ISampleSelector &sample_sel, - MPoly *mpoly, - int totpoly, - std::map<std::string, int> &r_mat_map); + void assign_facesets_to_material_indices(const Alembic::Abc::ISampleSelector &sample_sel, + MutableSpan<int> material_indices, + std::map<std::string, int> &r_mat_map); }; class AbcSubDReader final : public AbcObjectReader { diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc index db056c0eef6..af26565f8d6 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.cc +++ b/source/blender/io/alembic/intern/abc_reader_object.cc @@ -110,7 +110,7 @@ static Imath::M44d blend_matrices(const Imath::M44d &m0, convert_matrix_datatype(m0, mat0); convert_matrix_datatype(m1, mat1); - interp_m4_m4m4(ret, mat0, mat1, static_cast<float>(weight)); + interp_m4_m4m4(ret, mat0, mat1, float(weight)); return convert_matrix_datatype(ret); } @@ -133,11 +133,11 @@ Imath::M44d get_matrix(const IXformSchema &schema, const chrono_t time) } struct Mesh *AbcObjectReader::read_mesh(struct Mesh *existing_mesh, - const Alembic::Abc::ISampleSelector &UNUSED(sample_sel), - int UNUSED(read_flag), - const char *UNUSED(velocity_name), - const float UNUSED(velocity_scale), - const char **UNUSED(err_str)) + const Alembic::Abc::ISampleSelector & /*sample_sel*/, + int /*read_flag*/, + const char * /*velocity_name*/, + const float /*velocity_scale*/, + const char ** /*err_str*/) { return existing_mesh; } diff --git a/source/blender/io/alembic/intern/abc_reader_points.cc b/source/blender/io/alembic/intern/abc_reader_points.cc index ff189bc92dc..54ae71ad7a6 100644 --- a/source/blender/io/alembic/intern/abc_reader_points.cc +++ b/source/blender/io/alembic/intern/abc_reader_points.cc @@ -69,7 +69,7 @@ void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSel Mesh *read_mesh = this->read_mesh(mesh, sample_sel, 0, "", 0.0f, nullptr); if (read_mesh != mesh) { - BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object); } if (m_settings->validate_meshes) { diff --git a/source/blender/io/alembic/intern/abc_reader_transform.cc b/source/blender/io/alembic/intern/abc_reader_transform.cc index 0d3227fc718..71682531378 100644 --- a/source/blender/io/alembic/intern/abc_reader_transform.cc +++ b/source/blender/io/alembic/intern/abc_reader_transform.cc @@ -55,7 +55,7 @@ bool AbcEmptyReader::accepts_object_type( return true; } -void AbcEmptyReader::readObjectData(Main *bmain, const ISampleSelector &UNUSED(sample_sel)) +void AbcEmptyReader::readObjectData(Main *bmain, const ISampleSelector & /*sample_sel*/) { m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str()); m_object->data = nullptr; diff --git a/source/blender/io/alembic/intern/abc_util.cc b/source/blender/io/alembic/intern/abc_util.cc index 90f73d25c22..846a3622d62 100644 --- a/source/blender/io/alembic/intern/abc_util.cc +++ b/source/blender/io/alembic/intern/abc_util.cc @@ -73,7 +73,7 @@ Imath::M44d convert_matrix_datatype(float mat[4][4]) for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - m[i][j] = static_cast<double>(mat[i][j]); + m[i][j] = double(mat[i][j]); } } @@ -84,7 +84,7 @@ void convert_matrix_datatype(const Imath::M44d &xform, float r_mat[4][4]) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - r_mat[i][j] = static_cast<float>(xform[i][j]); + r_mat[i][j] = float(xform[i][j]); } } } diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc index 86622719f6e..39595089109 100644 --- a/source/blender/io/alembic/intern/alembic_capi.cc +++ b/source/blender/io/alembic/intern/alembic_capi.cc @@ -502,7 +502,7 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa /* Create objects and set scene frame range. */ - const float size = static_cast<float>(data->readers.size()); + const float size = float(data->readers.size()); size_t i = 0; chrono_t min_time = std::numeric_limits<chrono_t>::max(); @@ -542,8 +542,8 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa scene->r.cfra = scene->r.sfra; } else if (min_time < max_time) { - scene->r.sfra = static_cast<int>(round(min_time * FPS)); - scene->r.efra = static_cast<int>(round(max_time * FPS)); + scene->r.sfra = int(round(min_time * FPS)); + scene->r.efra = int(round(max_time * FPS)); scene->r.cfra = scene->r.sfra; } } @@ -601,9 +601,10 @@ static void import_endjob(void *user_data) else { Base *base; LayerCollection *lc; + const Scene *scene = data->scene; ViewLayer *view_layer = data->view_layer; - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); lc = BKE_layer_collection_get_active(view_layer); @@ -616,6 +617,7 @@ static void import_endjob(void *user_data) /* Sync the collection, and do view layer operations. */ BKE_layer_collection_resync_allow(); BKE_main_collection_sync(data->bmain); + BKE_view_layer_synced_ensure(scene, view_layer); for (AbcObjectReader *reader : data->readers) { Object *ob = reader->object(); base = BKE_view_layer_base_find(view_layer, ob); diff --git a/source/blender/io/avi/intern/avi.c b/source/blender/io/avi/intern/avi.c index 8bf4f8124a3..298aa9c8dfa 100644 --- a/source/blender/io/avi/intern/avi.c +++ b/source/blender/io/avi/intern/avi.c @@ -38,14 +38,14 @@ static char DEBUG_FCC[4]; (void)0 /* local functions */ -char *fcc_to_char(unsigned int fcc); -char *tcc_to_char(unsigned int tcc); +char *fcc_to_char(uint fcc); +char *tcc_to_char(uint tcc); /* implementation */ -unsigned int GET_FCC(FILE *fp) +uint GET_FCC(FILE *fp) { - unsigned char tmp[4]; + uchar tmp[4]; tmp[0] = getc(fp); tmp[1] = getc(fp); @@ -55,7 +55,7 @@ unsigned int GET_FCC(FILE *fp) return FCC(tmp); } -unsigned int GET_TCC(FILE *fp) +uint GET_TCC(FILE *fp) { char tmp[5]; @@ -67,7 +67,7 @@ unsigned int GET_TCC(FILE *fp) return FCC(tmp); } -char *fcc_to_char(unsigned int fcc) +char *fcc_to_char(uint fcc) { DEBUG_FCC[0] = (fcc)&127; DEBUG_FCC[1] = (fcc >> 8) & 127; @@ -77,7 +77,7 @@ char *fcc_to_char(unsigned int fcc) return DEBUG_FCC; } -char *tcc_to_char(unsigned int tcc) +char *tcc_to_char(uint tcc) { DEBUG_FCC[0] = (tcc)&127; DEBUG_FCC[1] = (tcc >> 8) & 127; @@ -917,7 +917,7 @@ AviError AVI_write_frame(AviMovie *movie, int frame_num, ...) va_start(ap, frame_num); for (stream = 0; stream < movie->header->Streams; stream++) { - unsigned int tbuf = 0; + uint tbuf = 0; format = va_arg(ap, AviFormat); buffer = va_arg(ap, void *); diff --git a/source/blender/io/avi/intern/avi_mjpeg.c b/source/blender/io/avi/intern/avi_mjpeg.c index fb42274fef2..de75fe8d69e 100644 --- a/source/blender/io/avi/intern/avi_mjpeg.c +++ b/source/blender/io/avi/intern/avi_mjpeg.c @@ -22,10 +22,8 @@ #include "avi_mjpeg.h" -static void jpegmemdestmgr_build(j_compress_ptr cinfo, unsigned char *buffer, size_t bufsize); -static void jpegmemsrcmgr_build(j_decompress_ptr dinfo, - const unsigned char *buffer, - size_t bufsize); +static void jpegmemdestmgr_build(j_compress_ptr cinfo, uchar *buffer, size_t bufsize); +static void jpegmemsrcmgr_build(j_decompress_ptr dinfo, const uchar *buffer, size_t bufsize); static size_t numbytes; @@ -215,11 +213,7 @@ static void std_huff_tables(j_decompress_ptr dinfo) sizeof(val_ac_chrominance)); } -static int Decode_JPEG(unsigned char *inBuffer, - unsigned char *outBuffer, - unsigned int width, - unsigned int height, - size_t bufsize) +static int Decode_JPEG(uchar *inBuffer, uchar *outBuffer, uint width, uint height, size_t bufsize) { struct jpeg_decompress_struct dinfo; struct jpeg_error_mgr jerr; @@ -272,16 +266,12 @@ static int Decode_JPEG(unsigned char *inBuffer, return 1; } -static void Compress_JPEG(int quality, - unsigned char *outbuffer, - const unsigned char *inBuffer, - int width, - int height, - size_t bufsize) +static void Compress_JPEG( + int quality, uchar *outbuffer, const uchar *inBuffer, int width, int height, size_t bufsize) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; - unsigned char marker[60]; + uchar marker[60]; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); @@ -339,7 +329,7 @@ static void Compress_JPEG(int quality, jpeg_destroy_compress(&cinfo); } -static void interlace(unsigned char *to, unsigned char *from, int width, int height) +static void interlace(uchar *to, uchar *from, int width, int height) { size_t i, rowstride = width * 3; @@ -353,7 +343,7 @@ static void interlace(unsigned char *to, unsigned char *from, int width, int hei } } -static void deinterlace(int odd, unsigned char *to, unsigned char *from, int width, int height) +static void deinterlace(int odd, uchar *to, uchar *from, int width, int height) { size_t i, rowstride = width * 3; @@ -367,20 +357,17 @@ static void deinterlace(int odd, unsigned char *to, unsigned char *from, int wid } } -void *avi_converter_from_mjpeg(AviMovie *movie, - int stream, - unsigned char *buffer, - const size_t *size) +void *avi_converter_from_mjpeg(AviMovie *movie, int stream, uchar *buffer, const size_t *size) { int deint; - unsigned char *buf; + uchar *buf; (void)stream; /* unused */ buf = imb_alloc_pixels(movie->header->Height, movie->header->Width, 3, - sizeof(unsigned char), + sizeof(uchar), "avi.avi_converter_from_mjpeg 1"); if (!buf) { return NULL; @@ -394,7 +381,7 @@ void *avi_converter_from_mjpeg(AviMovie *movie, buffer = imb_alloc_pixels(movie->header->Height, movie->header->Width, 3, - sizeof(unsigned char), + sizeof(uchar), "avi.avi_converter_from_mjpeg 2"); if (buffer) { interlace(buffer, buf, movie->header->Width, movie->header->Height); @@ -407,9 +394,9 @@ void *avi_converter_from_mjpeg(AviMovie *movie, return buf; } -void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer, size_t *size) +void *avi_converter_to_mjpeg(AviMovie *movie, int stream, uchar *buffer, size_t *size) { - unsigned char *buf; + uchar *buf; size_t bufsize = *size; numbytes = 0; @@ -418,7 +405,7 @@ void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer, buf = imb_alloc_pixels(movie->header->Height, movie->header->Width, 3, - sizeof(unsigned char), + sizeof(uchar), "avi.avi_converter_to_mjpeg 1"); if (!buf) { return NULL; @@ -441,7 +428,7 @@ void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer, buf = imb_alloc_pixels(movie->header->Height, movie->header->Width, 3, - sizeof(unsigned char), + sizeof(uchar), "avi.avi_converter_to_mjpeg 1"); if (buf) { @@ -488,7 +475,7 @@ static void jpegmemdestmgr_term_destination(j_compress_ptr cinfo) MEM_freeN(cinfo->dest); } -static void jpegmemdestmgr_build(j_compress_ptr cinfo, unsigned char *buffer, size_t bufsize) +static void jpegmemdestmgr_build(j_compress_ptr cinfo, uchar *buffer, size_t bufsize) { cinfo->dest = MEM_mallocN(sizeof(*(cinfo->dest)), "avi.jpegmemdestmgr_build"); @@ -511,7 +498,7 @@ static void jpegmemsrcmgr_init_source(j_decompress_ptr dinfo) static boolean jpegmemsrcmgr_fill_input_buffer(j_decompress_ptr dinfo) { - unsigned char *buf = (unsigned char *)dinfo->src->next_input_byte - 2; + uchar *buf = (uchar *)dinfo->src->next_input_byte - 2; /* if we get called, must have run out of data */ WARNMS(dinfo, JWRN_JPEG_EOF); @@ -542,9 +529,7 @@ static void jpegmemsrcmgr_term_source(j_decompress_ptr dinfo) MEM_freeN(dinfo->src); } -static void jpegmemsrcmgr_build(j_decompress_ptr dinfo, - const unsigned char *buffer, - size_t bufsize) +static void jpegmemsrcmgr_build(j_decompress_ptr dinfo, const uchar *buffer, size_t bufsize) { dinfo->src = MEM_mallocN(sizeof(*(dinfo->src)), "avi.jpegmemsrcmgr_build"); diff --git a/source/blender/io/avi/intern/avi_mjpeg.h b/source/blender/io/avi/intern/avi_mjpeg.h index 79fa0fe9995..aa74d771646 100644 --- a/source/blender/io/avi/intern/avi_mjpeg.h +++ b/source/blender/io/avi/intern/avi_mjpeg.h @@ -7,8 +7,5 @@ #pragma once -void *avi_converter_from_mjpeg(AviMovie *movie, - int stream, - unsigned char *buffer, - const size_t *size); -void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer, size_t *size); +void *avi_converter_from_mjpeg(AviMovie *movie, int stream, uchar *buffer, const size_t *size); +void *avi_converter_to_mjpeg(AviMovie *movie, int stream, uchar *buffer, size_t *size); diff --git a/source/blender/io/avi/intern/avi_rgb.c b/source/blender/io/avi/intern/avi_rgb.c index ffc3d0477fa..71022361df1 100644 --- a/source/blender/io/avi/intern/avi_rgb.c +++ b/source/blender/io/avi/intern/avi_rgb.c @@ -21,12 +21,9 @@ /* implementation */ -void *avi_converter_from_avi_rgb(AviMovie *movie, - int stream, - unsigned char *buffer, - const size_t *size) +void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, uchar *buffer, const size_t *size) { - unsigned char *buf; + uchar *buf; AviBitmapInfoHeader *bi; short bits = 32; @@ -38,24 +35,24 @@ void *avi_converter_from_avi_rgb(AviMovie *movie, } if (bits == 16) { - unsigned short *pxl; - unsigned char *to; + ushort *pxl; + uchar *to; #ifdef __BIG_ENDIAN__ - unsigned char *pxla; + uchar *pxla; #endif buf = imb_alloc_pixels( - movie->header->Height, movie->header->Width, 3, sizeof(unsigned char), "fromavirgbbuf"); + movie->header->Height, movie->header->Width, 3, sizeof(uchar), "fromavirgbbuf"); if (buf) { size_t y = movie->header->Height; to = buf; while (y--) { - pxl = (unsigned short *)(buffer + y * movie->header->Width * 2); + pxl = (ushort *)(buffer + y * movie->header->Width * 2); #ifdef __BIG_ENDIAN__ - pxla = (unsigned char *)pxl; + pxla = (uchar *)pxl; #endif size_t x = movie->header->Width; @@ -82,7 +79,7 @@ void *avi_converter_from_avi_rgb(AviMovie *movie, } buf = imb_alloc_pixels( - movie->header->Height, movie->header->Width, 3, sizeof(unsigned char), "fromavirgbbuf"); + movie->header->Height, movie->header->Width, 3, sizeof(uchar), "fromavirgbbuf"); if (buf) { size_t rowstride = movie->header->Width * 3; @@ -110,9 +107,9 @@ void *avi_converter_from_avi_rgb(AviMovie *movie, return buf; } -void *avi_converter_to_avi_rgb(AviMovie *movie, int stream, unsigned char *buffer, size_t *size) +void *avi_converter_to_avi_rgb(AviMovie *movie, int stream, uchar *buffer, size_t *size) { - unsigned char *buf; + uchar *buf; (void)stream; /* unused */ diff --git a/source/blender/io/avi/intern/avi_rgb32.c b/source/blender/io/avi/intern/avi_rgb32.c index 84ae023fcdd..fcb83ffe47d 100644 --- a/source/blender/io/avi/intern/avi_rgb32.c +++ b/source/blender/io/avi/intern/avi_rgb32.c @@ -17,15 +17,15 @@ #include "AVI_avi.h" #include "avi_rgb32.h" -void *avi_converter_from_rgb32(AviMovie *movie, int stream, unsigned char *buffer, size_t *size) +void *avi_converter_from_rgb32(AviMovie *movie, int stream, uchar *buffer, size_t *size) { - unsigned char *buf; + uchar *buf; (void)stream; /* unused */ *size = (size_t)movie->header->Height * (size_t)movie->header->Width * 3; buf = imb_alloc_pixels( - movie->header->Height, movie->header->Width, 3, sizeof(unsigned char), "fromrgb32buf"); + movie->header->Height, movie->header->Width, 3, sizeof(uchar), "fromrgb32buf"); if (!buf) { return NULL; } @@ -46,16 +46,16 @@ void *avi_converter_from_rgb32(AviMovie *movie, int stream, unsigned char *buffe return buf; } -void *avi_converter_to_rgb32(AviMovie *movie, int stream, unsigned char *buffer, size_t *size) +void *avi_converter_to_rgb32(AviMovie *movie, int stream, uchar *buffer, size_t *size) { - unsigned char *buf; - unsigned char *to, *from; + uchar *buf; + uchar *to, *from; (void)stream; /* unused */ *size = (size_t)movie->header->Height * (size_t)movie->header->Width * 4; buf = imb_alloc_pixels( - movie->header->Height, movie->header->Width, 4, sizeof(unsigned char), "torgb32buf"); + movie->header->Height, movie->header->Width, 4, sizeof(uchar), "torgb32buf"); if (!buf) { return NULL; } diff --git a/source/blender/io/collada/AnimationExporter.cpp b/source/blender/io/collada/AnimationExporter.cpp index 7df9df1f460..85e8ccf9f2a 100644 --- a/source/blender/io/collada/AnimationExporter.cpp +++ b/source/blender/io/collada/AnimationExporter.cpp @@ -687,7 +687,7 @@ std::string AnimationExporter::collada_interpolation_source(const BCAnimationCur std::vector<float> frames; curve.get_frames(frames); - for (unsigned int i = 0; i < curve.sample_count(); i++) { + for (uint i = 0; i < curve.sample_count(); i++) { float frame = frames[i]; int ipo = curve.get_interpolation_type(frame); if (ipo == BEZT_IPO_BEZ) { diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index cc91c3eeac9..2d872377bbf 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -55,7 +55,7 @@ void AnimationImporter::add_bezt(FCurve *fcu, float value, eBezTriple_Interpolation ipo) { - // float fps = (float)FPS; + // float fps = float(FPS); BezTriple bez; memset(&bez, 0, sizeof(BezTriple)); bez.vec[1][0] = frame; @@ -72,9 +72,9 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) COLLADAFW::FloatOrDoubleArray &input = curve->getInputValues(); COLLADAFW::FloatOrDoubleArray &output = curve->getOutputValues(); - float fps = (float)FPS; + float fps = float(FPS); size_t dim = curve->getOutDimension(); - unsigned int i; + uint i; std::vector<FCurve *> &fcurves = curve_map[curve->getUniqueId()]; @@ -91,7 +91,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) fcu->array_index = 0; fcu->auto_smoothing = U.auto_smoothing_new; - for (unsigned int j = 0; j < curve->getKeyCount(); j++) { + for (uint j = 0; j < curve->getKeyCount(); j++) { BezTriple bez; memset(&bez, 0, sizeof(BezTriple)); @@ -106,7 +106,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) COLLADAFW::FloatOrDoubleArray &outtan = curve->getOutTangentValues(); /* In-tangent. */ - unsigned int index = 2 * (j * dim + i); + uint index = 2 * (j * dim + i); bez.vec[0][0] = bc_get_float_value(intan, index) * fps; bez.vec[0][1] = bc_get_float_value(intan, index + 1); @@ -141,14 +141,14 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) default: fprintf(stderr, "Output dimension of %d is not yet supported (animation id = %s)\n", - (int)dim, + int(dim), curve->getOriginalId().c_str()); } } void AnimationImporter::fcurve_deg_to_rad(FCurve *cu) { - for (unsigned int i = 0; i < cu->totvert; i++) { + for (uint i = 0; i < cu->totvert; i++) { /* TODO: convert handles too. */ cu->bezt[i].vec[1][1] *= DEG2RADF(1.0f); cu->bezt[i].vec[0][1] *= DEG2RADF(1.0f); @@ -158,7 +158,7 @@ void AnimationImporter::fcurve_deg_to_rad(FCurve *cu) void AnimationImporter::fcurve_scale(FCurve *cu, int scale) { - for (unsigned int i = 0; i < cu->totvert; i++) { + for (uint i = 0; i < cu->totvert; i++) { /* TODO: convert handles too. */ cu->bezt[i].vec[1][1] *= scale; cu->bezt[i].vec[0][1] *= scale; @@ -262,7 +262,7 @@ AnimationImporter::~AnimationImporter() } if (!unused_curves.empty()) { - fprintf(stderr, "removed %d unused curves\n", (int)unused_curves.size()); + fprintf(stderr, "removed %d unused curves\n", int(unused_curves.size())); } } @@ -484,7 +484,7 @@ void AnimationImporter::find_frames(std::vector<float> *frames, std::vector<FCur for (iter = curves->begin(); iter != curves->end(); iter++) { FCurve *fcu = *iter; - for (unsigned int k = 0; k < fcu->totvert; k++) { + for (uint k = 0; k < fcu->totvert; k++) { /* get frame value from bezTriple */ float fra = fcu->bezt[k].vec[1][0]; /* if frame already not added add frame to frames */ @@ -525,12 +525,12 @@ void AnimationImporter::Assign_transform_animations( bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; /* to check if the no of curves are valid */ - bool xyz = ((tm_type == COLLADAFW::Transformation::TRANSLATE || - tm_type == COLLADAFW::Transformation::SCALE) && - binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ); + bool xyz = + (ELEM(tm_type, COLLADAFW::Transformation::TRANSLATE, COLLADAFW::Transformation::SCALE) && + binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ); if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) { - fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves->size()); + fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, int(curves->size())); return; } @@ -649,7 +649,7 @@ void AnimationImporter::Assign_color_animations(const COLLADAFW::UniqueId &listi const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings(); /* all the curves belonging to the current binding */ std::vector<FCurve *> animcurves; - for (unsigned int j = 0; j < bindings.getCount(); j++) { + for (uint j = 0; j < bindings.getCount(); j++) { animcurves = curve_map[bindings[j].animation]; switch (bindings[j].animationClass) { @@ -699,7 +699,7 @@ void AnimationImporter::Assign_float_animations(const COLLADAFW::UniqueId &listi const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings(); /* all the curves belonging to the current binding */ std::vector<FCurve *> animcurves; - for (unsigned int j = 0; j < bindings.getCount(); j++) { + for (uint j = 0; j < bindings.getCount(); j++) { animcurves = curve_map[bindings[j].animation]; BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); @@ -756,7 +756,7 @@ void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId &listid const COLLADAFW::AnimationList::AnimationBindings &bindings = animlist->getAnimationBindings(); /* all the curves belonging to the current binding */ std::vector<FCurve *> animcurves; - for (unsigned int j = 0; j < bindings.getCount(); j++) { + for (uint j = 0; j < bindings.getCount(); j++) { animcurves = curve_map[bindings[j].animation]; BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); @@ -767,7 +767,7 @@ void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId &listid for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { FCurve *fcu = *iter; - for (unsigned int i = 0; i < fcu->totvert; i++) { + for (uint i = 0; i < fcu->totvert; i++) { fcu->bezt[i].vec[0][1] = convert_to_focal_length( fcu->bezt[i].vec[0][1], fov_type, aspect, cam->sensor_x); fcu->bezt[i].vec[1][1] = convert_to_focal_length( @@ -817,7 +817,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob, } /* new curves to assign matrix transform animation */ FCurve *newcu[10]; /* if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale */ - unsigned int totcu = 10; + uint totcu = 10; const char *tm_str = nullptr; char rna_path[200]; for (int i = 0; i < totcu; i++) { @@ -1033,7 +1033,7 @@ void AnimationImporter::translate_Animations( const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations(); /* for each transformation in node */ - for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) { + for (uint i = 0; i < nodeTransforms.getCount(); i++) { COLLADAFW::Transformation *transform = nodeTransforms[i]; COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType(); @@ -1053,7 +1053,7 @@ void AnimationImporter::translate_Animations( animlist->getAnimationBindings(); /* all the curves belonging to the current binding */ std::vector<FCurve *> animcurves; - for (unsigned int j = 0; j < bindings.getCount(); j++) { + for (uint j = 0; j < bindings.getCount(); j++) { animcurves = curve_map[bindings[j].animation]; if (is_matrix) { apply_matrix_curves(ob, animcurves, root, node, transform); @@ -1092,7 +1092,7 @@ void AnimationImporter::translate_Animations( ListBase *AnimCurves = &(act->curves); const COLLADAFW::InstanceLightPointerArray &nodeLights = node->getInstanceLights(); - for (unsigned int i = 0; i < nodeLights.getCount(); i++) { + for (uint i = 0; i < nodeLights.getCount(); i++) { const COLLADAFW::Light *light = (COLLADAFW::Light *) FW_object_map[nodeLights[i]->getInstanciatedObjectId()]; @@ -1130,7 +1130,7 @@ void AnimationImporter::translate_Animations( ListBase *AnimCurves = &(act->curves); const COLLADAFW::InstanceCameraPointerArray &nodeCameras = node->getInstanceCameras(); - for (unsigned int i = 0; i < nodeCameras.getCount(); i++) { + for (uint i = 0; i < nodeCameras.getCount(); i++) { const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) FW_object_map[nodeCameras[i]->getInstanciatedObjectId()]; @@ -1184,9 +1184,9 @@ void AnimationImporter::translate_Animations( } const COLLADAFW::InstanceGeometryPointerArray &nodeGeoms = node->getInstanceGeometries(); - for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) { + for (uint i = 0; i < nodeGeoms.getCount(); i++) { const COLLADAFW::MaterialBindingArray &matBinds = nodeGeoms[i]->getMaterialBindings(); - for (unsigned int j = 0; j < matBinds.getCount(); j++) { + for (uint j = 0; j < matBinds.getCount(); j++) { const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial(); const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]); if (ef != nullptr) { /* can be NULL T28909. */ @@ -1273,7 +1273,7 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, /* new curves to assign matrix transform animation */ FCurve *newcu[10]; /* if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale. */ - unsigned int totcu = 10; + uint totcu = 10; const char *tm_str = nullptr; char rna_path[200]; for (int i = 0; i < totcu; i++) { @@ -1381,7 +1381,7 @@ AnimationImporter::AnimMix *AnimationImporter::get_animation_type( const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations(); /* for each transformation in node */ - for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) { + for (uint i = 0; i < nodeTransforms.getCount(); i++) { COLLADAFW::Transformation *transform = nodeTransforms[i]; const COLLADAFW::UniqueId &listid = transform->getAnimationList(); @@ -1395,7 +1395,7 @@ AnimationImporter::AnimMix *AnimationImporter::get_animation_type( } const COLLADAFW::InstanceLightPointerArray &nodeLights = node->getInstanceLights(); - for (unsigned int i = 0; i < nodeLights.getCount(); i++) { + for (uint i = 0; i < nodeLights.getCount(); i++) { const COLLADAFW::Light *light = (COLLADAFW::Light *) FW_object_map[nodeLights[i]->getInstanciatedObjectId()]; types->light = setAnimType(&(light->getColor()), (types->light), LIGHT_COLOR); @@ -1408,7 +1408,7 @@ AnimationImporter::AnimMix *AnimationImporter::get_animation_type( } const COLLADAFW::InstanceCameraPointerArray &nodeCameras = node->getInstanceCameras(); - for (unsigned int i = 0; i < nodeCameras.getCount(); i++) { + for (uint i = 0; i < nodeCameras.getCount(); i++) { const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) FW_object_map[nodeCameras[i]->getInstanciatedObjectId()]; if (camera == nullptr) { @@ -1440,9 +1440,9 @@ AnimationImporter::AnimMix *AnimationImporter::get_animation_type( } const COLLADAFW::InstanceGeometryPointerArray &nodeGeoms = node->getInstanceGeometries(); - for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) { + for (uint i = 0; i < nodeGeoms.getCount(); i++) { const COLLADAFW::MaterialBindingArray &matBinds = nodeGeoms[i]->getMaterialBindings(); - for (unsigned int j = 0; j < matBinds.getCount(); j++) { + for (uint j = 0; j < matBinds.getCount(); j++) { const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial(); const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]); if (ef != nullptr) { /* can be NULL T28909. */ @@ -1490,7 +1490,7 @@ void AnimationImporter::find_frames_old(std::vector<float> *frames, /* for each <rotate>, <translate>, etc. there is a separate Transformation */ const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations(); - unsigned int i; + uint i; /* find frames at which to sample plus convert all rotation keys to radians */ for (i = 0; i < nodeTransforms.getCount(); i++) { COLLADAFW::Transformation *transform = nodeTransforms[i]; @@ -1508,10 +1508,11 @@ void AnimationImporter::find_frames_old(std::vector<float> *frames, if (bindings.getCount()) { /* for each AnimationBinding get the fcurves which animate the transform */ - for (unsigned int j = 0; j < bindings.getCount(); j++) { + for (uint j = 0; j < bindings.getCount(); j++) { std::vector<FCurve *> &curves = curve_map[bindings[j].animation]; - bool xyz = ((nodeTmType == COLLADAFW::Transformation::TRANSLATE || - nodeTmType == COLLADAFW::Transformation::SCALE) && + bool xyz = (ELEM(nodeTmType, + COLLADAFW::Transformation::TRANSLATE, + COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ); if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) { @@ -1525,7 +1526,7 @@ void AnimationImporter::find_frames_old(std::vector<float> *frames, fcurve_deg_to_rad(fcu); } - for (unsigned int k = 0; k < fcu->totvert; k++) { + for (uint k = 0; k < fcu->totvert; k++) { /* get frame value from bezTriple */ float fra = fcu->bezt[k].vec[1][0]; /* if frame already not added add frame to frames */ @@ -1536,7 +1537,7 @@ void AnimationImporter::find_frames_old(std::vector<float> *frames, } } else { - fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves.size()); + fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, int(curves.size())); } } } @@ -1573,7 +1574,7 @@ Object *AnimationImporter::translate_animation_OLD( find_frames_old(&frames, node, tm_type); - unsigned int i; + uint i; float irest_dae[4][4]; float rest[4][4], irest[4][4]; @@ -1632,7 +1633,7 @@ Object *AnimationImporter::translate_animation_OLD( /* new curves */ FCurve *newcu[10]; /* if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale */ - unsigned int totcu = is_matrix ? 10 : (is_rotation ? 4 : 3); + uint totcu = is_matrix ? 10 : (is_rotation ? 4 : 3); for (i = 0; i < totcu; i++) { @@ -1825,7 +1826,7 @@ void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], unit_m4(mat); - for (unsigned int i = 0; i < tms.getCount(); i++) { + for (uint i = 0; i < tms.getCount(); i++) { COLLADAFW::Transformation *tm = tms[i]; COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); float m[4][4]; @@ -1883,8 +1884,11 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, const COLLADAFW::UniqueId &listid = tm->getAnimationList(); COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); - if (type != COLLADAFW::Transformation::ROTATE && type != COLLADAFW::Transformation::SCALE && - type != COLLADAFW::Transformation::TRANSLATE && type != COLLADAFW::Transformation::MATRIX) { + if (!ELEM(type, + COLLADAFW::Transformation::ROTATE, + COLLADAFW::Transformation::SCALE, + COLLADAFW::Transformation::TRANSLATE, + COLLADAFW::Transformation::MATRIX)) { fprintf(stderr, "animation of transformation %d is not supported yet\n", type); return false; } @@ -1909,7 +1913,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, dae_translate_to_v3(tm, vec); } - for (unsigned int index = 0; index < bindings.getCount(); index++) { + for (uint index = 0; index < bindings.getCount(); index++) { const COLLADAFW::AnimationList::AnimationBinding &binding = bindings[index]; std::vector<FCurve *> &curves = curve_map[binding.animation]; COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass; @@ -1934,7 +1938,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, if (type == COLLADAFW::Transformation::ROTATE) { if (curves.size() != 1) { - fprintf(stderr, "expected 1 curve, got %d\n", (int)curves.size()); + fprintf(stderr, "expected 1 curve, got %d\n", int(curves.size())); return false; } @@ -1946,7 +1950,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, COLLADABU::Math::Vector3 &axis = ((COLLADAFW::Rotate *)tm)->getRotationAxis(); - float ax[3] = {(float)axis[0], (float)axis[1], (float)axis[2]}; + float ax[3] = {float(axis[0]), float(axis[1]), float(axis[2])}; float angle = evaluate_fcurve(curves[0], fra); axis_angle_to_mat4(mat, ax, angle); @@ -1957,10 +1961,10 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) { if (is_xyz) { - fprintf(stderr, "%s: expected 3 curves, got %d\n", path, (int)curves.size()); + fprintf(stderr, "%s: expected 3 curves, got %d\n", path, int(curves.size())); } else { - fprintf(stderr, "%s: expected 1 curve, got %d\n", path, (int)curves.size()); + fprintf(stderr, "%s: expected 1 curve, got %d\n", path, int(curves.size())); } return false; } @@ -1989,7 +1993,7 @@ bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, /* for now, of matrix animation, * support only the case when all values are packed into one animation */ if (curves.size() != 16) { - fprintf(stderr, "%s: expected 16 curves, got %d\n", path, (int)curves.size()); + fprintf(stderr, "%s: expected 16 curves, got %d\n", path, int(curves.size())); return false; } @@ -2062,7 +2066,7 @@ bool AnimationImporter::calc_joint_parent_mat_rest(float mat[4][4], } COLLADAFW::NodePointerArray &children = node->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { + for (uint i = 0; i < children.getCount(); i++) { if (calc_joint_parent_mat_rest(mat, m, children[i], end)) { return true; } diff --git a/source/blender/io/collada/ArmatureExporter.cpp b/source/blender/io/collada/ArmatureExporter.cpp index 87dd2fbd816..3cc98917116 100644 --- a/source/blender/io/collada/ArmatureExporter.cpp +++ b/source/blender/io/collada/ArmatureExporter.cpp @@ -76,7 +76,7 @@ bool ArmatureExporter::add_instance_controller(Object *ob) ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); Mesh *me = (Mesh *)ob->data; - if (!me->dvert) { + if (BKE_mesh_deform_verts(me) == nullptr) { return false; } diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp index f056488fe93..1310337f501 100644 --- a/source/blender/io/collada/ArmatureImporter.cpp +++ b/source/blender/io/collada/ArmatureImporter.cpp @@ -190,7 +190,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::NodePointerArray &children = node->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { + for (uint i = 0; i < children.getCount(); i++) { int cl = create_bone(skin, children[i], bone, children.getCount(), mat, arm, layer_labels); if (cl > chain_length) { chain_length = cl; @@ -719,7 +719,7 @@ void ArmatureImporter::set_pose(Object *ob_arm, #endif COLLADAFW::NodePointerArray &children = root_node->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { + for (uint i = 0; i < children.getCount(); i++) { set_pose(ob_arm, children[i], bone_name, mat); } } @@ -727,7 +727,7 @@ void ArmatureImporter::set_pose(Object *ob_arm, bool ArmatureImporter::node_is_decomposed(const COLLADAFW::Node *node) { const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations(); - for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) { + for (uint i = 0; i < nodeTransforms.getCount(); i++) { COLLADAFW::Transformation *transform = nodeTransforms[i]; COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType(); if (tm_type == COLLADAFW::Transformation::MATRIX) { @@ -879,7 +879,7 @@ bool ArmatureImporter::write_skin_controller_data(const COLLADAFW::SkinControlle /* store join inv bind matrix to use it later in armature construction */ const COLLADAFW::Matrix4Array &inv_bind_mats = data->getInverseBindMatrices(); - for (unsigned int i = 0; i < data->getJointsCount(); i++) { + for (uint i = 0; i < data->getJointsCount(); i++) { skin.add_joint(inv_bind_mats[i]); } diff --git a/source/blender/io/collada/BCAnimationCurve.cpp b/source/blender/io/collada/BCAnimationCurve.cpp index fe90dc5d5fa..ac7fa81883a 100644 --- a/source/blender/io/collada/BCAnimationCurve.cpp +++ b/source/blender/io/collada/BCAnimationCurve.cpp @@ -329,8 +329,7 @@ bool BCAnimationCurve::is_transform_curve() const bool BCAnimationCurve::is_rotation_curve() const { std::string channel_type = this->get_channel_type(); - return (channel_type == "rotation" || channel_type == "rotation_euler" || - channel_type == "rotation_quaternion"); + return ELEM(channel_type, "rotation", "rotation_euler", "rotation_quaternion"); } float BCAnimationCurve::get_value(const float frame) @@ -426,10 +425,10 @@ bool BCAnimationCurve::add_value_from_rna(const int frame_index) if ((array_index >= 0) && (array_index < RNA_property_array_length(&ptr, prop))) { switch (RNA_property_type(prop)) { case PROP_BOOLEAN: - value = (float)RNA_property_boolean_get_index(&ptr, prop, array_index); + value = float(RNA_property_boolean_get_index(&ptr, prop, array_index)); break; case PROP_INT: - value = (float)RNA_property_int_get_index(&ptr, prop, array_index); + value = float(RNA_property_int_get_index(&ptr, prop, array_index)); break; case PROP_FLOAT: value = RNA_property_float_get_index(&ptr, prop, array_index); @@ -449,16 +448,16 @@ bool BCAnimationCurve::add_value_from_rna(const int frame_index) /* not an array */ switch (RNA_property_type(prop)) { case PROP_BOOLEAN: - value = (float)RNA_property_boolean_get(&ptr, prop); + value = float(RNA_property_boolean_get(&ptr, prop)); break; case PROP_INT: - value = (float)RNA_property_int_get(&ptr, prop); + value = float(RNA_property_int_get(&ptr, prop)); break; case PROP_FLOAT: value = RNA_property_float_get(&ptr, prop); break; case PROP_ENUM: - value = (float)RNA_property_enum_get(&ptr, prop); + value = float(RNA_property_enum_get(&ptr, prop)); break; default: fprintf(stderr, diff --git a/source/blender/io/collada/BCMath.cpp b/source/blender/io/collada/BCMath.cpp index d48e46ca115..6e052ee960d 100644 --- a/source/blender/io/collada/BCMath.cpp +++ b/source/blender/io/collada/BCMath.cpp @@ -140,9 +140,9 @@ void BCMatrix::sanitize(Matrix &mat, int precision) { for (auto &row : mat) { for (float &cell : row) { - double val = (double)cell; + double val = double(cell); val = double_round(val, precision); - cell = (float)val; + cell = float(val); } } } @@ -169,7 +169,7 @@ void BCMatrix::get_matrix(DMatrix &mat, const bool transposed, const int precisi for (int j = 0; j < 4; j++) { float val = (transposed) ? matrix[j][i] : matrix[i][j]; if (precision >= 0) { - val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision); + val = floor(val * pow(10, precision) + 0.5) / pow(10, precision); } mat[i][j] = val; } @@ -185,7 +185,7 @@ void BCMatrix::get_matrix(Matrix &mat, for (int j = 0; j < 4; j++) { float val = (transposed) ? matrix[j][i] : matrix[i][j]; if (precision >= 0) { - val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision); + val = floor(val * pow(10, precision) + 0.5) / pow(10, precision); } mat[i][j] = val; } diff --git a/source/blender/io/collada/BCSampleData.cpp b/source/blender/io/collada/BCSampleData.cpp index 42b436ec6fb..422ecdc598f 100644 --- a/source/blender/io/collada/BCSampleData.cpp +++ b/source/blender/io/collada/BCSampleData.cpp @@ -51,7 +51,7 @@ bool BCSample::get_value(std::string channel_target, const int array_index, floa else if (channel_type == "scale") { *val = matrix->scale()[array_index]; } - else if (channel_type == "rotation" || channel_type == "rotation_euler") { + else if (ELEM(channel_type, "rotation", "rotation_euler")) { *val = matrix->rotation()[array_index]; } else if (channel_type == "rotation_quaternion") { diff --git a/source/blender/io/collada/BlenderContext.cpp b/source/blender/io/collada/BlenderContext.cpp index 5f54f38a0ab..807488233ce 100644 --- a/source/blender/io/collada/BlenderContext.cpp +++ b/source/blender/io/collada/BlenderContext.cpp @@ -9,21 +9,25 @@ #include "BlenderContext.h" #include "ExportSettings.h" +#include "BKE_layer.h" #include "BKE_scene.h" -bool bc_is_base_node(LinkNode *export_set, Object *ob, ViewLayer *view_layer) +#include "BLI_listbase.h" + +bool bc_is_base_node(LinkNode *export_set, Object *ob, const Scene *scene, ViewLayer *view_layer) { - Object *root = bc_get_highest_exported_ancestor_or_self(export_set, ob, view_layer); + Object *root = bc_get_highest_exported_ancestor_or_self(export_set, ob, scene, view_layer); return (root == ob); } Object *bc_get_highest_exported_ancestor_or_self(LinkNode *export_set, Object *ob, + const Scene *scene, ViewLayer *view_layer) { Object *ancestor = ob; while (ob->parent) { - if (bc_is_in_Export_set(export_set, ob->parent, view_layer)) { + if (bc_is_in_Export_set(export_set, ob->parent, scene, view_layer)) { ancestor = ob->parent; } ob = ob->parent; @@ -31,10 +35,13 @@ Object *bc_get_highest_exported_ancestor_or_self(LinkNode *export_set, return ancestor; } -void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer) +void bc_get_children(std::vector<Object *> &child_set, + Object *ob, + const Scene *scene, + ViewLayer *view_layer) { - Base *base; - for (base = (Base *)view_layer->object_bases.first; base; base = base->next) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *cob = base->object; if (cob->parent == ob) { switch (ob->type) { @@ -51,7 +58,10 @@ void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *vi } } -bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer) +bool bc_is_in_Export_set(LinkNode *export_set, + Object *ob, + const Scene *scene, + ViewLayer *view_layer) { bool to_export = (BLI_linklist_index(export_set, ob) != -1); @@ -60,9 +70,9 @@ bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer * export list, but it contains children to export. */ std::vector<Object *> children; - bc_get_children(children, ob, view_layer); + bc_get_children(children, ob, scene, view_layer); for (Object *child : children) { - if (bc_is_in_Export_set(export_set, child, view_layer)) { + if (bc_is_in_Export_set(export_set, child, scene, view_layer)) { to_export = true; break; } diff --git a/source/blender/io/collada/BlenderContext.h b/source/blender/io/collada/BlenderContext.h index 6fdb043b3dc..8a782b74e52 100644 --- a/source/blender/io/collada/BlenderContext.h +++ b/source/blender/io/collada/BlenderContext.h @@ -22,8 +22,11 @@ extern "C" { static const BC_global_forward_axis BC_DEFAULT_FORWARD = BC_GLOBAL_FORWARD_Y; static const BC_global_up_axis BC_DEFAULT_UP = BC_GLOBAL_UP_Z; -bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer); -bool bc_is_base_node(LinkNode *export_set, Object *ob, ViewLayer *view_layer); +bool bc_is_in_Export_set(LinkNode *export_set, + Object *ob, + const Scene *scene, + ViewLayer *view_layer); +bool bc_is_base_node(LinkNode *export_set, Object *ob, const Scene *scene, ViewLayer *view_layer); /** * Returns the highest selected ancestor * returns NULL if no ancestor is selected @@ -32,6 +35,7 @@ bool bc_is_base_node(LinkNode *export_set, Object *ob, ViewLayer *view_layer); */ Object *bc_get_highest_exported_ancestor_or_self(LinkNode *export_set, Object *ob, + const Scene *scene, ViewLayer *view_layer); int bc_is_marked(Object *ob); void bc_remove_mark(Object *ob); diff --git a/source/blender/io/collada/CMakeLists.txt b/source/blender/io/collada/CMakeLists.txt index 3289a7c6e66..43cc0642921 100644 --- a/source/blender/io/collada/CMakeLists.txt +++ b/source/blender/io/collada/CMakeLists.txt @@ -2,7 +2,7 @@ # Copyright 2006 Blender Foundation. All rights reserved. remove_strict_flags() -FIND_FILE(OPENCOLLADA_ANIMATION_CLIP +find_file(OPENCOLLADA_ANIMATION_CLIP NAMES COLLADAFWAnimationClip.h PATHS @@ -14,7 +14,7 @@ if(OPENCOLLADA_ANIMATION_CLIP) add_definitions(-DWITH_OPENCOLLADA_ANIMATION_CLIP) endif() -# In cmake version 3.21 and up, we can instead use the NO_CACHE option for +# In CMAKE version 3.21 and up, we can instead use the NO_CACHE option for # find_file so we don't need to clear it from the cache here. unset(OPENCOLLADA_ANIMATION_CLIP CACHE) @@ -122,9 +122,4 @@ if(WITH_BUILDINFO) add_definitions(-DWITH_BUILDINFO) endif() -if(CMAKE_COMPILER_IS_GNUCXX) - # COLLADAFWArray.h gives error with gcc 4.5 - string(APPEND CMAKE_CXX_FLAGS " -fpermissive") -endif() - blender_add_lib(bf_collada "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/io/collada/CameraExporter.cpp b/source/blender/io/collada/CameraExporter.cpp index 45a73914256..7c3f304b722 100644 --- a/source/blender/io/collada/CameraExporter.cpp +++ b/source/blender/io/collada/CameraExporter.cpp @@ -51,7 +51,7 @@ void CamerasExporter::operator()(Object *ob, Scene *sce) case CAM_PERSP: { COLLADASW::PerspectiveOptic persp(mSW); persp.setXFov(RAD2DEGF(focallength_to_fov(cam->lens, cam->sensor_x)), "xfov"); - persp.setAspectRatio((float)(sce->r.xsch) / (float)(sce->r.ysch), false, "aspect_ratio"); + persp.setAspectRatio(float(sce->r.xsch) / float(sce->r.ysch), false, "aspect_ratio"); persp.setZFar(cam->clip_end, false, "zfar"); persp.setZNear(cam->clip_start, false, "znear"); COLLADASW::Camera ccam(mSW, &persp, cam_id, cam_name); @@ -64,7 +64,7 @@ void CamerasExporter::operator()(Object *ob, Scene *sce) default: { COLLADASW::OrthographicOptic ortho(mSW); ortho.setXMag(cam->ortho_scale / 2, "xmag"); - ortho.setAspectRatio((float)(sce->r.xsch) / (float)(sce->r.ysch), false, "aspect_ratio"); + ortho.setAspectRatio(float(sce->r.xsch) / float(sce->r.ysch), false, "aspect_ratio"); ortho.setZFar(cam->clip_end, false, "zfar"); ortho.setZNear(cam->clip_start, false, "znear"); COLLADASW::Camera ccam(mSW, &ortho, cam_id, cam_name); diff --git a/source/blender/io/collada/ControllerExporter.cpp b/source/blender/io/collada/ControllerExporter.cpp index 38ad0e42d0f..6bf8d904a41 100644 --- a/source/blender/io/collada/ControllerExporter.cpp +++ b/source/blender/io/collada/ControllerExporter.cpp @@ -63,7 +63,7 @@ bool ControllerExporter::add_instance_controller(Object *ob) ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); Mesh *me = (Mesh *)ob->data; - if (!me->dvert) { + if (BKE_mesh_deform_verts(me) == nullptr) { return false; } @@ -160,7 +160,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) bool use_instantiation = this->export_settings.get_use_object_instantiation(); Mesh *me; - if (((Mesh *)ob->data)->dvert == nullptr) { + if (BKE_mesh_deform_verts((Mesh *)ob->data) == nullptr) { return; } @@ -203,9 +203,10 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) } } + const MDeformVert *dvert = BKE_mesh_deform_verts(me); int oob_counter = 0; for (i = 0; i < me->totvert; i++) { - MDeformVert *vert = &me->dvert[i]; + const MDeformVert *vert = &dvert[i]; std::map<int, float> jw; /* We're normalizing the weights later */ diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 2ce97bc8b5d..660bbd7edb2 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -90,8 +90,12 @@ DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_set CTX_data_scene(C), view_layer, import_settings), - mesh_importer( - &unit_converter, &armature_importer, CTX_data_main(C), CTX_data_scene(C), view_layer), + mesh_importer(&unit_converter, + import_settings->custom_normals, + &armature_importer, + CTX_data_main(C), + CTX_data_scene(C), + view_layer), anim_importer(C, &unit_converter, &armature_importer, CTX_data_scene(C)) { } @@ -116,7 +120,7 @@ bool DocumentImporter::import() loader.registerExtraDataCallbackHandler(ehandler); /* deselect all to select new objects */ - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(CTX_data_scene(mContext), view_layer); std::string mFilename = std::string(this->import_settings->filepath); const std::string encodedFilename = bc_url_encode(mFilename); @@ -209,7 +213,7 @@ void DocumentImporter::finish() /* Write nodes to scene */ fprintf(stderr, "+-- Import Scene --------\n"); const COLLADAFW::NodePointerArray &roots = (*sit)->getRootNodes(); - for (unsigned int i = 0; i < roots.getCount(); i++) { + for (uint i = 0; i < roots.getCount(); i++) { std::vector<Object *> *objects_done = write_node(roots[i], nullptr, sce, nullptr, false); objects_to_scale->insert( objects_to_scale->end(), objects_done->begin(), objects_done->end()); @@ -230,14 +234,14 @@ void DocumentImporter::finish() for (const COLLADAFW::VisualScene *vscene : vscenes) { const COLLADAFW::NodePointerArray &roots = vscene->getRootNodes(); - for (unsigned int i = 0; i < roots.getCount(); i++) { + for (uint i = 0; i < roots.getCount(); i++) { translate_anim_recursive(roots[i], nullptr, nullptr); } } if (!libnode_ob.empty()) { - fprintf(stderr, "| Cleanup: free %d library nodes\n", (int)libnode_ob.size()); + fprintf(stderr, "| Cleanup: free %d library nodes\n", int(libnode_ob.size())); /* free all library_nodes */ std::vector<Object *>::iterator it; for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { @@ -288,7 +292,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, Object *ob; #endif - unsigned int i; + uint i; if (node->getType() == COLLADAFW::Node::JOINT && par == nullptr) { /* For Skeletons without root node we have to simulate the @@ -420,7 +424,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::NodePointerArray &children = source_node->getChildNodes(); if (children.getCount()) { - for (unsigned int i = 0; i < children.getCount(); i++) { + for (uint i = 0; i < children.getCount(); i++) { COLLADAFW::Node *child_node = children[i]; const COLLADAFW::UniqueId &child_id = child_node->getUniqueId(); if (object_map.find(child_id) == object_map.end()) { @@ -430,7 +434,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, Object *new_child = nullptr; if (inodes.getCount()) { /* \todo loop through instance nodes */ const COLLADAFW::UniqueId &id = inodes[0]->getInstanciatedObjectId(); - fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id)); + fprintf(stderr, "Doing %d child nodes\n", int(node_map.count(id))); new_child = create_instance_node( object_map.find(id)->second, node_map[id], child_node, sce, is_library_node); } @@ -671,7 +675,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, ob = *objects_done->begin(); } - for (unsigned int i = 0; i < child_nodes.getCount(); i++) { + for (uint i = 0; i < child_nodes.getCount(); i++) { std::vector<Object *> *child_objects; child_objects = write_node(child_nodes[i], node, sce, ob, is_library_node); delete child_objects; @@ -716,7 +720,7 @@ bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryN const COLLADAFW::NodePointerArray &nodes = libraryNodes->getNodes(); fprintf(stderr, "+-- Read Library nodes ----------\n"); - for (unsigned int i = 0; i < nodes.getCount(); i++) { + for (uint i = 0; i < nodes.getCount(); i++) { std::vector<Object *> *child_objects; child_objects = write_node(nodes[i], nullptr, sce, nullptr, true); delete child_objects; @@ -743,6 +747,7 @@ bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat) const std::string &str_mat_id = cmat->getName().empty() ? cmat->getOriginalId() : cmat->getName(); Material *ma = BKE_material_add(bmain, (char *)str_mat_id.c_str()); + id_us_min(&ma->id); this->uid_effect_map[cmat->getInstantiatedEffect()] = ma; this->uid_material_map[cmat->getUniqueId()] = ma; @@ -864,7 +869,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) double ymag = 2 * camera->getYMag().getValue(); double aspect = camera->getAspectRatio().getValue(); double xmag = aspect * ymag; - cam->ortho_scale = (float)xmag; + cam->ortho_scale = float(xmag); } break; case CAM_PERSP: default: { @@ -885,7 +890,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) case COLLADAFW::Camera::X_AND_Y: { switch (cam->type) { case CAM_ORTHO: - cam->ortho_scale = (float)camera->getXMag().getValue() * 2; + cam->ortho_scale = float(camera->getXMag().getValue()) * 2; break; case CAM_PERSP: default: { @@ -898,7 +903,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) case COLLADAFW::Camera::SINGLE_Y: { switch (cam->type) { case CAM_ORTHO: - cam->ortho_scale = (float)camera->getYMag().getValue(); + cam->ortho_scale = float(camera->getYMag().getValue()); break; case CAM_PERSP: default: { @@ -1177,7 +1182,7 @@ bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *e bool DocumentImporter::is_armature(COLLADAFW::Node *node) { COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); - for (unsigned int i = 0; i < child_nodes.getCount(); i++) { + for (uint i = 0; i < child_nodes.getCount(); i++) { if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) { return true; } diff --git a/source/blender/io/collada/EffectExporter.cpp b/source/blender/io/collada/EffectExporter.cpp index 40ce20617fc..e8a715633e1 100644 --- a/source/blender/io/collada/EffectExporter.cpp +++ b/source/blender/io/collada/EffectExporter.cpp @@ -217,7 +217,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob) create_image_samplers(ep, material_image_map, active_uv); #if 0 - unsigned int a, b; + uint a, b; for (a = 0, b = 0; a < tex_indices.size(); a++) { MTex *t = ma->mtex[tex_indices[a]]; Image *ima = t->tex->ima; diff --git a/source/blender/io/collada/ExportSettings.h b/source/blender/io/collada/ExportSettings.h index b3f192fdac6..e4c1b41fdde 100644 --- a/source/blender/io/collada/ExportSettings.h +++ b/source/blender/io/collada/ExportSettings.h @@ -81,7 +81,10 @@ typedef struct ExportSettings { #ifdef __cplusplus } -void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer); +void bc_get_children(std::vector<Object *> &child_set, + Object *ob, + const Scene *scene, + ViewLayer *view_layer); class BCExportSettings { @@ -271,7 +274,7 @@ class BCExportSettings { bool is_export_root(Object *ob) { - return bc_is_base_node(get_export_set(), ob, get_view_layer()); + return bc_is_base_node(get_export_set(), ob, get_scene(), get_view_layer()); } }; diff --git a/source/blender/io/collada/ExtraHandler.cpp b/source/blender/io/collada/ExtraHandler.cpp index b281f0e1a0a..d9c193ddbb5 100644 --- a/source/blender/io/collada/ExtraHandler.cpp +++ b/source/blender/io/collada/ExtraHandler.cpp @@ -43,7 +43,7 @@ bool ExtraHandler::textData(const char *text, size_t textLength) } bool ExtraHandler::parseElement(const char *profileName, - const unsigned long &elementHash, + const ulong &elementHash, const COLLADAFW::UniqueId &uniqueId) { /* implement for backwards compatibility, new version added object parameter */ @@ -51,7 +51,7 @@ bool ExtraHandler::parseElement(const char *profileName, } bool ExtraHandler::parseElement(const char *profileName, - const unsigned long &elementHash, + const ulong &elementHash, const COLLADAFW::UniqueId &uniqueId, COLLADAFW::Object *object) { diff --git a/source/blender/io/collada/ExtraTags.cpp b/source/blender/io/collada/ExtraTags.cpp index 398718f1133..9fb7bbb2295 100644 --- a/source/blender/io/collada/ExtraTags.cpp +++ b/source/blender/io/collada/ExtraTags.cpp @@ -49,7 +49,7 @@ float ExtraTags::asFloat(std::string tag, bool *ok) return -1.0f; } *ok = true; - return (float)atof(tags[tag].c_str()); + return float(atof(tags[tag].c_str())); } std::string ExtraTags::asString(std::string tag, bool *ok) @@ -67,7 +67,7 @@ bool ExtraTags::setData(std::string tag, short *data) bool ok = false; int tmp = asInt(tag, &ok); if (ok) { - *data = (short)tmp; + *data = short(tmp); } return ok; } @@ -97,7 +97,7 @@ bool ExtraTags::setData(std::string tag, char *data) bool ok = false; int tmp = asInt(tag, &ok); if (ok) { - *data = (char)tmp; + *data = char(tmp); } return ok; } diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index 7e2a24aeb41..a069c32026b 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -17,6 +17,7 @@ #include "BLI_utildefines.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_lib_id.h" @@ -26,6 +27,8 @@ #include "collada_internal.h" #include "collada_utils.h" +using blender::Span; + void GeometryExporter::exportGeom() { Scene *sce = blender_context.get_scene(); @@ -61,7 +64,7 @@ void GeometryExporter::operator()(Object *ob) exportedGeometry.insert(geom_id); - bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL); + bool has_color = bool(CustomData_has_layer(&me->fdata, CD_MCOL)); create_normals(nor, norind, me); @@ -74,7 +77,7 @@ void GeometryExporter::operator()(Object *ob) /* writes <source> for normal coords */ createNormalsSource(geom_id, me, nor); - bool has_uvs = (bool)CustomData_has_layer(&me->ldata, CD_MLOOPUV); + bool has_uvs = bool(CustomData_has_layer(&me->ldata, CD_MLOOPUV)); /* writes <source> for uv coords if mesh has uv coords */ if (has_uvs) { @@ -116,11 +119,12 @@ void GeometryExporter::operator()(Object *ob) if (this->export_settings.get_include_shapekeys()) { Key *key = BKE_key_from_object(ob); if (key) { + blender::MutableSpan<MVert> verts = me->verts_for_write(); KeyBlock *kb = (KeyBlock *)key->block.first; /* skip the basis */ kb = kb->next; for (; kb; kb = kb->next) { - BKE_keyblock_convert_to_mesh(kb, me->mvert, me->totvert); + BKE_keyblock_convert_to_mesh(kb, verts.data(), me->totvert); export_key_mesh(ob, me, kb); } } @@ -143,7 +147,7 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb) exportedGeometry.insert(geom_id); - bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL); + bool has_color = bool(CustomData_has_layer(&me->fdata, CD_MCOL)); create_normals(nor, norind, me); @@ -156,7 +160,7 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb) /* writes <source> for normal coords */ createNormalsSource(geom_id, me, nor); - bool has_uvs = (bool)CustomData_has_layer(&me->ldata, CD_MLOOPUV); + bool has_uvs = bool(CustomData_has_layer(&me->ldata, CD_MLOOPUV)); /* writes <source> for uv coords if mesh has uv coords */ if (has_uvs) { @@ -196,17 +200,16 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb) void GeometryExporter::createLooseEdgeList(Object *ob, Mesh *me, std::string &geom_id) { - - MEdge *medges = me->medge; + const Span<MEdge> edges = me->edges(); int totedges = me->totedge; int edges_in_linelist = 0; - std::vector<unsigned int> edge_list; + std::vector<uint> edge_list; int index; /* Find all loose edges in Mesh * and save vertex indices in edge_list */ for (index = 0; index < totedges; index++) { - MEdge *edge = &medges[index]; + const MEdge *edge = &edges[index]; if (edge->flag & ME_LOOSEEDGE) { edges_in_linelist += 1; @@ -241,7 +244,7 @@ void GeometryExporter::createLooseEdgeList(Object *ob, Mesh *me, std::string &ge static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase &primitive_list, - std::vector<unsigned long> &vcount_list) + std::vector<ulong> &vcount_list) { /* performs the actual writing */ if (is_triangulated) { @@ -282,18 +285,19 @@ static COLLADASW::PrimitivesBase *create_primitive_list(bool is_triangulated, static bool collect_vertex_counts_per_poly(Mesh *me, int material_index, - std::vector<unsigned long> &vcount_list) + std::vector<ulong> &vcount_list) { - MPoly *mpolys = me->mpoly; - int totpolys = me->totpoly; + const Span<MPoly> polys = me->polys(); + const blender::bke::AttributeAccessor attributes = me->attributes(); + const blender::VArray<int> material_indices = attributes.lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); bool is_triangulated = true; - int i; - /* Expecting that p->mat_nr is always 0 if the mesh has no materials assigned */ - for (i = 0; i < totpolys; i++) { - MPoly *p = &mpolys[i]; - if (p->mat_nr == material_index) { - int vertex_count = p->totloop; + /* Expecting that the material index is always 0 if the mesh has no materials assigned */ + for (const int i : polys.index_range()) { + if (material_indices[i] == material_index) { + const MPoly &poly = polys[i]; + const int vertex_count = poly.totloop; vcount_list.push_back(vertex_count); if (vertex_count != 3) { is_triangulated = false; @@ -318,12 +322,10 @@ void GeometryExporter::create_mesh_primitive_list(short material_index, std::string &geom_id, std::vector<BCPolygonNormalsIndices> &norind) { + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); - MPoly *mpolys = me->mpoly; - MLoop *mloops = me->mloop; - int totpolys = me->totpoly; - - std::vector<unsigned long> vcount_list; + std::vector<ulong> vcount_list; bool is_triangulated = collect_vertex_counts_per_poly(me, material_index, vcount_list); int polygon_count = vcount_list.size(); @@ -397,14 +399,18 @@ void GeometryExporter::create_mesh_primitive_list(short material_index, /* performs the actual writing */ prepareToAppendValues(is_triangulated, *primitive_list, vcount_list); + const blender::bke::AttributeAccessor attributes = me->attributes(); + const blender::VArray<int> material_indices = attributes.lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); + /* <p> */ int texindex = 0; - for (int i = 0; i < totpolys; i++) { - MPoly *p = &mpolys[i]; + for (const int i : polys.index_range()) { + const MPoly *p = &polys[i]; int loop_count = p->totloop; - if (p->mat_nr == material_index) { - MLoop *l = &mloops[p->loopstart]; + if (material_indices[i] == material_index) { + const MLoop *l = &loops[p->loopstart]; BCPolygonNormalsIndices normal_indices = norind[i]; for (int j = 0; j < loop_count; j++) { @@ -428,18 +434,13 @@ void GeometryExporter::create_mesh_primitive_list(short material_index, void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) { -#if 0 - int totverts = dm->getNumVerts(dm); - MVert *verts = dm->getVertArray(dm); -#endif - int totverts = me->totvert; - MVert *verts = me->mvert; + const Span<MVert> verts = me->verts(); COLLADASW::FloatSourceF source(mSW); source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::POSITION) + ARRAY_ID_SUFFIX); - source.setAccessorCount(totverts); + source.setAccessorCount(verts.size()); source.setAccessorStride(3); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); @@ -450,8 +451,7 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) * count = ""> */ source.prepareToAppendValues(); /* appends data to <float_array> */ - int i = 0; - for (i = 0; i < totverts; i++) { + for (const int i : verts.index_range()) { Vector co; if (export_settings.get_apply_global_orientation()) { bc_add_global_transform(co, verts[i].co, export_settings.get_global_transform()); @@ -500,11 +500,11 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) source.prepareToAppendValues(); - MPoly *mpoly; - int i; - for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) { - const MLoopCol *mlc = mloopcol + mpoly->loopstart; - for (int j = 0; j < mpoly->totloop; j++, mlc++) { + const Span<MPoly> polys = me->polys(); + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; + const MLoopCol *mlc = mloopcol + poly.loopstart; + for (int j = 0; j < poly.totloop; j++, mlc++) { source.appendValues(mlc->r / 255.0f, mlc->g / 255.0f, mlc->b / 255.0f, mlc->a / 255.0f); } } @@ -529,10 +529,8 @@ std::string GeometryExporter::makeTexcoordSourceId(std::string &geom_id, void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) { - - int totpoly = me->totpoly; int totuv = me->totloop; - MPoly *mpolys = me->mpoly; + const Span<MPoly> polys = me->polys(); int num_layers = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); @@ -558,8 +556,8 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) source.prepareToAppendValues(); - for (int index = 0; index < totpoly; index++) { - MPoly *mpoly = mpolys + index; + for (const int i : polys.index_range()) { + const MPoly *mpoly = &polys[i]; MLoopUV *mloop = mloops + mpoly->loopstart; for (int j = 0; j < mpoly->totloop; j++) { source.appendValues(mloop[j].uv[0], mloop[j].uv[1]); @@ -587,7 +585,7 @@ void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::v COLLADASW::FloatSourceF source(mSW); source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL)); source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL) + ARRAY_ID_SUFFIX); - source.setAccessorCount((unsigned long)nor.size()); + source.setAccessorCount(ulong(nor.size())); source.setAccessorStride(3); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); param.push_back("X"); @@ -614,12 +612,13 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<BCPolygonNormalsIndices> &polygons_normals, Mesh *me) { - std::map<Normal, unsigned int> shared_normal_indices; + std::map<Normal, uint> shared_normal_indices; int last_normal_index = -1; - MVert *verts = me->mvert; + const Span<MVert> verts = me->verts(); const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me); - MLoop *mloops = me->mloop; + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); const float(*lnors)[3] = nullptr; bool use_custom_normals = false; @@ -629,15 +628,15 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals, use_custom_normals = true; } - for (int poly_index = 0; poly_index < me->totpoly; poly_index++) { - MPoly *mpoly = &me->mpoly[poly_index]; + for (const int poly_index : polys.index_range()) { + const MPoly *mpoly = &polys[poly_index]; bool use_vertex_normals = use_custom_normals || mpoly->flag & ME_SMOOTH; if (!use_vertex_normals) { /* For flat faces use face normal as vertex normal: */ float vector[3]; - BKE_mesh_calc_poly_normal(mpoly, mloops + mpoly->loopstart, verts, vector); + BKE_mesh_calc_poly_normal(mpoly, &loops[mpoly->loopstart], verts.data(), vector); Normal n = {vector[0], vector[1], vector[2]}; normals.push_back(n); @@ -646,7 +645,7 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals, BCPolygonNormalsIndices poly_indices; for (int loop_index = 0; loop_index < mpoly->totloop; loop_index++) { - unsigned int loop_idx = mpoly->loopstart + loop_index; + uint loop_idx = mpoly->loopstart + loop_index; if (use_vertex_normals) { float normalized[3]; @@ -654,7 +653,7 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals, normalize_v3_v3(normalized, lnors[loop_idx]); } else { - copy_v3_v3(normalized, vert_normals[mloops[loop_index].v]); + copy_v3_v3(normalized, vert_normals[loops[loop_index].v]); normalize_v3(normalized); } Normal n = {normalized[0], normalized[1], normalized[2]}; diff --git a/source/blender/io/collada/ImportSettings.h b/source/blender/io/collada/ImportSettings.h index c92cf580112..2772314900c 100644 --- a/source/blender/io/collada/ImportSettings.h +++ b/source/blender/io/collada/ImportSettings.h @@ -8,6 +8,7 @@ typedef struct ImportSettings { bool import_units; + bool custom_normals; bool find_chains; bool auto_connect; bool fix_orientation; diff --git a/source/blender/io/collada/Materials.cpp b/source/blender/io/collada/Materials.cpp index b5d89d8d1cf..997da31b939 100644 --- a/source/blender/io/collada/Materials.cpp +++ b/source/blender/io/collada/Materials.cpp @@ -86,7 +86,7 @@ bNodeTree *MaterialNode::prepare_material_nodetree() return nullptr; } - material->nodetree = ntreeAddTree(nullptr, "Shader Nodetree", "ShaderNodeTree"); + ntreeAddTreeEmbedded(nullptr, &material->id, "Shader Nodetree", "ShaderNodeTree"); material->use_nodes = true; ntree = material->nodetree; return ntree; diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index 9fbba1b97fb..6d7593afb8b 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -33,6 +33,8 @@ #include "MeshImporter.h" #include "collada_utils.h" +using blender::MutableSpan; + /* get node name, or fall back to original id if not present (name is optional) */ template<class T> static std::string bc_get_dae_name(T *node) { @@ -100,7 +102,7 @@ void WVDataWrapper::print() COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues(); if (values->getCount()) { for (int i = 0; i < values->getCount(); i += 2) { - fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i + 1]); + fprintf(stderr, "%.1f, %.1f\n", float((*values)[i]), float((*values)[i + 1])); } } } break; @@ -131,8 +133,8 @@ void UVDataWrapper::getUV(int uv_index, float *uv) if (values->empty()) { return; } - uv[0] = (float)(*values)[uv_index * stride]; - uv[1] = (float)(*values)[uv_index * stride + 1]; + uv[0] = float((*values)[uv_index * stride]); + uv[1] = float((*values)[uv_index * stride + 1]); } break; case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN: @@ -189,9 +191,14 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol) } } -MeshImporter::MeshImporter( - UnitConverter *unitconv, ArmatureImporter *arm, Main *bmain, Scene *sce, ViewLayer *view_layer) +MeshImporter::MeshImporter(UnitConverter *unitconv, + bool use_custom_normals, + ArmatureImporter *arm, + Main *bmain, + Scene *sce, + ViewLayer *view_layer) : unitconverter(unitconv), + use_custom_normals(use_custom_normals), m_bmain(bmain), scene(sce), view_layer(view_layer), @@ -201,7 +208,7 @@ MeshImporter::MeshImporter( } bool MeshImporter::set_poly_indices( - MPoly *mpoly, MLoop *mloop, int loop_index, const unsigned int *indices, int loop_count) + MPoly *mpoly, MLoop *mloop, int loop_index, const uint *indices, int loop_count) { mpoly->loopstart = loop_index; mpoly->totloop = loop_count; @@ -269,7 +276,7 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) const std::string &name = bc_get_dae_name(mesh); - for (unsigned int i = 0; i < prim_arr.getCount(); i++) { + for (uint i = 0; i < prim_arr.getCount(); i++) { COLLADAFW::MeshPrimitive *mp = prim_arr[i]; COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType(); @@ -277,7 +284,7 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) const char *type_str = bc_primTypeToStr(type); /* OpenCollada passes POLYGONS type for <polylist> */ - if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) { + if (ELEM(type, COLLADAFW::MeshPrimitive::POLYLIST, COLLADAFW::MeshPrimitive::POLYGONS)) { COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; COLLADAFW::Polygons::VertexCountArray &vca = mpvc->getGroupedVerticesVertexCountArray(); @@ -285,7 +292,7 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) int hole_count = 0; int nonface_count = 0; - for (unsigned int j = 0; j < vca.getCount(); j++) { + for (uint j = 0; j < vca.getCount(); j++) { int count = vca[j]; if (abs(count) < 3) { nonface_count++; @@ -317,8 +324,9 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) /* TODO: Add Checker for line syntax here */ } - else if (type != COLLADAFW::MeshPrimitive::TRIANGLES && - type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) { + else if (!ELEM(type, + COLLADAFW::MeshPrimitive::TRIANGLES, + COLLADAFW::MeshPrimitive::TRIANGLE_FANS)) { fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str); return false; } @@ -341,13 +349,10 @@ void MeshImporter::read_vertices(COLLADAFW::Mesh *mesh, Mesh *me) } me->totvert = pos.getFloatValues()->getCount() / stride; - me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, nullptr, me->totvert); - - MVert *mvert; - int i; - - for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { - get_vector(mvert->co, pos, i, stride); + CustomData_add_layer(&me->vdata, CD_MVERT, CD_SET_DEFAULT, nullptr, me->totvert); + MutableSpan<MVert> verts = me->verts_for_write(); + for (const int i : verts.index_range()) { + get_vector(verts[i].co, pos, i, stride); } } @@ -448,12 +453,10 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) if (total_poly_count > 0) { me->totpoly = total_poly_count; me->totloop = total_loop_count; - me->mpoly = (MPoly *)CustomData_add_layer( - &me->pdata, CD_MPOLY, CD_CALLOC, nullptr, me->totpoly); - me->mloop = (MLoop *)CustomData_add_layer( - &me->ldata, CD_MLOOP, CD_CALLOC, nullptr, me->totloop); + CustomData_add_layer(&me->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, me->totpoly); + CustomData_add_layer(&me->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, me->totloop); - unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount(); + uint totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount(); for (int i = 0; i < totuvset; i++) { if (collada_mesh->getUVCoords().getLength(i) == 0) { totuvset = 0; @@ -468,10 +471,10 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) COLLADAFW::String &uvname = info->mName; /* Allocate space for UV_data */ CustomData_add_layer_named( - &me->ldata, CD_MLOOPUV, CD_DEFAULT, nullptr, me->totloop, uvname.c_str()); + &me->ldata, CD_MLOOPUV, CD_SET_DEFAULT, nullptr, me->totloop, uvname.c_str()); } /* activate the first uv map */ - me->mloopuv = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0); + CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, 0); } int totcolset = collada_mesh->getColors().getInputInfosArray().getCount(); @@ -481,14 +484,14 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) collada_mesh->getColors().getInputInfosArray()[i]; COLLADAFW::String colname = extract_vcolname(info->mName); CustomData_add_layer_named( - &me->ldata, CD_PROP_BYTE_COLOR, CD_DEFAULT, nullptr, me->totloop, colname.c_str()); + &me->ldata, CD_PROP_BYTE_COLOR, CD_SET_DEFAULT, nullptr, me->totloop, colname.c_str()); } - me->mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_PROP_BYTE_COLOR, 0); + CustomData_set_layer_active(&me->ldata, CD_PROP_BYTE_COLOR, 0); } } } -unsigned int MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index) +uint MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index) { int type = mp->getPrimitiveType(); int result; @@ -511,7 +514,7 @@ unsigned int MeshImporter::get_vertex_count(COLLADAFW::Polygons *mp, int index) return result; } -unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) +uint MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) { COLLADAFW::MeshPrimitiveArray &prim_arr = mesh->getMeshPrimitives(); int loose_edge_count = 0; @@ -546,21 +549,22 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len) totedge = mesh->totedge + len; /* Update custom-data. */ - CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge); + CustomData_copy(&mesh->edata, &edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, totedge); CustomData_copy_data(&mesh->edata, &edata, 0, 0, mesh->totedge); if (!CustomData_has_layer(&edata, CD_MEDGE)) { - CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, nullptr, totedge); + CustomData_add_layer(&edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, totedge); } CustomData_free(&mesh->edata, mesh->totedge); mesh->edata = edata; - BKE_mesh_update_customdata_pointers(mesh, false); /* new edges don't change tessellation */ + + MutableSpan<MEdge> edges = mesh->edges_for_write(); /* set default flags */ - medge = &mesh->medge[mesh->totedge]; + medge = &edges[mesh->totedge]; for (int i = 0; i < len; i++, medge++) { - medge->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; + medge->flag = ME_EDGEDRAW | ME_EDGERENDER; } mesh->totedge = totedge; @@ -568,14 +572,15 @@ void MeshImporter::mesh_add_edges(Mesh *mesh, int len) void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) { - unsigned int loose_edge_count = get_loose_edge_count(mesh); + uint loose_edge_count = get_loose_edge_count(mesh); if (loose_edge_count > 0) { - unsigned int face_edge_count = me->totedge; - /* unsigned int total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */ + uint face_edge_count = me->totedge; + /* uint total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */ mesh_add_edges(me, loose_edge_count); - MEdge *med = me->medge + face_edge_count; + MutableSpan<MEdge> edges = me->edges_for_write(); + MEdge *med = edges.data() + face_edge_count; COLLADAFW::MeshPrimitiveArray &prim_arr = mesh->getMeshPrimitives(); @@ -584,12 +589,10 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) int type = mp->getPrimitiveType(); if (type == COLLADAFW::MeshPrimitive::LINES) { - unsigned int edge_count = mp->getFaceCount(); - unsigned int *indices = mp->getPositionIndices().getData(); + uint edge_count = mp->getFaceCount(); + uint *indices = mp->getPositionIndices().getData(); for (int j = 0; j < edge_count; j++, med++) { - med->bweight = 0; - med->crease = 0; med->flag |= ME_LOOSEEDGE; med->v1 = indices[2 * j]; med->v2 = indices[2 * j + 1]; @@ -599,21 +602,28 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) } } -void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) +void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, + Mesh *me, + blender::Vector<blender::float3> &loop_normals) { - unsigned int i; + uint i; allocate_poly_data(collada_mesh, me); UVDataWrapper uvs(collada_mesh->getUVCoords()); VCOLDataWrapper vcol(collada_mesh->getColors()); - MPoly *mpoly = me->mpoly; - MLoop *mloop = me->mloop; + MutableSpan<MPoly> polys = me->polys_for_write(); + MutableSpan<MLoop> loops = me->loops_for_write(); + MPoly *mpoly = polys.data(); + MLoop *mloop = loops.data(); int loop_index = 0; MaterialIdPrimitiveArrayMap mat_prim_map; + int *material_indices = (int *)CustomData_add_layer_named( + &me->pdata, CD_PROP_INT32, CD_SET_DEFAULT, nullptr, me->totpoly, "material_index"); + COLLADAFW::MeshPrimitiveArray &prim_arr = collada_mesh->getMeshPrimitives(); COLLADAFW::MeshVertexData &nor = collada_mesh->getNormals(); @@ -623,8 +633,8 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) /* faces */ size_t prim_totpoly = mp->getFaceCount(); - unsigned int *position_indices = mp->getPositionIndices().getData(); - unsigned int *normal_indices = mp->getNormalIndices().getData(); + uint *position_indices = mp->getPositionIndices().getData(); + uint *normal_indices = mp->getNormalIndices().getData(); bool mp_has_normals = primitive_has_useable_normals(mp); bool mp_has_faces = primitive_has_faces(mp); @@ -632,29 +642,29 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) int collada_meshtype = mp->getPrimitiveType(); /* since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive */ - Primitive prim = {mpoly, 0}; + Primitive prim = {mpoly, material_indices, 0}; /* If MeshPrimitive is TRIANGLE_FANS we split it into triangles * The first triangle-fan vertex will be the first vertex in every triangle * XXX The proper function of TRIANGLE_FANS is not tested!!! - * XXX In particular the handling of the normal_indices looks very wrong to me */ + * XXX In particular the handling of the normal_indices is very wrong */ + /* TODO: UV, vertex color and custom normal support */ if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) { - unsigned int grouped_vertex_count = mp->getGroupedVertexElementsCount(); - for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) { - unsigned int first_vertex = position_indices[0]; /* Store first trifan vertex */ - unsigned int first_normal = normal_indices[0]; /* Store first trifan vertex normal */ - unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index); + uint grouped_vertex_count = mp->getGroupedVertexElementsCount(); + for (uint group_index = 0; group_index < grouped_vertex_count; group_index++) { + uint first_vertex = position_indices[0]; /* Store first trifan vertex */ + uint first_normal = normal_indices[0]; /* Store first trifan vertex normal */ + uint vertex_count = mp->getGroupedVerticesVertexCount(group_index); - for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) { + for (uint vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) { /* For each triangle store indices of its 3 vertices */ - unsigned int triangle_vertex_indices[3] = { + uint triangle_vertex_indices[3] = { first_vertex, position_indices[1], position_indices[2]}; set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3); if (mp_has_normals) { /* vertex normals, same implementation as for the triangles */ /* The same for vertices normals. */ - unsigned int vertex_normal_indices[3] = { - first_normal, normal_indices[1], normal_indices[2]}; + uint vertex_normal_indices[3] = {first_normal, normal_indices[1], normal_indices[2]}; if (!is_flat_face(vertex_normal_indices, nor, 3)) { mpoly->flag |= ME_SMOOTH; } @@ -662,6 +672,9 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) } mpoly++; + if (material_indices) { + material_indices++; + } mloop += 3; loop_index += 3; prim.totpoly++; @@ -676,17 +689,18 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) } } - if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST || - collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS || - collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES) { + if (ELEM(collada_meshtype, + COLLADAFW::MeshPrimitive::POLYLIST, + COLLADAFW::MeshPrimitive::POLYGONS, + COLLADAFW::MeshPrimitive::TRIANGLES)) { COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; - unsigned int start_index = 0; + uint start_index = 0; COLLADAFW::IndexListArray &index_list_array_uvcoord = mp->getUVCoordIndicesArray(); COLLADAFW::IndexListArray &index_list_array_vcolor = mp->getColorIndicesArray(); int invalid_loop_holes = 0; - for (unsigned int j = 0; j < prim_totpoly; j++) { + for (uint j = 0; j < prim_totpoly; j++) { /* Vertices in polygon: */ int vcount = get_vertex_count(mpvc, j); @@ -699,7 +713,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) invalid_loop_holes += 1; } - for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); + for (uint uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); uvset_index++) { /* get mtface by face index and uv set index */ COLLADAFW::IndexList &index_list = *index_list_array_uvcoord[uvset_index]; @@ -721,15 +735,28 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) } if (mp_has_normals) { + /* If it turns out that we have complete custom normals for each MPoly + * and we want to use custom normals, this will be overridden. */ if (!is_flat_face(normal_indices, nor, vcount)) { mpoly->flag |= ME_SMOOTH; } + + if (use_custom_normals) { + /* Store the custom normals for later application. */ + float vert_normal[3]; + uint *cur_normal = normal_indices; + for (int k = 0; k < vcount; k++, cur_normal++) { + get_vector(vert_normal, nor, *cur_normal, 3); + normalize_v3(vert_normal); + loop_normals.append(vert_normal); + } + } } if (mp->hasColorIndices()) { int vcolor_count = index_list_array_vcolor.getCount(); - for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) { + for (uint vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) { COLLADAFW::IndexList &color_index_list = *mp->getColorIndices(vcolor_index); COLLADAFW::String colname = extract_vcolname(color_index_list.getName()); @@ -807,10 +834,10 @@ void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData &arr, int i, return; } - v[0] = (float)(*values)[i++]; - v[1] = (float)(*values)[i++]; + v[0] = float((*values)[i++]); + v[1] = float((*values)[i++]); if (stride >= 3) { - v[2] = (float)(*values)[i]; + v[2] = float((*values)[i]); } else { v[2] = 0.0f; @@ -821,7 +848,7 @@ void MeshImporter::get_vector(float v[3], COLLADAFW::MeshVertexData &arr, int i, } } -bool MeshImporter::is_flat_face(unsigned int *nind, COLLADAFW::MeshVertexData &nor, int count) +bool MeshImporter::is_flat_face(uint *nind, COLLADAFW::MeshVertexData &nor, int count) { float a[3], b[3]; @@ -868,6 +895,16 @@ std::string *MeshImporter::get_geometry_name(const std::string &mesh_name) return nullptr; } +static bool bc_has_out_of_bound_indices(Mesh *me) +{ + for (const MLoop &loop : me->loops()) { + if (loop.v >= me->totvert) { + return true; + } + } + return false; +} + /** * this function checks if both objects have the same * materials assigned to Object (in the same order) @@ -1006,10 +1043,9 @@ void MeshImporter::assign_material_to_geom( for (it = prims.begin(); it != prims.end(); it++) { Primitive &prim = *it; - MPoly *mpoly = prim.mpoly; - for (int i = 0; i < prim.totpoly; i++, mpoly++) { - mpoly->mat_nr = mat_index; + for (int i = 0; i < prim.totpoly; i++) { + prim.material_indices[i] = mat_index; } } } @@ -1072,7 +1108,7 @@ Object *MeshImporter::create_mesh_object( COLLADAFW::MaterialBindingArray &mat_array = geom->getMaterialBindings(); /* loop through geom's materials */ - for (unsigned int i = 0; i < mat_array.getCount(); i++) { + for (uint i = 0; i < mat_array.getCount(); i++) { if (mat_array[i].getReferencedMaterial().isValid()) { assign_material_to_geom(mat_array[i], uid_material_map, ob, geom_uid, i); @@ -1115,8 +1151,37 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom) this->mesh_geom_map[std::string(me->id.name)] = str_geom_id; read_vertices(mesh, me); - read_polys(mesh, me); + + blender::Vector<blender::float3> loop_normals; + read_polys(mesh, me, loop_normals); + BKE_mesh_calc_edges(me, false, false); + + /* We must apply custom normals after edges have been calculated, because + * BKE_mesh_set_custom_normals()'s internals expect me->medge to be populated + * and for the MLoops to have correct edge indices. */ + if (use_custom_normals && !loop_normals.is_empty()) { + /* BKE_mesh_set_custom_normals()'s internals also expect that each MLoop + * has a valid vertex index, which may not be the case due to the existing + * logic in read_polys(). This check isn't necessary in the no-custom-normals + * case because the invalid MLoops get stripped in a later step. */ + if (bc_has_out_of_bound_indices(me)) { + fprintf(stderr, "Can't apply custom normals, encountered invalid loop vert indices!\n"); + } + /* There may be a mismatch in lengths if one or more of the MeshPrimitives in + * the Geometry had missing or otherwise invalid normals. */ + else if (me->totloop != loop_normals.size()) { + fprintf(stderr, + "Can't apply custom normals, me->totloop != loop_normals.size() (%d != %d)\n", + me->totloop, + int(loop_normals.size())); + } + else { + BKE_mesh_set_custom_normals(me, reinterpret_cast<float(*)[3]>(loop_normals.data())); + me->flag |= ME_AUTOSMOOTH; + } + } + /* read_lines() must be called after the face edges have been generated. * Otherwise the loose edges will be silently deleted again. */ read_lines(mesh, me); diff --git a/source/blender/io/collada/MeshImporter.h b/source/blender/io/collada/MeshImporter.h index 92b387a4bfe..a59b24d4f24 100644 --- a/source/blender/io/collada/MeshImporter.h +++ b/source/blender/io/collada/MeshImporter.h @@ -24,6 +24,7 @@ #include "collada_utils.h" #include "BLI_edgehash.h" +#include "BLI_math_vec_types.hh" #include "DNA_material_types.h" #include "DNA_mesh_types.h" @@ -63,6 +64,7 @@ class VCOLDataWrapper { class MeshImporter : public MeshImporterBase { private: UnitConverter *unitconverter; + bool use_custom_normals; Main *m_bmain; Scene *scene; @@ -80,6 +82,7 @@ class MeshImporter : public MeshImporterBase { * (<triangles>, <polylist>, etc.) */ struct Primitive { MPoly *mpoly; + int *material_indices; unsigned int totpoly; }; typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive>> MaterialIdPrimitiveArrayMap; @@ -155,7 +158,7 @@ class MeshImporter : public MeshImporterBase { * * TODO: import uv set names. */ - void read_polys(COLLADAFW::Mesh *mesh, Mesh *me); + void read_polys(COLLADAFW::Mesh *mesh, Mesh *me, blender::Vector<blender::float3> &loop_normals); /** * Read all loose edges. * IMPORTANT: This function assumes that all edges from existing @@ -178,6 +181,7 @@ class MeshImporter : public MeshImporterBase { public: MeshImporter(UnitConverter *unitconv, + bool use_custom_normals, ArmatureImporter *arm, Main *bmain, Scene *sce, diff --git a/source/blender/io/collada/SceneExporter.cpp b/source/blender/io/collada/SceneExporter.cpp index 1b1da110573..b98ff27c89e 100644 --- a/source/blender/io/collada/SceneExporter.cpp +++ b/source/blender/io/collada/SceneExporter.cpp @@ -82,11 +82,13 @@ void SceneExporter::writeNodeList(std::vector<Object *> &child_objects, Object * void SceneExporter::writeNode(Object *ob) { + const Scene *scene = blender_context.get_scene(); ViewLayer *view_layer = blender_context.get_view_layer(); std::vector<Object *> child_objects; - bc_get_children(child_objects, ob, view_layer); - bool can_export = bc_is_in_Export_set(this->export_settings.get_export_set(), ob, view_layer); + bc_get_children(child_objects, ob, scene, view_layer); + bool can_export = bc_is_in_Export_set( + this->export_settings.get_export_set(), ob, scene, view_layer); /* Add associated armature first if available */ bool armature_exported = false; @@ -94,7 +96,7 @@ void SceneExporter::writeNode(Object *ob) if (ob_arm != nullptr) { armature_exported = bc_is_in_Export_set( - this->export_settings.get_export_set(), ob_arm, view_layer); + this->export_settings.get_export_set(), ob_arm, scene, view_layer); if (armature_exported && bc_is_marked(ob_arm)) { writeNode(ob_arm); bc_remove_mark(ob_arm); diff --git a/source/blender/io/collada/SkinInfo.cpp b/source/blender/io/collada/SkinInfo.cpp index 8144e0a499d..0654bae3730 100644 --- a/source/blender/io/collada/SkinInfo.cpp +++ b/source/blender/io/collada/SkinInfo.cpp @@ -77,7 +77,7 @@ void SkinInfo::transfer_int_array_data_const(const COLLADAFW::IntValuesArray &sr void SkinInfo::transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray &src, COLLADAFW::UIntValuesArray &dest) { - dest.setData((unsigned int *)src.getData(), src.getCount()); + dest.setData((uint *)src.getData(), src.getCount()); dest.yieldOwnerShip(); } @@ -90,7 +90,7 @@ void SkinInfo::borrow_skin_controller_data(const COLLADAFW::SkinControllerData * /* cannot transfer data for FloatOrDoubleArray, copy values manually */ const COLLADAFW::FloatOrDoubleArray &weight = skin->getWeights(); - for (unsigned int i = 0; i < weight.getValuesCount(); i++) { + for (uint i = 0; i < weight.getValuesCount(); i++) { weights.push_back(bc_get_float_value(weight, i)); } @@ -118,7 +118,7 @@ void SkinInfo::set_controller(const COLLADAFW::SkinController *co) /* fill in joint UIDs */ const COLLADAFW::UniqueIdArray &joint_uids = co->getJoints(); - for (unsigned int i = 0; i < joint_uids.getCount(); i++) { + for (uint i = 0; i < joint_uids.getCount(); i++) { joint_data[i].joint_uid = joint_uids[i]; /* store armature pointer */ @@ -181,7 +181,7 @@ bool SkinInfo::uses_joint_or_descendant(COLLADAFW::Node *node) } COLLADAFW::NodePointerArray &children = node->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { + for (uint i = 0; i < children.getCount(); i++) { if (uses_joint_or_descendant(children[i])) { return true; } @@ -254,9 +254,9 @@ void SkinInfo::link_armature(bContext *C, * * get def group by index with BLI_findlink */ - for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) { + for (uint vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) { - unsigned int limit = weight + joints_per_vertex[vertex]; + uint limit = weight + joints_per_vertex[vertex]; for (; weight < limit; weight++) { int joint = joint_indices[weight], joint_weight = weight_indices[weight]; @@ -319,7 +319,7 @@ bool SkinInfo::find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_ro } COLLADAFW::NodePointerArray &children = tree_root->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { + for (uint i = 0; i < children.getCount(); i++) { if (find_node_in_tree(node, children[i])) { return true; } diff --git a/source/blender/io/collada/TransformReader.cpp b/source/blender/io/collada/TransformReader.cpp index e5872c28bce..cc1334bd99b 100644 --- a/source/blender/io/collada/TransformReader.cpp +++ b/source/blender/io/collada/TransformReader.cpp @@ -33,7 +33,7 @@ void TransformReader::get_node_mat(float mat[4][4], unit_m4(mat); - for (unsigned int i = 0; i < node->getTransformations().getCount(); i++) { + for (uint i = 0; i < node->getTransformations().getCount(); i++) { COLLADAFW::Transformation *tm = node->getTransformations()[i]; COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); @@ -87,8 +87,8 @@ void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[ { COLLADAFW::Rotate *ro = (COLLADAFW::Rotate *)tm; COLLADABU::Math::Vector3 &axis = ro->getRotationAxis(); - const float angle = (float)DEG2RAD(ro->getRotationAngle()); - const float ax[] = {(float)axis[0], (float)axis[1], (float)axis[2]}; + const float angle = float(DEG2RAD(ro->getRotationAngle())); + const float ax[] = {float(axis[0]), float(axis[1]), float(axis[2])}; #if 0 float quat[4]; axis_angle_to_quat(quat, axis, angle); @@ -104,15 +104,15 @@ void TransformReader::dae_translate_to_mat4(COLLADAFW::Transformation *tm, float unit_m4(m); - m[3][0] = (float)t[0]; - m[3][1] = (float)t[1]; - m[3][2] = (float)t[2]; + m[3][0] = float(t[0]); + m[3][1] = float(t[1]); + m[3][2] = float(t[2]); } void TransformReader::dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]) { COLLADABU::Math::Vector3 &s = ((COLLADAFW::Scale *)tm)->getScale(); - float size[3] = {(float)s[0], (float)s[1], (float)s[2]}; + float size[3] = {float(s[0]), float(s[1]), float(s[2])}; size_to_mat4(m, size); } diff --git a/source/blender/io/collada/collada.cpp b/source/blender/io/collada/collada.cpp index d559c0b4962..c33363ef205 100644 --- a/source/blender/io/collada/collada.cpp +++ b/source/blender/io/collada/collada.cpp @@ -29,6 +29,7 @@ static void print_import_header(ImportSettings &import_settings) fprintf(stderr, "+-- Collada Import parameters------\n"); fprintf(stderr, "| input file : %s\n", import_settings.filepath); fprintf(stderr, "| use units : %s\n", (import_settings.import_units) ? "yes" : "no"); + fprintf(stderr, "| custom normals : %s\n", (import_settings.custom_normals) ? "yes" : "no"); fprintf(stderr, "| autoconnect : %s\n", (import_settings.auto_connect) ? "yes" : "no"); fprintf(stderr, "+-- Armature Import parameters ----\n"); fprintf(stderr, "| find bone chains: %s\n", (import_settings.find_chains) ? "yes" : "no"); @@ -57,6 +58,7 @@ int collada_import(bContext *C, ImportSettings *import_settings) int collada_export(bContext *C, ExportSettings *export_settings) { BlenderContext blender_context(C); + const Scene *scene = blender_context.get_scene(); ViewLayer *view_layer = blender_context.get_view_layer(); int includeFilter = OB_REL_NONE; @@ -72,7 +74,7 @@ int collada_export(bContext *C, ExportSettings *export_settings) */ eObjectSet objectSet = (export_settings->selected) ? OB_SET_SELECTED : OB_SET_ALL; export_settings->export_set = BKE_object_relational_superset( - view_layer, objectSet, (eObRelationTypes)includeFilter); + scene, view_layer, objectSet, (eObRelationTypes)includeFilter); int export_count = BLI_linklist_count(export_settings->export_set); diff --git a/source/blender/io/collada/collada_internal.cpp b/source/blender/io/collada/collada_internal.cpp index da9a4cd4a9b..60e8edaa3bc 100644 --- a/source/blender/io/collada/collada_internal.cpp +++ b/source/blender/io/collada/collada_internal.cpp @@ -47,7 +47,7 @@ UnitConverter::UnitSystem UnitConverter::isMetricSystem() float UnitConverter::getLinearMeter() { - return (float)unit.getLinearUnitMeter(); + return float(unit.getLinearUnitMeter()); } void UnitConverter::convertVector3(COLLADABU::Math::Vector3 &vec, float *v) @@ -153,7 +153,7 @@ void UnitConverter::calculate_scale(Scene &sce) * The COLLADA spec also allows additional chars for member access ('.'), these * must obviously be removed too, otherwise they would be heavily misinterpreted. */ -const unsigned char translate_start_name_map[256] = { +const uchar translate_start_name_map[256] = { 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, @@ -172,7 +172,7 @@ const unsigned char translate_start_name_map[256] = { 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, }; -const unsigned char translate_name_map[256] = { +const uchar translate_name_map[256] = { 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, @@ -212,16 +212,16 @@ std::string translate_id(const std::string &id) } std::string id_translated = id; - id_translated[0] = translate_start_name_map[(unsigned int)id_translated[0]]; - for (unsigned int i = 1; i < id_translated.size(); i++) { - id_translated[i] = translate_name_map[(unsigned int)id_translated[i]]; + id_translated[0] = translate_start_name_map[uint(id_translated[0])]; + for (uint i = 1; i < id_translated.size(); i++) { + id_translated[i] = translate_name_map[uint(id_translated[i])]; } /* It's so much workload now, the if () should speed up things. */ if (id_translated != id) { /* Search duplicates. */ map_string_list::iterator iter = global_id_map.find(id_translated); if (iter != global_id_map.end()) { - unsigned int i = 0; + uint i = 0; bool found = false; for (i = 0; i < iter->second.size(); i++) { if (id == iter->second[i]) { diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index 75842734b08..22a73cd7db2 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -66,7 +66,7 @@ #include "ExportSettings.h" #include "collada_utils.h" -float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index) +float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, uint index) { if (index >= array.getValuesCount()) { return 0.0f; @@ -197,6 +197,7 @@ Object *bc_add_object(Main *bmain, Scene *scene, ViewLayer *view_layer, int type LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); BKE_collection_object_add(bmain, layer_collection->collection, ob); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, ob); /* TODO: is setting active needed? */ BKE_view_layer_base_select_and_set_active(view_layer, base); @@ -709,13 +710,13 @@ float bc_get_property(Bone *bone, std::string key, float def) if (property) { switch (property->type) { case IDP_INT: - result = (float)(IDP_Int(property)); + result = float(IDP_Int(property)); break; case IDP_FLOAT: - result = (float)(IDP_Float(property)); + result = float(IDP_Float(property)); break; case IDP_DOUBLE: - result = (float)(IDP_Double(property)); + result = float(IDP_Double(property)); break; default: result = def; @@ -1007,9 +1008,9 @@ void bc_create_restpose_mat(BCExportSettings &export_settings, void bc_sanitize_v3(float v[3], int precision) { for (int i = 0; i < 3; i++) { - double val = (double)v[i]; + double val = double(v[i]); val = double_round(val, precision); - v[i] = (float)val; + v[i] = float(val); } } @@ -1108,7 +1109,7 @@ static std::string bc_get_uvlayer_name(Mesh *me, int layer) static bNodeTree *prepare_material_nodetree(Material *ma) { if (ma->nodetree == nullptr) { - ma->nodetree = ntreeAddTree(nullptr, "Shader Nodetree", "ShaderNodeTree"); + ntreeAddTreeEmbedded(nullptr, &ma->id, "Shader Nodetree", "ShaderNodeTree"); ma->use_nodes = true; } return ma->nodetree; @@ -1338,7 +1339,7 @@ bool bc_get_float_from_shader(bNode *shader, double &val, std::string nodeid) bNodeSocket *socket = nodeFindSocket(shader, SOCK_IN, nodeid.c_str()); if (socket) { bNodeSocketValueFloat *ref = (bNodeSocketValueFloat *)socket->default_value; - val = (double)ref->value; + val = double(ref->value); return true; } return false; diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc index 1fbddc45964..03c1ba94d94 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc @@ -272,10 +272,11 @@ void AbstractHierarchyIterator::export_graph_construct() ExportGraph::key_type root_node_id = ObjectIdentifier::for_real_object(nullptr); export_graph_[root_node_id] = ExportChildren(); - DEG_OBJECT_ITER_BEGIN (depsgraph_, - object, - DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) { + DEGObjectIterSettings deg_iter_settings{}; + deg_iter_settings.depsgraph = depsgraph_; + deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET; + DEG_OBJECT_ITER_BEGIN (°_iter_settings, object) { /* Non-instanced objects always have their object-parent as export-parent. */ const bool weak_export = mark_as_weak_export(object); visit_object(object, object->parent, weak_export); diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.cc b/source/blender/io/gpencil/intern/gpencil_io_base.cc index 6db3eccedbe..b9d7b6719b1 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_base.cc @@ -20,6 +20,7 @@ #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_scene.h" @@ -127,13 +128,15 @@ void GpencilIO::prepare_camera_params(Scene *scene, const GpencilIOParams *ipara void GpencilIO::create_object_list() { + Scene *scene = CTX_data_scene(params_.C); ViewLayer *view_layer = CTX_data_view_layer(params_.C); float3 camera_z_axis; copy_v3_v3(camera_z_axis, rv3d_->viewinv[2]); ob_list_.clear(); - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + BKE_view_layer_synced_ensure(scene, view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { Object *object = base->object; if (object->type != OB_GPENCIL) { @@ -224,16 +227,16 @@ float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co) float2 r_co; mul_v2_project_m4_v3(&r_co.x, persmat_, &parent_co.x); - r_co.x = (r_co.x + 1.0f) / 2.0f * (float)render_x_; - r_co.y = (r_co.y + 1.0f) / 2.0f * (float)render_y_; + r_co.x = (r_co.x + 1.0f) / 2.0f * float(render_x_); + r_co.y = (r_co.y + 1.0f) / 2.0f * float(render_y_); /* Invert X axis. */ if (invert_axis_[0]) { - r_co.x = (float)render_x_ - r_co.x; + r_co.x = float(render_x_) - r_co.x; } /* Invert Y axis. */ if (invert_axis_[1]) { - r_co.y = (float)render_y_ - r_co.y; + r_co.y = float(render_y_) - r_co.y; } return r_co; @@ -241,7 +244,7 @@ float2 GpencilIO::gpencil_3D_point_to_render_space(const float3 co) float2 GpencilIO::gpencil_3D_point_to_2D(const float3 co) { - const bool is_camera = (bool)(rv3d_->persp == RV3D_CAMOB); + const bool is_camera = bool(rv3d_->persp == RV3D_CAMOB); if (is_camera) { return gpencil_3D_point_to_render_space(co); } @@ -257,7 +260,7 @@ float GpencilIO::stroke_point_radius_get(bGPDlayer *gpl, bGPDstroke *gps) /* Radius. */ bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view( - rv3d_, gpd_, gpl, gps, 3, diff_mat_.values); + rv3d_->viewmat, gpd_, gpl, gps, 3, diff_mat_.values, 0.0f); pt = &gps_perimeter->points[0]; const float2 screen_ex = gpencil_3D_point_to_2D(&pt->x); @@ -289,9 +292,9 @@ void GpencilIO::prepare_stroke_export_colors(Object *ob, bGPDstroke *gps) avg_opacity_ += pt.strength; } - mul_v4_v4fl(avg_color, avg_color, 1.0f / (float)gps->totpoints); + mul_v4_v4fl(avg_color, avg_color, 1.0f / float(gps->totpoints)); interp_v3_v3v3(stroke_color_, stroke_color_, avg_color, avg_color[3]); - avg_opacity_ /= (float)gps->totpoints; + avg_opacity_ /= float(gps->totpoints); /* Fill color. */ copy_v4_v4(fill_color_, gp_style->fill_rgba); diff --git a/source/blender/io/gpencil/intern/gpencil_io_base.hh b/source/blender/io/gpencil/intern/gpencil_io_base.hh index 4987ab34ffc..f712ed839d9 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_base.hh +++ b/source/blender/io/gpencil/intern/gpencil_io_base.hh @@ -70,7 +70,7 @@ class GpencilIO { float stroke_color_[4], fill_color_[4]; /* Geometry functions. */ - /** Convert to screenspace. */ + /** Convert to screen-space. */ bool gpencil_3D_point_to_screen_space(const float3 co, float2 &r_co); /** Convert to render space. */ float2 gpencil_3D_point_to_render_space(const float3 co); diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc index 700d91791a8..ddd72f816b0 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_pdf.cc @@ -37,7 +37,7 @@ namespace blender ::io ::gpencil { -static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void *UNUSED(user_data)) +static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void * /*user_data*/) { printf("ERROR: error_no=%04X, detail_no=%u\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no); } @@ -192,7 +192,7 @@ void GpencilExporterPDF::export_gpencil_layers() } else { bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view( - rv3d_, gpd_, gpl, gps_duplicate, 3, diff_mat_.values); + rv3d_->viewmat, gpd_, gpl, gps_duplicate, 3, diff_mat_.values, 0.0f); /* Sample stroke. */ if (params_.stroke_sample > 0.0f) { diff --git a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc index 2601ad05ea7..58f12e9b8b1 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_export_svg.cc @@ -217,7 +217,7 @@ void GpencilExporterSVG::export_gpencil_layers() } else { bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view( - rv3d_, gpd_, gpl, gps_duplicate, 3, diff_mat_.values); + rv3d_->viewmat, gpd_, gpl, gps_duplicate, 3, diff_mat_.values, 0.0f); /* Sample stroke. */ if (params_.stroke_sample > 0.0f) { diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_base.cc b/source/blender/io/gpencil/intern/gpencil_io_import_base.cc index 6d4439243fd..f6d02d36a17 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_import_base.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_import_base.cc @@ -31,7 +31,7 @@ Object *GpencilImporter::create_object() const float *cur_loc = scene_->cursor.location; const float rot[3] = {0.0f}; ushort local_view_bits = (params_.v3d && params_.v3d->localvd) ? params_.v3d->local_view_uuid : - (ushort)0; + ushort(0); Object *ob_gpencil = ED_object_add_type(params_.C, OB_GPENCIL, diff --git a/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc b/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc index 06460a1beba..23c80900659 100644 --- a/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc +++ b/source/blender/io/gpencil/intern/gpencil_io_import_svg.cc @@ -93,8 +93,8 @@ bool GpencilImporterSVG::read() /* Check frame. */ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, cfra_, GP_GETFRAME_ADD_NEW); /* Create materials. */ - bool is_stroke = (bool)shape->stroke.type; - bool is_fill = (bool)shape->fill.type; + bool is_stroke = bool(shape->stroke.type); + bool is_fill = bool(shape->fill.type); if ((!is_stroke) && (!is_fill)) { is_stroke = true; } @@ -148,11 +148,11 @@ void GpencilImporterSVG::create_stroke(bGPdata *gpd, const int32_t mat_index, const float matrix[4][4]) { - const bool is_stroke = (bool)shape->stroke.type; - const bool is_fill = (bool)shape->fill.type; + const bool is_stroke = bool(shape->stroke.type); + const bool is_fill = bool(shape->fill.type); const int edges = params_.resolution; - const float step = 1.0f / (float)(edges - 1); + const float step = 1.0f / float(edges - 1); const int totpoints = (path->npts / 3) * params_.resolution; @@ -212,19 +212,19 @@ void GpencilImporterSVG::create_stroke(bGPdata *gpd, } /* Unpack internal NanoSVG color. */ -static void unpack_nano_color(const unsigned int pack, float r_col[4]) +static void unpack_nano_color(const uint pack, float r_col[4]) { - unsigned char rgb_u[4]; + uchar rgb_u[4]; rgb_u[0] = ((pack) >> 0) & 0xFF; rgb_u[1] = ((pack) >> 8) & 0xFF; rgb_u[2] = ((pack) >> 16) & 0xFF; rgb_u[3] = ((pack) >> 24) & 0xFF; - r_col[0] = (float)rgb_u[0] / 255.0f; - r_col[1] = (float)rgb_u[1] / 255.0f; - r_col[2] = (float)rgb_u[2] / 255.0f; - r_col[3] = (float)rgb_u[3] / 255.0f; + r_col[0] = float(rgb_u[0]) / 255.0f; + r_col[1] = float(rgb_u[1]) / 255.0f; + r_col[2] = float(rgb_u[2]) / 255.0f; + r_col[3] = float(rgb_u[3]) / 255.0f; } void GpencilImporterSVG::convert_color(const int32_t color, float r_linear_rgba[4]) diff --git a/source/blender/io/stl/importer/stl_import.cc b/source/blender/io/stl/importer/stl_import.cc index 097d14b038c..e5fde6658ab 100644 --- a/source/blender/io/stl/importer/stl_import.cc +++ b/source/blender/io/stl/importer/stl_import.cc @@ -99,11 +99,12 @@ void importer_main(Main *bmain, BKE_mesh_validate(mesh, verbose_validate, false); } - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); LayerCollection *lc = BKE_layer_collection_get_active(view_layer); Object *obj = BKE_object_add_only_object(bmain, OB_MESH, ob_name); BKE_mesh_assign_object(bmain, obj, mesh); BKE_collection_object_add(bmain, lc->collection, obj); + BKE_view_layer_synced_ensure(scene, view_layer); Base *base = BKE_view_layer_base_find(view_layer, obj); BKE_view_layer_base_select_and_set_active(view_layer, base); diff --git a/source/blender/io/stl/importer/stl_import_ascii_reader.cc b/source/blender/io/stl/importer/stl_import_ascii_reader.cc index 2edb3c6a114..6a976a2fd2c 100644 --- a/source/blender/io/stl/importer/stl_import_ascii_reader.cc +++ b/source/blender/io/stl/importer/stl_import_ascii_reader.cc @@ -97,7 +97,7 @@ class StringBuffer { start++; } fast_float::from_chars_result res = fast_float::from_chars(start, end, out); - if (res.ec == std::errc::invalid_argument || res.ec == std::errc::result_out_of_range) { + if (ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) { out = 0.0f; } start = const_cast<char *>(res.ptr); diff --git a/source/blender/io/stl/importer/stl_import_mesh.cc b/source/blender/io/stl/importer/stl_import_mesh.cc index b9ed441f0d9..de993cd2f27 100644 --- a/source/blender/io/stl/importer/stl_import_mesh.cc +++ b/source/blender/io/stl/importer/stl_import_mesh.cc @@ -76,27 +76,26 @@ Mesh *STLMeshHelper::to_mesh(Main *bmain, char *mesh_name) id_us_min(&mesh->id); mesh->totvert = verts_.size(); - mesh->mvert = static_cast<MVert *>( - CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CALLOC, nullptr, mesh->totvert)); + CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_SET_DEFAULT, nullptr, mesh->totvert); + MutableSpan<MVert> verts = mesh->verts_for_write(); for (int i = 0; i < mesh->totvert; i++) { - copy_v3_v3(mesh->mvert[i].co, verts_[i]); + copy_v3_v3(verts[i].co, verts_[i]); } mesh->totpoly = tris_.size(); mesh->totloop = tris_.size() * 3; - mesh->mpoly = static_cast<MPoly *>( - CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_CALLOC, nullptr, mesh->totpoly)); - mesh->mloop = static_cast<MLoop *>( - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, nullptr, mesh->totloop)); - + CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly); + CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, mesh->totloop); + MutableSpan<MPoly> polys = mesh->polys_for_write(); + MutableSpan<MLoop> loops = mesh->loops_for_write(); threading::parallel_for(tris_.index_range(), 2048, [&](IndexRange tris_range) { for (const int i : tris_range) { - mesh->mpoly[i].loopstart = 3 * i; - mesh->mpoly[i].totloop = 3; + polys[i].loopstart = 3 * i; + polys[i].totloop = 3; - mesh->mloop[3 * i].v = tris_[i].v1; - mesh->mloop[3 * i + 1].v = tris_[i].v2; - mesh->mloop[3 * i + 2].v = tris_[i].v3; + loops[3 * i].v = tris_[i].v1; + loops[3 * i + 1].v = tris_[i].v2; + loops[3 * i + 2].v = tris_[i].v3; } }); diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt index 73b7d875c2f..efa22b2add2 100644 --- a/source/blender/io/usd/CMakeLists.txt +++ b/source/blender/io/usd/CMakeLists.txt @@ -20,13 +20,14 @@ add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1) # add a USD_HAS_IMAGING define so code can dynamically detect this. # Cleanup of this variable is done at the end of the file since # test code further down uses it to add imaging tests. -FIND_FILE(USD_IMAGING_HEADERS +find_file( + USD_IMAGING_HEADERS NAMES capsuleAdapter.h PATHS - ${USD_INCLUDE_DIRS} + ${USD_INCLUDE_DIRS} PATH_SUFFIXES - pxr/usdImaging/usdImaging/ + pxr/usdImaging/usdImaging/ NO_DEFAULT_PATH ) @@ -164,7 +165,7 @@ if(WITH_GTESTS) tests/usd_tests_common.h ) if(USD_IMAGING_HEADERS) - LIST(APPEND TEST_SRC tests/usd_imaging_test.cc) + list(APPEND TEST_SRC tests/usd_imaging_test.cc) endif() set(TEST_INC diff --git a/source/blender/io/usd/intern/usd_capi_export.cc b/source/blender/io/usd/intern/usd_capi_export.cc index 0fbfa4c6d5d..6731412e158 100644 --- a/source/blender/io/usd/intern/usd_capi_export.cc +++ b/source/blender/io/usd/intern/usd_capi_export.cc @@ -96,8 +96,7 @@ static void export_startjob(void *customdata, } usd_stage->SetMetadata(pxr::UsdGeomTokens->upAxis, pxr::VtValue(pxr::UsdGeomTokens->z)); - usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit, - static_cast<double>(scene->unit.scale_length)); + usd_stage->SetMetadata(pxr::UsdGeomTokens->metersPerUnit, double(scene->unit.scale_length)); usd_stage->GetRootLayer()->SetDocumentation(std::string("Blender v") + BKE_blender_version_string()); @@ -120,7 +119,7 @@ static void export_startjob(void *customdata, } /* Update the scene for the next frame to render. */ - scene->r.cfra = static_cast<int>(frame); + scene->r.cfra = int(frame); scene->r.subframe = frame - scene->r.cfra; BKE_scene_graph_update_for_newframe(data->depsgraph); diff --git a/source/blender/io/usd/intern/usd_capi_import.cc b/source/blender/io/usd/intern/usd_capi_import.cc index c80faa5960e..cd50f41b9fb 100644 --- a/source/blender/io/usd/intern/usd_capi_import.cc +++ b/source/blender/io/usd/intern/usd_capi_import.cc @@ -230,7 +230,7 @@ static void import_startjob(void *customdata, short *stop, short *do_update, flo *data->do_update = true; *data->progress = 0.2f; - const float size = static_cast<float>(archive->readers().size()); + const float size = float(archive->readers().size()); size_t i = 0; /* Sort readers by name: when creating a lot of objects in Blender, @@ -310,9 +310,10 @@ static void import_endjob(void *customdata) else if (data->archive) { Base *base; LayerCollection *lc; + const Scene *scene = data->scene; ViewLayer *view_layer = data->view_layer; - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); lc = BKE_layer_collection_get_active(view_layer); @@ -332,6 +333,7 @@ static void import_endjob(void *customdata) /* Sync the collection, and do view layer operations. */ BKE_layer_collection_resync_allow(); BKE_main_collection_sync(data->bmain); + BKE_view_layer_synced_ensure(scene, view_layer); for (USDPrimReader *reader : data->archive->readers()) { if (!reader) { continue; diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc index 51261c4d91e..fbfda975055 100644 --- a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc +++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc @@ -141,7 +141,7 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_hair_writer(const Hierarch } AbstractHierarchyWriter *USDHierarchyIterator::create_particle_writer( - const HierarchyContext *UNUSED(context)) + const HierarchyContext * /*context*/) { return nullptr; } diff --git a/source/blender/io/usd/intern/usd_reader_camera.cc b/source/blender/io/usd/intern/usd_reader_camera.cc index 7f1e9fef89d..da51787e437 100644 --- a/source/blender/io/usd/intern/usd_reader_camera.cc +++ b/source/blender/io/usd/intern/usd_reader_camera.cc @@ -71,7 +71,7 @@ void USDCameraReader::read_object_data(Main *bmain, const double motionSampleTim bcam->clip_end = clippingRangeVal.UncheckedGet<pxr::GfVec2f>()[1]; bcam->dof.focus_distance = focalDistanceVal.Get<float>(); - bcam->dof.aperture_fstop = static_cast<float>(fstopVal.Get<float>()); + bcam->dof.aperture_fstop = float(fstopVal.Get<float>()); if (bcam->type == CAM_ORTHO) { bcam->ortho_scale = max_ff(verAp.Get<float>(), horAp.Get<float>()); diff --git a/source/blender/io/usd/intern/usd_reader_curve.cc b/source/blender/io/usd/intern/usd_reader_curve.cc index 0d3c2feb8f3..ca48f3c2391 100644 --- a/source/blender/io/usd/intern/usd_reader_curve.cc +++ b/source/blender/io/usd/intern/usd_reader_curve.cc @@ -139,9 +139,9 @@ void USDCurvesReader::read_curve_sample(Curve *cu, const double motionSampleTime BPoint *bp = nu->bp; for (int j = 0; j < nu->pntsu; j++, bp++, idx++) { - bp->vec[0] = (float)usdPoints[idx][0]; - bp->vec[1] = (float)usdPoints[idx][1]; - bp->vec[2] = (float)usdPoints[idx][2]; + bp->vec[0] = float(usdPoints[idx][0]); + bp->vec[1] = float(usdPoints[idx][1]); + bp->vec[2] = float(usdPoints[idx][2]); bp->vec[3] = weight; bp->f1 = SELECT; bp->weight = weight; diff --git a/source/blender/io/usd/intern/usd_reader_curve.h b/source/blender/io/usd/intern/usd_reader_curve.h index 1e9330b81f1..48fb2c5e2d1 100644 --- a/source/blender/io/usd/intern/usd_reader_curve.h +++ b/source/blender/io/usd/intern/usd_reader_curve.h @@ -27,7 +27,7 @@ class USDCurvesReader : public USDGeomReader { bool valid() const override { - return static_cast<bool>(curve_prim_); + return bool(curve_prim_); } void create_object(Main *bmain, double motionSampleTime) override; diff --git a/source/blender/io/usd/intern/usd_reader_light.cc b/source/blender/io/usd/intern/usd_reader_light.cc index 55b9557dfb5..7204ea91896 100644 --- a/source/blender/io/usd/intern/usd_reader_light.cc +++ b/source/blender/io/usd/intern/usd_reader_light.cc @@ -203,7 +203,7 @@ void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime if (pxr::UsdAttribute cone_angle_attr = shaping_api.GetShapingConeAngleAttr()) { float cone_angle = 0.0f; if (cone_angle_attr.Get(&cone_angle, motionSampleTime)) { - blight->spotsize = cone_angle * ((float)M_PI / 180.0f) * 2.0f; + blight->spotsize = cone_angle * (float(M_PI) / 180.0f) * 2.0f; } } @@ -226,7 +226,7 @@ void USDLightReader::read_object_data(Main *bmain, const double motionSampleTime if (pxr::UsdAttribute angle_attr = distant_light.GetAngleAttr()) { float angle = 0.0f; if (angle_attr.Get(&angle, motionSampleTime)) { - blight->sun_angle = angle * (float)M_PI / 180.0f; + blight->sun_angle = angle * float(M_PI) / 180.0f; } } } diff --git a/source/blender/io/usd/intern/usd_reader_material.cc b/source/blender/io/usd/intern/usd_reader_material.cc index f59b8be147e..d1af4553083 100644 --- a/source/blender/io/usd/intern/usd_reader_material.cc +++ b/source/blender/io/usd/intern/usd_reader_material.cc @@ -4,6 +4,7 @@ #include "usd_reader_material.h" #include "BKE_image.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_node.h" @@ -323,6 +324,7 @@ Material *USDMaterialReader::add_material(const pxr::UsdShadeMaterial &usd_mater /* Create the material. */ Material *mtl = BKE_material_add(bmain_, mtl_name.c_str()); + id_us_min(&mtl->id); /* Get the UsdPreviewSurface shader source for the material, * if there is one. */ @@ -351,8 +353,7 @@ void USDMaterialReader::import_usd_preview(Material *mtl, * and output shaders. */ /* Add the node tree. */ - bNodeTree *ntree = ntreeAddTree(nullptr, "Shader Nodetree", "ShaderNodeTree"); - mtl->nodetree = ntree; + bNodeTree *ntree = ntreeAddTreeEmbedded(nullptr, &mtl->id, "Shader Nodetree", "ShaderNodeTree"); mtl->use_nodes = true; /* Create the Principled BSDF shader node. */ @@ -561,7 +562,7 @@ void USDMaterialReader::follow_connection(const pxr::UsdShadeInput &usd_input, /* For now, only convert UsdUVTexture and UsdPrimvarReader_float2 inputs. */ if (shader_id == usdtokens::UsdUVTexture) { - if (strcmp(dest_socket_name, "Normal") == 0) { + if (STREQ(dest_socket_name, "Normal")) { /* The normal texture input requires creating a normal map node. */ float locx = 0.0f; diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 103bb0d0cef..77c79852141 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -6,6 +6,7 @@ #include "usd_reader_mesh.h" #include "usd_reader_material.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_main.h" #include "BKE_material.h" @@ -102,7 +103,7 @@ static Material *find_existing_material( return mat_iter->second; } /* We can't find the Blender material which was previously created for this USD - * material, which should never happen. */ + * material, which should never happen. */ BLI_assert_unreachable(); } } @@ -182,6 +183,9 @@ static void assign_materials(Main *bmain, std::cout << "WARNING: Couldn't assign material " << it->first << std::endl; } } + if (ob->totcol > 0) { + ob->actcol = 1; + } } } // namespace utils @@ -207,7 +211,8 @@ static void *add_customdata_cb(Mesh *mesh, const char *name, const int data_type /* Create a new layer. */ numloops = mesh->totloop; - cd_ptr = CustomData_add_layer_named(loopdata, cd_data_type, CD_DEFAULT, nullptr, numloops, name); + cd_ptr = CustomData_add_layer_named( + loopdata, cd_data_type, CD_SET_DEFAULT, nullptr, numloops, name); return cd_ptr; } @@ -243,11 +248,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime) is_initial_load_ = false; if (read_mesh != mesh) { - /* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */ - /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ - uint16_t autosmooth = (read_mesh->flag & ME_AUTOSMOOTH); - BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_, &CD_MASK_MESH, true); - mesh->flag |= autosmooth; + BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_); } readFaceSetsSample(bmain, mesh, motionSampleTime); @@ -274,7 +275,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime) bool USDMeshReader::valid() const { - return static_cast<bool>(mesh_prim_); + return bool(mesh_prim_); } bool USDMeshReader::topology_changed(const Mesh *existing_mesh, const double motionSampleTime) @@ -307,18 +308,17 @@ bool USDMeshReader::topology_changed(const Mesh *existing_mesh, const double mot void USDMeshReader::read_mpolys(Mesh *mesh) { - MPoly *mpolys = mesh->mpoly; - MLoop *mloops = mesh->mloop; + MutableSpan<MPoly> polys = mesh->polys_for_write(); + MutableSpan<MLoop> loops = mesh->loops_for_write(); int loop_index = 0; for (int i = 0; i < face_counts_.size(); i++) { const int face_size = face_counts_[i]; - MPoly &poly = mpolys[i]; + MPoly &poly = polys[i]; poly.loopstart = loop_index; poly.totloop = face_size; - poly.mat_nr = 0; /* Polygons are always assumed to be smooth-shaded. If the mesh should be flat-shaded, * this is encoded in custom loop normals. */ @@ -327,12 +327,12 @@ void USDMeshReader::read_mpolys(Mesh *mesh) if (is_left_handed_) { int loop_end_index = loop_index + (face_size - 1); for (int f = 0; f < face_size; ++f, ++loop_index) { - mloops[loop_index].v = face_indices_[loop_end_index - f]; + loops[loop_index].v = face_indices_[loop_end_index - f]; } } else { for (int f = 0; f < face_size; ++f, ++loop_index) { - mloops[loop_index].v = face_indices_[loop_index]; + loops[loop_index].v = face_indices_[loop_index]; } } } @@ -342,9 +342,9 @@ void USDMeshReader::read_mpolys(Mesh *mesh) void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bool load_uvs) { - unsigned int loop_index = 0; - unsigned int rev_loop_index = 0; - unsigned int uv_index = 0; + uint loop_index = 0; + uint rev_loop_index = 0; + uint uv_index = 0; const CustomData *ldata = &mesh->ldata; @@ -396,6 +396,7 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo } } + const Span<MLoop> loops = mesh->loops(); for (int i = 0; i < face_counts_.size(); i++) { const int face_size = face_counts_[i]; @@ -421,9 +422,9 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo const UVSample &sample = uv_primvars[layer_idx]; - if (!(ELEM(sample.interpolation, - pxr::UsdGeomTokens->faceVarying, - pxr::UsdGeomTokens->vertex))) { + if (!ELEM(sample.interpolation, + pxr::UsdGeomTokens->faceVarying, + pxr::UsdGeomTokens->vertex)) { std::cerr << "WARNING: unexpected interpolation type " << sample.interpolation << " for uv " << layer->name << std::endl; continue; @@ -431,7 +432,7 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo /* For Vertex interpolation, use the vertex index. */ int usd_uv_index = sample.interpolation == pxr::UsdGeomTokens->vertex ? - mesh->mloop[loop_index].v : + loops[loop_index].v : loop_index; if (usd_uv_index >= sample.uvs.size()) { @@ -511,24 +512,23 @@ void USDMeshReader::read_colors(Mesh *mesh, const double motionSampleTime) MLoopCol *colors = static_cast<MLoopCol *>(cd_ptr); - mesh->mloopcol = colors; - - MPoly *poly = mesh->mpoly; - - for (int i = 0, e = mesh->totpoly; i < e; ++i, ++poly) { - for (int j = 0; j < poly->totloop; ++j) { - int loop_index = poly->loopstart + j; + const Span<MPoly> polys = mesh->polys(); + const Span<MLoop> loops = mesh->loops(); + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; + for (int j = 0; j < poly.totloop; ++j) { + int loop_index = poly.loopstart + j; /* Default for constant varying interpolation. */ int usd_index = 0; if (interp == pxr::UsdGeomTokens->vertex) { - usd_index = mesh->mloop[loop_index].v; + usd_index = loops[loop_index].v; } else if (interp == pxr::UsdGeomTokens->faceVarying) { - usd_index = poly->loopstart; + usd_index = poly.loopstart; if (is_left_handed_) { - usd_index += poly->totloop - 1 - j; + usd_index += poly.totloop - 1 - j; } else { usd_index += j; @@ -576,7 +576,7 @@ void USDMeshReader::read_vertex_creases(Mesh *mesh, const double motionSampleTim } float *creases = static_cast<float *>( - CustomData_add_layer(&mesh->vdata, CD_CREASE, CD_DEFAULT, nullptr, mesh->totvert)); + CustomData_add_layer(&mesh->vdata, CD_CREASE, CD_SET_DEFAULT, nullptr, mesh->totvert)); for (size_t i = 0; i < corner_indices.size(); i++) { creases[corner_indices[i]] = corner_sharpnesses[i]; @@ -601,7 +601,7 @@ void USDMeshReader::process_normals_vertex_varying(Mesh *mesh) MutableSpan vert_normals{(float3 *)BKE_mesh_vertex_normals_for_write(mesh), mesh->totvert}; BLI_STATIC_ASSERT(sizeof(normals_[0]) == sizeof(float3), "Expected float3 normals size"); - vert_normals.copy_from({(float3 *)normals_.data(), static_cast<int64_t>(normals_.size())}); + vert_normals.copy_from({(float3 *)normals_.data(), int64_t(normals_.size())}); BKE_mesh_vertex_normals_clear_dirty(mesh); } @@ -626,15 +626,15 @@ void USDMeshReader::process_normals_face_varying(Mesh *mesh) float(*lnors)[3] = static_cast<float(*)[3]>( MEM_malloc_arrayN(loop_count, sizeof(float[3]), "USD::FaceNormals")); - MPoly *mpoly = mesh->mpoly; - - for (int i = 0, e = mesh->totpoly; i < e; ++i, ++mpoly) { - for (int j = 0; j < mpoly->totloop; j++) { - int blender_index = mpoly->loopstart + j; + const Span<MPoly> polys = mesh->polys(); + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; + for (int j = 0; j < poly.totloop; j++) { + int blender_index = poly.loopstart + j; - int usd_index = mpoly->loopstart; + int usd_index = poly.loopstart; if (is_left_handed_) { - usd_index += mpoly->totloop - 1 - j; + usd_index += poly.totloop - 1 - j; } else { usd_index += j; @@ -667,12 +667,11 @@ void USDMeshReader::process_normals_uniform(Mesh *mesh) float(*lnors)[3] = static_cast<float(*)[3]>( MEM_malloc_arrayN(mesh->totloop, sizeof(float[3]), "USD::FaceNormals")); - MPoly *mpoly = mesh->mpoly; - - for (int i = 0, e = mesh->totpoly; i < e; ++i, ++mpoly) { - - for (int j = 0; j < mpoly->totloop; j++) { - int loop_index = mpoly->loopstart + j; + const Span<MPoly> polys = mesh->polys(); + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; + for (int j = 0; j < poly.totloop; j++) { + int loop_index = poly.loopstart + j; lnors[loop_index][0] = normals_[i][0]; lnors[loop_index][1] = normals_[i][1]; lnors[loop_index][2] = normals_[i][2]; @@ -695,8 +694,9 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings, * in code that expect this data to be there. */ if (new_mesh || (settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { + MutableSpan<MVert> verts = mesh->verts_for_write(); for (int i = 0; i < positions_.size(); i++) { - MVert &mvert = mesh->mvert[i]; + MVert &mvert = verts[i]; mvert.co[0] = positions_[i][0]; mvert.co[1] = positions_[i][1]; mvert.co[2] = positions_[i][2]; @@ -734,10 +734,9 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings, } } -void USDMeshReader::assign_facesets_to_mpoly(double motionSampleTime, - MPoly *mpoly, - const int /* totpoly */, - std::map<pxr::SdfPath, int> *r_mat_map) +void USDMeshReader::assign_facesets_to_material_indices(double motionSampleTime, + MutableSpan<int> material_indices, + std::map<pxr::SdfPath, int> *r_mat_map) { if (r_mat_map == nullptr) { return; @@ -777,9 +776,8 @@ void USDMeshReader::assign_facesets_to_mpoly(double motionSampleTime, pxr::VtIntArray indices; indicesAttribute.Get(&indices, motionSampleTime); - for (int i = 0; i < indices.size(); i++) { - MPoly &poly = mpoly[indices[i]]; - poly.mat_nr = mat_idx; + for (const int i : indices) { + material_indices[i] = mat_idx; } } } @@ -804,7 +802,12 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot } std::map<pxr::SdfPath, int> mat_map; - assign_facesets_to_mpoly(motionSampleTime, mesh->mpoly, mesh->totpoly, &mat_map); + + bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); + bke::SpanAttributeWriter<int> material_indices = + attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE); + this->assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map); + material_indices.finish(); /* Build material name map if it's not built yet. */ if (this->settings_->mat_name_to_mat.empty()) { utils::build_mat_map(bmain, &this->settings_->mat_name_to_mat); @@ -862,7 +865,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, pxr::TfToken interp = p.GetInterpolation(); - if (!(ELEM(interp, pxr::UsdGeomTokens->faceVarying, pxr::UsdGeomTokens->vertex))) { + if (!ELEM(interp, pxr::UsdGeomTokens->faceVarying, pxr::UsdGeomTokens->vertex)) { continue; } @@ -896,8 +899,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, existing_mesh, positions_.size(), 0, 0, face_indices_.size(), face_counts_.size()); for (pxr::TfToken token : uv_tokens) { - void *cd_ptr = add_customdata_cb(active_mesh, token.GetText(), CD_MLOOPUV); - active_mesh->mloopuv = static_cast<MLoopUV *>(cd_ptr); + add_customdata_cb(active_mesh, token.GetText(), CD_MLOOPUV); } } @@ -907,10 +909,14 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, /* 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 * USD are still valid now. */ - size_t num_polys = active_mesh->totpoly; - if (num_polys > 0 && import_params_.import_materials) { + MutableSpan<MPoly> polys = active_mesh->polys_for_write(); + if (!polys.is_empty() && import_params_.import_materials) { std::map<pxr::SdfPath, int> mat_map; - assign_facesets_to_mpoly(motionSampleTime, active_mesh->mpoly, num_polys, &mat_map); + bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write(); + bke::SpanAttributeWriter<int> material_indices = + attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE); + assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map); + material_indices.finish(); } } diff --git a/source/blender/io/usd/intern/usd_reader_mesh.h b/source/blender/io/usd/intern/usd_reader_mesh.h index 5e33ce8b5e8..181fd5ebf79 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.h +++ b/source/blender/io/usd/intern/usd_reader_mesh.h @@ -3,13 +3,13 @@ * Modifications Copyright 2021 Tangent Animation and. NVIDIA Corporation. All rights reserved. */ #pragma once +#include "BLI_span.hh" + #include "usd.h" #include "usd_reader_geom.h" #include "pxr/usd/usdGeom/mesh.h" -struct MPoly; - namespace blender::io::usd { class USDMeshReader : public USDGeomReader { @@ -61,10 +61,9 @@ class USDMeshReader : public USDGeomReader { /** Set USD uniform (per-face) normals as Blender loop normals. */ void process_normals_uniform(Mesh *mesh); void readFaceSetsSample(Main *bmain, Mesh *mesh, double motionSampleTime); - void assign_facesets_to_mpoly(double motionSampleTime, - struct MPoly *mpoly, - int totpoly, - std::map<pxr::SdfPath, int> *r_mat_map); + void assign_facesets_to_material_indices(double motionSampleTime, + MutableSpan<int> material_indices, + std::map<pxr::SdfPath, int> *r_mat_map); void read_mpolys(Mesh *mesh); void read_uvs(Mesh *mesh, double motionSampleTime, bool load_uvs = false); diff --git a/source/blender/io/usd/intern/usd_reader_nurbs.cc b/source/blender/io/usd/intern/usd_reader_nurbs.cc index d0a5dc1c4b4..0a7058fb100 100644 --- a/source/blender/io/usd/intern/usd_reader_nurbs.cc +++ b/source/blender/io/usd/intern/usd_reader_nurbs.cc @@ -33,7 +33,7 @@ static bool set_knots(const pxr::VtDoubleArray &knots, float *&nu_knots) nu_knots = static_cast<float *>(MEM_callocN(num_knots * sizeof(float), __func__)); for (size_t i = 0; i < num_knots; i++) { - nu_knots[i] = (float)knots[i]; + nu_knots[i] = float(knots[i]); } return true; @@ -117,7 +117,7 @@ void USDNurbsReader::read_curve_sample(Curve *cu, const double motionSampleTime) nu->pntsv = 1; if (i < orders.size()) { - nu->orderu = static_cast<short>(orders[i]); + nu->orderu = short(orders[i]); } else { nu->orderu = 4; @@ -141,9 +141,9 @@ void USDNurbsReader::read_curve_sample(Curve *cu, const double motionSampleTime) BPoint *bp = nu->bp; for (int j = 0; j < nu->pntsu; j++, bp++, idx++) { - bp->vec[0] = (float)usdPoints[idx][0]; - bp->vec[1] = (float)usdPoints[idx][1]; - bp->vec[2] = (float)usdPoints[idx][2]; + bp->vec[0] = float(usdPoints[idx][0]); + bp->vec[1] = float(usdPoints[idx][1]); + bp->vec[2] = float(usdPoints[idx][2]); bp->vec[3] = weight; bp->f1 = SELECT; bp->weight = weight; diff --git a/source/blender/io/usd/intern/usd_reader_nurbs.h b/source/blender/io/usd/intern/usd_reader_nurbs.h index a5441aad3cf..aa3940dc540 100644 --- a/source/blender/io/usd/intern/usd_reader_nurbs.h +++ b/source/blender/io/usd/intern/usd_reader_nurbs.h @@ -27,7 +27,7 @@ class USDNurbsReader : public USDGeomReader { bool valid() const override { - return static_cast<bool>(curve_prim_); + return bool(curve_prim_); } void create_object(Main *bmain, double motionSampleTime) override; diff --git a/source/blender/io/usd/intern/usd_reader_volume.cc b/source/blender/io/usd/intern/usd_reader_volume.cc index 13044de5002..fc25dda53b9 100644 --- a/source/blender/io/usd/intern/usd_reader_volume.cc +++ b/source/blender/io/usd/intern/usd_reader_volume.cc @@ -65,10 +65,10 @@ void USDVolumeReader::read_object_data(Main *bmain, const double motionSampleTim filepathAttr.GetTimeSamples(&filePathTimes); if (!filePathTimes.empty()) { - int start = static_cast<int>(filePathTimes.front()); - int end = static_cast<int>(filePathTimes.back()); + int start = int(filePathTimes.front()); + int end = int(filePathTimes.back()); - volume->is_sequence = static_cast<char>(true); + volume->is_sequence = char(true); volume->frame_start = start; volume->frame_duration = (end - start) + 1; } diff --git a/source/blender/io/usd/intern/usd_reader_volume.h b/source/blender/io/usd/intern/usd_reader_volume.h index 350fae6ada0..923c3d140c9 100644 --- a/source/blender/io/usd/intern/usd_reader_volume.h +++ b/source/blender/io/usd/intern/usd_reader_volume.h @@ -23,7 +23,7 @@ class USDVolumeReader : public USDXformReader { bool valid() const override { - return static_cast<bool>(volume_); + return bool(volume_); } void create_object(Main *bmain, double motionSampleTime) override; diff --git a/source/blender/io/usd/intern/usd_writer_hair.cc b/source/blender/io/usd/intern/usd_writer_hair.cc index 478a9e26274..8ec1447b505 100644 --- a/source/blender/io/usd/intern/usd_writer_hair.cc +++ b/source/blender/io/usd/intern/usd_writer_hair.cc @@ -64,7 +64,7 @@ void USDHairWriter::do_write(HierarchyContext &context) } } -bool USDHairWriter::check_is_animated(const HierarchyContext &UNUSED(context)) const +bool USDHairWriter::check_is_animated(const HierarchyContext & /*context*/) const { return true; } diff --git a/source/blender/io/usd/intern/usd_writer_material.cc b/source/blender/io/usd/intern/usd_writer_material.cc index 6862f3835cf..c195bf0e0bd 100644 --- a/source/blender/io/usd/intern/usd_writer_material.cc +++ b/source/blender/io/usd/intern/usd_writer_material.cc @@ -455,7 +455,7 @@ static bNode *traverse_channel(bNodeSocket *input, const short target_type) static bNode *find_bsdf_node(Material *material) { LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) { - if (node->type == SH_NODE_BSDF_PRINCIPLED || node->type == SH_NODE_BSDF_DIFFUSE) { + if (ELEM(node->type, SH_NODE_BSDF_PRINCIPLED, SH_NODE_BSDF_DIFFUSE)) { return node; } } @@ -707,7 +707,7 @@ static void export_texture(bNode *node, const pxr::UsdStageRefPtr stage, const bool allow_overwrite) { - if (node->type != SH_NODE_TEX_IMAGE && node->type != SH_NODE_TEX_ENVIRONMENT) { + if (!ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) { return; } diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index b76f74cfd3d..e949bafe517 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -11,6 +11,7 @@ #include "BLI_math_vector.h" #include "BKE_attribute.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_lib_id.h" #include "BKE_material.h" @@ -245,8 +246,8 @@ static void get_vertices(const Mesh *mesh, USDMeshData &usd_mesh_data) { usd_mesh_data.points.reserve(mesh->totvert); - const MVert *verts = mesh->mvert; - for (int i = 0; i < mesh->totvert; ++i) { + const Span<MVert> verts = mesh->verts(); + for (const int i : verts.index_range()) { usd_mesh_data.points.push_back(pxr::GfVec3f(verts[i].co)); } } @@ -255,46 +256,49 @@ static void get_loops_polys(const Mesh *mesh, USDMeshData &usd_mesh_data) { /* Only construct face groups (a.k.a. geometry subsets) when we need them for material * assignments. */ - bool construct_face_groups = mesh->totcol > 1; + const bke::AttributeAccessor attributes = mesh->attributes(); + const VArray<int> material_indices = attributes.lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); + if (!material_indices.is_single() && mesh->totcol > 1) { + const VArraySpan<int> indices_span(material_indices); + for (const int i : indices_span.index_range()) { + usd_mesh_data.face_groups[indices_span[i]].push_back(i); + } + } usd_mesh_data.face_vertex_counts.reserve(mesh->totpoly); usd_mesh_data.face_indices.reserve(mesh->totloop); - MLoop *mloop = mesh->mloop; - MPoly *mpoly = mesh->mpoly; - for (int i = 0; i < mesh->totpoly; ++i, ++mpoly) { - MLoop *loop = mloop + mpoly->loopstart; - usd_mesh_data.face_vertex_counts.push_back(mpoly->totloop); - for (int j = 0; j < mpoly->totloop; ++j, ++loop) { - usd_mesh_data.face_indices.push_back(loop->v); - } + const Span<MPoly> polys = mesh->polys(); + const Span<MLoop> loops = mesh->loops(); - if (construct_face_groups) { - usd_mesh_data.face_groups[mpoly->mat_nr].push_back(i); + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; + usd_mesh_data.face_vertex_counts.push_back(poly.totloop); + for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { + usd_mesh_data.face_indices.push_back(loop.v); } } } static void get_edge_creases(const Mesh *mesh, USDMeshData &usd_mesh_data) { - const float factor = 1.0f / 255.0f; + const float *creases = static_cast<const float *>(CustomData_get_layer(&mesh->edata, CD_CREASE)); + if (!creases) { + return; + } - MEdge *edge = mesh->medge; - float sharpness; - for (int edge_idx = 0, totedge = mesh->totedge; edge_idx < totedge; ++edge_idx, ++edge) { - if (edge->crease == 0) { + const Span<MEdge> edges = mesh->edges(); + for (const int i : edges.index_range()) { + const float crease = creases[i]; + if (crease == 0.0f) { continue; } - if (edge->crease == 255) { - sharpness = pxr::UsdGeomMesh::SHARPNESS_INFINITE; - } - else { - sharpness = static_cast<float>(edge->crease) * factor; - } + const float sharpness = crease >= 1.0f ? pxr::UsdGeomMesh::SHARPNESS_INFINITE : crease; - usd_mesh_data.crease_vertex_indices.push_back(edge->v1); - usd_mesh_data.crease_vertex_indices.push_back(edge->v2); + usd_mesh_data.crease_vertex_indices.push_back(edges[i].v1); + usd_mesh_data.crease_vertex_indices.push_back(edges[i].v2); usd_mesh_data.crease_lengths.push_back(2); usd_mesh_data.crease_sharpnesses.push_back(sharpness); } @@ -392,6 +396,8 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ { pxr::UsdTimeCode timecode = get_export_time_code(); const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL)); + const Span<MPoly> polys = mesh->polys(); + const Span<MLoop> loops = mesh->loops(); pxr::VtVec3fArray loop_normals; loop_normals.reserve(mesh->totloop); @@ -406,21 +412,20 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ /* Compute the loop normals based on the 'smooth' flag. */ const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh); const float(*face_normals)[3] = BKE_mesh_poly_normals_ensure(mesh); - MPoly *mpoly = mesh->mpoly; - for (int poly_idx = 0, totpoly = mesh->totpoly; poly_idx < totpoly; ++poly_idx, ++mpoly) { - MLoop *mloop = mesh->mloop + mpoly->loopstart; + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; - if ((mpoly->flag & ME_SMOOTH) == 0) { + if ((poly.flag & ME_SMOOTH) == 0) { /* Flat shaded, use common normal for all verts. */ - pxr::GfVec3f pxr_normal(face_normals[poly_idx]); - for (int loop_idx = 0; loop_idx < mpoly->totloop; ++loop_idx) { + pxr::GfVec3f pxr_normal(face_normals[i]); + for (int loop_idx = 0; loop_idx < poly.totloop; ++loop_idx) { loop_normals.push_back(pxr_normal); } } else { /* Smooth shaded, use individual vert normals. */ - for (int loop_idx = 0; loop_idx < mpoly->totloop; ++loop_idx, ++mloop) { - loop_normals.push_back(pxr::GfVec3f(vert_normals[mloop->v])); + for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) { + loop_normals.push_back(pxr::GfVec3f(vert_normals[loop.v])); } } } diff --git a/source/blender/io/usd/intern/usd_writer_volume.cc b/source/blender/io/usd/intern/usd_writer_volume.cc index 6300e5c657c..8cc3c65ee70 100644 --- a/source/blender/io/usd/intern/usd_writer_volume.cc +++ b/source/blender/io/usd/intern/usd_writer_volume.cc @@ -145,14 +145,14 @@ std::optional<std::string> USDVolumeWriter::construct_vdb_file_path(const Volume BLI_strncpy(vdb_file_name, volume->id.name + 2, FILE_MAXFILE); const pxr::UsdTimeCode timecode = get_export_time_code(); if (!timecode.IsDefault()) { - const int frame = (int)timecode.GetValue(); + const int frame = int(timecode.GetValue()); const int num_frame_digits = frame == 0 ? 1 : integer_digits_i(abs(frame)); BLI_path_frame(vdb_file_name, frame, num_frame_digits); } strcat(vdb_file_name, ".vdb"); char vdb_file_path[FILE_MAX]; - BLI_path_join(vdb_file_path, sizeof(vdb_file_path), vdb_directory_path, vdb_file_name, NULL); + BLI_path_join(vdb_file_path, sizeof(vdb_file_path), vdb_directory_path, vdb_file_name, nullptr); return vdb_file_path; } diff --git a/source/blender/io/usd/usd.h b/source/blender/io/usd/usd.h index ebf37df27eb..98d544df251 100644 --- a/source/blender/io/usd/usd.h +++ b/source/blender/io/usd/usd.h @@ -52,7 +52,7 @@ struct USDImportParams { bool import_materials; bool import_meshes; bool import_volumes; - char *prim_path_mask; + char prim_path_mask[1024]; bool import_subdiv; bool import_instance_proxies; bool create_collection; diff --git a/source/blender/io/wavefront_obj/IO_wavefront_obj.h b/source/blender/io/wavefront_obj/IO_wavefront_obj.h index 847b02d3fd1..0a92bbca477 100644 --- a/source/blender/io/wavefront_obj/IO_wavefront_obj.h +++ b/source/blender/io/wavefront_obj/IO_wavefront_obj.h @@ -16,8 +16,6 @@ extern "C" { #endif -static const int TOTAL_AXES = 3; - struct OBJExportParams { /** Full path to the destination .OBJ file. */ char filepath[FILE_MAX]; @@ -50,18 +48,15 @@ struct OBJExportParams { bool export_triangulated_mesh; bool export_curves_as_nurbs; ePathReferenceMode path_mode; + bool export_pbr_extensions; /* Grouping options. */ bool export_object_groups; bool export_material_groups; bool export_vertex_groups; - /** - * Calculate smooth groups from sharp edges. - */ + /* Calculate smooth groups from sharp edges. */ bool export_smooth_groups; - /** - * Create bitflags instead of the default "0"/"1" group IDs. - */ + /* Create bitflags instead of the default "0"/"1" group IDs. */ bool smooth_groups_bitflags; }; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc index 53aa80700cc..95be927589e 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc @@ -44,7 +44,7 @@ static const char *DEFORM_GROUP_DISABLED = "off"; * So an empty material name is written. */ static const char *MATERIAL_GROUP_DISABLED = ""; -void OBJWriter::write_vert_uv_normal_indices(FormatHandler<eFileType::OBJ> &fh, +void OBJWriter::write_vert_uv_normal_indices(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> uv_indices, @@ -57,12 +57,12 @@ void OBJWriter::write_vert_uv_normal_indices(FormatHandler<eFileType::OBJ> &fh, const int uv_offset = offsets.uv_vertex_offset + 1; const int normal_offset = offsets.normal_offset + 1; const int n = vert_indices.size(); - fh.write<eOBJSyntaxElement::poly_element_begin>(); + fh.write_obj_poly_begin(); if (!flip) { for (int j = 0; j < n; ++j) { - fh.write<eOBJSyntaxElement::vertex_uv_normal_indices>(vert_indices[j] + vertex_offset, - uv_indices[j] + uv_offset, - normal_indices[j] + normal_offset); + fh.write_obj_poly_v_uv_normal(vert_indices[j] + vertex_offset, + uv_indices[j] + uv_offset, + normal_indices[j] + normal_offset); } } else { @@ -71,15 +71,15 @@ void OBJWriter::write_vert_uv_normal_indices(FormatHandler<eFileType::OBJ> &fh, * then go backwards. Same logic in other write_*_indices functions below. */ for (int k = 0; k < n; ++k) { int j = k == 0 ? 0 : n - k; - fh.write<eOBJSyntaxElement::vertex_uv_normal_indices>(vert_indices[j] + vertex_offset, - uv_indices[j] + uv_offset, - normal_indices[j] + normal_offset); + fh.write_obj_poly_v_uv_normal(vert_indices[j] + vertex_offset, + uv_indices[j] + uv_offset, + normal_indices[j] + normal_offset); } } - fh.write<eOBJSyntaxElement::poly_element_end>(); + fh.write_obj_poly_end(); } -void OBJWriter::write_vert_normal_indices(FormatHandler<eFileType::OBJ> &fh, +void OBJWriter::write_vert_normal_indices(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> /*uv_indices*/, @@ -90,24 +90,24 @@ void OBJWriter::write_vert_normal_indices(FormatHandler<eFileType::OBJ> &fh, const int vertex_offset = offsets.vertex_offset + 1; const int normal_offset = offsets.normal_offset + 1; const int n = vert_indices.size(); - fh.write<eOBJSyntaxElement::poly_element_begin>(); + fh.write_obj_poly_begin(); if (!flip) { for (int j = 0; j < n; ++j) { - fh.write<eOBJSyntaxElement::vertex_normal_indices>(vert_indices[j] + vertex_offset, - normal_indices[j] + normal_offset); + fh.write_obj_poly_v_normal(vert_indices[j] + vertex_offset, + normal_indices[j] + normal_offset); } } else { for (int k = 0; k < n; ++k) { int j = k == 0 ? 0 : n - k; - fh.write<eOBJSyntaxElement::vertex_normal_indices>(vert_indices[j] + vertex_offset, - normal_indices[j] + normal_offset); + fh.write_obj_poly_v_normal(vert_indices[j] + vertex_offset, + normal_indices[j] + normal_offset); } } - fh.write<eOBJSyntaxElement::poly_element_end>(); + fh.write_obj_poly_end(); } -void OBJWriter::write_vert_uv_indices(FormatHandler<eFileType::OBJ> &fh, +void OBJWriter::write_vert_uv_indices(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> uv_indices, @@ -118,24 +118,22 @@ void OBJWriter::write_vert_uv_indices(FormatHandler<eFileType::OBJ> &fh, const int vertex_offset = offsets.vertex_offset + 1; const int uv_offset = offsets.uv_vertex_offset + 1; const int n = vert_indices.size(); - fh.write<eOBJSyntaxElement::poly_element_begin>(); + fh.write_obj_poly_begin(); if (!flip) { for (int j = 0; j < n; ++j) { - fh.write<eOBJSyntaxElement::vertex_uv_indices>(vert_indices[j] + vertex_offset, - uv_indices[j] + uv_offset); + fh.write_obj_poly_v_uv(vert_indices[j] + vertex_offset, uv_indices[j] + uv_offset); } } else { for (int k = 0; k < n; ++k) { int j = k == 0 ? 0 : n - k; - fh.write<eOBJSyntaxElement::vertex_uv_indices>(vert_indices[j] + vertex_offset, - uv_indices[j] + uv_offset); + fh.write_obj_poly_v_uv(vert_indices[j] + vertex_offset, uv_indices[j] + uv_offset); } } - fh.write<eOBJSyntaxElement::poly_element_end>(); + fh.write_obj_poly_end(); } -void OBJWriter::write_vert_indices(FormatHandler<eFileType::OBJ> &fh, +void OBJWriter::write_vert_indices(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> /*uv_indices*/, @@ -144,27 +142,27 @@ void OBJWriter::write_vert_indices(FormatHandler<eFileType::OBJ> &fh, { const int vertex_offset = offsets.vertex_offset + 1; const int n = vert_indices.size(); - fh.write<eOBJSyntaxElement::poly_element_begin>(); + fh.write_obj_poly_begin(); if (!flip) { for (int j = 0; j < n; ++j) { - fh.write<eOBJSyntaxElement::vertex_indices>(vert_indices[j] + vertex_offset); + fh.write_obj_poly_v(vert_indices[j] + vertex_offset); } } else { for (int k = 0; k < n; ++k) { int j = k == 0 ? 0 : n - k; - fh.write<eOBJSyntaxElement::vertex_indices>(vert_indices[j] + vertex_offset); + fh.write_obj_poly_v(vert_indices[j] + vertex_offset); } } - fh.write<eOBJSyntaxElement::poly_element_end>(); + fh.write_obj_poly_end(); } void OBJWriter::write_header() const { using namespace std::string_literals; - FormatHandler<eFileType::OBJ> fh; - fh.write<eOBJSyntaxElement::string>("# Blender "s + BKE_blender_version_string() + "\n"); - fh.write<eOBJSyntaxElement::string>("# www.blender.org\n"); + FormatHandler fh; + fh.write_string("# Blender "s + BKE_blender_version_string()); + fh.write_string("# www.blender.org"); fh.write_to_file(outfile_); } @@ -174,8 +172,8 @@ void OBJWriter::write_mtllib_name(const StringRefNull mtl_filepath) const char mtl_file_name[FILE_MAXFILE]; char mtl_dir_name[FILE_MAXDIR]; BLI_split_dirfile(mtl_filepath.data(), mtl_dir_name, mtl_file_name, FILE_MAXDIR, FILE_MAXFILE); - FormatHandler<eFileType::OBJ> fh; - fh.write<eOBJSyntaxElement::mtllib>(mtl_file_name); + FormatHandler fh; + fh.write_obj_mtllib(mtl_file_name); fh.write_to_file(outfile_); } @@ -184,18 +182,17 @@ static void spaces_to_underscores(std::string &r_name) std::replace(r_name.begin(), r_name.end(), ' ', '_'); } -void OBJWriter::write_object_name(FormatHandler<eFileType::OBJ> &fh, - const OBJMesh &obj_mesh_data) const +void OBJWriter::write_object_name(FormatHandler &fh, const OBJMesh &obj_mesh_data) const { std::string object_name = obj_mesh_data.get_object_name(); spaces_to_underscores(object_name); if (export_params_.export_object_groups) { std::string mesh_name = obj_mesh_data.get_object_mesh_name(); spaces_to_underscores(mesh_name); - fh.write<eOBJSyntaxElement::object_group>(object_name + "_" + mesh_name); + fh.write_obj_group(object_name + "_" + mesh_name); return; } - fh.write<eOBJSyntaxElement::object_name>(object_name); + fh.write_obj_object(object_name); } /* Split up large meshes into multi-threaded jobs; each job processes @@ -213,9 +210,7 @@ static int calc_chunk_count(int count) * will be written into the final /fh/ buffer at the end. */ template<typename Function> -void obj_parallel_chunked_output(FormatHandler<eFileType::OBJ> &fh, - int tot_count, - const Function &function) +void obj_parallel_chunked_output(FormatHandler &fh, int tot_count, const Function &function) { if (tot_count <= 0) { return; @@ -231,7 +226,7 @@ void obj_parallel_chunked_output(FormatHandler<eFileType::OBJ> &fh, return; } /* Give each chunk its own temporary output buffer, and process them in parallel. */ - std::vector<FormatHandler<eFileType::OBJ>> buffers(chunk_count); + std::vector<FormatHandler> buffers(chunk_count); blender::threading::parallel_for(IndexRange(chunk_count), 1, [&](IndexRange range) { for (const int r : range) { int i_start = r * chunk_size; @@ -248,58 +243,57 @@ void obj_parallel_chunked_output(FormatHandler<eFileType::OBJ> &fh, } } -void OBJWriter::write_vertex_coords(FormatHandler<eFileType::OBJ> &fh, +void OBJWriter::write_vertex_coords(FormatHandler &fh, const OBJMesh &obj_mesh_data, bool write_colors) const { const int tot_count = obj_mesh_data.tot_vertices(); Mesh *mesh = obj_mesh_data.get_mesh(); - CustomDataLayer *colors_layer = nullptr; + const CustomDataLayer *colors_layer = nullptr; if (write_colors) { colors_layer = BKE_id_attributes_active_color_get(&mesh->id); } if (write_colors && (colors_layer != nullptr)) { - const bke::AttributeAccessor attributes = bke::mesh_attributes(*mesh); + const bke::AttributeAccessor attributes = mesh->attributes(); const VArray<ColorGeometry4f> attribute = attributes.lookup_or_default<ColorGeometry4f>( colors_layer->name, ATTR_DOMAIN_POINT, {0.0f, 0.0f, 0.0f, 0.0f}); BLI_assert(tot_count == attribute.size()); - obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) { + obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler &buf, int i) { float3 vertex = obj_mesh_data.calc_vertex_coords(i, export_params_.scaling_factor); ColorGeometry4f linear = attribute.get(i); float srgb[3]; linearrgb_to_srgb_v3_v3(srgb, linear); - buf.write<eOBJSyntaxElement::vertex_coords_color>( - vertex[0], vertex[1], vertex[2], srgb[0], srgb[1], srgb[2]); + buf.write_obj_vertex_color(vertex[0], vertex[1], vertex[2], srgb[0], srgb[1], srgb[2]); }); } else { - obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) { + obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler &buf, int i) { float3 vertex = obj_mesh_data.calc_vertex_coords(i, export_params_.scaling_factor); - buf.write<eOBJSyntaxElement::vertex_coords>(vertex[0], vertex[1], vertex[2]); + buf.write_obj_vertex(vertex[0], vertex[1], vertex[2]); }); } } -void OBJWriter::write_uv_coords(FormatHandler<eFileType::OBJ> &fh, OBJMesh &r_obj_mesh_data) const +void OBJWriter::write_uv_coords(FormatHandler &fh, OBJMesh &r_obj_mesh_data) const { const Vector<float2> &uv_coords = r_obj_mesh_data.get_uv_coords(); const int tot_count = uv_coords.size(); - obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) { + obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler &buf, int i) { const float2 &uv_vertex = uv_coords[i]; - buf.write<eOBJSyntaxElement::uv_vertex_coords>(uv_vertex[0], uv_vertex[1]); + buf.write_obj_uv(uv_vertex[0], uv_vertex[1]); }); } -void OBJWriter::write_poly_normals(FormatHandler<eFileType::OBJ> &fh, OBJMesh &obj_mesh_data) +void OBJWriter::write_poly_normals(FormatHandler &fh, OBJMesh &obj_mesh_data) { /* Poly normals should be calculated earlier via store_normal_coords_and_indices. */ const Vector<float3> &normal_coords = obj_mesh_data.get_normal_coords(); const int tot_count = normal_coords.size(); - obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler<eFileType::OBJ> &buf, int i) { + obj_parallel_chunked_output(fh, tot_count, [&](FormatHandler &buf, int i) { const float3 &normal = normal_coords[i]; - buf.write<eOBJSyntaxElement::normal>(normal[0], normal[1], normal[2]); + buf.write_obj_normal(normal[0], normal[1], normal[2]); }); } @@ -334,7 +328,7 @@ static int get_smooth_group(const OBJMesh &mesh, const OBJExportParams ¶ms, return group; } -void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh, +void OBJWriter::write_poly_elements(FormatHandler &fh, const IndexOffsets &offsets, const OBJMesh &obj_mesh_data, std::function<const char *(int)> matname_fn) @@ -346,7 +340,7 @@ void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh, const int tot_deform_groups = obj_mesh_data.tot_deform_groups(); threading::EnumerableThreadSpecific<Vector<float>> group_weights; - obj_parallel_chunked_output(fh, tot_polygons, [&](FormatHandler<eFileType::OBJ> &buf, int idx) { + obj_parallel_chunked_output(fh, tot_polygons, [&](FormatHandler &buf, int idx) { /* Polygon order for writing into the file is not necessarily the same * as order in the mesh; it will be sorted by material indices. Remap current * and previous indices here according to the order. */ @@ -362,7 +356,7 @@ void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh, const int prev_group = get_smooth_group(obj_mesh_data, export_params_, prev_i); const int group = get_smooth_group(obj_mesh_data, export_params_, i); if (group != prev_group) { - buf.write<eOBJSyntaxElement::smooth_group>(group); + buf.write_obj_smooth(group); } } @@ -375,19 +369,22 @@ void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh, prev_i, local_weights); const int16_t group = obj_mesh_data.get_poly_deform_group_index(i, local_weights); if (group != prev_group) { - buf.write<eOBJSyntaxElement::object_group>( - group == NOT_FOUND ? DEFORM_GROUP_DISABLED : - obj_mesh_data.get_poly_deform_group_name(group)); + buf.write_obj_group(group == NOT_FOUND ? DEFORM_GROUP_DISABLED : + obj_mesh_data.get_poly_deform_group_name(group)); } } + const bke::AttributeAccessor attributes = obj_mesh_data.get_mesh()->attributes(); + const VArray<int> material_indices = attributes.lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); + /* Write material name and material group if different from previous. */ if (export_params_.export_materials && obj_mesh_data.tot_materials() > 0) { - const int16_t prev_mat = idx == 0 ? NEGATIVE_INIT : obj_mesh_data.ith_poly_matnr(prev_i); - const int16_t mat = obj_mesh_data.ith_poly_matnr(i); + const int16_t prev_mat = idx == 0 ? NEGATIVE_INIT : std::max(0, material_indices[prev_i]); + const int16_t mat = std::max(0, material_indices[i]); if (mat != prev_mat) { if (mat == NOT_FOUND) { - buf.write<eOBJSyntaxElement::poly_usemtl>(MATERIAL_GROUP_DISABLED); + buf.write_obj_usemtl(MATERIAL_GROUP_DISABLED); } else { const char *mat_name = matname_fn(mat); @@ -397,9 +394,9 @@ void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh, if (export_params_.export_material_groups) { std::string object_name = obj_mesh_data.get_object_name(); spaces_to_underscores(object_name); - fh.write<eOBJSyntaxElement::object_group>(object_name + "_" + mat_name); + fh.write_obj_group(object_name + "_" + mat_name); } - buf.write<eOBJSyntaxElement::poly_usemtl>(mat_name); + buf.write_obj_usemtl(mat_name); } } } @@ -414,7 +411,7 @@ void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh, }); } -void OBJWriter::write_edges_indices(FormatHandler<eFileType::OBJ> &fh, +void OBJWriter::write_edges_indices(FormatHandler &fh, const IndexOffsets &offsets, const OBJMesh &obj_mesh_data) const { @@ -426,13 +423,12 @@ void OBJWriter::write_edges_indices(FormatHandler<eFileType::OBJ> &fh, if (!vertex_indices) { continue; } - fh.write<eOBJSyntaxElement::edge>((*vertex_indices)[0] + offsets.vertex_offset + 1, - (*vertex_indices)[1] + offsets.vertex_offset + 1); + fh.write_obj_edge((*vertex_indices)[0] + offsets.vertex_offset + 1, + (*vertex_indices)[1] + offsets.vertex_offset + 1); } } -void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, - const OBJCurve &obj_nurbs_data) const +void OBJWriter::write_nurbs_curve(FormatHandler &fh, const OBJCurve &obj_nurbs_data) const { const int total_splines = obj_nurbs_data.total_splines(); for (int spline_idx = 0; spline_idx < total_splines; spline_idx++) { @@ -440,15 +436,14 @@ void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, for (int vertex_idx = 0; vertex_idx < total_vertices; vertex_idx++) { const float3 vertex_coords = obj_nurbs_data.vertex_coordinates( spline_idx, vertex_idx, export_params_.scaling_factor); - fh.write<eOBJSyntaxElement::vertex_coords>( - vertex_coords[0], vertex_coords[1], vertex_coords[2]); + fh.write_obj_vertex(vertex_coords[0], vertex_coords[1], vertex_coords[2]); } const char *nurbs_name = obj_nurbs_data.get_curve_name(); const int nurbs_degree = obj_nurbs_data.get_nurbs_degree(spline_idx); - fh.write<eOBJSyntaxElement::object_group>(nurbs_name); - fh.write<eOBJSyntaxElement::cstype>(); - fh.write<eOBJSyntaxElement::nurbs_degree>(nurbs_degree); + fh.write_obj_group(nurbs_name); + fh.write_obj_cstype(); + fh.write_obj_nurbs_degree(nurbs_degree); /** * The numbers written here are indices into the vertex coordinates written * earlier, relative to the line that is going to be written. @@ -457,13 +452,13 @@ void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, * 0.0 1.0 -1 -2 -3 -4 -1 -2 -3 for a cyclic curve with 4 vertices. */ const int total_control_points = obj_nurbs_data.total_spline_control_points(spline_idx); - fh.write<eOBJSyntaxElement::curve_element_begin>(); + fh.write_obj_curve_begin(); for (int i = 0; i < total_control_points; i++) { /* "+1" to keep indices one-based, even if they're negative: i.e., -1 refers to the * last vertex coordinate, -2 second last. */ - fh.write<eOBJSyntaxElement::vertex_indices>(-((i % total_vertices) + 1)); + fh.write_obj_poly_v(-((i % total_vertices) + 1)); } - fh.write<eOBJSyntaxElement::curve_element_end>(); + fh.write_obj_curve_end(); /** * In `parm u 0 0.1 ..` line:, (total control points + 2) equidistant numbers in the @@ -474,7 +469,7 @@ void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, const short flagsu = obj_nurbs_data.get_nurbs_flagu(spline_idx); const bool cyclic = flagsu & CU_NURB_CYCLIC; const bool endpoint = !cyclic && (flagsu & CU_NURB_ENDPOINT); - fh.write<eOBJSyntaxElement::nurbs_parameter_begin>(); + fh.write_obj_nurbs_parm_begin(); for (int i = 1; i <= total_control_points + 2; i++) { float parm = 1.0f * i / (total_control_points + 2 + 1); if (endpoint) { @@ -485,11 +480,10 @@ void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, parm = 1; } } - fh.write<eOBJSyntaxElement::nurbs_parameters>(parm); + fh.write_obj_nurbs_parm(parm); } - fh.write<eOBJSyntaxElement::nurbs_parameter_end>(); - - fh.write<eOBJSyntaxElement::nurbs_group_end>(); + fh.write_obj_nurbs_parm_end(); + fh.write_obj_nurbs_group_end(); } } @@ -497,6 +491,21 @@ void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, /** \name .MTL writers. * \{ */ +static const char *tex_map_type_to_string[] = { + "map_Kd", + "map_Pm", + "map_Ks", + "map_Ns", + "map_Pr", + "map_Ps", + "map_refl", + "map_Ke", + "map_d", + "map_Bump", +}; +BLI_STATIC_ASSERT(ARRAY_SIZE(tex_map_type_to_string) == int(MTLTexMapType::Count), + "array size mismatch"); + /** * Convert #float3 to string of space-separated numbers, with no leading or trailing space. * Only to be used in NON-performance-critical code. @@ -537,9 +546,9 @@ void MTLWriter::write_header(const char *blen_filepath) const char *blen_basename = (blen_filepath && blen_filepath[0] != '\0') ? BLI_path_basename(blen_filepath) : "None"; - fmt_handler_.write<eMTLSyntaxElement::string>("# Blender "s + BKE_blender_version_string() + - " MTL File: '" + blen_basename + "'\n"); - fmt_handler_.write<eMTLSyntaxElement::string>("# www.blender.org\n"); + fmt_handler_.write_string("# Blender "s + BKE_blender_version_string() + " MTL File: '" + + blen_basename + "'"); + fmt_handler_.write_string("# www.blender.org"); } StringRefNull MTLWriter::mtl_file_path() const @@ -547,77 +556,109 @@ StringRefNull MTLWriter::mtl_file_path() const return mtl_filepath_; } -void MTLWriter::write_bsdf_properties(const MTLMaterial &mtl) +void MTLWriter::write_bsdf_properties(const MTLMaterial &mtl, bool write_pbr) { /* For various material properties, we only capture information * coming from the texture, or the default value of the socket. * When the texture is present, do not emit the default value. */ - if (!mtl.tex_map_of_type(eMTLSyntaxElement::map_Ns).is_valid()) { - fmt_handler_.write<eMTLSyntaxElement::Ns>(mtl.Ns); + + /* Do not write Ns & Ka when writing in PBR mode. */ + if (!write_pbr) { + if (!mtl.tex_map_of_type(MTLTexMapType::SpecularExponent).is_valid()) { + fmt_handler_.write_mtl_float("Ns", mtl.spec_exponent); + } + fmt_handler_.write_mtl_float3( + "Ka", mtl.ambient_color.x, mtl.ambient_color.y, mtl.ambient_color.z); } - fmt_handler_.write<eMTLSyntaxElement::Ka>(mtl.Ka.x, mtl.Ka.y, mtl.Ka.z); - if (!mtl.tex_map_of_type(eMTLSyntaxElement::map_Kd).is_valid()) { - fmt_handler_.write<eMTLSyntaxElement::Kd>(mtl.Kd.x, mtl.Kd.y, mtl.Kd.z); + if (!mtl.tex_map_of_type(MTLTexMapType::Color).is_valid()) { + fmt_handler_.write_mtl_float3("Kd", mtl.color.x, mtl.color.y, mtl.color.z); } - if (!mtl.tex_map_of_type(eMTLSyntaxElement::map_Ks).is_valid()) { - fmt_handler_.write<eMTLSyntaxElement::Ks>(mtl.Ks.x, mtl.Ks.y, mtl.Ks.z); + if (!mtl.tex_map_of_type(MTLTexMapType::Specular).is_valid()) { + fmt_handler_.write_mtl_float3("Ks", mtl.spec_color.x, mtl.spec_color.y, mtl.spec_color.z); } - if (!mtl.tex_map_of_type(eMTLSyntaxElement::map_Ke).is_valid()) { - fmt_handler_.write<eMTLSyntaxElement::Ke>(mtl.Ke.x, mtl.Ke.y, mtl.Ke.z); + if (!mtl.tex_map_of_type(MTLTexMapType::Emission).is_valid()) { + fmt_handler_.write_mtl_float3( + "Ke", mtl.emission_color.x, mtl.emission_color.y, mtl.emission_color.z); } - fmt_handler_.write<eMTLSyntaxElement::Ni>(mtl.Ni); - if (!mtl.tex_map_of_type(eMTLSyntaxElement::map_d).is_valid()) { - fmt_handler_.write<eMTLSyntaxElement::d>(mtl.d); + fmt_handler_.write_mtl_float("Ni", mtl.ior); + if (!mtl.tex_map_of_type(MTLTexMapType::Alpha).is_valid()) { + fmt_handler_.write_mtl_float("d", mtl.alpha); + } + fmt_handler_.write_mtl_illum(mtl.illum_mode); + + if (write_pbr) { + if (!mtl.tex_map_of_type(MTLTexMapType::Roughness).is_valid() && mtl.roughness >= 0.0f) { + fmt_handler_.write_mtl_float("Pr", mtl.roughness); + } + if (!mtl.tex_map_of_type(MTLTexMapType::Metallic).is_valid() && mtl.metallic >= 0.0f) { + fmt_handler_.write_mtl_float("Pm", mtl.metallic); + } + if (!mtl.tex_map_of_type(MTLTexMapType::Sheen).is_valid() && mtl.sheen >= 0.0f) { + fmt_handler_.write_mtl_float("Ps", mtl.sheen); + } + if (mtl.cc_thickness >= 0.0f) { + fmt_handler_.write_mtl_float("Pc", mtl.cc_thickness); + } + if (mtl.cc_roughness >= 0.0f) { + fmt_handler_.write_mtl_float("Pcr", mtl.cc_roughness); + } + if (mtl.aniso >= 0.0f) { + fmt_handler_.write_mtl_float("aniso", mtl.aniso); + } + if (mtl.aniso_rot >= 0.0f) { + fmt_handler_.write_mtl_float("anisor", mtl.aniso_rot); + } + if (mtl.transmit_color.x > 0.0f || mtl.transmit_color.y > 0.0f || + mtl.transmit_color.z > 0.0f) { + fmt_handler_.write_mtl_float3( + "Tf", mtl.transmit_color.x, mtl.transmit_color.y, mtl.transmit_color.z); + } } - fmt_handler_.write<eMTLSyntaxElement::illum>(mtl.illum); } -void MTLWriter::write_texture_map( - const MTLMaterial &mtl_material, - const Map<const eMTLSyntaxElement, tex_map_XX>::Item &texture_map, - const char *blen_filedir, - const char *dest_dir, - ePathReferenceMode path_mode, - Set<std::pair<std::string, std::string>> ©_set) +void MTLWriter::write_texture_map(const MTLMaterial &mtl_material, + MTLTexMapType texture_key, + const MTLTexMap &texture_map, + const char *blen_filedir, + const char *dest_dir, + ePathReferenceMode path_mode, + Set<std::pair<std::string, std::string>> ©_set) { std::string options; /* Option strings should have their own leading spaces. */ - if (texture_map.value.translation != float3{0.0f, 0.0f, 0.0f}) { - options.append(" -o ").append(float3_to_string(texture_map.value.translation)); + if (texture_map.translation != float3{0.0f, 0.0f, 0.0f}) { + options.append(" -o ").append(float3_to_string(texture_map.translation)); } - if (texture_map.value.scale != float3{1.0f, 1.0f, 1.0f}) { - options.append(" -s ").append(float3_to_string(texture_map.value.scale)); + if (texture_map.scale != float3{1.0f, 1.0f, 1.0f}) { + options.append(" -s ").append(float3_to_string(texture_map.scale)); } - if (texture_map.key == eMTLSyntaxElement::map_Bump && mtl_material.map_Bump_strength > 0.0001f) { - options.append(" -bm ").append(std::to_string(mtl_material.map_Bump_strength)); + if (texture_key == MTLTexMapType::Normal && mtl_material.normal_strength > 0.0001f) { + options.append(" -bm ").append(std::to_string(mtl_material.normal_strength)); } std::string path = path_reference( - texture_map.value.image_path.c_str(), blen_filedir, dest_dir, path_mode, ©_set); + texture_map.image_path.c_str(), blen_filedir, dest_dir, path_mode, ©_set); /* Always emit forward slashes for cross-platform compatibility. */ std::replace(path.begin(), path.end(), '\\', '/'); -#define SYNTAX_DISPATCH(eMTLSyntaxElement) \ - if (texture_map.key == eMTLSyntaxElement) { \ - fmt_handler_.write<eMTLSyntaxElement>(options, path.c_str()); \ - return; \ - } + fmt_handler_.write_mtl_map(tex_map_type_to_string[int(texture_key)], options, path); +} - SYNTAX_DISPATCH(eMTLSyntaxElement::map_Kd); - SYNTAX_DISPATCH(eMTLSyntaxElement::map_Ks); - SYNTAX_DISPATCH(eMTLSyntaxElement::map_Ns); - SYNTAX_DISPATCH(eMTLSyntaxElement::map_d); - SYNTAX_DISPATCH(eMTLSyntaxElement::map_refl); - SYNTAX_DISPATCH(eMTLSyntaxElement::map_Ke); - SYNTAX_DISPATCH(eMTLSyntaxElement::map_Bump); -#undef SYNTAX_DISPATCH +static bool is_pbr_map(MTLTexMapType type) +{ + return type == MTLTexMapType::Metallic || type == MTLTexMapType::Roughness || + type == MTLTexMapType::Sheen; +} - BLI_assert(!"This map type was not written to the file."); +static bool is_non_pbr_map(MTLTexMapType type) +{ + return type == MTLTexMapType::SpecularExponent || type == MTLTexMapType::Reflection; } void MTLWriter::write_materials(const char *blen_filepath, ePathReferenceMode path_mode, - const char *dest_dir) + const char *dest_dir, + bool write_pbr) { if (mtlmaterials_.size() == 0) { return; @@ -633,14 +674,22 @@ void MTLWriter::write_materials(const char *blen_filepath, [](const MTLMaterial &a, const MTLMaterial &b) { return a.name < b.name; }); Set<std::pair<std::string, std::string>> copy_set; for (const MTLMaterial &mtlmat : mtlmaterials_) { - fmt_handler_.write<eMTLSyntaxElement::string>("\n"); - fmt_handler_.write<eMTLSyntaxElement::newmtl>(mtlmat.name); - write_bsdf_properties(mtlmat); - for (const auto &tex : mtlmat.texture_maps.items()) { - if (!tex.value.is_valid()) { + fmt_handler_.write_string(""); + fmt_handler_.write_mtl_newmtl(mtlmat.name); + write_bsdf_properties(mtlmat, write_pbr); + for (int key = 0; key < int(MTLTexMapType::Count); key++) { + const MTLTexMap &tex = mtlmat.texture_maps[key]; + if (!tex.is_valid()) { + continue; + } + if (!write_pbr && is_pbr_map((MTLTexMapType)key)) { + continue; + } + if (write_pbr && is_non_pbr_map((MTLTexMapType)key)) { continue; } - write_texture_map(mtlmat, tex, blen_filedir, dest_dir, path_mode, copy_set); + write_texture_map( + mtlmat, (MTLTexMapType)key, tex, blen_filedir, dest_dir, path_mode, copy_set); } } path_reference_copy(copy_set); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh index 97c23484426..eda4576297b 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh @@ -66,7 +66,7 @@ class OBJWriter : NonMovable, NonCopyable { /** * Write object's name or group. */ - void write_object_name(FormatHandler<eFileType::OBJ> &fh, const OBJMesh &obj_mesh_data) const; + void write_object_name(FormatHandler &fh, const OBJMesh &obj_mesh_data) const; /** * Write file name of Material Library in .OBJ file. */ @@ -74,19 +74,19 @@ class OBJWriter : NonMovable, NonCopyable { /** * Write vertex coordinates for all vertices as "v x y z" or "v x y z r g b". */ - void write_vertex_coords(FormatHandler<eFileType::OBJ> &fh, + void write_vertex_coords(FormatHandler &fh, const OBJMesh &obj_mesh_data, bool write_colors) const; /** * Write UV vertex coordinates for all vertices as `vt u v`. * \note UV indices are stored here, but written with polygons later. */ - void write_uv_coords(FormatHandler<eFileType::OBJ> &fh, OBJMesh &obj_mesh_data) const; + void write_uv_coords(FormatHandler &fh, OBJMesh &obj_mesh_data) const; /** * Write loop normals for smooth-shaded polygons, and polygon normals otherwise, as "vn x y z". * \note Normal indices ares stored here, but written with polygons later. */ - void write_poly_normals(FormatHandler<eFileType::OBJ> &fh, OBJMesh &obj_mesh_data); + void write_poly_normals(FormatHandler &fh, OBJMesh &obj_mesh_data); /** * Write polygon elements with at least vertex indices, and conditionally with UV vertex * indices and polygon normal indices. Also write groups: smooth, vertex, material. @@ -94,23 +94,23 @@ class OBJWriter : NonMovable, NonCopyable { * name used in the .obj file. * \note UV indices were stored while writing UV vertices. */ - void write_poly_elements(FormatHandler<eFileType::OBJ> &fh, + void write_poly_elements(FormatHandler &fh, const IndexOffsets &offsets, const OBJMesh &obj_mesh_data, std::function<const char *(int)> matname_fn); /** * Write loose edges of a mesh as "l v1 v2". */ - void write_edges_indices(FormatHandler<eFileType::OBJ> &fh, + void write_edges_indices(FormatHandler &fh, const IndexOffsets &offsets, const OBJMesh &obj_mesh_data) const; /** * Write a NURBS curve to the .OBJ file in parameter form. */ - void write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, const OBJCurve &obj_nurbs_data) const; + void write_nurbs_curve(FormatHandler &fh, const OBJCurve &obj_nurbs_data) const; private: - using func_vert_uv_normal_indices = void (OBJWriter::*)(FormatHandler<eFileType::OBJ> &fh, + using func_vert_uv_normal_indices = void (OBJWriter::*)(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> uv_indices, @@ -124,7 +124,7 @@ class OBJWriter : NonMovable, NonCopyable { /** * Write one line of polygon indices as "f v1/vt1/vn1 v2/vt2/vn2 ...". */ - void write_vert_uv_normal_indices(FormatHandler<eFileType::OBJ> &fh, + void write_vert_uv_normal_indices(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> uv_indices, @@ -133,7 +133,7 @@ class OBJWriter : NonMovable, NonCopyable { /** * Write one line of polygon indices as "f v1//vn1 v2//vn2 ...". */ - void write_vert_normal_indices(FormatHandler<eFileType::OBJ> &fh, + void write_vert_normal_indices(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> /*uv_indices*/, @@ -142,7 +142,7 @@ class OBJWriter : NonMovable, NonCopyable { /** * Write one line of polygon indices as "f v1/vt1 v2/vt2 ...". */ - void write_vert_uv_indices(FormatHandler<eFileType::OBJ> &fh, + void write_vert_uv_indices(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> uv_indices, @@ -151,7 +151,7 @@ class OBJWriter : NonMovable, NonCopyable { /** * Write one line of polygon indices as "f v1 v2 ...". */ - void write_vert_indices(FormatHandler<eFileType::OBJ> &fh, + void write_vert_indices(FormatHandler &fh, const IndexOffsets &offsets, Span<int> vert_indices, Span<int> /*uv_indices*/, @@ -164,7 +164,7 @@ class OBJWriter : NonMovable, NonCopyable { */ class MTLWriter : NonMovable, NonCopyable { private: - FormatHandler<eFileType::MTL> fmt_handler_; + FormatHandler fmt_handler_; FILE *outfile_; std::string mtl_filepath_; Vector<MTLMaterial> mtlmaterials_; @@ -186,7 +186,8 @@ class MTLWriter : NonMovable, NonCopyable { */ void write_materials(const char *blen_filepath, ePathReferenceMode path_mode, - const char *dest_dir); + const char *dest_dir, + bool write_pbr); StringRefNull mtl_file_path() const; /** * Add the materials of the given object to #MTLWriter, de-duplicating @@ -203,12 +204,13 @@ class MTLWriter : NonMovable, NonCopyable { /** * Write properties sourced from p-BSDF node or #Object.Material. */ - void write_bsdf_properties(const MTLMaterial &mtl_material); + void write_bsdf_properties(const MTLMaterial &mtl_material, bool write_pbr); /** * Write a texture map in the form "map_XX -s 1. 1. 1. -o 0. 0. 0. [-bm 1.] path/to/image". */ void write_texture_map(const MTLMaterial &mtl_material, - const Map<const eMTLSyntaxElement, tex_map_XX>::Item &texture_map, + MTLTexMapType texture_key, + const MTLTexMap &texture_map, const char *blen_filedir, const char *dest_dir, ePathReferenceMode mode, diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh index 5413c9969e3..59ee7bd32c0 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_io.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_io.hh @@ -23,268 +23,24 @@ namespace blender::io::obj { -enum class eFileType { - OBJ, - MTL, -}; - -enum class eOBJSyntaxElement { - vertex_coords, - vertex_coords_color, - uv_vertex_coords, - normal, - poly_element_begin, - vertex_uv_normal_indices, - vertex_normal_indices, - vertex_uv_indices, - vertex_indices, - poly_element_end, - poly_usemtl, - edge, - cstype, - nurbs_degree, - curve_element_begin, - curve_element_end, - nurbs_parameter_begin, - nurbs_parameters, - nurbs_parameter_end, - nurbs_group_end, - new_line, - mtllib, - smooth_group, - object_group, - object_name, - /* Use rarely. New line is NOT included for string. */ - string, -}; - -enum class eMTLSyntaxElement { - newmtl, - Ni, - d, - Ns, - illum, - Ka, - Kd, - Ks, - Ke, - map_Kd, - map_Ks, - map_Ns, - map_d, - map_refl, - map_Ke, - map_Bump, - /* Use rarely. New line is NOT included for string. */ - string, -}; - -template<eFileType filetype> struct FileTypeTraits; - -/* Used to prevent mixing of say OBJ file format with MTL syntax elements. */ -template<> struct FileTypeTraits<eFileType::OBJ> { - using SyntaxType = eOBJSyntaxElement; -}; - -template<> struct FileTypeTraits<eFileType::MTL> { - using SyntaxType = eMTLSyntaxElement; -}; - -struct FormattingSyntax { - /* Formatting syntax with the file format key like `newmtl %s\n`. */ - const char *fmt = nullptr; - /* Number of arguments needed by the syntax. */ - const int total_args = 0; - /* Whether types of the given arguments are accepted by the syntax above. Fail to compile by - * default. - */ - const bool are_types_valid = false; -}; - -/** - * Type dependent but always false. Use to add a `constexpr` conditional compile-time error. - */ -template<typename T> struct always_false : std::false_type { -}; - -template<typename... T> -constexpr bool is_type_float = (... && std::is_floating_point_v<std::decay_t<T>>); - -template<typename... T> -constexpr bool is_type_integral = (... && std::is_integral_v<std::decay_t<T>>); - -template<typename... T> -constexpr bool is_type_string_related = (... && std::is_constructible_v<std::string, T>); - -/* GCC (at least 9.3) while compiling the obj_exporter_tests.cc with optimizations on, - * results in "obj_export_io.hh:205:18: warning: ‘%s’ directive output truncated writing 34 bytes - * into a region of size 6" and similar warnings. Yes the output is truncated, and that is covered - * as an edge case by tests on purpose. */ -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wformat-truncation" -#endif -template<typename... T> -constexpr FormattingSyntax syntax_elem_to_formatting(const eOBJSyntaxElement key) -{ - switch (key) { - case eOBJSyntaxElement::vertex_coords: { - return {"v {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; - } - case eOBJSyntaxElement::vertex_coords_color: { - return {"v {:.6f} {:.6f} {:.6f} {:.4f} {:.4f} {:.4f}\n", 6, is_type_float<T...>}; - } - case eOBJSyntaxElement::uv_vertex_coords: { - return {"vt {:.6f} {:.6f}\n", 2, is_type_float<T...>}; - } - case eOBJSyntaxElement::normal: { - return {"vn {:.4f} {:.4f} {:.4f}\n", 3, is_type_float<T...>}; - } - case eOBJSyntaxElement::poly_element_begin: { - return {"f", 0, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::vertex_uv_normal_indices: { - return {" {}/{}/{}", 3, is_type_integral<T...>}; - } - case eOBJSyntaxElement::vertex_normal_indices: { - return {" {}//{}", 2, is_type_integral<T...>}; - } - case eOBJSyntaxElement::vertex_uv_indices: { - return {" {}/{}", 2, is_type_integral<T...>}; - } - case eOBJSyntaxElement::vertex_indices: { - return {" {}", 1, is_type_integral<T...>}; - } - case eOBJSyntaxElement::poly_usemtl: { - return {"usemtl {}\n", 1, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::edge: { - return {"l {} {}\n", 2, is_type_integral<T...>}; - } - case eOBJSyntaxElement::cstype: { - return {"cstype bspline\n", 0, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::nurbs_degree: { - return {"deg {}\n", 1, is_type_integral<T...>}; - } - case eOBJSyntaxElement::curve_element_begin: { - return {"curv 0.0 1.0", 0, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::nurbs_parameter_begin: { - return {"parm u 0.0", 0, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::nurbs_parameters: { - return {" {:.6f}", 1, is_type_float<T...>}; - } - case eOBJSyntaxElement::nurbs_parameter_end: { - return {" 1.0\n", 0, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::nurbs_group_end: { - return {"end\n", 0, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::poly_element_end: { - ATTR_FALLTHROUGH; - } - case eOBJSyntaxElement::curve_element_end: { - ATTR_FALLTHROUGH; - } - case eOBJSyntaxElement::new_line: { - return {"\n", 0, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::mtllib: { - return {"mtllib {}\n", 1, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::smooth_group: { - return {"s {}\n", 1, is_type_integral<T...>}; - } - case eOBJSyntaxElement::object_group: { - return {"g {}\n", 1, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::object_name: { - return {"o {}\n", 1, is_type_string_related<T...>}; - } - case eOBJSyntaxElement::string: { - return {"{}", 1, is_type_string_related<T...>}; - } - } -} - -template<typename... T> -constexpr FormattingSyntax syntax_elem_to_formatting(const eMTLSyntaxElement key) -{ - switch (key) { - case eMTLSyntaxElement::newmtl: { - return {"newmtl {}\n", 1, is_type_string_related<T...>}; - } - case eMTLSyntaxElement::Ni: { - return {"Ni {:.6f}\n", 1, is_type_float<T...>}; - } - case eMTLSyntaxElement::d: { - return {"d {:.6f}\n", 1, is_type_float<T...>}; - } - case eMTLSyntaxElement::Ns: { - return {"Ns {:.6f}\n", 1, is_type_float<T...>}; - } - case eMTLSyntaxElement::illum: { - return {"illum {}\n", 1, is_type_integral<T...>}; - } - case eMTLSyntaxElement::Ka: { - return {"Ka {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; - } - case eMTLSyntaxElement::Kd: { - return {"Kd {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; - } - case eMTLSyntaxElement::Ks: { - return {"Ks {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; - } - case eMTLSyntaxElement::Ke: { - return {"Ke {:.6f} {:.6f} {:.6f}\n", 3, is_type_float<T...>}; - } - /* NOTE: first texture map related argument, if present, will have its own leading space. */ - case eMTLSyntaxElement::map_Kd: { - return {"map_Kd{} {}\n", 2, is_type_string_related<T...>}; - } - case eMTLSyntaxElement::map_Ks: { - return {"map_Ks{} {}\n", 2, is_type_string_related<T...>}; - } - case eMTLSyntaxElement::map_Ns: { - return {"map_Ns{} {}\n", 2, is_type_string_related<T...>}; - } - case eMTLSyntaxElement::map_d: { - return {"map_d{} {}\n", 2, is_type_string_related<T...>}; - } - case eMTLSyntaxElement::map_refl: { - return {"map_refl{} {}\n", 2, is_type_string_related<T...>}; - } - case eMTLSyntaxElement::map_Ke: { - return {"map_Ke{} {}\n", 2, is_type_string_related<T...>}; - } - case eMTLSyntaxElement::map_Bump: { - return {"map_Bump{} {}\n", 2, is_type_string_related<T...>}; - } - case eMTLSyntaxElement::string: { - return {"{}", 1, is_type_string_related<T...>}; - } - } -} -#if defined(__GNUC__) && !defined(__clang__) -# pragma GCC diagnostic pop -#endif - /** - * File format and syntax agnostic file buffer writer. + * File buffer writer. * All writes are done into an internal chunked memory buffer * (list of default 64 kilobyte blocks). * Call write_fo_file once in a while to write the memory buffer(s) * into the given file. */ -template<eFileType filetype, size_t buffer_chunk_size = 64 * 1024> class FormatHandler : NonCopyable, NonMovable { private: typedef std::vector<char> VectorChar; std::vector<VectorChar> blocks_; + size_t buffer_chunk_size_; public: + FormatHandler(size_t buffer_chunk_size = 64 * 1024) : buffer_chunk_size_(buffer_chunk_size) + { + } + /* Write contents to the buffer(s) into a file, and clear the buffers. */ void write_to_file(FILE *f) { @@ -305,7 +61,7 @@ class FormatHandler : NonCopyable, NonMovable { return blocks_.size(); } - void append_from(FormatHandler<filetype, buffer_chunk_size> &v) + void append_from(FormatHandler &v) { blocks_.insert(blocks_.end(), std::make_move_iterator(v.blocks_.begin()), @@ -313,24 +69,132 @@ class FormatHandler : NonCopyable, NonMovable { v.blocks_.clear(); } - /** - * Example invocation: `writer->write<eMTLSyntaxElement::newmtl>("foo")`. - * - * \param key: Must match what the instance's filetype expects; i.e., `eMTLSyntaxElement` for - * `eFileType::MTL`. - */ - template<typename FileTypeTraits<filetype>::SyntaxType key, typename... T> - constexpr void write(T &&...args) - { - /* Get format syntax, number of arguments expected and whether types of given arguments are - * valid. - */ - constexpr FormattingSyntax fmt_nargs_valid = syntax_elem_to_formatting<T...>(key); - BLI_STATIC_ASSERT(fmt_nargs_valid.are_types_valid && - (sizeof...(T) == fmt_nargs_valid.total_args), - "Types of all arguments and the number of arguments should match what the " - "formatting specifies."); - write_impl(fmt_nargs_valid.fmt, std::forward<T>(args)...); + void write_obj_vertex(float x, float y, float z) + { + write_impl("v {:.6f} {:.6f} {:.6f}\n", x, y, z); + } + void write_obj_vertex_color(float x, float y, float z, float r, float g, float b) + { + write_impl("v {:.6f} {:.6f} {:.6f} {:.4f} {:.4f} {:.4f}\n", x, y, z, r, g, b); + } + void write_obj_uv(float x, float y) + { + write_impl("vt {:.6f} {:.6f}\n", x, y); + } + void write_obj_normal(float x, float y, float z) + { + write_impl("vn {:.4f} {:.4f} {:.4f}\n", x, y, z); + } + void write_obj_poly_begin() + { + write_impl("f"); + } + void write_obj_poly_end() + { + write_obj_newline(); + } + void write_obj_poly_v_uv_normal(int v, int uv, int n) + { + write_impl(" {}/{}/{}", v, uv, n); + } + void write_obj_poly_v_normal(int v, int n) + { + write_impl(" {}//{}", v, n); + } + void write_obj_poly_v_uv(int v, int uv) + { + write_impl(" {}/{}", v, uv); + } + void write_obj_poly_v(int v) + { + write_impl(" {}", v); + } + void write_obj_usemtl(StringRef s) + { + write_impl("usemtl {}\n", s); + } + void write_obj_mtllib(StringRef s) + { + write_impl("mtllib {}\n", s); + } + void write_obj_smooth(int s) + { + write_impl("s {}\n", s); + } + void write_obj_group(StringRef s) + { + write_impl("g {}\n", s); + } + void write_obj_object(StringRef s) + { + write_impl("o {}\n", s); + } + void write_obj_edge(int a, int b) + { + write_impl("l {} {}\n", a, b); + } + void write_obj_cstype() + { + write_impl("cstype bspline\n"); + } + void write_obj_nurbs_degree(int deg) + { + write_impl("deg {}\n", deg); + } + void write_obj_curve_begin() + { + write_impl("curv 0.0 1.0"); + } + void write_obj_curve_end() + { + write_obj_newline(); + } + void write_obj_nurbs_parm_begin() + { + write_impl("parm u 0.0"); + } + void write_obj_nurbs_parm(float v) + { + write_impl(" {:.6f}", v); + } + void write_obj_nurbs_parm_end() + { + write_impl(" 1.0\n"); + } + void write_obj_nurbs_group_end() + { + write_impl("end\n"); + } + void write_obj_newline() + { + write_impl("\n"); + } + + void write_mtl_newmtl(StringRef s) + { + write_impl("newmtl {}\n", s); + } + void write_mtl_float(const char *type, float v) + { + write_impl("{} {:.6f}\n", type, v); + } + void write_mtl_float3(const char *type, float r, float g, float b) + { + write_impl("{} {:.6f} {:.6f} {:.6f}\n", type, r, g, b); + } + void write_mtl_illum(int mode) + { + write_impl("illum {}\n", mode); + } + /* NOTE: options, if present, will have its own leading space. */ + void write_mtl_map(const char *type, StringRef options, StringRef value) + { + write_impl("{}{} {}\n", type, options, value); + } + + void write_string(StringRef s) + { + write_impl("{}\n", s); } private: @@ -340,7 +204,7 @@ class FormatHandler : NonCopyable, NonMovable { { if (blocks_.empty() || (blocks_.back().capacity() - blocks_.back().size() < at_least)) { VectorChar &b = blocks_.emplace_back(VectorChar()); - b.reserve(std::max(at_least, buffer_chunk_size)); + b.reserve(std::max(at_least, buffer_chunk_size_)); } } diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 815163ad19e..9f19a6390d3 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -6,6 +6,7 @@ /* Silence warnings from copying deprecated fields. Needed for an Object copy constructor use. */ #define DNA_DEPRECATED_ALLOW +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_lib_id.h" @@ -187,28 +188,38 @@ void OBJMesh::ensure_mesh_edges() const void OBJMesh::calc_smooth_groups(const bool use_bitflags) { - poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(export_mesh_eval_->medge, - export_mesh_eval_->totedge, - export_mesh_eval_->mpoly, - export_mesh_eval_->totpoly, - export_mesh_eval_->mloop, - export_mesh_eval_->totloop, + const Span<MEdge> edges = export_mesh_eval_->edges(); + const Span<MPoly> polys = export_mesh_eval_->polys(); + const Span<MLoop> loops = export_mesh_eval_->loops(); + poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(edges.data(), + edges.size(), + polys.data(), + polys.size(), + loops.data(), + loops.size(), &tot_smooth_groups_, use_bitflags); } void OBJMesh::calc_poly_order() { - const int tot_polys = tot_polygons(); - poly_order_.resize(tot_polys); - for (int i = 0; i < tot_polys; ++i) { + const bke::AttributeAccessor attributes = export_mesh_eval_->attributes(); + const VArray<int> material_indices = attributes.lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); + if (material_indices.is_single() && material_indices.get_internal_single() == 0) { + return; + } + const VArraySpan<int> material_indices_span(material_indices); + + poly_order_.resize(material_indices_span.size()); + for (const int i : material_indices_span.index_range()) { poly_order_[i] = i; } - const MPoly *mpolys = export_mesh_eval_->mpoly; + /* Sort polygons by their material index. */ blender::parallel_sort(poly_order_.begin(), poly_order_.end(), [&](int a, int b) { - int mat_a = mpolys[a].mat_nr; - int mat_b = mpolys[b].mat_nr; + int mat_a = material_indices_span[a]; + int mat_b = material_indices_span[b]; if (mat_a != mat_b) { return mat_a < mat_b; } @@ -231,14 +242,8 @@ const Material *OBJMesh::get_object_material(const int16_t mat_nr) const bool OBJMesh::is_ith_poly_smooth(const int poly_index) const { - return export_mesh_eval_->mpoly[poly_index].flag & ME_SMOOTH; -} - -int16_t OBJMesh::ith_poly_matnr(const int poly_index) const -{ - BLI_assert(poly_index < export_mesh_eval_->totpoly); - const int16_t r_mat_nr = export_mesh_eval_->mpoly[poly_index].mat_nr; - return r_mat_nr >= 0 ? r_mat_nr : NOT_FOUND; + const Span<MPoly> polys = export_mesh_eval_->polys(); + return polys[poly_index].flag & ME_SMOOTH; } const char *OBJMesh::get_object_name() const @@ -263,7 +268,8 @@ const char *OBJMesh::get_object_material_name(const int16_t mat_nr) const float3 OBJMesh::calc_vertex_coords(const int vert_index, const float scaling_factor) const { float3 r_coords; - copy_v3_v3(r_coords, export_mesh_eval_->mvert[vert_index].co); + const Span<MVert> verts = export_mesh_eval_->verts(); + copy_v3_v3(r_coords, verts[vert_index].co); mul_m4_v3(world_and_axes_transform_, r_coords); mul_v3_fl(r_coords, scaling_factor); return r_coords; @@ -271,8 +277,10 @@ float3 OBJMesh::calc_vertex_coords(const int vert_index, const float scaling_fac Vector<int> OBJMesh::calc_poly_vertex_indices(const int poly_index) const { - const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index]; - const MLoop *mloop = &export_mesh_eval_->mloop[mpoly.loopstart]; + const Span<MPoly> polys = export_mesh_eval_->polys(); + const Span<MLoop> loops = export_mesh_eval_->loops(); + const MPoly &mpoly = polys[poly_index]; + const MLoop *mloop = &loops[mpoly.loopstart]; const int totloop = mpoly.totloop; Vector<int> r_poly_vertex_indices(totloop); for (int loop_index = 0; loop_index < totloop; loop_index++) { @@ -283,9 +291,8 @@ Vector<int> OBJMesh::calc_poly_vertex_indices(const int poly_index) const void OBJMesh::store_uv_coords_and_indices() { - const MPoly *mpoly = export_mesh_eval_->mpoly; - const MLoop *mloop = export_mesh_eval_->mloop; - const int totpoly = export_mesh_eval_->totpoly; + const Span<MPoly> polys = export_mesh_eval_->polys(); + const Span<MLoop> loops = export_mesh_eval_->loops(); const int totvert = export_mesh_eval_->totvert; const MLoopUV *mloopuv = static_cast<const MLoopUV *>( CustomData_get_layer(&export_mesh_eval_->ldata, CD_MLOOPUV)); @@ -295,10 +302,18 @@ void OBJMesh::store_uv_coords_and_indices() } const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT}; - UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create( - mpoly, nullptr, mloop, mloopuv, totpoly, totvert, limit, false, false); - - uv_indices_.resize(totpoly); + UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(polys.data(), + nullptr, + nullptr, + loops.data(), + mloopuv, + polys.size(), + totvert, + limit, + false, + false); + + uv_indices_.resize(polys.size()); /* At least total vertices of a mesh will be present in its texture map. So * reserve minimum space early. */ uv_coords_.reserve(totvert); @@ -310,16 +325,16 @@ void OBJMesh::store_uv_coords_and_indices() if (uv_vert->separate) { tot_uv_vertices_ += 1; } - const int vertices_in_poly = mpoly[uv_vert->poly_index].totloop; + const int verts_in_poly = polys[uv_vert->poly_index].totloop; /* Store UV vertex coordinates. */ uv_coords_.resize(tot_uv_vertices_); - const int loopstart = mpoly[uv_vert->poly_index].loopstart; + const int loopstart = polys[uv_vert->poly_index].loopstart; Span<float> vert_uv_coords(mloopuv[loopstart + uv_vert->loop_of_poly_index].uv, 2); uv_coords_[tot_uv_vertices_ - 1] = float2(vert_uv_coords[0], vert_uv_coords[1]); /* Store UV vertex indices. */ - uv_indices_[uv_vert->poly_index].resize(vertices_in_poly); + uv_indices_[uv_vert->poly_index].resize(verts_in_poly); /* Keep indices zero-based and let the writer handle the "+ 1" as per OBJ spec. */ uv_indices_[uv_vert->poly_index][uv_vert->loop_of_poly_index] = tot_uv_vertices_ - 1; } @@ -340,10 +355,11 @@ Span<int> OBJMesh::calc_poly_uv_indices(const int poly_index) const float3 OBJMesh::calc_poly_normal(const int poly_index) const { float3 r_poly_normal; - const MPoly &poly = export_mesh_eval_->mpoly[poly_index]; - const MLoop &mloop = export_mesh_eval_->mloop[poly.loopstart]; - const MVert &mvert = *(export_mesh_eval_->mvert); - BKE_mesh_calc_poly_normal(&poly, &mloop, &mvert, r_poly_normal); + const Span<MVert> verts = export_mesh_eval_->verts(); + const Span<MPoly> polys = export_mesh_eval_->polys(); + const Span<MLoop> loops = export_mesh_eval_->loops(); + const MPoly &poly = polys[poly_index]; + BKE_mesh_calc_poly_normal(&poly, &loops[poly.loopstart], verts.data(), r_poly_normal); mul_m3_v3(world_and_axes_normal_transform_, r_poly_normal); normalize_v3(r_poly_normal); return r_poly_normal; @@ -353,7 +369,7 @@ float3 OBJMesh::calc_poly_normal(const int poly_index) const static float round_float_to_n_digits(const float f, int round_digits) { float scale = powf(10.0, round_digits); - return ceilf((scale * f - 0.49999999f)) / scale; + return ceilf(scale * f - 0.49999999f) / scale; } static float3 round_float3_to_n_digits(const float3 &v, int round_digits) @@ -367,6 +383,8 @@ static float3 round_float3_to_n_digits(const float3 &v, int round_digits) void OBJMesh::store_normal_coords_and_indices() { + const Span<MPoly> polys = export_mesh_eval_->polys(); + /* We'll round normal components to 4 digits. * This will cover up some minor differences * between floating point calculations on different platforms. @@ -382,7 +400,7 @@ void OBJMesh::store_normal_coords_and_indices() const float(*lnors)[3] = static_cast<const float(*)[3]>( CustomData_get_layer(&export_mesh_eval_->ldata, CD_NORMAL)); for (int poly_index = 0; poly_index < export_mesh_eval_->totpoly; ++poly_index) { - const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index]; + const MPoly &mpoly = polys[poly_index]; bool need_per_loop_normals = lnors != nullptr || (mpoly.flag & ME_SMOOTH); if (need_per_loop_normals) { for (int loop_of_poly = 0; loop_of_poly < mpoly.totloop; ++loop_of_poly) { @@ -426,7 +444,8 @@ Vector<int> OBJMesh::calc_poly_normal_indices(const int poly_index) const if (loop_to_normal_index_.is_empty()) { return {}; } - const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index]; + const Span<MPoly> polys = export_mesh_eval_->polys(); + const MPoly &mpoly = polys[poly_index]; const int totloop = mpoly.totloop; Vector<int> r_poly_normal_indices(totloop); for (int poly_loop_index = 0; poly_loop_index < totloop; poly_loop_index++) { @@ -449,23 +468,23 @@ int16_t OBJMesh::get_poly_deform_group_index(const int poly_index, { BLI_assert(poly_index < export_mesh_eval_->totpoly); BLI_assert(group_weights.size() == BKE_object_defgroup_count(&export_object_eval_)); - - const MDeformVert *dvert_layer = static_cast<const MDeformVert *>( - CustomData_get_layer(&export_mesh_eval_->vdata, CD_MDEFORMVERT)); - if (!dvert_layer) { + const Span<MPoly> polys = export_mesh_eval_->polys(); + const Span<MLoop> loops = export_mesh_eval_->loops(); + const Span<MDeformVert> dverts = export_mesh_eval_->deform_verts(); + if (dverts.is_empty()) { return NOT_FOUND; } group_weights.fill(0); bool found_any_group = false; - const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index]; - const MLoop *mloop = &export_mesh_eval_->mloop[mpoly.loopstart]; + const MPoly &mpoly = polys[poly_index]; + const MLoop *mloop = &loops[mpoly.loopstart]; for (int loop_i = 0; loop_i < mpoly.totloop; ++loop_i, ++mloop) { - const MDeformVert &dvert = dvert_layer[mloop->v]; - for (int weight_i = 0; weight_i < dvert.totweight; ++weight_i) { - const auto group = dvert.dw[weight_i].def_nr; + const MDeformVert &dv = dverts[mloop->v]; + for (int weight_i = 0; weight_i < dv.totweight; ++weight_i) { + const auto group = dv.dw[weight_i].def_nr; if (group < group_weights.size()) { - group_weights[group] += dvert.dw[weight_i].weight; + group_weights[group] += dv.dw[weight_i].weight; found_any_group = true; } } @@ -489,9 +508,10 @@ const char *OBJMesh::get_poly_deform_group_name(const int16_t def_group_index) c std::optional<std::array<int, 2>> OBJMesh::calc_loose_edge_vert_indices(const int edge_index) const { - const MEdge &edge = export_mesh_eval_->medge[edge_index]; + const Span<MEdge> edges = export_mesh_eval_->edges(); + const MEdge &edge = edges[edge_index]; if (edge.flag & ME_LOOSEEDGE) { - return std::array<int, 2>{static_cast<int>(edge.v1), static_cast<int>(edge.v2)}; + return std::array<int, 2>{int(edge.v1), int(edge.v2)}; } return std::nullopt; } diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh index ee2e6227700..db29f5651ed 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh @@ -130,11 +130,6 @@ class OBJMesh : NonCopyable { * Return mat_nr-th material of the object. The given index should be zero-based. */ const Material *get_object_material(int16_t mat_nr) const; - /** - * Returns a zero-based index of a polygon's material indexing into - * the Object's material slots. - */ - int16_t ith_poly_matnr(int poly_index) const; void ensure_mesh_normals() const; void ensure_mesh_edges() const; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc index 4ed148ec64e..0231bc79b89 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc @@ -6,6 +6,7 @@ #include "BKE_image.h" #include "BKE_node.h" +#include "BKE_node_runtime.hh" #include "BLI_map.hh" #include "BLI_math_vector.h" @@ -15,13 +16,26 @@ #include "DNA_material_types.h" #include "DNA_node_types.h" -#include "NOD_node_tree_ref.hh" - #include "obj_export_mesh.hh" #include "obj_export_mtl.hh" namespace blender::io::obj { +const char *tex_map_type_to_socket_id[] = { + "Base Color", + "Metallic", + "Specular", + "Roughness", /* Map specular exponent to roughness. */ + "Roughness", + "Sheen", + "Metallic", /* Map reflection to metallic. */ + "Emission", + "Alpha", + "Normal", +}; +BLI_STATIC_ASSERT(ARRAY_SIZE(tex_map_type_to_socket_id) == int(MTLTexMapType::Count), + "array size mismatch"); + /** * Copy a float property of the given type from the bNode to given buffer. */ @@ -72,25 +86,25 @@ static void copy_property_from_node(const eNodeSocketDatatype property_type, * Collect all the source sockets linked to the destination socket in a destination node. */ static void linked_sockets_to_dest_id(const bNode *dest_node, - const nodes::NodeTreeRef &node_tree, - StringRefNull dest_socket_id, - Vector<const nodes::OutputSocketRef *> &r_linked_sockets) + const bNodeTree &node_tree, + const char *dest_socket_id, + Vector<const bNodeSocket *> &r_linked_sockets) { r_linked_sockets.clear(); if (!dest_node) { return; } - Span<const nodes::NodeRef *> object_dest_nodes = node_tree.nodes_by_type(dest_node->idname); - Span<const nodes::InputSocketRef *> dest_inputs = object_dest_nodes.first()->inputs(); - const nodes::InputSocketRef *dest_socket = nullptr; - for (const nodes::InputSocketRef *curr_socket : dest_inputs) { - if (STREQ(curr_socket->bsocket()->identifier, dest_socket_id.c_str())) { + Span<const bNode *> object_dest_nodes = node_tree.nodes_by_type(dest_node->idname); + Span<const bNodeSocket *> dest_inputs = object_dest_nodes.first()->input_sockets(); + const bNodeSocket *dest_socket = nullptr; + for (const bNodeSocket *curr_socket : dest_inputs) { + if (STREQ(curr_socket->identifier, dest_socket_id)) { dest_socket = curr_socket; break; } } if (dest_socket) { - Span<const nodes::OutputSocketRef *> linked_sockets = dest_socket->directly_linked_sockets(); + Span<const bNodeSocket *> linked_sockets = dest_socket->directly_linked_sockets(); r_linked_sockets.resize(linked_sockets.size()); r_linked_sockets = linked_sockets; } @@ -99,40 +113,52 @@ static void linked_sockets_to_dest_id(const bNode *dest_node, /** * From a list of sockets, get the parent node which is of the given node type. */ -static const bNode *get_node_of_type(Span<const nodes::OutputSocketRef *> sockets_list, - const int node_type) +static const bNode *get_node_of_type(Span<const bNodeSocket *> sockets_list, const int node_type) { - for (const nodes::SocketRef *socket : sockets_list) { - const bNode *parent_node = socket->bnode(); - if (parent_node->typeinfo->type == node_type) { - return parent_node; + for (const bNodeSocket *socket : sockets_list) { + const bNode &parent_node = socket->owner_node(); + if (parent_node.typeinfo->type == node_type) { + return &parent_node; } } return nullptr; } -/** +/* * From a texture image shader node, get the image's filepath. * If packed image is found, only the file "name" is returned. */ -static const char *get_image_filepath(const bNode *tex_node) +static std::string get_image_filepath(const bNode *tex_node) { if (!tex_node) { - return nullptr; + return ""; } Image *tex_image = reinterpret_cast<Image *>(tex_node->id); if (!tex_image || !BKE_image_has_filepath(tex_image)) { - return nullptr; + return ""; } - const char *path = tex_image->filepath; + if (BKE_image_has_packedfile(tex_image)) { /* Put image in the same directory as the .MTL file. */ - path = BLI_path_slash_rfind(path) + 1; + const char *filename = BLI_path_slash_rfind(tex_image->filepath) + 1; fprintf(stderr, "Packed image found:'%s'. Unpack and place the image in the same " "directory as the .MTL file.\n", - path); + filename); + return filename; } + + char path[FILE_MAX]; + BLI_strncpy(path, tex_image->filepath, FILE_MAX); + + if (tex_image->source == IMA_SRC_SEQUENCE) { + char head[FILE_MAX], tail[FILE_MAX]; + ushort numlen; + int framenr = static_cast<NodeTexImage *>(tex_node->storage)->iuser.framenr; + BLI_path_sequence_decode(path, head, tail, &numlen); + BLI_path_sequence_encode(path, head, tail, numlen, framenr); + } + return path; } @@ -141,16 +167,16 @@ static const char *get_image_filepath(const bNode *tex_node) * We only want one that feeds directly into a Material Output node * (that is the behavior of the legacy Python exporter). */ -static const nodes::NodeRef *find_bsdf_node(const nodes::NodeTreeRef *nodetree) +static const bNode *find_bsdf_node(const bNodeTree *nodetree) { if (!nodetree) { return nullptr; } - for (const nodes::NodeRef *node : nodetree->nodes_by_type("ShaderNodeOutputMaterial")) { - const nodes::InputSocketRef *node_input_socket0 = node->inputs()[0]; - for (const nodes::OutputSocketRef *out_sock : node_input_socket0->directly_linked_sockets()) { - const nodes::NodeRef &in_node = out_sock->node(); - if (in_node.typeinfo()->type == SH_NODE_BSDF_PRINCIPLED) { + for (const bNode *node : nodetree->nodes_by_type("ShaderNodeOutputMaterial")) { + const bNodeSocket &node_input_socket0 = node->input_socket(0); + for (const bNodeSocket *out_sock : node_input_socket0.directly_linked_sockets()) { + const bNode &in_node = out_sock->owner_node(); + if (in_node.typeinfo->type == SH_NODE_BSDF_PRINCIPLED) { return &in_node; } } @@ -161,58 +187,68 @@ static const nodes::NodeRef *find_bsdf_node(const nodes::NodeTreeRef *nodetree) /** * Store properties found either in bNode or material into r_mtl_mat. */ -static void store_bsdf_properties(const nodes::NodeRef *bsdf_node, +static void store_bsdf_properties(const bNode *bsdf_node, const Material *material, MTLMaterial &r_mtl_mat) { - const bNode *bnode = nullptr; - if (bsdf_node) { - bnode = bsdf_node->bnode(); - } - - /* If p-BSDF is not present, fallback to #Object.Material. */ float roughness = material->roughness; - if (bnode) { - copy_property_from_node(SOCK_FLOAT, bnode, "Roughness", {&roughness, 1}); + if (bsdf_node) { + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Roughness", {&roughness, 1}); } /* Empirical approximation. Importer should use the inverse of this method. */ float spec_exponent = (1.0f - roughness); spec_exponent *= spec_exponent * 1000.0f; float specular = material->spec; - if (bnode) { - copy_property_from_node(SOCK_FLOAT, bnode, "Specular", {&specular, 1}); + if (bsdf_node) { + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Specular", {&specular, 1}); } float metallic = material->metallic; - if (bnode) { - copy_property_from_node(SOCK_FLOAT, bnode, "Metallic", {&metallic, 1}); + if (bsdf_node) { + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Metallic", {&metallic, 1}); } float refraction_index = 1.0f; - if (bnode) { - copy_property_from_node(SOCK_FLOAT, bnode, "IOR", {&refraction_index, 1}); + if (bsdf_node) { + copy_property_from_node(SOCK_FLOAT, bsdf_node, "IOR", {&refraction_index, 1}); } - float dissolved = material->a; - if (bnode) { - copy_property_from_node(SOCK_FLOAT, bnode, "Alpha", {&dissolved, 1}); + float alpha = material->a; + if (bsdf_node) { + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Alpha", {&alpha, 1}); } - const bool transparent = dissolved != 1.0f; + const bool transparent = alpha != 1.0f; float3 diffuse_col = {material->r, material->g, material->b}; - if (bnode) { - copy_property_from_node(SOCK_RGBA, bnode, "Base Color", {diffuse_col, 3}); + if (bsdf_node) { + copy_property_from_node(SOCK_RGBA, bsdf_node, "Base Color", {diffuse_col, 3}); } float3 emission_col{0.0f}; float emission_strength = 0.0f; - if (bnode) { - copy_property_from_node(SOCK_FLOAT, bnode, "Emission Strength", {&emission_strength, 1}); - copy_property_from_node(SOCK_RGBA, bnode, "Emission", {emission_col, 3}); + if (bsdf_node) { + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Emission Strength", {&emission_strength, 1}); + copy_property_from_node(SOCK_RGBA, bsdf_node, "Emission", {emission_col, 3}); } mul_v3_fl(emission_col, emission_strength); + float sheen = -1.0f; + float clearcoat = -1.0f; + float clearcoat_roughness = -1.0f; + float aniso = -1.0f; + float aniso_rot = -1.0f; + float transmission = -1.0f; + if (bsdf_node) { + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Sheen", {&sheen, 1}); + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Clearcoat", {&clearcoat, 1}); + copy_property_from_node( + SOCK_FLOAT, bsdf_node, "Clearcoat Roughness", {&clearcoat_roughness, 1}); + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Anisotropic", {&aniso, 1}); + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Anisotropic Rotation", {&aniso_rot, 1}); + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Transmission", {&transmission, 1}); + } + /* See https://wikipedia.org/wiki/Wavefront_.obj_file for all possible values of `illum`. */ /* Highlight on. */ int illum = 2; @@ -235,26 +271,34 @@ static void store_bsdf_properties(const nodes::NodeRef *bsdf_node, /* Transparency: Glass on, Reflection: Ray trace off */ illum = 9; } - r_mtl_mat.Ns = spec_exponent; + r_mtl_mat.spec_exponent = spec_exponent; if (metallic != 0.0f) { - r_mtl_mat.Ka = {metallic, metallic, metallic}; + r_mtl_mat.ambient_color = {metallic, metallic, metallic}; } else { - r_mtl_mat.Ka = {1.0f, 1.0f, 1.0f}; + r_mtl_mat.ambient_color = {1.0f, 1.0f, 1.0f}; } - r_mtl_mat.Kd = diffuse_col; - r_mtl_mat.Ks = {specular, specular, specular}; - r_mtl_mat.Ke = emission_col; - r_mtl_mat.Ni = refraction_index; - r_mtl_mat.d = dissolved; - r_mtl_mat.illum = illum; + r_mtl_mat.color = diffuse_col; + r_mtl_mat.spec_color = {specular, specular, specular}; + r_mtl_mat.emission_color = emission_col; + r_mtl_mat.ior = refraction_index; + r_mtl_mat.alpha = alpha; + r_mtl_mat.illum_mode = illum; + r_mtl_mat.roughness = roughness; + r_mtl_mat.metallic = metallic; + r_mtl_mat.sheen = sheen; + r_mtl_mat.cc_thickness = clearcoat; + r_mtl_mat.cc_roughness = clearcoat_roughness; + r_mtl_mat.aniso = aniso; + r_mtl_mat.aniso_rot = aniso_rot; + r_mtl_mat.transmit_color = {transmission, transmission, transmission}; } /** * Store image texture options and file-paths in `r_mtl_mat`. */ -static void store_image_textures(const nodes::NodeRef *bsdf_node, - const nodes::NodeTreeRef *node_tree, +static void store_image_textures(const bNode *bsdf_node, + const bNodeTree *node_tree, const Material *material, MTLMaterial &r_mtl_mat) { @@ -262,21 +306,20 @@ static void store_image_textures(const nodes::NodeRef *bsdf_node, /* No nodetree, no images, or no Principled BSDF node. */ return; } - const bNode *bnode = bsdf_node->bnode(); /* Normal Map Texture has two extra tasks of: * - finding a Normal Map node before finding a texture node. * - finding "Strength" property of the node for `-bm` option. */ - for (Map<const eMTLSyntaxElement, tex_map_XX>::MutableItem texture_map : - r_mtl_mat.texture_maps.items()) { - Vector<const nodes::OutputSocketRef *> linked_sockets; + for (int key = 0; key < int(MTLTexMapType::Count); ++key) { + MTLTexMap &value = r_mtl_mat.texture_maps[key]; + Vector<const bNodeSocket *> linked_sockets; const bNode *normal_map_node{nullptr}; - if (texture_map.key == eMTLSyntaxElement::map_Bump) { + if (key == int(MTLTexMapType::Normal)) { /* Find sockets linked to destination "Normal" socket in P-BSDF node. */ - linked_sockets_to_dest_id(bnode, *node_tree, "Normal", linked_sockets); + linked_sockets_to_dest_id(bsdf_node, *node_tree, "Normal", linked_sockets); /* Among the linked sockets, find Normal Map shader node. */ normal_map_node = get_node_of_type(linked_sockets, SH_NODE_NORMAL_MAP); @@ -285,16 +328,17 @@ static void store_image_textures(const nodes::NodeRef *bsdf_node, } else { /* Skip emission map if emission strength is zero. */ - if (texture_map.key == eMTLSyntaxElement::map_Ke) { + if (key == int(MTLTexMapType::Emission)) { float emission_strength = 0.0f; - copy_property_from_node(SOCK_FLOAT, bnode, "Emission Strength", {&emission_strength, 1}); + copy_property_from_node( + SOCK_FLOAT, bsdf_node, "Emission Strength", {&emission_strength, 1}); if (emission_strength == 0.0f) { continue; } } /* Find sockets linked to the destination socket of interest, in P-BSDF node. */ linked_sockets_to_dest_id( - bnode, *node_tree, texture_map.value.dest_socket_id, linked_sockets); + bsdf_node, *node_tree, tex_map_type_to_socket_id[key], linked_sockets); } /* Among the linked sockets, find Image Texture shader node. */ @@ -302,8 +346,8 @@ static void store_image_textures(const nodes::NodeRef *bsdf_node, if (!tex_node) { continue; } - const char *tex_image_filepath = get_image_filepath(tex_node); - if (!tex_image_filepath) { + const std::string tex_image_filepath = get_image_filepath(tex_node); + if (tex_image_filepath.empty()) { continue; } @@ -313,14 +357,14 @@ static void store_image_textures(const nodes::NodeRef *bsdf_node, if (normal_map_node) { copy_property_from_node( - SOCK_FLOAT, normal_map_node, "Strength", {&r_mtl_mat.map_Bump_strength, 1}); + SOCK_FLOAT, normal_map_node, "Strength", {&r_mtl_mat.normal_strength, 1}); } /* Texture transform options. Only translation (origin offset, "-o") and scale * ("-o") are supported. */ - copy_property_from_node(SOCK_VECTOR, mapping, "Location", {texture_map.value.translation, 3}); - copy_property_from_node(SOCK_VECTOR, mapping, "Scale", {texture_map.value.scale, 3}); + copy_property_from_node(SOCK_VECTOR, mapping, "Location", {value.translation, 3}); + copy_property_from_node(SOCK_VECTOR, mapping, "Scale", {value.scale, 3}); - texture_map.value.image_path = tex_image_filepath; + value.image_path = tex_image_filepath; } } @@ -330,14 +374,14 @@ MTLMaterial mtlmaterial_for_material(const Material *material) MTLMaterial mtlmat; mtlmat.name = std::string(material->id.name + 2); std::replace(mtlmat.name.begin(), mtlmat.name.end(), ' ', '_'); - const nodes::NodeTreeRef *nodetree = nullptr; - if (material->nodetree) { - nodetree = new nodes::NodeTreeRef(material->nodetree); + const bNodeTree *nodetree = material->nodetree; + if (nodetree != nullptr) { + nodetree->ensure_topology_cache(); } - const nodes::NodeRef *bsdf_node = find_bsdf_node(nodetree); + + const bNode *bsdf_node = find_bsdf_node(nodetree); store_bsdf_properties(bsdf_node, material, mtlmat); store_image_textures(bsdf_node, nodetree, material, mtlmat); - delete nodetree; return mtlmat; } diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mtl.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.hh index f83b3b49bf5..2d4edd8979d 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mtl.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.hh @@ -6,36 +6,35 @@ #pragma once -#include "BLI_map.hh" #include "BLI_math_vec_types.hh" #include "DNA_node_types.h" -#include "obj_export_io.hh" - -namespace blender { -template<> struct DefaultHash<io::obj::eMTLSyntaxElement> { - uint64_t operator()(const io::obj::eMTLSyntaxElement value) const - { - return static_cast<uint64_t>(value); - } -}; - -} // namespace blender +struct Material; namespace blender::io::obj { -/** - * Generic container for texture node properties. - */ -struct tex_map_XX { - tex_map_XX(StringRef to_socket_id) : dest_socket_id(to_socket_id){}; +enum class MTLTexMapType { + Color = 0, + Metallic, + Specular, + SpecularExponent, + Roughness, + Sheen, + Reflection, + Emission, + Alpha, + Normal, + Count +}; +extern const char *tex_map_type_to_socket_id[]; + +struct MTLTexMap { bool is_valid() const { return !image_path.empty(); } /* Target socket which this texture node connects to. */ - const std::string dest_socket_id; float3 translation{0.0f}; float3 scale{1.0f}; /* Only Flat and Sphere projections are supported. */ @@ -48,42 +47,38 @@ struct tex_map_XX { * Container suited for storing Material data for/from a .MTL file. */ struct MTLMaterial { - MTLMaterial() - { - texture_maps.add(eMTLSyntaxElement::map_Kd, tex_map_XX("Base Color")); - texture_maps.add(eMTLSyntaxElement::map_Ks, tex_map_XX("Specular")); - texture_maps.add(eMTLSyntaxElement::map_Ns, tex_map_XX("Roughness")); - texture_maps.add(eMTLSyntaxElement::map_d, tex_map_XX("Alpha")); - texture_maps.add(eMTLSyntaxElement::map_refl, tex_map_XX("Metallic")); - texture_maps.add(eMTLSyntaxElement::map_Ke, tex_map_XX("Emission")); - texture_maps.add(eMTLSyntaxElement::map_Bump, tex_map_XX("Normal")); - } - - const tex_map_XX &tex_map_of_type(const eMTLSyntaxElement key) const + const MTLTexMap &tex_map_of_type(MTLTexMapType key) const { - BLI_assert(texture_maps.contains(key)); - return texture_maps.lookup(key); + return texture_maps[int(key)]; } - tex_map_XX &tex_map_of_type(const eMTLSyntaxElement key) + MTLTexMap &tex_map_of_type(MTLTexMapType key) { - BLI_assert(texture_maps.contains(key)); - return texture_maps.lookup(key); + return texture_maps[int(key)]; } std::string name; /* Always check for negative values while importing or exporting. Use defaults if * any value is negative. */ - float Ns{-1.0f}; - float3 Ka{-1.0f}; - float3 Kd{-1.0f}; - float3 Ks{-1.0f}; - float3 Ke{-1.0f}; - float Ni{-1.0f}; - float d{-1.0f}; - int illum{-1}; - Map<const eMTLSyntaxElement, tex_map_XX> texture_maps; - /** Only used for Normal Map node: "map_Bump". */ - float map_Bump_strength{-1.0f}; + float spec_exponent{-1.0f}; /* `Ns` */ + float3 ambient_color{-1.0f}; /* `Ka` */ + float3 color{-1.0f}; /* `Kd` */ + float3 spec_color{-1.0f}; /* `Ks` */ + float3 emission_color{-1.0f}; /* `Ke` */ + float ior{-1.0f}; /* `Ni` */ + float alpha{-1.0f}; /* `d` */ + float3 transmit_color{-1.0f}; /* `Kt` / `Tf` */ + float roughness{-1.0f}; /* `Pr` */ + float metallic{-1.0f}; /* `Pm` */ + float sheen{-1.0f}; /* `Ps` */ + float cc_thickness{-1.0f}; /* `Pc` */ + float cc_roughness{-1.0f}; /* `Pcr` */ + float aniso{-1.0f}; /* `aniso` */ + float aniso_rot{-1.0f}; /* `anisor` */ + + int illum_mode{-1}; + MTLTexMap texture_maps[int(MTLTexMapType::Count)]; + /* Only used for Normal Map node: `map_Bump`. */ + float normal_strength{-1.0f}; }; MTLMaterial mtlmaterial_for_material(const Material *material); diff --git a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc index 77d4f6268bc..daf2a06e112 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc @@ -89,11 +89,12 @@ filter_supported_objects(Depsgraph *depsgraph, const OBJExportParams &export_par { Vector<std::unique_ptr<OBJMesh>> r_exportable_meshes; Vector<std::unique_ptr<OBJCurve>> r_exportable_nurbs; - const int deg_objects_visibility_flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | - DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI; - DEG_OBJECT_ITER_BEGIN (depsgraph, object, deg_objects_visibility_flags) { + DEGObjectIterSettings deg_iter_settings{}; + deg_iter_settings.depsgraph = depsgraph; + deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI; + DEG_OBJECT_ITER_BEGIN (°_iter_settings, object) { if (export_params.export_selected_objects && !(object->base_flag & BASE_SELECTED)) { continue; } @@ -143,7 +144,7 @@ static void write_mesh_objects(Vector<std::unique_ptr<OBJMesh>> exportable_as_me * we have to have the output text buffer for each object, * and write them all into the file at the end. */ size_t count = exportable_as_mesh.size(); - std::vector<FormatHandler<eFileType::OBJ>> buffers(count); + std::vector<FormatHandler> buffers(count); /* Serial: gather material indices, ensure normals & edges. */ Vector<Vector<int>> mtlindices; @@ -242,7 +243,7 @@ static void write_mesh_objects(Vector<std::unique_ptr<OBJMesh>> exportable_as_me static void write_nurbs_curve_objects(const Vector<std::unique_ptr<OBJCurve>> &exportable_as_nurbs, const OBJWriter &obj_writer) { - FormatHandler<eFileType::OBJ> fh; + FormatHandler fh; /* #OBJCurve doesn't have any dynamically allocated memory, so it's fine * to wait for #blender::Vector to clean the objects up. */ for (const std::unique_ptr<OBJCurve> &obj_curve : exportable_as_nurbs) { @@ -268,7 +269,7 @@ void export_frame(Depsgraph *depsgraph, const OBJExportParams &export_params, co std::unique_ptr<MTLWriter> mtl_writer = nullptr; if (export_params.export_materials) { try { - mtl_writer = std::make_unique<MTLWriter>(export_params.filepath); + mtl_writer = std::make_unique<MTLWriter>(filepath); } catch (const std::system_error &ex) { print_exception_error(ex); @@ -293,7 +294,10 @@ void export_frame(Depsgraph *depsgraph, const OBJExportParams &export_params, co } BLI_path_slash_native(dest_dir); BLI_path_normalize(nullptr, dest_dir); - mtl_writer->write_materials(export_params.blen_filepath, export_params.path_mode, dest_dir); + mtl_writer->write_materials(export_params.blen_filepath, + export_params.path_mode, + dest_dir, + export_params.export_pbr_extensions); } write_nurbs_curve_objects(std::move(exportable_as_nurbs), *frame_writer); } diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc index 7069e1185e0..bd1c2d32a12 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc @@ -10,6 +10,7 @@ #include "BLI_string_ref.hh" #include "BLI_vector.hh" +#include "obj_export_mtl.hh" #include "obj_import_file_reader.hh" #include "obj_import_string_utils.hh" @@ -102,10 +103,10 @@ static void geom_add_mrgb_colors(const char *p, const char *end, GlobalVertices while (p + mrgb_length <= end) { uint32_t value = 0; std::from_chars_result res = std::from_chars(p, p + mrgb_length, value, 16); - if (res.ec == std::errc::invalid_argument || res.ec == std::errc::result_out_of_range) { + if (ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) { return; } - unsigned char srgb[4]; + uchar srgb[4]; srgb[0] = (value >> 16) & 0xFF; srgb[1] = (value >> 8) & 0xFF; srgb[2] = value & 0xFF; @@ -163,7 +164,7 @@ static void geom_add_edge(Geometry *geom, edge_v1 += edge_v1 < 0 ? r_global_vertices.vertices.size() : -1; edge_v2 += edge_v2 < 0 ? r_global_vertices.vertices.size() : -1; BLI_assert(edge_v1 >= 0 && edge_v2 >= 0); - geom->edges_.append({static_cast<uint>(edge_v1), static_cast<uint>(edge_v2)}); + geom->edges_.append({uint(edge_v1), uint(edge_v2)}); geom->track_vertex_index(edge_v1); geom->track_vertex_index(edge_v2); } @@ -215,7 +216,7 @@ static void geom_add_polygon(Geometry *geom, fprintf(stderr, "Invalid vertex index %i (valid range [0, %zu)), ignoring face\n", corner.vert_index, - (size_t)global_vertices.vertices.size()); + size_t(global_vertices.vertices.size())); face_valid = false; } else { @@ -227,7 +228,7 @@ static void geom_add_polygon(Geometry *geom, fprintf(stderr, "Invalid UV index %i (valid range [0, %zu)), ignoring face\n", corner.uv_vert_index, - (size_t)global_vertices.uv_vertices.size()); + size_t(global_vertices.uv_vertices.size())); face_valid = false; } } @@ -243,7 +244,7 @@ static void geom_add_polygon(Geometry *geom, fprintf(stderr, "Invalid normal index %i (valid range [0, %zu)), ignoring face\n", corner.vertex_normal_index, - (size_t)global_vertices.vertex_normals.size()); + size_t(global_vertices.vertex_normals.size())); face_valid = false; } } @@ -484,7 +485,7 @@ void OBJParser::parse(Vector<std::unique_ptr<Geometry>> &r_all_geometries, /* Parse the buffer (until last newline) that we have so far, * line by line. */ - StringRef buffer_str{buffer.data(), (int64_t)last_nl}; + StringRef buffer_str{buffer.data(), int64_t(last_nl)}; while (!buffer_str.is_empty()) { StringRef line = read_next_line(buffer_str); const char *p = line.begin(), *end = line.end(); @@ -592,36 +593,40 @@ void OBJParser::parse(Vector<std::unique_ptr<Geometry>> &r_all_geometries, add_default_mtl_library(); } -static eMTLSyntaxElement mtl_line_start_to_enum(const char *&p, const char *end) +static MTLTexMapType mtl_line_start_to_texture_type(const char *&p, const char *end) { if (parse_keyword(p, end, "map_Kd")) { - return eMTLSyntaxElement::map_Kd; + return MTLTexMapType::Color; } if (parse_keyword(p, end, "map_Ks")) { - return eMTLSyntaxElement::map_Ks; + return MTLTexMapType::Specular; } if (parse_keyword(p, end, "map_Ns")) { - return eMTLSyntaxElement::map_Ns; + return MTLTexMapType::SpecularExponent; } if (parse_keyword(p, end, "map_d")) { - return eMTLSyntaxElement::map_d; + return MTLTexMapType::Alpha; } - if (parse_keyword(p, end, "refl")) { - return eMTLSyntaxElement::map_refl; - } - if (parse_keyword(p, end, "map_refl")) { - return eMTLSyntaxElement::map_refl; + if (parse_keyword(p, end, "refl") || parse_keyword(p, end, "map_refl")) { + return MTLTexMapType::Reflection; } if (parse_keyword(p, end, "map_Ke")) { - return eMTLSyntaxElement::map_Ke; + return MTLTexMapType::Emission; + } + if (parse_keyword(p, end, "bump") || parse_keyword(p, end, "map_Bump") || + parse_keyword(p, end, "map_bump")) { + return MTLTexMapType::Normal; + } + if (parse_keyword(p, end, "map_Pr")) { + return MTLTexMapType::Roughness; } - if (parse_keyword(p, end, "bump")) { - return eMTLSyntaxElement::map_Bump; + if (parse_keyword(p, end, "map_Pm")) { + return MTLTexMapType::Metallic; } - if (parse_keyword(p, end, "map_Bump") || parse_keyword(p, end, "map_bump")) { - return eMTLSyntaxElement::map_Bump; + if (parse_keyword(p, end, "map_Ps")) { + return MTLTexMapType::Sheen; } - return eMTLSyntaxElement::string; + return MTLTexMapType::Count; } static const std::pair<StringRef, int> unsupported_texture_options[] = { @@ -639,7 +644,7 @@ static const std::pair<StringRef, int> unsupported_texture_options[] = { static bool parse_texture_option(const char *&p, const char *end, MTLMaterial *material, - tex_map_XX &tex_map) + MTLTexMap &tex_map) { p = drop_whitespace(p, end); if (parse_keyword(p, end, "-o")) { @@ -651,7 +656,7 @@ static bool parse_texture_option(const char *&p, return true; } if (parse_keyword(p, end, "-bm")) { - p = parse_float(p, end, 1.0f, material->map_Bump_strength, true, true); + p = parse_float(p, end, 1.0f, material->normal_strength, true, true); return true; } if (parse_keyword(p, end, "-type")) { @@ -693,13 +698,13 @@ static void parse_texture_map(const char *p, if (!is_map && !is_refl && !is_bump) { return; } - eMTLSyntaxElement key = mtl_line_start_to_enum(p, end); - if (key == eMTLSyntaxElement::string || !material->texture_maps.contains(key)) { + MTLTexMapType key = mtl_line_start_to_texture_type(p, end); + if (key == MTLTexMapType::Count) { /* No supported texture map found. */ std::cerr << "OBJ import: MTL texture map type not supported: '" << line << "'" << std::endl; return; } - tex_map_XX &tex_map = material->texture_maps.lookup(key); + MTLTexMap &tex_map = material->tex_map_of_type(key); tex_map.mtl_dir_path = mtl_dir_path; /* Parse texture map options. */ @@ -748,7 +753,7 @@ MTLParser::MTLParser(StringRefNull mtl_library, StringRefNull obj_filepath) { char obj_file_dir[FILE_MAXDIR]; BLI_split_dir_part(obj_filepath.data(), obj_file_dir, FILE_MAXDIR); - BLI_path_join(mtl_file_path_, FILE_MAX, obj_file_dir, mtl_library.data(), NULL); + BLI_path_join(mtl_file_path_, FILE_MAX, obj_file_dir, mtl_library.data(), nullptr); BLI_split_dir_part(mtl_file_path_, mtl_dir_path_, FILE_MAXDIR); } @@ -763,7 +768,7 @@ void MTLParser::parse_and_store(Map<string, std::unique_ptr<MTLMaterial>> &r_mat MTLMaterial *material = nullptr; - StringRef buffer_str{(const char *)buffer, (int64_t)buffer_len}; + StringRef buffer_str{(const char *)buffer, int64_t(buffer_len)}; while (!buffer_str.is_empty()) { const StringRef line = read_next_line(buffer_str); const char *p = line.begin(), *end = line.end(); @@ -784,31 +789,55 @@ void MTLParser::parse_and_store(Map<string, std::unique_ptr<MTLMaterial>> &r_mat } else if (material != nullptr) { if (parse_keyword(p, end, "Ns")) { - parse_float(p, end, 324.0f, material->Ns); + parse_float(p, end, 324.0f, material->spec_exponent); } else if (parse_keyword(p, end, "Ka")) { - parse_floats(p, end, 0.0f, material->Ka, 3); + parse_floats(p, end, 0.0f, material->ambient_color, 3); } else if (parse_keyword(p, end, "Kd")) { - parse_floats(p, end, 0.8f, material->Kd, 3); + parse_floats(p, end, 0.8f, material->color, 3); } else if (parse_keyword(p, end, "Ks")) { - parse_floats(p, end, 0.5f, material->Ks, 3); + parse_floats(p, end, 0.5f, material->spec_color, 3); } else if (parse_keyword(p, end, "Ke")) { - parse_floats(p, end, 0.0f, material->Ke, 3); + parse_floats(p, end, 0.0f, material->emission_color, 3); } else if (parse_keyword(p, end, "Ni")) { - parse_float(p, end, 1.45f, material->Ni); + parse_float(p, end, 1.45f, material->ior); } else if (parse_keyword(p, end, "d")) { - parse_float(p, end, 1.0f, material->d); + parse_float(p, end, 1.0f, material->alpha); } else if (parse_keyword(p, end, "illum")) { /* Some files incorrectly use a float (T60135). */ float val; parse_float(p, end, 1.0f, val); - material->illum = val; + material->illum_mode = val; + } + else if (parse_keyword(p, end, "Pr")) { + parse_float(p, end, 0.5f, material->roughness); + } + else if (parse_keyword(p, end, "Pm")) { + parse_float(p, end, 0.0f, material->metallic); + } + else if (parse_keyword(p, end, "Ps")) { + parse_float(p, end, 0.0f, material->sheen); + } + else if (parse_keyword(p, end, "Pc")) { + parse_float(p, end, 0.0f, material->cc_thickness); + } + else if (parse_keyword(p, end, "Pcr")) { + parse_float(p, end, 0.0f, material->cc_roughness); + } + else if (parse_keyword(p, end, "aniso")) { + parse_float(p, end, 0.0f, material->aniso); + } + else if (parse_keyword(p, end, "anisor")) { + parse_float(p, end, 0.0f, material->aniso_rot); + } + else if (parse_keyword(p, end, "Kt") || parse_keyword(p, end, "Tf")) { + parse_floats(p, end, 0.0f, material->transmit_color, 3); } else { parse_texture_map(p, end, material, mtl_dir_path_); diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index a570b374231..33ece88d3d4 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -8,7 +8,7 @@ #include "DNA_mesh_types.h" #include "DNA_scene_types.h" -#include "BKE_attribute.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_material.h" @@ -22,6 +22,7 @@ #include "IO_wavefront_obj.h" #include "importer_mesh_utils.hh" +#include "obj_export_mtl.hh" #include "obj_import_mesh.hh" namespace blender::io::obj { @@ -68,11 +69,7 @@ Object *MeshFromGeometry::create_mesh(Main *bmain, } transform_object(obj, import_params); - /* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */ - const uint16_t autosmooth = (mesh->flag & ME_AUTOSMOOTH); - Mesh *dst = static_cast<Mesh *>(obj->data); - BKE_mesh_nomain_to_mesh(mesh, dst, obj, &CD_MASK_EVERYTHING, true); - dst->flag |= autosmooth; + BKE_mesh_nomain_to_mesh(mesh, static_cast<Mesh *>(obj->data), obj); /* NOTE: vertex groups have to be created after final mesh is assigned to the object. */ create_vertex_groups(obj); @@ -157,6 +154,7 @@ void MeshFromGeometry::fixup_invalid_faces() void MeshFromGeometry::create_vertices(Mesh *mesh) { + MutableSpan<MVert> verts = mesh->verts_for_write(); /* Go through all the global vertex indices from min to max, * checking which ones are actually and building a global->local * index mapping. Write out the used vertex positions into the Mesh @@ -168,22 +166,27 @@ void MeshFromGeometry::create_vertices(Mesh *mesh) if (!mesh_geometry_.vertices_.contains(vi)) { continue; } - int local_vi = (int)mesh_geometry_.global_to_local_vertices_.size(); + int local_vi = int(mesh_geometry_.global_to_local_vertices_.size()); BLI_assert(local_vi >= 0 && local_vi < mesh->totvert); - copy_v3_v3(mesh->mvert[local_vi].co, global_vertices_.vertices[vi]); + copy_v3_v3(verts[local_vi].co, global_vertices_.vertices[vi]); mesh_geometry_.global_to_local_vertices_.add_new(vi, local_vi); } } void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) { - mesh->dvert = nullptr; + MutableSpan<MDeformVert> dverts; const int64_t total_verts = mesh_geometry_.get_vertex_count(); if (use_vertex_groups && total_verts && mesh_geometry_.has_vertex_groups_) { - mesh->dvert = static_cast<MDeformVert *>( - CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, nullptr, total_verts)); + dverts = mesh->deform_verts_for_write(); } + MutableSpan<MPoly> polys = mesh->polys_for_write(); + MutableSpan<MLoop> loops = mesh->loops_for_write(); + bke::SpanAttributeWriter<int> material_indices = + mesh->attributes_for_write().lookup_or_add_for_write_only_span<int>("material_index", + ATTR_DOMAIN_FACE); + const int64_t tot_face_elems{mesh->totpoly}; int tot_loop_idx = 0; @@ -195,40 +198,42 @@ void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) continue; } - MPoly &mpoly = mesh->mpoly[poly_idx]; + MPoly &mpoly = polys[poly_idx]; mpoly.totloop = curr_face.corner_count_; mpoly.loopstart = tot_loop_idx; if (curr_face.shaded_smooth) { mpoly.flag |= ME_SMOOTH; } - mpoly.mat_nr = curr_face.material_index; + material_indices.span[poly_idx] = curr_face.material_index; /* Importing obj files without any materials would result in negative indices, which is not * supported. */ - if (mpoly.mat_nr < 0) { - mpoly.mat_nr = 0; + if (material_indices.span[poly_idx] < 0) { + material_indices.span[poly_idx] = 0; } for (int idx = 0; idx < curr_face.corner_count_; ++idx) { const PolyCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx]; - MLoop &mloop = mesh->mloop[tot_loop_idx]; + MLoop &mloop = loops[tot_loop_idx]; tot_loop_idx++; mloop.v = mesh_geometry_.global_to_local_vertices_.lookup_default(curr_corner.vert_index, 0); /* Setup vertex group data, if needed. */ - if (!mesh->dvert) { + if (dverts.is_empty()) { continue; } const int group_index = curr_face.vertex_group_index; - MDeformWeight *dw = BKE_defvert_ensure_index(mesh->dvert + mloop.v, group_index); + MDeformWeight *dw = BKE_defvert_ensure_index(&dverts[mloop.v], group_index); dw->weight = 1.0f; } } + + material_indices.finish(); } void MeshFromGeometry::create_vertex_groups(Object *obj) { Mesh *mesh = static_cast<Mesh *>(obj->data); - if (mesh->dvert == nullptr) { + if (mesh->deform_verts().is_empty()) { return; } for (const std::string &name : mesh_geometry_.group_order_) { @@ -238,12 +243,14 @@ void MeshFromGeometry::create_vertex_groups(Object *obj) void MeshFromGeometry::create_edges(Mesh *mesh) { + MutableSpan<MEdge> edges = mesh->edges_for_write(); + const int64_t tot_edges{mesh_geometry_.edges_.size()}; const int64_t total_verts{mesh_geometry_.get_vertex_count()}; UNUSED_VARS_NDEBUG(total_verts); for (int i = 0; i < tot_edges; ++i) { const MEdge &src_edge = mesh_geometry_.edges_[i]; - MEdge &dst_edge = mesh->medge[i]; + MEdge &dst_edge = edges[i]; dst_edge.v1 = mesh_geometry_.global_to_local_vertices_.lookup_default(src_edge.v1, 0); dst_edge.v2 = mesh_geometry_.global_to_local_vertices_.lookup_default(src_edge.v2, 0); BLI_assert(dst_edge.v1 < total_verts && dst_edge.v2 < total_verts); @@ -262,18 +269,19 @@ void MeshFromGeometry::create_uv_verts(Mesh *mesh) return; } MLoopUV *mluv_dst = static_cast<MLoopUV *>(CustomData_add_layer( - &mesh->ldata, CD_MLOOPUV, CD_DEFAULT, nullptr, mesh_geometry_.total_loops_)); + &mesh->ldata, CD_MLOOPUV, CD_SET_DEFAULT, nullptr, mesh_geometry_.total_loops_)); int tot_loop_idx = 0; for (const PolyElem &curr_face : mesh_geometry_.face_elements_) { for (int idx = 0; idx < curr_face.corner_count_; ++idx) { const PolyCorner &curr_corner = mesh_geometry_.face_corners_[curr_face.start_index_ + idx]; - if (curr_corner.uv_vert_index >= 0 && - curr_corner.uv_vert_index < global_vertices_.uv_vertices.size()) { - const float2 &mluv_src = global_vertices_.uv_vertices[curr_corner.uv_vert_index]; - copy_v2_v2(mluv_dst[tot_loop_idx].uv, mluv_src); - tot_loop_idx++; + const int uv_index = curr_corner.uv_vert_index; + float2 uv(0, 0); + if (uv_index >= 0 && uv_index < global_vertices_.uv_vertices.size()) { + uv = global_vertices_.uv_vertices[uv_index]; } + copy_v2_v2(mluv_dst[tot_loop_idx].uv, uv); + tot_loop_idx++; } } } @@ -296,9 +304,10 @@ static Material *get_or_create_material(Main *bmain, const MTLMaterial &mtl = *materials.lookup_or_add(name, std::make_unique<MTLMaterial>()); Material *mat = BKE_material_add(bmain, name.c_str()); - ShaderNodetreeWrap mat_wrap{bmain, mtl, mat, relative_paths}; + id_us_min(&mat->id); + mat->use_nodes = true; - mat->nodetree = mat_wrap.get_nodetree(); + mat->nodetree = create_mtl_node_tree(bmain, mtl, mat, relative_paths); BKE_ntree_update_main_tree(bmain, mat->nodetree, nullptr); created_materials.add_new(name, mat); @@ -319,6 +328,9 @@ void MeshFromGeometry::create_materials(Main *bmain, } BKE_object_material_assign_single_obdata(bmain, obj, mat, obj->totcol + 1); } + if (obj->totcol > 0) { + obj->actcol = 1; + } } void MeshFromGeometry::create_normals(Mesh *mesh) diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mtl.cc b/source/blender/io/wavefront_obj/importer/obj_import_mtl.cc index 093cbec32fe..787b1fc9730 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mtl.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mtl.cc @@ -17,8 +17,7 @@ #include "NOD_shader.h" -/* TODO: move eMTLSyntaxElement out of following file into a more neutral place */ -#include "obj_export_io.hh" +#include "obj_export_mtl.hh" #include "obj_import_mtl.hh" #include "obj_import_string_utils.hh" @@ -29,12 +28,12 @@ namespace blender::io::obj { * Only float value(s) can be set using this method. */ static void set_property_of_socket(eNodeSocketDatatype property_type, - StringRef socket_id, + const char *socket_id, Span<float> value, bNode *r_node) { BLI_assert(r_node); - bNodeSocket *socket{nodeFindSocket(r_node, SOCK_IN, socket_id.data())}; + bNodeSocket *socket{nodeFindSocket(r_node, SOCK_IN, socket_id)}; BLI_assert(socket && socket->type == property_type); switch (property_type) { case SOCK_FLOAT: { @@ -95,7 +94,7 @@ static Image *create_placeholder_image(Main *bmain, const std::string &path) return image; } -static Image *load_texture_image(Main *bmain, const tex_map_XX &tex_map, bool relative_paths) +static Image *load_texture_image(Main *bmain, const MTLTexMap &tex_map, bool relative_paths) { Image *image = nullptr; @@ -124,7 +123,7 @@ static Image *load_texture_image(Main *bmain, const tex_map_XX &tex_map, bool re /* Try replacing underscores with spaces. */ std::string no_underscore_path{no_quote_path}; std::replace(no_underscore_path.begin(), no_underscore_path.end(), '_', ' '); - if (no_underscore_path != no_quote_path && no_underscore_path != tex_path) { + if (!ELEM(no_underscore_path, no_quote_path, tex_path)) { image = load_image_at_path(bmain, no_underscore_path, relative_paths); if (image != nullptr) { return image; @@ -143,85 +142,43 @@ static Image *load_texture_image(Main *bmain, const tex_map_XX &tex_map, bool re return image; } -ShaderNodetreeWrap::ShaderNodetreeWrap(Main *bmain, - const MTLMaterial &mtl_mat, - Material *mat, - bool relative_paths) - : mtl_mat_(mtl_mat) -{ - nodetree_.reset(ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname)); - bsdf_ = add_node_to_tree(SH_NODE_BSDF_PRINCIPLED); - shader_output_ = add_node_to_tree(SH_NODE_OUTPUT_MATERIAL); - - set_bsdf_socket_values(mat); - add_image_textures(bmain, mat, relative_paths); - link_sockets(bsdf_, "BSDF", shader_output_, "Surface", 4); - - nodeSetActive(nodetree_.get(), shader_output_); -} - -/** - * Assert if caller hasn't acquired nodetree. - */ -ShaderNodetreeWrap::~ShaderNodetreeWrap() -{ - if (nodetree_) { - /* nodetree's ownership must be acquired by the caller. */ - nodetree_.reset(); - BLI_assert(0); - } -} +/* Nodes are arranged in columns by type, with manually placed x coordinates + * based on node widths. */ +const float node_locx_texcoord = -880.0f; +const float node_locx_mapping = -680.0f; +const float node_locx_image = -480.0f; +const float node_locx_normalmap = -200.0f; +const float node_locx_bsdf = 0.0f; +const float node_locx_output = 280.0f; -bNodeTree *ShaderNodetreeWrap::get_nodetree() -{ - /* If this function has been reached, we know that nodes and the nodetree - * can be added to the scene safely. */ - return nodetree_.release(); -} - -bNode *ShaderNodetreeWrap::add_node_to_tree(const int node_type) -{ - return nodeAddStaticNode(nullptr, nodetree_.get(), node_type); -} +/* Nodes are arranged in rows; one row for each image being used. */ +const float node_locy_top = 300.0f; +const float node_locy_step = 300.0f; -std::pair<float, float> ShaderNodetreeWrap::set_node_locations(const int pos_x) +/* Add a node of the given type at the given location. */ +static bNode *add_node(bNodeTree *ntree, int type, float x, float y) { - int pos_y = 0; - bool found = false; - while (true) { - for (Span<int> location : node_locations) { - if (location[0] == pos_x && location[1] == pos_y) { - pos_y += 1; - found = true; - } - else { - found = false; - } - } - if (!found) { - node_locations.append({pos_x, pos_y}); - return {pos_x * node_size_, pos_y * node_size_ * 2.0 / 3.0}; - } - } + bNode *node = nodeAddStaticNode(nullptr, ntree, type); + node->locx = x; + node->locy = y; + return node; } -void ShaderNodetreeWrap::link_sockets(bNode *from_node, - StringRef from_node_id, - bNode *to_node, - StringRef to_node_id, - const int from_node_pos_x) +static void link_sockets(bNodeTree *ntree, + bNode *from_node, + const char *from_node_id, + bNode *to_node, + const char *to_node_id) { - std::tie(from_node->locx, from_node->locy) = set_node_locations(from_node_pos_x); - std::tie(to_node->locx, to_node->locy) = set_node_locations(from_node_pos_x + 1); - bNodeSocket *from_sock{nodeFindSocket(from_node, SOCK_OUT, from_node_id.data())}; - bNodeSocket *to_sock{nodeFindSocket(to_node, SOCK_IN, to_node_id.data())}; + bNodeSocket *from_sock{nodeFindSocket(from_node, SOCK_OUT, from_node_id)}; + bNodeSocket *to_sock{nodeFindSocket(to_node, SOCK_IN, to_node_id)}; BLI_assert(from_sock && to_sock); - nodeAddLink(nodetree_.get(), from_node, from_sock, to_node, to_sock); + nodeAddLink(ntree, from_node, from_sock, to_node, to_sock); } -void ShaderNodetreeWrap::set_bsdf_socket_values(Material *mat) +static void set_bsdf_socket_values(bNode *bsdf, Material *mat, const MTLMaterial &mtl_mat) { - const int illum = mtl_mat_.illum; + const int illum = mtl_mat.illum_mode; bool do_highlight = false; bool do_tranparency = false; bool do_reflection = false; @@ -287,21 +244,23 @@ void ShaderNodetreeWrap::set_bsdf_socket_values(Material *mat) /* Approximations for trying to map obj/mtl material model into * Principled BSDF: */ /* Specular: average of Ks components. */ - float specular = (mtl_mat_.Ks[0] + mtl_mat_.Ks[1] + mtl_mat_.Ks[2]) / 3; + float specular = (mtl_mat.spec_color[0] + mtl_mat.spec_color[1] + mtl_mat.spec_color[2]) / 3; if (specular < 0.0f) { specular = do_highlight ? 1.0f : 0.0f; } /* Roughness: map 0..1000 range to 1..0 and apply non-linearity. */ float roughness; - if (mtl_mat_.Ns < 0.0f) { + if (mtl_mat.spec_exponent < 0.0f) { roughness = do_highlight ? 0.0f : 1.0f; } else { - float clamped_ns = std::max(0.0f, std::min(1000.0f, mtl_mat_.Ns)); + float clamped_ns = std::max(0.0f, std::min(1000.0f, mtl_mat.spec_exponent)); roughness = 1.0f - sqrt(clamped_ns / 1000.0f); } - /* Metallic: average of Ka components. */ - float metallic = (mtl_mat_.Ka[0] + mtl_mat_.Ka[1] + mtl_mat_.Ka[2]) / 3; + /* Metallic: average of `Ka` components. */ + float metallic = (mtl_mat.ambient_color[0] + mtl_mat.ambient_color[1] + + mtl_mat.ambient_color[2]) / + 3; if (do_reflection) { if (metallic < 0.0f) { metallic = 1.0f; @@ -311,7 +270,7 @@ void ShaderNodetreeWrap::set_bsdf_socket_values(Material *mat) metallic = 0.0f; } - float ior = mtl_mat_.Ni; + float ior = mtl_mat.ior; if (ior < 0) { if (do_tranparency) { ior = 1.0f; @@ -320,93 +279,153 @@ void ShaderNodetreeWrap::set_bsdf_socket_values(Material *mat) ior = 1.5f; } } - float alpha = mtl_mat_.d; + float alpha = mtl_mat.alpha; if (do_tranparency && alpha < 0) { alpha = 1.0f; } - float3 base_color = {mtl_mat_.Kd[0], mtl_mat_.Kd[1], mtl_mat_.Kd[2]}; + /* PBR values, when present, override the ones calculated above. */ + if (mtl_mat.roughness >= 0) { + roughness = mtl_mat.roughness; + } + if (mtl_mat.metallic >= 0) { + metallic = mtl_mat.metallic; + } + + float3 base_color = mtl_mat.color; if (base_color.x >= 0 && base_color.y >= 0 && base_color.z >= 0) { - set_property_of_socket(SOCK_RGBA, "Base Color", {base_color, 3}, bsdf_); + set_property_of_socket(SOCK_RGBA, "Base Color", {base_color, 3}, bsdf); /* Viewport shading uses legacy r,g,b base color. */ mat->r = base_color.x; mat->g = base_color.y; mat->b = base_color.z; } - float3 emission_color = {mtl_mat_.Ke[0], mtl_mat_.Ke[1], mtl_mat_.Ke[2]}; + float3 emission_color = mtl_mat.emission_color; if (emission_color.x >= 0 && emission_color.y >= 0 && emission_color.z >= 0) { - set_property_of_socket(SOCK_RGBA, "Emission", {emission_color, 3}, bsdf_); + set_property_of_socket(SOCK_RGBA, "Emission", {emission_color, 3}, bsdf); } - if (mtl_mat_.tex_map_of_type(eMTLSyntaxElement::map_Ke).is_valid()) { - set_property_of_socket(SOCK_FLOAT, "Emission Strength", {1.0f}, bsdf_); + if (mtl_mat.tex_map_of_type(MTLTexMapType::Emission).is_valid()) { + set_property_of_socket(SOCK_FLOAT, "Emission Strength", {1.0f}, bsdf); } - set_property_of_socket(SOCK_FLOAT, "Specular", {specular}, bsdf_); - set_property_of_socket(SOCK_FLOAT, "Roughness", {roughness}, bsdf_); + set_property_of_socket(SOCK_FLOAT, "Specular", {specular}, bsdf); + set_property_of_socket(SOCK_FLOAT, "Roughness", {roughness}, bsdf); mat->roughness = roughness; - set_property_of_socket(SOCK_FLOAT, "Metallic", {metallic}, bsdf_); + set_property_of_socket(SOCK_FLOAT, "Metallic", {metallic}, bsdf); mat->metallic = metallic; if (ior != -1) { - set_property_of_socket(SOCK_FLOAT, "IOR", {ior}, bsdf_); + set_property_of_socket(SOCK_FLOAT, "IOR", {ior}, bsdf); } if (alpha != -1) { - set_property_of_socket(SOCK_FLOAT, "Alpha", {alpha}, bsdf_); + set_property_of_socket(SOCK_FLOAT, "Alpha", {alpha}, bsdf); } if (do_tranparency || (alpha >= 0.0f && alpha < 1.0f)) { mat->blend_method = MA_BM_BLEND; } + + if (mtl_mat.sheen >= 0) { + set_property_of_socket(SOCK_FLOAT, "Sheen", {mtl_mat.sheen}, bsdf); + } + if (mtl_mat.cc_thickness >= 0) { + set_property_of_socket(SOCK_FLOAT, "Clearcoat", {mtl_mat.cc_thickness}, bsdf); + } + if (mtl_mat.cc_roughness >= 0) { + set_property_of_socket(SOCK_FLOAT, "Clearcoat Roughness", {mtl_mat.cc_roughness}, bsdf); + } + if (mtl_mat.aniso >= 0) { + set_property_of_socket(SOCK_FLOAT, "Anisotropic", {mtl_mat.aniso}, bsdf); + } + if (mtl_mat.aniso_rot >= 0) { + set_property_of_socket(SOCK_FLOAT, "Anisotropic Rotation", {mtl_mat.aniso_rot}, bsdf); + } + + /* Transmission: average of transmission color. */ + float transmission = (mtl_mat.transmit_color[0] + mtl_mat.transmit_color[1] + + mtl_mat.transmit_color[2]) / + 3; + if (transmission >= 0) { + set_property_of_socket(SOCK_FLOAT, "Transmission", {transmission}, bsdf); + } } -void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *mat, bool relative_paths) +static void add_image_textures(Main *bmain, + bNodeTree *ntree, + bNode *bsdf, + Material *mat, + const MTLMaterial &mtl_mat, + bool relative_paths) { - for (const Map<const eMTLSyntaxElement, tex_map_XX>::Item texture_map : - mtl_mat_.texture_maps.items()) { - if (!texture_map.value.is_valid()) { + float node_locy = node_locy_top; + for (int key = 0; key < int(MTLTexMapType::Count); ++key) { + const MTLTexMap &value = mtl_mat.texture_maps[key]; + if (!value.is_valid()) { /* No Image texture node of this map type can be added to this material. */ continue; } - bNode *image_texture = add_node_to_tree(SH_NODE_TEX_IMAGE); - BLI_assert(image_texture); - Image *image = load_texture_image(bmain, texture_map.value, relative_paths); + Image *image = load_texture_image(bmain, value, relative_paths); if (image == nullptr) { continue; } - image_texture->id = &image->id; - static_cast<NodeTexImage *>(image_texture->storage)->projection = - texture_map.value.projection_type; + + bNode *image_node = add_node(ntree, SH_NODE_TEX_IMAGE, node_locx_image, node_locy); + BLI_assert(image_node); + image_node->id = &image->id; + static_cast<NodeTexImage *>(image_node->storage)->projection = value.projection_type; /* Add normal map node if needed. */ bNode *normal_map = nullptr; - if (texture_map.key == eMTLSyntaxElement::map_Bump) { - normal_map = add_node_to_tree(SH_NODE_NORMAL_MAP); - const float bump = std::max(0.0f, mtl_mat_.map_Bump_strength); + if (key == int(MTLTexMapType::Normal)) { + normal_map = add_node(ntree, SH_NODE_NORMAL_MAP, node_locx_normalmap, node_locy); + const float bump = std::max(0.0f, mtl_mat.normal_strength); set_property_of_socket(SOCK_FLOAT, "Strength", {bump}, normal_map); } /* Add UV mapping & coordinate nodes only if needed. */ - if (texture_map.value.translation != float3(0, 0, 0) || - texture_map.value.scale != float3(1, 1, 1)) { - bNode *mapping = add_node_to_tree(SH_NODE_MAPPING); - bNode *texture_coordinate = add_node_to_tree(SH_NODE_TEX_COORD); - set_property_of_socket(SOCK_VECTOR, "Location", {texture_map.value.translation, 3}, mapping); - set_property_of_socket(SOCK_VECTOR, "Scale", {texture_map.value.scale, 3}, mapping); - - link_sockets(texture_coordinate, "UV", mapping, "Vector", 0); - link_sockets(mapping, "Vector", image_texture, "Vector", 1); + if (value.translation != float3(0, 0, 0) || value.scale != float3(1, 1, 1)) { + bNode *texcoord = add_node(ntree, SH_NODE_TEX_COORD, node_locx_texcoord, node_locy); + bNode *mapping = add_node(ntree, SH_NODE_MAPPING, node_locx_mapping, node_locy); + set_property_of_socket(SOCK_VECTOR, "Location", {value.translation, 3}, mapping); + set_property_of_socket(SOCK_VECTOR, "Scale", {value.scale, 3}, mapping); + + link_sockets(ntree, texcoord, "UV", mapping, "Vector"); + link_sockets(ntree, mapping, "Vector", image_node, "Vector"); } if (normal_map) { - link_sockets(image_texture, "Color", normal_map, "Color", 2); - link_sockets(normal_map, "Normal", bsdf_, "Normal", 3); + link_sockets(ntree, image_node, "Color", normal_map, "Color"); + link_sockets(ntree, normal_map, "Normal", bsdf, "Normal"); } - else if (texture_map.key == eMTLSyntaxElement::map_d) { - link_sockets(image_texture, "Alpha", bsdf_, texture_map.value.dest_socket_id, 2); + else if (key == int(MTLTexMapType::Alpha)) { + link_sockets(ntree, image_node, "Alpha", bsdf, tex_map_type_to_socket_id[key]); mat->blend_method = MA_BM_BLEND; } else { - link_sockets(image_texture, "Color", bsdf_, texture_map.value.dest_socket_id, 2); + link_sockets(ntree, image_node, "Color", bsdf, tex_map_type_to_socket_id[key]); } + + /* Next layout row: goes downwards on the screen. */ + node_locy -= node_locy_step; } } + +bNodeTree *create_mtl_node_tree(Main *bmain, + const MTLMaterial &mtl, + Material *mat, + bool relative_paths) +{ + bNodeTree *ntree = ntreeAddTreeEmbedded( + nullptr, &mat->id, "Shader Nodetree", ntreeType_Shader->idname); + + bNode *bsdf = add_node(ntree, SH_NODE_BSDF_PRINCIPLED, node_locx_bsdf, node_locy_top); + bNode *output = add_node(ntree, SH_NODE_OUTPUT_MATERIAL, node_locx_output, node_locy_top); + + set_bsdf_socket_values(bsdf, mat, mtl); + add_image_textures(bmain, ntree, bsdf, mat, mtl, relative_paths); + link_sockets(ntree, bsdf, "BSDF", output, "Surface"); + nodeSetActive(ntree, output); + + return ntree; +} + } // namespace blender::io::obj diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mtl.hh b/source/blender/io/wavefront_obj/importer/obj_import_mtl.hh index 17dd0106fea..a3ba803e921 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mtl.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_mtl.hh @@ -1,93 +1,19 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -/** \file - * \ingroup obj - */ - #pragma once -#include <array> - -#include "BLI_map.hh" -#include "BLI_math_vec_types.hh" -#include "BLI_string_ref.hh" -#include "BLI_vector.hh" - #include "DNA_node_types.h" -#include "MEM_guardedalloc.h" - -#include "obj_export_mtl.hh" +struct Main; +struct Material; namespace blender::io::obj { -struct UniqueNodetreeDeleter { - void operator()(bNodeTree *node) - { - MEM_freeN(node); - } -}; - -using unique_nodetree_ptr = std::unique_ptr<bNodeTree, UniqueNodetreeDeleter>; - -class ShaderNodetreeWrap { - private: - /* Node arrangement: - * Texture Coordinates -> Mapping -> Image Texture -> (optional) Normal Map -> p-BSDF -> Material - * Output. */ - unique_nodetree_ptr nodetree_; - bNode *bsdf_; - bNode *shader_output_; - const MTLMaterial &mtl_mat_; - - /* List of all locations occupied by nodes. */ - Vector<std::array<int, 2>> node_locations; - const float node_size_{300.f}; - - public: - /** - * Initializes a nodetree with a p-BSDF node's BSDF socket connected to shader output node's - * surface socket. - */ - ShaderNodetreeWrap(Main *bmain, const MTLMaterial &mtl_mat, Material *mat, bool relative_paths); - ~ShaderNodetreeWrap(); - - /** - * Release nodetree for materials to own it. nodetree has its unique deleter - * if destructor is not reached for some reason. - */ - bNodeTree *get_nodetree(); +struct MTLMaterial; - private: - /** - * Add a new static node to the tree. - * No two nodes are linked here. - */ - bNode *add_node_to_tree(const int node_type); - /** - * Return x-y coordinates for a node where y is determined by other nodes present in - * the same vertical column. - */ - std::pair<float, float> set_node_locations(const int pos_x); - /** - * Link two nodes by the sockets of given IDs. - * Also releases the ownership of the "from" node for nodetree to free it. - * \param from_node_pos_x: 0 to 4 value as per nodetree arrangement. - */ - void link_sockets(bNode *from_node, - StringRef from_node_id, - bNode *to_node, - StringRef to_node_id, - const int from_node_pos_x); - /** - * Set values of sockets in p-BSDF node of the nodetree. - */ - void set_bsdf_socket_values(Material *mat); - /** - * Create image texture, vector and normal mapping nodes from MTL materials and link the - * nodes to p-BSDF node. - */ - void add_image_textures(Main *bmain, Material *mat, bool relative_paths); -}; +bNodeTree *create_mtl_node_tree(Main *bmain, + const MTLMaterial &mtl_mat, + Material *mat, + bool relative_paths); } // namespace blender::io::obj diff --git a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh index 04d9a665588..91f09d9e188 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_objects.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_objects.hh @@ -110,7 +110,7 @@ struct Geometry { int get_vertex_count() const { - return (int)vertices_.size(); + return int(vertices_.size()); } void track_vertex_index(int index) { diff --git a/source/blender/io/wavefront_obj/importer/obj_import_string_utils.cc b/source/blender/io/wavefront_obj/importer/obj_import_string_utils.cc index 7e282b164b0..a69b4206db6 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_string_utils.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_string_utils.cc @@ -94,7 +94,7 @@ const char *parse_float(const char *p, } p = drop_plus(p, end); fast_float::from_chars_result res = fast_float::from_chars(p, end, dst); - if (res.ec == std::errc::invalid_argument || res.ec == std::errc::result_out_of_range) { + if (ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) { dst = fallback; } else if (require_trailing_space && res.ptr < end && !is_whitespace(*res.ptr)) { @@ -125,7 +125,7 @@ const char *parse_int(const char *p, const char *end, int fallback, int &dst, bo } p = drop_plus(p, end); std::from_chars_result res = std::from_chars(p, end, dst); - if (res.ec == std::errc::invalid_argument || res.ec == std::errc::result_out_of_range) { + if (ELEM(res.ec, std::errc::invalid_argument, std::errc::result_out_of_range)) { dst = fallback; } return res.ptr; diff --git a/source/blender/io/wavefront_obj/importer/obj_importer.cc b/source/blender/io/wavefront_obj/importer/obj_importer.cc index 5d3f75e7f38..ccbcce64d65 100644 --- a/source/blender/io/wavefront_obj/importer/obj_importer.cc +++ b/source/blender/io/wavefront_obj/importer/obj_importer.cc @@ -19,6 +19,7 @@ #include "DNA_collection_types.h" +#include "obj_export_mtl.hh" #include "obj_import_file_reader.hh" #include "obj_import_mesh.hh" #include "obj_import_nurbs.hh" @@ -75,6 +76,7 @@ static void geometry_to_blender_objects(Main *bmain, /* Sync the collection after all objects are created. */ BKE_layer_collection_resync_allow(); BKE_main_collection_sync(bmain); + BKE_view_layer_synced_ensure(scene, view_layer); /* After collection sync, select objects in the view layer and do DEG updates. */ for (Object *obj : objects) { @@ -122,7 +124,7 @@ void importer_main(Main *bmain, } if (import_params.clear_selection) { - BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_deselect_all(scene, view_layer); } geometry_to_blender_objects(bmain, scene, diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc index f582064e0c1..dcba78ac99e 100644 --- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc @@ -185,17 +185,17 @@ TEST(obj_exporter_writer, mtllib) TEST(obj_exporter_writer, format_handler_buffer_chunking) { /* Use a tiny buffer chunk size, so that the test below ends up creating several blocks. */ - FormatHandler<eFileType::OBJ, 16> h; - h.write<eOBJSyntaxElement::object_name>("abc"); - h.write<eOBJSyntaxElement::object_name>("abcd"); - h.write<eOBJSyntaxElement::object_name>("abcde"); - h.write<eOBJSyntaxElement::object_name>("abcdef"); - h.write<eOBJSyntaxElement::object_name>("012345678901234567890123456789abcd"); - h.write<eOBJSyntaxElement::object_name>("123"); - h.write<eOBJSyntaxElement::curve_element_begin>(); - h.write<eOBJSyntaxElement::new_line>(); - h.write<eOBJSyntaxElement::nurbs_parameter_begin>(); - h.write<eOBJSyntaxElement::new_line>(); + FormatHandler h(16); + h.write_obj_object("abc"); + h.write_obj_object("abcd"); + h.write_obj_object("abcde"); + h.write_obj_object("abcdef"); + h.write_obj_object("012345678901234567890123456789abcd"); + h.write_obj_object("123"); + h.write_obj_curve_begin(); + h.write_obj_newline(); + h.write_obj_nurbs_parm_begin(); + h.write_obj_newline(); size_t got_blocks = h.get_block_count(); ASSERT_EQ(got_blocks, 7); @@ -527,4 +527,27 @@ TEST_F(obj_exporter_regression_test, all_objects_mat_groups) _export.params); } +TEST_F(obj_exporter_regression_test, materials_without_pbr) +{ + OBJExportParamsDefault _export; + _export.params.export_normals = false; + _export.params.path_mode = PATH_REFERENCE_RELATIVE; + compare_obj_export_to_golden("io_tests/blend_geometry/materials_pbr.blend", + "io_tests/obj/materials_without_pbr.obj", + "io_tests/obj/materials_without_pbr.mtl", + _export.params); +} + +TEST_F(obj_exporter_regression_test, materials_pbr) +{ + OBJExportParamsDefault _export; + _export.params.export_normals = false; + _export.params.path_mode = PATH_REFERENCE_RELATIVE; + _export.params.export_pbr_extensions = true; + compare_obj_export_to_golden("io_tests/blend_geometry/materials_pbr.blend", + "io_tests/obj/materials_pbr.obj", + "io_tests/obj/materials_pbr.mtl", + _export.params); +} + } // namespace blender::io::obj diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh index 7d3b41ed527..006d86312b6 100644 --- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh +++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh @@ -31,6 +31,7 @@ struct OBJExportParamsDefault { params.path_mode = PATH_REFERENCE_AUTO; params.export_triangulated_mesh = false; params.export_curves_as_nurbs = false; + params.export_pbr_extensions = false; params.export_object_groups = false; params.export_material_groups = false; diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc index bd9360548af..cd97d5fb485 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -8,11 +8,12 @@ #include "BKE_curve.h" #include "BKE_customdata.h" #include "BKE_main.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_scene.h" #include "BLI_listbase.h" -#include "BLI_math_base.h" +#include "BLI_math_base.hh" #include "BLI_math_vec_types.hh" #include "BLO_readfile.h" @@ -71,12 +72,13 @@ class obj_importer_test : public BlendfileLoadingBaseTest { depsgraph_create(DAG_EVAL_VIEWPORT); - const int deg_objects_visibility_flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | - DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI; + DEGObjectIterSettings deg_iter_settings{}; + deg_iter_settings.depsgraph = depsgraph; + deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI; size_t object_index = 0; - DEG_OBJECT_ITER_BEGIN (depsgraph, object, deg_objects_visibility_flags) { + DEG_OBJECT_ITER_BEGIN (°_iter_settings, object) { if (object_index >= expect_count) { ADD_FAILURE(); break; @@ -85,7 +87,7 @@ class obj_importer_test : public BlendfileLoadingBaseTest { ASSERT_STREQ(object->id.name, exp.name.c_str()); EXPECT_EQ(object->type, exp.type); EXPECT_V3_NEAR(object->loc, float3(0, 0, 0), 0.0001f); - if (strcmp(object->id.name, "OBCube") != 0) { + if (!STREQ(object->id.name, "OBCube")) { EXPECT_V3_NEAR(object->rot, float3(M_PI_2, 0, 0), 0.0001f); } EXPECT_V3_NEAR(object->scale, float3(1, 1, 1), 0.0001f); @@ -95,8 +97,9 @@ class obj_importer_test : public BlendfileLoadingBaseTest { EXPECT_EQ(mesh->totedge, exp.mesh_totedge_or_curve_endp); EXPECT_EQ(mesh->totpoly, exp.mesh_totpoly_or_curve_order); EXPECT_EQ(mesh->totloop, exp.mesh_totloop_or_curve_cyclic); - EXPECT_V3_NEAR(mesh->mvert[0].co, exp.vert_first, 0.0001f); - EXPECT_V3_NEAR(mesh->mvert[mesh->totvert - 1].co, exp.vert_last, 0.0001f); + const Span<MVert> verts = mesh->verts(); + EXPECT_V3_NEAR(verts.first().co, exp.vert_first, 0.0001f); + EXPECT_V3_NEAR(verts.last().co, exp.vert_last, 0.0001f); const float3 *lnors = (const float3 *)(CustomData_get_layer(&mesh->ldata, CD_NORMAL)); float3 normal_first = lnors != nullptr ? lnors[0] : float3(0, 0, 0); EXPECT_V3_NEAR(normal_first, exp.normal_first, 0.0001f); diff --git a/source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc b/source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc index 08050ac34c9..ce3c14a2939 100644 --- a/source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc @@ -6,6 +6,7 @@ #include "testing/testing.h" +#include "obj_export_mtl.hh" #include "obj_import_file_reader.hh" namespace blender::io::obj { @@ -49,18 +50,26 @@ class obj_mtl_parser_test : public testing::Test { } const MTLMaterial &got = *materials.lookup(exp.name); const float tol = 0.0001f; - EXPECT_V3_NEAR(exp.Ka, got.Ka, tol); - EXPECT_V3_NEAR(exp.Kd, got.Kd, tol); - EXPECT_V3_NEAR(exp.Ks, got.Ks, tol); - EXPECT_V3_NEAR(exp.Ke, got.Ke, tol); - EXPECT_NEAR(exp.Ns, got.Ns, tol); - EXPECT_NEAR(exp.Ni, got.Ni, tol); - EXPECT_NEAR(exp.d, got.d, tol); - EXPECT_NEAR(exp.map_Bump_strength, got.map_Bump_strength, tol); - EXPECT_EQ(exp.illum, got.illum); - for (const auto &it : exp.texture_maps.items()) { - const tex_map_XX &exp_tex = it.value; - const tex_map_XX &got_tex = got.texture_maps.lookup(it.key); + EXPECT_V3_NEAR(exp.ambient_color, got.ambient_color, tol); + EXPECT_V3_NEAR(exp.color, got.color, tol); + EXPECT_V3_NEAR(exp.spec_color, got.spec_color, tol); + EXPECT_V3_NEAR(exp.emission_color, got.emission_color, tol); + EXPECT_V3_NEAR(exp.transmit_color, got.transmit_color, tol); + EXPECT_NEAR(exp.spec_exponent, got.spec_exponent, tol); + EXPECT_NEAR(exp.ior, got.ior, tol); + EXPECT_NEAR(exp.alpha, got.alpha, tol); + EXPECT_NEAR(exp.normal_strength, got.normal_strength, tol); + EXPECT_EQ(exp.illum_mode, got.illum_mode); + EXPECT_NEAR(exp.roughness, got.roughness, tol); + EXPECT_NEAR(exp.metallic, got.metallic, tol); + EXPECT_NEAR(exp.sheen, got.sheen, tol); + EXPECT_NEAR(exp.cc_thickness, got.cc_thickness, tol); + EXPECT_NEAR(exp.cc_roughness, got.cc_roughness, tol); + EXPECT_NEAR(exp.aniso, got.aniso, tol); + EXPECT_NEAR(exp.aniso_rot, got.aniso_rot, tol); + for (int key = 0; key < int(MTLTexMapType::Count); key++) { + const MTLTexMap &exp_tex = exp.texture_maps[key]; + const MTLTexMap &got_tex = got.texture_maps[key]; EXPECT_STREQ(exp_tex.image_path.c_str(), got_tex.image_path.c_str()); EXPECT_V3_NEAR(exp_tex.translation, got_tex.translation, tol); EXPECT_V3_NEAR(exp_tex.scale, got_tex.scale, tol); @@ -101,20 +110,20 @@ TEST_F(obj_mtl_parser_test, string_newlines_whitespace) "map_Ks sometex_s_spaces_after_name.png \t \r\n"; MTLMaterial mat[6]; mat[0].name = "simple"; - mat[0].Ka = {0.1f, 0.2f, 0.3f}; - mat[0].illum = 4; + mat[0].ambient_color = {0.1f, 0.2f, 0.3f}; + mat[0].illum_mode = 4; mat[1].name = "tab_indentation"; - mat[1].Kd = {0.2f, 0.3f, 0.4f}; + mat[1].color = {0.2f, 0.3f, 0.4f}; mat[2].name = "space_after_name"; - mat[2].Ks = {0.4f, 0.5f, 0.6f}; + mat[2].spec_color = {0.4f, 0.5f, 0.6f}; mat[3].name = "space_before_name"; mat[4].name = "indented_values"; - mat[4].Ka = {0.5f, 0.6f, 0.7f}; - mat[4].Kd = {0.6f, 0.7f, 0.8f}; + mat[4].ambient_color = {0.5f, 0.6f, 0.7f}; + mat[4].color = {0.6f, 0.7f, 0.8f}; mat[5].name = "crlf_ending"; - mat[5].Ns = 5.0f; - mat[5].tex_map_of_type(eMTLSyntaxElement::map_Kd).image_path = "sometex_d.png"; - mat[5].tex_map_of_type(eMTLSyntaxElement::map_Ks).image_path = "sometex_s_spaces_after_name.png"; + mat[5].spec_exponent = 5.0f; + mat[5].tex_map_of_type(MTLTexMapType::Color).image_path = "sometex_d.png"; + mat[5].tex_map_of_type(MTLTexMapType::Specular).image_path = "sometex_s_spaces_after_name.png"; check_string(text, mat, ARRAY_SIZE(mat)); } @@ -122,8 +131,8 @@ TEST_F(obj_mtl_parser_test, cube) { MTLMaterial mat; mat.name = "red"; - mat.Ka = {0.2f, 0.2f, 0.2f}; - mat.Kd = {1, 0, 0}; + mat.ambient_color = {0.2f, 0.2f, 0.2f}; + mat.color = {1, 0, 0}; check("cube.mtl", &mat, 1); } @@ -131,28 +140,28 @@ TEST_F(obj_mtl_parser_test, all_objects) { MTLMaterial mat[7]; for (auto &m : mat) { - m.Ka = {1, 1, 1}; - m.Ks = {0.5f, 0.5f, 0.5f}; - m.Ke = {0, 0, 0}; - m.Ns = 250; - m.Ni = 1; - m.d = 1; - m.illum = 2; + m.ambient_color = {1, 1, 1}; + m.spec_color = {0.5f, 0.5f, 0.5f}; + m.emission_color = {0, 0, 0}; + m.spec_exponent = 250; + m.ior = 1; + m.alpha = 1; + m.illum_mode = 2; } mat[0].name = "Blue"; - mat[0].Kd = {0, 0, 1}; + mat[0].color = {0, 0, 1}; mat[1].name = "BlueDark"; - mat[1].Kd = {0, 0, 0.5f}; + mat[1].color = {0, 0, 0.5f}; mat[2].name = "Green"; - mat[2].Kd = {0, 1, 0}; + mat[2].color = {0, 1, 0}; mat[3].name = "GreenDark"; - mat[3].Kd = {0, 0.5f, 0}; + mat[3].color = {0, 0.5f, 0}; mat[4].name = "Material"; - mat[4].Kd = {0.8f, 0.8f, 0.8f}; + mat[4].color = {0.8f, 0.8f, 0.8f}; mat[5].name = "Red"; - mat[5].Kd = {1, 0, 0}; + mat[5].color = {1, 0, 0}; mat[6].name = "RedDark"; - mat[6].Kd = {0.5f, 0, 0}; + mat[6].color = {0.5f, 0, 0}; check("all_objects.mtl", mat, ARRAY_SIZE(mat)); } @@ -160,92 +169,101 @@ TEST_F(obj_mtl_parser_test, materials) { MTLMaterial mat[6]; mat[0].name = "no_textures_red"; - mat[0].Ka = {0.3f, 0.3f, 0.3f}; - mat[0].Kd = {0.8f, 0.3f, 0.1f}; - mat[0].Ns = 5.624998f; + mat[0].ambient_color = {0.3f, 0.3f, 0.3f}; + mat[0].color = {0.8f, 0.3f, 0.1f}; + mat[0].spec_exponent = 5.624998f; mat[1].name = "four_maps"; - mat[1].Ka = {1, 1, 1}; - mat[1].Kd = {0.8f, 0.8f, 0.8f}; - mat[1].Ks = {0.5f, 0.5f, 0.5f}; - mat[1].Ke = {0, 0, 0}; - mat[1].Ns = 1000; - mat[1].Ni = 1.45f; - mat[1].d = 1; - mat[1].illum = 2; - mat[1].map_Bump_strength = 1; + mat[1].ambient_color = {1, 1, 1}; + mat[1].color = {0.8f, 0.8f, 0.8f}; + mat[1].spec_color = {0.5f, 0.5f, 0.5f}; + mat[1].emission_color = {0, 0, 0}; + mat[1].spec_exponent = 1000; + mat[1].ior = 1.45f; + mat[1].alpha = 1; + mat[1].illum_mode = 2; + mat[1].normal_strength = 1; { - tex_map_XX &kd = mat[1].tex_map_of_type(eMTLSyntaxElement::map_Kd); + MTLTexMap &kd = mat[1].tex_map_of_type(MTLTexMapType::Color); kd.image_path = "texture.png"; - tex_map_XX &ns = mat[1].tex_map_of_type(eMTLSyntaxElement::map_Ns); + MTLTexMap &ns = mat[1].tex_map_of_type(MTLTexMapType::SpecularExponent); ns.image_path = "sometexture_Roughness.png"; - tex_map_XX &refl = mat[1].tex_map_of_type(eMTLSyntaxElement::map_refl); + MTLTexMap &refl = mat[1].tex_map_of_type(MTLTexMapType::Reflection); refl.image_path = "sometexture_Metallic.png"; - tex_map_XX &bump = mat[1].tex_map_of_type(eMTLSyntaxElement::map_Bump); + MTLTexMap &bump = mat[1].tex_map_of_type(MTLTexMapType::Normal); bump.image_path = "sometexture_Normal.png"; } mat[2].name = "Clay"; - mat[2].Ka = {1, 1, 1}; - mat[2].Kd = {0.8f, 0.682657f, 0.536371f}; - mat[2].Ks = {0.5f, 0.5f, 0.5f}; - mat[2].Ke = {0, 0, 0}; - mat[2].Ns = 440.924042f; - mat[2].Ni = 1.45f; - mat[2].d = 1; - mat[2].illum = 2; + mat[2].ambient_color = {1, 1, 1}; + mat[2].color = {0.8f, 0.682657f, 0.536371f}; + mat[2].spec_color = {0.5f, 0.5f, 0.5f}; + mat[2].emission_color = {0, 0, 0}; + mat[2].spec_exponent = 440.924042f; + mat[2].ior = 1.45f; + mat[2].alpha = 1; + mat[2].illum_mode = 2; mat[3].name = "Hat"; - mat[3].Ka = {1, 1, 1}; - mat[3].Kd = {0.8f, 0.8f, 0.8f}; - mat[3].Ks = {0.5f, 0.5f, 0.5f}; - mat[3].Ns = 800; - mat[3].map_Bump_strength = 0.5f; + mat[3].ambient_color = {1, 1, 1}; + mat[3].color = {0.8f, 0.8f, 0.8f}; + mat[3].spec_color = {0.5f, 0.5f, 0.5f}; + mat[3].spec_exponent = 800; + mat[3].normal_strength = 0.5f; { - tex_map_XX &kd = mat[3].tex_map_of_type(eMTLSyntaxElement::map_Kd); + MTLTexMap &kd = mat[3].tex_map_of_type(MTLTexMapType::Color); kd.image_path = "someHatTexture_BaseColor.jpg"; - tex_map_XX &ns = mat[3].tex_map_of_type(eMTLSyntaxElement::map_Ns); + MTLTexMap &ns = mat[3].tex_map_of_type(MTLTexMapType::SpecularExponent); ns.image_path = "someHatTexture_Roughness.jpg"; - tex_map_XX &refl = mat[3].tex_map_of_type(eMTLSyntaxElement::map_refl); + MTLTexMap &refl = mat[3].tex_map_of_type(MTLTexMapType::Reflection); refl.image_path = "someHatTexture_Metalness.jpg"; - tex_map_XX &bump = mat[3].tex_map_of_type(eMTLSyntaxElement::map_Bump); + MTLTexMap &bump = mat[3].tex_map_of_type(MTLTexMapType::Normal); bump.image_path = "someHatTexture_Normal.jpg"; } mat[4].name = "Parser_Test"; - mat[4].Ka = {0.1f, 0.2f, 0.3f}; - mat[4].Kd = {0.4f, 0.5f, 0.6f}; - mat[4].Ks = {0.7f, 0.8f, 0.9f}; - mat[4].illum = 6; - mat[4].Ns = 15.5; - mat[4].Ni = 1.5; - mat[4].d = 0.5; - mat[4].map_Bump_strength = 0.1f; + mat[4].ambient_color = {0.1f, 0.2f, 0.3f}; + mat[4].color = {0.4f, 0.5f, 0.6f}; + mat[4].spec_color = {0.7f, 0.8f, 0.9f}; + mat[4].illum_mode = 6; + mat[4].spec_exponent = 15.5; + mat[4].ior = 1.5; + mat[4].alpha = 0.5; + mat[4].normal_strength = 0.1f; + mat[4].transmit_color = {0.1f, 0.3f, 0.5f}; + mat[4].normal_strength = 0.1f; + mat[4].roughness = 0.2f; + mat[4].metallic = 0.3f; + mat[4].sheen = 0.4f; + mat[4].cc_thickness = 0.5f; + mat[4].cc_roughness = 0.6f; + mat[4].aniso = 0.7f; + mat[4].aniso_rot = 0.8f; { - tex_map_XX &kd = mat[4].tex_map_of_type(eMTLSyntaxElement::map_Kd); + MTLTexMap &kd = mat[4].tex_map_of_type(MTLTexMapType::Color); kd.image_path = "sometex_d.png"; - tex_map_XX &ns = mat[4].tex_map_of_type(eMTLSyntaxElement::map_Ns); + MTLTexMap &ns = mat[4].tex_map_of_type(MTLTexMapType::SpecularExponent); ns.image_path = "sometex_ns.psd"; - tex_map_XX &refl = mat[4].tex_map_of_type(eMTLSyntaxElement::map_refl); + MTLTexMap &refl = mat[4].tex_map_of_type(MTLTexMapType::Reflection); refl.image_path = "clouds.tiff"; refl.scale = {1.5f, 2.5f, 3.5f}; refl.translation = {4.5f, 5.5f, 6.5f}; refl.projection_type = SHD_PROJ_SPHERE; - tex_map_XX &bump = mat[4].tex_map_of_type(eMTLSyntaxElement::map_Bump); + MTLTexMap &bump = mat[4].tex_map_of_type(MTLTexMapType::Normal); bump.image_path = "somebump.tga"; bump.scale = {3, 4, 5}; } mat[5].name = "Parser_ScaleOffset_Test"; { - tex_map_XX &kd = mat[5].tex_map_of_type(eMTLSyntaxElement::map_Kd); + MTLTexMap &kd = mat[5].tex_map_of_type(MTLTexMapType::Color); kd.translation = {2.5f, 0.0f, 0.0f}; kd.image_path = "OffsetOneValue.png"; - tex_map_XX &ks = mat[5].tex_map_of_type(eMTLSyntaxElement::map_Ks); + MTLTexMap &ks = mat[5].tex_map_of_type(MTLTexMapType::Specular); ks.scale = {1.5f, 2.5f, 1.0f}; ks.translation = {3.5f, 4.5f, 0.0f}; ks.image_path = "ScaleOffsetBothTwovalues.png"; - tex_map_XX &ns = mat[5].tex_map_of_type(eMTLSyntaxElement::map_Ns); + MTLTexMap &ns = mat[5].tex_map_of_type(MTLTexMapType::SpecularExponent); ns.scale = {0.5f, 1.0f, 1.0f}; ns.image_path = "1.Value.png"; } @@ -253,4 +271,75 @@ TEST_F(obj_mtl_parser_test, materials) check("materials.mtl", mat, ARRAY_SIZE(mat)); } +TEST_F(obj_mtl_parser_test, materials_without_pbr) +{ + MTLMaterial mat[2]; + mat[0].name = "Mat1"; + mat[0].spec_exponent = 360.0f; + mat[0].ambient_color = {0.9f, 0.9f, 0.9f}; + mat[0].color = {0.8f, 0.276449f, 0.101911f}; + mat[0].spec_color = {0.25f, 0.25f, 0.25f}; + mat[0].emission_color = {0, 0, 0}; + mat[0].ior = 1.45f; + mat[0].alpha = 1; + mat[0].illum_mode = 3; + + mat[1].name = "Mat2"; + mat[1].ambient_color = {1, 1, 1}; + mat[1].color = {0.8f, 0.8f, 0.8f}; + mat[1].spec_color = {0.5f, 0.5f, 0.5f}; + mat[1].ior = 1.45f; + mat[1].alpha = 1; + mat[1].illum_mode = 2; + { + MTLTexMap &ns = mat[1].tex_map_of_type(MTLTexMapType::SpecularExponent); + ns.image_path = "../blend_geometry/texture_roughness.png"; + MTLTexMap &ke = mat[1].tex_map_of_type(MTLTexMapType::Emission); + ke.image_path = "../blend_geometry/texture_illum.png"; + } + + check("materials_without_pbr.mtl", mat, ARRAY_SIZE(mat)); +} + +TEST_F(obj_mtl_parser_test, materials_pbr) +{ + MTLMaterial mat[2]; + mat[0].name = "Mat1"; + mat[0].color = {0.8f, 0.276449f, 0.101911f}; + mat[0].spec_color = {0.25f, 0.25f, 0.25f}; + mat[0].emission_color = {0, 0, 0}; + mat[0].ior = 1.45f; + mat[0].alpha = 1; + mat[0].illum_mode = 3; + mat[0].roughness = 0.4f; + mat[0].metallic = 0.9f; + mat[0].sheen = 0.3f; + mat[0].cc_thickness = 0.393182f; + mat[0].cc_roughness = 0.05f; + mat[0].aniso = 0.2f; + mat[0].aniso_rot = 0.0f; + + mat[1].name = "Mat2"; + mat[1].color = {0.8f, 0.8f, 0.8f}; + mat[1].spec_color = {0.5f, 0.5f, 0.5f}; + mat[1].ior = 1.45f; + mat[1].alpha = 1; + mat[1].illum_mode = 2; + mat[1].metallic = 0.0f; + mat[1].cc_thickness = 0.3f; + mat[1].cc_roughness = 0.4f; + mat[1].aniso = 0.8f; + mat[1].aniso_rot = 0.7f; + { + MTLTexMap &pr = mat[1].tex_map_of_type(MTLTexMapType::Roughness); + pr.image_path = "../blend_geometry/texture_roughness.png"; + MTLTexMap &ps = mat[1].tex_map_of_type(MTLTexMapType::Sheen); + ps.image_path = "../blend_geometry/texture_checker.png"; + MTLTexMap &ke = mat[1].tex_map_of_type(MTLTexMapType::Emission); + ke.image_path = "../blend_geometry/texture_illum.png"; + } + + check("materials_pbr.mtl", mat, ARRAY_SIZE(mat)); +} + } // namespace blender::io::obj |