Fix T38962: Boolean modifier crashes when only right operand has UV layer
[blender.git] / source / blender / modifiers / intern / MOD_boolean_util.c
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  * The Original Code is Copyright (C) Blender Foundation
19  * All rights reserved.
20  *
21  * Contributor(s): Sergey Sharybin.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/modifiers/intern/MOD_boolean_util.c
27  *  \ingroup modifiers
28  */
29
30 #include "DNA_material_types.h"
31 #include "DNA_meshdata_types.h"
32 #include "DNA_modifier_types.h"
33 #include "DNA_object_types.h"
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BLI_utildefines.h"
38 #include "BLI_alloca.h"
39 #include "BLI_ghash.h"
40 #include "BLI_math.h"
41 #include "BLI_polyfill2d.h"
42
43 #include "BKE_cdderivedmesh.h"
44 #include "BKE_material.h"
45
46 #include "MOD_boolean_util.h"
47
48 #include "carve-capi.h"
49
50 /* Adopted from BM_loop_interp_from_face(),
51  *
52  * Transform matrix is used in cases when target coordinate needs
53  * to be converted to source space (namely when interpolating
54  * boolean result loops from second operand).
55  *
56  * TODO(sergey): Consider making it a generic function in DerivedMesh.c.
57  */
58 static void DM_loop_interp_from_poly(DerivedMesh *source_dm,
59                                      MVert *source_mverts,
60                                      MLoop *source_mloops,
61                                      MPoly *source_poly,
62                                      DerivedMesh *target_dm,
63                                      MVert *target_mverts,
64                                      MLoop *target_mloop,
65                                      float transform[4][4],
66                                      int target_loop_index)
67 {
68         float (*cos_3d)[3] = BLI_array_alloca(cos_3d, source_poly->totloop);
69         int *source_indices = BLI_array_alloca(source_indices, source_poly->totloop);
70         float *weights = BLI_array_alloca(weights, source_poly->totloop);
71         int i;
72         int target_vert_index = target_mloop[target_loop_index].v;
73         float coord[3];
74
75         for (i = 0; i < source_poly->totloop; ++i) {
76                 MLoop *mloop = &source_mloops[source_poly->loopstart + i];
77                 source_indices[i] = source_poly->loopstart + i;
78                 copy_v3_v3(cos_3d[i], source_mverts[mloop->v].co);
79         }
80
81         if (transform) {
82                 mul_v3_m4v3(coord, transform, target_mverts[target_vert_index].co);
83         }
84         else {
85                 copy_v3_v3(coord, target_mverts[target_vert_index].co);
86         }
87
88         interp_weights_poly_v3(weights, cos_3d, source_poly->totloop, coord);
89
90         DM_interp_loop_data(source_dm, target_dm, source_indices, weights,
91                             source_poly->totloop, target_loop_index);
92 }
93
94 /* **** Importer from derived mesh to Carve ****  */
95
96 typedef struct ImportMeshData {
97         DerivedMesh *dm;
98         float obmat[4][4];
99         MVert *mvert;
100         MEdge *medge;
101         MLoop *mloop;
102         MPoly *mpoly;
103 } ImportMeshData;
104
105 /* Get number of vertices. */
106 static int importer_GetNumVerts(ImportMeshData *import_data)
107 {
108         DerivedMesh *dm = import_data->dm;
109         return dm->getNumVerts(dm);
110 }
111
112 /* Get number of edges. */
113 static int importer_GetNumEdges(ImportMeshData *import_data)
114 {
115         DerivedMesh *dm = import_data->dm;
116         return dm->getNumEdges(dm);
117 }
118
119 /* Get number of loops. */
120 static int importer_GetNumLoops(ImportMeshData *import_data)
121 {
122         DerivedMesh *dm = import_data->dm;
123         return dm->getNumLoops(dm);
124 }
125
126 /* Get number of polys. */
127 static int importer_GetNumPolys(ImportMeshData *import_data)
128 {
129         DerivedMesh *dm = import_data->dm;
130         return dm->getNumPolys(dm);
131 }
132
133 /* Get 3D coordinate of vertex with given index. */
134 static void importer_GetVertCoord(ImportMeshData *import_data, int vert_index, float coord[3])
135 {
136         MVert *mvert = import_data->mvert;
137
138         BLI_assert(vert_index >= 0 && vert_index < import_data->dm->getNumVerts(import_data->dm));
139
140         mul_v3_m4v3(coord, import_data->obmat, mvert[vert_index].co);
141 }
142
143 /* Get index of vertices which are adjucent to edge specified by it's index. */
144 static void importer_GetEdgeVerts(ImportMeshData *import_data, int edge_index, int *v1, int *v2)
145 {
146         MEdge *medge = &import_data->medge[edge_index];
147
148         BLI_assert(edge_index >= 0 && edge_index < import_data->dm->getNumEdges(import_data->dm));
149
150         *v1 = medge->v1;
151         *v2 = medge->v2;
152 }
153
154 /* Get number of adjucent vertices to the poly specified by it's index. */
155 static int importer_GetPolyNumVerts(ImportMeshData *import_data, int poly_index)
156 {
157         MPoly *mpoly = import_data->mpoly;
158
159         BLI_assert(poly_index >= 0 && poly_index < import_data->dm->getNumPolys(import_data->dm));
160
161         return mpoly[poly_index].totloop;
162 }
163
164 /* Get list of adjucent vertices to the poly specified by it's index. */
165 static void importer_GetPolyVerts(ImportMeshData *import_data, int poly_index, int *verts)
166 {
167         MPoly *mpoly = &import_data->mpoly[poly_index];
168         MLoop *mloop = import_data->mloop + mpoly->loopstart;
169         int i;
170         BLI_assert(poly_index >= 0 && poly_index < import_data->dm->getNumPolys(import_data->dm));
171         for (i = 0; i < mpoly->totloop; i++, mloop++) {
172                 verts[i] = mloop->v;
173         }
174 }
175
176 // Triangulate 2D polygon.
177 #if 0
178 static int importer_triangulate2DPoly(ImportMeshData *UNUSED(import_data),
179                                       const float (*vertices)[2], int num_vertices,
180                                       unsigned int (*triangles)[3])
181 {
182         // TODO(sergey): Currently import_data is unused but in the future we could
183         // put memory arena there which will reduce amount of allocations happening
184         // over the triangulation period.
185         //
186         // However that's not so much straighforward to do it right now because we
187         // also are tu consider threaded import/export.
188
189         BLI_assert(num_vertices > 3);
190
191         BLI_polyfill_calc(vertices, num_vertices, triangles);
192
193         return num_vertices - 2;
194 }
195 #endif
196
197 static CarveMeshImporter MeshImporter = {
198         importer_GetNumVerts,
199         importer_GetNumEdges,
200         importer_GetNumLoops,
201         importer_GetNumPolys,
202         importer_GetVertCoord,
203         importer_GetEdgeVerts,
204         importer_GetPolyNumVerts,
205         importer_GetPolyVerts,
206
207         /* TODO(sergey): We don't use BLI_polyfill_calc() because it tends
208          * to generate degenerated geometry which is fatal for booleans.
209          *
210          * For now we stick to Carve's triangulation.
211          */
212         NULL, /* importer_triangulate2DPoly */
213 };
214
215 /* **** Exporter from Carve to derived mesh ****  */
216
217 typedef struct ExportMeshData {
218         DerivedMesh *dm;
219         float obimat[4][4];
220         MVert *mvert;
221         MEdge *medge;
222         MLoop *mloop;
223         MPoly *mpoly;
224         int *vert_origindex;
225         int *edge_origindex;
226         int *poly_origindex;
227         int *loop_origindex;
228
229         /* Objects and derived meshes of left and right operands.
230          * Used for custom data merge and interpolation.
231          */
232         Object *ob_left;
233         Object *ob_right;
234         DerivedMesh *dm_left;
235         DerivedMesh *dm_right;
236         MVert *mvert_left;
237         MLoop *mloop_left;
238         MPoly *mpoly_left;
239         MVert *mvert_right;
240         MLoop *mloop_right;
241         MPoly *mpoly_right;
242
243         float left_to_right_mat[4][4];
244
245         /* Hash to map materials from right object to result. */
246         GHash *material_hash;
247 } ExportMeshData;
248
249 BLI_INLINE Object *which_object(ExportMeshData *export_data, int which_mesh)
250 {
251         Object *object = NULL;
252         switch (which_mesh) {
253                 case CARVE_MESH_LEFT:
254                         object = export_data->ob_left;
255                         break;
256                 case CARVE_MESH_RIGHT:
257                         object = export_data->ob_right;
258                         break;
259         }
260         return object;
261 }
262
263 BLI_INLINE DerivedMesh *which_dm(ExportMeshData *export_data, int which_mesh)
264 {
265         DerivedMesh *dm = NULL;
266         switch (which_mesh) {
267                 case CARVE_MESH_LEFT:
268                         dm = export_data->dm_left;
269                         break;
270                 case CARVE_MESH_RIGHT:
271                         dm = export_data->dm_right;
272                         break;
273         }
274         return dm;
275 }
276
277 BLI_INLINE MVert *which_mvert(ExportMeshData *export_data, int which_mesh)
278 {
279         MVert *mvert = NULL;
280         switch (which_mesh) {
281                 case CARVE_MESH_LEFT:
282                         mvert = export_data->mvert_left;
283                         break;
284                 case CARVE_MESH_RIGHT:
285                         mvert = export_data->mvert_right;
286                         break;
287         }
288         return mvert;
289 }
290
291 BLI_INLINE MLoop *which_mloop(ExportMeshData *export_data, int which_mesh)
292 {
293         MLoop *mloop = NULL;
294         switch (which_mesh) {
295                 case CARVE_MESH_LEFT:
296                         mloop = export_data->mloop_left;
297                         break;
298                 case CARVE_MESH_RIGHT:
299                         mloop = export_data->mloop_right;
300                         break;
301         }
302         return mloop;
303 }
304
305 BLI_INLINE MPoly *which_mpoly(ExportMeshData *export_data, int which_mesh)
306 {
307         MPoly *mpoly = NULL;
308         switch (which_mesh) {
309                 case CARVE_MESH_LEFT:
310                         mpoly = export_data->mpoly_left;
311                         break;
312                 case CARVE_MESH_RIGHT:
313                         mpoly = export_data->mpoly_right;
314                         break;
315         }
316         return mpoly;
317 }
318
319 static void allocate_custom_layers(CustomData *data, int type, int num_elements, int num_layers)
320 {
321         int i;
322         for (i = 0; i < num_layers; i++) {
323                 CustomData_add_layer(data, type, CD_DEFAULT, NULL, num_elements);
324         }
325 }
326
327 /* Create new external mesh */
328 static void exporter_InitGeomArrays(ExportMeshData *export_data,
329                                     int num_verts, int num_edges,
330                                     int num_loops, int num_polys)
331 {
332         DerivedMesh *dm = CDDM_new(num_verts, num_edges, 0,
333                                    num_loops, num_polys);
334         DerivedMesh *dm_left = export_data->dm_left,
335                     *dm_right = export_data->dm_right;
336
337         /* Mask for custom data layers to be merhed from operands. */
338         CustomDataMask merge_mask = CD_MASK_DERIVEDMESH & ~CD_MASK_ORIGINDEX;
339
340         export_data->dm = dm;
341         export_data->mvert = dm->getVertArray(dm);
342         export_data->medge = dm->getEdgeArray(dm);
343         export_data->mloop = dm->getLoopArray(dm);
344         export_data->mpoly = dm->getPolyArray(dm);
345
346         /* Allocate layers for UV layers and vertex colors.
347          * Without this interpolation of those data will not happen.
348          */
349         allocate_custom_layers(&dm->loopData, CD_MLOOPCOL, num_loops,
350                                CustomData_number_of_layers(&dm_left->loopData, CD_MLOOPCOL));
351         allocate_custom_layers(&dm->loopData, CD_MLOOPUV, num_loops,
352                                CustomData_number_of_layers(&dm_left->loopData, CD_MLOOPUV));
353
354         allocate_custom_layers(&dm->loopData, CD_MLOOPCOL, num_loops,
355                                CustomData_number_of_layers(&dm_right->loopData, CD_MLOOPCOL));
356         allocate_custom_layers(&dm->loopData, CD_MLOOPUV, num_loops,
357                                CustomData_number_of_layers(&dm_right->loopData, CD_MLOOPUV));
358
359         /* Merge custom data layers from operands.
360          *
361          * Will only create custom data layers for all the layers which appears in
362          * the operand. Data for those layers will not be allocated or initialized.
363          */
364         CustomData_merge(&dm_left->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
365         CustomData_merge(&dm_right->polyData, &dm->polyData, merge_mask, CD_DEFAULT, num_polys);
366
367         export_data->vert_origindex = dm->getVertDataArray(dm, CD_ORIGINDEX);
368         export_data->edge_origindex = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
369         export_data->poly_origindex = dm->getPolyDataArray(dm, CD_ORIGINDEX);
370         export_data->loop_origindex = dm->getLoopDataArray(dm, CD_ORIGINDEX);
371 }
372
373 /* Set coordinate of vertex with given index. */
374 static void exporter_SetVert(ExportMeshData *export_data,
375                              int vert_index, float coord[3],
376                              int which_orig_mesh, int orig_vert_index)
377 {
378         DerivedMesh *dm = export_data->dm;
379         DerivedMesh *dm_orig;
380         MVert *mvert = export_data->mvert;
381
382         BLI_assert(vert_index >= 0 && vert_index <= dm->getNumVerts(dm));
383
384         dm_orig = which_dm(export_data, which_orig_mesh);
385         if (dm_orig) {
386                 BLI_assert(orig_vert_index >= 0 && orig_vert_index < dm_orig->getNumVerts(dm_orig));
387                 CustomData_copy_data(&dm_orig->vertData, &dm->vertData, orig_vert_index, vert_index, 1);
388         }
389
390         /* Set original index of the vertex. */
391         if (export_data->vert_origindex) {
392                 if (which_orig_mesh == CARVE_MESH_LEFT) {
393                         export_data->vert_origindex[vert_index] = orig_vert_index;
394                 }
395                 else {
396                         export_data->vert_origindex[vert_index] = ORIGINDEX_NONE;
397                 }
398         }
399
400         mul_v3_m4v3(mvert[vert_index].co, export_data->obimat, coord);
401 }
402
403 /* Set vertices which are adjucent to the edge specified by it's index. */
404 static void exporter_SetEdge(ExportMeshData *export_data,
405                              int edge_index, int v1, int v2,
406                              int which_orig_mesh, int orig_edge_index)
407 {
408         DerivedMesh *dm = export_data->dm;
409         MEdge *medge = &export_data->medge[edge_index];
410         DerivedMesh *dm_orig;
411
412         BLI_assert(edge_index >= 0 && edge_index < dm->getNumEdges(dm));
413         BLI_assert(v1 >= 0 && v1 < dm->getNumVerts(dm));
414         BLI_assert(v2 >= 0 && v2 < dm->getNumVerts(dm));
415
416         dm_orig = which_dm(export_data, which_orig_mesh);
417         if (dm_orig) {
418                 BLI_assert(orig_edge_index >= 0 && orig_edge_index < dm_orig->getNumEdges(dm_orig));
419
420                 /* Copy all edge layers, including mpoly. */
421                 CustomData_copy_data(&dm_orig->edgeData, &dm->edgeData, orig_edge_index, edge_index, 1);
422         }
423
424         /* Set original index of the edge. */
425         if (export_data->edge_origindex) {
426                 if (which_orig_mesh == CARVE_MESH_LEFT) {
427                         export_data->edge_origindex[edge_index] = orig_edge_index;
428                 }
429                 else {
430                         export_data->edge_origindex[edge_index] = ORIGINDEX_NONE;
431                 }
432         }
433
434         medge->v1 = v1;
435         medge->v2 = v2;
436
437         medge->flag |= ME_EDGEDRAW | ME_EDGERENDER;
438 }
439
440 static void setMPolyMaterial(ExportMeshData *export_data,
441                              MPoly *mpoly,
442                              int which_orig_mesh)
443 {
444         Object *orig_object;
445         GHash *material_hash;
446         Material *orig_mat;
447
448         if (which_orig_mesh == CARVE_MESH_LEFT) {
449                 /* No need to change materian index for faces from left operand */
450                 return;
451         }
452
453         material_hash = export_data->material_hash;
454         orig_object = which_object(export_data, which_orig_mesh);
455
456         /* Set material, based on lookup in hash table. */
457         orig_mat = give_current_material(orig_object, mpoly->mat_nr + 1);
458
459         if (orig_mat) {
460                 /* For faces from right operand check if there's requested material
461                  * in the left operand. And if it is, use index of that material,
462                  * otherwise fallback to first material (material with index=0).
463                  */
464                 if (!BLI_ghash_haskey(material_hash, orig_mat)) {
465                         int a, mat_nr;
466
467                         mat_nr = 0;
468                         for (a = 0; a < export_data->ob_left->totcol; a++) {
469                                 if (give_current_material(export_data->ob_left, a + 1) == orig_mat) {
470                                         mat_nr = a;
471                                         break;
472                                 }
473                         }
474
475                         BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
476
477                         mpoly->mat_nr = mat_nr;
478                 }
479                 else
480                         mpoly->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
481         }
482         else {
483                 mpoly->mat_nr = 0;
484         }
485 }
486
487 /* Set list of adjucent loops to the poly specified by it's index. */
488 static void exporter_SetPoly(ExportMeshData *export_data,
489                              int poly_index, int start_loop, int num_loops,
490                              int which_orig_mesh, int orig_poly_index)
491 {
492         DerivedMesh *dm = export_data->dm;
493         MPoly *mpoly = &export_data->mpoly[poly_index];
494         DerivedMesh *dm_orig;
495         int i;
496
497         /* Poly is always to be either from left or right operand. */
498         dm_orig = which_dm(export_data, which_orig_mesh);
499
500         BLI_assert(poly_index >= 0 && poly_index < dm->getNumPolys(dm));
501         BLI_assert(start_loop >= 0 && start_loop <= dm->getNumLoops(dm) - num_loops);
502         BLI_assert(num_loops >= 3);
503         BLI_assert(dm_orig != NULL);
504         BLI_assert(orig_poly_index >= 0 && orig_poly_index < dm_orig->getNumPolys(dm_orig));
505
506         /* Copy all poly layers, including mpoly. */
507         CustomData_copy_data(&dm_orig->polyData, &dm->polyData, orig_poly_index, poly_index, 1);
508
509         /* Set material of the curren poly.
510          * This would re-map materials from right operand to materials from the
511          * left one as well.
512          */
513         setMPolyMaterial(export_data, mpoly, which_orig_mesh);
514
515         /* Set original index of the poly. */
516         if (export_data->poly_origindex) {
517                 if (which_orig_mesh == CARVE_MESH_LEFT) {
518                         export_data->poly_origindex[poly_index] = orig_poly_index;
519                 }
520                 else {
521                         export_data->poly_origindex[poly_index] = ORIGINDEX_NONE;
522                 }
523         }
524
525         /* Set poly data itself. */
526         mpoly->loopstart = start_loop;
527         mpoly->totloop = num_loops;
528
529         /* Interpolate data for poly loops. */
530         {
531                 MVert *source_mverts = which_mvert(export_data, which_orig_mesh);
532                 MLoop *source_mloops = which_mloop(export_data, which_orig_mesh);
533                 MPoly *source_mpolys = which_mpoly(export_data, which_orig_mesh);
534                 MPoly *source_poly = &source_mpolys[orig_poly_index];
535                 MVert *target_mverts = export_data->mvert;
536                 MLoop *target_mloops = export_data->mloop;
537                 float (*transform)[4] = NULL;
538
539                 if (which_orig_mesh == CARVE_MESH_RIGHT) {
540                         transform = export_data->left_to_right_mat;
541                 }
542
543                 for (i = 0; i < mpoly->totloop; i++) {
544                         DM_loop_interp_from_poly(dm_orig,
545                                                  source_mverts,
546                                                  source_mloops,
547                                                  source_poly,
548                                                  dm,
549                                                  target_mverts,
550                                                  target_mloops,
551                                                  transform,
552                                                  i + mpoly->loopstart);
553                 }
554         }
555 }
556
557 /* Set list vertex and edge which are adjucent to loop with given index. */
558 static void exporter_SetLoop(ExportMeshData *export_data,
559                              int loop_index, int vertex, int edge,
560                              int which_orig_mesh, int orig_loop_index)
561 {
562         DerivedMesh *dm = export_data->dm;
563         MLoop *mloop = &export_data->mloop[loop_index];
564         DerivedMesh *dm_orig;
565
566         BLI_assert(loop_index >= 0 && loop_index < dm->getNumLoops(dm));
567         BLI_assert(vertex >= 0 && vertex < dm->getNumVerts(dm));
568         BLI_assert(edge >= 0 && vertex < dm->getNumEdges(dm));
569
570         dm_orig = which_dm(export_data, which_orig_mesh);
571         if (dm_orig) {
572                 BLI_assert(orig_loop_index >= 0 && orig_loop_index < dm_orig->getNumLoops(dm_orig));
573
574                 /* Copy all loop layers, including mpoly. */
575                 CustomData_copy_data(&dm_orig->loopData, &dm->loopData, orig_loop_index, loop_index, 1);
576         }
577
578         /* Set original index of the loop. */
579         if (export_data->loop_origindex) {
580                 if (which_orig_mesh == CARVE_MESH_LEFT) {
581                         export_data->loop_origindex[loop_index] = orig_loop_index;
582                 }
583                 else {
584                         export_data->loop_origindex[loop_index] = ORIGINDEX_NONE;
585                 }
586         }
587
588         mloop->v = vertex;
589         mloop->e = edge;
590 }
591
592 /* Edge index from a loop index for a given original mesh. */
593 static int exporter_MapLoopToEdge(ExportMeshData *export_data,
594                                   int which_mesh, int loop_index)
595 {
596         DerivedMesh *dm = which_dm(export_data, which_mesh);
597         MLoop *mloop = which_mloop(export_data, which_mesh);
598
599         (void) dm;  /* Unused in release builds. */
600
601         BLI_assert(dm != NULL);
602         BLI_assert(loop_index >= 0 && loop_index < dm->getNumLoops(dm));
603
604         return mloop[loop_index].e;
605 }
606
607 static CarveMeshExporter MeshExporter = {
608         exporter_InitGeomArrays,
609         exporter_SetVert,
610         exporter_SetEdge,
611         exporter_SetPoly,
612         exporter_SetLoop,
613         exporter_MapLoopToEdge
614 };
615
616 static int operation_from_optype(int int_op_type)
617 {
618         int operation;
619
620         switch (int_op_type) {
621                 case 1:
622                         operation = CARVE_OP_INTERSECTION;
623                         break;
624                 case 2:
625                         operation = CARVE_OP_UNION;
626                         break;
627                 case 3:
628                         operation = CARVE_OP_A_MINUS_B;
629                         break;
630                 default:
631                         BLI_assert(!"Should not happen");
632                         operation = -1;
633                         break;
634         }
635
636         return operation;
637 }
638
639 static void prepare_import_data(Object *object, DerivedMesh *dm, ImportMeshData *import_data)
640 {
641         import_data->dm = dm;
642         copy_m4_m4(import_data->obmat, object->obmat);
643         import_data->mvert = dm->getVertArray(dm);
644         import_data->medge = dm->getEdgeArray(dm);
645         import_data->mloop = dm->getLoopArray(dm);
646         import_data->mpoly = dm->getPolyArray(dm);
647 }
648
649 static struct CarveMeshDescr *carve_mesh_from_dm(Object *object, DerivedMesh *dm)
650 {
651         ImportMeshData import_data;
652         prepare_import_data(object, dm, &import_data);
653         return carve_addMesh(&import_data, &MeshImporter);
654 }
655
656 static void prepare_export_data(Object *object_left, DerivedMesh *dm_left,
657                                 Object *object_right, DerivedMesh *dm_right,
658                                 ExportMeshData *export_data)
659 {
660         float object_right_imat[4][4];
661
662         invert_m4_m4(export_data->obimat, object_left->obmat);
663
664         export_data->ob_left = object_left;
665         export_data->ob_right = object_right;
666
667         export_data->dm_left = dm_left;
668         export_data->dm_right = dm_right;
669
670         export_data->mvert_left = dm_left->getVertArray(dm_left);
671         export_data->mloop_left = dm_left->getLoopArray(dm_left);
672         export_data->mpoly_left = dm_left->getPolyArray(dm_left);
673         export_data->mvert_right = dm_right->getVertArray(dm_right);
674         export_data->mloop_right = dm_right->getLoopArray(dm_right);
675         export_data->mpoly_right = dm_right->getPolyArray(dm_right);
676
677         export_data->material_hash = BLI_ghash_ptr_new("CSG_mat gh");
678
679         /* Matrix to convert coord from left object's loca; space to
680          * right object's local space.
681          */
682         invert_m4_m4(object_right_imat, object_right->obmat);
683         mul_m4_m4m4(export_data->left_to_right_mat, object_left->obmat,
684                     object_right_imat);
685 }
686
687 DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob,
688                                    DerivedMesh *dm_select, struct Object *ob_select,
689                                    int int_op_type)
690 {
691
692         struct CarveMeshDescr *left, *right, *output = NULL;
693         DerivedMesh *output_dm = NULL;
694         int operation;
695         bool result;
696
697         if (dm == NULL || dm_select == NULL) {
698                 return NULL;
699         }
700
701         operation = operation_from_optype(int_op_type);
702         if (operation == -1) {
703                 return NULL;
704         }
705
706         left = carve_mesh_from_dm(ob_select, dm_select);
707         right = carve_mesh_from_dm(ob, dm);
708
709         result = carve_performBooleanOperation(left, right, operation, &output);
710
711         carve_deleteMesh(left);
712         carve_deleteMesh(right);
713
714         if (result) {
715                 ExportMeshData export_data;
716
717                 prepare_export_data(ob_select, dm_select, ob, dm, &export_data);
718
719                 carve_exportMesh(output, &MeshExporter, &export_data);
720                 output_dm = export_data.dm;
721
722                 /* Free memory used by export mesh. */
723                 BLI_ghash_free(export_data.material_hash, NULL, NULL);
724
725                 output_dm->dirty |= DM_DIRTY_NORMALS;
726                 carve_deleteMesh(output);
727         }
728
729         return output_dm;
730 }