Blender V2.61 - r43446

BOP_CarveInterface.cpp

Go to the documentation of this file.
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 }