[Bf-blender-cvs] [54d69a2fd1b] master: Fix new OBJ exporter to handle instancing.

Howard Trickey noreply at git.blender.org
Fri Jan 21 20:41:46 CET 2022


Commit: 54d69a2fd1be60aaba62f92cd0db5b5ba71495aa
Author: Howard Trickey
Date:   Fri Jan 21 14:37:33 2022 -0500
Branches: master
https://developer.blender.org/rB54d69a2fd1be60aaba62f92cd0db5b5ba71495aa

Fix new OBJ exporter to handle instancing.

The new OBJ exporter did not handle object instances.
The fix is to use a dependency graph iterator, asking for instances.
Unfortunately that iterator makes a temporary copy of instance objects
that does not persist past the iteration, but we need to save all the
objects and meshes to write later, so the Object has to be copied now.

This changed some unit tests. Even though the tests don't have instancing,
the iterator also picks up some Text objects as Mesh ones (which is a good
thing), resulting in two more objects in the all_objects.obj file output.

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

M	source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
M	source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
M	source/blender/io/wavefront_obj/exporter/obj_exporter.cc
M	source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc

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

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 d6e1d8a7ea5..b77b5735784 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc
@@ -17,6 +17,8 @@
 /** \file
  * \ingroup obj
  */
+/* Silence warnings from copying deprecated fields. Needed for an Object copy constructor use. */
+#define DNA_DEPRECATED_ALLOW
 
 #include "BKE_customdata.h"
 #include "BKE_deform.h"
