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