Initial revision
[blender.git] / intern / bsp / intern / CSG_BooleanOps.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 /**
33
34  * Implementation of external api for CSG part of BSP lib interface.
35  */
36
37 #include "../extern/CSG_BooleanOps.h"
38 #include "BSP_CSGMesh_CFIterator.h"
39 #include "BSP_CSGMeshBuilder.h"
40 #include "BSP_CSGHelper.h"
41 #include "BSP_CSGUserData.h"
42 #include "MEM_RefCountPtr.h"
43
44 struct BSP_MeshInfo {
45         MEM_RefCountPtr<BSP_CSGMesh> output_mesh;
46         CSG_MeshPropertyDescriptor obA_descriptor;
47         CSG_MeshPropertyDescriptor obB_descriptor;
48         CSG_MeshPropertyDescriptor output_descriptor;
49 };
50
51 using namespace std;
52         
53         CSG_BooleanOperation * 
54 CSG_NewBooleanFunction(
55         void
56 ){
57         BSP_MeshInfo * mesh_info = new BSP_MeshInfo;
58         CSG_BooleanOperation * output = new CSG_BooleanOperation;
59
60         if (mesh_info==NULL || output==NULL) return NULL;
61
62         mesh_info->output_mesh = NULL;
63         output->CSG_info = mesh_info;
64
65         return output;
66 }
67         
68         CSG_MeshPropertyDescriptor
69 CSG_DescibeOperands(
70         CSG_BooleanOperation * operation,
71         CSG_MeshPropertyDescriptor operandA_desciption,
72         CSG_MeshPropertyDescriptor operandB_desciption
73 ){
74         BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
75
76         mesh_info->obA_descriptor = operandA_desciption;
77         mesh_info->obB_descriptor = operandB_desciption;
78
79         if (
80                 (operandA_desciption.user_data_size == operandB_desciption.user_data_size) &&
81                 (operandA_desciption.user_face_vertex_data_size == operandB_desciption.user_face_vertex_data_size)
82         ) {
83                 // Then both operands have the same sets of data we can cope with this!
84                 mesh_info->output_descriptor.user_data_size = operandA_desciption.user_data_size;
85                 mesh_info->output_descriptor.user_face_vertex_data_size = operandA_desciption.user_face_vertex_data_size;
86         } else {
87                 // There maybe some common subset of data we can seperate out but for now we just use the 
88                 // default 
89                 mesh_info->output_descriptor.user_data_size = 0;
90                 mesh_info->output_descriptor.user_face_vertex_data_size = 0;
91         }
92         return mesh_info->output_descriptor;
93 }
94
95         int
96 CSG_PerformBooleanOperation(
97         CSG_BooleanOperation * operation,
98         CSG_OperationType op_type,
99         CSG_FaceIteratorDescriptor obAFaces,
100         CSG_VertexIteratorDescriptor obAVertices,
101         CSG_FaceIteratorDescriptor obBFaces,
102         CSG_VertexIteratorDescriptor obBVertices,
103         CSG_InterpolateUserFaceVertexDataFunc interp_func
104 ){
105         
106         if (operation == NULL) return 0;
107         BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
108         if (mesh_info == NULL) return 0;
109
110         bool success = 0;
111
112         obAFaces.Reset(obAFaces.it);
113         obBFaces.Reset(obBFaces.it);
114         obAVertices.Reset(obAVertices.it);
115         obBVertices.Reset(obBVertices.it);
116
117
118         try {
119                 // Build the individual meshes
120                 
121                 MEM_SmartPtr<BSP_CSGMesh> obA = 
122                         BSP_CSGMeshBuilder::NewMesh(mesh_info->obA_descriptor,obAFaces,obAVertices);
123
124                 MEM_SmartPtr<BSP_CSGMesh> obB = 
125                         BSP_CSGMeshBuilder::NewMesh(mesh_info->obB_descriptor,obBFaces,obBVertices);
126
127                 // create an empty vertex array for the output mesh 
128                 MEM_SmartPtr<vector<BSP_MVertex> > output_verts(new vector<BSP_MVertex>);
129                 // and some user data arrays matching the output descriptor
130
131                 MEM_SmartPtr<BSP_CSGUserData> output_f_data = new BSP_CSGUserData(
132                         mesh_info->output_descriptor.user_data_size
133                 );
134                 MEM_SmartPtr<BSP_CSGUserData> output_fv_data = new BSP_CSGUserData(
135                         mesh_info->output_descriptor.user_face_vertex_data_size
136                 );
137
138                 // create the output mesh!
139                 mesh_info->output_mesh = BSP_CSGMesh::New();
140
141                 if (
142                         obA == NULL ||
143                         obB == NULL ||
144                         output_verts == NULL ||
145                         mesh_info->output_mesh == NULL ||
146                         output_f_data == NULL ||
147                         output_fv_data == NULL
148                 ) {
149                         return 0;
150                 }
151
152                 mesh_info->output_mesh->SetVertices(output_verts);
153                 mesh_info->output_mesh->SetFaceData(output_f_data);
154                 mesh_info->output_mesh->SetFaceVertexData(output_fv_data);
155
156                 BSP_CSGHelper helper;
157                 // translate enums!
158
159                 switch(op_type) {
160                         case e_csg_union : 
161                         case e_csg_classify :
162                                 success = helper.ComputeOp(obA,obB,e_intern_csg_union,
163                                         mesh_info->output_mesh.Ref(),interp_func
164                                 );
165                                 break;
166                         case e_csg_intersection :
167                                 success = helper.ComputeOp(obA,obB,e_intern_csg_intersection,
168                                         mesh_info->output_mesh.Ref(),interp_func
169                                 );
170                                 break;
171                         case e_csg_difference :
172                                 success = helper.ComputeOp(obA,obB,e_intern_csg_difference,
173                                         mesh_info->output_mesh.Ref(),interp_func
174                                 );
175                                 break;
176                         default :
177                                 success = 0;
178                 }
179         }
180         catch(...) {
181                 return 0;
182         }
183
184         return success;
185 }
186
187         int
188 CSG_OutputFaceDescriptor(
189         CSG_BooleanOperation * operation,
190         CSG_FaceIteratorDescriptor * output
191 ){
192         if (operation == NULL) return 0;
193         BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
194
195         if (mesh_info == NULL) return 0;
196         if (mesh_info->output_mesh == NULL) return 0;
197
198         BSP_CSGMesh_FaceIt_Construct(mesh_info->output_mesh,output);
199         return 1;
200 }
201
202
203         int
204 CSG_OutputVertexDescriptor(
205         CSG_BooleanOperation * operation,
206         CSG_VertexIteratorDescriptor *output
207 ){
208         if (operation == NULL) return 0;
209         BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
210
211         if (mesh_info == NULL) return 0;
212         if (mesh_info->output_mesh == NULL) return 0;
213
214         BSP_CSGMeshVertexIt_Construct(mesh_info->output_mesh,output);
215         return 1;
216 }
217
218         void
219 CSG_FreeVertexDescriptor(
220         CSG_VertexIteratorDescriptor * v_descriptor
221 ){      
222         BSP_CSGMesh_VertexIt_Destruct(v_descriptor);
223 }       
224
225
226         void
227 CSG_FreeFaceDescriptor(
228         CSG_FaceIteratorDescriptor * f_descriptor
229 ){
230         BSP_CSGMesh_FaceIt_Destruct(f_descriptor);
231 }
232
233
234         void
235 CSG_FreeBooleanOperation(
236         CSG_BooleanOperation *operation
237 ){
238         if (operation != NULL) {
239                 BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
240                 delete(mesh_info);
241                 delete(operation);
242         }
243 }
244
245
246
247
248
249
250
251
252
253
254
255