Blender  V2.59
LOD_ManMesh2.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: LOD_ManMesh2.cpp 35147 2011-02-25 10:47:28Z 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 
00034 #include "LOD_ManMesh2.h"
00035 
00036 #include "MT_assert.h"
00037 #include <algorithm>
00038 #include "LOD_MeshException.h"
00039 #include "CTR_TaggedSetOps.h"
00040 #include "CTR_UHeap.h"
00041 #include "LOD_ExternBufferEditor.h"
00042 
00043 
00044 using namespace std;
00045 
00046 LOD_ManMesh2::
00047 LOD_ManMesh2(
00048 ) :
00049         m_bbox_min(0,0,0),
00050         m_bbox_max(0,0,0)
00051 {
00052 }
00053         
00054 
00055         LOD_ManMesh2 *
00056 LOD_ManMesh2::
00057 New(
00058 ){
00059         MEM_SmartPtr<LOD_ManMesh2> output(new LOD_ManMesh2());
00060         if (output == NULL) return NULL;
00061 
00062         // build the vertex, edge and face sets.
00063 
00064         MEM_SmartPtr<vector<LOD_Vertex> > verts(new vector<LOD_Vertex>);
00065         MEM_SmartPtr<vector<LOD_TriFace> > faces(new vector<LOD_TriFace>);
00066         MEM_SmartPtr<vector<LOD_Edge> > edges(new vector<LOD_Edge>);
00067         
00068         if ((faces == NULL) || (edges == NULL) || (verts == NULL)) {
00069                 return NULL;
00070         }
00071         
00072         output->m_verts = verts.Release();
00073         output->m_faces = faces.Release();
00074         output->m_edges = edges.Release();
00075 
00076         return output.Release();
00077 }       
00078 
00079 // take ownership of the vertices.
00080 
00081         bool    
00082 LOD_ManMesh2::
00083 SetVertices(
00084         MEM_SmartPtr<vector<LOD_Vertex> > verts
00085 ){
00086 
00087 
00088         // take ownership of vertices
00089         m_verts = verts;
00090 
00091         // create a polygon and edge buffer of half the size 
00092         // and just use the automatic resizing feature of vector<>
00093         // to worry about the dynamic array resizing
00094         
00095         m_faces->clear();
00096         m_edges->clear();
00097 
00098         m_faces->reserve(m_verts->size()/2);
00099         m_edges->reserve(m_verts->size()/2);
00100 
00101         return true;    
00102 
00103 }
00104 
00105         
00106 // add a triangle to the mesh
00107 
00108         void
00109 LOD_ManMesh2::
00110 AddTriangle(
00111         int verts[3]
00112 ) {
00113 
00114         MT_assert(verts[0] < int(m_verts->size()));
00115         MT_assert(verts[1] < int(m_verts->size()));
00116         MT_assert(verts[2] < int(m_verts->size()));
00117 
00118         LOD_TriFace face;
00119         face.m_verts[0] = verts[0];
00120         face.m_verts[1] = verts[1];
00121         face.m_verts[2] = verts[2];
00122 
00123         LOD_FaceInd face_index = m_faces->size();
00124 
00125         m_faces->push_back(face);       
00126 
00127         // now work out if any of the directed edges or their
00128         // companion edges exist already.
00129         // We go through the edges associated with each of the given vertices 
00130 
00131         // the safest thing to do is iterate through each of the edge sets
00132         // check against each of the 2 other triangle edges to see if they are there
00133         
00134         vector<LOD_EdgeInd> new_edges;
00135         new_edges.reserve(3);
00136 
00137         InsertEdge(verts[0],verts[1],face_index,new_edges);
00138         InsertEdge(verts[1],verts[2],face_index,new_edges);
00139         InsertEdge(verts[2],verts[0],face_index,new_edges);
00140 
00141 }
00142         
00143 // Adds the index of any created edges to new_edges
00144 
00145         bool
00146 LOD_ManMesh2::
00147 InsertEdge(
00148         const LOD_VertexInd v1,
00149         const LOD_VertexInd v2,
00150         const LOD_FaceInd f,
00151         vector<LOD_EdgeInd> &new_edges
00152 ){
00153         
00154         MT_assert(!v1.IsEmpty());
00155         MT_assert(!v2.IsEmpty());
00156         MT_assert(!f.IsEmpty());
00157 
00158         vector<LOD_Vertex> &verts = VertexSet();
00159         vector<LOD_Edge> &edges = EdgeSet();
00160         
00161         LOD_EdgeInd e;
00162 
00163         e = FindEdge(v1,v2);
00164 
00165         if (e.IsEmpty()) {
00166                 // This edge does not exist -- make a new one 
00167 
00168                 LOD_Edge temp_e;
00169                 temp_e.m_verts[0] = v1;
00170                 temp_e.m_verts[1] = v2;
00171 
00172                 e = m_edges->size();
00173 
00174                 // set the face ptr for this half-edge
00175                 temp_e.m_faces[0] = f;
00176 
00177                 m_edges->push_back(temp_e);
00178 
00179                 // add the edge index to it's vertices 
00180 
00181                 verts[v1].AddEdge(e);
00182                 verts[v2].AddEdge(e);
00183 
00184                 new_edges.push_back(e);
00185 
00186         } else {
00187 
00188                 // edge already exists
00189                 // insure that there is no polygon already
00190                 // attached to the other side of this edge
00191 
00192                 // swap the empty face pointer in edge with f
00193 
00194                 LOD_Edge &edge = edges[e];
00195 
00196                 edge.SwapFace(LOD_FaceInd::Empty(),f);
00197         }
00198                 
00199 
00200         return true;
00201 
00202 }
00203 
00204         void
00205 LOD_ManMesh2::
00206 ConnectTriangle(
00207         LOD_FaceInd fi,
00208         std::vector<LOD_EdgeInd> & new_edges
00209 ){
00210 
00211         vector<LOD_TriFace> &faces = FaceSet();
00212 
00213         MT_assert(!faces[fi].Degenerate());
00214 
00215         LOD_TriFace & face = faces[fi];
00216 
00217         InsertEdge(face.m_verts[0],face.m_verts[1],fi,new_edges);
00218         InsertEdge(face.m_verts[1],face.m_verts[2],fi,new_edges);
00219         InsertEdge(face.m_verts[2],face.m_verts[0],fi,new_edges);
00220 };
00221 
00222 
00223 
00224 
00225 // geometry access
00227 
00228         vector<LOD_Vertex> &
00229 LOD_ManMesh2::
00230 VertexSet(
00231 ) const {
00232         return m_verts.Ref();
00233 }               
00234 
00235         vector<LOD_TriFace> &
00236 LOD_ManMesh2::
00237 FaceSet(
00238 ) const {
00239         return m_faces.Ref();
00240 }
00241 
00242         vector<LOD_Edge> &
00243 LOD_ManMesh2::
00244 EdgeSet(
00245 ) const {
00246         return m_edges.Ref();
00247 };
00248 
00249 LOD_ManMesh2::
00250 ~LOD_ManMesh2(
00251 ){
00252         //auto ptr takes care of vertex arrays etc.
00253 }
00254 
00255         LOD_EdgeInd
00256 LOD_ManMesh2::
00257 FindEdge(
00258         const LOD_VertexInd v1,
00259         const LOD_VertexInd v2
00260 ) {
00261 
00262         vector<LOD_Vertex> &verts = VertexSet();
00263         vector<LOD_Edge> &edges = EdgeSet();
00264 
00265         LOD_Edge e;
00266         e.m_verts[0] = v1;
00267         e.m_verts[1] = v2;
00268         
00269         vector<LOD_EdgeInd> &v1_edges = verts[v1].m_edges;
00270         vector<LOD_EdgeInd>::const_iterator v1_end = v1_edges.end();
00271         vector<LOD_EdgeInd>::iterator v1_begin = v1_edges.begin();
00272 
00273         for (; v1_begin != v1_end; ++v1_begin) {
00274                 if (edges[*v1_begin] == e) return *v1_begin;
00275         }
00276         
00277         return LOD_EdgeInd::Empty();
00278 }
00279 
00280 // face queries
00282 
00283         void
00284 LOD_ManMesh2::
00285 FaceVertices(
00286         LOD_FaceInd fi,
00287         vector<LOD_VertexInd> &output
00288 ){      
00289         const vector<LOD_TriFace> &faces = FaceSet();
00290         const LOD_TriFace & f = faces[fi];
00291 
00292         output.push_back(f.m_verts[0]);
00293         output.push_back(f.m_verts[1]);
00294         output.push_back(f.m_verts[2]);
00295 }
00296         
00297         void
00298 LOD_ManMesh2::
00299 FaceEdges(
00300         LOD_FaceInd fi,
00301         vector<LOD_EdgeInd> &output
00302 ){
00303         const vector<LOD_TriFace> &faces = FaceSet();
00304         vector<LOD_Edge> &edges = EdgeSet();
00305         vector<LOD_Vertex> &verts = VertexSet();        
00306 
00307         const LOD_TriFace & f = faces[fi];
00308         // intersect vertex edges
00309 
00310         vector<LOD_EdgeInd> & v0_edges = verts[f.m_verts[0]].m_edges;
00311         vector<LOD_EdgeInd> & v1_edges = verts[f.m_verts[1]].m_edges;
00312         vector<LOD_EdgeInd> & v2_edges = verts[f.m_verts[2]].m_edges;
00313 
00314         CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v0_edges,v1_edges,edges,output);
00315         CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v1_edges,v2_edges,edges,output);
00316         CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v2_edges,v0_edges,edges,output);
00317 
00318         MT_assert(output.size() == 3);
00319         if (output.size() != 3) {
00320                 LOD_MeshException e(LOD_MeshException::e_non_manifold);
00321                 throw(e);       
00322         }
00323 }
00324         
00325 
00326 // edge queries
00328 
00329         void
00330 LOD_ManMesh2::
00331 EdgeVertices(
00332         LOD_EdgeInd ei,
00333         vector<LOD_VertexInd> &output
00334 ){
00335         const vector<LOD_Edge> &edges = EdgeSet();
00336         const LOD_Edge & e = edges[ei];
00337 
00338         output.push_back(e.m_verts[0]);
00339         output.push_back(e.m_verts[1]);
00340 }
00341 
00342         void
00343 LOD_ManMesh2::
00344 EdgeFaces(
00345         LOD_EdgeInd ei,
00346         vector<LOD_FaceInd> &output
00347 ){
00348         const vector<LOD_Edge> &edges = EdgeSet();
00349         const LOD_Edge & e = edges[ei];
00350 
00351         if (!e.m_faces[0].IsEmpty()) {
00352                 output.push_back(e.m_faces[0]);
00353         }
00354         if (!e.m_faces[1].IsEmpty()) {
00355                 output.push_back(e.m_faces[1]);
00356         }
00357 }       
00358 
00359 // vertex queries
00361 
00362         void
00363 LOD_ManMesh2::
00364 VertexEdges(
00365         LOD_VertexInd vi,
00366         vector<LOD_EdgeInd> &output
00367 ){
00368         // iterate through the edges of v and push them onto the 
00369         // output
00370         
00371         vector<LOD_Vertex> &verts = VertexSet();
00372 
00373         vector<LOD_EdgeInd> & v_edges = verts[vi].m_edges;
00374         vector<LOD_EdgeInd>::iterator v_it = v_edges.begin();
00375 
00376         for (; v_it != v_edges.end(); ++v_it) {
00377                 output.push_back(*v_it);
00378         }       
00379 }
00380 
00381         void
00382 LOD_ManMesh2::
00383 VertexFaces(
00384         LOD_VertexInd vi,
00385         vector<LOD_FaceInd> &output
00386 ){
00387         const vector<LOD_Vertex> &verts = VertexSet();
00388         vector<LOD_Edge> &edges = EdgeSet();
00389         vector<LOD_TriFace> &faces = FaceSet();
00390 
00391         const vector<LOD_EdgeInd> &v_edges = verts[vi].m_edges;
00392         vector<LOD_EdgeInd>::const_iterator e_it = v_edges.begin();
00393 
00394         for (; e_it != v_edges.end(); ++e_it) {
00395 
00396                 LOD_Edge &e = edges[*e_it]; 
00397 
00398                 if ((!e.m_faces[0].IsEmpty()) && (!faces[e.m_faces[0]].SelectTag())) {
00399                         output.push_back(e.m_faces[0]);
00400                         faces[e.m_faces[0]].SetSelectTag(true);
00401                 }
00402 
00403                 if ((!e.m_faces[1].IsEmpty()) && (!faces[e.m_faces[1]].SelectTag())) {
00404                         output.push_back(e.m_faces[1]);
00405                         faces[e.m_faces[1]].SetSelectTag(true);
00406                 }
00407         }
00408 
00409         vector<LOD_FaceInd>::iterator f_it = output.begin();
00410 
00411         for (; f_it != output.end(); ++f_it) {
00412                 faces[*f_it].SetSelectTag(false);
00413         }
00414 };
00415                 
00416         void
00417 LOD_ManMesh2::
00418 SetBBox(
00419         MT_Vector3 bbox_min,
00420         MT_Vector3 bbox_max
00421 ){
00422         m_bbox_min = bbox_min;
00423         m_bbox_max = bbox_max;
00424 };
00425 
00426         void
00427 LOD_ManMesh2::
00428 SC_TriFace(
00429         LOD_FaceInd f
00430 ){
00431         LOD_TriFace face = (*m_faces)[f];
00432         
00433         // check for unique vertices
00434 
00435         if (
00436                 (face.m_verts[0] == face.m_verts[1]) ||
00437                 (face.m_verts[1] == face.m_verts[2]) ||
00438                 (face.m_verts[2] == face.m_verts[0])
00439         ) {
00440                 MT_assert(false);
00441         }       
00442 
00443 }
00444 
00445 
00446         void
00447 LOD_ManMesh2::
00448 SC_EdgeList(
00449         LOD_VertexInd v
00450 ){
00451         vector<LOD_Edge> &edges = EdgeSet();
00452         vector<LOD_Vertex> &verts = VertexSet();
00453 
00454         vector<LOD_EdgeInd>::iterator e_it = verts[v].m_edges.begin();
00455 
00456         for (;e_it != verts[v].m_edges.end(); ++e_it) {
00457                 MT_assert( (edges[*e_it].m_verts[0] == v) || (edges[*e_it].m_verts[1] == v));
00458         }                               
00459 
00460 };
00461         
00462         void
00463 LOD_ManMesh2::
00464 DeleteVertex(
00465         LOD_ExternBufferEditor & extern_editor,
00466         LOD_VertexInd v
00467 ){
00468 
00469         vector<LOD_Edge> &edges = EdgeSet();
00470         vector<LOD_Vertex> &verts = VertexSet();
00471         vector<LOD_TriFace> &faces = FaceSet();
00472 
00473         // need to update all the edge and polygons pointing to 
00474         // the last vertex in m_verts
00475 
00476         if (verts.size() == 1) {
00477                 verts.clear();
00478                 return;
00479         }
00480 
00481         LOD_VertexInd last = LOD_VertexInd(size_t(verts.end() - verts.begin() - 1));
00482 
00483         if (!(last == v)) {
00484 
00485                 // we asume that v is already disconnected
00486 
00487                 vector<LOD_FaceInd> v_faces;
00488                 vector<LOD_EdgeInd> v_edges;
00489 
00490                 v_faces.reserve(64);
00491                 v_edges.reserve(64);
00492 
00493                 VertexFaces(last,v_faces);
00494                 VertexEdges(last,v_edges);
00495 
00496                 // map the faces and edges to look at v 
00497 
00498                 vector<LOD_FaceInd>::iterator face_it = v_faces.begin();
00499 
00500                 for(; face_it != v_faces.end(); ++face_it) {
00501                         faces[*face_it].SwapVertex(last,v);
00502                 }
00503                 vector<LOD_EdgeInd>::iterator edge_it = v_edges.begin();
00504 
00505                 for (; edge_it != v_edges.end(); ++edge_it) {
00506                         edges[*edge_it].SwapVertex(last,v);
00507                 }
00508 
00509                 // copy the last vertex onto v and pop off the back.
00510 
00511                 verts[v] = verts[last];
00512 
00513                 // tidy external buffer
00514                 extern_editor.CopyModifiedFaces(*this,v_faces);
00515         }
00516 
00517         verts.pop_back();       
00518         extern_editor.CopyBackVertex(v);
00519 
00520 
00521 };              
00522 
00523         void
00524 LOD_ManMesh2::
00525 DeleteEdge(
00526         LOD_EdgeInd e,
00527         CTR_UHeap<LOD_Edge> * heap
00528 ){
00529         vector<LOD_Edge> &edges = EdgeSet();
00530         vector<LOD_Vertex> &verts = VertexSet();
00531 
00532         if (edges.size() == 1) {
00533                 edges.clear();
00534                 return;
00535         }
00536 
00537         LOD_EdgeInd last = LOD_EdgeInd(size_t(edges.end() - edges.begin() - 1));
00538 
00539         if (!(last == e)) {
00540                 vector<LOD_EdgeInd> e_verts;
00541                 e_verts.reserve(2);
00542                 EdgeVertices(last,e_verts);
00543                 // something is wrong if there arent two!
00544 
00545                 verts[e_verts[0]].SwapEdge(last,e);
00546                 verts[e_verts[1]].SwapEdge(last,e);
00547 
00548                 // edges[e] should already have been removed from the heap
00549 
00550                 MT_assert(edges[e].HeapPos() == -1);
00551 
00552                 edges[e] = edges[last];
00553                 // also have to swap there heap positions.!!!!!
00554 
00555                 heap->HeapVector()[edges[e].HeapPos()] = e;
00556 
00557 
00558         }
00559         edges.pop_back();
00560 };
00561         
00562         void
00563 LOD_ManMesh2::
00564 DeleteFace(
00565         LOD_ExternBufferEditor & extern_editor,
00566         LOD_FaceInd f
00567 ){
00568 
00569         vector<LOD_Edge> &edges = EdgeSet();
00570         vector<LOD_TriFace> &faces = FaceSet();
00571 
00572         if (faces.size() == 1) {
00573                 faces.clear();
00574                 return;
00575         }
00576 
00577         LOD_FaceInd last = LOD_FaceInd(size_t (faces.end() - faces.begin() - 1));
00578 
00579         if (!(last == f)) {
00580                 
00581                 // we have to update the edges which point to the last 
00582                 // face 
00583 
00584                 vector<LOD_EdgeInd> f_edges;
00585                 f_edges.reserve(3);
00586 
00587                 FaceEdges(last,f_edges);
00588 
00589                 vector<LOD_EdgeInd>::iterator edge_it = f_edges.begin();
00590                 vector<LOD_EdgeInd>::const_iterator edge_end = f_edges.end();
00591         
00592                 for (; edge_it != edge_end; ++edge_it) {
00593                         edges[*edge_it].SwapFace(last,f);
00594                 }
00595 
00596                 faces[f] = faces[last];
00597 
00598         }
00599         faces.pop_back();
00600 
00601         // tidy external buffers
00602         extern_editor.CopyBackFace(f);
00603 };      
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619