From da46eed1081ed9609a3245c5e23bdacf352ac783 Mon Sep 17 00:00:00 2001 From: Thomas Hope Date: Fri, 15 Aug 2025 15:03:44 +0200 Subject: [PATCH] IO: Add Apply Transforms option to obj exporter When enabled (default), exported OBJ files have the object transform applied to their vertices. This is the previous default behaviour. When disabled, exported vertices use their local object coordinates. Pull Request: https://projects.blender.org/blender/blender/pulls/139436 --- source/blender/editors/io/io_obj.cc | 7 +++++++ source/blender/io/wavefront_obj/IO_wavefront_obj.hh | 1 + .../io/wavefront_obj/exporter/obj_export_mesh.cc | 13 +++++++++---- .../io/wavefront_obj/exporter/obj_export_mesh.hh | 3 ++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/io/io_obj.cc b/source/blender/editors/io/io_obj.cc index ca868b4b748..96e2737d39b 100644 --- a/source/blender/editors/io/io_obj.cc +++ b/source/blender/editors/io/io_obj.cc @@ -102,6 +102,7 @@ static wmOperatorStatus wm_obj_export_exec(bContext *C, wmOperator *op) export_params.up_axis = eIOAxis(RNA_enum_get(op->ptr, "up_axis")); export_params.global_scale = RNA_float_get(op->ptr, "global_scale"); export_params.apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers"); + export_params.apply_transform = RNA_boolean_get(op->ptr, "apply_transform"); export_params.export_eval_mode = eEvaluationMode(RNA_enum_get(op->ptr, "export_eval_mode")); export_params.export_selected_objects = RNA_boolean_get(op->ptr, "export_selected_objects"); @@ -168,6 +169,7 @@ static void ui_obj_export_settings(const bContext *C, uiLayout *layout, PointerR col->prop( ptr, "export_triangulated_mesh", UI_ITEM_NONE, IFACE_("Triangulated Mesh"), ICON_NONE); col->prop(ptr, "apply_modifiers", UI_ITEM_NONE, IFACE_("Apply Modifiers"), ICON_NONE); + col->prop(ptr, "apply_transform", UI_ITEM_NONE, IFACE_("Apply Transform"), ICON_NONE); col->prop(ptr, "export_eval_mode", UI_ITEM_NONE, IFACE_("Properties"), ICON_NONE); } @@ -322,6 +324,11 @@ void WM_OT_obj_export(wmOperatorType *ot) /* File Writer options. */ RNA_def_boolean( ot->srna, "apply_modifiers", true, "Apply Modifiers", "Apply modifiers to exported meshes"); + RNA_def_boolean(ot->srna, + "apply_transform", + true, + "Apply Transform", + "Apply object transforms to exported vertices"); RNA_def_enum(ot->srna, "export_eval_mode", io_obj_export_evaluation_mode, diff --git a/source/blender/io/wavefront_obj/IO_wavefront_obj.hh b/source/blender/io/wavefront_obj/IO_wavefront_obj.hh index 9325e93ff46..6564adabf9e 100644 --- a/source/blender/io/wavefront_obj/IO_wavefront_obj.hh +++ b/source/blender/io/wavefront_obj/IO_wavefront_obj.hh @@ -47,6 +47,7 @@ struct OBJExportParams { /* File Write Options. */ bool export_selected_objects = false; bool apply_modifiers = true; + bool apply_transform = true; eEvaluationMode export_eval_mode = DAG_EVAL_VIEWPORT; bool export_uv = true; bool export_normals = true; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 6ce8e797876..9979b77d28c 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -69,8 +69,11 @@ OBJMesh::OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Obj this->materials[i] = BKE_object_material_get_eval(obj_eval, i + 1); } - set_world_axes_transform( - *obj_eval, export_params.forward_axis, export_params.up_axis, export_params.global_scale); + set_world_axes_transform(*obj_eval, + export_params.forward_axis, + export_params.up_axis, + export_params.global_scale, + export_params.apply_transform); } /** @@ -146,13 +149,15 @@ void OBJMesh::triangulate_mesh_eval() void OBJMesh::set_world_axes_transform(const Object &obj_eval, const eIOAxis forward, const eIOAxis up, - const float global_scale) + const float global_scale, + const bool apply_transform) { float3x3 axes_transform; /* +Y-forward and +Z-up are the default Blender axis settings. */ mat3_from_axis_conversion(forward, up, IO_AXIS_Y, IO_AXIS_Z, axes_transform.ptr()); - const float4x4 &object_to_world = obj_eval.object_to_world(); + const float4x4 &object_to_world = apply_transform ? obj_eval.object_to_world() : + float4x4::identity(); const float3x3 transform = axes_transform * float3x3(object_to_world); world_and_axes_transform_ = float4x4(transform); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh index ae60551e105..e91121e8ec6 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh @@ -223,6 +223,7 @@ class OBJMesh : NonCopyable { void set_world_axes_transform(const Object &obj_eval, eIOAxis forward, eIOAxis up, - float global_scale); + float global_scale, + bool apply_transform); }; } // namespace blender::io::obj