Blender  V2.59
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  * $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 }