From 0576f4ca9b41f1f0e7dfdd896e539488419306ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 11 Apr 2019 15:03:08 +0200 Subject: Fix T62664: Exporting Metaballs as Alembic crashes Blender The `AbcMetaballWriter` now subclasses `AbcGenericMeshWriter` instead of wrapping an `AbcMeshWriter`. `AbcGenericMeshWriter` was created for this purpose (writing non-mesh objects as mesh to Alembic) and performs the work in a cleaner and, more importantly, not crashing way. --- source/blender/alembic/intern/abc_mball.cc | 40 +++++++++++++----------------- source/blender/alembic/intern/abc_mball.h | 16 ++++++------ source/blender/alembic/intern/abc_mesh.cc | 9 +++++-- source/blender/alembic/intern/abc_mesh.h | 1 + 4 files changed, 33 insertions(+), 33 deletions(-) (limited to 'source') diff --git a/source/blender/alembic/intern/abc_mball.cc b/source/blender/alembic/intern/abc_mball.cc index d023150106b..bb6ab57643f 100644 --- a/source/blender/alembic/intern/abc_mball.cc +++ b/source/blender/alembic/intern/abc_mball.cc @@ -44,41 +44,33 @@ AbcMBallWriter::AbcMBallWriter( AbcTransformWriter *parent, uint32_t time_sampling, ExportSettings &settings) - : AbcObjectWriter(ob, time_sampling, settings, parent) + : AbcGenericMeshWriter(ob, parent, time_sampling, settings) , m_bmain(bmain) { m_is_animated = isAnimated(); - - m_mesh_ob = BKE_object_copy(bmain, ob); - m_mesh_ob->runtime.curve_cache = (CurveCache *)MEM_callocN( - sizeof(CurveCache), - "CurveCache for AbcMBallWriter"); - /* TODO(Sybren): reimplement metaball writing as subclass of AbcGenericMeshWriter. */ - m_mesh_writer = new AbcMeshWriter(m_mesh_ob, parent, time_sampling, settings); - m_mesh_writer->setIsAnimated(m_is_animated); } AbcMBallWriter::~AbcMBallWriter() -{ - delete m_mesh_writer; - BKE_object_free(m_mesh_ob); -} +{} bool AbcMBallWriter::isAnimated() const { return true; } -void AbcMBallWriter::do_write() +Mesh *AbcMBallWriter::getEvaluatedMesh(Scene * /*scene_eval*/, Object *ob_eval, bool &r_needsfree) { - /* We have already stored a sample for this object. */ - if (!m_first_frame && !m_is_animated) - return; - + if (ob_eval->runtime.mesh_eval != NULL) { + /* Mesh_eval only exists when generative modifiers are in use. */ + r_needsfree = false; + return ob_eval->runtime.mesh_eval; + } + r_needsfree = true; + + /* The approach below is copied from BKE_mesh_new_from_object() */ Mesh *tmpmesh = BKE_mesh_add(m_bmain, ((ID *)m_object->data)->name + 2); BLI_assert(tmpmesh != NULL); - m_mesh_ob->data = tmpmesh; /* BKE_mesh_add gives us a user count we don't need */ id_us_min(&tmpmesh->id); @@ -92,12 +84,14 @@ void AbcMBallWriter::do_write() BKE_mesh_from_metaball(&disp, tmpmesh); BKE_displist_free(&disp); - BKE_mesh_texspace_copy_from_object(tmpmesh, m_mesh_ob); + BKE_mesh_texspace_copy_from_object(tmpmesh, m_object); - m_mesh_writer->write(); + return tmpmesh; +} - BKE_id_free(m_bmain, tmpmesh); - m_mesh_ob->data = NULL; +void AbcMBallWriter::freeEvaluatedMesh(struct Mesh *mesh) +{ + BKE_id_free(m_bmain, mesh); } bool AbcMBallWriter::isBasisBall(Scene *scene, Object *ob) diff --git a/source/blender/alembic/intern/abc_mball.h b/source/blender/alembic/intern/abc_mball.h index 629a584e89e..18ceda01f87 100644 --- a/source/blender/alembic/intern/abc_mball.h +++ b/source/blender/alembic/intern/abc_mball.h @@ -22,24 +22,21 @@ #define __ABC_MBALL_H__ #include "abc_object.h" +#include "abc_mesh.h" -class AbcMeshWriter; struct EvaluationContext; struct Main; struct MetaBall; struct Object; /* AbcMBallWriter converts the metaballs to meshes at every frame, - * and defers to a wrapped AbcMeshWriter to perform the writing + * and defers to AbcGenericMeshWriter to perform the writing * to the Alembic file. Only the basis balls are exported, as this * results in the entire shape as one mesh. */ -class AbcMBallWriter : public AbcObjectWriter { - AbcMeshWriter *m_mesh_writer; - Object *m_mesh_ob; - bool m_is_animated; +class AbcMBallWriter : public AbcGenericMeshWriter { Main *m_bmain; public: - AbcMBallWriter( + explicit AbcMBallWriter( Main *bmain, Object *ob, AbcTransformWriter *parent, @@ -50,8 +47,11 @@ public: static bool isBasisBall(Scene *scene, Object *ob); +protected: + Mesh *getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &r_needsfree) override; + void freeEvaluatedMesh(struct Mesh *mesh) override; + private: - virtual void do_write(); bool isAnimated() const; }; diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index 2472fe1945f..97cd6ffc0e3 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -387,14 +387,19 @@ void AbcGenericMeshWriter::do_write() writeMesh(mesh); } - if (needsfree) BKE_id_free(NULL, mesh); + if (needsfree) freeEvaluatedMesh(mesh); } catch (...) { - if (needsfree) BKE_id_free(NULL, mesh); + if (needsfree) freeEvaluatedMesh(mesh); throw; } } +void AbcGenericMeshWriter::freeEvaluatedMesh(struct Mesh *mesh) +{ + BKE_id_free(NULL, mesh); +} + void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh) { std::vector points, normals; diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h index 938c292b686..35ad0f8b297 100644 --- a/source/blender/alembic/intern/abc_mesh.h +++ b/source/blender/alembic/intern/abc_mesh.h @@ -61,6 +61,7 @@ protected: virtual void do_write(); virtual bool isAnimated() const; virtual Mesh *getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &r_needsfree) = 0; + virtual void freeEvaluatedMesh(struct Mesh *mesh); Mesh *getFinalMesh(bool &r_needsfree); -- cgit v1.2.3