| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) Blender Foundation | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): none yet. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * CSG operations.  | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-25 13:57:17 +00:00
										 |  |  | /** \file blender/modifiers/intern/MOD_boolean_util.c
 | 
					
						
							|  |  |  |  *  \ingroup modifiers | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | #include "DNA_material_types.h"
 | 
					
						
							|  |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							|  |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-16 05:46:10 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 22:33:43 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2011-01-07 18:36:47 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-20 13:50:24 +00:00
										 |  |  | #include "BLI_listbase.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-12 22:33:43 +00:00
										 |  |  | #include "BLI_ghash.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_cdderivedmesh.h"
 | 
					
						
							|  |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							|  |  |  | #include "BKE_material.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							|  |  |  | #include "BKE_object.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-12 22:33:43 +00:00
										 |  |  | #include "CSG_BooleanOps.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-13 14:16:36 +00:00
										 |  |  | #include "MOD_boolean_util.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Here's the vertex iterator structure used to walk through | 
					
						
							|  |  |  |  * the blender vertex structure. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	DerivedMesh *dm; | 
					
						
							|  |  |  | 	Object *ob; | 
					
						
							|  |  |  | 	int pos; | 
					
						
							|  |  |  | } VertexIt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Implementations of local vertex iterator functions. | 
					
						
							|  |  |  |  * These describe a blender mesh to the CSG module. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | static void VertexIt_Destruct(CSG_VertexIteratorDescriptor *iterator) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (iterator->it) { | 
					
						
							|  |  |  | 		// deallocate memory for iterator
 | 
					
						
							|  |  |  | 		MEM_freeN(iterator->it); | 
					
						
							|  |  |  | 		iterator->it = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	iterator->Done = NULL; | 
					
						
							|  |  |  | 	iterator->Fill = NULL; | 
					
						
							|  |  |  | 	iterator->Reset = NULL; | 
					
						
							|  |  |  | 	iterator->Step = NULL; | 
					
						
							|  |  |  | 	iterator->num_elements = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }		 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int VertexIt_Done(CSG_IteratorPtr it) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	VertexIt *iterator = (VertexIt *)it; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	return(iterator->pos >= iterator->dm->getNumVerts(iterator->dm)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	VertexIt *iterator = (VertexIt *)it; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	MVert *verts = iterator->dm->getVertArray(iterator->dm); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float global_pos[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* boolean happens in global space, transform both with obmat */ | 
					
						
							|  |  |  | 	mul_v3_m4v3( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	    global_pos, | 
					
						
							|  |  |  | 	    iterator->ob->obmat, | 
					
						
							|  |  |  | 	    verts[iterator->pos].co | 
					
						
							|  |  |  | 	    ); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	vert->position[0] = global_pos[0]; | 
					
						
							|  |  |  | 	vert->position[1] = global_pos[1]; | 
					
						
							|  |  |  | 	vert->position[2] = global_pos[2]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void VertexIt_Step(CSG_IteratorPtr it) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	VertexIt *iterator = (VertexIt *)it; | 
					
						
							| 
									
										
										
										
											2012-05-03 21:35:04 +00:00
										 |  |  | 	iterator->pos++; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | }  | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  | static void VertexIt_Reset(CSG_IteratorPtr it) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	VertexIt *iterator = (VertexIt *)it; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	iterator->pos = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh *dm, Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	VertexIt *it; | 
					
						
							|  |  |  | 	if (output == 0) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// allocate some memory for blender iterator
 | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 	it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt), "Boolean_VIt")); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	if (it == 0) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// assign blender specific variables
 | 
					
						
							|  |  |  | 	it->dm = dm; | 
					
						
							|  |  |  | 	it->ob = ob; // needed for obmat transformations 
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	it->pos = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	// assign iterator function pointers.
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	output->Step = VertexIt_Step; | 
					
						
							|  |  |  | 	output->Fill = VertexIt_Fill; | 
					
						
							|  |  |  | 	output->Done = VertexIt_Done; | 
					
						
							|  |  |  | 	output->Reset = VertexIt_Reset; | 
					
						
							|  |  |  | 	output->num_elements = it->dm->getNumVerts(it->dm); | 
					
						
							|  |  |  | 	output->it = it; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Blender Face iterator | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	DerivedMesh *dm; | 
					
						
							|  |  |  | 	int pos; | 
					
						
							|  |  |  | 	int offset; | 
					
						
							|  |  |  | 	int flip; | 
					
						
							|  |  |  | } FaceIt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | static void FaceIt_Destruct(CSG_FaceIteratorDescriptor *iterator) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	MEM_freeN(iterator->it); | 
					
						
							|  |  |  | 	iterator->Done = NULL; | 
					
						
							|  |  |  | 	iterator->Fill = NULL; | 
					
						
							|  |  |  | 	iterator->Reset = NULL; | 
					
						
							|  |  |  | 	iterator->Step = NULL; | 
					
						
							|  |  |  | 	iterator->num_elements = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int FaceIt_Done(CSG_IteratorPtr it) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// assume CSG_IteratorPtr is of the correct type.
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	FaceIt *iterator = (FaceIt *)it; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	return(iterator->pos >= iterator->dm->getNumTessFaces(iterator->dm)); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// assume CSG_IteratorPtr is of the correct type.
 | 
					
						
							|  |  |  | 	FaceIt *face_it = (FaceIt *)it; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	MFace *mfaces = face_it->dm->getTessFaceArray(face_it->dm); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	MFace *mface = &mfaces[face_it->pos]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* reverse face vertices if necessary */ | 
					
						
							|  |  |  | 	face->vertex_index[1] = mface->v2; | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	if (face_it->flip == 0) { | 
					
						
							|  |  |  | 		face->vertex_index[0] = mface->v1; | 
					
						
							|  |  |  | 		face->vertex_index[2] = mface->v3; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		face->vertex_index[2] = mface->v1; | 
					
						
							|  |  |  | 		face->vertex_index[0] = mface->v3; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (mface->v4) { | 
					
						
							|  |  |  | 		face->vertex_index[3] = mface->v4; | 
					
						
							|  |  |  | 		face->vertex_number = 4; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		face->vertex_number = 3; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	face->orig_face = face_it->offset + face_it->pos; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void FaceIt_Step(CSG_IteratorPtr it) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	FaceIt *face_it = (FaceIt *)it; | 
					
						
							| 
									
										
										
										
											2012-05-03 21:35:04 +00:00
										 |  |  | 	face_it->pos++; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void FaceIt_Reset(CSG_IteratorPtr it) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	FaceIt *face_it = (FaceIt *)it; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	face_it->pos = 0; | 
					
						
							|  |  |  | }	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void FaceIt_Construct( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |         CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset, Object *ob) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	FaceIt *it; | 
					
						
							|  |  |  | 	if (output == 0) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// allocate some memory for blender iterator
 | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 	it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt), "Boolean_FIt")); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	if (it == 0) { | 
					
						
							| 
									
										
										
										
											2012-02-27 10:35:39 +00:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// assign blender specific variables
 | 
					
						
							|  |  |  | 	it->dm = dm; | 
					
						
							|  |  |  | 	it->offset = offset; | 
					
						
							|  |  |  | 	it->pos = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* determine if we will need to reverse order of face vertices */ | 
					
						
							|  |  |  | 	if (ob->size[0] < 0.0f) { | 
					
						
							|  |  |  | 		if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) { | 
					
						
							|  |  |  | 			it->flip = 1; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			it->flip = 1; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			it->flip = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) { | 
					
						
							|  |  |  | 			it->flip = 0; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			it->flip = 0; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 			it->flip = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// assign iterator function pointers.
 | 
					
						
							|  |  |  | 	output->Step = FaceIt_Step; | 
					
						
							|  |  |  | 	output->Fill = FaceIt_Fill; | 
					
						
							|  |  |  | 	output->Done = FaceIt_Done; | 
					
						
							|  |  |  | 	output->Reset = FaceIt_Reset; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	output->num_elements = it->dm->getNumTessFaces(it->dm); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	output->it = it; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Object *AddNewBlenderMesh(Scene *scene, Base *base) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// This little function adds a new mesh object to the blender object list
 | 
					
						
							|  |  |  | 	// It uses ob to duplicate data as this seems to be easier than creating
 | 
					
						
							|  |  |  | 	// a new one. This new oject contains no faces nor vertices.
 | 
					
						
							|  |  |  | 	Mesh *old_me; | 
					
						
							|  |  |  | 	Base *basen; | 
					
						
							|  |  |  | 	Object *ob_new; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// now create a new blender object.
 | 
					
						
							|  |  |  | 	// duplicating all the settings from the previous object
 | 
					
						
							|  |  |  | 	// to the new one.
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ob_new = BKE_object_copy(base->object); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Ok we don't want to use the actual data from the
 | 
					
						
							|  |  |  | 	// last object, the above function incremented the 
 | 
					
						
							|  |  |  | 	// number of users, so decrement it here.
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	old_me = ob_new->data; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	old_me->id.us--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Now create a new base to add into the linked list of 
 | 
					
						
							|  |  |  | 	// vase objects.
 | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	basen = MEM_mallocN(sizeof(Base), "duplibase"); | 
					
						
							|  |  |  | 	*basen = *base; | 
					
						
							|  |  |  | 	BLI_addhead(&scene->base, basen);   /* addhead: anders oneindige lus */ | 
					
						
							|  |  |  | 	basen->object = ob_new; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	basen->flag &= ~SELECT; | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 	// Initialize the mesh data associated with this object.						
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ob_new->data = BKE_mesh_add("Mesh"); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Finally assign the object type.
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ob_new->type = OB_MESH; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ob_new; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void InterpCSGFace( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |         DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr, | 
					
						
							|  |  |  |         float mapmat[][4]) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float obco[3], *co[4], *orig_co[4], w[4][4]; | 
					
						
							|  |  |  | 	MFace *mface, *orig_mface; | 
					
						
							|  |  |  | 	int j; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	mface = CDDM_get_tessface(dm, index); | 
					
						
							|  |  |  | 	orig_mface = orig_dm->getTessFaceArray(orig_dm) + orig_index; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get the vertex coordinates from the original mesh
 | 
					
						
							|  |  |  | 	orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co; | 
					
						
							|  |  |  | 	orig_co[1] = (orig_dm->getVertArray(orig_dm) + orig_mface->v2)->co; | 
					
						
							|  |  |  | 	orig_co[2] = (orig_dm->getVertArray(orig_dm) + orig_mface->v3)->co; | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	orig_co[3] = (orig_mface->v4) ? (orig_dm->getVertArray(orig_dm) + orig_mface->v4)->co : NULL; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// get the vertex coordinates from the new derivedmesh
 | 
					
						
							|  |  |  | 	co[0] = CDDM_get_vert(dm, mface->v1)->co; | 
					
						
							|  |  |  | 	co[1] = CDDM_get_vert(dm, mface->v2)->co; | 
					
						
							|  |  |  | 	co[2] = CDDM_get_vert(dm, mface->v3)->co; | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	co[3] = (nr == 4) ? CDDM_get_vert(dm, mface->v4)->co : NULL; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (j = 0; j < nr; j++) { | 
					
						
							|  |  |  | 		// get coordinate into the space of the original mesh
 | 
					
						
							|  |  |  | 		if (mapmat) | 
					
						
							|  |  |  | 			mul_v3_m4v3(obco, mapmat, co[j]); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			copy_v3_v3(obco, co[j]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		interp_weights_face_v3(w[j], orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	CustomData_interp(&orig_dm->faceData, &dm->faceData, &orig_index, NULL, (float *)w, 1, index); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Iterate over the CSG Output Descriptors and create a new DerivedMesh
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  |  * from them */ | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |         CSG_FaceIteratorDescriptor *face_it, | 
					
						
							|  |  |  |         CSG_VertexIteratorDescriptor *vertex_it, | 
					
						
							|  |  |  |         float parinv[][4], | 
					
						
							|  |  |  |         float mapmat[][4], | 
					
						
							|  |  |  |         Material **mat, | 
					
						
							|  |  |  |         int *totmat, | 
					
						
							|  |  |  |         DerivedMesh *dm1, | 
					
						
							|  |  |  |         Object *ob1, | 
					
						
							|  |  |  |         DerivedMesh *dm2, | 
					
						
							|  |  |  |         Object *ob2) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-03 15:28:53 +00:00
										 |  |  | 	DerivedMesh *result, *orig_dm; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	GHash *material_hash = NULL; | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	Mesh *me1 = (Mesh *)ob1->data; | 
					
						
							|  |  |  | 	Mesh *me2 = (Mesh *)ob2->data; | 
					
						
							| 
									
										
										
										
											2012-01-24 08:43:17 +00:00
										 |  |  | 	int i, *origindex_layer; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// create a new DerivedMesh
 | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements, 0, 0); | 
					
						
							| 
									
										
										
										
											2012-03-20 01:33:24 +00:00
										 |  |  | 	CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH & ~(CD_MASK_NORMAL | CD_MASK_POLYINDEX | CD_MASK_ORIGINDEX), | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	                 CD_DEFAULT, face_it->num_elements); | 
					
						
							| 
									
										
										
										
											2012-03-20 01:33:24 +00:00
										 |  |  | 	CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH & ~(CD_MASK_NORMAL | CD_MASK_POLYINDEX | CD_MASK_ORIGINDEX), | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	                 CD_DEFAULT, face_it->num_elements); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// step through the vertex iterators:
 | 
					
						
							|  |  |  | 	for (i = 0; !vertex_it->Done(vertex_it->it); i++) { | 
					
						
							|  |  |  | 		CSG_IVertex csgvert; | 
					
						
							|  |  |  | 		MVert *mvert = CDDM_get_vert(result, i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// retrieve a csg vertex from the boolean module
 | 
					
						
							|  |  |  | 		vertex_it->Fill(vertex_it->it, &csgvert); | 
					
						
							|  |  |  | 		vertex_it->Step(vertex_it->it); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// we have to map the vertex coordinates back in the coordinate frame
 | 
					
						
							|  |  |  | 		// of the resulting object, since it was computed in world space
 | 
					
						
							|  |  |  | 		mul_v3_m4v3(mvert->co, parinv, csgvert.position); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// a hash table to remap materials to indices
 | 
					
						
							| 
									
										
										
										
											2012-01-27 08:04:03 +00:00
										 |  |  | 	material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "CSG_mat gh"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mat) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		*totmat = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 16:54:21 +00:00
										 |  |  | 	origindex_layer = result->getTessFaceDataArray(result, CD_ORIGINDEX); | 
					
						
							| 
									
										
										
										
											2012-01-24 08:43:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	// step through the face iterators
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	for (i = 0; !face_it->Done(face_it->it); i++) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		Mesh *orig_me; | 
					
						
							|  |  |  | 		Object *orig_ob; | 
					
						
							|  |  |  | 		Material *orig_mat; | 
					
						
							|  |  |  | 		CSG_IFace csgface; | 
					
						
							|  |  |  | 		MFace *mface; | 
					
						
							|  |  |  | 		int orig_index, mat_nr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// retrieve a csg face from the boolean module
 | 
					
						
							|  |  |  | 		face_it->Fill(face_it->it, &csgface); | 
					
						
							|  |  |  | 		face_it->Step(face_it->it); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// find the original mesh and data
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 		orig_ob = (csgface.orig_face < dm1->getNumTessFaces(dm1)) ? ob1 : ob2; | 
					
						
							|  |  |  | 		orig_dm = (csgface.orig_face < dm1->getNumTessFaces(dm1)) ? dm1 : dm2; | 
					
						
							|  |  |  | 		orig_me = (orig_ob == ob1) ? me1 : me2; | 
					
						
							|  |  |  | 		orig_index = (orig_ob == ob1) ? csgface.orig_face : csgface.orig_face - dm1->getNumTessFaces(dm1); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// copy all face layers, including mface
 | 
					
						
							|  |  |  | 		CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// set mface
 | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 		mface = CDDM_get_tessface(result, i); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		mface->v1 = csgface.vertex_index[0]; | 
					
						
							|  |  |  | 		mface->v2 = csgface.vertex_index[1]; | 
					
						
							|  |  |  | 		mface->v3 = csgface.vertex_index[2]; | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 		mface->v4 = (csgface.vertex_number == 4) ? csgface.vertex_index[3] : 0; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// set material, based on lookup in hash table
 | 
					
						
							| 
									
										
										
										
											2012-04-02 22:26:00 +00:00
										 |  |  | 		orig_mat = give_current_material(orig_ob, mface->mat_nr + 1); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (mat && orig_mat) { | 
					
						
							|  |  |  | 			if (!BLI_ghash_haskey(material_hash, orig_mat)) { | 
					
						
							|  |  |  | 				mat[*totmat] = orig_mat; | 
					
						
							|  |  |  | 				mat_nr = mface->mat_nr = (*totmat)++; | 
					
						
							|  |  |  | 				BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr)); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat)); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		else if (orig_mat) { | 
					
						
							|  |  |  | 			if (orig_ob == ob1) { | 
					
						
							| 
									
										
										
										
											2012-01-27 08:04:03 +00:00
										 |  |  | 				// No need to change materian index for faces from left operand
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				// for faces from right operand checn if there's needed material in left operand and if it is,
 | 
					
						
							|  |  |  | 				// use index of that material, otherwise fallback to first material (material with index=0)
 | 
					
						
							|  |  |  | 				if (!BLI_ghash_haskey(material_hash, orig_mat)) { | 
					
						
							|  |  |  | 					int a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					mat_nr = 0; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 					for (a = 0; a < ob1->totcol; a++) { | 
					
						
							| 
									
										
										
										
											2012-05-03 21:35:04 +00:00
										 |  |  | 						if (give_current_material(ob1, a + 1) == orig_mat) { | 
					
						
							| 
									
										
										
										
											2012-01-27 08:04:03 +00:00
										 |  |  | 							mat_nr = a; | 
					
						
							|  |  |  | 							break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					mface->mat_nr = mat_nr; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat)); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		else | 
					
						
							|  |  |  | 			mface->mat_nr = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 		              (orig_me == me2) ? mapmat : NULL); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		test_index_face(mface, &result->faceData, i, csgface.vertex_number); | 
					
						
							| 
									
										
										
										
											2012-01-24 08:43:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		if (origindex_layer && orig_ob == ob2) | 
					
						
							| 
									
										
										
										
											2012-01-24 08:43:17 +00:00
										 |  |  | 			origindex_layer[i] = ORIGINDEX_NONE; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (material_hash) | 
					
						
							|  |  |  | 		BLI_ghash_free(material_hash, NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-06 02:59:28 +00:00
										 |  |  | 	CDDM_calc_edges_tessface(result); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-03 15:28:53 +00:00
										 |  |  | 	CDDM_tessfaces_to_faces(result); /*builds ngon faces from tess (mface) faces*/ | 
					
						
							| 
									
										
										
										
											2012-03-20 00:51:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* this fixes shading issues but SHOULD NOT.
 | 
					
						
							|  |  |  | 	 * TODO, find out why face normals are wrong & flicker - campbell */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 	DM_debug_print(result); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CustomData_free(&result->faceData, result->numTessFaceData); | 
					
						
							|  |  |  | 	result->numTessFaceData = 0; | 
					
						
							|  |  |  | 	DM_ensure_tessface(result); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-23 12:28:18 +00:00
										 |  |  | 	CDDM_calc_normals(result); | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-03 15:28:53 +00:00
										 |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | static void BuildMeshDescriptors( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |         struct DerivedMesh *dm, | 
					
						
							|  |  |  |         struct Object *ob, | 
					
						
							|  |  |  |         int face_offset, | 
					
						
							|  |  |  |         struct CSG_FaceIteratorDescriptor *face_it, | 
					
						
							|  |  |  |         struct CSG_VertexIteratorDescriptor *vertex_it) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 	VertexIt_Construct(vertex_it, dm, ob); | 
					
						
							|  |  |  | 	FaceIt_Construct(face_it, dm, face_offset, ob); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | static void FreeMeshDescriptors( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |         struct CSG_FaceIteratorDescriptor *face_it, | 
					
						
							|  |  |  |         struct CSG_VertexIteratorDescriptor *vertex_it) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	VertexIt_Destruct(vertex_it); | 
					
						
							|  |  |  | 	FaceIt_Destruct(face_it); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-13 14:16:36 +00:00
										 |  |  | static DerivedMesh *NewBooleanDerivedMesh_intern( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |         DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, | 
					
						
							|  |  |  |         int int_op_type, Material **mat, int *totmat) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float inv_mat[4][4]; | 
					
						
							|  |  |  | 	float map_mat[4][4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DerivedMesh *result = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (dm == NULL || dm_select == NULL) return 0; | 
					
						
							| 
									
										
										
										
											2010-07-19 04:44:37 +00:00
										 |  |  | 	if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select)) return 0; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// we map the final object back into ob's local coordinate space. For this
 | 
					
						
							|  |  |  | 	// we need to compute the inverse transform from global to ob (inv_mat),
 | 
					
						
							|  |  |  | 	// and the transform from ob to ob_select for use in interpolation (map_mat)
 | 
					
						
							|  |  |  | 	invert_m4_m4(inv_mat, ob->obmat); | 
					
						
							| 
									
										
										
											
												Math lib: matrix multiplication order fix for two functions that were
inconsistent with similar functions & math notation:
mul_m4_m4m4(R, B, A) => mult_m4_m4m4(R, A, B)
mul_m3_m3m4(R, B, A) => mult_m3_m3m4(R, A, B)
For branch maintainers, it should be relatively simple to fix things manually,
it's also possible run this script after merging to do automatic replacement:
http://www.pasteall.org/27459/python
											
										 
											2011-12-16 19:53:12 +00:00
										 |  |  | 	mult_m4_m4m4(map_mat, inv_mat, ob_select->obmat); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	invert_m4_m4(inv_mat, ob_select->obmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// interface with the boolean module:
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// the idea is, we pass the boolean module verts and faces using the
 | 
					
						
							|  |  |  | 		// provided descriptors. once the boolean operation is performed, we
 | 
					
						
							|  |  |  | 		// get back output descriptors, from which we then build a DerivedMesh
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CSG_VertexIteratorDescriptor vd_1, vd_2; | 
					
						
							|  |  |  | 		CSG_FaceIteratorDescriptor fd_1, fd_2; | 
					
						
							|  |  |  | 		CSG_OperationType op_type; | 
					
						
							|  |  |  | 		CSG_BooleanOperation *bool_op; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// work out the operation they chose and pick the appropriate 
 | 
					
						
							|  |  |  | 		// enum from the csg module.
 | 
					
						
							|  |  |  | 		switch (int_op_type) { | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 			case 1: op_type = e_csg_intersection; break; | 
					
						
							|  |  |  | 			case 2: op_type = e_csg_union; break; | 
					
						
							|  |  |  | 			case 3: op_type = e_csg_difference; break; | 
					
						
							|  |  |  | 			case 4: op_type = e_csg_classify; break; | 
					
						
							|  |  |  | 			default: op_type = e_csg_intersection; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1); | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		BuildMeshDescriptors(dm, ob, dm_select->getNumTessFaces(dm_select), &fd_2, &vd_2); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		bool_op = CSG_NewBooleanFunction(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// perform the operation
 | 
					
						
							|  |  |  | 		if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) { | 
					
						
							|  |  |  | 			CSG_VertexIteratorDescriptor vd_o; | 
					
						
							|  |  |  | 			CSG_FaceIteratorDescriptor fd_o; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			CSG_OutputFaceDescriptor(bool_op, &fd_o); | 
					
						
							|  |  |  | 			CSG_OutputVertexDescriptor(bool_op, &vd_o); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// iterate through results of operation and insert
 | 
					
						
							|  |  |  | 			// into new object
 | 
					
						
							|  |  |  | 			result = ConvertCSGDescriptorsToDerivedMesh( | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 			    &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// free up the memory
 | 
					
						
							|  |  |  | 			CSG_FreeVertexDescriptor(&vd_o); | 
					
						
							|  |  |  | 			CSG_FreeFaceDescriptor(&fd_o); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							| 
									
										
										
										
											2012-01-23 17:43:41 +00:00
										 |  |  | 			printf("Unknown internal error in boolean\n"); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		CSG_FreeBooleanOperation(bool_op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		FreeMeshDescriptors(&fd_1, &vd_1); | 
					
						
							|  |  |  | 		FreeMeshDescriptors(&fd_2, &vd_2); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Mesh *me_new; | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	int a, maxmat, totmat = 0; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	Object *ob_new, *ob, *ob_select; | 
					
						
							|  |  |  | 	Material **mat; | 
					
						
							|  |  |  | 	DerivedMesh *result; | 
					
						
							|  |  |  | 	DerivedMesh *dm_select; | 
					
						
							|  |  |  | 	DerivedMesh *dm; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ob = base->object; | 
					
						
							|  |  |  | 	ob_select = base_select->object; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); | 
					
						
							|  |  |  | 	dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ??
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	maxmat = ob->totcol + ob_select->totcol; | 
					
						
							| 
									
										
										
										
											2012-05-03 21:35:04 +00:00
										 |  |  | 	mat = (Material **)MEM_mallocN(sizeof(Material *) * maxmat, "NewBooleanMeshMat"); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	/* put some checks in for nice user feedback */ | 
					
						
							| 
									
										
										
										
											2012-03-06 18:40:15 +00:00
										 |  |  | 	if (dm == NULL || dm_select == NULL) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select)) { | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 		MEM_freeN(mat); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	result = NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (result == NULL) { | 
					
						
							|  |  |  | 		MEM_freeN(mat); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* create a new blender mesh object - using 'base' as  a template */ | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  | 	ob_new = AddNewBlenderMesh(scene, base_select); | 
					
						
							|  |  |  | 	me_new = ob_new->data; | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 05:20:18 +00:00
										 |  |  | 	DM_to_mesh(result, me_new, ob_new); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 	result->release(result); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dm->release(dm); | 
					
						
							|  |  |  | 	dm_select->release(dm_select); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* add materials to object */ | 
					
						
							|  |  |  | 	for (a = 0; a < totmat; a++) | 
					
						
							| 
									
										
										
										
											2012-05-03 21:35:04 +00:00
										 |  |  | 		assign_material(ob_new, mat[a], a + 1); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN(mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* update dag */ | 
					
						
							| 
									
										
										
										
											2010-12-05 18:59:23 +00:00
										 |  |  | 	DAG_id_tag_update(&ob_new->id, OB_RECALC_DATA); | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, | 
					
						
							| 
									
										
										
										
											2012-05-06 13:38:33 +00:00
										 |  |  |                                    int int_op_type) | 
					
						
							| 
									
										
										
										
											2010-04-11 22:12:30 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL); | 
					
						
							|  |  |  | } |