|
Blender
V2.59
|
00001 00002 /* mesh.c 00003 * 00004 * 00005 * 00006 * $Id: mesh.c 38879 2011-07-31 11:12:38Z dfelinto $ 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 * 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) 2001-2002 by NaN Holding BV. 00025 * All rights reserved. 00026 * 00027 * Contributor(s): Blender Foundation 00028 * 00029 * ***** END GPL LICENSE BLOCK ***** 00030 */ 00031 00037 #include <stdlib.h> 00038 #include <string.h> 00039 #include <stdio.h> 00040 #include <math.h> 00041 00042 #include "MEM_guardedalloc.h" 00043 00044 #include "DNA_scene_types.h" 00045 #include "DNA_material_types.h" 00046 #include "DNA_object_types.h" 00047 #include "DNA_key_types.h" 00048 #include "DNA_meshdata_types.h" 00049 #include "DNA_ipo_types.h" 00050 00051 #include "BLI_blenlib.h" 00052 #include "BLI_editVert.h" 00053 #include "BLI_math.h" 00054 #include "BLI_edgehash.h" 00055 #include "BLI_utildefines.h" 00056 00057 #include "BKE_animsys.h" 00058 #include "BKE_main.h" 00059 #include "BKE_DerivedMesh.h" 00060 #include "BKE_global.h" 00061 #include "BKE_mesh.h" 00062 #include "BKE_displist.h" 00063 #include "BKE_library.h" 00064 #include "BKE_material.h" 00065 #include "BKE_modifier.h" 00066 #include "BKE_multires.h" 00067 #include "BKE_key.h" 00068 /* these 2 are only used by conversion functions */ 00069 #include "BKE_curve.h" 00070 /* -- */ 00071 #include "BKE_object.h" 00072 00073 00074 EditMesh *BKE_mesh_get_editmesh(Mesh *me) 00075 { 00076 return me->edit_mesh; 00077 } 00078 00079 void BKE_mesh_end_editmesh(Mesh *UNUSED(me), EditMesh *UNUSED(em)) 00080 { 00081 } 00082 00083 00084 void mesh_update_customdata_pointers(Mesh *me) 00085 { 00086 me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); 00087 me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); 00088 me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY); 00089 00090 me->medge = CustomData_get_layer(&me->edata, CD_MEDGE); 00091 00092 me->mface = CustomData_get_layer(&me->fdata, CD_MFACE); 00093 me->mcol = CustomData_get_layer(&me->fdata, CD_MCOL); 00094 me->mtface = CustomData_get_layer(&me->fdata, CD_MTFACE); 00095 } 00096 00097 /* Note: unlinking is called when me->id.us is 0, question remains how 00098 * much unlinking of Library data in Mesh should be done... probably 00099 * we need a more generic method, like the expand() functions in 00100 * readfile.c */ 00101 00102 void unlink_mesh(Mesh *me) 00103 { 00104 int a; 00105 00106 if(me==NULL) return; 00107 00108 for(a=0; a<me->totcol; a++) { 00109 if(me->mat[a]) me->mat[a]->id.us--; 00110 me->mat[a]= NULL; 00111 } 00112 00113 if(me->key) { 00114 me->key->id.us--; 00115 if (me->key->id.us == 0 && me->key->ipo ) 00116 me->key->ipo->id.us--; 00117 } 00118 me->key= NULL; 00119 00120 if(me->texcomesh) me->texcomesh= NULL; 00121 } 00122 00123 00124 /* do not free mesh itself */ 00125 void free_mesh(Mesh *me) 00126 { 00127 unlink_mesh(me); 00128 00129 if(me->pv) { 00130 if(me->pv->vert_map) MEM_freeN(me->pv->vert_map); 00131 if(me->pv->edge_map) MEM_freeN(me->pv->edge_map); 00132 if(me->pv->old_faces) MEM_freeN(me->pv->old_faces); 00133 if(me->pv->old_edges) MEM_freeN(me->pv->old_edges); 00134 me->totvert= me->pv->totvert; 00135 me->totedge= me->pv->totedge; 00136 me->totface= me->pv->totface; 00137 MEM_freeN(me->pv); 00138 } 00139 00140 CustomData_free(&me->vdata, me->totvert); 00141 CustomData_free(&me->edata, me->totedge); 00142 CustomData_free(&me->fdata, me->totface); 00143 00144 if(me->adt) { 00145 BKE_free_animdata(&me->id); 00146 me->adt= NULL; 00147 } 00148 00149 if(me->mat) MEM_freeN(me->mat); 00150 00151 if(me->bb) MEM_freeN(me->bb); 00152 if(me->mselect) MEM_freeN(me->mselect); 00153 if(me->edit_mesh) MEM_freeN(me->edit_mesh); 00154 } 00155 00156 void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount) 00157 { 00158 /* Assumes dst is already set up */ 00159 int i; 00160 00161 if (!src || !dst) 00162 return; 00163 00164 memcpy (dst, src, copycount * sizeof(MDeformVert)); 00165 00166 for (i=0; i<copycount; i++){ 00167 if (src[i].dw){ 00168 dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight"); 00169 memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight); 00170 } 00171 } 00172 00173 } 00174 00175 void free_dverts(MDeformVert *dvert, int totvert) 00176 { 00177 /* Instead of freeing the verts directly, 00178 call this function to delete any special 00179 vert data */ 00180 int i; 00181 00182 if (!dvert) 00183 return; 00184 00185 /* Free any special data from the verts */ 00186 for (i=0; i<totvert; i++){ 00187 if (dvert[i].dw) MEM_freeN (dvert[i].dw); 00188 } 00189 MEM_freeN (dvert); 00190 } 00191 00192 Mesh *add_mesh(const char *name) 00193 { 00194 Mesh *me; 00195 00196 me= alloc_libblock(&G.main->mesh, ID_ME, name); 00197 00198 me->size[0]= me->size[1]= me->size[2]= 1.0; 00199 me->smoothresh= 30; 00200 me->texflag= AUTOSPACE; 00201 me->flag= ME_TWOSIDED; 00202 me->bb= unit_boundbox(); 00203 me->drawflag= ME_DRAWEDGES|ME_DRAWFACES|ME_DRAWCREASES; 00204 00205 return me; 00206 } 00207 00208 Mesh *copy_mesh(Mesh *me) 00209 { 00210 Mesh *men; 00211 MTFace *tface; 00212 int a, i; 00213 00214 men= copy_libblock(me); 00215 00216 men->mat= MEM_dupallocN(me->mat); 00217 for(a=0; a<men->totcol; a++) { 00218 id_us_plus((ID *)men->mat[a]); 00219 } 00220 id_us_plus((ID *)men->texcomesh); 00221 00222 CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert); 00223 CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge); 00224 CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface); 00225 mesh_update_customdata_pointers(men); 00226 00227 /* ensure indirect linked data becomes lib-extern */ 00228 for(i=0; i<me->fdata.totlayer; i++) { 00229 if(me->fdata.layers[i].type == CD_MTFACE) { 00230 tface= (MTFace*)me->fdata.layers[i].data; 00231 00232 for(a=0; a<me->totface; a++, tface++) 00233 if(tface->tpage) 00234 id_lib_extern((ID*)tface->tpage); 00235 } 00236 } 00237 00238 men->mselect= NULL; 00239 men->edit_mesh= NULL; 00240 men->pv= NULL; /* looks like this is no-longer supported but NULL just incase */ 00241 00242 men->bb= MEM_dupallocN(men->bb); 00243 00244 men->key= copy_key(me->key); 00245 if(men->key) men->key->from= (ID *)men; 00246 00247 return men; 00248 } 00249 00250 static void make_local_tface(Main *bmain, Mesh *me) 00251 { 00252 MTFace *tface; 00253 Image *ima; 00254 int a, i; 00255 00256 for(i=0; i<me->fdata.totlayer; i++) { 00257 if(me->fdata.layers[i].type == CD_MTFACE) { 00258 tface= (MTFace*)me->fdata.layers[i].data; 00259 00260 for(a=0; a<me->totface; a++, tface++) { 00261 /* special case: ima always local immediately */ 00262 if(tface->tpage) { 00263 ima= tface->tpage; 00264 if(ima->id.lib) { 00265 ima->id.lib= NULL; 00266 ima->id.flag= LIB_LOCAL; 00267 new_id(&bmain->image, (ID *)ima, NULL); 00268 } 00269 } 00270 } 00271 } 00272 } 00273 } 00274 00275 static void expand_local_mesh(Main *bmain, Mesh *me) 00276 { 00277 id_lib_extern((ID *)me->texcomesh); 00278 00279 if(me->mtface) { 00280 /* why is this an exception? - should not really make local when extern'ing - campbell */ 00281 make_local_tface(bmain, me); 00282 } 00283 00284 if(me->mat) { 00285 extern_local_matarar(me->mat, me->totcol); 00286 } 00287 } 00288 00289 void make_local_mesh(Mesh *me) 00290 { 00291 Main *bmain= G.main; 00292 Object *ob; 00293 int local=0, lib=0; 00294 00295 /* - only lib users: do nothing 00296 * - only local users: set flag 00297 * - mixed: make copy 00298 */ 00299 00300 if(me->id.lib==NULL) return; 00301 if(me->id.us==1) { 00302 me->id.lib= NULL; 00303 me->id.flag= LIB_LOCAL; 00304 00305 new_id(&bmain->mesh, (ID *)me, NULL); 00306 expand_local_mesh(bmain, me); 00307 return; 00308 } 00309 00310 for(ob= bmain->object.first; ob && ELEM(0, lib, local); ob= ob->id.next) { 00311 if(me == ob->data) { 00312 if(ob->id.lib) lib= 1; 00313 else local= 1; 00314 } 00315 } 00316 00317 if(local && lib==0) { 00318 me->id.lib= NULL; 00319 me->id.flag= LIB_LOCAL; 00320 00321 new_id(&bmain->mesh, (ID *)me, NULL); 00322 expand_local_mesh(bmain, me); 00323 } 00324 else if(local && lib) { 00325 Mesh *men= copy_mesh(me); 00326 men->id.us= 0; 00327 00328 for(ob= bmain->object.first; ob; ob= ob->id.next) { 00329 if(me == ob->data) { 00330 if(ob->id.lib==NULL) { 00331 set_mesh(ob, men); 00332 } 00333 } 00334 } 00335 } 00336 } 00337 00338 void boundbox_mesh(Mesh *me, float *loc, float *size) 00339 { 00340 BoundBox *bb; 00341 float min[3], max[3]; 00342 float mloc[3], msize[3]; 00343 00344 if(me->bb==NULL) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); 00345 bb= me->bb; 00346 00347 if (!loc) loc= mloc; 00348 if (!size) size= msize; 00349 00350 INIT_MINMAX(min, max); 00351 if(!minmax_mesh(me, min, max)) { 00352 min[0] = min[1] = min[2] = -1.0f; 00353 max[0] = max[1] = max[2] = 1.0f; 00354 } 00355 00356 mid_v3_v3v3(loc, min, max); 00357 00358 size[0]= (max[0]-min[0])/2.0f; 00359 size[1]= (max[1]-min[1])/2.0f; 00360 size[2]= (max[2]-min[2])/2.0f; 00361 00362 boundbox_set_from_min_max(bb, min, max); 00363 } 00364 00365 void tex_space_mesh(Mesh *me) 00366 { 00367 float loc[3], size[3]; 00368 int a; 00369 00370 boundbox_mesh(me, loc, size); 00371 00372 if(me->texflag & AUTOSPACE) { 00373 for (a=0; a<3; a++) { 00374 if(size[a]==0.0f) size[a]= 1.0f; 00375 else if(size[a]>0.0f && size[a]<0.00001f) size[a]= 0.00001f; 00376 else if(size[a]<0.0f && size[a]> -0.00001f) size[a]= -0.00001f; 00377 } 00378 00379 copy_v3_v3(me->loc, loc); 00380 copy_v3_v3(me->size, size); 00381 zero_v3(me->rot); 00382 } 00383 } 00384 00385 BoundBox *mesh_get_bb(Object *ob) 00386 { 00387 Mesh *me= ob->data; 00388 00389 if(ob->bb) 00390 return ob->bb; 00391 00392 if (!me->bb) 00393 tex_space_mesh(me); 00394 00395 return me->bb; 00396 } 00397 00398 void mesh_get_texspace(Mesh *me, float *loc_r, float *rot_r, float *size_r) 00399 { 00400 if (!me->bb) { 00401 tex_space_mesh(me); 00402 } 00403 00404 if (loc_r) VECCOPY(loc_r, me->loc); 00405 if (rot_r) VECCOPY(rot_r, me->rot); 00406 if (size_r) VECCOPY(size_r, me->size); 00407 } 00408 00409 float *get_mesh_orco_verts(Object *ob) 00410 { 00411 Mesh *me = ob->data; 00412 MVert *mvert = NULL; 00413 Mesh *tme = me->texcomesh?me->texcomesh:me; 00414 int a, totvert; 00415 float (*vcos)[3] = NULL; 00416 00417 /* Get appropriate vertex coordinates */ 00418 vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh"); 00419 mvert = tme->mvert; 00420 totvert = MIN2(tme->totvert, me->totvert); 00421 00422 for(a=0; a<totvert; a++, mvert++) { 00423 copy_v3_v3(vcos[a], mvert->co); 00424 } 00425 00426 return (float*)vcos; 00427 } 00428 00429 void transform_mesh_orco_verts(Mesh *me, float (*orco)[3], int totvert, int invert) 00430 { 00431 float loc[3], size[3]; 00432 int a; 00433 00434 mesh_get_texspace(me->texcomesh?me->texcomesh:me, loc, NULL, size); 00435 00436 if(invert) { 00437 for(a=0; a<totvert; a++) { 00438 float *co = orco[a]; 00439 madd_v3_v3v3v3(co, loc, co, size); 00440 } 00441 } 00442 else { 00443 for(a=0; a<totvert; a++) { 00444 float *co = orco[a]; 00445 co[0] = (co[0]-loc[0])/size[0]; 00446 co[1] = (co[1]-loc[1])/size[1]; 00447 co[2] = (co[2]-loc[2])/size[2]; 00448 } 00449 } 00450 } 00451 00452 /* rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0. 00453 this is necessary to make the if(mface->v4) check for quads work */ 00454 int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) 00455 { 00456 /* first test if the face is legal */ 00457 if((mface->v3 || nr==4) && mface->v3==mface->v4) { 00458 mface->v4= 0; 00459 nr--; 00460 } 00461 if((mface->v2 || mface->v4) && mface->v2==mface->v3) { 00462 mface->v3= mface->v4; 00463 mface->v4= 0; 00464 nr--; 00465 } 00466 if(mface->v1==mface->v2) { 00467 mface->v2= mface->v3; 00468 mface->v3= mface->v4; 00469 mface->v4= 0; 00470 nr--; 00471 } 00472 00473 /* check corrupt cases, bowtie geometry, cant handle these because edge data wont exist so just return 0 */ 00474 if(nr==3) { 00475 if( 00476 /* real edges */ 00477 mface->v1==mface->v2 || 00478 mface->v2==mface->v3 || 00479 mface->v3==mface->v1 00480 ) { 00481 return 0; 00482 } 00483 } 00484 else if(nr==4) { 00485 if( 00486 /* real edges */ 00487 mface->v1==mface->v2 || 00488 mface->v2==mface->v3 || 00489 mface->v3==mface->v4 || 00490 mface->v4==mface->v1 || 00491 /* across the face */ 00492 mface->v1==mface->v3 || 00493 mface->v2==mface->v4 00494 ) { 00495 return 0; 00496 } 00497 } 00498 00499 /* prevent a zero at wrong index location */ 00500 if(nr==3) { 00501 if(mface->v3==0) { 00502 static int corner_indices[4] = {1, 2, 0, 3}; 00503 00504 SWAP(int, mface->v1, mface->v2); 00505 SWAP(int, mface->v2, mface->v3); 00506 00507 if(fdata) 00508 CustomData_swap(fdata, mfindex, corner_indices); 00509 } 00510 } 00511 else if(nr==4) { 00512 if(mface->v3==0 || mface->v4==0) { 00513 static int corner_indices[4] = {2, 3, 0, 1}; 00514 00515 SWAP(int, mface->v1, mface->v3); 00516 SWAP(int, mface->v2, mface->v4); 00517 00518 if(fdata) 00519 CustomData_swap(fdata, mfindex, corner_indices); 00520 } 00521 } 00522 00523 return nr; 00524 } 00525 00526 Mesh *get_mesh(Object *ob) 00527 { 00528 00529 if(ob==NULL) return NULL; 00530 if(ob->type==OB_MESH) return ob->data; 00531 else return NULL; 00532 } 00533 00534 void set_mesh(Object *ob, Mesh *me) 00535 { 00536 Mesh *old=NULL; 00537 00538 multires_force_update(ob); 00539 00540 if(ob==NULL) return; 00541 00542 if(ob->type==OB_MESH) { 00543 old= ob->data; 00544 if (old) 00545 old->id.us--; 00546 ob->data= me; 00547 id_us_plus((ID *)me); 00548 } 00549 00550 test_object_materials((ID *)me); 00551 00552 test_object_modifiers(ob); 00553 } 00554 00555 /* ************** make edges in a Mesh, for outside of editmode */ 00556 00557 struct edgesort { 00558 int v1, v2; 00559 short is_loose, is_draw; 00560 }; 00561 00562 /* edges have to be added with lowest index first for sorting */ 00563 static void to_edgesort(struct edgesort *ed, int v1, int v2, short is_loose, short is_draw) 00564 { 00565 if(v1<v2) { 00566 ed->v1= v1; ed->v2= v2; 00567 } 00568 else { 00569 ed->v1= v2; ed->v2= v1; 00570 } 00571 ed->is_loose= is_loose; 00572 ed->is_draw= is_draw; 00573 } 00574 00575 static int vergedgesort(const void *v1, const void *v2) 00576 { 00577 const struct edgesort *x1=v1, *x2=v2; 00578 00579 if( x1->v1 > x2->v1) return 1; 00580 else if( x1->v1 < x2->v1) return -1; 00581 else if( x1->v2 > x2->v2) return 1; 00582 else if( x1->v2 < x2->v2) return -1; 00583 00584 return 0; 00585 } 00586 00587 static void mfaces_strip_loose(MFace *mface, int *totface) 00588 { 00589 int a,b; 00590 00591 for (a=b=0; a<*totface; a++) { 00592 if (mface[a].v3) { 00593 if (a!=b) { 00594 memcpy(&mface[b],&mface[a],sizeof(mface[b])); 00595 } 00596 b++; 00597 } 00598 } 00599 00600 *totface= b; 00601 } 00602 00603 /* Create edges based on known verts and faces */ 00604 static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, int UNUSED(totvert), int totface, 00605 int old, MEdge **alledge, int *_totedge) 00606 { 00607 MFace *mface; 00608 MEdge *medge; 00609 struct edgesort *edsort, *ed; 00610 int a, totedge=0, final=0; 00611 00612 /* we put all edges in array, sort them, and detect doubles that way */ 00613 00614 for(a= totface, mface= allface; a>0; a--, mface++) { 00615 if(mface->v4) totedge+=4; 00616 else if(mface->v3) totedge+=3; 00617 else totedge+=1; 00618 } 00619 00620 if(totedge==0) { 00621 /* flag that mesh has edges */ 00622 (*alledge)= MEM_callocN(0, "make mesh edges"); 00623 (*_totedge) = 0; 00624 return; 00625 } 00626 00627 ed= edsort= MEM_mallocN(totedge*sizeof(struct edgesort), "edgesort"); 00628 00629 for(a= totface, mface= allface; a>0; a--, mface++) { 00630 to_edgesort(ed++, mface->v1, mface->v2, !mface->v3, mface->edcode & ME_V1V2); 00631 if(mface->v4) { 00632 to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3); 00633 to_edgesort(ed++, mface->v3, mface->v4, 0, mface->edcode & ME_V3V4); 00634 to_edgesort(ed++, mface->v4, mface->v1, 0, mface->edcode & ME_V4V1); 00635 } 00636 else if(mface->v3) { 00637 to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3); 00638 to_edgesort(ed++, mface->v3, mface->v1, 0, mface->edcode & ME_V3V1); 00639 } 00640 } 00641 00642 qsort(edsort, totedge, sizeof(struct edgesort), vergedgesort); 00643 00644 /* count final amount */ 00645 for(a=totedge, ed=edsort; a>1; a--, ed++) { 00646 /* edge is unique when it differs from next edge, or is last */ 00647 if(ed->v1 != (ed+1)->v1 || ed->v2 != (ed+1)->v2) final++; 00648 } 00649 final++; 00650 00651 (*alledge)= medge= MEM_callocN(sizeof (MEdge) * final, "make_edges mdge"); 00652 (*_totedge)= final; 00653 00654 for(a=totedge, ed=edsort; a>1; a--, ed++) { 00655 /* edge is unique when it differs from next edge, or is last */ 00656 if(ed->v1 != (ed+1)->v1 || ed->v2 != (ed+1)->v2) { 00657 medge->v1= ed->v1; 00658 medge->v2= ed->v2; 00659 if(old==0 || ed->is_draw) medge->flag= ME_EDGEDRAW|ME_EDGERENDER; 00660 if(ed->is_loose) medge->flag|= ME_LOOSEEDGE; 00661 00662 /* order is swapped so extruding this edge as a surface wont flip face normals 00663 * with cyclic curves */ 00664 if(ed->v1+1 != ed->v2) { 00665 SWAP(int, medge->v1, medge->v2); 00666 } 00667 medge++; 00668 } 00669 else { 00670 /* equal edge, we merge the drawflag */ 00671 (ed+1)->is_draw |= ed->is_draw; 00672 } 00673 } 00674 /* last edge */ 00675 medge->v1= ed->v1; 00676 medge->v2= ed->v2; 00677 medge->flag= ME_EDGEDRAW; 00678 if(ed->is_loose) medge->flag|= ME_LOOSEEDGE; 00679 medge->flag |= ME_EDGERENDER; 00680 00681 MEM_freeN(edsort); 00682 } 00683 00684 void make_edges(Mesh *me, int old) 00685 { 00686 MEdge *medge; 00687 int totedge=0; 00688 00689 make_edges_mdata(me->mvert, me->mface, me->totvert, me->totface, old, &medge, &totedge); 00690 if(totedge==0) { 00691 /* flag that mesh has edges */ 00692 me->medge = medge; 00693 me->totedge = 0; 00694 return; 00695 } 00696 00697 medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, totedge); 00698 me->medge= medge; 00699 me->totedge= totedge; 00700 00701 mesh_strip_loose_faces(me); 00702 } 00703 00704 void mesh_strip_loose_faces(Mesh *me) 00705 { 00706 int a,b; 00707 00708 for (a=b=0; a<me->totface; a++) { 00709 if (me->mface[a].v3) { 00710 if (a!=b) { 00711 memcpy(&me->mface[b],&me->mface[a],sizeof(me->mface[b])); 00712 CustomData_copy_data(&me->fdata, &me->fdata, a, b, 1); 00713 CustomData_free_elem(&me->fdata, a, 1); 00714 } 00715 b++; 00716 } 00717 } 00718 me->totface = b; 00719 } 00720 00721 void mesh_strip_loose_edges(Mesh *me) 00722 { 00723 int a,b; 00724 00725 for (a=b=0; a<me->totedge; a++) { 00726 if (me->medge[a].v1!=me->medge[a].v2) { 00727 if (a!=b) { 00728 memcpy(&me->medge[b],&me->medge[a],sizeof(me->medge[b])); 00729 CustomData_copy_data(&me->edata, &me->edata, a, b, 1); 00730 CustomData_free_elem(&me->edata, a, 1); 00731 } 00732 b++; 00733 } 00734 } 00735 me->totedge = b; 00736 } 00737 00738 void mball_to_mesh(ListBase *lb, Mesh *me) 00739 { 00740 DispList *dl; 00741 MVert *mvert; 00742 MFace *mface; 00743 float *nors, *verts; 00744 int a, *index; 00745 00746 dl= lb->first; 00747 if(dl==NULL) return; 00748 00749 if(dl->type==DL_INDEX4) { 00750 me->totvert= dl->nr; 00751 me->totface= dl->parts; 00752 00753 mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, dl->nr); 00754 mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, dl->parts); 00755 me->mvert= mvert; 00756 me->mface= mface; 00757 00758 a= dl->nr; 00759 nors= dl->nors; 00760 verts= dl->verts; 00761 while(a--) { 00762 VECCOPY(mvert->co, verts); 00763 normal_float_to_short_v3(mvert->no, nors); 00764 mvert++; 00765 nors+= 3; 00766 verts+= 3; 00767 } 00768 00769 a= dl->parts; 00770 index= dl->index; 00771 while(a--) { 00772 mface->v1= index[0]; 00773 mface->v2= index[1]; 00774 mface->v3= index[2]; 00775 mface->v4= index[3]; 00776 mface->flag= ME_SMOOTH; 00777 00778 test_index_face(mface, NULL, 0, (mface->v3==mface->v4)? 3: 4); 00779 00780 mface++; 00781 index+= 4; 00782 } 00783 00784 make_edges(me, 0); // all edges 00785 } 00786 } 00787 00788 /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ 00789 /* return non-zero on error */ 00790 int nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert, 00791 MEdge **alledge, int *totedge, MFace **allface, int *totface) 00792 { 00793 return nurbs_to_mdata_customdb(ob, &ob->disp, 00794 allvert, totvert, alledge, totedge, allface, totface); 00795 } 00796 00797 /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */ 00798 /* use specified dispbase */ 00799 int nurbs_to_mdata_customdb(Object *ob, ListBase *dispbase, MVert **allvert, int *_totvert, 00800 MEdge **alledge, int *_totedge, MFace **allface, int *_totface) 00801 { 00802 DispList *dl; 00803 Curve *cu; 00804 MVert *mvert; 00805 MFace *mface; 00806 float *data; 00807 int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0; 00808 int p1, p2, p3, p4, *index; 00809 int conv_polys= 0; 00810 00811 cu= ob->data; 00812 00813 conv_polys|= cu->flag & CU_3D; /* 2d polys are filled with DL_INDEX3 displists */ 00814 conv_polys|= ob->type == OB_SURF; /* surf polys are never filled */ 00815 00816 /* count */ 00817 dl= dispbase->first; 00818 while(dl) { 00819 if(dl->type==DL_SEGM) { 00820 totvert+= dl->parts*dl->nr; 00821 totvlak+= dl->parts*(dl->nr-1); 00822 } 00823 else if(dl->type==DL_POLY) { 00824 if(conv_polys) { 00825 totvert+= dl->parts*dl->nr; 00826 totvlak+= dl->parts*dl->nr; 00827 } 00828 } 00829 else if(dl->type==DL_SURF) { 00830 totvert+= dl->parts*dl->nr; 00831 totvlak+= (dl->parts-1+((dl->flag & DL_CYCL_V)==2))*(dl->nr-1+(dl->flag & DL_CYCL_U)); 00832 } 00833 else if(dl->type==DL_INDEX3) { 00834 totvert+= dl->nr; 00835 totvlak+= dl->parts; 00836 } 00837 dl= dl->next; 00838 } 00839 00840 if(totvert==0) { 00841 /* error("can't convert"); */ 00842 /* Make Sure you check ob->data is a curve */ 00843 return -1; 00844 } 00845 00846 *allvert= mvert= MEM_callocN(sizeof (MVert) * totvert, "nurbs_init mvert"); 00847 *allface= mface= MEM_callocN(sizeof (MFace) * totvlak, "nurbs_init mface"); 00848 00849 /* verts and faces */ 00850 vertcount= 0; 00851 00852 dl= dispbase->first; 00853 while(dl) { 00854 int smooth= dl->rt & CU_SMOOTH ? 1 : 0; 00855 00856 if(dl->type==DL_SEGM) { 00857 startvert= vertcount; 00858 a= dl->parts*dl->nr; 00859 data= dl->verts; 00860 while(a--) { 00861 VECCOPY(mvert->co, data); 00862 data+=3; 00863 vertcount++; 00864 mvert++; 00865 } 00866 00867 for(a=0; a<dl->parts; a++) { 00868 ofs= a*dl->nr; 00869 for(b=1; b<dl->nr; b++) { 00870 mface->v1= startvert+ofs+b-1; 00871 mface->v2= startvert+ofs+b; 00872 if(smooth) mface->flag |= ME_SMOOTH; 00873 mface++; 00874 } 00875 } 00876 00877 } 00878 else if(dl->type==DL_POLY) { 00879 if(conv_polys) { 00880 startvert= vertcount; 00881 a= dl->parts*dl->nr; 00882 data= dl->verts; 00883 while(a--) { 00884 VECCOPY(mvert->co, data); 00885 data+=3; 00886 vertcount++; 00887 mvert++; 00888 } 00889 00890 for(a=0; a<dl->parts; a++) { 00891 ofs= a*dl->nr; 00892 for(b=0; b<dl->nr; b++) { 00893 mface->v1= startvert+ofs+b; 00894 if(b==dl->nr-1) mface->v2= startvert+ofs; 00895 else mface->v2= startvert+ofs+b+1; 00896 if(smooth) mface->flag |= ME_SMOOTH; 00897 mface++; 00898 } 00899 } 00900 } 00901 } 00902 else if(dl->type==DL_INDEX3) { 00903 startvert= vertcount; 00904 a= dl->nr; 00905 data= dl->verts; 00906 while(a--) { 00907 VECCOPY(mvert->co, data); 00908 data+=3; 00909 vertcount++; 00910 mvert++; 00911 } 00912 00913 a= dl->parts; 00914 index= dl->index; 00915 while(a--) { 00916 mface->v1= startvert+index[0]; 00917 mface->v2= startvert+index[2]; 00918 mface->v3= startvert+index[1]; 00919 mface->v4= 0; 00920 mface->mat_nr= (unsigned char)dl->col; 00921 test_index_face(mface, NULL, 0, 3); 00922 00923 if(smooth) mface->flag |= ME_SMOOTH; 00924 mface++; 00925 index+= 3; 00926 } 00927 00928 00929 } 00930 else if(dl->type==DL_SURF) { 00931 startvert= vertcount; 00932 a= dl->parts*dl->nr; 00933 data= dl->verts; 00934 while(a--) { 00935 VECCOPY(mvert->co, data); 00936 data+=3; 00937 vertcount++; 00938 mvert++; 00939 } 00940 00941 for(a=0; a<dl->parts; a++) { 00942 00943 if( (dl->flag & DL_CYCL_V)==0 && a==dl->parts-1) break; 00944 00945 if(dl->flag & DL_CYCL_U) { /* p2 -> p1 -> */ 00946 p1= startvert+ dl->nr*a; /* p4 -> p3 -> */ 00947 p2= p1+ dl->nr-1; /* -----> next row */ 00948 p3= p1+ dl->nr; 00949 p4= p2+ dl->nr; 00950 b= 0; 00951 } 00952 else { 00953 p2= startvert+ dl->nr*a; 00954 p1= p2+1; 00955 p4= p2+ dl->nr; 00956 p3= p1+ dl->nr; 00957 b= 1; 00958 } 00959 if( (dl->flag & DL_CYCL_V) && a==dl->parts-1) { 00960 p3-= dl->parts*dl->nr; 00961 p4-= dl->parts*dl->nr; 00962 } 00963 00964 for(; b<dl->nr; b++) { 00965 mface->v1= p1; 00966 mface->v2= p3; 00967 mface->v3= p4; 00968 mface->v4= p2; 00969 mface->mat_nr= (unsigned char)dl->col; 00970 test_index_face(mface, NULL, 0, 4); 00971 00972 if(smooth) mface->flag |= ME_SMOOTH; 00973 mface++; 00974 00975 p4= p3; 00976 p3++; 00977 p2= p1; 00978 p1++; 00979 } 00980 } 00981 00982 } 00983 00984 dl= dl->next; 00985 } 00986 00987 *_totvert= totvert; 00988 *_totface= totvlak; 00989 00990 make_edges_mdata(*allvert, *allface, totvert, totvlak, 0, alledge, _totedge); 00991 mfaces_strip_loose(*allface, _totface); 00992 00993 return 0; 00994 } 00995 00996 /* this may fail replacing ob->data, be sure to check ob->type */ 00997 void nurbs_to_mesh(Object *ob) 00998 { 00999 Main *bmain= G.main; 01000 Object *ob1; 01001 DerivedMesh *dm= ob->derivedFinal; 01002 Mesh *me; 01003 Curve *cu; 01004 MVert *allvert= NULL; 01005 MEdge *alledge= NULL; 01006 MFace *allface= NULL; 01007 int totvert, totedge, totface; 01008 01009 cu= ob->data; 01010 01011 if (dm == NULL) { 01012 if (nurbs_to_mdata (ob, &allvert, &totvert, &alledge, &totedge, &allface, &totface) != 0) { 01013 /* Error initializing */ 01014 return; 01015 } 01016 01017 /* make mesh */ 01018 me= add_mesh("Mesh"); 01019 me->totvert= totvert; 01020 me->totface= totface; 01021 me->totedge= totedge; 01022 01023 me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, allvert, me->totvert); 01024 me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, allface, me->totface); 01025 me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, alledge, me->totedge); 01026 01027 mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); 01028 } else { 01029 me= add_mesh("Mesh"); 01030 DM_to_mesh(dm, me); 01031 } 01032 01033 me->totcol= cu->totcol; 01034 me->mat= cu->mat; 01035 01036 tex_space_mesh(me); 01037 01038 cu->mat= NULL; 01039 cu->totcol= 0; 01040 01041 if(ob->data) { 01042 free_libblock(&bmain->curve, ob->data); 01043 } 01044 ob->data= me; 01045 ob->type= OB_MESH; 01046 01047 /* other users */ 01048 ob1= bmain->object.first; 01049 while(ob1) { 01050 if(ob1->data==cu) { 01051 ob1->type= OB_MESH; 01052 01053 ob1->data= ob->data; 01054 id_us_plus((ID *)ob->data); 01055 } 01056 ob1= ob1->id.next; 01057 } 01058 } 01059 01060 typedef struct EdgeLink { 01061 Link *next, *prev; 01062 void *edge; 01063 } EdgeLink; 01064 01065 typedef struct VertLink { 01066 Link *next, *prev; 01067 int index; 01068 } VertLink; 01069 01070 static void prependPolyLineVert(ListBase *lb, int index) 01071 { 01072 VertLink *vl= MEM_callocN(sizeof(VertLink), "VertLink"); 01073 vl->index = index; 01074 BLI_addhead(lb, vl); 01075 } 01076 01077 static void appendPolyLineVert(ListBase *lb, int index) 01078 { 01079 VertLink *vl= MEM_callocN(sizeof(VertLink), "VertLink"); 01080 vl->index = index; 01081 BLI_addtail(lb, vl); 01082 } 01083 01084 void mesh_to_curve(Scene *scene, Object *ob) 01085 { 01086 /* make new mesh data from the original copy */ 01087 DerivedMesh *dm= mesh_get_derived_final(scene, ob, CD_MASK_MESH); 01088 01089 MVert *mverts= dm->getVertArray(dm); 01090 MEdge *med, *medge= dm->getEdgeArray(dm); 01091 MFace *mf, *mface= dm->getFaceArray(dm); 01092 01093 int totedge = dm->getNumEdges(dm); 01094 int totface = dm->getNumFaces(dm); 01095 int totedges = 0; 01096 int i, needsFree = 0; 01097 01098 /* only to detect edge polylines */ 01099 EdgeHash *eh = BLI_edgehash_new(); 01100 EdgeHash *eh_edge = BLI_edgehash_new(); 01101 01102 01103 ListBase edges = {NULL, NULL}; 01104 01105 /* create edges from all faces (so as to find edges not in any faces) */ 01106 mf= mface; 01107 for (i = 0; i < totface; i++, mf++) { 01108 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) 01109 BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); 01110 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) 01111 BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); 01112 01113 if (mf->v4) { 01114 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) 01115 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); 01116 if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) 01117 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); 01118 } else { 01119 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) 01120 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); 01121 } 01122 } 01123 01124 med= medge; 01125 for(i=0; i<totedge; i++, med++) { 01126 if (!BLI_edgehash_haskey(eh, med->v1, med->v2)) { 01127 EdgeLink *edl= MEM_callocN(sizeof(EdgeLink), "EdgeLink"); 01128 01129 BLI_edgehash_insert(eh_edge, med->v1, med->v2, NULL); 01130 edl->edge= med; 01131 01132 BLI_addtail(&edges, edl); totedges++; 01133 } 01134 } 01135 BLI_edgehash_free(eh_edge, NULL); 01136 BLI_edgehash_free(eh, NULL); 01137 01138 if(edges.first) { 01139 Curve *cu = add_curve(ob->id.name+2, OB_CURVE); 01140 cu->flag |= CU_3D; 01141 01142 while(edges.first) { 01143 /* each iteration find a polyline and add this as a nurbs poly spline */ 01144 01145 ListBase polyline = {NULL, NULL}; /* store a list of VertLink's */ 01146 int closed = FALSE; 01147 int totpoly= 0; 01148 MEdge *med_current= ((EdgeLink *)edges.last)->edge; 01149 int startVert= med_current->v1; 01150 int endVert= med_current->v2; 01151 int ok= TRUE; 01152 01153 appendPolyLineVert(&polyline, startVert); totpoly++; 01154 appendPolyLineVert(&polyline, endVert); totpoly++; 01155 BLI_freelinkN(&edges, edges.last); totedges--; 01156 01157 while(ok) { /* while connected edges are found... */ 01158 ok = FALSE; 01159 i= totedges; 01160 while(i) { 01161 EdgeLink *edl; 01162 01163 i-=1; 01164 edl= BLI_findlink(&edges, i); 01165 med= edl->edge; 01166 01167 if(med->v1==endVert) { 01168 endVert = med->v2; 01169 appendPolyLineVert(&polyline, med->v2); totpoly++; 01170 BLI_freelinkN(&edges, edl); totedges--; 01171 ok= TRUE; 01172 } 01173 else if(med->v2==endVert) { 01174 endVert = med->v1; 01175 appendPolyLineVert(&polyline, endVert); totpoly++; 01176 BLI_freelinkN(&edges, edl); totedges--; 01177 ok= TRUE; 01178 } 01179 else if(med->v1==startVert) { 01180 startVert = med->v2; 01181 prependPolyLineVert(&polyline, startVert); totpoly++; 01182 BLI_freelinkN(&edges, edl); totedges--; 01183 ok= TRUE; 01184 } 01185 else if(med->v2==startVert) { 01186 startVert = med->v1; 01187 prependPolyLineVert(&polyline, startVert); totpoly++; 01188 BLI_freelinkN(&edges, edl); totedges--; 01189 ok= TRUE; 01190 } 01191 } 01192 } 01193 01194 /* Now we have a polyline, make into a curve */ 01195 if(startVert==endVert) { 01196 BLI_freelinkN(&polyline, polyline.last); 01197 totpoly--; 01198 closed = TRUE; 01199 } 01200 01201 /* --- nurbs --- */ 01202 { 01203 Nurb *nu; 01204 BPoint *bp; 01205 VertLink *vl; 01206 01207 /* create new 'nurb' within the curve */ 01208 nu = (Nurb *)MEM_callocN(sizeof(Nurb), "MeshNurb"); 01209 01210 nu->pntsu= totpoly; 01211 nu->pntsv= 1; 01212 nu->orderu= 4; 01213 nu->flagu= CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC:0); /* endpoint */ 01214 nu->resolu= 12; 01215 01216 nu->bp= (BPoint *)MEM_callocN(sizeof(BPoint)*totpoly, "bpoints"); 01217 01218 /* add points */ 01219 vl= polyline.first; 01220 for (i=0, bp=nu->bp; i < totpoly; i++, bp++, vl=(VertLink *)vl->next) { 01221 copy_v3_v3(bp->vec, mverts[vl->index].co); 01222 bp->f1= SELECT; 01223 bp->radius = bp->weight = 1.0; 01224 } 01225 BLI_freelistN(&polyline); 01226 01227 /* add nurb to curve */ 01228 BLI_addtail(&cu->nurb, nu); 01229 } 01230 /* --- done with nurbs --- */ 01231 } 01232 01233 ((Mesh *)ob->data)->id.us--; 01234 ob->data= cu; 01235 ob->type= OB_CURVE; 01236 01237 /* curve objects can't contain DM in usual cases, we could free memory */ 01238 needsFree= 1; 01239 } 01240 01241 dm->needsFree = needsFree; 01242 dm->release(dm); 01243 01244 if (needsFree) { 01245 ob->derivedFinal = NULL; 01246 01247 /* curve object could have got bounding box only in special cases */ 01248 if(ob->bb) { 01249 MEM_freeN(ob->bb); 01250 ob->bb= NULL; 01251 } 01252 } 01253 } 01254 01255 void mesh_delete_material_index(Mesh *me, int index) 01256 { 01257 MFace *mf; 01258 int i; 01259 01260 for (i=0, mf=me->mface; i<me->totface; i++, mf++) { 01261 if (mf->mat_nr && mf->mat_nr>=index) 01262 mf->mat_nr--; 01263 } 01264 } 01265 01266 void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) 01267 { 01268 Mesh *me = meshOb->data; 01269 int i; 01270 01271 for (i=0; i<me->totface; i++) { 01272 MFace *mf = &((MFace*) me->mface)[i]; 01273 01274 if (enableSmooth) { 01275 mf->flag |= ME_SMOOTH; 01276 } else { 01277 mf->flag &= ~ME_SMOOTH; 01278 } 01279 } 01280 01281 mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); 01282 } 01283 01284 void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3]) 01285 { 01286 float (*tnorms)[3]= MEM_callocN(numVerts*sizeof(*tnorms), "tnorms"); 01287 float (*fnors)[3]= (faceNors_r)? faceNors_r: MEM_callocN(sizeof(*fnors)*numFaces, "meshnormals"); 01288 int i; 01289 01290 for(i=0; i<numFaces; i++) { 01291 MFace *mf= &mfaces[i]; 01292 float *f_no= fnors[i]; 01293 float *n4 = (mf->v4)? tnorms[mf->v4]: NULL; 01294 float *c4 = (mf->v4)? mverts[mf->v4].co: NULL; 01295 01296 if(mf->v4) 01297 normal_quad_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co); 01298 else 01299 normal_tri_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co); 01300 01301 accumulate_vertex_normals(tnorms[mf->v1], tnorms[mf->v2], tnorms[mf->v3], n4, 01302 f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, c4); 01303 } 01304 01305 /* following Mesh convention; we use vertex coordinate itself for normal in this case */ 01306 for(i=0; i<numVerts; i++) { 01307 MVert *mv= &mverts[i]; 01308 float *no= tnorms[i]; 01309 01310 if(normalize_v3(no) == 0.0f) 01311 normalize_v3_v3(no, mv->co); 01312 01313 normal_float_to_short_v3(mv->no, no); 01314 } 01315 01316 MEM_freeN(tnorms); 01317 01318 if(fnors != faceNors_r) 01319 MEM_freeN(fnors); 01320 } 01321 01322 float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3] 01323 { 01324 int i, numVerts = me->totvert; 01325 float (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos1"); 01326 01327 if (numVerts_r) *numVerts_r = numVerts; 01328 for (i=0; i<numVerts; i++) 01329 VECCOPY(cos[i], me->mvert[i].co); 01330 01331 return cos; 01332 } 01333 01334 UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit) 01335 { 01336 UvVertMap *vmap; 01337 UvMapVert *buf; 01338 MFace *mf; 01339 MTFace *tf; 01340 unsigned int a; 01341 int i, totuv, nverts; 01342 01343 totuv = 0; 01344 01345 /* generate UvMapVert array */ 01346 mf= mface; 01347 tf= tface; 01348 for(a=0; a<totface; a++, mf++, tf++) 01349 if(!selected || (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL))) 01350 totuv += (mf->v4)? 4: 3; 01351 01352 if(totuv==0) 01353 return NULL; 01354 01355 vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap"); 01356 if (!vmap) 01357 return NULL; 01358 01359 vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totvert, "UvMapVert*"); 01360 buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert"); 01361 01362 if (!vmap->vert || !vmap->buf) { 01363 free_uv_vert_map(vmap); 01364 return NULL; 01365 } 01366 01367 mf= mface; 01368 tf= tface; 01369 for(a=0; a<totface; a++, mf++, tf++) { 01370 if(!selected || (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL))) { 01371 nverts= (mf->v4)? 4: 3; 01372 01373 for(i=0; i<nverts; i++) { 01374 buf->tfindex= i; 01375 buf->f= a; 01376 buf->separate = 0; 01377 buf->next= vmap->vert[*(&mf->v1 + i)]; 01378 vmap->vert[*(&mf->v1 + i)]= buf; 01379 buf++; 01380 } 01381 } 01382 } 01383 01384 /* sort individual uvs for each vert */ 01385 tf= tface; 01386 for(a=0; a<totvert; a++) { 01387 UvMapVert *newvlist= NULL, *vlist=vmap->vert[a]; 01388 UvMapVert *iterv, *v, *lastv, *next; 01389 float *uv, *uv2, uvdiff[2]; 01390 01391 while(vlist) { 01392 v= vlist; 01393 vlist= vlist->next; 01394 v->next= newvlist; 01395 newvlist= v; 01396 01397 uv= (tf+v->f)->uv[v->tfindex]; 01398 lastv= NULL; 01399 iterv= vlist; 01400 01401 while(iterv) { 01402 next= iterv->next; 01403 01404 uv2= (tf+iterv->f)->uv[iterv->tfindex]; 01405 sub_v2_v2v2(uvdiff, uv2, uv); 01406 01407 01408 if(fabsf(uv[0]-uv2[0]) < limit[0] && fabsf(uv[1]-uv2[1]) < limit[1]) { 01409 if(lastv) lastv->next= next; 01410 else vlist= next; 01411 iterv->next= newvlist; 01412 newvlist= iterv; 01413 } 01414 else 01415 lastv=iterv; 01416 01417 iterv= next; 01418 } 01419 01420 newvlist->separate = 1; 01421 } 01422 01423 vmap->vert[a]= newvlist; 01424 } 01425 01426 return vmap; 01427 } 01428 01429 UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v) 01430 { 01431 return vmap->vert[v]; 01432 } 01433 01434 void free_uv_vert_map(UvVertMap *vmap) 01435 { 01436 if (vmap) { 01437 if (vmap->vert) MEM_freeN(vmap->vert); 01438 if (vmap->buf) MEM_freeN(vmap->buf); 01439 MEM_freeN(vmap); 01440 } 01441 } 01442 01443 /* Generates a map where the key is the vertex and the value is a list 01444 of faces that use that vertex as a corner. The lists are allocated 01445 from one memory pool. */ 01446 void create_vert_face_map(ListBase **map, IndexNode **mem, const MFace *mface, const int totvert, const int totface) 01447 { 01448 int i,j; 01449 IndexNode *node = NULL; 01450 01451 (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map"); 01452 (*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem"); 01453 node = *mem; 01454 01455 /* Find the users */ 01456 for(i = 0; i < totface; ++i){ 01457 for(j = 0; j < (mface[i].v4?4:3); ++j, ++node) { 01458 node->index = i; 01459 BLI_addtail(&(*map)[((unsigned int*)(&mface[i]))[j]], node); 01460 } 01461 } 01462 } 01463 01464 /* Generates a map where the key is the vertex and the value is a list 01465 of edges that use that vertex as an endpoint. The lists are allocated 01466 from one memory pool. */ 01467 void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, const int totvert, const int totedge) 01468 { 01469 int i, j; 01470 IndexNode *node = NULL; 01471 01472 (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map"); 01473 (*mem) = MEM_callocN(sizeof(IndexNode) * totedge * 2, "vert edge map mem"); 01474 node = *mem; 01475 01476 /* Find the users */ 01477 for(i = 0; i < totedge; ++i){ 01478 for(j = 0; j < 2; ++j, ++node) { 01479 node->index = i; 01480 BLI_addtail(&(*map)[((unsigned int*)(&medge[i].v1))[j]], node); 01481 } 01482 } 01483 } 01484 01485 /* Partial Mesh Visibility */ 01486 PartialVisibility *mesh_pmv_copy(PartialVisibility *pmv) 01487 { 01488 PartialVisibility *n= MEM_dupallocN(pmv); 01489 n->vert_map= MEM_dupallocN(pmv->vert_map); 01490 n->edge_map= MEM_dupallocN(pmv->edge_map); 01491 n->old_edges= MEM_dupallocN(pmv->old_edges); 01492 n->old_faces= MEM_dupallocN(pmv->old_faces); 01493 return n; 01494 } 01495 01496 void mesh_pmv_free(PartialVisibility *pv) 01497 { 01498 MEM_freeN(pv->vert_map); 01499 MEM_freeN(pv->edge_map); 01500 MEM_freeN(pv->old_faces); 01501 MEM_freeN(pv->old_edges); 01502 MEM_freeN(pv); 01503 } 01504 01505 void mesh_pmv_revert(Mesh *me) 01506 { 01507 if(me->pv) { 01508 unsigned i; 01509 MVert *nve, *old_verts; 01510 01511 /* Reorder vertices */ 01512 nve= me->mvert; 01513 old_verts = MEM_mallocN(sizeof(MVert)*me->pv->totvert,"PMV revert verts"); 01514 for(i=0; i<me->pv->totvert; ++i) 01515 old_verts[i]= nve[me->pv->vert_map[i]]; 01516 01517 /* Restore verts, edges and faces */ 01518 CustomData_free_layer_active(&me->vdata, CD_MVERT, me->totvert); 01519 CustomData_free_layer_active(&me->edata, CD_MEDGE, me->totedge); 01520 CustomData_free_layer_active(&me->fdata, CD_MFACE, me->totface); 01521 01522 CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, old_verts, me->pv->totvert); 01523 CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, me->pv->old_edges, me->pv->totedge); 01524 CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, me->pv->old_faces, me->pv->totface); 01525 mesh_update_customdata_pointers(me); 01526 01527 me->totvert= me->pv->totvert; 01528 me->totedge= me->pv->totedge; 01529 me->totface= me->pv->totface; 01530 01531 me->pv->old_edges= NULL; 01532 me->pv->old_faces= NULL; 01533 01534 /* Free maps */ 01535 MEM_freeN(me->pv->edge_map); 01536 me->pv->edge_map= NULL; 01537 MEM_freeN(me->pv->vert_map); 01538 me->pv->vert_map= NULL; 01539 } 01540 } 01541 01542 void mesh_pmv_off(Mesh *me) 01543 { 01544 if(me->pv) { 01545 mesh_pmv_revert(me); 01546 MEM_freeN(me->pv); 01547 me->pv= NULL; 01548 } 01549 } 01550 01551 /* basic vertex data functions */ 01552 int minmax_mesh(Mesh *me, float min[3], float max[3]) 01553 { 01554 int i= me->totvert; 01555 MVert *mvert; 01556 for(mvert= me->mvert; i--; mvert++) { 01557 DO_MINMAX(mvert->co, min, max); 01558 } 01559 01560 return (me->totvert != 0); 01561 } 01562 01563 int mesh_center_median(Mesh *me, float cent[3]) 01564 { 01565 int i= me->totvert; 01566 MVert *mvert; 01567 zero_v3(cent); 01568 for(mvert= me->mvert; i--; mvert++) { 01569 add_v3_v3(cent, mvert->co); 01570 } 01571 /* otherwise we get NAN for 0 verts */ 01572 if(me->totvert) { 01573 mul_v3_fl(cent, 1.0f/(float)me->totvert); 01574 } 01575 01576 return (me->totvert != 0); 01577 } 01578 01579 int mesh_center_bounds(Mesh *me, float cent[3]) 01580 { 01581 float min[3], max[3]; 01582 INIT_MINMAX(min, max); 01583 if(minmax_mesh(me, min, max)) { 01584 mid_v3_v3v3(cent, min, max); 01585 return 1; 01586 } 01587 01588 return 0; 01589 } 01590 01591 void mesh_translate(Mesh *me, float offset[3], int do_keys) 01592 { 01593 int i= me->totvert; 01594 MVert *mvert; 01595 for(mvert= me->mvert; i--; mvert++) { 01596 add_v3_v3(mvert->co, offset); 01597 } 01598 01599 if (do_keys && me->key) { 01600 KeyBlock *kb; 01601 for (kb=me->key->block.first; kb; kb=kb->next) { 01602 float *fp= kb->data; 01603 for (i= kb->totelem; i--; fp+=3) { 01604 add_v3_v3(fp, offset); 01605 } 01606 } 01607 } 01608 }