Alembic: exporting MetaBalls as mesh
[blender.git] / source / blender / alembic / intern / abc_mball.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Sybren A. Stüvel
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 #include "abc_mball.h"
24 #include "abc_mesh.h"
25 #include "abc_transform.h"
26
27 extern "C" {
28 #include "DNA_meta_types.h"
29 #include "DNA_mesh_types.h"
30 #include "DNA_object_types.h"
31
32 #include "BKE_curve.h"
33 #include "BKE_depsgraph.h"
34 #include "BKE_displist.h"
35 #include "BKE_main.h"
36 #include "BKE_mball.h"
37 #include "BKE_mesh.h"
38 #include "BKE_object.h"
39
40 #include "DEG_depsgraph.h"
41 #include "MEM_guardedalloc.h"
42 }
43
44 AbcMBallWriter::AbcMBallWriter(
45         Main *bmain,
46         Scene *scene,
47         Object *ob,
48         AbcTransformWriter *parent,
49         uint32_t time_sampling,
50         ExportSettings &settings)
51     : AbcObjectWriter(scene, ob, time_sampling, settings, parent)
52     , m_bmain(bmain)
53 {
54         m_is_animated = isAnimated();
55
56         m_mesh_ob = BKE_object_copy(bmain, ob);
57         m_mesh_ob->curve_cache = (CurveCache*)MEM_callocN(
58                                      sizeof(CurveCache),
59                                      "CurveCache for AbcMBallWriter");
60
61         m_mesh_writer = new AbcMeshWriter(scene, m_mesh_ob, parent,
62                                           time_sampling, settings);
63         m_mesh_writer->setIsAnimated(m_is_animated);
64 }
65
66
67 AbcMBallWriter::~AbcMBallWriter()
68 {
69         delete m_mesh_writer;
70         BKE_object_free(m_mesh_ob);
71 }
72
73 bool AbcMBallWriter::isAnimated() const
74 {
75         MetaBall *mb = static_cast<MetaBall *>(m_object->data);
76         if (mb->adt != NULL) return true;
77
78         /* Any movement of any object in the parent chain
79          * could cause the mball to deform. */
80         for (Object *ob = m_object; ob != NULL; ob = ob->parent) {
81                 if (ob->adt != NULL) return true;
82         }
83         return false;
84 }
85
86 void AbcMBallWriter::do_write()
87 {
88         /* We have already stored a sample for this object. */
89         if (!m_first_frame && !m_is_animated)
90                 return;
91
92         Mesh *tmpmesh = BKE_mesh_add(m_bmain, ((ID *)m_object->data)->name + 2);
93         BLI_assert(tmpmesh != NULL);
94         m_mesh_ob->data = tmpmesh;
95
96         /* BKE_mesh_add gives us a user count we don't need */
97         id_us_min(&tmpmesh->id);
98
99         ListBase disp = {NULL, NULL};
100         /* TODO(sergey): This is gonna to work for until EvaluationContext
101          *               only contains for_render flag. As soon as CoW is
102          *               implemented, this is to be rethinked.
103          */
104         EvaluationContext eval_ctx;
105         DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_RENDER);
106         BKE_displist_make_mball_forRender(&eval_ctx, m_scene, m_object, &disp);
107         BKE_mesh_from_metaball(&disp, tmpmesh);
108         BKE_displist_free(&disp);
109
110         BKE_mesh_texspace_copy_from_object(tmpmesh, m_mesh_ob);
111
112         m_mesh_writer->write();
113
114         BKE_id_free(m_bmain, tmpmesh);
115         m_mesh_ob->data = NULL;
116 }
117
118 bool AbcMBallWriter::isBasisBall(Scene *scene, Object *ob)
119 {
120         Object *basis_ob = BKE_mball_basis_find(scene, ob);
121         return ob == basis_ob;
122 }