diff options
Diffstat (limited to 'source/blender/io')
18 files changed, 438 insertions, 613 deletions
diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index 2820a128072..9c71944fc92 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -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); diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 2253880d5ca..16e5ee968a3 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -391,7 +391,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; } @@ -896,7 +896,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) { diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index b40546dfd97..fab53908d5a 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -341,7 +341,8 @@ 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); + me->mvert = (MVert *)CustomData_add_layer( + &me->vdata, CD_MVERT, CD_SET_DEFAULT, nullptr, me->totvert); MVert *mvert; int i; @@ -449,9 +450,9 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) 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->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, me->totpoly); me->mloop = (MLoop *)CustomData_add_layer( - &me->ldata, CD_MLOOP, CD_CALLOC, nullptr, me->totloop); + &me->ldata, CD_MLOOP, CD_SET_DEFAULT, nullptr, me->totloop); unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount(); for (int i = 0; i < totuvset; i++) { @@ -468,7 +469,7 @@ 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); @@ -481,7 +482,7 @@ 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); } @@ -546,11 +547,11 @@ 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); @@ -615,7 +616,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) MaterialIdPrimitiveArrayMap mat_prim_map; int *material_indices = (int *)CustomData_add_layer_named( - &me->pdata, CD_PROP_INT32, CD_DEFAULT, nullptr, me->totpoly, "material_index"); + &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(); diff --git a/source/blender/io/stl/importer/stl_import_mesh.cc b/source/blender/io/stl/importer/stl_import_mesh.cc index b9ed441f0d9..178b5b9347f 100644 --- a/source/blender/io/stl/importer/stl_import_mesh.cc +++ b/source/blender/io/stl/importer/stl_import_mesh.cc @@ -77,7 +77,7 @@ Mesh *STLMeshHelper::to_mesh(Main *bmain, char *mesh_name) 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)); for (int i = 0; i < mesh->totvert; i++) { copy_v3_v3(mesh->mvert[i].co, verts_[i]); } @@ -85,9 +85,9 @@ Mesh *STLMeshHelper::to_mesh(Main *bmain, char *mesh_name) 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)); + CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_SET_DEFAULT, nullptr, mesh->totpoly)); mesh->mloop = static_cast<MLoop *>( - CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CALLOC, nullptr, mesh->totloop)); + CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_CONSTRUCT, nullptr, mesh->totloop)); threading::parallel_for(tris_.index_range(), 2048, [&](IndexRange tris_range) { for (const int i : tris_range) { diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 73a65bafc85..89a98097780 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -208,7 +208,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; } @@ -576,7 +577,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]; 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 4c3d52131b7..902f801ee5b 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,7 +243,7 @@ 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 { @@ -265,41 +260,40 @@ void OBJWriter::write_vertex_coords(FormatHandler<eFileType::OBJ> &fh, 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,9 +369,8 @@ 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)); } } @@ -391,7 +384,7 @@ void OBJWriter::write_poly_elements(FormatHandler<eFileType::OBJ> &fh, 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); @@ -401,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); } } } @@ -418,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 { @@ -430,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++) { @@ -444,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. @@ -461,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 @@ -478,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) { @@ -489,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(); } } @@ -501,6 +491,18 @@ void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh, /** \name .MTL writers. * \{ */ +static const char *tex_map_type_to_string[] = { + "map_Kd", + "map_Ks", + "map_Ns", + "map_d", + "map_refl", + "map_Ke", + "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. @@ -541,9 +543,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 @@ -556,67 +558,52 @@ void MTLWriter::write_bsdf_properties(const MTLMaterial &mtl) /* 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); + if (!mtl.tex_map_of_type(MTLTexMapType::Ns).is_valid()) { + fmt_handler_.write_mtl_float("Ns", mtl.Ns); } - 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); + fmt_handler_.write_mtl_float3("Ka", mtl.Ka.x, mtl.Ka.y, mtl.Ka.z); + if (!mtl.tex_map_of_type(MTLTexMapType::Kd).is_valid()) { + fmt_handler_.write_mtl_float3("Kd", mtl.Kd.x, mtl.Kd.y, mtl.Kd.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::Ks).is_valid()) { + fmt_handler_.write_mtl_float3("Ks", mtl.Ks.x, mtl.Ks.y, mtl.Ks.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::Ke).is_valid()) { + fmt_handler_.write_mtl_float3("Ke", mtl.Ke.x, mtl.Ke.y, mtl.Ke.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.Ni); + if (!mtl.tex_map_of_type(MTLTexMapType::d).is_valid()) { + fmt_handler_.write_mtl_float("d", mtl.d); } - fmt_handler_.write<eMTLSyntaxElement::illum>(mtl.illum); + fmt_handler_.write_mtl_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) { + if (texture_key == MTLTexMapType::bump && mtl_material.map_Bump_strength > 0.0001f) { options.append(" -bm ").append(std::to_string(mtl_material.map_Bump_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; \ - } - - 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 - - BLI_assert(!"This map type was not written to the file."); + fmt_handler_.write_mtl_map(tex_map_type_to_string[(int)texture_key], options, path); } void MTLWriter::write_materials(const char *blen_filepath, @@ -637,14 +624,16 @@ 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); + fmt_handler_.write_string(""); + fmt_handler_.write_mtl_newmtl(mtlmat.name); write_bsdf_properties(mtlmat); - for (const auto &tex : mtlmat.texture_maps.items()) { - if (!tex.value.is_valid()) { + for (int key = 0; key < (int)MTLTexMapType::Count; key++) { + const MTLTexMap &tex = mtlmat.texture_maps[key]; + if (!tex.is_valid()) { 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..4544037fbc1 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_; @@ -208,7 +208,8 @@ class MTLWriter : NonMovable, NonCopyable { * 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..cc0f7c0824c 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_mtl.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc index 4ed148ec64e..0b228ef8c37 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,23 @@ #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", + "Specular", + "Roughness", + "Alpha", + "Metallic", + "Emission", + "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 +83,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,13 +110,12 @@ 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; @@ -141,16 +151,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,55 +171,50 @@ 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}); + if (bsdf_node) { + copy_property_from_node(SOCK_FLOAT, bsdf_node, "Alpha", {&dissolved, 1}); } const bool transparent = dissolved != 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); @@ -253,8 +258,8 @@ static void store_bsdf_properties(const nodes::NodeRef *bsdf_node, /** * 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 +267,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::bump) { /* 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 +289,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::Ke) { 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. */ @@ -317,10 +322,10 @@ static void store_image_textures(const nodes::NodeRef *bsdf_node, } /* 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 +335,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..d8eafff107b 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,23 @@ #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 { Kd = 0, Ks, Ns, d, refl, Ke, bump, 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,26 +35,13 @@ 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; @@ -81,7 +55,7 @@ struct MTLMaterial { float Ni{-1.0f}; float d{-1.0f}; int illum{-1}; - Map<const eMTLSyntaxElement, tex_map_XX> texture_maps; + MTLTexMap texture_maps[(int)MTLTexMapType::Count]; /** Only used for Normal Map node: "map_Bump". */ float map_Bump_strength{-1.0f}; }; diff --git a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc index 77d4f6268bc..76cf9066bf4 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc @@ -143,7 +143,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 +242,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) { 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 633f70b2e38..088784b4194 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 @@ -592,36 +592,31 @@ 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::Kd; } if (parse_keyword(p, end, "map_Ks")) { - return eMTLSyntaxElement::map_Ks; + return MTLTexMapType::Ks; } if (parse_keyword(p, end, "map_Ns")) { - return eMTLSyntaxElement::map_Ns; + return MTLTexMapType::Ns; } if (parse_keyword(p, end, "map_d")) { - return eMTLSyntaxElement::map_d; + return MTLTexMapType::d; } - 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::refl; } if (parse_keyword(p, end, "map_Ke")) { - return eMTLSyntaxElement::map_Ke; - } - if (parse_keyword(p, end, "bump")) { - return eMTLSyntaxElement::map_Bump; + return MTLTexMapType::Ke; } - if (parse_keyword(p, end, "map_Bump") || parse_keyword(p, end, "map_bump")) { - return eMTLSyntaxElement::map_Bump; + if (parse_keyword(p, end, "bump") || parse_keyword(p, end, "map_Bump") || + parse_keyword(p, end, "map_bump")) { + return MTLTexMapType::bump; } - return eMTLSyntaxElement::string; + return MTLTexMapType::Count; } static const std::pair<StringRef, int> unsupported_texture_options[] = { @@ -639,7 +634,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")) { @@ -693,13 +688,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. */ 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 4e6983bc0d5..7f7fda8d8f1 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -181,7 +181,7 @@ void MeshFromGeometry::create_polys_loops(Mesh *mesh, bool use_vertex_groups) 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)); + CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_SET_DEFAULT, nullptr, total_verts)); } bke::SpanAttributeWriter<int> material_indices = @@ -268,7 +268,7 @@ 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_) { 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..c28de14f2f7 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,6 @@ #include "NOD_shader.h" -/* TODO: move eMTLSyntaxElement out of following file into a more neutral place */ -#include "obj_export_io.hh" #include "obj_import_mtl.hh" #include "obj_import_string_utils.hh" @@ -29,12 +27,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 +93,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; @@ -206,15 +204,15 @@ std::pair<float, float> ShaderNodetreeWrap::set_node_locations(const int pos_x) } void ShaderNodetreeWrap::link_sockets(bNode *from_node, - StringRef from_node_id, + const char *from_node_id, bNode *to_node, - StringRef to_node_id, + const char *to_node_id, const int from_node_pos_x) { 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); } @@ -338,7 +336,7 @@ void ShaderNodetreeWrap::set_bsdf_socket_values(Material *mat) if (emission_color.x >= 0 && emission_color.y >= 0 && emission_color.z >= 0) { set_property_of_socket(SOCK_RGBA, "Emission", {emission_color, 3}, bsdf_); } - if (mtl_mat_.tex_map_of_type(eMTLSyntaxElement::map_Ke).is_valid()) { + if (mtl_mat_.tex_map_of_type(MTLTexMapType::Ke).is_valid()) { set_property_of_socket(SOCK_FLOAT, "Emission Strength", {1.0f}, bsdf_); } set_property_of_socket(SOCK_FLOAT, "Specular", {specular}, bsdf_); @@ -359,38 +357,36 @@ void ShaderNodetreeWrap::set_bsdf_socket_values(Material *mat) void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *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()) { + 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; + static_cast<NodeTexImage *>(image_texture->storage)->projection = value.projection_type; /* Add normal map node if needed. */ bNode *normal_map = nullptr; - if (texture_map.key == eMTLSyntaxElement::map_Bump) { + if (key == (int)MTLTexMapType::bump) { normal_map = add_node_to_tree(SH_NODE_NORMAL_MAP); const float bump = std::max(0.0f, mtl_mat_.map_Bump_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)) { + if (value.translation != float3(0, 0, 0) || 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); + set_property_of_socket(SOCK_VECTOR, "Location", {value.translation, 3}, mapping); + set_property_of_socket(SOCK_VECTOR, "Scale", {value.scale, 3}, mapping); link_sockets(texture_coordinate, "UV", mapping, "Vector", 0); link_sockets(mapping, "Vector", image_texture, "Vector", 1); @@ -400,12 +396,12 @@ void ShaderNodetreeWrap::add_image_textures(Main *bmain, Material *mat, bool rel link_sockets(image_texture, "Color", normal_map, "Color", 2); link_sockets(normal_map, "Normal", bsdf_, "Normal", 3); } - 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::d) { + link_sockets(image_texture, "Alpha", bsdf_, tex_map_type_to_socket_id[key], 2); mat->blend_method = MA_BM_BLEND; } else { - link_sockets(image_texture, "Color", bsdf_, texture_map.value.dest_socket_id, 2); + link_sockets(image_texture, "Color", bsdf_, tex_map_type_to_socket_id[key], 2); } } } 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..2c51d92a2cd 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mtl.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_mtl.hh @@ -10,7 +10,6 @@ #include "BLI_map.hh" #include "BLI_math_vec_types.hh" -#include "BLI_string_ref.hh" #include "BLI_vector.hh" #include "DNA_node_types.h" @@ -75,9 +74,9 @@ class ShaderNodetreeWrap { * \param from_node_pos_x: 0 to 4 value as per nodetree arrangement. */ void link_sockets(bNode *from_node, - StringRef from_node_id, + const char *from_node_id, bNode *to_node, - StringRef to_node_id, + const char *to_node_id, const int from_node_pos_x); /** * Set values of sockets in p-BSDF node of the nodetree. 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..0fd711bdac6 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); 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..35f977f41df 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -12,7 +12,7 @@ #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" 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..41faba95b30 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 @@ -58,9 +58,9 @@ class obj_mtl_parser_test : public testing::Test { 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); + 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); @@ -113,8 +113,8 @@ TEST_F(obj_mtl_parser_test, string_newlines_whitespace) mat[4].Kd = {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].tex_map_of_type(MTLTexMapType::Kd).image_path = "sometex_d.png"; + mat[5].tex_map_of_type(MTLTexMapType::Ks).image_path = "sometex_s_spaces_after_name.png"; check_string(text, mat, ARRAY_SIZE(mat)); } @@ -175,13 +175,13 @@ TEST_F(obj_mtl_parser_test, materials) mat[1].illum = 2; mat[1].map_Bump_strength = 1; { - tex_map_XX &kd = mat[1].tex_map_of_type(eMTLSyntaxElement::map_Kd); + MTLTexMap &kd = mat[1].tex_map_of_type(MTLTexMapType::Kd); 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::Ns); 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::refl); 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::bump); bump.image_path = "sometexture_Normal.png"; } @@ -202,13 +202,13 @@ TEST_F(obj_mtl_parser_test, materials) mat[3].Ns = 800; mat[3].map_Bump_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::Kd); 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::Ns); 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::refl); 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::bump); bump.image_path = "someHatTexture_Normal.jpg"; } @@ -222,30 +222,30 @@ TEST_F(obj_mtl_parser_test, materials) mat[4].d = 0.5; mat[4].map_Bump_strength = 0.1f; { - tex_map_XX &kd = mat[4].tex_map_of_type(eMTLSyntaxElement::map_Kd); + MTLTexMap &kd = mat[4].tex_map_of_type(MTLTexMapType::Kd); 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::Ns); 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::refl); 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::bump); 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::Kd); 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::Ks); 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::Ns); ns.scale = {0.5f, 1.0f, 1.0f}; ns.image_path = "1.Value.png"; } |