Blender V2.61 - r43446

BME_mesh.c

Go to the documentation of this file.
00001 /*
00002  * BME_mesh.c    jan 2007
00003  *
00004  *  BMesh mesh level functions.
00005  *
00006  *
00007  * ***** BEGIN GPL LICENSE BLOCK *****
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License
00011  * as published by the Free Software Foundation; either version 2
00012  * of the License, or (at your option) any later version.
00013  * about this.  
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00023  *
00024  * The Original Code is Copyright (C) 2007 Blender Foundation.
00025  * All rights reserved.
00026  *
00027  * The Original Code is: all of this file.
00028  *
00029  * Contributor(s): Geoffrey Bantle.
00030  *
00031  * ***** END GPL LICENSE BLOCK *****
00032  */
00033 
00039 #include "BLI_listbase.h"
00040 #include "MEM_guardedalloc.h"
00041 #include "BKE_bmesh.h"
00042 #include "bmesh_private.h"
00043 
00044 /*  
00045  *  BME MAKE MESH
00046  *
00047  *  Allocates a new BME_Mesh structure.
00048  *  Returns -
00049  *  Pointer to a Bmesh
00050  *
00051 */
00052 
00053 BME_Mesh *BME_make_mesh(int allocsize[4])
00054 {
00055     /*allocate the structure*/
00056     BME_Mesh *bm = MEM_callocN(sizeof(BME_Mesh),"BMesh");
00057     /*allocate the memory pools for the mesh elements*/
00058     bm->vpool = BLI_mempool_create(sizeof(BME_Vert), allocsize[0], allocsize[0], FALSE, FALSE);
00059     bm->epool = BLI_mempool_create(sizeof(BME_Edge), allocsize[1], allocsize[1], FALSE, FALSE);
00060     bm->lpool = BLI_mempool_create(sizeof(BME_Loop), allocsize[2], allocsize[2], FALSE, FALSE);
00061     bm->ppool = BLI_mempool_create(sizeof(BME_Poly), allocsize[3], allocsize[3], FALSE, FALSE);
00062     return bm;
00063 }
00064 /*  
00065  *  BME FREE MESH
00066  *
00067  *  Frees a BME_Mesh structure.
00068 */
00069 
00070 void BME_free_mesh(BME_Mesh *bm)
00071 {
00072     BME_Vert *v;
00073     BME_Edge *e;
00074     BME_Loop *l;
00075     BME_Poly *f;
00076 
00077     for(v=bm->verts.first; v; v=v->next) CustomData_bmesh_free_block(&bm->vdata, &v->data);
00078     for(e=bm->edges.first; e; e=e->next) CustomData_bmesh_free_block(&bm->edata, &e->data);
00079     for(f=bm->polys.first; f; f=f->next){
00080         CustomData_bmesh_free_block(&bm->pdata, &f->data);
00081         l = f->loopbase;
00082         do{
00083             CustomData_bmesh_free_block(&bm->ldata, &l->data);
00084             l = l->next;
00085         }while(l!=f->loopbase);
00086     }
00087 
00088     /*Free custom data pools, This should probably go in CustomData_free?*/
00089     if(bm->vdata.totlayer) BLI_mempool_destroy(bm->vdata.pool);
00090     if(bm->edata.totlayer) BLI_mempool_destroy(bm->edata.pool);
00091     if(bm->ldata.totlayer) BLI_mempool_destroy(bm->ldata.pool);
00092     if(bm->pdata.totlayer) BLI_mempool_destroy(bm->pdata.pool);
00093 
00094      /*free custom data*/
00095     CustomData_free(&bm->vdata,0);
00096     CustomData_free(&bm->edata,0);
00097     CustomData_free(&bm->ldata,0);
00098     CustomData_free(&bm->pdata,0);
00099 
00100     /*destroy element pools*/
00101     BLI_mempool_destroy(bm->vpool);
00102     BLI_mempool_destroy(bm->epool);
00103     BLI_mempool_destroy(bm->ppool);
00104     BLI_mempool_destroy(bm->lpool);
00105     
00106     MEM_freeN(bm);  
00107 }
00108 
00109 /*  
00110  *  BME MODEL BEGIN AND END
00111  *
00112  *  These two functions represent the 'point of entry' for tools. Every BMesh tool
00113  *  must begin with a call to BME_model_end() and finish with a call to BME_model_end().
00114  *  No modification of mesh data is allowed except in between these two calls.
00115  *
00116  *  The purpose of these calls is allow for housekeeping tasks to be performed,
00117  *  such as allocating/freeing scratch arrays or performing debug validation of 
00118  *  the mesh structure.
00119  *
00120  *  Returns -
00121  *  Nothing
00122  *
00123 */
00124 
00125 int BME_model_begin(BME_Mesh *bm){
00126     /*Initialize some scratch pointer arrays used by eulers*/
00127     bm->vtar = MEM_callocN(sizeof(BME_Vert *) * 1024, "BMesh scratch vert array");
00128     bm->edar = MEM_callocN(sizeof(BME_Edge *) * 1024, "BMesh scratch edge array");
00129     bm->lpar = MEM_callocN(sizeof(BME_Loop *) * 1024, "BMesh scratch loop array");
00130     bm->plar = MEM_callocN(sizeof(BME_Poly *) * 1024, "BMesh scratch poly array");
00131 
00132     bm->vtarlen = bm->edarlen = bm->lparlen = bm->plarlen = 1024;
00133 
00134     return 1;
00135 }
00136 
00137 void BME_model_end(BME_Mesh *bm){
00138     int meshok, totvert, totedge, totpoly;
00139 
00140     totvert = BLI_countlist(&(bm->verts));
00141     totedge = BLI_countlist(&(bm->edges));
00142     totpoly = BLI_countlist(&(bm->polys));
00143 
00144     if(bm->vtar) MEM_freeN(bm->vtar);
00145     if(bm->edar) MEM_freeN(bm->edar);
00146     if(bm->lpar) MEM_freeN(bm->lpar);
00147     if(bm->plar) MEM_freeN(bm->plar);
00148     
00149     bm->vtar = NULL;
00150     bm->edar = NULL;
00151     bm->lpar = NULL;
00152     bm->plar = NULL;
00153     bm->vtarlen = bm->edarlen = bm->lparlen = bm->plarlen = 0;
00154     
00155     
00156     if(bm->totvert!=totvert || bm->totedge!=totedge || bm->totpoly!=totpoly)
00157         BME_error();
00158     
00159     meshok = BME_validate_mesh(bm, 1);
00160     if(!meshok){
00161         BME_error();
00162     }
00163 }
00164 
00165 /*  
00166  *  BME VALIDATE MESH
00167  *
00168  *  There are several levels of validation for meshes. At the 
00169  *  Euler level, some basic validation is done to local topology.
00170  *  To catch more subtle problems however, BME_validate_mesh() is 
00171  *  called by BME_model_end() whenever a tool is done executing.
00172  *  The purpose of this function is to insure that during the course 
00173  *  of tool execution that nothing has been done to invalidate the 
00174  *  structure, and if it has, provide a way of reporting that so that
00175  *  we can restore the proper structure from a backup. Since a full mesh
00176  *  validation would be too expensive, this is presented as a compromise.
00177  *
00178  *  TODO 
00179  *  
00180  *  -Make this only part of debug builds
00181  */
00182 
00183 #define VHALT(halt) {BME_error(); if(halt) return 0;}
00184 
00185 int BME_validate_mesh(struct BME_Mesh *bm, int halt)
00186 {
00187     BME_Vert *v;
00188     BME_Edge *e;
00189     BME_Poly *f;
00190     BME_Loop *l;
00191     BME_CycleNode *diskbase;
00192     int i, ok;
00193     
00194     /*Simple edge verification*/
00195     for(e=bm->edges.first; e; e=e->next){
00196         if(e->v1 == e->v2) VHALT(halt);
00197         /*validate e->d1.data and e->d2.data*/
00198         if(e->d1.data != e || e->d2.data != e) VHALT(halt);
00199         /*validate e->loop->e*/
00200         if(e->loop){
00201             if(e->loop->e != e) VHALT(halt);
00202         }
00203     }
00204     
00205     /*calculate disk cycle lengths*/
00206     for(v=bm->verts.first; v; v=v->next) v->tflag1 = v->tflag2 = 0;
00207     for(e=bm->edges.first; e; e=e->next){ 
00208         e->v1->tflag1++;
00209         e->v2->tflag1++;
00210     }
00211     /*Validate vertices and disk cycle*/
00212     for(v=bm->verts.first; v; v=v->next){
00213         /*validate v->edge pointer*/
00214         if(v->tflag1){
00215             if(v->edge){
00216                 ok = BME_vert_in_edge(v->edge,v);
00217                 if(!ok) VHALT(halt);
00218                 /*validate length of disk cycle*/
00219                 diskbase = BME_disk_getpointer(v->edge, v);
00220                 ok = BME_cycle_validate(v->tflag1, diskbase);
00221                 if(!ok) VHALT(halt);
00222                 /*validate that each edge in disk cycle contains V*/
00223                 for(i=0, e=v->edge; i < v->tflag1; i++, e = BME_disk_nextedge(e,v)){
00224                     ok = BME_vert_in_edge(e, v);
00225                     if(!ok) VHALT(halt);
00226                 }
00227             }
00228             else VHALT(halt);
00229         }
00230     }
00231     /*validate edges*/
00232     for(e=bm->edges.first; e; e=e->next){
00233         /*seperate these into BME_disk_hasedge (takes pointer to edge)*/
00234         /*search v1 disk cycle for edge*/
00235         ok = BME_disk_hasedge(e->v1,e);
00236         if(!ok) VHALT(halt);
00237         /*search v2 disk cycle for edge*/
00238         ok = BME_disk_hasedge(e->v2,e);
00239         if(!ok) VHALT(halt);
00240     }
00241     
00242     for(e=bm->edges.first; e; e=e->next) e->tflag2 = 0; //store incident faces
00243     /*Validate the loop cycle integrity.*/
00244     for(f=bm->polys.first; f; f=f->next){
00245         ok = BME_cycle_length(f->loopbase);
00246         if(ok > 1){
00247             f->tflag1 = ok;
00248         }
00249         else VHALT(halt);
00250         for(i=0, l=f->loopbase; i < f->tflag1; i++, l=l->next){
00251             /*verify loop->v pointers*/
00252             ok = BME_verts_in_edge(l->v, l->next->v, l->e);
00253             if(!ok) VHALT(halt);
00254             /*verify radial node data pointer*/
00255             if(l->radial.data != l) VHALT(halt);
00256             /*validate l->e->loop poitner*/
00257             if(l->e->loop == NULL) VHALT(halt);
00258             /*validate l->f pointer*/
00259             if(l->f != f) VHALT(halt);
00260             /*see if l->e->loop is actually in radial cycle*/
00261             
00262             l->e->tflag2++;
00263          }
00264     }
00265     
00266     /*validate length of radial cycle*/
00267     for(e=bm->edges.first; e; e=e->next){
00268         if(e->loop){
00269             ok = BME_cycle_validate(e->tflag2,&(e->loop->radial));
00270             if(!ok) VHALT(halt);
00271         }
00272     }
00273     
00274     /*validate that EIDs are within range... if not indicates corrupted mem*/
00275 
00276     /*if we get this far, pretty safe to return 1*/
00277     return 1;
00278 }
00279 
00280 /*  Currently just a convient place for a breakpoint.
00281     Probably should take an error string
00282 */
00283 void BME_error(void){
00284     printf("BME modelling error!");
00285 }