Blender V2.61 - r43446

BME_tools.c

Go to the documentation of this file.
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 }