Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00032 #include "../extern/BOP_Interface.h" 00033 #include "../../bsp/intern/BSP_CSGMesh_CFIterator.h" 00034 00035 #include <carve/csg_triangulator.hpp> 00036 #include <carve/interpolator.hpp> 00037 #include <carve/rescale.hpp> 00038 00039 typedef unsigned int uint; 00040 00041 #define MAX(x,y) ((x)>(y)?(x):(y)) 00042 #define MIN(x,y) ((x)<(y)?(x):(y)) 00043 00044 static int isFacePlanar(CSG_IFace &face, std::vector<carve::geom3d::Vector> &vertices) 00045 { 00046 carve::geom3d::Vector v1, v2, v3, cross; 00047 00048 if (face.vertex_number == 4) { 00049 v1 = vertices[face.vertex_index[1]] - vertices[face.vertex_index[0]]; 00050 v2 = vertices[face.vertex_index[3]] - vertices[face.vertex_index[0]]; 00051 v3 = vertices[face.vertex_index[2]] - vertices[face.vertex_index[0]]; 00052 00053 cross = carve::geom::cross(v1, v2); 00054 00055 float production = carve::geom::dot(cross, v3); 00056 float magnitude = 1e-6 * cross.length(); 00057 00058 return fabs(production) < magnitude; 00059 } 00060 00061 return 1; 00062 } 00063 00064 static carve::mesh::MeshSet<3> *Carve_addMesh(CSG_FaceIteratorDescriptor& face_it, 00065 CSG_VertexIteratorDescriptor& vertex_it, 00066 carve::interpolate::FaceAttr<uint> &oface_num, 00067 uint &num_origfaces ) 00068 { 00069 CSG_IVertex vertex; 00070 std::vector<carve::geom3d::Vector> vertices; 00071 00072 while (!vertex_it.Done(vertex_it.it)) { 00073 vertex_it.Fill(vertex_it.it,&vertex); 00074 vertices.push_back(carve::geom::VECTOR(vertex.position[0], 00075 vertex.position[1], 00076 vertex.position[2])); 00077 vertex_it.Step(vertex_it.it); 00078 } 00079 00080 CSG_IFace face; 00081 std::vector<int> f; 00082 int numfaces = 0; 00083 00084 // now for the polygons. 00085 // we may need to decalare some memory for user defined face properties. 00086 00087 std::vector<int> forig; 00088 while (!face_it.Done(face_it.it)) { 00089 face_it.Fill(face_it.it,&face); 00090 00091 if (isFacePlanar(face, vertices)) { 00092 f.push_back(face.vertex_number); 00093 f.push_back(face.vertex_index[0]); 00094 f.push_back(face.vertex_index[1]); 00095 f.push_back(face.vertex_index[2]); 00096 00097 if (face.vertex_number == 4) 00098 f.push_back(face.vertex_index[3]); 00099 00100 forig.push_back(face.orig_face); 00101 ++numfaces; 00102 face_it.Step(face_it.it); 00103 ++num_origfaces; 00104 } 00105 else { 00106 f.push_back(3); 00107 f.push_back(face.vertex_index[0]); 00108 f.push_back(face.vertex_index[1]); 00109 f.push_back(face.vertex_index[2]); 00110 00111 forig.push_back(face.orig_face); 00112 ++numfaces; 00113 00114 if (face.vertex_number == 4) { 00115 f.push_back(3); 00116 f.push_back(face.vertex_index[0]); 00117 f.push_back(face.vertex_index[2]); 00118 f.push_back(face.vertex_index[3]); 00119 00120 forig.push_back(face.orig_face); 00121 ++numfaces; 00122 } 00123 00124 face_it.Step(face_it.it); 00125 ++num_origfaces; 00126 } 00127 } 00128 00129 carve::mesh::MeshSet<3> *poly = new carve::mesh::MeshSet<3> (vertices, numfaces, f); 00130 00131 uint i; 00132 carve::mesh::MeshSet<3>::face_iter face_iter = poly->faceBegin(); 00133 for (i = 0; face_iter != poly->faceEnd(); ++face_iter, ++i) { 00134 carve::mesh::MeshSet<3>::face_t *face = *face_iter; 00135 oface_num.setAttribute(face, forig[i]); 00136 } 00137 00138 return poly; 00139 } 00140 00141 // check whether two faces share an edge, and if so merge them 00142 static uint quadMerge(std::map<carve::mesh::MeshSet<3>::vertex_t*, uint> *vertexToIndex_map, 00143 carve::mesh::MeshSet<3>::face_t *f1, carve::mesh::MeshSet<3>::face_t *f2, 00144 uint v, uint quad[4]) 00145 { 00146 uint current, n1, p1, n2, p2; 00147 uint v1[3]; 00148 uint v2[3]; 00149 00150 // get the vertex indices for each face 00151 v1[0] = vertexToIndex_map->find(f1->edge->vert)->second; 00152 v1[1] = vertexToIndex_map->find(f1->edge->next->vert)->second; 00153 v1[2] = vertexToIndex_map->find(f1->edge->next->next->vert)->second; 00154 00155 v2[0] = vertexToIndex_map->find(f2->edge->vert)->second; 00156 v2[1] = vertexToIndex_map->find(f2->edge->next->vert)->second; 00157 v2[2] = vertexToIndex_map->find(f2->edge->next->next->vert)->second; 00158 00159 // locate the current vertex we're examining, and find the next and 00160 // previous vertices based on the face windings 00161 if (v1[0] == v) {current = 0; p1 = 2; n1 = 1;} 00162 else if (v1[1] == v) {current = 1; p1 = 0; n1 = 2;} 00163 else {current = 2; p1 = 1; n1 = 0;} 00164 00165 if (v2[0] == v) {p2 = 2; n2 = 1;} 00166 else if (v2[1] == v) {p2 = 0; n2 = 2;} 00167 else {p2 = 1; n2 = 0;} 00168 00169 // if we find a match, place indices into quad in proper order and return 00170 // success code 00171 if (v1[p1] == v2[n2]) { 00172 quad[0] = v1[current]; 00173 quad[1] = v1[n1]; 00174 quad[2] = v1[p1]; 00175 quad[3] = v2[p2]; 00176 00177 return 1; 00178 } 00179 else if (v1[n1] == v2[p2]) { 00180 quad[0] = v1[current]; 00181 quad[1] = v2[n2]; 00182 quad[2] = v1[n1]; 00183 quad[3] = v1[p1]; 00184 00185 return 1; 00186 } 00187 00188 return 0; 00189 } 00190 00191 static BSP_CSGMesh* Carve_exportMesh(carve::mesh::MeshSet<3>* &poly, carve::interpolate::FaceAttr<uint> &oface_num, 00192 uint num_origfaces) 00193 { 00194 uint i; 00195 BSP_CSGMesh* outputMesh = BSP_CSGMesh::New(); 00196 00197 if (outputMesh == NULL) 00198 return NULL; 00199 00200 std::vector<BSP_MVertex>* vertices = new std::vector<BSP_MVertex>; 00201 00202 outputMesh->SetVertices(vertices); 00203 00204 std::map<carve::mesh::MeshSet<3>::vertex_t*, uint> vertexToIndex_map; 00205 std::vector<carve::mesh::MeshSet<3>::vertex_t>::iterator it = poly->vertex_storage.begin(); 00206 for (i = 0; it != poly->vertex_storage.end(); ++i, ++it) { 00207 carve::mesh::MeshSet<3>::vertex_t *vertex = &(*it); 00208 vertexToIndex_map[vertex] = i; 00209 } 00210 00211 for (i = 0; i < poly->vertex_storage.size(); ++i ) { 00212 BSP_MVertex outVtx(MT_Point3 (poly->vertex_storage[i].v[0], 00213 poly->vertex_storage[i].v[1], 00214 poly->vertex_storage[i].v[2])); 00215 outVtx.m_edges.clear(); 00216 outputMesh->VertexSet().push_back(outVtx); 00217 } 00218 00219 // build vectors of faces for each original face and each vertex 00220 std::vector< std::vector<uint> > vi(poly->vertex_storage.size()); 00221 std::vector< std::vector<uint> > ofaces(num_origfaces); 00222 carve::mesh::MeshSet<3>::face_iter face_iter = poly->faceBegin(); 00223 for (i = 0; face_iter != poly->faceEnd(); ++face_iter, ++i) { 00224 carve::mesh::MeshSet<3>::face_t *f = *face_iter; 00225 ofaces[oface_num.getAttribute(f)].push_back(i); 00226 carve::mesh::MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin(); 00227 for (; edge_iter != f->end(); ++edge_iter) { 00228 int index = vertexToIndex_map[edge_iter->vert]; 00229 vi[index].push_back(i); 00230 } 00231 } 00232 00233 uint quadverts[4] = {0, 0, 0, 0}; 00234 // go over each set of faces which belong to an original face 00235 std::vector< std::vector<uint> >::const_iterator fii; 00236 uint orig = 0; 00237 for (fii=ofaces.begin(); fii!=ofaces.end(); ++fii, ++orig) { 00238 std::vector<uint> fl = *fii; 00239 // go over a single set from an original face 00240 while (fl.size() > 0) { 00241 // remove one new face 00242 uint findex = fl.back(); 00243 fl.pop_back(); 00244 00245 carve::mesh::MeshSet<3>::face_t *f = *(poly->faceBegin() + findex); 00246 00247 // add all information except vertices to the output mesh 00248 outputMesh->FaceSet().push_back(BSP_MFace()); 00249 BSP_MFace& outFace = outputMesh->FaceSet().back(); 00250 outFace.m_verts.clear(); 00251 outFace.m_plane.setValue(f->plane.N.v); 00252 outFace.m_orig_face = orig; 00253 00254 // for each vertex of this face, check other faces containing 00255 // that vertex to see if there is a neighbor also belonging to 00256 // the original face 00257 uint result = 0; 00258 00259 carve::mesh::MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin(); 00260 for (; edge_iter != f->end(); ++edge_iter) { 00261 int v = vertexToIndex_map[edge_iter->vert]; 00262 for (uint pos2=0; !result && pos2 < vi[v].size();pos2++) { 00263 00264 // if we find the current face, ignore it 00265 uint otherf = vi[v][pos2]; 00266 if (findex == otherf) 00267 continue; 00268 00269 carve::mesh::MeshSet<3>::face_t *f2 = *(poly->faceBegin() + otherf); 00270 00271 // if other face doesn't have the same original face, 00272 // ignore it also 00273 uint other_orig = oface_num.getAttribute(f2); 00274 if (orig != other_orig) 00275 continue; 00276 00277 // if, for some reason, we don't find the other face in 00278 // the current set of faces, ignore it 00279 uint other_index = 0; 00280 while (other_index < fl.size() && fl[other_index] != otherf) ++other_index; 00281 if (other_index == fl.size()) continue; 00282 00283 // see if the faces share an edge 00284 result = quadMerge(&vertexToIndex_map, f, f2, v, quadverts); 00285 // if faces can be merged, then remove the other face 00286 // from the current set 00287 if (result) { 00288 uint replace = fl.back(); 00289 fl.pop_back(); 00290 if(otherf != replace) 00291 fl[other_index] = replace; 00292 } 00293 } 00294 } 00295 00296 // if we merged faces, use the list of common vertices; otherwise 00297 // use the faces's vertices 00298 if (result) { 00299 // make quat using verts stored in result 00300 outFace.m_verts.push_back(quadverts[0]); 00301 outFace.m_verts.push_back(quadverts[1]); 00302 outFace.m_verts.push_back(quadverts[2]); 00303 outFace.m_verts.push_back(quadverts[3]); 00304 } else { 00305 carve::mesh::MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin(); 00306 for (; edge_iter != f->end(); ++edge_iter) { 00307 //int index = ofacevert_num.getAttribute(f, edge_iter.idx()); 00308 int index = vertexToIndex_map[edge_iter->vert]; 00309 outFace.m_verts.push_back( index ); 00310 } 00311 } 00312 } 00313 } 00314 00315 // Build the mesh edges using topological informtion 00316 outputMesh->BuildEdges(); 00317 00318 return outputMesh; 00319 } 00320 00332 BoolOpState BOP_performBooleanOperation(BoolOpType opType, 00333 BSP_CSGMesh** outputMesh, 00334 CSG_FaceIteratorDescriptor obAFaces, 00335 CSG_VertexIteratorDescriptor obAVertices, 00336 CSG_FaceIteratorDescriptor obBFaces, 00337 CSG_VertexIteratorDescriptor obBVertices) 00338 { 00339 carve::csg::CSG::OP op; 00340 carve::mesh::MeshSet<3> *left, *right, *output; 00341 carve::csg::CSG csg; 00342 carve::geom3d::Vector min, max; 00343 carve::interpolate::FaceAttr<uint> oface_num; 00344 uint num_origfaces = 0; 00345 00346 switch (opType) { 00347 case BOP_UNION: 00348 op = carve::csg::CSG::UNION; 00349 break; 00350 case BOP_INTERSECTION: 00351 op = carve::csg::CSG::INTERSECTION; 00352 break; 00353 case BOP_DIFFERENCE: 00354 op = carve::csg::CSG::A_MINUS_B; 00355 break; 00356 default: 00357 return BOP_ERROR; 00358 } 00359 00360 left = Carve_addMesh(obAFaces, obAVertices, oface_num, num_origfaces ); 00361 right = Carve_addMesh(obBFaces, obBVertices, oface_num, num_origfaces ); 00362 00363 min.x = max.x = left->vertex_storage[0].v.x; 00364 min.y = max.y = left->vertex_storage[0].v.y; 00365 min.z = max.z = left->vertex_storage[0].v.z; 00366 for (uint i = 1; i < left->vertex_storage.size(); ++i) { 00367 min.x = MIN(min.x,left->vertex_storage[i].v.x); 00368 min.y = MIN(min.y,left->vertex_storage[i].v.y); 00369 min.z = MIN(min.z,left->vertex_storage[i].v.z); 00370 max.x = MAX(max.x,left->vertex_storage[i].v.x); 00371 max.y = MAX(max.y,left->vertex_storage[i].v.y); 00372 max.z = MAX(max.z,left->vertex_storage[i].v.z); 00373 } 00374 for (uint i = 0; i < right->vertex_storage.size(); ++i) { 00375 min.x = MIN(min.x,right->vertex_storage[i].v.x); 00376 min.y = MIN(min.y,right->vertex_storage[i].v.y); 00377 min.z = MIN(min.z,right->vertex_storage[i].v.z); 00378 max.x = MAX(max.x,right->vertex_storage[i].v.x); 00379 max.y = MAX(max.y,right->vertex_storage[i].v.y); 00380 max.z = MAX(max.z,right->vertex_storage[i].v.z); 00381 } 00382 00383 carve::rescale::rescale scaler(min.x, min.y, min.z, max.x, max.y, max.z); 00384 carve::rescale::fwd fwd_r(scaler); 00385 carve::rescale::rev rev_r(scaler); 00386 00387 left->transform(fwd_r); 00388 right->transform(fwd_r); 00389 00390 csg.hooks.registerHook(new carve::csg::CarveTriangulator, carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT); 00391 00392 oface_num.installHooks(csg); 00393 output = csg.compute( left, right, op, NULL, carve::csg::CSG::CLASSIFY_EDGE); 00394 delete left; 00395 delete right; 00396 00397 output->transform(rev_r); 00398 00399 *outputMesh = Carve_exportMesh( output, oface_num, num_origfaces); 00400 delete output; 00401 00402 return BOP_OK; 00403 }