[Bf-blender-cvs] [a99a62231e0] master: obj: implement support for PBR .mtl extensions

Aras Pranckevicius noreply at git.blender.org
Tue Sep 13 14:04:25 CEST 2022


Commit: a99a62231e040a15c93add9ffa582ec9e1d9c4f1
Author: Aras Pranckevicius
Date:   Tue Sep 13 13:28:57 2022 +0300
Branches: master
https://developer.blender.org/rBa99a62231e040a15c93add9ffa582ec9e1d9c4f1

obj: implement support for PBR .mtl extensions

Implement import & export support for "PBR extensions" in .mtl files
(T101029, also fixes T86736).

Newly supported parameters:
- Roughness (Pr, map_Pr)
- Metallic (Pm, map_Pm)
- Sheen (Ps, map_Ps)
- Clearcoat thickness (Pc) and roughness (Pcr)
- Anisotropy (aniso) and rotation (anisor)
- Transmittance (Tf / Kt)

Exporter has an option to enable these additional PBR parameters
export; defaults to off since not all software understands that.

Exporter UI tweaked and all material-related options were put into
their own separate box.

Added/extended test files in Subversion repository for test coverage.

===================================================================

M	source/blender/editors/io/io_obj.c
M	source/blender/io/wavefront_obj/IO_wavefront_obj.h
M	source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
M	source/blender/io/wavefront_obj/exporter/obj_export_file_writer.hh
M	source/blender/io/wavefront_obj/exporter/obj_export_mtl.cc
M	source/blender/io/wavefront_obj/exporter/obj_export_mtl.hh
M	source/blender/io/wavefront_obj/exporter/obj_exporter.cc
M	source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc
M	source/blender/io/wavefront_obj/importer/obj_import_mtl.cc
M	source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
M	source/blender/io/wavefront_obj/tests/obj_exporter_tests.hh
M	source/blender/io/wavefront_obj/tests/obj_mtl_parser_tests.cc

===================================================================

diff --git a/source/blender/editors/io/io_obj.c b/source/blender/editors/io/io_obj.c
index 619d8a34132..cb8eafeb52d 100644
--- a/source/blender/editors/io/io_obj.c
+++ b/source/blender/editors/io/io_obj.c
@@ -93,6 +93,7 @@ static int wm_obj_export_exec(bContext *C, wmOperator *op)
   export_params.path_mode = RNA_enum_get(op->ptr, "path_mode");
   export_params.export_triangulated_mesh = RNA_boolean_get(op->ptr, "export_triangulated_mesh");
   export_params.export_curves_as_nurbs = RNA_boolean_get(op->ptr, "export_curves_as_nurbs");
+  export_params.export_pbr_extensions = RNA_boolean_get(op->ptr, "export_pbr_extensions");
 
   export_params.export_object_groups = RNA_boolean_get(op->ptr, "export_object_groups");
   export_params.export_material_groups = RNA_boolean_get(op->ptr, "export_material_groups");
@@ -118,7 +119,6 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
 
   /* Object Transform options. */
   box = uiLayoutBox(layout);
-  uiItemL(box, IFACE_("Object Properties"), ICON_OBJECT_DATA);
   col = uiLayoutColumn(box, false);
   sub = uiLayoutColumnWithHeading(col, false, IFACE_("Limit to"));
   uiItemR(sub, imfptr, "export_selected_objects", 0, IFACE_("Selected Only"), ICON_NONE);
@@ -134,27 +134,31 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
   sub = uiLayoutColumnWithHeading(col, false, IFACE_("Objects"));
   uiItemR(sub, imfptr, "apply_modifiers", 0, IFACE_("Apply Modifiers"), ICON_NONE);
   uiItemR(sub, imfptr, "export_eval_mode", 0, IFACE_("Properties"), ICON_NONE);
-  sub = uiLayoutColumn(sub, false);
-  uiLayoutSetEnabled(sub, export_materials);
-  uiItemR(sub, imfptr, "path_mode", 0, IFACE_("Path Mode"), ICON_NONE);
 
-  /* Options for what to write. */
+  /* Geometry options. */
   box = uiLayoutBox(layout);
-  uiItemL(box, IFACE_("Geometry"), ICON_EXPORT);
   col = uiLayoutColumn(box, false);
-  sub = uiLayoutColumnWithHeading(col, false, IFACE_("Export"));
+  sub = uiLayoutColumnWithHeading(col, false, IFACE_("Geometry"));
   uiItemR(sub, imfptr, "export_uv", 0, IFACE_("UV Coordinates"), ICON_NONE);
   uiItemR(sub, imfptr, "export_normals", 0, IFACE_("Normals"), ICON_NONE);
   uiItemR(sub, imfptr, "export_colors", 0, IFACE_("Colors"), ICON_NONE);
-  uiItemR(sub, imfptr, "export_materials", 0, IFACE_("Materials"), ICON_NONE);
   uiItemR(sub, imfptr, "export_triangulated_mesh", 0, IFACE_("Triangulated Mesh"), ICON_NONE);
   uiItemR(sub, imfptr, "export_curves_as_nurbs", 0, IFACE_("Curves as NURBS"), ICON_NONE);
 