@@ -42,20 +44,21 @@
 namespace blender::io::obj {
 OBJMesh::OBJMesh(Depsgraph *depsgraph, const OBJExportParams &export_params, Object *mesh_object)
 {
-  export_object_eval_ = DEG_get_evaluated_object(depsgraph, mesh_object);
-  export_mesh_eval_ = BKE_object_get_evaluated_mesh(export_object_eval_);
+  /* We need to copy the object because it may be in temporary space. */
+  Object *obj_eval = DEG_get_evaluated_object(depsgraph, mesh_object);
+  export_object_eval_ = *obj_eval;
+  export_mesh_eval_ = BKE_object_get_evaluated_mesh(&export_object_eval_);
   mesh_eval_needs_free_ = false;
 
   if (!export_mesh_eval_) {
     /* Curves and NURBS surfaces need a new mesh when they're
      * exported in the form of vertices and edges.
      */
-    export_mesh_eval_ = BKE_mesh_new_from_object(depsgraph, export_object_eval_, true, true);
+    export_mesh_eval_ = BKE_mesh_new_from_object(depsgraph, &export_object_eval_, true, true);
     /* Since a new mesh been allocated, it needs to be freed in the destructor. */
     mesh_eval_needs_free_ = true;
   }
-  if (export_params.export_triangulated_mesh &&
-      ELEM(export_object_eval_->type, OB_MESH, OB_SURF)) {
+  if (export_params.export_triangulated_mesh && ELEM(export_object_eval_.type, OB_MESH, OB_SURF)) {
     std::tie(export_mesh_eval_, mesh_eval_needs_free_) = triangulate_mesh_eval();
   }
   set_world_axes_transform(export_params.forward_axis, export_params.up_axis);
@@ -116,10 +119,10 @@ void OBJMesh::set_world_axes_transform(const eTransformAxisForward forward,
   mat3_from_axis_conversion(OBJ_AXIS_Y_FORWARD, OBJ_AXIS_Z_UP, forward, up, axes_transform);
   /* mat3_from_axis_conversion returns a transposed matrix! */
   transpose_m3(axes_transform);
-  mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_->obmat);
+  mul_m4_m3m4(world_and_axes_transform_, axes_transform, export_object_eval_.obmat);
   /* mul_m4_m3m4 does not transform last row of obmat, i.e. location data. */
-  mul_v3_m3v3(world_and_axes_transform_[3], axes_transform, export_object_eval_->obmat[3]);
-  world_and_axes_transform_[3][3] = export_object_eval_->obmat[3][3];
+  mul_v3_m3v3(world_and_axes_transform_[3], axes_transform, export_object_eval_.obmat[3]);
+  world_and_axes_transform_[3][3] = export_object_eval_.obmat[3][3];
 }
 
 int OBJMesh::tot_vertices() const
@@ -185,8 +188,14 @@ void OBJMesh::calc_smooth_groups(const bool use_bitflags)
 
 const Material *OBJMesh::get_object_material(const int16_t mat_nr) const
 {
-  /* "+ 1" as material getter needs one-based indices.  */
-  const Material *r_mat = BKE_object_material_get(export_object_eval_, mat_nr + 1);
+  /**
+   * The const_cast is safe here because BKE_object_material_get won't change the object
+   * but it is a big can of worms to fix the declaration of that function right now.
+   *
+   * The call uses "+ 1" as material getter needs one-based indices.
+   */
+  Object *obj = const_cast<Object *>(&export_object_eval_);
+  const Material *r_mat = BKE_object_material_get(obj, mat_nr + 1);
 #ifdef DEBUG
   if (!r_mat) {
     std::cerr << "Material not found for mat_nr = " << mat_nr << std::endl;
@@ -209,7 +218,7 @@ int16_t OBJMesh::ith_poly_matnr(const int poly_index) const
 
 const char *OBJMesh::get_object_name() const
 {
-  return export_object_eval_->id.name + 2;
+  return export_object_eval_.id.name + 2;
 }
 
 const char *OBJMesh::get_object_mesh_name() const
@@ -403,7 +412,7 @@ int16_t OBJMesh::get_poly_deform_group_index(const int poly_index) const
   BLI_assert(poly_index < export_mesh_eval_->totpoly);
   const MPoly &mpoly = export_mesh_eval_->mpoly[poly_index];
   const MLoop *mloop = &export_mesh_eval_->mloop[mpoly.loopstart];
-  const Object *obj = export_object_eval_;
+  const Object *obj = &export_object_eval_;
   const int tot_deform_groups = BKE_object_defgroup_count(obj);
   /* Indices of the vector index into deform groups of an object; values are the]
    * number of vertex members in one deform group. */
@@ -444,7 +453,7 @@ int16_t OBJMesh::get_poly_deform_group_index(const int poly_index) const
 const char *OBJMesh::get_poly_deform_group_name(const int16_t def_group_index) const
 {
   const bDeformGroup &vertex_group = *(static_cast<bDeformGroup *>(
-      BLI_findlink(BKE_object_defgroup_list(export_object_eval_), def_group_index)));
+      BLI_findlink(BKE_object_defgroup_list(&export_object_eval_), def_group_index)));
   return vertex_group.name;
 }
 
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 390d8034337..f3ace140006 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.hh
@@ -32,6 +32,7 @@
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
 
 #include "IO_wavefront_obj.h"
 
@@ -57,7 +58,11 @@ using unique_bmesh_ptr = std::unique_ptr<BMesh, CustomBMeshDeleter>;
 
 class OBJMesh : NonCopyable {
  private:
-  Object *export_object_eval_;
+  /**
+   * We need to copy the entire Object structure here because the dependency graph iterator
+   * sometimes builds an Object in a temporary space that doesn't persist.
+   */
+  Object export_object_eval_;
   Mesh *export_mesh_eval_;
   /**
    * For curves which are converted to mesh, and triangulated meshes, a new mesh is allocated.
@@ -85,7 +90,7 @@ class OBJMesh : NonCopyable {
    * Total number of normal indices (maximum entry, plus 1, in
    * the loop_to_norm_index_ vector).
    */
-  int tot_normal_indices_ = NEGATIVE_INIT;
+  int tot_normal_indices_ = 0;
   /**
    * Total smooth groups in an object.
    */
diff --git a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
index 595e6aaf4f2..0c753ccdcac 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_exporter.cc
@@ -91,28 +91,29 @@ filter_supported_objects(Depsgraph *depsgraph, const OBJExportParams &export_par
 {
   Vector<std::unique_ptr<OBJMesh>> r_exportable_meshes;
   Vector<std::unique_ptr<OBJCurve>> r_exportable_nurbs;
-  const ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
-  LISTBASE_FOREACH (const Base *, base, &view_layer->object_bases) {
-    Object *object_in_layer = base->object;
-    if (export_params.export_selected_objects && !(object_in_layer->base_flag & BASE_SELECTED)) {
+  const int deg_objects_visibility_flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+                                           DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
+                                           DEG_ITER_OBJECT_FLAG_VISIBLE |
+                                           DEG_ITER_OBJECT_FLAG_DUPLI;
+  DEG_OBJECT_ITER_BEGIN (depsgraph, object, deg_objects_visibility_flags) {
+    if (export_params.export_selected_objects && !(object->base_flag & BASE_SELECTED)) {
       continue;
     }
-    switch (object_in_layer->type) {
+    switch (object->type) {
       case OB_SURF:
         /* Export in mesh form: vertices and polygons. */
         ATTR_FALLTHROUGH;
       case OB_MESH:
-        r_exportable_meshes.append(
-            std::make_unique<OBJMesh>(depsgraph, export_params, object_in_layer));
+        r_exportable_meshes.append(std::make_unique<OBJMesh>(depsgraph, export_params, object));
         break;
       case OB_CURVE: {
-        Curve *curve = static_cast<Curve *>(object_in_layer->data);
+        Curve *curve = static_cast<Curve *>(object->data);
         Nurb *nurb{static_cast<Nurb *>(curve->nurb.first)};
         if (!nurb) {
           /* An empty curve. Not yet supported to export these as meshes. */
           if (export_params.export_curves_as_nurbs) {
             r_exportable_nurbs.append(
-                std::make_unique<OBJCurve>(depsgraph, export_params, object_in_layer));
+                std::make_unique<OBJCurve>(depsgraph, export_params, object));
           }
           break;
         }
@@ -121,18 +122,18 @@ filter_supported_objects(Depsgraph *depsgraph, const OBJExportParams &export_par
             if (export_params.export_curves_as_nurbs) {
               /* Export in parameter form: control points. */
               r_exportable_nurbs.append(
-                  std::make_unique<OBJCurve>(depsgraph, export_params, object_in_layer));
+                  std::make_unique<OBJCurve>(depsgraph, export_params, object));
             }
             else {
               /* Export in mesh form: edges and vertices. */
               r_exportable_meshes.append(
-                  std::make_unique<OBJMesh>(depsgraph, export_params, object_in_layer));
+                  std::make_unique<OBJMesh>(depsgraph, export_params, object));
             }
             break;
           case CU_BEZIER:
             /* Always export in mesh form: edges and vertices. */
             r_exportable_meshes.append(
-                std::make_unique<OBJMesh>(depsgraph, export_params, object_in_layer));
+                std::make_unique<OBJMesh>(depsgraph, export_params, object));
             break;
           default:
             /* Other curve types are not supported. */
@@ -145,6 +146,7 @@ filter_supported_objects(Depsgraph *depsgraph, const OBJExportParams &export_par
         break;
     }
   }
+  DEG_OBJECT_ITER_END;
   return {std::move(r_exportable_meshes), std::move(r_exportable_nurbs)};
 }
 
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 92d478c20a1..5dac913c902 100644
--- a/source/blender/

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list