diff options
Diffstat (limited to 'source/blender/io')
4 files changed, 45 insertions, 29 deletions
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/io/wavefront_obj/tests/obj_exporter_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc @@ -60,7 +60,7 @@ TEST_F(obj_exporter_test, filter_objects_curves_as_mesh) return; } auto [objmeshes, objcurves]{filter_supported_objects(depsgraph, _export.params)}; - EXPECT_EQ(objmeshes.size(), 17); + EXPECT_EQ(objmeshes.size(), 19); EXPECT_EQ(objcurves.size(), 0); } @@ -73,7 +73,7 @@ TEST_F(obj_exporter_test, filter_objects_curves_as_nurbs) } _export.params.export_curves_as_nurbs = true; auto [objmeshes, objcurves]{filter_supported_objects(depsgraph, _export.params)}; - EXPECT_EQ(objmeshes.size(), 16); + EXPECT_EQ(objmeshes.size(), 18); EXPECT_EQ(objcurves.size(), 2); } |