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