Blender  V2.59
BSP_CSGMesh.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: BSP_CSGMesh.cpp 35145 2011-02-25 10:44:20Z jesterking $
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  * The Original Code is: all of this file.
00023  *
00024  * Contributor(s): none yet.
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00035 #include "BSP_CSGMesh.h"
00036 #include "MT_assert.h"
00037 #include "CTR_TaggedSetOps.h"
00038 #include "MT_Plane3.h"
00039 #include "BSP_CSGException.h"
00040 
00041 // for insert_iterator
00042 #include <iterator>
00043 
00044 // for vector reverse
00045 #include <iostream>
00046 #include <algorithm>
00047 using namespace std;
00048 
00049 BSP_CSGMesh::
00050 BSP_CSGMesh(
00051 ) :
00052         MEM_RefCountable()
00053 {
00054         m_verts     = NULL;
00055         m_faces     = NULL;
00056         m_edges     = NULL;
00057 }
00058 
00059         BSP_CSGMesh *
00060 BSP_CSGMesh::
00061 New(
00062 ){
00063         return new BSP_CSGMesh();
00064 }
00065 
00066         BSP_CSGMesh *
00067 BSP_CSGMesh::
00068 NewCopy(
00069 ) const {
00070 
00071         BSP_CSGMesh *mesh = New();
00072         if (mesh == NULL) return NULL;
00073 
00074         mesh->m_bbox_max = m_bbox_max;
00075         mesh->m_bbox_min = m_bbox_min;
00076 
00077         if (m_edges != NULL) {
00078                 mesh->m_edges = new vector<BSP_MEdge>(*m_edges);
00079                 if (mesh->m_edges == NULL) {
00080                         delete mesh;
00081                         return NULL;
00082                 }
00083         }
00084         if (m_verts != NULL) {
00085                 mesh->m_verts = new vector<BSP_MVertex>(*m_verts);
00086                 if (mesh->m_verts == NULL) {
00087                         if (m_edges != NULL) free(mesh->m_edges);
00088                         delete mesh;
00089                         return NULL;
00090                 }
00091         }
00092         if (m_faces != NULL) {
00093                 mesh->m_faces = new vector<BSP_MFace>(*m_faces);
00094                 if (mesh->m_faces == NULL) {
00095                         delete mesh;
00096                         return NULL;
00097                 }
00098         }
00099 
00100         return mesh;
00101 }
00102         
00103         void
00104 BSP_CSGMesh::
00105 Invert(
00106 ){
00107 
00108         vector<BSP_MFace> & faces = FaceSet();
00109 
00110         vector<BSP_MFace>::const_iterator faces_end = faces.end();
00111         vector<BSP_MFace>::iterator faces_it = faces.begin();
00112 
00113         for (; faces_it != faces_end; ++faces_it) {     
00114                 faces_it->Invert();
00115         }
00116 }
00117 
00118         bool
00119 BSP_CSGMesh::
00120 SetVertices(
00121         vector<BSP_MVertex> *verts
00122 ){
00123         if (verts == NULL) return false;
00124 
00125         // create polygon and edge arrays and reserve some space.
00126         m_faces = new vector<BSP_MFace>;
00127         if (!m_faces) return false;
00128 
00129         m_faces->reserve(verts->size()/2);
00130         
00131         // previous verts get deleted here.
00132         m_verts = verts;
00133         return true;
00134 }
00135 
00136                 void
00137 BSP_CSGMesh::
00138 AddPolygon(
00139         const int * verts,
00140         int num_verts
00141 ){
00142         MT_assert(verts != NULL);
00143         MT_assert(num_verts >=3);
00144 
00145         if (verts == NULL || num_verts <3) return;
00146 
00147         // make a polyscone from these vertex indices.
00148 
00149         const BSP_FaceInd fi = m_faces->size();
00150         m_faces->push_back(BSP_MFace());                        
00151         BSP_MFace & face = m_faces->back();
00152 
00153         insert_iterator<vector<BSP_VertexInd> > insert_point(face.m_verts,face.m_verts.end()); 
00154         copy (verts,verts + num_verts,insert_point);
00155 
00156         // compute and store the plane equation for this face.
00157 
00158         MT_Plane3 face_plane = FacePlane(fi);   
00159         face.m_plane = face_plane;
00160 };
00161 
00162 // assumes that the face already has a plane equation
00163         void
00164 BSP_CSGMesh::
00165 AddPolygon(
00166         const BSP_MFace &face
00167 ){
00168         m_faces->push_back(face);                       
00169 };
00170 
00171 
00172         bool
00173 BSP_CSGMesh::
00174 BuildEdges(
00175 ){
00176 
00177         if (m_faces == NULL) return false;
00178 
00179         if (m_edges != NULL) {
00180                 DestroyEdges();
00181         }
00182 
00183         m_edges = new vector<BSP_MEdge>;
00184 
00185         if (m_edges == NULL) {
00186                 return false;
00187         }
00188                 
00189 
00190         //iterate through the face set and add edges for all polygon
00191         //edges
00192         
00193         vector<BSP_MFace>::const_iterator f_it_end = FaceSet().end();
00194         vector<BSP_MFace>::iterator f_it_begin = FaceSet().begin();
00195         vector<BSP_MFace>::iterator f_it = FaceSet().begin();
00196 
00197         vector<BSP_EdgeInd> dummy;
00198 
00199         for (;f_it != f_it_end; ++f_it) {
00200 
00201                 BSP_MFace & face = *f_it;
00202 
00203                 int vertex_num = face.m_verts.size();
00204                 BSP_VertexInd prev_vi(face.m_verts[vertex_num-1]);
00205 
00206                 for (int vert = 0; vert < vertex_num; ++vert) {
00207 
00208                         BSP_FaceInd fi(size_t (f_it - f_it_begin));
00209                         InsertEdge(prev_vi,face.m_verts[vert],fi,dummy);
00210                         prev_vi = face.m_verts[vert];
00211                 }
00212                         
00213         }
00214         dummy.clear();
00215         return true;
00216 }       
00217                 
00218         void
00219 BSP_CSGMesh::
00220 DestroyEdges(
00221 ){
00222         if ( m_edges != NULL ) {
00223                 delete m_edges;
00224                 m_edges = NULL;
00225         }       
00226         
00227         // Run through the vertices
00228         // and clear their edge arrays.
00229 
00230         if (m_verts){
00231 
00232                 vector<BSP_MVertex>::const_iterator vertex_end = VertexSet().end();
00233                 vector<BSP_MVertex>::iterator vertex_it = VertexSet().begin();
00234 
00235                 for (; vertex_it != vertex_end; ++vertex_it) {
00236                         vertex_it->m_edges.clear();
00237                 }
00238         }
00239 }
00240 
00241 
00242         BSP_EdgeInd
00243 BSP_CSGMesh::
00244 FindEdge(
00245         const BSP_VertexInd & v1,
00246         const BSP_VertexInd & v2
00247 ) const {
00248         
00249         vector<BSP_MVertex> &verts = VertexSet();
00250         vector<BSP_MEdge> &edges = EdgeSet();
00251 
00252         BSP_MEdge e;
00253         e.m_verts[0] = v1;
00254         e.m_verts[1] = v2;
00255         
00256         vector<BSP_EdgeInd> &v1_edges = verts[v1].m_edges;
00257         vector<BSP_EdgeInd>::const_iterator v1_end = v1_edges.end();
00258         vector<BSP_EdgeInd>::const_iterator v1_begin = v1_edges.begin();
00259 
00260         for (; v1_begin != v1_end; ++v1_begin) {
00261                 if (edges[*v1_begin] == e) return *v1_begin;
00262         }
00263         
00264         return BSP_EdgeInd::Empty();
00265 }
00266 
00267         void
00268 BSP_CSGMesh::
00269 InsertEdge(
00270         const BSP_VertexInd & v1,
00271         const BSP_VertexInd & v2,
00272         const BSP_FaceInd & f,
00273         vector<BSP_EdgeInd> &new_edges
00274 ){
00275 
00276         MT_assert(!v1.IsEmpty());
00277         MT_assert(!v2.IsEmpty());
00278         MT_assert(!f.IsEmpty());
00279 
00280         if (v1.IsEmpty() || v2.IsEmpty() || f.IsEmpty()) {
00281                 BSP_CSGException e(e_mesh_error);
00282                 throw (e);
00283         }
00284 
00285         vector<BSP_MVertex> &verts = VertexSet();
00286         vector<BSP_MEdge> &edges = EdgeSet();
00287         
00288         BSP_EdgeInd e;
00289 
00290         e = FindEdge(v1,v2);
00291         if (e.IsEmpty()) {
00292                 // This edge does not exist -- make a new one 
00293 
00294                 BSP_MEdge temp_e;
00295                 temp_e.m_verts[0] = v1;
00296                 temp_e.m_verts[1] = v2;
00297 
00298                 e = m_edges->size();
00299                 // set the face index from the edge back to this polygon.
00300                 temp_e.m_faces.push_back(f);
00301 
00302                 m_edges->push_back(temp_e);
00303 
00304                 // add the edge index to it's vertices 
00305                 verts[v1].AddEdge(e);
00306                 verts[v2].AddEdge(e);
00307 
00308                 new_edges.push_back(e);
00309 
00310         } else {
00311 
00312                 // edge already exists
00313                 // insure that there is no polygon already
00314                 // attached to the other side of this edge
00315                 // swap the empty face pointer in edge with f
00316 
00317                 BSP_MEdge &edge = edges[e];
00318 
00319                 // set the face index from the edge back to this polygon.
00320                 edge.m_faces.push_back(f);
00321         }
00322 }               
00323 
00324 
00325 // geometry access
00327 
00328         vector<BSP_MVertex> &
00329 BSP_CSGMesh::
00330 VertexSet(
00331 ) const {
00332         return *m_verts;
00333 }               
00334 
00335         vector<BSP_MFace> &
00336 BSP_CSGMesh::
00337 FaceSet(
00338 ) const {
00339         return *m_faces;
00340 }
00341 
00342         vector<BSP_MEdge> &
00343 BSP_CSGMesh::
00344 EdgeSet(
00345 ) const {
00346         return *m_edges;
00347 }
00348 
00349 BSP_CSGMesh::
00350 ~BSP_CSGMesh(
00351 ){
00352         if ( m_verts != NULL ) delete m_verts;
00353         if ( m_faces != NULL ) delete m_faces;
00354         if ( m_edges != NULL ) delete m_edges;
00355 }
00356 
00357 // local geometry queries.
00359 
00360 // face queries
00362 
00363         void
00364 BSP_CSGMesh::
00365 FaceVertices(
00366         const BSP_FaceInd & f,
00367         vector<BSP_VertexInd> &output
00368 ){
00369         vector<BSP_MFace> & face_set = FaceSet();
00370         output.insert(
00371                 output.end(),
00372                 face_set[f].m_verts.begin(),
00373                 face_set[f].m_verts.end()
00374         );
00375 }
00376 
00377 
00378         void
00379 BSP_CSGMesh::
00380 FaceEdges(
00381         const BSP_FaceInd & fi,
00382         vector<BSP_EdgeInd> &output
00383 ){
00384         // take intersection of the edges emminating from all the vertices
00385         // of this polygon;
00386 
00387         vector<BSP_MFace> &faces = FaceSet();
00388         vector<BSP_MEdge> &edges = EdgeSet();
00389 
00390         const BSP_MFace & f = faces[fi];
00391 
00392         // collect vertex edges;
00393 
00394         vector<BSP_VertexInd>::const_iterator face_verts_it = f.m_verts.begin();
00395         vector<BSP_VertexInd>::const_iterator face_verts_end = f.m_verts.end();
00396 
00397         vector< vector<BSP_EdgeInd> > vertex_edges(f.m_verts.size());
00398                 
00399         int vector_slot = 0;
00400 
00401         for (;face_verts_it != face_verts_end; ++face_verts_it, ++vector_slot) {
00402                 VertexEdges(*face_verts_it,vertex_edges[vector_slot]);
00403         }       
00404 
00405         int prev = vector_slot - 1; 
00406 
00407         // intersect pairs of edge sets 
00408 
00409         for (int i = 0; i < vector_slot;i++) {
00410                 CTR_TaggedSetOps<BSP_EdgeInd,BSP_MEdge>::IntersectPair(vertex_edges[prev],vertex_edges[i],edges,output);        
00411                 prev = i;
00412         }
00413         
00414         // should always have 3 or more unique edges per face.
00415         MT_assert(output.size() >=3);
00416 
00417         if (output.size() < 3) {
00418                 BSP_CSGException e(e_mesh_error);
00419                 throw(e);
00420         }
00421 };
00422         
00423 // edge queries
00425 
00426         void
00427 BSP_CSGMesh::
00428 EdgeVertices(
00429         const BSP_EdgeInd & e,
00430         vector<BSP_VertexInd> &output
00431 ){
00432         const vector<BSP_MEdge> &edges = EdgeSet();
00433         output.push_back(edges[e].m_verts[0]);
00434         output.push_back(edges[e].m_verts[1]);
00435 } 
00436 
00437         void
00438 BSP_CSGMesh::
00439 EdgeFaces(
00440         const BSP_EdgeInd & e,
00441         vector<BSP_FaceInd> &output
00442 ){
00443 
00444         vector<BSP_MEdge> & edge_set = EdgeSet();
00445         output.insert(
00446                 output.end(),
00447                 edge_set[e].m_faces.begin(),
00448                 edge_set[e].m_faces.end()
00449         );
00450         
00451 }
00452 
00453 // vertex queries
00455 
00456         void
00457 BSP_CSGMesh::
00458 VertexEdges(
00459         const BSP_VertexInd &v,
00460         vector<BSP_EdgeInd> &output
00461 ){
00462 
00463         vector<BSP_MVertex> & vertex_set = VertexSet();
00464         output.insert(
00465                 output.end(),
00466                 vertex_set[v].m_edges.begin(),
00467                 vertex_set[v].m_edges.end()
00468         );
00469 }
00470 
00471         void
00472 BSP_CSGMesh::
00473 VertexFaces(
00474         const BSP_VertexInd &vi,
00475         vector<BSP_FaceInd> &output
00476 ) {
00477 
00478         vector<BSP_MEdge> &edges = EdgeSet();
00479         vector<BSP_MFace> &faces = FaceSet();
00480         vector<BSP_MVertex> &verts = VertexSet();
00481 
00482         const vector<BSP_EdgeInd> &v_edges = verts[vi].m_edges;
00483         vector<BSP_EdgeInd>::const_iterator e_it = v_edges.begin();
00484 
00485         for (; e_it != v_edges.end(); ++e_it) {
00486 
00487                 BSP_MEdge &e = edges[*e_it]; 
00488 
00489                 // iterate through the faces of this edge - push unselected
00490                 // edges to ouput and then select the edge
00491 
00492                 vector<BSP_FaceInd>::const_iterator e_faces_end = e.m_faces.end();
00493                 vector<BSP_FaceInd>::iterator e_faces_it = e.m_faces.begin();
00494 
00495                 for (;e_faces_it != e_faces_end; ++e_faces_it) {
00496 
00497                         if (!faces[*e_faces_it].SelectTag()) {
00498                                 output.push_back(*e_faces_it);
00499                                 faces[*e_faces_it].SetSelectTag(true);
00500                         }
00501                 }
00502         }
00503 
00504         // deselect selected faces.
00505         vector<BSP_FaceInd>::iterator f_it = output.begin();
00506 
00507         for (; f_it != output.end(); ++f_it) {
00508                 faces[*f_it].SetSelectTag(false);
00509         }
00510 }
00511 
00512         bool
00513 BSP_CSGMesh::
00514 SC_Face(
00515         BSP_FaceInd f
00516 ){
00517 
00518 
00519 
00520 #if 0
00521         {
00522         // check area is greater than zero.
00523 
00524                 vector<BSP_MVertex> & verts = VertexSet();
00525 
00526                 vector<BSP_VertexInd> f_verts;
00527                 FaceVertices(f,f_verts);
00528 
00529                 MT_assert(f_verts.size() >= 3);
00530 
00531                 BSP_VertexInd root = f_verts[0];
00532                 
00533                 MT_Scalar area = 0;
00534 
00535                 for (int i=2; i < f_verts.size(); i++) {
00536                         MT_Vector3 a = verts[root].m_pos;
00537                         MT_Vector3 b = verts[f_verts[i-1]].m_pos;
00538                         MT_Vector3 c = verts[f_verts[i]].m_pos;
00539 
00540                         MT_Vector3 l1 = b-a;
00541                         MT_Vector3 l2 = c-b;
00542 
00543                         area += (l1.cross(l2)).length()/2;
00544                 }
00545 
00546                 MT_assert(!MT_fuzzyZero(area));
00547         }
00548 #endif
00549         // Check coplanarity 
00550 #if 0
00551         MT_Plane3 plane = FacePlane(f);
00552 
00553         const BSP_MFace & face = FaceSet()[f];
00554         vector<BSP_VertexInd>::const_iterator f_verts_it = face.m_verts.begin();
00555         vector<BSP_VertexInd>::const_iterator f_verts_end = face.m_verts.end();
00556 
00557         for (;f_verts_it != f_verts_end; ++f_verts_it) {
00558                 MT_Scalar dist = plane.signedDistance(
00559                         VertexSet()[*f_verts_it].m_pos
00560                 );
00561 
00562                 MT_assert(fabs(dist) < BSP_SPLIT_EPSILON);
00563         }
00564 #endif
00565 
00566 
00567         // Check connectivity
00568 
00569         vector<BSP_EdgeInd> f_edges;    
00570         FaceEdges(f,f_edges);
00571 
00572         MT_assert(f_edges.size() == FaceSet()[f].m_verts.size());
00573 
00574         unsigned int i;
00575         for (i = 0; i < f_edges.size(); ++i) {
00576 
00577                 int matches = 0;
00578                 for (unsigned int j = 0; j < EdgeSet()[f_edges[i]].m_faces.size(); j++) {
00579 
00580                         if (EdgeSet()[f_edges[i]].m_faces[j] == f) matches++;
00581                 }
00582 
00583                 MT_assert(matches == 1);
00584 
00585         }       
00586         return true;
00587 }       
00588 
00589         MT_Plane3
00590 BSP_CSGMesh::
00591 FacePlane(
00592         const BSP_FaceInd & fi
00593 ) const{
00594 
00595         const BSP_MFace & f0 = FaceSet()[fi];   
00596 
00597         // Have to be a bit careful here coz the poly may have 
00598         // a lot of parallel edges. Should walk round the polygon
00599         // and check length of cross product.
00600 
00601         const MT_Vector3 & p1 = VertexSet()[f0.m_verts[0]].m_pos;
00602         const MT_Vector3 & p2 = VertexSet()[f0.m_verts[1]].m_pos;
00603 
00604         int face_size = f0.m_verts.size();
00605         MT_Vector3 n;
00606 
00607         for (int i = 2 ; i <face_size; i++) { 
00608                 const MT_Vector3 & pi =  VertexSet()[f0.m_verts[i]].m_pos;
00609                 
00610                 MT_Vector3 l1 = p2-p1;
00611                 MT_Vector3 l2 = pi-p2;
00612                 n = l1.cross(l2);
00613                 MT_Scalar length = n.length();
00614 
00615                 if (!MT_fuzzyZero(length)) {
00616                         n = n * (1/length);
00617                         break;
00618                 } 
00619         }
00620         return MT_Plane3(n,p1);
00621 }
00622 
00623         void
00624 BSP_CSGMesh::
00625 ComputeFacePlanes(
00626 ){
00627 
00628         int fsize = FaceSet().size();
00629         int i=0;
00630         for (i = 0; i < fsize; i++) {
00631         
00632                 FaceSet()[i].m_plane = FacePlane(i);
00633         }
00634 };
00635 
00636 
00637         int
00638 BSP_CSGMesh::
00639 CountTriangles(
00640 ) const {
00641 
00642         // Each polygon of n sides can be partitioned into n-3 triangles.
00643         // So we just go through and sum this function of polygon size.
00644         
00645         vector<BSP_MFace> & face_set = FaceSet();
00646 
00647         vector<BSP_MFace>::const_iterator face_it = face_set.begin();
00648         vector<BSP_MFace>::const_iterator face_end = face_set.end();
00649 
00650         int sum = 0;
00651 
00652         for (;face_it != face_end; face_it++) {
00653         
00654                 // Should be careful about degenerate faces here.
00655                 sum += face_it->m_verts.size() - 2;
00656         }
00657 
00658         return sum;
00659 }
00660