2011-02-23 10:52:22 +00:00
/*
2008-02-23 22:11:16 +00:00
* BME_tools . c jan 2007
*
* Functions for changing the topology of a mesh .
*
*
2008-04-16 22:40:48 +00:00
* * * * * * BEGIN GPL LICENSE BLOCK * * * * *
2008-02-23 22:11:16 +00:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
2008-04-16 22:40:48 +00:00
* of the License , or ( at your option ) any later version .
2008-02-23 22:11:16 +00:00
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
2010-02-12 13:34:04 +00:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2008-02-23 22:11:16 +00:00
*
* The Original Code is Copyright ( C ) 2004 Blender Foundation .
* All rights reserved .
*
* The Original Code is : all of this file .
*
* Contributor ( s ) : Geoffrey Bantle and Levi Schooley .
*
2008-04-16 22:40:48 +00:00
* * * * * * END GPL LICENSE BLOCK * * * * *
2008-02-23 22:11:16 +00:00
*/
2011-02-27 20:40:57 +00:00
/** \file blender/blenkernel/intern/BME_tools.c
* \ ingroup bke
*/
2008-02-23 22:11:16 +00:00
# include <math.h>
# include "MEM_guardedalloc.h"
# include "DNA_meshdata_types.h"
Merge of trunk into blender 2.5:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r12987:17416
Issues:
* GHOST/X11 had conflicting changes. Some code was added in 2.5, which was
later added in trunk also, but reverted partially, specifically revision
16683. I have left out this reversion in the 2.5 branch since I think it is
needed there.
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16683
* Scons had various conflicting changes, I decided to go with trunk version
for everything except priorities and some library renaming.
* In creator.c, there were various fixes and fixes for fixes related to the -w
-W and -p options. In 2.5 -w and -W is not coded yet, and -p is done
differently. Since this is changed so much, and I don't think those fixes
would be needed in 2.5, I've left them out.
* Also in creator.c: there was code for a python bugfix where the screen was not
initialized when running with -P. The code that initializes the screen there
I had to disable, that can't work in 2.5 anymore but left it commented as a
reminder.
Further I had to disable some new function calls. using src/ and python/, as
was done already in this branch, disabled function calls:
* bpath.c: error reporting
* BME_conversions.c: editmesh conversion functions.
* SHD_dynamic: disabled almost completely, there is no python/.
* KX_PythonInit.cpp and Ketsji/ build files: Mathutils is not there, disabled.
* text.c: clipboard copy call.
* object.c: OB_SUPPORT_MATERIAL.
* DerivedMesh.c and subsurf_ccg, stipple_quarttone.
Still to be done:
* Go over files and functions that were moved to a different location but could
still use changes that were done in trunk.
2008-11-12 21:16:53 +00:00
# include "DNA_object_types.h"
2008-02-23 22:11:16 +00:00
2009-11-10 20:43:45 +00:00
# include "BLI_math.h"
2011-01-07 18:36:47 +00:00
# include "BLI_utildefines.h"
# include "BKE_bmesh.h"
2008-02-23 22:11:16 +00:00
2008-02-25 04:53:37 +00:00
/*split this all into a seperate bevel.c file in src*/
2008-02-23 22:11:16 +00:00
/* ------- Bevel code starts here -------- */
BME_TransData_Head * BME_init_transdata ( int bufsize ) {
BME_TransData_Head * td ;
td = MEM_callocN ( sizeof ( BME_TransData_Head ) , " BMesh transdata header " ) ;
2010-05-07 07:54:25 +00:00
td - > gh = BLI_ghash_new ( BLI_ghashutil_ptrhash , BLI_ghashutil_ptrcmp , " BME_init_transdata gh " ) ;
2010-04-15 10:28:32 +00:00
td - > ma = BLI_memarena_new ( bufsize , " BME_TransData arena " ) ;
2008-02-23 22:11:16 +00:00
BLI_memarena_use_calloc ( td - > ma ) ;
return td ;
}
void BME_free_transdata ( BME_TransData_Head * td ) {
BLI_ghash_free ( td - > gh , NULL , NULL ) ;
BLI_memarena_free ( td - > ma ) ;
MEM_freeN ( td ) ;
}
2011-11-28 03:01:06 +00:00
BME_TransData * BME_assign_transdata (
BME_TransData_Head * td , BME_Mesh * bm , BME_Vert * v ,
float * co , float * org , float * vec , float * loc ,
float factor , float weight , float maxfactor , float * max )
{
2008-02-23 22:11:16 +00:00
BME_TransData * vtd ;
int is_new = 0 ;
if ( v = = NULL ) return NULL ;
if ( ( vtd = BLI_ghash_lookup ( td - > gh , v ) ) = = NULL & & bm ! = NULL ) {
vtd = BLI_memarena_alloc ( td - > ma , sizeof ( * vtd ) ) ;
BLI_ghash_insert ( td - > gh , v , vtd ) ;
td - > len + + ;
is_new = 1 ;
}
vtd - > bm = bm ;
vtd - > v = v ;
2011-11-28 03:01:06 +00:00
if ( co ! = NULL ) {
copy_v3_v3 ( vtd - > co , co ) ;
}
if ( org = = NULL & & is_new ) {
copy_v3_v3 ( vtd - > org , v - > co ) ; /* default */
}
else if ( org ! = NULL ) {
copy_v3_v3 ( vtd - > org , org ) ;
}
2008-02-23 22:11:16 +00:00
if ( vec ! = NULL ) {
2011-11-28 03:01:06 +00:00
copy_v3_v3 ( vtd - > vec , vec ) ;
2009-11-10 20:43:45 +00:00
normalize_v3 ( vtd - > vec ) ;
2008-02-23 22:11:16 +00:00
}
2011-11-28 03:01:06 +00:00
2008-02-23 22:11:16 +00:00
vtd - > loc = loc ;
vtd - > factor = factor ;
vtd - > weight = weight ;
vtd - > maxfactor = maxfactor ;
vtd - > max = max ;
return vtd ;
}
BME_TransData * BME_get_transdata ( BME_TransData_Head * td , BME_Vert * v ) {
BME_TransData * vtd ;
vtd = BLI_ghash_lookup ( td - > gh , v ) ;
return vtd ;
}
/* a hack (?) to use the transdata memarena to allocate floats for use with the max limits */
float * BME_new_transdata_float ( BME_TransData_Head * td ) {
return BLI_memarena_alloc ( td - > ma , sizeof ( float ) ) ;
}
2010-10-17 06:38:56 +00:00
static int BME_is_nonmanifold_vert ( BME_Mesh * UNUSED ( bm ) , BME_Vert * v ) {
2008-02-23 22:11:16 +00:00
BME_Edge * e , * oe ;
BME_Loop * l ;
int len , count , flag ;
if ( v - > edge = = NULL ) {
/* loose vert */
return 1 ;
}
/* count edges while looking for non-manifold edges */
oe = v - > edge ;
for ( len = 0 , e = v - > edge ; e ! = oe | | ( e = = oe & & len = = 0 ) ; len + + , e = BME_disk_nextedge ( e , v ) ) {
if ( e - > loop = = NULL ) {
/* loose edge */
return 1 ;
}
if ( BME_cycle_length ( & ( e - > loop - > radial ) ) > 2 ) {
/* edge shared by more than two faces */
return 1 ;
}
}
count = 1 ;
flag = 1 ;
e = NULL ;
oe = v - > edge ;
l = oe - > loop ;
while ( e ! = oe ) {
if ( l - > v = = v ) l = l - > prev ;
else l = l - > next ;
e = l - > e ;
count + + ; /* count the edges */
if ( flag & & l - > radial . next - > data = = l ) {
/* we've hit the edge of an open mesh, reset once */
flag = 0 ;
count = 1 ;
oe = e ;
e = NULL ;
l = oe - > loop ;
}
else if ( l - > radial . next - > data = = l ) {
/* break the loop */
e = oe ;
}
else {
l = l - > radial . next - > data ;
}
}
if ( count < len ) {
/* vert shared by multiple regions */
return 1 ;
}
return 0 ;
}
/* a wrapper for BME_JFKE that [for now just] checks to
* make sure loop directions are compatible */
2008-02-25 04:53:37 +00:00
static BME_Poly * BME_JFKE_safe ( BME_Mesh * bm , BME_Poly * f1 , BME_Poly * f2 , BME_Edge * e ) {
2008-02-23 22:11:16 +00:00
BME_Loop * l1 , * l2 ;
l1 = e - > loop ;
l2 = l1 - > radial . next - > data ;
if ( l1 - > v = = l2 - > v ) {
BME_loop_reverse ( bm , f2 ) ;
}
return BME_JFKE ( bm , f1 , f2 , e ) ;
}
/* a wrapper for BME_SFME that transfers element flags */
2008-02-25 04:53:37 +00:00
static BME_Poly * BME_split_face ( BME_Mesh * bm , BME_Poly * f , BME_Vert * v1 , BME_Vert * v2 , BME_Loop * * nl , BME_Edge * example ) {
2008-02-23 22:11:16 +00:00
BME_Poly * nf ;
nf = BME_SFME ( bm , f , v1 , v2 , nl ) ;
nf - > flag = f - > flag ;
/* if the edge was selected, select this face, too */
2009-06-13 16:57:26 +00:00
if ( example & & ( example - > flag & SELECT ) ) f - > flag | = ME_FACE_SEL ;
2008-02-23 22:11:16 +00:00
nf - > h = f - > h ;
nf - > mat_nr = f - > mat_nr ;
if ( nl & & example ) {
( * nl ) - > e - > flag = example - > flag ;
( * nl ) - > e - > h = example - > h ;
( * nl ) - > e - > crease = example - > crease ;
( * nl ) - > e - > bweight = example - > bweight ;
}
return nf ;
}
2008-07-04 17:59:16 +00:00
2008-12-26 14:19:25 +00:00
#if 0
2008-07-04 17:59:16 +00:00
static void BME_data_interp_from_verts ( BME_Mesh * bm , BME_Vert * v1 , BME_Vert * v2 , BME_Vert * v , float fac )
{
void * src [ 2 ] ;
float w [ 2 ] ;
if ( v1 - > data & & v2 - > data ) {
src [ 0 ] = v1 - > data ;
src [ 1 ] = v2 - > data ;
w [ 0 ] = 1.0f - fac ;
w [ 1 ] = fac ;
2008-07-08 02:22:37 +00:00
CustomData_bmesh_interp ( & bm - > vdata , src , w , NULL , 2 , v - > data ) ;
2008-07-04 17:59:16 +00:00
}
}
2008-12-26 14:19:25 +00:00
# endif
2008-07-04 17:59:16 +00:00
2008-07-08 02:22:37 +00:00
2010-10-17 06:38:56 +00:00
static void BME_data_facevert_edgesplit ( BME_Mesh * bm , BME_Vert * v1 , BME_Vert * UNUSED ( v2 ) , BME_Vert * v , BME_Edge * e1 , float fac ) {
2008-07-08 02:22:37 +00:00
void * src [ 2 ] ;
float w [ 2 ] ;
BME_Loop * l = NULL , * v1loop = NULL , * vloop = NULL , * v2loop = NULL ;
w [ 0 ] = 1.0f - fac ;
w [ 1 ] = fac ;
if ( ! e1 - > loop ) return ;
l = e1 - > loop ;
do {
if ( l - > v = = v1 ) {
v1loop = l ;
vloop = v1loop - > next ;
v2loop = vloop - > next ;
} else if ( l - > v = = v ) {
v1loop = l - > next ;
vloop = l ;
v2loop = l - > prev ;
}
src [ 0 ] = v1loop - > data ;
src [ 1 ] = v2loop - > data ;
CustomData_bmesh_interp ( & bm - > ldata , src , w , NULL , 2 , vloop - > data ) ;
l = l - > radial . next - > data ;
} while ( l ! = e1 - > loop ) ;
}
2008-07-04 17:59:16 +00:00
/* a wrapper for BME_SEMV that transfers element flags */ /*add custom data interpolation in here!*/
2008-02-25 04:53:37 +00:00
static BME_Vert * BME_split_edge ( BME_Mesh * bm , BME_Vert * v , BME_Edge * e , BME_Edge * * ne , float percent ) {
2008-02-23 22:11:16 +00:00
BME_Vert * nv , * v2 ;
float len ;
v2 = BME_edge_getothervert ( e , v ) ;
nv = BME_SEMV ( bm , v , e , ne ) ;
if ( nv = = NULL ) return NULL ;
VECSUB ( nv - > co , v2 - > co , v - > co ) ;
2009-11-10 20:43:45 +00:00
len = len_v3 ( nv - > co ) ;
2008-02-23 22:11:16 +00:00
VECADDFAC ( nv - > co , v - > co , nv - > co , len * percent ) ;
nv - > flag = v - > flag ;
nv - > bweight = v - > bweight ;
if ( ne ) {
( * ne ) - > flag = e - > flag ;
( * ne ) - > h = e - > h ;
( * ne ) - > crease = e - > crease ;
( * ne ) - > bweight = e - > bweight ;
}
2008-07-08 02:22:37 +00:00
/*v->nv->v2*/
BME_data_facevert_edgesplit ( bm , v2 , v , nv , e , 0.75 ) ;
2008-02-23 22:11:16 +00:00
return nv ;
}
2008-07-08 02:22:37 +00:00
static void BME_collapse_vert ( BME_Mesh * bm , BME_Edge * ke , BME_Vert * kv , float fac ) {
void * src [ 2 ] ;
float w [ 2 ] ;
BME_Loop * l = NULL , * kvloop = NULL , * tvloop = NULL ;
BME_Vert * tv = BME_edge_getothervert ( ke , kv ) ;
w [ 0 ] = 1.0f - fac ;
w [ 1 ] = fac ;
if ( ke - > loop ) {
l = ke - > loop ;
do {
if ( l - > v = = tv & & l - > next - > v = = kv ) {
tvloop = l ;
kvloop = l - > next ;
src [ 0 ] = kvloop - > data ;
src [ 1 ] = tvloop - > data ;
CustomData_bmesh_interp ( & bm - > ldata , src , w , NULL , 2 , kvloop - > data ) ;
}
l = l - > radial . next - > data ;
} while ( l ! = ke - > loop ) ;
}
BME_JEKV ( bm , ke , kv ) ;
}
2008-07-04 17:59:16 +00:00
2008-02-25 04:53:37 +00:00
static int BME_bevel_is_split_vert ( BME_Loop * l ) {
2008-02-23 22:11:16 +00:00
/* look for verts that have already been added to the edge when
* beveling other polys ; this can be determined by testing the
* vert and the edges around it for originality
*/
if ( ( l - > v - > tflag1 & BME_BEVEL_ORIG ) = = 0
& & ( l - > e - > tflag1 & BME_BEVEL_ORIG )
& & ( l - > prev - > e - > tflag1 & BME_BEVEL_ORIG ) )
{
return 1 ;
}
return 0 ;
}
/* get a vector, vec, that points from v1->co to wherever makes sense to
* the bevel operation as a whole based on the relationship between v1 and v2
* ( won ' t necessarily be a vec from v1 - > co to v2 - > co , though it probably will be ) ;
* the return value is - 1 for failure , 0 if we used vert co ' s , and 1 if we used transform origins */
2011-11-28 03:01:06 +00:00
static int BME_bevel_get_vec ( float * vec , BME_Vert * v1 , BME_Vert * v2 , BME_TransData_Head * td )
{
2008-02-23 22:11:16 +00:00
BME_TransData * vtd1 , * vtd2 ;
vtd1 = BME_get_transdata ( td , v1 ) ;
vtd2 = BME_get_transdata ( td , v2 ) ;
if ( ! vtd1 | | ! vtd2 ) {
2008-02-25 04:53:37 +00:00
//printf("BME_bevel_get_vec() got called without proper BME_TransData\n");
2008-02-23 22:11:16 +00:00
return - 1 ;
}
/* compare the transform origins to see if we can use the vert co's;
* if they belong to different origins , then we will use the origins to determine
* the vector */
2009-11-10 20:43:45 +00:00
if ( compare_v3v3 ( vtd1 - > org , vtd2 - > org , 0.000001f ) ) {
2011-11-28 03:01:06 +00:00
sub_v3_v3v3 ( vec , v2 - > co , v1 - > co ) ;
2009-11-10 20:43:45 +00:00
if ( len_v3 ( vec ) < 0.000001f ) {
2011-11-28 03:01:06 +00:00
zero_v3 ( vec ) ;
2008-02-23 22:11:16 +00:00
}
return 0 ;
}
else {
2011-11-28 03:01:06 +00:00
sub_v3_v3v3 ( vec , vtd2 - > org , vtd1 - > org ) ;
2009-11-10 20:43:45 +00:00
if ( len_v3 ( vec ) < 0.000001f ) {
2011-11-28 03:01:06 +00:00
zero_v3 ( vec ) ;
2008-02-23 22:11:16 +00:00
}
return 1 ;
}
}
/* "Projects" a vector perpendicular to vec2 against vec1, such that
* the projected vec1 + vec2 has a min distance of 1 from the " edge " defined by vec2 .
* note : the direction , is_forward , is used in conjunction with up_vec to determine
* whether this is a convex or concave corner . If it is a concave corner , it will
* be projected " backwards. " If vec1 is before vec2 , is_forward should be 0 ( we are projecting backwards ) .
* vec1 is the vector to project onto ( expected to be normalized )
* vec2 is the direction of projection ( pointing away from vec1 )
* up_vec is used for orientation ( expected to be normalized )
* returns the length of the projected vector that lies along vec1 */
2011-11-28 03:01:06 +00:00
static float BME_bevel_project_vec ( float * vec1 , float * vec2 , float * up_vec , int is_forward , BME_TransData_Head * UNUSED ( td ) )
{
2008-02-23 22:11:16 +00:00
float factor , vec3 [ 3 ] , tmp [ 3 ] , c1 , c2 ;
2009-11-10 20:43:45 +00:00
cross_v3_v3v3 ( tmp , vec1 , vec2 ) ;
normalize_v3 ( tmp ) ;
factor = dot_v3v3 ( up_vec , tmp ) ;
2008-02-23 22:11:16 +00:00
if ( ( factor > 0 & & is_forward ) | | ( factor < 0 & & ! is_forward ) ) {
2009-11-10 20:43:45 +00:00
cross_v3_v3v3 ( vec3 , vec2 , tmp ) ; /* hmm, maybe up_vec should be used instead of tmp */
2008-02-23 22:11:16 +00:00
}
else {
2009-11-10 20:43:45 +00:00
cross_v3_v3v3 ( vec3 , tmp , vec2 ) ; /* hmm, maybe up_vec should be used instead of tmp */
2008-02-23 22:11:16 +00:00
}
2009-11-10 20:43:45 +00:00
normalize_v3 ( vec3 ) ;
c1 = dot_v3v3 ( vec3 , vec1 ) ;
c2 = dot_v3v3 ( vec1 , vec1 ) ;
2011-11-28 03:01:06 +00:00
if ( fabsf ( c1 ) < 0.000001f | | fabsf ( c2 ) < 0.000001f ) {
2008-02-23 22:11:16 +00:00
factor = 0.0f ;
}
else {
factor = c2 / c1 ;
}
return factor ;
}
/* BME_bevel_split_edge() is the main math work-house; its responsibilities are:
* using the vert and the loop passed , get or make the split vert , set its coordinates
* and transform properties , and set the max limits .
* Finally , return the split vert . */
2008-02-25 04:53:37 +00:00
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 ) {
2011-09-27 11:02:19 +00:00
BME_TransData * vtd , * vtd1 /* , *vtd2 */ /* UNUSED */ ;
BME_Vert * sv , * v2 , * v3 /* , *ov */ /* UNUSED */ ;
2008-02-23 22:11:16 +00:00
BME_Loop * lv1 , * lv2 ;
BME_Edge * ne , * e1 , * e2 ;
float maxfactor , scale , len , dis , vec1 [ 3 ] , vec2 [ 3 ] , t_up_vec [ 3 ] ;
2011-09-27 11:02:19 +00:00
int is_edge , forward /* , is_split_vert */ /* UNUSED */ ;
2008-02-23 22:11:16 +00:00
if ( l = = NULL ) {
/* what you call operator overloading in C :)
* I wanted to use the same function for both wire edges and poly loops
* so . . . here we walk around edges to find the needed verts */
forward = 1 ;
2011-09-27 11:02:19 +00:00
/* is_split_vert = 0; */ /* UNUSED */
2008-02-23 22:11:16 +00:00
if ( v - > edge = = NULL ) {
2008-02-25 04:53:37 +00:00
//printf("We can't split a loose vert's edge!\n");
2008-02-23 22:11:16 +00:00
return NULL ;
}
e1 = v - > edge ; /* we just use the first two edges */
e2 = BME_disk_nextedge ( v - > edge , v ) ;
if ( e1 = = e2 ) {
2008-02-25 04:53:37 +00:00
//printf("You need at least two edges to use BME_bevel_split_edge()\n");
2008-02-23 22:11:16 +00:00
return NULL ;
}
v2 = BME_edge_getothervert ( e1 , v ) ;
v3 = BME_edge_getothervert ( e2 , v ) ;
if ( v1 ! = v2 & & v1 ! = v3 ) {
2008-02-25 04:53:37 +00:00
//printf("Error: more than 2 edges in v's disk cycle, or v1 does not share an edge with v\n");
2008-02-23 22:11:16 +00:00
return NULL ;
}
if ( v1 = = v2 ) {
v2 = v3 ;
}
else {
e1 = e2 ;
}
2011-09-27 11:02:19 +00:00
/* ov = BME_edge_getothervert(e1,v); */ /* UNUSED */
2008-02-23 22:11:16 +00:00
sv = BME_split_edge ( bm , v , e1 , & ne , 0 ) ;
2008-07-04 17:59:16 +00:00
//BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
2008-07-08 02:22:37 +00:00
//BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
//BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
2008-02-23 22:11:16 +00:00
BME_assign_transdata ( td , bm , sv , sv - > co , sv - > co , NULL , sv - > co , 0 , - 1 , - 1 , NULL ) ; /* quick default */
sv - > tflag1 | = BME_BEVEL_BEVEL ;
ne - > tflag1 = BME_BEVEL_ORIG ; /* mark edge as original, even though it isn't */
BME_bevel_get_vec ( vec1 , v1 , v , td ) ;
BME_bevel_get_vec ( vec2 , v2 , v , td ) ;
2009-11-10 20:43:45 +00:00
cross_v3_v3v3 ( t_up_vec , vec1 , vec2 ) ;
normalize_v3 ( t_up_vec ) ;
2008-02-23 22:11:16 +00:00
up_vec = t_up_vec ;
}
else {
/* establish loop direction */
if ( l - > v = = v ) {
forward = 1 ;
lv1 = l - > next ;
lv2 = l - > prev ;
v1 = l - > next - > v ;
v2 = l - > prev - > v ;
}
else if ( l - > next - > v = = v ) {
forward = 0 ;
lv1 = l ;
lv2 = l - > next - > next ;
v1 = l - > v ;
v2 = l - > next - > next - > v ;
}
else {
2008-02-25 04:53:37 +00:00
//printf("ERROR: BME_bevel_split_edge() - v must be adjacent to l\n");
2008-02-23 22:11:16 +00:00
return NULL ;
}
if ( BME_bevel_is_split_vert ( lv1 ) ) {
2011-09-27 11:02:19 +00:00
/* is_split_vert = 1; */ /* UNUSED */
2008-02-23 22:11:16 +00:00
sv = v1 ;
if ( forward ) v1 = l - > next - > next - > v ;
else v1 = l - > prev - > v ;
}
else {
2011-09-27 11:02:19 +00:00
/* is_split_vert = 0; */ /* UNUSED */
/* ov = BME_edge_getothervert(l->e,v); */ /* UNUSED */
2008-02-23 22:11:16 +00:00
sv = BME_split_edge ( bm , v , l - > e , & ne , 0 ) ;
2008-07-04 17:59:16 +00:00
//BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
2008-07-08 02:22:37 +00:00
//BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
//BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
2008-02-23 22:11:16 +00:00
BME_assign_transdata ( td , bm , sv , sv - > co , sv - > co , NULL , sv - > co , 0 , - 1 , - 1 , NULL ) ; /* quick default */
sv - > tflag1 | = BME_BEVEL_BEVEL ;
ne - > tflag1 = BME_BEVEL_ORIG ; /* mark edge as original, even though it isn't */
}
if ( BME_bevel_is_split_vert ( lv2 ) ) {
if ( forward ) v2 = lv2 - > prev - > v ;
else v2 = lv2 - > next - > v ;
}
}
is_edge = BME_bevel_get_vec ( vec1 , v , v1 , td ) ; /* get the vector we will be projecting onto */
BME_bevel_get_vec ( vec2 , v , v2 , td ) ; /* get the vector we will be projecting parallel to */
2009-11-10 20:43:45 +00:00
len = len_v3 ( vec1 ) ;
normalize_v3 ( vec1 ) ;
2008-02-23 22:11:16 +00:00
vtd = BME_get_transdata ( td , sv ) ;
vtd1 = BME_get_transdata ( td , v ) ;
2011-09-27 11:02:19 +00:00
/* vtd2 = BME_get_transdata(td,v1); */ /* UNUSED */
2008-02-23 22:11:16 +00:00
if ( vtd1 - > loc = = NULL ) {
/* this is a vert with data only for calculating initial weights */
if ( vtd1 - > weight < 0 ) {
vtd1 - > weight = 0 ;
}
scale = vtd1 - > weight / vtd1 - > factor ;
if ( ! vtd1 - > max ) {
vtd1 - > max = BME_new_transdata_float ( td ) ;
* vtd1 - > max = - 1 ;
}
}
else {
scale = vtd1 - > weight ;
}
vtd - > max = vtd1 - > max ;
if ( is_edge & & vtd1 - > loc ! = NULL ) {
maxfactor = vtd1 - > maxfactor ;
}
else {
maxfactor = scale * BME_bevel_project_vec ( vec1 , vec2 , up_vec , forward , td ) ;
if ( vtd - > maxfactor > 0 & & vtd - > maxfactor < maxfactor ) {
maxfactor = vtd - > maxfactor ;
}
}
dis = ( v1 - > tflag1 & BME_BEVEL_ORIG ) ? len / 3 : len / 2 ;
if ( is_edge | | dis > maxfactor * value ) {
dis = maxfactor * value ;
}
2011-11-28 03:01:06 +00:00
madd_v3_v3v3fl ( sv - > co , v - > co , vec1 , dis ) ;
sub_v3_v3v3 ( vec1 , sv - > co , vtd1 - > org ) ;
2009-11-10 20:43:45 +00:00
dis = len_v3 ( vec1 ) ;
normalize_v3 ( vec1 ) ;
2008-02-23 22:11:16 +00:00
BME_assign_transdata ( td , bm , sv , vtd1 - > org , vtd1 - > org , vec1 , sv - > co , dis , scale , maxfactor , vtd - > max ) ;
return sv ;
}
2008-02-25 04:53:37 +00:00
static float BME_bevel_set_max ( BME_Vert * v1 , BME_Vert * v2 , float value , BME_TransData_Head * td ) {
2008-02-23 22:11:16 +00:00
BME_TransData * vtd1 , * vtd2 ;
float max , fac1 , fac2 , vec1 [ 3 ] , vec2 [ 3 ] , vec3 [ 3 ] ;
BME_bevel_get_vec ( vec1 , v1 , v2 , td ) ;
vtd1 = BME_get_transdata ( td , v1 ) ;
vtd2 = BME_get_transdata ( td , v2 ) ;
if ( vtd1 - > loc = = NULL ) {
fac1 = 0 ;
}
else {
2011-11-28 03:01:06 +00:00
copy_v3_v3 ( vec2 , vtd1 - > vec ) ;
mul_v3_fl ( vec2 , vtd1 - > factor ) ;
2009-11-10 20:43:45 +00:00
if ( dot_v3v3 ( vec1 , vec1 ) ) {
2011-11-28 03:01:06 +00:00
project_v3_v3v3 ( vec2 , vec2 , vec1 ) ;
fac1 = len_v3 ( vec2 ) / value ;
2008-02-23 22:11:16 +00:00
}
else {
fac1 = 0 ;
}
}
if ( vtd2 - > loc = = NULL ) {
fac2 = 0 ;
}
else {
2011-11-28 03:01:06 +00:00
copy_v3_v3 ( vec3 , vtd2 - > vec ) ;
mul_v3_fl ( vec3 , vtd2 - > factor ) ;
2009-11-10 20:43:45 +00:00
if ( dot_v3v3 ( vec1 , vec1 ) ) {
2011-11-28 03:01:06 +00:00
project_v3_v3v3 ( vec2 , vec3 , vec1 ) ;
fac2 = len_v3 ( vec2 ) / value ;
2008-02-23 22:11:16 +00:00
}
else {
fac2 = 0 ;
}
}
if ( fac1 | | fac2 ) {
2011-11-28 03:01:06 +00:00
max = len_v3 ( vec1 ) / ( fac1 + fac2 ) ;
2008-02-23 22:11:16 +00:00
if ( vtd1 - > max & & ( * vtd1 - > max < 0 | | max < * vtd1 - > max ) ) {
* vtd1 - > max = max ;
}
if ( vtd2 - > max & & ( * vtd2 - > max < 0 | | max < * vtd2 - > max ) ) {
* vtd2 - > max = max ;
}
}
else {
max = - 1 ;
}
return max ;
}
2010-10-17 06:38:56 +00:00
static BME_Vert * BME_bevel_wire ( BME_Mesh * bm , BME_Vert * v , float value , int res , int UNUSED ( options ) , BME_TransData_Head * td ) {
2008-02-23 22:11:16 +00:00
BME_Vert * ov1 , * ov2 , * v1 , * v2 ;
ov1 = BME_edge_getothervert ( v - > edge , v ) ;
ov2 = BME_edge_getothervert ( BME_disk_nextedge ( v - > edge , v ) , v ) ;
/* split the edges */
v1 = BME_bevel_split_edge ( bm , v , ov1 , NULL , NULL , value , td ) ;
v1 - > tflag1 | = BME_BEVEL_NONMAN ;
v2 = BME_bevel_split_edge ( bm , v , ov2 , NULL , NULL , value , td ) ;
v2 - > tflag1 | = BME_BEVEL_NONMAN ;
if ( value > 0.5 ) {
BME_bevel_set_max ( v1 , ov1 , value , td ) ;
BME_bevel_set_max ( v2 , ov2 , value , td ) ;
}
/* remove the original vert */
if ( res ) {
BME_JEKV ( bm , v - > edge , v ) ;
}
return v1 ;
}
2010-10-17 06:38:56 +00:00
static BME_Loop * BME_bevel_edge ( BME_Mesh * bm , BME_Loop * l , float value , int UNUSED ( options ) , float * up_vec , BME_TransData_Head * td ) {
2008-02-23 22:11:16 +00:00
BME_Vert * v1 , * v2 , * kv ;
2008-02-25 04:38:48 +00:00
BME_Loop * kl = NULL , * nl ;
2008-02-23 22:11:16 +00:00
BME_Edge * e ;
BME_Poly * f ;
f = l - > f ;
e = l - > e ;
if ( ( l - > e - > tflag1 & BME_BEVEL_BEVEL ) = = 0
& & ( ( l - > v - > tflag1 & BME_BEVEL_BEVEL ) | | ( l - > next - > v - > tflag1 & BME_BEVEL_BEVEL ) ) )
{ /* sanity check */
return l ;
}
/* checks and operations for prev edge */
/* first, check to see if this edge was inset previously */
if ( ( l - > prev - > e - > tflag1 & BME_BEVEL_ORIG ) = = 0
& & ( l - > v - > tflag1 & BME_BEVEL_NONMAN ) = = 0 ) {
kl = l - > prev - > radial . next - > data ;
if ( kl - > v = = l - > v ) kl = kl - > prev ;
else kl = kl - > next ;
kv = l - > v ;
}
else {
kv = NULL ;
}
/* get/make the first vert to be used in SFME */
if ( l - > v - > tflag1 & BME_BEVEL_NONMAN ) {
v1 = l - > v ;
}
else { /* we'll need to split the previous edge */
v1 = BME_bevel_split_edge ( bm , l - > v , NULL , l - > prev , up_vec , value , td ) ;
}
/* if we need to clean up geometry... */
if ( kv ) {
l = l - > next ;
if ( kl - > v = = kv ) {
BME_split_face ( bm , kl - > f , kl - > prev - > v , kl - > next - > v , & nl , kl - > prev - > e ) ;
BME_JFKE ( bm , ( ( BME_Loop * ) kl - > prev - > radial . next - > data ) - > f , kl - > f , kl - > prev - > e ) ;
2008-07-08 02:22:37 +00:00
BME_collapse_vert ( bm , kl - > e , kv , 1.0 ) ;
//BME_JEKV(bm,kl->e,kv);
2008-02-23 22:11:16 +00:00
}
else {
BME_split_face ( bm , kl - > f , kl - > next - > next - > v , kl - > v , & nl , kl - > next - > e ) ;
BME_JFKE ( bm , ( ( BME_Loop * ) kl - > next - > radial . next - > data ) - > f , kl - > f , kl - > next - > e ) ;
2008-07-08 02:22:37 +00:00
BME_collapse_vert ( bm , kl - > e , kv , 1.0 ) ;
//BME_JEKV(bm,kl->e,kv);
2008-02-23 22:11:16 +00:00
}
l = l - > prev ;
}
/* checks and operations for the next edge */
/* first, check to see if this edge was inset previously */
if ( ( l - > next - > e - > tflag1 & BME_BEVEL_ORIG ) = = 0
& & ( l - > next - > v - > tflag1 & BME_BEVEL_NONMAN ) = = 0 ) {
kl = l - > next - > radial . next - > data ;
if ( kl - > v = = l - > next - > v ) kl = kl - > prev ;
else kl = kl - > next ;
kv = l - > next - > v ;
}
else {
kv = NULL ;
}
/* get/make the second vert to be used in SFME */
if ( l - > next - > v - > tflag1 & BME_BEVEL_NONMAN ) {
v2 = l - > next - > v ;
}
else { /* we'll need to split the next edge */
v2 = BME_bevel_split_edge ( bm , l - > next - > v , NULL , l - > next , up_vec , value , td ) ;
}
/* if we need to clean up geometry... */
if ( kv ) {
if ( kl - > v = = kv ) {
BME_split_face ( bm , kl - > f , kl - > prev - > v , kl - > next - > v , & nl , kl - > prev - > e ) ;
BME_JFKE ( bm , ( ( BME_Loop * ) kl - > prev - > radial . next - > data ) - > f , kl - > f , kl - > prev - > e ) ;
2008-07-08 02:22:37 +00:00
BME_collapse_vert ( bm , kl - > e , kv , 1.0 ) ;
//BME_JEKV(bm,kl->e,kv);
2008-02-23 22:11:16 +00:00
}
else {
BME_split_face ( bm , kl - > f , kl - > next - > next - > v , kl - > v , & nl , kl - > next - > e ) ;
BME_JFKE ( bm , ( ( BME_Loop * ) kl - > next - > radial . next - > data ) - > f , kl - > f , kl - > next - > e ) ;
2008-07-08 02:22:37 +00:00
BME_collapse_vert ( bm , kl - > e , kv , 1.0 ) ;
//BME_JEKV(bm,kl->e,kv);
2008-02-23 22:11:16 +00:00
}
}
if ( ( v1 - > tflag1 & BME_BEVEL_NONMAN ) = = 0 | | ( v2 - > tflag1 & BME_BEVEL_NONMAN ) = = 0 ) {
BME_split_face ( bm , f , v2 , v1 , & l , e ) ;
l - > e - > tflag1 = BME_BEVEL_BEVEL ;
l = l - > radial . next - > data ;
}
2008-03-10 19:32:20 +00:00
if ( l - > f ! = f ) {
//printf("Whoops! You got something out of order in BME_bevel_edge()!\n");
}
2008-02-23 22:11:16 +00:00
return l ;
}
2010-10-17 06:38:56 +00:00
static BME_Loop * BME_bevel_vert ( BME_Mesh * bm , BME_Loop * l , float value , int UNUSED ( options ) , float * up_vec , BME_TransData_Head * td ) {
2008-02-23 22:11:16 +00:00
BME_Vert * v1 , * v2 ;
2011-09-27 11:02:19 +00:00
/* BME_Poly *f; */ /* UNUSED */
2008-02-23 22:11:16 +00:00
/* get/make the first vert to be used in SFME */
/* may need to split the previous edge */
v1 = BME_bevel_split_edge ( bm , l - > v , NULL , l - > prev , up_vec , value , td ) ;
/* get/make the second vert to be used in SFME */
/* may need to split this edge (so move l) */
l = l - > prev ;
v2 = BME_bevel_split_edge ( bm , l - > next - > v , NULL , l - > next , up_vec , value , td ) ;
l = l - > next - > next ;
/* "cut off" this corner */
2011-09-27 11:02:19 +00:00
/* f = */ /* UNUSED */ BME_split_face ( bm , l - > f , v2 , v1 , NULL , l - > e ) ;
2008-02-23 22:11:16 +00:00
return l ;
}
/**
* BME_bevel_poly
*
* Polygon inset tool :
*
* Insets a polygon / face based on the tflag1 ' s of its vertices
* and edges . Used by the bevel tool only , for now .
* The parameter " value " is the distance to inset ( should be negative ) .
* The parameter " options " is not currently used .
*
* Returns -
* A BME_Poly pointer to the resulting inner face .
*/
2008-02-25 04:53:37 +00:00
static BME_Poly * BME_bevel_poly ( BME_Mesh * bm , BME_Poly * f , float value , int options , BME_TransData_Head * td ) {
2008-02-23 22:11:16 +00:00
BME_Loop * l , * ol ;
BME_TransData * vtd1 , * vtd2 ;
float up_vec [ 3 ] , vec1 [ 3 ] , vec2 [ 3 ] , vec3 [ 3 ] , fac1 , fac2 , max = - 1 ;
int len , i ;
up_vec [ 0 ] = 0.0f ;
up_vec [ 1 ] = 0.0f ;
up_vec [ 2 ] = 0.0f ;
/* find a good normal for this face (there's better ways, I'm sure) */
ol = f - > loopbase ;
l = ol - > next ;
for ( i = 0 , ol = f - > loopbase , l = ol - > next ; l - > next ! = ol ; l = l - > next ) {
BME_bevel_get_vec ( vec1 , l - > next - > v , ol - > v , td ) ;
BME_bevel_get_vec ( vec2 , l - > v , ol - > v , td ) ;
2011-11-28 03:01:06 +00:00
cross_v3_v3v3 ( vec3 , vec2 , vec1 ) ;
add_v3_v3 ( up_vec , vec3 ) ;
2008-02-23 22:11:16 +00:00
i + + ;
}
2009-11-10 20:43:45 +00:00
mul_v3_fl ( up_vec , 1.0f / i ) ;
normalize_v3 ( up_vec ) ;
2008-02-23 22:11:16 +00:00
for ( i = 0 , len = f - > len ; i < len ; i + + , l = l - > next ) {
if ( ( l - > e - > tflag1 & BME_BEVEL_BEVEL ) & & ( l - > e - > tflag1 & BME_BEVEL_ORIG ) ) {
max = 1.0f ;
l = BME_bevel_edge ( bm , l , value , options , up_vec , td ) ;
}
else if ( ( l - > v - > tflag1 & BME_BEVEL_BEVEL ) & & ( l - > v - > tflag1 & BME_BEVEL_ORIG ) & & ( l - > prev - > e - > tflag1 & BME_BEVEL_BEVEL ) = = 0 ) {
max = 1.0f ;
l = BME_bevel_vert ( bm , l , value , options , up_vec , td ) ;
}
}
/* max pass */
if ( value > 0.5 & & max > 0 ) {
max = - 1 ;
for ( i = 0 , len = f - > len ; i < len ; i + + , l = l - > next ) {
if ( ( l - > e - > tflag1 & BME_BEVEL_BEVEL ) | | ( l - > e - > tflag1 & BME_BEVEL_ORIG ) ) {
BME_bevel_get_vec ( vec1 , l - > v , l - > next - > v , td ) ;
vtd1 = BME_get_transdata ( td , l - > v ) ;
vtd2 = BME_get_transdata ( td , l - > next - > v ) ;
if ( vtd1 - > loc = = NULL ) {
fac1 = 0 ;
}
else {
2011-11-28 03:01:06 +00:00
copy_v3_v3 ( vec2 , vtd1 - > vec ) ;
2009-11-10 20:43:45 +00:00
mul_v3_fl ( vec2 , vtd1 - > factor ) ;
if ( dot_v3v3 ( vec1 , vec1 ) ) {
project_v3_v3v3 ( vec2 , vec2 , vec1 ) ;
fac1 = len_v3 ( vec2 ) / value ;
2008-02-23 22:11:16 +00:00
}
else {
fac1 = 0 ;
}
}
if ( vtd2 - > loc = = NULL ) {
fac2 = 0 ;
}
else {
2011-11-28 03:01:06 +00:00
copy_v3_v3 ( vec3 , vtd2 - > vec ) ;
2009-11-10 20:43:45 +00:00
mul_v3_fl ( vec3 , vtd2 - > factor ) ;
if ( dot_v3v3 ( vec1 , vec1 ) ) {
project_v3_v3v3 ( vec2 , vec3 , vec1 ) ;
fac2 = len_v3 ( vec2 ) / value ;
2008-02-23 22:11:16 +00:00
}
else {
fac2 = 0 ;
}
}
if ( fac1 | | fac2 ) {
2009-11-10 20:43:45 +00:00
max = len_v3 ( vec1 ) / ( fac1 + fac2 ) ;
2008-02-23 22:11:16 +00:00
if ( vtd1 - > max & & ( * vtd1 - > max < 0 | | max < * vtd1 - > max ) ) {
* vtd1 - > max = max ;
}
if ( vtd2 - > max & & ( * vtd2 - > max < 0 | | max < * vtd2 - > max ) ) {
* vtd2 - > max = max ;
}
}
}
}
}
return l - > f ;
}
2011-11-28 03:01:06 +00:00
static void BME_bevel_add_vweight ( BME_TransData_Head * td , BME_Mesh * bm , BME_Vert * v , float weight , float factor , int options )
{
2008-02-23 22:11:16 +00:00
BME_TransData * vtd ;
if ( v - > tflag1 & BME_BEVEL_NONMAN ) return ;
v - > tflag1 | = BME_BEVEL_BEVEL ;
2008-02-24 11:16:37 +00:00
if ( ( vtd = BME_get_transdata ( td , v ) ) ) {
2008-02-23 22:11:16 +00:00
if ( options & BME_BEVEL_EMIN ) {
vtd - > factor = 1.0 ;
if ( vtd - > weight < 0 | | weight < vtd - > weight ) {
vtd - > weight = weight ;
}
}
else if ( options & BME_BEVEL_EMAX ) {
vtd - > factor = 1.0 ;
if ( weight > vtd - > weight ) {
vtd - > weight = weight ;
}
}
else if ( vtd - > weight < 0 ) {
vtd - > factor = factor ;
vtd - > weight = weight ;
}
else {
vtd - > factor + = factor ; /* increment number of edges with weights (will be averaged) */
vtd - > weight + = weight ; /* accumulate all the weights */
}
}
else {
/* we'll use vtd->loc == NULL to mark that this vert is not moving */
vtd = BME_assign_transdata ( td , bm , v , v - > co , NULL , NULL , NULL , factor , weight , - 1 , NULL ) ;
}
}
2010-10-17 06:38:56 +00:00
static float BME_bevel_get_angle ( BME_Mesh * UNUSED ( bm ) , BME_Edge * e , BME_Vert * v ) {
2008-02-23 22:11:16 +00:00
BME_Vert * v1 , * v2 ;
BME_Loop * l1 , * l2 ;
float vec1 [ 3 ] , vec2 [ 3 ] , vec3 [ 3 ] , vec4 [ 3 ] ;
l1 = e - > loop ;
l2 = e - > loop - > radial . next - > data ;
if ( l1 - > v = = v ) {
v1 = l1 - > prev - > v ;
v2 = l1 - > next - > v ;
}
else {
v1 = l1 - > next - > next - > v ;
v2 = l1 - > v ;
}
VECSUB ( vec1 , v1 - > co , v - > co ) ;
VECSUB ( vec2 , v2 - > co , v - > co ) ;
2009-11-10 20:43:45 +00:00
cross_v3_v3v3 ( vec3 , vec1 , vec2 ) ;
2008-02-23 22:11:16 +00:00
l1 = l2 ;
if ( l1 - > v = = v ) {
v1 = l1 - > prev - > v ;
v2 = l1 - > next - > v ;
}
else {
v1 = l1 - > next - > next - > v ;
v2 = l1 - > v ;
}
VECSUB ( vec1 , v1 - > co , v - > co ) ;
VECSUB ( vec2 , v2 - > co , v - > co ) ;
2009-11-10 20:43:45 +00:00
cross_v3_v3v3 ( vec4 , vec2 , vec1 ) ;
2008-02-23 22:11:16 +00:00
2009-11-10 20:43:45 +00:00
normalize_v3 ( vec3 ) ;
normalize_v3 ( vec4 ) ;
2008-02-23 22:11:16 +00:00
2009-11-10 20:43:45 +00:00
return dot_v3v3 ( vec3 , vec4 ) ;
2008-02-23 22:11:16 +00:00
}
2008-06-01 01:56:35 +00:00
static int BME_face_sharededges ( BME_Poly * f1 , BME_Poly * f2 ) {
BME_Loop * l ;
int count = 0 ;
l = f1 - > loopbase ;
do {
if ( BME_radial_find_face ( l - > e , f2 ) ) count + + ;
l = l - > next ;
} while ( l ! = f1 - > loopbase ) ;
return count ;
}
2008-02-23 22:11:16 +00:00
/**
* BME_bevel_initialize
*
* Prepare the mesh for beveling :
*
* Sets the tflag1 ' s of the mesh elements based on the options passed .
*
* Returns -
* A BME_Mesh pointer to the BMesh passed as a parameter .
*/
2010-10-16 14:32:17 +00:00
static BME_Mesh * BME_bevel_initialize ( BME_Mesh * bm , int options , int UNUSED ( defgrp_index ) , float angle , BME_TransData_Head * td ) {
2008-02-23 22:11:16 +00:00
BME_Vert * v ;
BME_Edge * e ;
BME_Poly * f ;
2011-09-27 11:02:19 +00:00
/* BME_TransData *vtd; */ /* UNUSED */
/* MDeformVert *dvert; */ /* UNUSED */
/* MDeformWeight *dw; */ /* UNUSED */
2008-02-24 11:16:37 +00:00
int len ;
2008-02-23 22:11:16 +00:00
float weight , threshold ;
/* vert pass */
for ( v = bm - > verts . first ; v ; v = v - > next ) {
2011-09-27 11:02:19 +00:00
/* dvert = NULL; */ /* UNUSED */
/* dw = NULL; */ /* UNUSED */
2008-02-23 22:11:16 +00:00
v - > tflag1 = BME_BEVEL_ORIG ;
/* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if
* the vert is manifold ( or is shared by only two edges - wire bevel )
* BME_BEVEL_SELECT is passed and the vert has v - > flag & SELECT or
* BME_BEVEL_VWEIGHT is passed , and the vert has a defgrp and weight
* BME_BEVEL_ANGLE is not passed
* BME_BEVEL_EWEIGHT is not passed
*/
/* originally coded, a vertex gets tagged with BME_BEVEL_NONMAN in this pass if
* the vert is loose , shared by multiple regions , or is shared by wire edges
* note : verts belonging to edges of open meshes are not tagged with BME_BEVEL_NONMAN
*/
/* originally coded, a vertex gets a transform weight set in this pass if
* BME_BEVEL_VWEIGHT is passed , and the vert has a defgrp and weight
*/
/* get disk cycle length */
if ( v - > edge = = NULL ) {
len = 0 ;
}
else {
len = BME_cycle_length ( BME_disk_getpointer ( v - > edge , v ) ) ;
/* we'll assign a default transform data to every vert (except the loose ones) */
2011-09-27 11:02:19 +00:00
/* vtd = */ /* UNUSED */ BME_assign_transdata ( td , bm , v , v - > co , v - > co , NULL , NULL , 0 , - 1 , - 1 , NULL ) ;
2008-02-23 22:11:16 +00:00
}
/* check for non-manifold vert */
if ( BME_is_nonmanifold_vert ( bm , v ) ) {
v - > tflag1 | = BME_BEVEL_NONMAN ;
}
/* BME_BEVEL_BEVEL tests */
if ( ( v - > tflag1 & BME_BEVEL_NONMAN ) = = 0 | | len = = 2 ) { /* either manifold vert, or wire vert */
if ( ( ( options & BME_BEVEL_SELECT ) & & ( v - > flag & SELECT ) )
| | ( ( options & BME_BEVEL_WEIGHT ) & & ( options & BME_BEVEL_VERT ) ) /* use weights for verts */
| | ( ( options & BME_BEVEL_ANGLE ) = = 0
& & ( options & BME_BEVEL_SELECT ) = = 0
& & ( options & BME_BEVEL_WEIGHT ) = = 0 ) )
{
if ( options & BME_BEVEL_WEIGHT ) {
/* do vert weight stuff */
//~ dvert = CustomData_em_get(&bm->vdata,v->data,CD_MDEFORMVERT);
//~ if (!dvert) continue;
//~ for (i = 0; i < dvert->totweight; ++i) {
//~ if(dvert->dw[i].def_nr == defgrp_index) {
//~ dw = &dvert->dw[i];
//~ break;
//~ }
//~ }
//~ if (!dw || dw->weight == 0.0) continue;
if ( v - > bweight = = 0.0 ) continue ;
2011-09-27 11:02:19 +00:00
/* vtd = */ /* UNUSED */ BME_assign_transdata ( td , bm , v , v - > co , v - > co , NULL , NULL , 1.0 , v - > bweight , - 1 , NULL ) ;
2008-02-23 22:11:16 +00:00
v - > tflag1 | = BME_BEVEL_BEVEL ;
}
else {
2011-09-27 11:02:19 +00:00
/* vtd = */ /* UNUSED */ BME_assign_transdata ( td , bm , v , v - > co , v - > co , NULL , NULL , 1.0 , 1.0 , - 1 , NULL ) ;
2008-02-23 22:11:16 +00:00
v - > tflag1 | = BME_BEVEL_BEVEL ;
}
}
}
}
/* edge pass */
2011-07-05 08:28:54 +00:00
threshold = ( float ) cos ( ( angle + 0.001 ) * M_PI / 180.0 ) ;
2008-02-23 22:11:16 +00:00
for ( e = bm - > edges . first ; e ; e = e - > next ) {
e - > tflag1 = BME_BEVEL_ORIG ;
weight = 0.0 ;
/* originally coded, an edge gets tagged with BME_BEVEL_BEVEL in this pass if
* BME_BEVEL_VERT is not set
* the edge is manifold ( shared by exactly two faces )
* BME_BEVEL_SELECT is passed and the edge has e - > flag & SELECT or
* BME_BEVEL_EWEIGHT is passed , and the edge has the crease set or
* BME_BEVEL_ANGLE is passed , and the edge is sharp enough
* BME_BEVEL_VWEIGHT is passed , and both verts are set for bevel
*/
/* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if
* the vert belongs to the edge
* the vert is not tagged with BME_BEVEL_NONMAN
* the edge is eligible for bevel ( even if BME_BEVEL_VERT is set , or the edge is shared by less than 2 faces )
*/
/* originally coded, a vertex gets a transform weight set in this pass if
* the vert belongs to the edge
* the edge has a weight
*/
/* note: edge weights are cumulative at the verts,
* i . e . the vert ' s weight is the average of the weights of its weighted edges
*/
if ( e - > loop = = NULL ) {
len = 0 ;
e - > v1 - > tflag1 | = BME_BEVEL_NONMAN ;
e - > v2 - > tflag1 | = BME_BEVEL_NONMAN ;
}
else {
len = BME_cycle_length ( & ( e - > loop - > radial ) ) ;
}
if ( len > 2 ) {
/* non-manifold edge of the worst kind */
continue ;
}
if ( ( options & BME_BEVEL_SELECT ) & & ( e - > flag & SELECT ) ) {
weight = 1.0 ;
/* stupid editmode doesn't always flush selections, or something */
e - > v1 - > flag | = SELECT ;
e - > v2 - > flag | = SELECT ;
}
else if ( ( options & BME_BEVEL_WEIGHT ) & & ( options & BME_BEVEL_VERT ) = = 0 ) {
weight = e - > bweight ;
}
else if ( options & BME_BEVEL_ANGLE ) {
if ( ( e - > v1 - > tflag1 & BME_BEVEL_NONMAN ) = = 0 & & BME_bevel_get_angle ( bm , e , e - > v1 ) < threshold ) {
e - > tflag1 | = BME_BEVEL_BEVEL ;
e - > v1 - > tflag1 | = BME_BEVEL_BEVEL ;
BME_bevel_add_vweight ( td , bm , e - > v1 , 1.0 , 1.0 , options ) ;
}
else {
BME_bevel_add_vweight ( td , bm , e - > v1 , 0.0 , 1.0 , options ) ;
}
if ( ( e - > v2 - > tflag1 & BME_BEVEL_NONMAN ) = = 0 & & BME_bevel_get_angle ( bm , e , e - > v2 ) < threshold ) {
e - > tflag1 | = BME_BEVEL_BEVEL ;
e - > v2 - > tflag1 | = BME_BEVEL_BEVEL ;
BME_bevel_add_vweight ( td , bm , e - > v2 , 1.0 , 1.0 , options ) ;
}
else {
BME_bevel_add_vweight ( td , bm , e - > v2 , 0.0 , 1.0 , options ) ;
}
}
//~ else if ((options & BME_BEVEL_VWEIGHT) && (options & BME_BEVEL_VERT) == 0) {
//~ if ((e->v1->tflag1 & BME_BEVEL_BEVEL) && (e->v2->tflag1 & BME_BEVEL_BEVEL)) {
//~ e->tflag1 |= BME_BEVEL_BEVEL;
//~ }
//~ }
else if ( ( options & BME_BEVEL_SELECT ) = = 0
& & ( options & BME_BEVEL_VERT ) = = 0 )
{
weight = 1.0 ;
}
if ( weight > 0.0 ) {
e - > tflag1 | = BME_BEVEL_BEVEL ;
BME_bevel_add_vweight ( td , bm , e - > v1 , weight , 1.0 , options ) ;
BME_bevel_add_vweight ( td , bm , e - > v2 , weight , 1.0 , options ) ;
}
if ( len ! = 2 | | options & BME_BEVEL_VERT ) {
e - > tflag1 & = ~ BME_BEVEL_BEVEL ;
}
}
/* face pass */
for ( f = bm - > polys . first ; f ; f = f - > next ) f - > tflag1 = BME_BEVEL_ORIG ;
2008-06-01 01:56:35 +00:00
/*clean up edges with 2 faces that share more than one edge*/
for ( e = bm - > edges . first ; e ; e = e - > next ) {
if ( e - > tflag1 & BME_BEVEL_BEVEL ) {
int count = 0 ;
count = BME_face_sharededges ( e - > loop - > f , ( ( BME_Loop * ) e - > loop - > radial . next - > data ) - > f ) ;
if ( count > 1 ) {
e - > tflag1 & = ~ BME_BEVEL_BEVEL ;
}
}
}
2008-02-23 22:11:16 +00:00
return bm ;
2011-11-28 03:01:06 +00:00
2008-02-23 22:11:16 +00:00
}
/* tags all elements as originals */
2008-02-25 04:53:37 +00:00
static BME_Mesh * BME_bevel_reinitialize ( BME_Mesh * bm ) {
2008-02-23 22:11:16 +00:00
BME_Vert * v ;
BME_Edge * e ;
BME_Poly * f ;
for ( v = bm - > verts . first ; v ; v = v - > next ) {
v - > tflag1 | = BME_BEVEL_ORIG ;
}
for ( e = bm - > edges . first ; e ; e = e - > next ) {
e - > tflag1 | = BME_BEVEL_ORIG ;
}
for ( f = bm - > polys . first ; f ; f = f - > next ) {
f - > tflag1 | = BME_BEVEL_ORIG ;
}
return bm ;
2011-11-28 03:01:06 +00:00
2008-02-23 22:11:16 +00:00
}
/**
* BME_bevel_mesh
*
* Mesh beveling tool :
*
* Bevels an entire mesh . It currently uses the tflag1 ' s of
* its vertices and edges to track topological changes .
* The parameter " value " is the distance to inset ( should be negative ) .
* The parameter " options " is not currently used .
*
* Returns -
* A BME_Mesh pointer to the BMesh passed as a parameter .
*/
2008-02-25 04:53:37 +00:00
static void bmesh_dissolve_disk ( BME_Mesh * bm , BME_Vert * v ) {
BME_Poly * f ;
BME_Edge * e ;
int done , len ;
if ( v - > edge ) {
done = 0 ;
while ( ! done ) {
done = 1 ;
e = v - > edge ; /*loop the edge looking for a edge to dissolve*/
do {
f = NULL ;
len = BME_cycle_length ( & ( e - > loop - > radial ) ) ;
if ( len = = 2 ) {
f = BME_JFKE_safe ( bm , e - > loop - > f , ( ( BME_Loop * ) ( e - > loop - > radial . next - > data ) ) - > f , e ) ;
}
if ( f ) {
done = 0 ;
break ;
}
e = BME_disk_nextedge ( e , v ) ;
} while ( e ! = v - > edge ) ;
}
2008-07-08 02:22:37 +00:00
BME_collapse_vert ( bm , v - > edge , v , 1.0 ) ;
//BME_JEKV(bm,v->edge,v);
2008-02-25 04:53:37 +00:00
}
}
2010-10-16 14:32:17 +00:00
static BME_Mesh * BME_bevel_mesh ( BME_Mesh * bm , float value , int res , int options , int UNUSED ( defgrp_index ) , BME_TransData_Head * td ) {
2008-02-24 11:16:37 +00:00
BME_Vert * v , * nv ;
BME_Edge * e , * oe ;
2008-02-23 22:11:16 +00:00
BME_Loop * l , * l2 ;
2008-02-25 04:53:37 +00:00
BME_Poly * f ;
unsigned int i , len ;
2008-02-23 22:11:16 +00:00
for ( f = bm - > polys . first ; f ; f = f - > next ) {
if ( f - > tflag1 & BME_BEVEL_ORIG ) {
BME_bevel_poly ( bm , f , value , options , td ) ;
}
}
/* here we will loop through all the verts to clean up the left over geometry */
/* crazy idea. when res == 0, don't remove the original geometry */
for ( v = bm - > verts . first ; v ; /* we may kill v, so increment in-loop */ ) {
nv = v - > next ;
if ( ( v - > tflag1 & BME_BEVEL_NONMAN ) & & ( v - > tflag1 & BME_BEVEL_BEVEL ) & & ( v - > tflag1 & BME_BEVEL_ORIG ) ) {
v = BME_bevel_wire ( bm , v , value , res , options , td ) ;
}
else if ( res & & ( ( v - > tflag1 & BME_BEVEL_BEVEL ) & & ( v - > tflag1 & BME_BEVEL_ORIG ) ) ) {
2008-06-01 01:56:35 +00:00
int count = 0 ;
2008-02-23 22:11:16 +00:00
/* first, make sure we're not sitting on an edge to be removed */
oe = v - > edge ;
e = BME_disk_nextedge ( oe , v ) ;
while ( ( e - > tflag1 & BME_BEVEL_BEVEL ) & & ( e - > tflag1 & BME_BEVEL_ORIG ) ) {
e = BME_disk_nextedge ( e , v ) ;
if ( e = = oe ) {
2008-02-25 04:53:37 +00:00
//printf("Something's wrong! We can't remove every edge here!\n");
2008-02-23 22:11:16 +00:00
break ;
}
}
/* look for original edges, and remove them */
oe = e ;
2008-03-07 03:24:23 +00:00
while ( ( e = BME_disk_next_edgeflag ( oe , v , 0 , BME_BEVEL_ORIG | BME_BEVEL_BEVEL ) ) ) {
2008-06-01 01:56:35 +00:00
count + + ;
2008-02-23 22:11:16 +00:00
/* join the faces (we'll split them later) */
f = BME_JFKE_safe ( bm , e - > loop - > f , ( ( BME_Loop * ) e - > loop - > radial . next - > data ) - > f , e ) ;
2008-03-10 19:32:20 +00:00
if ( ! f ) {
//printf("Non-manifold geometry not getting tagged right?\n");
}
2008-02-23 22:11:16 +00:00
}
2008-06-01 01:56:35 +00:00
/*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!*/
2008-02-23 22:11:16 +00:00
/* all original edges marked to be beveled have been removed;
* now we need to link up the edges for this " corner " */
len = BME_cycle_length ( BME_disk_getpointer ( v - > edge , v ) ) ;
for ( i = 0 , e = v - > edge ; i < len ; i + + , e = BME_disk_nextedge ( e , v ) ) {
l = e - > loop ;
l2 = l - > radial . next - > data ;
if ( l - > v ! = v ) l = l - > next ;
if ( l2 - > v ! = v ) l2 = l2 - > next ;
/* look for faces that have had the original edges removed via JFKE */
if ( l - > f - > len > 3 ) {
BME_split_face ( bm , l - > f , l - > next - > v , l - > prev - > v , & l , l - > e ) ; /* clip this corner off */
if ( len > 2 ) {
l - > e - > tflag1 | = BME_BEVEL_BEVEL ;
}
}
if ( l2 - > f - > len > 3 ) {
BME_split_face ( bm , l2 - > f , l2 - > next - > v , l2 - > prev - > v , & l , l2 - > e ) ; /* clip this corner off */
if ( len > 2 ) {
l - > e - > tflag1 | = BME_BEVEL_BEVEL ;
}
}
}
2008-02-25 04:53:37 +00:00
bmesh_dissolve_disk ( bm , v ) ;
2008-02-23 22:11:16 +00:00
}
v = nv ;
}
2008-02-24 06:23:20 +00:00
2008-02-23 22:11:16 +00:00
return bm ;
}
2008-02-25 04:53:37 +00:00
static BME_Mesh * BME_tesselate ( BME_Mesh * bm ) {
2008-02-23 22:11:16 +00:00
BME_Loop * l , * nextloop ;
BME_Poly * f ;
for ( f = bm - > polys . first ; f ; f = f - > next ) {
l = f - > loopbase ;
while ( l - > f - > len > 4 ) {
nextloop = l - > next - > next - > next ;
/* make a quad */
BME_split_face ( bm , l - > f , l - > v , nextloop - > v , NULL , l - > e ) ;
l = nextloop ;
}
}
return bm ;
}
2008-02-25 04:53:37 +00:00
/*Main bevel function:
Should be only one exported
*/
2008-02-23 22:11:16 +00:00
/* options that can be passed:
* BME_BEVEL_VWEIGHT < - - - - v , Look at vertex weights ; use defgrp_index if option is present
* BME_BEVEL_SELECT < - - - - v , e , check selection for verts and edges
* BME_BEVEL_ANGLE < - - - - v , e , don ' t bevel - tag verts - tag verts per edge
* BME_BEVEL_VERT < - - - - e , don ' t tag edges
* BME_BEVEL_EWEIGHT < - - - - e , use crease flag for now
* BME_BEVEL_PERCENT < - - - - Will need to think about this one ; will probably need to incorporate into actual bevel routine
* BME_BEVEL_RADIUS < - - - - Will need to think about this one ; will probably need to incorporate into actual bevel routine
* All weights / limits are stored per - vertex
*/
BME_Mesh * BME_bevel ( BME_Mesh * bm , float value , int res , int options , int defgrp_index , float angle , BME_TransData_Head * * rtd ) {
BME_Vert * v ;
BME_TransData_Head * td ;
BME_TransData * vtd ;
int i ;
float fac = 1 , d ;
td = BME_init_transdata ( BLI_MEMARENA_STD_BUFSIZE ) ;
BME_bevel_initialize ( bm , options , defgrp_index , angle , td ) ;
/* recursion math courtesy of Martin Poirier (theeth) */
for ( i = 0 ; i < res - 1 ; i + + ) {
if ( i = = 0 ) fac + = 1.0f / 3.0f ; else fac + = 1.0f / ( 3 * i * 2.0f ) ;
}
d = 1.0f / fac ;
/* crazy idea. if res == 0, don't remove original geometry */
for ( i = 0 ; i < res | | ( res = = 0 & & i = = 0 ) ; i + + ) {
if ( i ! = 0 ) BME_bevel_reinitialize ( bm ) ;
2008-02-25 04:53:37 +00:00
BME_model_begin ( bm ) ;
2008-02-23 22:11:16 +00:00
BME_bevel_mesh ( bm , d , res , options , defgrp_index , td ) ;
2008-02-25 04:53:37 +00:00
BME_model_end ( bm ) ;
2008-02-23 22:11:16 +00:00
if ( i = = 0 ) d / = 3 ; else d / = 2 ;
}
BME_tesselate ( bm ) ;
if ( rtd ) {
* rtd = td ;
return bm ;
}
/* transform pass */
for ( v = bm - > verts . first ; v ; v = v - > next ) {
2008-02-24 11:16:37 +00:00
if ( ( vtd = BME_get_transdata ( td , v ) ) ) {
2008-02-23 22:11:16 +00:00
if ( vtd - > max & & ( * vtd - > max > 0 & & value > * vtd - > max ) ) {
d = * vtd - > max ;
}
else {
d = value ;
}
2011-11-28 03:01:06 +00:00
madd_v3_v3v3fl ( v - > co , vtd - > org , vtd - > vec , vtd - > factor * d ) ;
2008-02-23 22:11:16 +00:00
}
v - > tflag1 = 0 ;
}
BME_free_transdata ( td ) ;
return bm ;
}