+  /* Material options. */
+  box = uiLayoutBox(layout);
+  col = uiLayoutColumn(box, false);
+  sub = uiLayoutColumnWithHeading(col, false, IFACE_("Materials"));
+  uiItemR(sub, imfptr, "export_materials", 0, IFACE_("Export"), ICON_NONE);
+  sub = uiLayoutColumn(sub, false);
+  uiLayoutSetEnabled(sub, export_materials);
+  uiItemR(sub, imfptr, "export_pbr_extensions", 0, IFACE_("PBR Extensions"), ICON_NONE);
+  uiItemR(sub, imfptr, "path_mode", 0, IFACE_("Path Mode"), ICON_NONE);
+
   /* Grouping options. */
   box = uiLayoutBox(layout);
-  uiItemL(box, IFACE_("Grouping"), ICON_GROUP);
   col = uiLayoutColumn(box, false);
-  sub = uiLayoutColumnWithHeading(col, false, IFACE_("Export"));
+  sub = uiLayoutColumnWithHeading(col, false, IFACE_("Grouping"));
   uiItemR(sub, imfptr, "export_object_groups", 0, IFACE_("Object Groups"), ICON_NONE);
   uiItemR(sub, imfptr, "export_material_groups", 0, IFACE_("Material Groups"), ICON_NONE);
   uiItemR(sub, imfptr, "export_vertex_groups", 0, IFACE_("Vertex Groups"), ICON_NONE);
@@ -165,14 +169,13 @@ static void ui_obj_export_settings(uiLayout *layout, PointerRNA *imfptr)
 
   /* Animation options. */
   box = uiLayoutBox(layout);
-  uiItemL(box, IFACE_("Animation"), ICON_ANIM);
   col = uiLayoutColumn(box, false);
-  sub = uiLayoutColumn(col, false);
-  uiItemR(sub, imfptr, "export_animation", 0, NULL, ICON_NONE);
+  sub = uiLayoutColumnWithHeading(col, false, IFACE_("Animation"));
+  uiItemR(sub, imfptr, "export_animation", 0, IFACE_("Export"), ICON_NONE);
   sub = uiLayoutColumn(sub, true);
+  uiLayoutSetEnabled(sub, export_animation);
   uiItemR(sub, imfptr, "start_frame", 0, IFACE_("Frame Start"), ICON_NONE);
   uiItemR(sub, imfptr, "end_frame", 0, IFACE_("End"), ICON_NONE);
-  uiLayoutSetEnabled(sub, export_animation);
 }
 
 static void wm_obj_export_draw(bContext *UNUSED(C), wmOperator *op)
@@ -336,6 +339,12 @@ void WM_OT_obj_export(struct wmOperatorType *ot)
                   "Export Materials",
                   "Export MTL library. There must be a Principled-BSDF node for image textures to "
                   "be exported to the MTL file");
+  RNA_def_boolean(ot->srna,
+                  "export_pbr_extensions",
+                  false,
+                  "Export Materials with PBR Extensions",
+                  "Export MTL library using PBR extensions (roughness, metallic, sheen, "
+                  "clearcoat, anisotropy, transmission)");
   RNA_def_enum(ot->srna,
                "path_mode",
                io_obj_path_mode,
diff --git a/source/blender/io/wavefront_obj/IO_wavefront_obj.h b/source/blender/io/wavefront_obj/IO_wavefront_obj.h
index 544630c9cc0..0a92bbca477 100644
--- a/source/blender/io/wavefront_obj/IO_wavefront_obj.h
+++ b/source/blender/io/wavefront_obj/IO_wavefront_obj.h
@@ -48,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 27526734624..f2547e6fc14 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
@@ -493,11 +493,14 @@ void OBJWriter::write_nurbs_curve(FormatHandler &fh, const OBJCurve &obj_nurbs_d
 
 static const char *tex_map_type_to_string[] = {
     "map_Kd",
+    "map_Pm",
     "map_Ks",
     "map_Ns",
-    "map_d",
+    "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,
@@ -553,16 +556,20 @@ 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(MTLTexMapType::SpecularExponent).is_valid()) {
-    fmt_handler_.write_mtl_float("Ns", mtl.spec_exponent);
+
+  /* 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_mtl_float3(
-      "Ka", mtl.ambient_color.x, mtl.ambient_color.y, mtl.ambient_color.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);
   }
@@ -578,6 +585,35 @@ void MTLWriter::write_bsdf_properties(const MTLMaterial &mtl)
     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);
+    }
+  }
 }
 
 void MTLWriter::write_texture_map(const MTLMaterial &mtl_material,
@@ -608,9 +644,21 @@ void MTLWriter::write_texture_map(const MTLMaterial &mtl_material,
   fmt_handler_.write_mtl_map(tex_map_type_to_string[(int)texture_key], options, path);
 }
 
+static bool is_pbr_map(MTLTexMapType type)
+{
+  return type == MTLTexMapType::Metallic || type == MTLTexMapType::Roughness ||
+         type == MTLTexMapType::Sheen;
+}
+
+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;
@@ -628,12 +676,18 @@ void MTLWriter::write_materials(const char *blen_filepath,
   for (const MTLMaterial &mtlmat : mtlmate

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list