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