Blender V2.61 - r43446
|
00001 /* 00002 * BME_tools.c jan 2007 00003 * 00004 * Functions for changing the topology of a mesh. 00005 * 00006 * 00007 * ***** BEGIN GPL LICENSE BLOCK ***** 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 * 00023 * The Original Code is Copyright (C) 2004 Blender Foundation. 00024 * All rights reserved. 00025 * 00026 * The Original Code is: all of this file. 00027 * 00028 * Contributor(s): Geoffrey Bantle and Levi Schooley. 00029 * 00030 * ***** END GPL LICENSE BLOCK ***** 00031 */ 00032 00038 #include <math.h> 00039 00040 #include "MEM_guardedalloc.h" 00041 00042 #include "DNA_meshdata_types.h" 00043 #include "DNA_object_types.h" 00044 00045 #include "BLI_math.h" 00046 #include "BLI_utildefines.h" 00047 00048 #include "BKE_bmesh.h" 00049 00050 /*split this all into a seperate bevel.c file in src*/ 00051 00052 /* ------- Bevel code starts here -------- */ 00053 00054 BME_TransData_Head *BME_init_transdata(int bufsize) { 00055 BME_TransData_Head *td; 00056 00057 td = MEM_callocN(sizeof(BME_TransData_Head), "BMesh transdata header"); 00058 td->gh = BLI_ghash_new(BLI_ghashutil_ptrhash,BLI_ghashutil_ptrcmp, "BME_init_transdata gh"); 00059 td->ma = BLI_memarena_new(bufsize, "BME_TransData arena"); 00060 BLI_memarena_use_calloc(td->ma); 00061 00062 return td; 00063 } 00064 00065 void BME_free_transdata(BME_TransData_Head *td) { 00066 BLI_ghash_free(td->gh,NULL,NULL); 00067 BLI_memarena_free(td->ma); 00068 MEM_freeN(td); 00069 } 00070 00071 BME_TransData *BME_assign_transdata( 00072 BME_TransData_Head *td, BME_Mesh *bm, BME_Vert *v, 00073 float *co, float *org, float *vec, float *loc, 00074 float factor, float weight, float maxfactor, float *max) 00075 { 00076 BME_TransData *vtd; 00077 int is_new = 0; 00078 00079 if (v == NULL) return NULL; 00080 00081 if ((vtd = BLI_ghash_lookup(td->gh, v)) == NULL && bm != NULL) { 00082 vtd = BLI_memarena_alloc(td->ma, sizeof(*vtd)); 00083 BLI_ghash_insert(td->gh, v, vtd); 00084 td->len++; 00085 is_new = 1; 00086 } 00087 00088 vtd->bm = bm; 00089 vtd->v = v; 00090 00091 if (co != NULL) { 00092 copy_v3_v3(vtd->co, co); 00093 } 00094 00095 if (org == NULL && is_new) { 00096 copy_v3_v3(vtd->org, v->co); /* default */ 00097 } 00098 else if (org != NULL) { 00099 copy_v3_v3(vtd->org,org); 00100 } 00101 00102 if (vec != NULL) { 00103 copy_v3_v3(vtd->vec,vec); 00104 normalize_v3(vtd->vec); 00105 } 00106 00107 vtd->loc = loc; 00108 00109 vtd->factor = factor; 00110 vtd->weight = weight; 00111 vtd->maxfactor = maxfactor; 00112 vtd->max = max; 00113 00114 return vtd; 00115 } 00116 00117 BME_TransData *BME_get_transdata(BME_TransData_Head *td, BME_Vert *v) { 00118 BME_TransData *vtd; 00119 vtd = BLI_ghash_lookup(td->gh, v); 00120 return vtd; 00121 } 00122 00123 /* a hack (?) to use the transdata memarena to allocate floats for use with the max limits */ 00124 float *BME_new_transdata_float(BME_TransData_Head *td) { 00125 return BLI_memarena_alloc(td->ma, sizeof(float)); 00126 } 00127 00128 static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) { 00129 BME_Edge *e, *oe; 00130 BME_Loop *l; 00131 int len, count, flag; 00132 00133 if (v->edge == NULL) { 00134 /* loose vert */ 00135 return 1; 00136 } 00137 00138 /* count edges while looking for non-manifold edges */ 00139 oe = v->edge; 00140 for (len=0,e=v->edge; e != oe || (e == oe && len == 0); len++,e=BME_disk_nextedge(e,v)) { 00141 if (e->loop == NULL) { 00142 /* loose edge */ 00143 return 1; 00144 } 00145 00146 if (BME_cycle_length(&(e->loop->radial)) > 2) { 00147 /* edge shared by more than two faces */ 00148 return 1; 00149 } 00150 } 00151 00152 count = 1; 00153 flag = 1; 00154 e = NULL; 00155 oe = v->edge; 00156 l = oe->loop; 00157 while(e != oe) { 00158 if (l->v == v) l = l->prev; 00159 else l = l->next; 00160 e = l->e; 00161 count++; /* count the edges */ 00162 00163 if (flag && l->radial.next->data == l) { 00164 /* we've hit the edge of an open mesh, reset once */ 00165 flag = 0; 00166 count = 1; 00167 oe = e; 00168 e = NULL; 00169 l = oe->loop; 00170 } 00171 else if (l->radial.next->data == l) { 00172 /* break the loop */ 00173 e = oe; 00174 } 00175 else { 00176 l = l->radial.next->data; 00177 } 00178 } 00179 00180 if (count < len) { 00181 /* vert shared by multiple regions */ 00182 return 1; 00183 } 00184 00185 return 0; 00186 } 00187 00188 /* a wrapper for BME_JFKE that [for now just] checks to 00189 * make sure loop directions are compatible */ 00190 static BME_Poly *BME_JFKE_safe(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e) { 00191 BME_Loop *l1, *l2; 00192 00193 l1 = e->loop; 00194 l2 = l1->radial.next->data; 00195 if (l1->v == l2->v) { 00196 BME_loop_reverse(bm, f2); 00197 } 00198 00199 return BME_JFKE(bm, f1, f2, e); 00200 } 00201 00202 /* a wrapper for BME_SFME that transfers element flags */ 00203 static BME_Poly *BME_split_face(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Loop **nl, BME_Edge *example) { 00204 BME_Poly *nf; 00205 nf = BME_SFME(bm,f,v1,v2,nl); 00206 nf->flag = f->flag; 00207 /* if the edge was selected, select this face, too */ 00208 if (example && (example->flag & SELECT)) f->flag |= ME_FACE_SEL; 00209 nf->h = f->h; 00210 nf->mat_nr = f->mat_nr; 00211 if (nl && example) { 00212 (*nl)->e->flag = example->flag; 00213 (*nl)->e->h = example->h; 00214 (*nl)->e->crease = example->crease; 00215 (*nl)->e->bweight = example->bweight; 00216 } 00217 00218 return nf; 00219 } 00220 00221 00222 #if 0 00223 static void BME_data_interp_from_verts(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, float fac) 00224 { 00225 void *src[2]; 00226 float w[2]; 00227 if (v1->data && v2->data) { 00228 src[0]= v1->data; 00229 src[1]= v2->data; 00230 w[0] = 1.0f-fac; 00231 w[1] = fac; 00232 CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->data); 00233 } 00234 } 00235 #endif 00236 00237 00238 static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *UNUSED(v2), BME_Vert *v, BME_Edge *e1, float fac){ 00239 void *src[2]; 00240 float w[2]; 00241 BME_Loop *l=NULL, *v1loop = NULL, *vloop = NULL, *v2loop = NULL; 00242 00243 w[0] = 1.0f - fac; 00244 w[1] = fac; 00245 00246 if(!e1->loop) return; 00247 l = e1->loop; 00248 do{ 00249 if(l->v == v1){ 00250 v1loop = l; 00251 vloop = v1loop->next; 00252 v2loop = vloop->next; 00253 }else if(l->v == v){ 00254 v1loop = l->next; 00255 vloop = l; 00256 v2loop = l->prev; 00257 00258 } 00259 00260 src[0] = v1loop->data; 00261 src[1] = v2loop->data; 00262 00263 CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, vloop->data); 00264 l = l->radial.next->data; 00265 }while(l!=e1->loop); 00266 } 00267 00268 00269 /* a wrapper for BME_SEMV that transfers element flags */ /*add custom data interpolation in here!*/ 00270 static BME_Vert *BME_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Edge **ne, float percent) { 00271 BME_Vert *nv, *v2; 00272 float len; 00273 00274 v2 = BME_edge_getothervert(e,v); 00275 nv = BME_SEMV(bm,v,e,ne); 00276 if (nv == NULL) return NULL; 00277 VECSUB(nv->co,v2->co,v->co); 00278 len = len_v3(nv->co); 00279 VECADDFAC(nv->co,v->co,nv->co,len*percent); 00280 nv->flag = v->flag; 00281 nv->bweight = v->bweight; 00282 if (ne) { 00283 (*ne)->flag = e->flag; 00284 (*ne)->h = e->h; 00285 (*ne)->crease = e->crease; 00286 (*ne)->bweight = e->bweight; 00287 } 00288 /*v->nv->v2*/ 00289 BME_data_facevert_edgesplit(bm,v2, v, nv, e, 0.75); 00290 return nv; 00291 } 00292 00293 static void BME_collapse_vert(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv, float fac){ 00294 void *src[2]; 00295 float w[2]; 00296 BME_Loop *l=NULL, *kvloop=NULL, *tvloop=NULL; 00297 BME_Vert *tv = BME_edge_getothervert(ke,kv); 00298 00299 w[0] = 1.0f - fac; 00300 w[1] = fac; 00301 00302 if(ke->loop){ 00303 l = ke->loop; 00304 do{ 00305 if(l->v == tv && l->next->v == kv){ 00306 tvloop = l; 00307 kvloop = l->next; 00308 00309 src[0] = kvloop->data; 00310 src[1] = tvloop->data; 00311 CustomData_bmesh_interp(&bm->ldata, src,w, NULL, 2, kvloop->data); 00312 } 00313 l=l->radial.next->data; 00314 }while(l!=ke->loop); 00315 } 00316 BME_JEKV(bm,ke,kv); 00317 } 00318 00319 00320 00321 static int BME_bevel_is_split_vert(BME_Loop *l) { 00322 /* look for verts that have already been added to the edge when 00323 * beveling other polys; this can be determined by testing the 00324 * vert and the edges around it for originality 00325 */ 00326 if ((l->v->tflag1 & BME_BEVEL_ORIG)==0 00327 && (l->e->tflag1 & BME_BEVEL_ORIG) 00328 && (l->prev->e->tflag1 & BME_BEVEL_ORIG)) 00329 { 00330 return 1; 00331 } 00332 return 0; 00333 } 00334 00335 /* get a vector, vec, that points from v1->co to wherever makes sense to 00336 * the bevel operation as a whole based on the relationship between v1 and v2 00337 * (won't necessarily be a vec from v1->co to v2->co, though it probably will be); 00338 * the return value is -1 for failure, 0 if we used vert co's, and 1 if we used transform origins */ 00339 static int BME_bevel_get_vec(float *vec, BME_Vert *v1, BME_Vert *v2, BME_TransData_Head *td) 00340 { 00341 BME_TransData *vtd1, *vtd2; 00342 00343 vtd1 = BME_get_transdata(td,v1); 00344 vtd2 = BME_get_transdata(td,v2); 00345 if (!vtd1 || !vtd2) { 00346 //printf("BME_bevel_get_vec() got called without proper BME_TransData\n"); 00347 return -1; 00348 } 00349 00350 /* compare the transform origins to see if we can use the vert co's; 00351 * if they belong to different origins, then we will use the origins to determine 00352 * the vector */ 00353 if (compare_v3v3(vtd1->org,vtd2->org,0.000001f)) { 00354 sub_v3_v3v3(vec, v2->co, v1->co); 00355 if (len_v3(vec) < 0.000001f) { 00356 zero_v3(vec); 00357 } 00358 return 0; 00359 } 00360 else { 00361 sub_v3_v3v3(vec,vtd2->org,vtd1->org); 00362 if (len_v3(vec) < 0.000001f) { 00363 zero_v3(vec); 00364 } 00365 return 1; 00366 } 00367 } 00368 00369 /* "Projects" a vector perpendicular to vec2 against vec1, such that 00370 * the projected vec1 + vec2 has a min distance of 1 from the "edge" defined by vec2. 00371 * note: the direction, is_forward, is used in conjunction with up_vec to determine 00372 * whether this is a convex or concave corner. If it is a concave corner, it will 00373 * be projected "backwards." If vec1 is before vec2, is_forward should be 0 (we are projecting backwards). 00374 * vec1 is the vector to project onto (expected to be normalized) 00375 * vec2 is the direction of projection (pointing away from vec1) 00376 * up_vec is used for orientation (expected to be normalized) 00377 * returns the length of the projected vector that lies along vec1 */ 00378 static float BME_bevel_project_vec(float *vec1, float *vec2, float *up_vec, int is_forward, BME_TransData_Head *UNUSED(td)) 00379 { 00380 float factor, vec3[3], tmp[3],c1,c2; 00381 00382 cross_v3_v3v3(tmp,vec1,vec2); 00383 normalize_v3(tmp); 00384 factor = dot_v3v3(up_vec,tmp); 00385 if ((factor > 0 && is_forward) || (factor < 0 && !is_forward)) { 00386 cross_v3_v3v3(vec3,vec2,tmp); /* hmm, maybe up_vec should be used instead of tmp */ 00387 } 00388 else { 00389 cross_v3_v3v3(vec3,tmp,vec2); /* hmm, maybe up_vec should be used instead of tmp */ 00390 } 00391 normalize_v3(vec3); 00392 c1 = dot_v3v3(vec3,vec1); 00393 c2 = dot_v3v3(vec1,vec1); 00394 if (fabsf(c1) < 0.000001f || fabsf(c2) < 0.000001f) { 00395 factor = 0.0f; 00396 } 00397 else { 00398 factor = c2/c1; 00399 } 00400 00401 return factor; 00402 } 00403 00404 /* BME_bevel_split_edge() is the main math work-house; its responsibilities are: 00405 * using the vert and the loop passed, get or make the split vert, set its coordinates 00406 * and transform properties, and set the max limits. 00407 * Finally, return the split vert. */ 00408 static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, BME_Loop *l, float *up_vec, float value, BME_TransData_Head *td) { 00409 BME_TransData *vtd, *vtd1 /* , *vtd2 */ /* UNUSED */; 00410 BME_Vert *sv, *v2, *v3 /* , *ov */ /* UNUSED */; 00411 BME_Loop *lv1, *lv2; 00412 BME_Edge *ne, *e1, *e2; 00413 float maxfactor, scale, len, dis, vec1[3], vec2[3], t_up_vec[3]; 00414 int is_edge, forward /* , is_split_vert */ /* UNUSED */; 00415 00416 if (l == NULL) { 00417 /* what you call operator overloading in C :) 00418 * I wanted to use the same function for both wire edges and poly loops 00419 * so... here we walk around edges to find the needed verts */ 00420 forward = 1; 00421 /* is_split_vert = 0; */ /* UNUSED */ 00422 if (v->edge == NULL) { 00423 //printf("We can't split a loose vert's edge!\n"); 00424 return NULL; 00425 } 00426 e1 = v->edge; /* we just use the first two edges */ 00427 e2 = BME_disk_nextedge(v->edge, v); 00428 if (e1 == e2) { 00429 //printf("You need at least two edges to use BME_bevel_split_edge()\n"); 00430 return NULL; 00431 } 00432 v2 = BME_edge_getothervert(e1, v); 00433 v3 = BME_edge_getothervert(e2, v); 00434 if (v1 != v2 && v1 != v3) { 00435 //printf("Error: more than 2 edges in v's disk cycle, or v1 does not share an edge with v\n"); 00436 return NULL; 00437 } 00438 if (v1 == v2) { 00439 v2 = v3; 00440 } 00441 else { 00442 e1 = e2; 00443 } 00444 /* ov = BME_edge_getothervert(e1,v); */ /* UNUSED */ 00445 sv = BME_split_edge(bm,v,e1,&ne,0); 00446 //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/ 00447 //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25); 00448 //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25); 00449 BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */ 00450 sv->tflag1 |= BME_BEVEL_BEVEL; 00451 ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */ 00452 BME_bevel_get_vec(vec1,v1,v,td); 00453 BME_bevel_get_vec(vec2,v2,v,td); 00454 cross_v3_v3v3(t_up_vec,vec1,vec2); 00455 normalize_v3(t_up_vec); 00456 up_vec = t_up_vec; 00457 } 00458 else { 00459 /* establish loop direction */ 00460 if (l->v == v) { 00461 forward = 1; 00462 lv1 = l->next; 00463 lv2 = l->prev; 00464 v1 = l->next->v; 00465 v2 = l->prev->v; 00466 } 00467 else if (l->next->v == v) { 00468 forward = 0; 00469 lv1 = l; 00470 lv2 = l->next->next; 00471 v1 = l->v; 00472 v2 = l->next->next->v; 00473 } 00474 else { 00475 //printf("ERROR: BME_bevel_split_edge() - v must be adjacent to l\n"); 00476 return NULL; 00477 } 00478 00479 if (BME_bevel_is_split_vert(lv1)) { 00480 /* is_split_vert = 1; */ /* UNUSED */ 00481 sv = v1; 00482 if (forward) v1 = l->next->next->v; 00483 else v1 = l->prev->v; 00484 } 00485 else { 00486 /* is_split_vert = 0; */ /* UNUSED */ 00487 /* ov = BME_edge_getothervert(l->e,v); */ /* UNUSED */ 00488 sv = BME_split_edge(bm,v,l->e,&ne,0); 00489 //BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/ 00490 //BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25); 00491 //BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25); 00492 BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */ 00493 sv->tflag1 |= BME_BEVEL_BEVEL; 00494 ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */ 00495 } 00496 00497 if (BME_bevel_is_split_vert(lv2)) { 00498 if (forward) v2 = lv2->prev->v; 00499 else v2 = lv2->next->v; 00500 } 00501 } 00502 00503 is_edge = BME_bevel_get_vec(vec1,v,v1,td); /* get the vector we will be projecting onto */ 00504 BME_bevel_get_vec(vec2,v,v2,td); /* get the vector we will be projecting parallel to */ 00505 len = len_v3(vec1); 00506 normalize_v3(vec1); 00507 00508 vtd = BME_get_transdata(td, sv); 00509 vtd1 = BME_get_transdata(td, v); 00510 /* vtd2 = BME_get_transdata(td,v1); */ /* UNUSED */ 00511 00512 if (vtd1->loc == NULL) { 00513 /* this is a vert with data only for calculating initial weights */ 00514 if (vtd1->weight < 0) { 00515 vtd1->weight = 0; 00516 } 00517 scale = vtd1->weight/vtd1->factor; 00518 if (!vtd1->max) { 00519 vtd1->max = BME_new_transdata_float(td); 00520 *vtd1->max = -1; 00521 } 00522 } 00523 else { 00524 scale = vtd1->weight; 00525 } 00526 vtd->max = vtd1->max; 00527 00528 if (is_edge && vtd1->loc != NULL) { 00529 maxfactor = vtd1->maxfactor; 00530 } 00531 else { 00532 maxfactor = scale*BME_bevel_project_vec(vec1,vec2,up_vec,forward,td); 00533 if (vtd->maxfactor > 0 && vtd->maxfactor < maxfactor) { 00534 maxfactor = vtd->maxfactor; 00535 } 00536 } 00537 00538 dis = (v1->tflag1 & BME_BEVEL_ORIG)? len/3 : len/2; 00539 if (is_edge || dis > maxfactor*value) { 00540 dis = maxfactor*value; 00541 } 00542 madd_v3_v3v3fl(sv->co, v->co, vec1, dis); 00543 sub_v3_v3v3(vec1, sv->co, vtd1->org); 00544 dis = len_v3(vec1); 00545 normalize_v3(vec1); 00546 BME_assign_transdata(td, bm, sv, vtd1->org, vtd1->org, vec1, sv->co, dis, scale, maxfactor, vtd->max); 00547 00548 return sv; 00549 } 00550 00551 static float BME_bevel_set_max(BME_Vert *v1, BME_Vert *v2, float value, BME_TransData_Head *td) { 00552 BME_TransData *vtd1, *vtd2; 00553 float max, fac1, fac2, vec1[3], vec2[3], vec3[3]; 00554 00555 BME_bevel_get_vec(vec1,v1,v2,td); 00556 vtd1 = BME_get_transdata(td,v1); 00557 vtd2 = BME_get_transdata(td,v2); 00558 00559 if (vtd1->loc == NULL) { 00560 fac1 = 0; 00561 } 00562 else { 00563 copy_v3_v3(vec2, vtd1->vec); 00564 mul_v3_fl(vec2, vtd1->factor); 00565 if (dot_v3v3(vec1, vec1)) { 00566 project_v3_v3v3(vec2, vec2,vec1); 00567 fac1 = len_v3(vec2) / value; 00568 } 00569 else { 00570 fac1 = 0; 00571 } 00572 } 00573 00574 if (vtd2->loc == NULL) { 00575 fac2 = 0; 00576 } 00577 else { 00578 copy_v3_v3(vec3, vtd2->vec); 00579 mul_v3_fl(vec3, vtd2->factor); 00580 if (dot_v3v3(vec1, vec1)) { 00581 project_v3_v3v3(vec2, vec3, vec1); 00582 fac2 = len_v3(vec2) / value; 00583 } 00584 else { 00585 fac2 = 0; 00586 } 00587 } 00588 00589 if (fac1 || fac2) { 00590 max = len_v3(vec1) / (fac1 + fac2); 00591 if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) { 00592 *vtd1->max = max; 00593 } 00594 if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) { 00595 *vtd2->max = max; 00596 } 00597 } 00598 else { 00599 max = -1; 00600 } 00601 00602 return max; 00603 } 00604 00605 static BME_Vert *BME_bevel_wire(BME_Mesh *bm, BME_Vert *v, float value, int res, int UNUSED(options), BME_TransData_Head *td) { 00606 BME_Vert *ov1, *ov2, *v1, *v2; 00607 00608 ov1 = BME_edge_getothervert(v->edge, v); 00609 ov2 = BME_edge_getothervert(BME_disk_nextedge(v->edge, v), v); 00610 00611 /* split the edges */ 00612 v1 = BME_bevel_split_edge(bm,v,ov1,NULL,NULL,value,td); 00613 v1->tflag1 |= BME_BEVEL_NONMAN; 00614 v2 = BME_bevel_split_edge(bm,v,ov2,NULL,NULL,value,td); 00615 v2->tflag1 |= BME_BEVEL_NONMAN; 00616 00617 if (value > 0.5) { 00618 BME_bevel_set_max(v1,ov1,value,td); 00619 BME_bevel_set_max(v2,ov2,value,td); 00620 } 00621 00622 /* remove the original vert */ 00623 if (res) { 00624 BME_JEKV(bm,v->edge,v); 00625 } 00626 00627 return v1; 00628 } 00629 00630 static BME_Loop *BME_bevel_edge(BME_Mesh *bm, BME_Loop *l, float value, int UNUSED(options), float *up_vec, BME_TransData_Head *td) { 00631 BME_Vert *v1, *v2, *kv; 00632 BME_Loop *kl=NULL, *nl; 00633 BME_Edge *e; 00634 BME_Poly *f; 00635 00636 f = l->f; 00637 e = l->e; 00638 00639 if ((l->e->tflag1 & BME_BEVEL_BEVEL) == 0 00640 && ((l->v->tflag1 & BME_BEVEL_BEVEL) || (l->next->v->tflag1 & BME_BEVEL_BEVEL))) 00641 { /* sanity check */ 00642 return l; 00643 } 00644 00645 /* checks and operations for prev edge */ 00646 /* first, check to see if this edge was inset previously */ 00647 if ((l->prev->e->tflag1 & BME_BEVEL_ORIG) == 0 00648 && (l->v->tflag1 & BME_BEVEL_NONMAN) == 0) { 00649 kl = l->prev->radial.next->data; 00650 if (kl->v == l->v) kl = kl->prev; 00651 else kl = kl->next; 00652 kv = l->v; 00653 } 00654 else { 00655 kv = NULL; 00656 } 00657 /* get/make the first vert to be used in SFME */ 00658 if (l->v->tflag1 & BME_BEVEL_NONMAN){ 00659 v1 = l->v; 00660 } 00661 else { /* we'll need to split the previous edge */ 00662 v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td); 00663 } 00664 /* if we need to clean up geometry... */ 00665 if (kv) { 00666 l = l->next; 00667 if (kl->v == kv) { 00668 BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e); 00669 BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e); 00670 BME_collapse_vert(bm, kl->e, kv, 1.0); 00671 //BME_JEKV(bm,kl->e,kv); 00672 00673 } 00674 else { 00675 BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e); 00676 BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e); 00677 BME_collapse_vert(bm, kl->e, kv, 1.0); 00678 //BME_JEKV(bm,kl->e,kv); 00679 } 00680 l = l->prev; 00681 } 00682 00683 /* checks and operations for the next edge */ 00684 /* first, check to see if this edge was inset previously */ 00685 if ((l->next->e->tflag1 & BME_BEVEL_ORIG) == 0 00686 && (l->next->v->tflag1 & BME_BEVEL_NONMAN) == 0) { 00687 kl = l->next->radial.next->data; 00688 if (kl->v == l->next->v) kl = kl->prev; 00689 else kl = kl->next; 00690 kv = l->next->v; 00691 } 00692 else { 00693 kv = NULL; 00694 } 00695 /* get/make the second vert to be used in SFME */ 00696 if (l->next->v->tflag1 & BME_BEVEL_NONMAN) { 00697 v2 = l->next->v; 00698 } 00699 else { /* we'll need to split the next edge */ 00700 v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td); 00701 } 00702 /* if we need to clean up geometry... */ 00703 if (kv) { 00704 if (kl->v == kv) { 00705 BME_split_face(bm,kl->f,kl->prev->v,kl->next->v,&nl,kl->prev->e); 00706 BME_JFKE(bm,((BME_Loop*)kl->prev->radial.next->data)->f,kl->f,kl->prev->e); 00707 BME_collapse_vert(bm, kl->e, kv, 1.0); 00708 //BME_JEKV(bm,kl->e,kv); 00709 } 00710 else { 00711 BME_split_face(bm,kl->f,kl->next->next->v,kl->v,&nl,kl->next->e); 00712 BME_JFKE(bm,((BME_Loop*)kl->next->radial.next->data)->f,kl->f,kl->next->e); 00713 BME_collapse_vert(bm, kl->e, kv, 1.0); 00714 //BME_JEKV(bm,kl->e,kv); 00715 } 00716 } 00717 00718 if ((v1->tflag1 & BME_BEVEL_NONMAN)==0 || (v2->tflag1 & BME_BEVEL_NONMAN)==0) { 00719 BME_split_face(bm,f,v2,v1,&l,e); 00720 l->e->tflag1 = BME_BEVEL_BEVEL; 00721 l = l->radial.next->data; 00722 } 00723 00724 if (l->f != f){ 00725 //printf("Whoops! You got something out of order in BME_bevel_edge()!\n"); 00726 } 00727 00728 return l; 00729 } 00730 00731 static BME_Loop *BME_bevel_vert(BME_Mesh *bm, BME_Loop *l, float value, int UNUSED(options), float *up_vec, BME_TransData_Head *td) { 00732 BME_Vert *v1, *v2; 00733 /* BME_Poly *f; */ /* UNUSED */ 00734 00735 /* get/make the first vert to be used in SFME */ 00736 /* may need to split the previous edge */ 00737 v1 = BME_bevel_split_edge(bm,l->v,NULL,l->prev,up_vec,value,td); 00738 00739 /* get/make the second vert to be used in SFME */ 00740 /* may need to split this edge (so move l) */ 00741 l = l->prev; 00742 v2 = BME_bevel_split_edge(bm,l->next->v,NULL,l->next,up_vec,value,td); 00743 l = l->next->next; 00744 00745 /* "cut off" this corner */ 00746 /* f = */ /* UNUSED */ BME_split_face(bm,l->f,v2,v1,NULL,l->e); 00747 00748 return l; 00749 } 00750 00764 static BME_Poly *BME_bevel_poly(BME_Mesh *bm, BME_Poly *f, float value, int options, BME_TransData_Head *td) { 00765 BME_Loop *l, *ol; 00766 BME_TransData *vtd1, *vtd2; 00767 float up_vec[3], vec1[3], vec2[3], vec3[3], fac1, fac2, max = -1; 00768 int len, i; 00769 00770 up_vec[0] = 0.0f; 00771 up_vec[1] = 0.0f; 00772 up_vec[2] = 0.0f; 00773 /* find a good normal for this face (there's better ways, I'm sure) */ 00774 ol = f->loopbase; 00775 l = ol->next; 00776 for (i=0,ol=f->loopbase,l=ol->next; l->next!=ol; l=l->next) { 00777 BME_bevel_get_vec(vec1,l->next->v,ol->v,td); 00778 BME_bevel_get_vec(vec2,l->v,ol->v,td); 00779 cross_v3_v3v3(vec3, vec2, vec1); 00780 add_v3_v3(up_vec, vec3); 00781 i++; 00782 } 00783 mul_v3_fl(up_vec,1.0f/i); 00784 normalize_v3(up_vec); 00785 00786 for (i=0,len=f->len; i<len; i++,l=l->next) { 00787 if ((l->e->tflag1 & BME_BEVEL_BEVEL) && (l->e->tflag1 & BME_BEVEL_ORIG)) { 00788 max = 1.0f; 00789 l = BME_bevel_edge(bm, l, value, options, up_vec, td); 00790 } 00791 else if ((l->v->tflag1 & BME_BEVEL_BEVEL) && (l->v->tflag1 & BME_BEVEL_ORIG) && (l->prev->e->tflag1 & BME_BEVEL_BEVEL) == 0) { 00792 max = 1.0f; 00793 l = BME_bevel_vert(bm, l, value, options, up_vec, td); 00794 } 00795 } 00796 00797 /* max pass */ 00798 if (value > 0.5 && max > 0) { 00799 max = -1; 00800 for (i=0,len=f->len; i<len; i++,l=l->next) { 00801 if ((l->e->tflag1 & BME_BEVEL_BEVEL) || (l->e->tflag1 & BME_BEVEL_ORIG)) { 00802 BME_bevel_get_vec(vec1,l->v,l->next->v,td); 00803 vtd1 = BME_get_transdata(td,l->v); 00804 vtd2 = BME_get_transdata(td,l->next->v); 00805 if (vtd1->loc == NULL) { 00806 fac1 = 0; 00807 } 00808 else { 00809 copy_v3_v3(vec2,vtd1->vec); 00810 mul_v3_fl(vec2,vtd1->factor); 00811 if (dot_v3v3(vec1, vec1)) { 00812 project_v3_v3v3(vec2,vec2,vec1); 00813 fac1 = len_v3(vec2)/value; 00814 } 00815 else { 00816 fac1 = 0; 00817 } 00818 } 00819 if (vtd2->loc == NULL) { 00820 fac2 = 0; 00821 } 00822 else { 00823 copy_v3_v3(vec3,vtd2->vec); 00824 mul_v3_fl(vec3,vtd2->factor); 00825 if (dot_v3v3(vec1, vec1)) { 00826 project_v3_v3v3(vec2,vec3,vec1); 00827 fac2 = len_v3(vec2)/value; 00828 } 00829 else { 00830 fac2 = 0; 00831 } 00832 } 00833 if (fac1 || fac2) { 00834 max = len_v3(vec1)/(fac1 + fac2); 00835 if (vtd1->max && (*vtd1->max < 0 || max < *vtd1->max)) { 00836 *vtd1->max = max; 00837 } 00838 if (vtd2->max && (*vtd2->max < 0 || max < *vtd2->max)) { 00839 *vtd2->max = max; 00840 } 00841 } 00842 } 00843 } 00844 } 00845 00846 return l->f; 00847 } 00848 00849 static void BME_bevel_add_vweight(BME_TransData_Head *td, BME_Mesh *bm, BME_Vert *v, float weight, float factor, int options) 00850 { 00851 BME_TransData *vtd; 00852 00853 if (v->tflag1 & BME_BEVEL_NONMAN) return; 00854 v->tflag1 |= BME_BEVEL_BEVEL; 00855 if ( (vtd = BME_get_transdata(td, v)) ) { 00856 if (options & BME_BEVEL_EMIN) { 00857 vtd->factor = 1.0; 00858 if (vtd->weight < 0 || weight < vtd->weight) { 00859 vtd->weight = weight; 00860 } 00861 } 00862 else if (options & BME_BEVEL_EMAX) { 00863 vtd->factor = 1.0; 00864 if (weight > vtd->weight) { 00865 vtd->weight = weight; 00866 } 00867 } 00868 else if (vtd->weight < 0) { 00869 vtd->factor = factor; 00870 vtd->weight = weight; 00871 } 00872 else { 00873 vtd->factor += factor; /* increment number of edges with weights (will be averaged) */ 00874 vtd->weight += weight; /* accumulate all the weights */ 00875 } 00876 } 00877 else { 00878 /* we'll use vtd->loc == NULL to mark that this vert is not moving */ 00879 vtd = BME_assign_transdata(td, bm, v, v->co, NULL, NULL, NULL, factor, weight, -1, NULL); 00880 } 00881 } 00882 00883 static float BME_bevel_get_angle(BME_Mesh *UNUSED(bm), BME_Edge *e, BME_Vert *v) { 00884 BME_Vert *v1, *v2; 00885 BME_Loop *l1, *l2; 00886 float vec1[3], vec2[3], vec3[3], vec4[3]; 00887 00888 l1 = e->loop; 00889 l2 = e->loop->radial.next->data; 00890 if (l1->v == v) { 00891 v1 = l1->prev->v; 00892 v2 = l1->next->v; 00893 } 00894 else { 00895 v1 = l1->next->next->v; 00896 v2 = l1->v; 00897 } 00898 VECSUB(vec1,v1->co,v->co); 00899 VECSUB(vec2,v2->co,v->co); 00900 cross_v3_v3v3(vec3,vec1,vec2); 00901 00902 l1 = l2; 00903 if (l1->v == v) { 00904 v1 = l1->prev->v; 00905 v2 = l1->next->v; 00906 } 00907 else { 00908 v1 = l1->next->next->v; 00909 v2 = l1->v; 00910 } 00911 VECSUB(vec1,v1->co,v->co); 00912 VECSUB(vec2,v2->co,v->co); 00913 cross_v3_v3v3(vec4,vec2,vec1); 00914 00915 normalize_v3(vec3); 00916 normalize_v3(vec4); 00917 00918 return dot_v3v3(vec3,vec4); 00919 } 00920 static int BME_face_sharededges(BME_Poly *f1, BME_Poly *f2){ 00921 BME_Loop *l; 00922 int count = 0; 00923 00924 l = f1->loopbase; 00925 do{ 00926 if(BME_radial_find_face(l->e,f2)) count++; 00927 l = l->next; 00928 }while(l != f1->loopbase); 00929 00930 return count; 00931 } 00942 static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defgrp_index), float angle, BME_TransData_Head *td) { 00943 BME_Vert *v; 00944 BME_Edge *e; 00945 BME_Poly *f; 00946 /* BME_TransData *vtd; */ /* UNUSED */ 00947 /* MDeformVert *dvert; */ /* UNUSED */ 00948 /* MDeformWeight *dw; */ /* UNUSED */ 00949 int len; 00950 float weight, threshold; 00951 00952 /* vert pass */ 00953 for (v=bm->verts.first; v; v=v->next) { 00954 /* dvert = NULL; */ /* UNUSED */ 00955 /* dw = NULL; */ /* UNUSED */ 00956 v->tflag1 = BME_BEVEL_ORIG; 00957 /* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if 00958 * the vert is manifold (or is shared by only two edges - wire bevel) 00959 * BME_BEVEL_SELECT is passed and the vert has v->flag&SELECT or 00960 * BME_BEVEL_VWEIGHT is passed, and the vert has a defgrp and weight 00961 * BME_BEVEL_ANGLE is not passed 00962 * BME_BEVEL_EWEIGHT is not passed 00963 */ 00964 /* originally coded, a vertex gets tagged with BME_BEVEL_NONMAN in this pass if 00965 * the vert is loose, shared by multiple regions, or is shared by wire edges 00966 * note: verts belonging to edges of open meshes are not tagged with BME_BEVEL_NONMAN 00967 */ 00968 /* originally coded, a vertex gets a transform weight set in this pass if 00969 * BME_BEVEL_VWEIGHT is passed, and the vert has a defgrp and weight 00970 */ 00971 00972 /* get disk cycle length */ 00973 if (v->edge == NULL) { 00974 len = 0; 00975 } 00976 else { 00977 len = BME_cycle_length(BME_disk_getpointer(v->edge,v)); 00978 /* we'll assign a default transform data to every vert (except the loose ones) */ 00979 /* vtd = */ /* UNUSED */ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL); 00980 } 00981 00982 /* check for non-manifold vert */ 00983 if (BME_is_nonmanifold_vert(bm,v)) { 00984 v->tflag1 |= BME_BEVEL_NONMAN; 00985 } 00986 00987 /* BME_BEVEL_BEVEL tests */ 00988 if ((v->tflag1 & BME_BEVEL_NONMAN) == 0 || len == 2) { /* either manifold vert, or wire vert */ 00989 if (((options & BME_BEVEL_SELECT) && (v->flag & SELECT)) 00990 || ((options & BME_BEVEL_WEIGHT) && (options & BME_BEVEL_VERT)) /* use weights for verts */ 00991 || ((options & BME_BEVEL_ANGLE) == 0 00992 && (options & BME_BEVEL_SELECT) == 0 00993 && (options & BME_BEVEL_WEIGHT) == 0)) 00994 { 00995 if (options & BME_BEVEL_WEIGHT) { 00996 /* do vert weight stuff */ 00997 //~ dvert = CustomData_em_get(&bm->vdata,v->data,CD_MDEFORMVERT); 00998 //~ if (!dvert) continue; 00999 //~ for (i = 0; i < dvert->totweight; ++i) { 01000 //~ if(dvert->dw[i].def_nr == defgrp_index) { 01001 //~ dw = &dvert->dw[i]; 01002 //~ break; 01003 //~ } 01004 //~ } 01005 //~ if (!dw || dw->weight == 0.0) continue; 01006 if (v->bweight == 0.0) continue; 01007 /* vtd = */ /* UNUSED */ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0, v->bweight, -1, NULL); 01008 v->tflag1 |= BME_BEVEL_BEVEL; 01009 } 01010 else { 01011 /* vtd = */ /* UNUSED */ BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0, 1.0, -1, NULL); 01012 v->tflag1 |= BME_BEVEL_BEVEL; 01013 } 01014 } 01015 } 01016 } 01017 01018 /* edge pass */ 01019 threshold = (float)cos((angle + 0.001) * M_PI / 180.0); 01020 for (e=bm->edges.first; e; e=e->next) { 01021 e->tflag1 = BME_BEVEL_ORIG; 01022 weight = 0.0; 01023 /* originally coded, an edge gets tagged with BME_BEVEL_BEVEL in this pass if 01024 * BME_BEVEL_VERT is not set 01025 * the edge is manifold (shared by exactly two faces) 01026 * BME_BEVEL_SELECT is passed and the edge has e->flag&SELECT or 01027 * BME_BEVEL_EWEIGHT is passed, and the edge has the crease set or 01028 * BME_BEVEL_ANGLE is passed, and the edge is sharp enough 01029 * BME_BEVEL_VWEIGHT is passed, and both verts are set for bevel 01030 */ 01031 /* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if 01032 * the vert belongs to the edge 01033 * the vert is not tagged with BME_BEVEL_NONMAN 01034 * the edge is eligible for bevel (even if BME_BEVEL_VERT is set, or the edge is shared by less than 2 faces) 01035 */ 01036 /* originally coded, a vertex gets a transform weight set in this pass if 01037 * the vert belongs to the edge 01038 * the edge has a weight 01039 */ 01040 /* note: edge weights are cumulative at the verts, 01041 * i.e. the vert's weight is the average of the weights of its weighted edges 01042 */ 01043 01044 if (e->loop == NULL) { 01045 len = 0; 01046 e->v1->tflag1 |= BME_BEVEL_NONMAN; 01047 e->v2->tflag1 |= BME_BEVEL_NONMAN; 01048 } 01049 else { 01050 len = BME_cycle_length(&(e->loop->radial)); 01051 } 01052 01053 if (len > 2) { 01054 /* non-manifold edge of the worst kind */ 01055 continue; 01056 } 01057 01058 if ((options & BME_BEVEL_SELECT) && (e->flag & SELECT)) { 01059 weight = 1.0; 01060 /* stupid editmode doesn't always flush selections, or something */ 01061 e->v1->flag |= SELECT; 01062 e->v2->flag |= SELECT; 01063 } 01064 else if ((options & BME_BEVEL_WEIGHT) && (options & BME_BEVEL_VERT) == 0) { 01065 weight = e->bweight; 01066 } 01067 else if (options & BME_BEVEL_ANGLE) { 01068 if ((e->v1->tflag1 & BME_BEVEL_NONMAN) == 0 && BME_bevel_get_angle(bm,e,e->v1) < threshold) { 01069 e->tflag1 |= BME_BEVEL_BEVEL; 01070 e->v1->tflag1 |= BME_BEVEL_BEVEL; 01071 BME_bevel_add_vweight(td, bm, e->v1, 1.0, 1.0, options); 01072 } 01073 else { 01074 BME_bevel_add_vweight(td, bm, e->v1, 0.0, 1.0, options); 01075 } 01076 if ((e->v2->tflag1 & BME_BEVEL_NONMAN) == 0 && BME_bevel_get_angle(bm,e,e->v2) < threshold) { 01077 e->tflag1 |= BME_BEVEL_BEVEL; 01078 e->v2->tflag1 |= BME_BEVEL_BEVEL; 01079 BME_bevel_add_vweight(td, bm, e->v2, 1.0, 1.0, options); 01080 } 01081 else { 01082 BME_bevel_add_vweight(td, bm, e->v2, 0.0, 1.0, options); 01083 } 01084 } 01085 //~ else if ((options & BME_BEVEL_VWEIGHT) && (options & BME_BEVEL_VERT) == 0) { 01086 //~ if ((e->v1->tflag1 & BME_BEVEL_BEVEL) && (e->v2->tflag1 & BME_BEVEL_BEVEL)) { 01087 //~ e->tflag1 |= BME_BEVEL_BEVEL; 01088 //~ } 01089 //~ } 01090 else if ((options & BME_BEVEL_SELECT) == 0 01091 && (options & BME_BEVEL_VERT) == 0) 01092 { 01093 weight = 1.0; 01094 } 01095 01096 if (weight > 0.0) { 01097 e->tflag1 |= BME_BEVEL_BEVEL; 01098 BME_bevel_add_vweight(td, bm, e->v1, weight, 1.0, options); 01099 BME_bevel_add_vweight(td, bm, e->v2, weight, 1.0, options); 01100 } 01101 01102 if (len != 2 || options & BME_BEVEL_VERT) { 01103 e->tflag1 &= ~BME_BEVEL_BEVEL; 01104 } 01105 } 01106 01107 /* face pass */ 01108 for (f=bm->polys.first; f; f=f->next) f->tflag1 = BME_BEVEL_ORIG; 01109 01110 /*clean up edges with 2 faces that share more than one edge*/ 01111 for (e=bm->edges.first; e; e=e->next){ 01112 if(e->tflag1 & BME_BEVEL_BEVEL){ 01113 int count = 0; 01114 count = BME_face_sharededges(e->loop->f, ((BME_Loop*)e->loop->radial.next->data)->f); 01115 if(count > 1){ 01116 e->tflag1 &= ~BME_BEVEL_BEVEL; 01117 } 01118 } 01119 } 01120 01121 return bm; 01122 01123 } 01124 01125 /* tags all elements as originals */ 01126 static BME_Mesh *BME_bevel_reinitialize(BME_Mesh *bm) { 01127 BME_Vert *v; 01128 BME_Edge *e; 01129 BME_Poly *f; 01130 01131 for (v = bm->verts.first; v; v=v->next) { 01132 v->tflag1 |= BME_BEVEL_ORIG; 01133 } 01134 01135 for (e=bm->edges.first; e; e=e->next) { 01136 e->tflag1 |= BME_BEVEL_ORIG; 01137 } 01138 01139 for (f=bm->polys.first; f; f=f->next) { 01140 f->tflag1 |= BME_BEVEL_ORIG; 01141 } 01142 return bm; 01143 01144 } 01145 01160 static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){ 01161 BME_Poly *f; 01162 BME_Edge *e; 01163 int done, len; 01164 01165 if(v->edge){ 01166 done = 0; 01167 while(!done){ 01168 done = 1; 01169 e = v->edge; /*loop the edge looking for a edge to dissolve*/ 01170 do{ 01171 f = NULL; 01172 len = BME_cycle_length(&(e->loop->radial)); 01173 if(len == 2){ 01174 f = BME_JFKE_safe(bm,e->loop->f, ((BME_Loop*)(e->loop->radial.next->data))->f, e); 01175 } 01176 if(f){ 01177 done = 0; 01178 break; 01179 } 01180 e = BME_disk_nextedge(e,v); 01181 }while(e != v->edge); 01182 } 01183 BME_collapse_vert(bm, v->edge, v, 1.0); 01184 //BME_JEKV(bm,v->edge,v); 01185 } 01186 } 01187 static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int UNUSED(defgrp_index), BME_TransData_Head *td) { 01188 BME_Vert *v, *nv; 01189 BME_Edge *e, *oe; 01190 BME_Loop *l, *l2; 01191 BME_Poly *f; 01192 unsigned int i, len; 01193 01194 for (f=bm->polys.first; f; f=f->next) { 01195 if(f->tflag1 & BME_BEVEL_ORIG) { 01196 BME_bevel_poly(bm,f,value,options,td); 01197 } 01198 } 01199 01200 /* here we will loop through all the verts to clean up the left over geometry */ 01201 /* crazy idea. when res == 0, don't remove the original geometry */ 01202 for (v = bm->verts.first; v; /* we may kill v, so increment in-loop */) { 01203 nv = v->next; 01204 if ((v->tflag1 & BME_BEVEL_NONMAN) && (v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG)) { 01205 v = BME_bevel_wire(bm, v, value, res, options, td); 01206 } 01207 else if (res && ((v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG))) { 01208 int count = 0; 01209 /* first, make sure we're not sitting on an edge to be removed */ 01210 oe = v->edge; 01211 e = BME_disk_nextedge(oe,v); 01212 while ((e->tflag1 & BME_BEVEL_BEVEL) && (e->tflag1 & BME_BEVEL_ORIG)) { 01213 e = BME_disk_nextedge(e,v); 01214 if (e == oe) { 01215 //printf("Something's wrong! We can't remove every edge here!\n"); 01216 break; 01217 } 01218 } 01219 /* look for original edges, and remove them */ 01220 oe = e; 01221 while ( (e = BME_disk_next_edgeflag(oe, v, 0, BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) ) { 01222 count++; 01223 /* join the faces (we'll split them later) */ 01224 f = BME_JFKE_safe(bm,e->loop->f,((BME_Loop*)e->loop->radial.next->data)->f,e); 01225 if (!f){ 01226 //printf("Non-manifold geometry not getting tagged right?\n"); 01227 } 01228 } 01229 01230 /*need to do double check *before* you bevel to make sure that manifold edges are for two faces that share only *one* edge to make sure it doesnt hang here!*/ 01231 01232 01233 /* all original edges marked to be beveled have been removed; 01234 * now we need to link up the edges for this "corner" */ 01235 len = BME_cycle_length(BME_disk_getpointer(v->edge, v)); 01236 for (i=0,e=v->edge; i < len; i++,e=BME_disk_nextedge(e,v)) { 01237 l = e->loop; 01238 l2 = l->radial.next->data; 01239 if (l->v != v) l = l->next; 01240 if (l2->v != v) l2 = l2->next; 01241 /* look for faces that have had the original edges removed via JFKE */ 01242 if (l->f->len > 3) { 01243 BME_split_face(bm,l->f,l->next->v,l->prev->v,&l,l->e); /* clip this corner off */ 01244 if (len > 2) { 01245 l->e->tflag1 |= BME_BEVEL_BEVEL; 01246 } 01247 } 01248 if (l2->f->len > 3) { 01249 BME_split_face(bm,l2->f,l2->next->v,l2->prev->v,&l,l2->e); /* clip this corner off */ 01250 if (len > 2) { 01251 l->e->tflag1 |= BME_BEVEL_BEVEL; 01252 } 01253 } 01254 } 01255 bmesh_dissolve_disk(bm, v); 01256 } 01257 v = nv; 01258 } 01259 01260 return bm; 01261 } 01262 01263 static BME_Mesh *BME_tesselate(BME_Mesh *bm) { 01264 BME_Loop *l, *nextloop; 01265 BME_Poly *f; 01266 01267 for (f=bm->polys.first; f; f=f->next) { 01268 l = f->loopbase; 01269 while (l->f->len > 4) { 01270 nextloop = l->next->next->next; 01271 /* make a quad */ 01272 BME_split_face(bm,l->f,l->v,nextloop->v,NULL,l->e); 01273 l = nextloop; 01274 } 01275 } 01276 return bm; 01277 } 01278 01279 01280 /*Main bevel function: 01281 Should be only one exported 01282 01283 */ 01284 01285 /* options that can be passed: 01286 * BME_BEVEL_VWEIGHT <---- v, Look at vertex weights; use defgrp_index if option is present 01287 * BME_BEVEL_SELECT <---- v,e, check selection for verts and edges 01288 * BME_BEVEL_ANGLE <---- v,e, don't bevel-tag verts - tag verts per edge 01289 * BME_BEVEL_VERT <---- e, don't tag edges 01290 * BME_BEVEL_EWEIGHT <---- e, use crease flag for now 01291 * BME_BEVEL_PERCENT <---- Will need to think about this one; will probably need to incorporate into actual bevel routine 01292 * BME_BEVEL_RADIUS <---- Will need to think about this one; will probably need to incorporate into actual bevel routine 01293 * All weights/limits are stored per-vertex 01294 */ 01295 BME_Mesh *BME_bevel(BME_Mesh *bm, float value, int res, int options, int defgrp_index, float angle, BME_TransData_Head **rtd) { 01296 BME_Vert *v; 01297 BME_TransData_Head *td; 01298 BME_TransData *vtd; 01299 int i; 01300 float fac=1, d; 01301 01302 td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE); 01303 01304 BME_bevel_initialize(bm, options, defgrp_index, angle, td); 01305 01306 /* recursion math courtesy of Martin Poirier (theeth) */ 01307 for (i=0; i<res-1; i++) { 01308 if (i==0) fac += 1.0f/3.0f; else fac += 1.0f/(3 * i * 2.0f); 01309 } 01310 d = 1.0f/fac; 01311 /* crazy idea. if res == 0, don't remove original geometry */ 01312 for (i=0; i<res || (res==0 && i==0); i++) { 01313 if (i != 0) BME_bevel_reinitialize(bm); 01314 BME_model_begin(bm); 01315 BME_bevel_mesh(bm,d,res,options,defgrp_index,td); 01316 BME_model_end(bm); 01317 if (i==0) d /= 3; else d /= 2; 01318 } 01319 01320 BME_tesselate(bm); 01321 01322 if (rtd) { 01323 *rtd = td; 01324 return bm; 01325 } 01326 01327 /* transform pass */ 01328 for (v = bm->verts.first; v; v=v->next) { 01329 if ( (vtd = BME_get_transdata(td, v)) ) { 01330 if (vtd->max && (*vtd->max > 0 && value > *vtd->max)) { 01331 d = *vtd->max; 01332 } 01333 else { 01334 d = value; 01335 } 01336 madd_v3_v3v3fl(v->co,vtd->org,vtd->vec,vtd->factor*d); 01337 } 01338 v->tflag1 = 0; 01339 } 01340 01341 BME_free_transdata(td); 01342 return bm; 01343 }