From 183c8e0a0a82f260c4db250f4b04bb3f650618c3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 7 Sep 2009 07:42:12 +0000 Subject: no functional changes, use hole rather then dutch 'gat' for bevel lists and made some comments English. --- source/blender/blenkernel/intern/curve.c | 10 +++++----- source/blender/imbuf/intern/anim5.c | 10 +++++----- source/blender/include/BIF_oops.h | 2 +- source/blender/makesdna/DNA_curve_types.h | 2 +- source/blender/src/editlattice.c | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 25af0cb5ce3..a1ad5347f7e 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1783,14 +1783,14 @@ void makeBevelList(Object *ob) bl= blnext; } - /* STEP 3: COUNT POLYS TELLEN AND AUTOHOLE */ + /* STEP 3: POLYS COUNT AND AUTOHOLE */ bl= cu->bev.first; poly= 0; while(bl) { if(bl->nr && bl->poly>=0) { poly++; bl->poly= poly; - bl->gat= 0; /* 'gat' is dutch for hole */ + bl->hole= 0; } bl= bl->next; } @@ -1842,7 +1842,7 @@ void makeBevelList(Object *ob) sd1= sortdata+ (a-1); for(b=a-1; b>=0; b--, sd1--) { /* all polys to the left */ if(bevelinside(sd1->bl, bl)) { - bl->gat= 1- sd1->bl->gat; + bl->hole= 1- sd1->bl->hole; break; } } @@ -1852,7 +1852,7 @@ void makeBevelList(Object *ob) if((cu->flag & CU_3D)==0) { sd= sortdata; for(a=0; abl->gat==sd->dir) { + if(sd->bl->hole==sd->dir) { bl= sd->bl; bevp1= (BevPoint *)(bl+1); bevp2= bevp1+ (bl->nr-1); @@ -2033,7 +2033,7 @@ void makeBevelList(Object *ob) } QUATCOPY(quat_prev, quat); /* quat_prev can't have the tilt applied */ VECCOPY(vec_prev, vec); - + AxisAngleToQuat(q, vec, bevp1->alfa); QuatMul(quat, q, quat); QuatToMat3(quat, bevp1->mat); diff --git a/source/blender/imbuf/intern/anim5.c b/source/blender/imbuf/intern/anim5.c index b6f29b6a145..2437d0d9568 100644 --- a/source/blender/imbuf/intern/anim5.c +++ b/source/blender/imbuf/intern/anim5.c @@ -204,12 +204,12 @@ static void anim5decode(struct ImBuf * ibuf, uchar * dlta) { int *ofspoint; uchar **planes; - /* samenstelling delta: - lijst met ofsets voor delta's per bitplane (ofspoint) - per kolom in delta (point) - aantal handelingen (noops) + /* composition delta: + list with ofsets for delta' s by bitplane (ofspoint) + by column in delta (point) + number of operations (noops) code - bijbehorende data + associated data ... ... */ diff --git a/source/blender/include/BIF_oops.h b/source/blender/include/BIF_oops.h index 2375a918d0e..c35acf584f1 100644 --- a/source/blender/include/BIF_oops.h +++ b/source/blender/include/BIF_oops.h @@ -61,7 +61,7 @@ struct Oops *add_test_oops(void *id); /* incl links */ void add_texture_oops(struct Material *ma); void build_oops(void); struct Oops *find_oops(ID *id); -void free_oops(struct Oops *oops); /* ook oops zelf */ +void free_oops(struct Oops *oops); /* also oops themselves */ void free_oopspace(struct SpaceOops *so); void new_oops_location(struct Oops *); int oops_test_overlap(struct Oops *test); diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 88c03a41160..60dba9ce018 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -61,7 +61,7 @@ typedef struct Path { typedef struct BevList { struct BevList *next, *prev; int nr, flag; - short poly, gat; + short poly, hole; } BevList; /* These two Lines with # tell makesdna this struct can be excluded. */ diff --git a/source/blender/src/editlattice.c b/source/blender/src/editlattice.c index 06b092a30ac..a65c51c76f6 100644 --- a/source/blender/src/editlattice.c +++ b/source/blender/src/editlattice.c @@ -25,7 +25,7 @@ * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** - * i.t.t. wat de naam doet vermoeden: ook algemene lattice (calc) functies + * what the name suggests: also general lattice (calc) functions */ #include -- cgit v1.2.3 From 4cb53d91ea1843dc0cb2c1d4c846e5a1974a20eb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 9 Sep 2009 18:09:03 +0000 Subject: Small code cleanup related to curves, to avoid cryptic names: renamed set_four_ipo -> key_curve_position_weights renamed set_afgeleide_four_ipo -> key_curve_tangent_weights added key_curve_normal_weights --- source/blender/blenkernel/BKE_key.h | 5 +- source/blender/blenkernel/intern/anim.c | 10 +-- source/blender/blenkernel/intern/curve.c | 4 +- source/blender/blenkernel/intern/key.c | 115 ++++++++++++++++----------- source/blender/blenkernel/intern/lattice.c | 6 +- source/blender/blenkernel/intern/object.c | 2 +- source/blender/blenkernel/intern/particle.c | 6 +- source/blender/blenkernel/intern/texture.c | 4 +- source/blender/blenloader/intern/readfile.c | 1 - source/blender/render/intern/source/strand.c | 4 +- 10 files changed, 91 insertions(+), 66 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index faf8692b89a..94a7a7482e4 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -51,8 +51,9 @@ struct Key *copy_key(struct Key *key); void make_local_key(struct Key *key); void sort_keys(struct Key *key); -void set_four_ipo(float d, float *data, int type); -void set_afgeleide_four_ipo(float d, float *data, int type); +void key_curve_position_weights(float t, float *data, int type); +void key_curve_tangent_weights(float t, float *data, int type); +void key_curve_normal_weights(float t, float *data, int type); /* only exported to curve.c! */ void cp_cu_key(struct Curve *cu, struct KeyBlock *kb, int start, int end); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index ffb7ff51b87..e75b31dd892 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -253,7 +253,7 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK /* note, commented out for follow constraint */ //if(cu->flag & CU_FOLLOW) { - set_afgeleide_four_ipo(1.0f-fac, data, KEY_BSPLINE); + key_curve_tangent_weights(1.0f-fac, data, KEY_BSPLINE); dir[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ; dir[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ; @@ -268,10 +268,10 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK nu= cu->nurb.first; /* make sure that first and last frame are included in the vectors here */ - if((nu->type & 7)==CU_POLY) set_four_ipo(1.0f-fac, data, KEY_LINEAR); - else if((nu->type & 7)==CU_BEZIER) set_four_ipo(1.0f-fac, data, KEY_LINEAR); - else if(s0==s1 || p2==p3) set_four_ipo(1.0f-fac, data, KEY_CARDINAL); - else set_four_ipo(1.0f-fac, data, KEY_BSPLINE); + if((nu->type & 7)==CU_POLY) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR); + else if((nu->type & 7)==CU_BEZIER) key_curve_position_weights(1.0f-fac, data, KEY_LINEAR); + else if(s0==s1 || p2==p3) key_curve_position_weights(1.0f-fac, data, KEY_CARDINAL); + else key_curve_position_weights(1.0f-fac, data, KEY_BSPLINE); vec[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ; vec[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ; diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index a1ad5347f7e..86cfe9d4c6f 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1476,7 +1476,7 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * if (nu->tilt_interp==3) { /* May as well support for tilt also 2.47 ease interp */ tilt_array[a] = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac); } else { - set_four_ipo(fac, t, nu->tilt_interp); + key_curve_position_weights(fac, t, nu->tilt_interp); tilt_array[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; } } @@ -1491,7 +1491,7 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * /* reuse interpolation from tilt if we can */ if (tilt_array==NULL || nu->tilt_interp != nu->radius_interp) { - set_four_ipo(fac, t, nu->radius_interp); + key_curve_position_weights(fac, t, nu->radius_interp); } radius_array[a]= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius; } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 755a41ec4b2..70136afc321 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -258,66 +258,91 @@ void sort_keys(Key *key) /**************** do the key ****************/ +void key_curve_position_weights(float t, float *data, int type) +{ + float t2, t3, fc; + + if(type==KEY_LINEAR) { + data[0]= 0.0f; + data[1]= -t + 1.0f; + data[2]= t; + data[3]= 0.0f; + } + else if(type==KEY_CARDINAL) { + t2= t*t; + t3= t2*t; + fc= 0.71f; + + data[0]= -fc*t3 + 2.0f*fc*t2 - fc*t; + data[1]= (2.0f-fc)*t3 + (fc-3.0f)*t2 + 1.0f; + data[2]= (fc-2.0f)*t3 + (3.0f-2.0f*fc)*t2 + fc*t; + data[3]= fc*t3 - fc*t2; + } + else if(type==KEY_BSPLINE) { + t2= t*t; + t3= t2*t; + + data[0]= -0.16666666f*t3 + 0.5f*t2 - 0.5f*t + 0.16666666f; + data[1]= 0.5f*t3 - t2 + 0.6666666f; + data[2]= -0.5f*t3 + 0.5f*t2 + 0.5f*t + 0.16666666f; + data[3]= 0.16666666f*t3; + } +} -void set_four_ipo(float d, float *data, int type) +/* first derivative */ +void key_curve_tangent_weights(float t, float *data, int type) { - float d2, d3, fc; + float t2, fc; if(type==KEY_LINEAR) { data[0]= 0.0f; - data[1]= 1.0f-d; - data[2]= d; + data[1]= -1.0f; + data[2]= 1.0f; data[3]= 0.0f; } - else { - d2= d*d; - d3= d2*d; + else if(type==KEY_CARDINAL) { + t2= t*t; + fc= 0.71f; - if(type==KEY_CARDINAL) { - - fc= 0.71f; - - data[0]= -fc*d3 +2.0f*fc*d2 -fc*d; - data[1]= (2.0f-fc)*d3 +(fc-3.0f)*d2 +1.0f; - data[2]= (fc-2.0f)*d3 +(3.0f-2.0f*fc)*d2 +fc*d; - data[3]= fc*d3 -fc*d2; - } - else if(type==KEY_BSPLINE) { + data[0]= -3.0f*fc*t2 +4.0f*fc*t - fc; + data[1]= 3.0f*(2.0f-fc)*t2 +2.0f*(fc-3.0f)*t; + data[2]= 3.0f*(fc-2.0f)*t2 +2.0f*(3.0f-2.0f*fc)*t + fc; + data[3]= 3.0f*fc*t2 -2.0f*fc*t; + } + else if(type==KEY_BSPLINE) { + t2= t*t; - data[0]= -0.16666666f*d3 +0.5f*d2 -0.5f*d +0.16666666f; - data[1]= 0.5f*d3 -d2 +0.6666666f; - data[2]= -0.5f*d3 +0.5f*d2 +0.5f*d +0.16666666f; - data[3]= 0.16666666f*d3 ; - } + data[0]= -0.5f*t2 + t - 0.5f; + data[1]= 1.5f*t2 - 2.0f*t; + data[2]= -1.5f*t2 + t + 0.5f; + data[3]= 0.5f*t2; } } -void set_afgeleide_four_ipo(float d, float *data, int type) +/* second derivative */ +void key_curve_normal_weights(float t, float *data, int type) { - float d2, fc; + float fc; if(type==KEY_LINEAR) { - + data[0]= 0.0f; + data[1]= 0.0f; + data[2]= 0.0f; + data[3]= 0.0f; } - else { - d2= d*d; + else if(type==KEY_CARDINAL) { + fc= 0.71f; - if(type==KEY_CARDINAL) { - - fc= 0.71f; - - data[0]= -3.0f*fc*d2 +4.0f*fc*d -fc; - data[1]= 3.0f*(2.0f-fc)*d2 +2.0f*(fc-3.0f)*d; - data[2]= 3.0f*(fc-2.0f)*d2 +2.0f*(3.0f-2.0f*fc)*d +fc; - data[3]= 3.0f*fc*d2 -2.0f*fc*d; - } - else if(type==KEY_BSPLINE) { - - data[0]= -0.16666666f*3.0f*d2 +d -0.5f; - data[1]= 1.5f*d2 -2.0f*d; - data[2]= -1.5f*d2 +d +0.5f; - data[3]= 0.16666666f*3.0f*d2 ; - } + data[0]= -6.0f*fc*t + 4.0f*fc; + data[1]= 6.0f*(2.0f-fc)*t + 2.0f*(fc-3.0f); + data[2]= 6.0f*(fc-2.0f)*t + 2.0f*(3.0f-2.0f*fc); + data[3]= 6.0f*fc*t - 2.0f*fc; + } + else if(type==KEY_BSPLINE) { + data[0]= -1.0f*t + 1.0f; + data[1]= 3.0f*t - 2.0f; + data[2]= -3.0f*t + 1.0f; + data[3]= 1.0f*t; } } @@ -428,10 +453,10 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl) /* interpolation */ - set_four_ipo(d, t, k[1]->type); + key_curve_position_weights(d, t, k[1]->type); if(k[1]->type != k[2]->type) { - set_four_ipo(d, fval, k[2]->type); + key_curve_position_weights(d, fval, k[2]->type); temp= 1.0f-d; t[0]= temp*t[0]+ d*fval[0]; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 6614c657647..07973d0de57 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -367,7 +367,7 @@ void calc_latt_deform(float *co, float weight) u= (vec[0]-lt->fu)/lt->du; ui= (int)floor(u); u -= ui; - set_four_ipo(u, tu, lt->typeu); + key_curve_position_weights(u, tu, lt->typeu); } else { tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0; @@ -378,7 +378,7 @@ void calc_latt_deform(float *co, float weight) v= (vec[1]-lt->fv)/lt->dv; vi= (int)floor(v); v -= vi; - set_four_ipo(v, tv, lt->typev); + key_curve_position_weights(v, tv, lt->typev); } else { tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0; @@ -389,7 +389,7 @@ void calc_latt_deform(float *co, float weight) w= (vec[2]-lt->fw)/lt->dw; wi= (int)floor(w); w -= wi; - set_four_ipo(w, tw, lt->typew); + key_curve_position_weights(w, tw, lt->typew); } else { tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ec068c35c11..572c217e919 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2312,7 +2312,7 @@ void object_handle_update(Object *ob) if(ob->recalc & OB_RECALC_DATA) { - // printf("recalcdata %s\n", ob->id.name+2); + printf("recalc data %s\n", ob->id.name); /* includes all keys and modifiers */ if(ob->type==OB_MESH) { diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index b5b2c07af9c..e8a84ccceb5 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -873,7 +873,7 @@ static void interpolate_particle(short type, ParticleKey keys[4], float dt, Part VecfCubicInterpol(keys[1].co, keys[1].vel, keys[2].co, keys[2].vel, dt, result->co, result->vel); } else { - set_four_ipo(dt, t, type); + key_curve_position_weights(dt, t, type); weighted_particle_vector(keys[0].co, keys[1].co, keys[2].co, keys[3].co, t, result->co); @@ -881,12 +881,12 @@ static void interpolate_particle(short type, ParticleKey keys[4], float dt, Part float temp[3]; if(dt>0.999f){ - set_four_ipo(dt-0.001f, t, type); + key_curve_position_weights(dt-0.001f, t, type); weighted_particle_vector(keys[0].co, keys[1].co, keys[2].co, keys[3].co, t, temp); VECSUB(result->vel, result->co, temp); } else{ - set_four_ipo(dt+0.001f, t, type); + key_curve_position_weights(dt+0.001f, t, type); weighted_particle_vector(keys[0].co, keys[1].co, keys[2].co, keys[3].co, t, temp); VECSUB(result->vel, temp, result->co); } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index be005af7827..f2c2498b39f 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -368,9 +368,9 @@ int do_colorband(ColorBand *coba, float in, float out[4]) CLAMP(fac, 0.0f, 1.0f); if(coba->ipotype==3) - set_four_ipo(fac, t, KEY_CARDINAL); + key_curve_position_weights(fac, t, KEY_CARDINAL); else - set_four_ipo(fac, t, KEY_BSPLINE); + key_curve_position_weights(fac, t, KEY_BSPLINE); out[0]= t[3]*cbd3->r +t[2]*cbd2->r +t[1]*cbd1->r +t[0]*cbd0->r; out[1]= t[3]*cbd3->g +t[2]*cbd2->g +t[1]*cbd1->g +t[0]*cbd0->g; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4e5789d87e8..61192ee0882 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -127,7 +127,6 @@ #include "BKE_global.h" // for G #include "BKE_group.h" #include "BKE_image.h" -#include "BKE_key.h" //void set_four_ipo #include "BKE_lattice.h" #include "BKE_library.h" // for wich_libbase #include "BKE_main.h" // for Main diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 05e36160f0e..88c275d0997 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -122,14 +122,14 @@ void strand_eval_point(StrandSegment *sseg, StrandPoint *spoint) spoint->dtstrandco *= 0.5f; } else { - set_four_ipo(t, data, type); + key_curve_position_weights(t, data, type); spoint->co[0]= data[0]*p[0][0] + data[1]*p[1][0] + data[2]*p[2][0] + data[3]*p[3][0]; spoint->co[1]= data[0]*p[0][1] + data[1]*p[1][1] + data[2]*p[2][1] + data[3]*p[3][1]; spoint->co[2]= data[0]*p[0][2] + data[1]*p[1][2] + data[2]*p[2][2] + data[3]*p[3][2]; spoint->strandco= (1.0f-t)*sseg->v[1]->strandco + t*sseg->v[2]->strandco; } - set_afgeleide_four_ipo(t, data, type); + key_curve_tangent_weights(t, data, type); spoint->dtco[0]= data[0]*p[0][0] + data[1]*p[1][0] + data[2]*p[2][0] + data[3]*p[3][0]; spoint->dtco[1]= data[0]*p[0][1] + data[1]*p[1][1] + data[2]*p[2][1] + data[3]*p[3][1]; spoint->dtco[2]= data[0]*p[0][2] + data[1]*p[1][2] + data[2]*p[2][2] + data[3]*p[3][2]; -- cgit v1.2.3 From 2fc4ee354574d52200544eec00aed95442cf4d04 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 10 Sep 2009 02:57:25 +0000 Subject: Curve cleanup Renamed BevPoint's members * x,y,z -> vec[3]; compatible with other functions. * f1 -> split_tag; used by displist to set the splitting flag. * f2 -> dupe_tag; used in curve.c to remove duplicates. BevList * flag -> dupe_nr; was being used as a counter for duplicate points. * use arithb.c functions where possible. * arrays for coords, tilt and radius were being allocated, then copied into the BevPoint's, now write directly into the values without allocing/freeing arrays. --- source/blender/blenkernel/BKE_curve.h | 2 +- source/blender/blenkernel/intern/anim.c | 28 ++-- source/blender/blenkernel/intern/armature.c | 8 +- source/blender/blenkernel/intern/colortools.c | 4 +- source/blender/blenkernel/intern/curve.c | 225 +++++++++----------------- source/blender/blenkernel/intern/displist.c | 40 ++--- source/blender/makesdna/DNA_curve_types.h | 6 +- source/blender/python/api2_2x/Geometry.c | 2 +- source/blender/src/drawipo.c | 4 +- source/blender/src/drawobject.c | 6 +- 10 files changed, 127 insertions(+), 198 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 79f4708fd41..2aa8e35391f 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -70,7 +70,7 @@ void minmaxNurb( struct Nurb *nu, float *min, float *max); void makeknots( struct Nurb *nu, short uv); void makeNurbfaces(struct Nurb *nu, float *coord_array, int rowstride); -void makeNurbcurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu); +void makeNurbcurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu, int stride); void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); float *make_orco_curve( struct Object *ob); float *make_orco_surf( struct Object *ob); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index e75b31dd892..2e08763821f 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -86,11 +86,11 @@ void free_path(Path *path) void calc_curvepath(Object *ob) { BevList *bl; - BevPoint *bevp, *bevpn, *bevpfirst, *bevplast, *tempbevp; + BevPoint *bevp, *bevpn, *bevpfirst, *bevplast; Curve *cu; Nurb *nu; Path *path; - float *fp, *dist, *maxdist, x, y, z; + float *fp, *dist, *maxdist, xyz[3]; float fac, d=0, fac1, fac2; int a, tot, cycl=0; float *ft; @@ -129,19 +129,12 @@ void calc_curvepath(Object *ob) *fp= 0; for(a=0; ax - bevp->x; - y= bevpfirst->y - bevp->y; - z= bevpfirst->z - bevp->z; - } - else { - tempbevp = bevp+1; - x= (tempbevp)->x - bevp->x; - y= (tempbevp)->y - bevp->y; - z= (tempbevp)->z - bevp->z; - } - *fp= *(fp-1)+ (float)sqrt(x*x+y*y+z*z); + if(cycl && a==tot-1) + VecSubf(xyz, bevpfirst->vec, bevp->vec); + else + VecSubf(xyz, (bevp+1)->vec, bevp->vec); + *fp= *(fp-1)+VecLength(xyz); bevp++; } @@ -178,14 +171,11 @@ void calc_curvepath(Object *ob) fac2= *(fp)-d; fac1= fac2/fac1; fac2= 1.0f-fac1; - - ft[0]= fac1*bevp->x+ fac2*(bevpn)->x; - ft[1]= fac1*bevp->y+ fac2*(bevpn)->y; - ft[2]= fac1*bevp->z+ fac2*(bevpn)->z; + + VecLerpf(ft, bevp->vec, bevpn->vec, fac2); ft[3]= fac1*bevp->alfa+ fac2*(bevpn)->alfa; ft+= 4; - } MEM_freeN(dist); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 1577eb4f850..9a73b3355ce 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -654,10 +654,10 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) if(bone->segments > MAX_BBONE_SUBDIV) bone->segments= MAX_BBONE_SUBDIV; - forward_diff_bezier(0.0, h1[0], h2[0], 0.0, data[0], MAX_BBONE_SUBDIV, 4); - forward_diff_bezier(0.0, h1[1], length + h2[1], length, data[0]+1, MAX_BBONE_SUBDIV, 4); - forward_diff_bezier(0.0, h1[2], h2[2], 0.0, data[0]+2, MAX_BBONE_SUBDIV, 4); - forward_diff_bezier(roll1, roll1 + 0.390464f*(roll2-roll1), roll2 - 0.390464f*(roll2-roll1), roll2, data[0]+3, MAX_BBONE_SUBDIV, 4); + forward_diff_bezier(0.0, h1[0], h2[0], 0.0, data[0], MAX_BBONE_SUBDIV, 4*sizeof(float)); + forward_diff_bezier(0.0, h1[1], length + h2[1], length, data[0]+1, MAX_BBONE_SUBDIV, 4*sizeof(float)); + forward_diff_bezier(0.0, h1[2], h2[2], 0.0, data[0]+2, MAX_BBONE_SUBDIV, 4*sizeof(float)); + forward_diff_bezier(roll1, roll1 + 0.390464f*(roll2-roll1), roll2 - 0.390464f*(roll2-roll1), roll2, data[0]+3, MAX_BBONE_SUBDIV, 4*sizeof(float)); equalize_bezier(data[0], bone->segments); // note: does stride 4! diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 1bc34aea9a1..96ff3264822 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -413,8 +413,8 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) for(a=0; atotpoint-1; a++, fp += 2*CM_RESOL) { correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a+1].vec[0], bezt[a+1].vec[1]); - forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a+1].vec[0][0], bezt[a+1].vec[1][0], fp, CM_RESOL-1, 2); - forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2); + forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a+1].vec[0][0], bezt[a+1].vec[1][0], fp, CM_RESOL-1, 2*sizeof(float)); + forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2*sizeof(float)); } /* store first and last handle for extrapolation, unit length */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 86cfe9d4c6f..4d10308be20 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -64,7 +64,6 @@ #include "BKE_library.h" #include "BKE_key.h" - /* globals */ extern ListBase editNurb; /* editcurve.c */ @@ -813,7 +812,7 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride) MEM_freeN(jend); } -void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu) +void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu, int stride) /* coord_array has to be 3*4*pntsu*resolu in size and zero-ed * tilt_array and radius_array will be written to if valid */ { @@ -897,10 +896,10 @@ void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radiu } } - coord_fp+= 3; + coord_fp = (float *)(((char *)coord_fp) + stride); - if (tilt_fp) tilt_fp++; - if (radius_fp) radius_fp++; + if (tilt_fp) tilt_fp = (float *)(((char *)tilt_fp) + stride); + if (radius_fp) radius_fp = (float *)(((char *)radius_fp) + stride); u+= ustep; } @@ -931,7 +930,7 @@ void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int i for(a=0; a<=it; a++) { *p= q0; - p+= stride; + p = (float *)(((char *)p)+stride); q0+= q1; q1+= q2; q2+= q3; @@ -1350,8 +1349,8 @@ static short bevelinside(BevList *bl1,BevList *bl2) /* take first vertex of possible hole */ bevp= (BevPoint *)(bl2+1); - hvec1[0]= bevp->x; - hvec1[1]= bevp->y; + hvec1[0]= bevp->vec[0]; + hvec1[1]= bevp->vec[1]; hvec1[2]= 0.0; VECCOPY(hvec2,hvec1); hvec2[0]+=1000; @@ -1364,16 +1363,16 @@ static short bevelinside(BevList *bl1,BevList *bl2) prevbevp= bevp+(nr-1); while(nr--) { - min= prevbevp->y; - max= bevp->y; + min= prevbevp->vec[0]; + max= bevp->vec[1]; if(maxy; + max= prevbevp->vec[1]; } if(min!=max) { if(min<=hvec1[1] && max>=hvec1[1]) { /* there's a transition, calc intersection point */ - mode= cu_isectLL(&(prevbevp->x),&(bevp->x),hvec1,hvec2,0,1,&lab,&mu,vec); + mode= cu_isectLL(prevbevp->vec, bevp->vec, hvec1, hvec2, 0, 1, &lab, &mu, vec); /* if lab==0.0 or lab==1.0 then the edge intersects exactly a transition only allow for one situation: we choose lab= 1.0 */ @@ -1446,12 +1445,15 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si } -static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, int resolu) +static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, int resolu, int stride) { BezTriple *pprev, *next, *last; float fac, dfac, t[4]; int a; + if(tilt_array==NULL && radius_array==NULL) + return; + last= nu->bezt+(nu->pntsu-1); /* returns a point */ @@ -1474,11 +1476,13 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * for(a=0; atilt_interp==3) { /* May as well support for tilt also 2.47 ease interp */ - tilt_array[a] = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac); + *tilt_array = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac); } else { key_curve_position_weights(fac, t, nu->tilt_interp); - tilt_array[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; + *tilt_array= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; } + + tilt_array = (float *)(((char *)tilt_array) + stride); } if (radius_array) { @@ -1486,15 +1490,17 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * /* Support 2.47 ease interp * Note! - this only takes the 2 points into account, * giving much more localized results to changes in radius, sometimes you want that */ - radius_array[a] = prevbezt->radius + (bezt->radius - prevbezt->radius)*(3.0f*fac*fac - 2.0f*fac*fac*fac); + *radius_array = prevbezt->radius + (bezt->radius - prevbezt->radius)*(3.0f*fac*fac - 2.0f*fac*fac*fac); } else { /* reuse interpolation from tilt if we can */ if (tilt_array==NULL || nu->tilt_interp != nu->radius_interp) { key_curve_position_weights(fac, t, nu->radius_interp); } - radius_array[a]= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius; + *radius_array= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius; } + + radius_array = (float *)(((char *)radius_array) + stride); } } } @@ -1514,8 +1520,6 @@ void makeBevelList(Object *ob) BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; float min, inp, x1, x2, y1, y2, vec[3], vec_prev[3], q[4], quat[4], quat_prev[4], cross[3]; - float *coord_array, *tilt_array=NULL, *radius_array=NULL, *coord_fp, *tilt_fp=NULL, *radius_fp=NULL; - float *v1, *v2; struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu, len=0; int do_tilt, do_radius; @@ -1558,17 +1562,15 @@ void makeBevelList(Object *ob) if(nu->flagu & CU_CYCLIC) bl->poly= 0; else bl->poly= -1; bl->nr= len; - bl->flag= 0; + bl->dupe_nr= 0; bevp= (BevPoint *)(bl+1); bp= nu->bp; while(len--) { - bevp->x= bp->vec[0]; - bevp->y= bp->vec[1]; - bevp->z= bp->vec[2]; + VECCOPY(bevp->vec, bp->vec); bevp->alfa= bp->alfa; bevp->radius= bp->radius; - bevp->f1= SELECT; + bevp->split_tag= TRUE; bevp++; bp++; } @@ -1594,88 +1596,52 @@ void makeBevelList(Object *ob) bezt++; } - coord_array= coord_fp= MEM_mallocN(3*sizeof(float)*(resolu+1), "makeBevelCoords"); - - if(do_tilt) - tilt_array= tilt_fp= MEM_callocN(sizeof(float)*(resolu+1), "makeBevelTilt"); - - if (do_radius) - radius_array= radius_fp= MEM_callocN(sizeof(float)*(resolu+1), "nakeBevelRadius"); - while(a--) { if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) { - - bevp->x= prevbezt->vec[1][0]; - bevp->y= prevbezt->vec[1][1]; - bevp->z= prevbezt->vec[1][2]; + + VECCOPY(bevp->vec, prevbezt->vec[1]); bevp->alfa= prevbezt->alfa; bevp->radius= prevbezt->radius; - bevp->f1= SELECT; - bevp->f2= 0; + bevp->split_tag= TRUE; + bevp->dupe_tag= FALSE; bevp++; bl->nr++; - bl->flag= 1; + bl->dupe_nr= 1; } else { - v1= prevbezt->vec[1]; - v2= bezt->vec[0]; - /* always do all three, to prevent data hanging around */ - forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], coord_array, resolu, 3); - forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], coord_array+1, resolu, 3); - forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], coord_array+2, resolu, 3); + int j; + + /* BevPoint must stay aligned to 4 so sizeof(BevPoint)/sizeof(float) works */ + for(j=0; j<3; j++) { + forward_diff_bezier( prevbezt->vec[1][j], prevbezt->vec[2][j], + bezt->vec[0][j], bezt->vec[1][j], + &(bevp->vec[j]), resolu, sizeof(BevPoint)); + } - if (do_tilt || do_radius) - alfa_bezpart(prevbezt, bezt, nu, tilt_array, radius_array, resolu); + /* if both arrays are NULL do nothiong */ + alfa_bezpart( prevbezt, bezt, nu, + do_tilt ? &bevp->alfa : NULL, + do_radius ? &bevp->radius : NULL, + resolu, sizeof(BevPoint)); /* indicate with handlecodes double points */ if(prevbezt->h1==prevbezt->h2) { - if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= SELECT; + if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->split_tag= TRUE; } else { - if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= SELECT; - else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= SELECT; - } - - nr= resolu; - - coord_fp = coord_array; - tilt_fp = tilt_array; - radius_fp = radius_array; - - while(nr--) { - bevp->x= coord_fp[0]; - bevp->y= coord_fp[1]; - bevp->z= coord_fp[2]; - coord_fp+=3; - - if (do_tilt) { - bevp->alfa= *tilt_fp; - tilt_fp++; - } - - if (do_radius) { - bevp->radius= *radius_fp; - radius_fp++; - } - bevp++; + if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->split_tag= TRUE; + else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->split_tag= TRUE; } bl->nr+= resolu; - + bevp+= resolu; } prevbezt= bezt; bezt++; } - MEM_freeN(coord_array); - if (do_tilt) MEM_freeN(tilt_array); - if (do_radius) MEM_freeN(radius_array); - coord_array = tilt_array = radius_array = NULL; - if((nu->flagu & CU_CYCLIC)==0) { /* not cyclic: endpoint */ - bevp->x= prevbezt->vec[1][0]; - bevp->y= prevbezt->vec[1][1]; - bevp->z= prevbezt->vec[1][2]; + VECCOPY(bevp->vec, prevbezt->vec[1]); bevp->alfa= prevbezt->alfa; bevp->radius= prevbezt->radius; bl->nr++; @@ -1688,45 +1654,15 @@ void makeBevelList(Object *ob) bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); BLI_addtail(&(cu->bev), bl); bl->nr= len; - bl->flag= 0; + bl->dupe_nr= 0; if(nu->flagu & CU_CYCLIC) bl->poly= 0; else bl->poly= -1; bevp= (BevPoint *)(bl+1); - - coord_array= coord_fp= MEM_callocN(3*sizeof(float)*len, "makeBevelCoords"); /* has to be zero-ed */ - - if(do_tilt) - tilt_array= tilt_fp= MEM_callocN(sizeof(float)*len, "makeBevelTilt"); - - if (do_radius) - radius_array= radius_fp= MEM_callocN(sizeof(float)*len, "nakeBevelRadius"); - - makeNurbcurve(nu, coord_array, tilt_array, radius_array, resolu); - while(len--) { - bevp->x= coord_fp[0]; - bevp->y= coord_fp[1]; - bevp->z= coord_fp[2]; - coord_fp+=3; - - if (do_tilt) { - bevp->alfa= *tilt_fp; - tilt_fp++; - } - - if (do_radius) { - bevp->radius= *radius_fp; - radius_fp++; - } - - - bevp->f1= bevp->f2= 0; - bevp++; - } - MEM_freeN(coord_array); - if (do_tilt) MEM_freeN(tilt_array); - if (do_radius) MEM_freeN(radius_array); - coord_array = tilt_array = radius_array = NULL; + makeNurbcurve( nu, &bevp->vec[0], + do_tilt ? &bevp->alfa : NULL, + do_radius ? &bevp->radius : NULL, + resolu, sizeof(BevPoint)); } } } @@ -1742,11 +1678,11 @@ void makeBevelList(Object *ob) bevp0= bevp1+(nr-1); nr--; while(nr--) { - if( fabs(bevp0->x-bevp1->x)<0.00001 ) { - if( fabs(bevp0->y-bevp1->y)<0.00001 ) { - if( fabs(bevp0->z-bevp1->z)<0.00001 ) { - bevp0->f2= SELECT; - bl->flag++; + if( fabs(bevp0->vec[0]-bevp1->vec[0])<0.00001 ) { + if( fabs(bevp0->vec[1]-bevp1->vec[1])<0.00001 ) { + if( fabs(bevp0->vec[2]-bevp1->vec[2])<0.00001 ) { + bevp0->dupe_tag= TRUE; + bl->dupe_nr++; } } } @@ -1759,8 +1695,8 @@ void makeBevelList(Object *ob) bl= cu->bev.first; while(bl) { blnext= bl->next; - if(bl->nr && bl->flag) { - nr= bl->nr- bl->flag+1; /* +1 because vectorbezier sets flag too */ + if(bl->nr && bl->dupe_nr) { + nr= bl->nr- bl->dupe_nr+1; /* +1 because vectorbezier sets flag too */ blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList4"); memcpy(blnew, bl, sizeof(BevList)); blnew->nr= 0; @@ -1770,7 +1706,7 @@ void makeBevelList(Object *ob) bevp1= (BevPoint *)(blnew+1); nr= bl->nr; while(nr--) { - if(bevp0->f2==0) { + if(bevp0->dupe_tag==0) { memcpy(bevp1, bevp0, sizeof(BevPoint)); bevp1++; blnew->nr++; @@ -1778,7 +1714,7 @@ void makeBevelList(Object *ob) bevp0++; } MEM_freeN(bl); - blnew->flag= 0; + blnew->dupe_nr= 0; } bl= blnext; } @@ -1807,8 +1743,8 @@ void makeBevelList(Object *ob) bevp= (BevPoint *)(bl+1); nr= bl->nr; while(nr--) { - if(min>bevp->x) { - min= bevp->x; + if(min>bevp->vec[0]) { + min= bevp->vec[0]; bevp1= bevp; } bevp++; @@ -1823,8 +1759,7 @@ void makeBevelList(Object *ob) if(bevp1== bevp) bevp2= (BevPoint *)(bl+1); else bevp2= bevp1+1; - inp= (bevp1->x- bevp0->x)*(bevp0->y- bevp2->y) - +(bevp0->y- bevp1->y)*(bevp0->x- bevp2->x); + inp= (bevp1->vec[0]- bevp0->vec[0]) * (bevp0->vec[1]- bevp2->vec[1]) + (bevp0->vec[1]- bevp1->vec[1]) * (bevp0->vec[0]- bevp2->vec[0]); if(inp>0.0) sd->dir= 1; else sd->dir= 0; @@ -1879,8 +1814,8 @@ void makeBevelList(Object *ob) bevp2= (BevPoint *)(bl+1); bevp1= bevp2+1; - x1= bevp1->x- bevp2->x; - y1= bevp1->y- bevp2->y; + x1= bevp1->vec[0]- bevp2->vec[0]; + y1= bevp1->vec[1]- bevp2->vec[1]; calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa)); bevp2->sina= bevp1->sina; @@ -1889,7 +1824,7 @@ void makeBevelList(Object *ob) if(cu->flag & CU_3D) { /* 3D */ float quat[4], q[4]; - VecSubf(vec, &bevp1->x, &bevp2->x); + VecSubf(vec, bevp1->vec, bevp2->vec); vectoquat(vec, 5, 1, quat); @@ -1924,7 +1859,7 @@ void makeBevelList(Object *ob) while(nr--) { /* Normalizes */ - VecBisect3(vec, &bevp0->x, &bevp1->x, &bevp2->x); + VecBisect3(vec, bevp0->vec, bevp1->vec, bevp2->vec); if(bl->nr==nr+1) { /* first time */ vectoquat(vec, 5, 1, quat); @@ -1976,7 +1911,7 @@ void makeBevelList(Object *ob) nr= bl->nr; while(nr--) { - VecBisect3(vec, &bevp0->x, &bevp1->x, &bevp2->x); + VecBisect3(vec, bevp0->vec, bevp1->vec, bevp2->vec); quat_tmp1= (float *)bevp1->mat; quat_tmp2= quat_tmp1+4; @@ -1989,10 +1924,10 @@ void makeBevelList(Object *ob) QuatToMat3(quat, bevp1->mat); /* generic */ - x1= bevp1->x- bevp0->x; - x2= bevp1->x- bevp2->x; - y1= bevp1->y- bevp0->y; - y2= bevp1->y- bevp2->y; + x1= bevp1->vec[0]- bevp0->vec[0]; + x2= bevp1->vec[0]- bevp2->vec[0]; + y1= bevp1->vec[1]- bevp0->vec[1]; + y2= bevp1->vec[1]- bevp2->vec[1]; calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); @@ -2014,7 +1949,7 @@ void makeBevelList(Object *ob) if(cu->flag & CU_3D) { /* 3D */ /* Normalizes */ - VecBisect3(vec, &bevp0->x, &bevp1->x, &bevp2->x); + VecBisect3(vec, bevp0->vec, bevp1->vec, bevp2->vec); if(bl->nr==nr+1 || !(cu->flag & CU_NO_TWIST)) { /* first time */ vectoquat(vec, 5, 1, quat); @@ -2039,10 +1974,10 @@ void makeBevelList(Object *ob) QuatToMat3(quat, bevp1->mat); } - x1= bevp1->x- bevp0->x; - x2= bevp1->x- bevp2->x; - y1= bevp1->y- bevp0->y; - y2= bevp1->y- bevp2->y; + x1= bevp1->vec[0]- bevp0->vec[0]; + x2= bevp1->vec[0]- bevp2->vec[0]; + y1= bevp1->vec[1]- bevp0->vec[1]; + y2= bevp1->vec[1]- bevp2->vec[1]; calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index afc769b0966..c55dc8addb1 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -804,7 +804,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) DispList *dl; BezTriple *bezt, *prevbezt; BPoint *bp; - float *data, *v1, *v2; + float *data; int a, len, resolu; nu= nubase->first; @@ -869,11 +869,15 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) data+= 3; } else { - v1= prevbezt->vec[1]; - v2= bezt->vec[0]; - forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], data, resolu, 3); - forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], data+1, resolu, 3); - forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], data+2, resolu, 3); + int j; + for(j=0; j<3; j++) { + forward_diff_bezier( prevbezt->vec[1][j], + prevbezt->vec[2][j], + bezt->vec[0][j], + bezt->vec[1][j], + data+j, resolu, 3*sizeof(float)); + } + data+= 3*resolu; } @@ -900,7 +904,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) data= dl->verts; if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, NULL, NULL, resolu); + makeNurbcurve(nu, data, NULL, NULL, resolu, 3*sizeof(float)); } else if((nu->type & 7)==CU_POLY) { len= nu->pntsu; @@ -1397,7 +1401,7 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender, int forOrco if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, NULL, NULL, nu->resolu); + makeNurbcurve(nu, data, NULL, NULL, nu->resolu, 3*sizeof(float)); } else { len= (nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv); @@ -1508,9 +1512,9 @@ void makeDispListCurveTypes(Object *ob, int forOrco) bevp= (BevPoint *)(bl+1); data= dl->verts; while(a--) { - data[0]= bevp->x+widfac*bevp->sina; - data[1]= bevp->y+widfac*bevp->cosa; - data[2]= bevp->z; + data[0]= bevp->vec[0]+widfac*bevp->sina; + data[1]= bevp->vec[1]+widfac*bevp->cosa; + data[2]= bevp->vec[2]; bevp++; data+=3; } @@ -1550,7 +1554,7 @@ void makeDispListCurveTypes(Object *ob, int forOrco) fac = calc_taper(cu->taperobj, a, bl->nr); } - if (bevp->f1) { + if (bevp->split_tag) { dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F); } @@ -1566,14 +1570,14 @@ void makeDispListCurveTypes(Object *ob, int forOrco) Mat3MulVecfl(bevp->mat, vec); - data[0]= bevp->x+ fac*vec[0]; - data[1]= bevp->y+ fac*vec[1]; - data[2]= bevp->z+ fac*vec[2]; + data[0]= bevp->vec[0] + fac*vec[0]; + data[1]= bevp->vec[1] + fac*vec[1]; + data[2]= bevp->vec[2] + fac*vec[2]; } else { - data[0]= bevp->x+ fac*(widfac+fp1[1])*bevp->sina; - data[1]= bevp->y+ fac*(widfac+fp1[1])*bevp->cosa; - data[2]= bevp->z+ fac*fp1[2]; + data[0]= bevp->vec[0] + fac*(widfac+fp1[1])*bevp->sina; + data[1]= bevp->vec[1] + fac*(widfac+fp1[1])*bevp->cosa; + data[2]= bevp->vec[2] + fac*fp1[2]; } } } diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 60dba9ce018..65d8cc6fbc6 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -60,7 +60,7 @@ typedef struct Path { # typedef struct BevList { struct BevList *next, *prev; - int nr, flag; + int nr, dupe_nr; short poly, hole; } BevList; @@ -68,8 +68,8 @@ typedef struct BevList { # # typedef struct BevPoint { - float x, y, z, alfa, radius, sina, cosa, mat[3][3]; - short f1, f2; + float vec[3], mat[3][3], alfa, radius, sina, cosa; + short split_tag, dupe_tag; } BevPoint; /* Keyframes on IPO curves and Points on Bezier Curves/Paths are generally BezTriples */ diff --git a/source/blender/python/api2_2x/Geometry.c b/source/blender/python/api2_2x/Geometry.c index e5679ea6ed7..4297453c91e 100644 --- a/source/blender/python/api2_2x/Geometry.c +++ b/source/blender/python/api2_2x/Geometry.c @@ -509,7 +509,7 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args ) coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "BezierInterp"); for(i=0; imat[2][2]; glBegin(GL_LINE_STRIP); - glVertex3f(bevp->x - ox - dx, bevp->y - oy - dy, bevp->z - oz - dz); - glVertex3f(bevp->x, bevp->y, bevp->z); - glVertex3f(bevp->x + ox - dx, bevp->y + oy - dy, bevp->z + oz - dz); + glVertex3f(bevp->vec[0] - ox - dx, bevp->vec[1] - oy - dy, bevp->vec[2] - oz - dz); + glVertex3fv(bevp->vec); + glVertex3f(bevp->vec[0] + ox - dx, bevp->vec[1] + oy - dy, bevp->vec[2] + oz - dz); glEnd(); bevp += skip+1; -- cgit v1.2.3 From cfb6f35f9fd2905b7d51b78258f98ab45d2c5ced Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 10 Sep 2009 14:20:21 +0000 Subject: UI: * layout.itemR now has icon_only option to show only icon in e.g. enums buttons, for uv editor header. * Automatic key shortcuts in menus now show the shortcut even if operator properties don't match. Not sure this will work well everywhere, but seems to be working ok for now. * Open recent now show shorter filenames instead of the whole file path. * Tweak object Duplicate menu item. --- source/blender/blenlib/BLI_fileops.h | 1 + source/blender/blenlib/intern/fileops.c | 25 ++++++++++++++ source/blender/editors/include/UI_interface.h | 1 + .../blender/editors/interface/interface_layout.c | 31 +++++++++-------- source/blender/editors/interface/interface_utils.c | 7 +++- source/blender/editors/object/object_add.c | 2 +- source/blender/editors/object/object_ops.c | 2 +- source/blender/windowmanager/intern/wm_keymap.c | 40 +++++++++++++++------- source/blender/windowmanager/intern/wm_operators.c | 2 +- 9 files changed, 79 insertions(+), 32 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 0c1cdbc4d3a..b79920b188b 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -54,6 +54,7 @@ char *BLI_last_slash(const char *string); int BLI_add_slash(char *string); void BLI_del_slash(char *string); char *first_slash(char *string); +const char *BLI_short_filename(const char *string); /* only for the sane unix world: direct calls to system functions :( */ #ifndef WIN32 diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index e7dc9b0eb1f..15277c438f4 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -84,6 +84,31 @@ char *BLI_last_slash(const char *string) { else return lfslash; } +static const char *last_slash_len(const char *string, int len) { + int a; + + for(a=len-1; a>=0; a--) + if(string[a] == '/' || string[a] == '\\') + return &string[a]; + + return NULL; +} + +const char *BLI_short_filename(const char *string) { + const char *ls, *lls; + + ls= last_slash_len(string, strlen(string)); + if(!ls) + return string; + + lls= last_slash_len(string, ls-string); + + if(lls) + return lls+1; + else + return ls+1; +} + /* adds a slash if there isnt one there alredy */ int BLI_add_slash(char *string) { int len = strlen(string); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index e2338078a8a..b45ab2d4997 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -589,6 +589,7 @@ void UI_exit(void); #define UI_ITEM_R_EXPAND 2 #define UI_ITEM_R_SLIDER 4 #define UI_ITEM_R_TOGGLE 8 +#define UI_ITEM_R_ICON_ONLY 16 uiLayout *uiBlockLayout(uiBlock *block, int dir, int type, int x, int y, int size, int em, struct uiStyle *style); void uiBlockSetCurLayout(uiBlock *block, uiLayout *layout); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 04d575d96d4..bf449dba597 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -443,7 +443,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, char *name, int icon uiBlockSetCurLayout(block, layout); } -static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, char *uiname, int x, int y, int w, int h) +static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, char *uiname, int x, int y, int w, int h, int icon_only) { EnumPropertyItem *item; const char *identifier; @@ -463,7 +463,7 @@ static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, value= item[a].value; itemw= ui_text_icon_width(block->curlayout, name, icon, 0); - if(icon && strcmp(name, "") != 0) + if(icon && strcmp(name, "") != 0 && !icon_only) uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL); else if(icon) uiDefIconButR(block, ROW, 0, icon, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL); @@ -477,7 +477,7 @@ static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, } /* create label + button for RNA property */ -static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h) +static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h, int icon_only) { uiLayout *sub; uiBut *but; @@ -506,7 +506,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, i but= uiDefIconButO(block, BUT, "BUTTONS_OT_file_browse", WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, "Browse for file or directory."); } else - but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h); + but= uiDefAutoButR(block, ptr, prop, index, (icon_only)? "": NULL, icon, x, y, w, h); uiBlockSetCurLayout(block, layout); return but; @@ -788,7 +788,7 @@ void uiItemO(uiLayout *layout, char *name, int icon, char *opname) /* RNA property items */ -static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int *r_w, int *r_h) +static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int icon_only, int *r_w, int *r_h) { PropertyType type; PropertySubType subtype; @@ -799,9 +799,9 @@ static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PointerRNA subtype= RNA_property_subtype(prop); len= RNA_property_array_length(ptr, prop); - if(ELEM3(type, PROP_STRING, PROP_POINTER, PROP_ENUM) && !name[0]) + if(ELEM3(type, PROP_STRING, PROP_POINTER, PROP_ENUM) && !name[0] && !icon_only) name= "non-empty text"; - else if(type == PROP_BOOLEAN && !name[0]) + else if(type == PROP_BOOLEAN && !name[0] && !icon_only) icon= ICON_DOT; w= ui_text_icon_width(layout, name, icon, 0); @@ -823,7 +823,7 @@ static void ui_item_rna_size(uiLayout *layout, char *name, int icon, PointerRNA if(type == PROP_BOOLEAN && strcmp(name, "") != 0) w += UI_UNIT_X/5; else if(type == PROP_ENUM) - w += UI_UNIT_X/2; + w += UI_UNIT_X/4; else if(type == PROP_FLOAT || type == PROP_INT) w += UI_UNIT_X*3; } @@ -838,7 +838,7 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper uiBut *but; PropertyType type; char namestr[UI_MAX_NAME_STR]; - int len, w, h, slider, toggle, expand; + int len, w, h, slider, toggle, expand, icon_only; if(!ptr->data || !prop) return; @@ -872,9 +872,10 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper slider= (flag & UI_ITEM_R_SLIDER); toggle= (flag & UI_ITEM_R_TOGGLE); expand= (flag & UI_ITEM_R_EXPAND); + icon_only= (flag & UI_ITEM_R_ICON_ONLY); /* get size */ - ui_item_rna_size(layout, name, icon, ptr, prop, index, &w, &h); + ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, &w, &h); /* array property */ if(index == RNA_NO_INDEX && len > 0) @@ -883,7 +884,7 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper else if(type == PROP_ENUM && index == RNA_ENUM_VALUE) { char *identifier= (char*)RNA_property_identifier(prop); - if(icon && strcmp(name, "") != 0) + if(icon && strcmp(name, "") != 0 && !icon_only) uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL); else if(icon) uiDefIconButR(block, ROW, 0, icon, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL); @@ -892,10 +893,10 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper } /* expanded enum */ else if(type == PROP_ENUM && expand) - ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h); + ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h, icon_only); /* property with separate label */ else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) { - but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h); + but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h, icon_only); ui_but_add_search(but, ptr, prop, NULL, NULL); } /* single button */ @@ -1160,8 +1161,8 @@ void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *p /* create button */ block= uiLayoutGetBlock(layout); - ui_item_rna_size(layout, name, icon, ptr, prop, 0, &w, &h); - but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h); + ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, &w, &h); + but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0); ui_but_add_search(but, ptr, prop, searchptr, searchprop); } diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 5b44f6544d1..63f81c9e46c 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -108,7 +108,12 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind but= uiDefButR(block, NUM, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); break; case PROP_ENUM: - but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + if(icon && name && strcmp(name, "") == 0) + but= uiDefIconButR(block, MENU, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + else if(icon) + but= uiDefIconTextButR(block, MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + else + but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); break; case PROP_STRING: if(icon && name && strcmp(name, "") == 0) diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index eaf7d41b9fe..f4c8c63c480 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1122,7 +1122,7 @@ void OBJECT_OT_convert(wmOperatorType *ot) RNA_def_boolean(ot->srna, "keep_original", 0, "Keep Original", "Keep original objects instead of replacing them."); } -/************************** Add Duplicate **********************/ +/**************************** Duplicate ************************/ /* dupflag: a flag made from constants declared in DNA_userdef_types.h diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index bb8c5dc292e..ddcecdeb1f1 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -176,7 +176,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(LATTICE_OT_make_regular); /* macros */ - ot= WM_operatortype_append_macro("OBJECT_OT_duplicate_move", "Add Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER); + ot= WM_operatortype_append_macro("OBJECT_OT_duplicate_move", "Duplicate", OPTYPE_UNDO|OPTYPE_REGISTER); if(ot) { WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate"); WM_operatortype_macro_define(ot, "TFM_OT_translate"); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index ad0dd786791..5566aeba260 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -242,33 +242,41 @@ static char *wm_keymap_item_to_string(wmKeymapItem *kmi, char *str, int len) return str; } -static wmKeymapItem *wm_keymap_item_find_handlers(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties) +static wmKeymapItem *wm_keymap_item_find_handlers(ListBase *handlers, const char *opname, int opcontext, IDProperty *properties, int compare_props) { wmEventHandler *handler; wmKeymapItem *kmi; /* find keymap item in handlers */ - for(handler=handlers->first; handler; handler=handler->next) - if(handler->keymap) - for(kmi=handler->keymap->first; kmi; kmi=kmi->next) - if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) - if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) + for(handler=handlers->first; handler; handler=handler->next) { + if(handler->keymap) { + for(kmi=handler->keymap->first; kmi; kmi=kmi->next) { + if(strcmp(kmi->idname, opname) == 0 && WM_key_event_string(kmi->type)[0]) { + if(compare_props) { + if(kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) + return kmi; + } + else return kmi; + } + } + } + } return NULL; } -static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname, int opcontext, IDProperty *properties) +static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname, int opcontext, IDProperty *properties, int compare_props) { wmKeymapItem *found= NULL; /* look into multiple handler lists to find the item */ if(CTX_wm_window(C)) - found= wm_keymap_item_find_handlers(&CTX_wm_window(C)->handlers, opname, opcontext, properties); + found= wm_keymap_item_find_handlers(&CTX_wm_window(C)->handlers, opname, opcontext, properties, compare_props); if(CTX_wm_area(C) && found==NULL) - found= wm_keymap_item_find_handlers(&CTX_wm_area(C)->handlers, opname, opcontext, properties); + found= wm_keymap_item_find_handlers(&CTX_wm_area(C)->handlers, opname, opcontext, properties, compare_props); if(found==NULL) { if(ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { @@ -279,12 +287,12 @@ static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname, break; if(ar) - found= wm_keymap_item_find_handlers(&ar->handlers, opname, opcontext, properties); + found= wm_keymap_item_find_handlers(&ar->handlers, opname, opcontext, properties, compare_props); } } else { if(CTX_wm_region(C)) - found= wm_keymap_item_find_handlers(&CTX_wm_region(C)->handlers, opname, opcontext, properties); + found= wm_keymap_item_find_handlers(&CTX_wm_region(C)->handlers, opname, opcontext, properties, compare_props); } } @@ -293,7 +301,10 @@ static wmKeymapItem *wm_keymap_item_find(const bContext *C, const char *opname, char *WM_key_event_operator_string(const bContext *C, const char *opname, int opcontext, IDProperty *properties, char *str, int len) { - wmKeymapItem *found= wm_keymap_item_find(C, opname, opcontext, properties); + wmKeymapItem *found= wm_keymap_item_find(C, opname, opcontext, properties, 1); + + if(!found) + found= wm_keymap_item_find(C, opname, opcontext, properties, 0); if(found) { wm_keymap_item_to_string(found, str, len); @@ -306,7 +317,10 @@ char *WM_key_event_operator_string(const bContext *C, const char *opname, int op /* searches context and changes keymap item, if found */ void WM_key_event_operator_change(const bContext *C, const char *opname, int opcontext, IDProperty *properties, short key, short modifier) { - wmKeymapItem *found= wm_keymap_item_find(C, opname, opcontext, properties); + wmKeymapItem *found= wm_keymap_item_find(C, opname, opcontext, properties, 1); + + if(!found) + found= wm_keymap_item_find(C, opname, opcontext, properties, 0); if(found) { keymap_event_set(found, key, KM_PRESS, modifier, 0); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 0913d58258f..6debe5a8825 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -837,7 +837,7 @@ static EnumPropertyItem *open_recentfile_itemf(bContext *C, PointerRNA *ptr, int for(recent = G.recent_files.first, i=0; (inext, i++) { tmp.value= i+ofs+1; tmp.identifier= recent->filename; - tmp.name= recent->filename; + tmp.name= BLI_short_filename(recent->filename); RNA_enum_item_add(&item, &totitem, &tmp); } -- cgit v1.2.3 From e19537efccce4a8fd15f5b2b2baa51c4edef3b4e Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Thu, 10 Sep 2009 20:31:15 +0000 Subject: SVN maintenance. --- source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c | 2 +- source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c | 2 +- source/blender/nodes/intern/CMP_nodes/CMP_levels.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender') diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c index 0a4d3fceff9..470d04d9dcc 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c @@ -1,5 +1,5 @@ /** - * $Id: CMP_colorMatte.c 12931 2007-12-17 18:20:48Z theeth $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c b/source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c index 921ac869cb8..f24aedd6661 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c @@ -1,5 +1,5 @@ /** - * $Id: CMP_diffMatte.c 12931 2007-12-17 18:20:48Z theeth $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_levels.c b/source/blender/nodes/intern/CMP_nodes/CMP_levels.c index 414c535789e..28b769a8a97 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_levels.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_levels.c @@ -1,5 +1,5 @@ /** - * $Id: CMP_levels.c 12931 2007-12-17 18:20:48Z theeth $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * -- cgit v1.2.3 From e9587a89faf33aa0c1383b59f006be4cc7443a5a Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Thu, 10 Sep 2009 22:32:33 +0000 Subject: Hair dynamics with cloth simulation - Hair dynamics have their own panel in particle settings with the settings from cloth panel that apply to hair. - Basic internal friction force to quickly emulate self collisions and volume preservation. (Still very early code, but gives some idea of what's possible). - Softbody simulation is no longer used for hair. * Old files with sb dynamics should just load the hair without dynamics so new dynamics can be applied. * Invasion of particles exceptions in sb code is finally over. - Collisions with other objects are disabled for now and will be worked out in the future. Other changes/fixes: - Particle mode editing flag wasn't saved properly. - Some old files with edited hair didn't load correctly. - Disabled delete & specials menu in particle mode for non-hair editing. - Fixed yet one more cloth & softbody pointcache update issue. - Disconnect/connect hair now uses only the deformed mesh so it works correctly also for subsurfed emitters. - Hair editing now updates correctly with a moving emitter. --- source/blender/blenkernel/BKE_cloth.h | 3 +- source/blender/blenkernel/BKE_particle.h | 2 +- source/blender/blenkernel/intern/cloth.c | 45 ++- source/blender/blenkernel/intern/implicit.c | 88 +++++- source/blender/blenkernel/intern/object.c | 7 +- source/blender/blenkernel/intern/particle.c | 209 +++++++------- source/blender/blenkernel/intern/particle_system.c | 305 ++++++++++++-------- source/blender/blenkernel/intern/pointcache.c | 33 +-- source/blender/blenkernel/intern/softbody.c | 307 ++++----------------- source/blender/blenloader/intern/readfile.c | 32 ++- source/blender/blenloader/intern/writefile.c | 9 +- source/blender/editors/physics/editparticle.c | 48 +++- source/blender/editors/space_buttons/buttons_ops.c | 26 +- source/blender/editors/space_view3d/drawobject.c | 6 + source/blender/makesdna/DNA_cloth_types.h | 2 +- source/blender/makesdna/DNA_object_force.h | 2 - source/blender/makesdna/DNA_particle_types.h | 15 +- source/blender/makesrna/intern/rna_cloth.c | 10 +- source/blender/makesrna/intern/rna_particle.c | 39 ++- 19 files changed, 620 insertions(+), 568 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index bc4585106e6..e5b3adbd0c0 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -176,7 +176,8 @@ typedef enum CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */ - CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12) /* edit cache in editmode */ + CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12), /* edit cache in editmode */ + CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS = (1 << 13) /* don't allow spring compression */ } CLOTH_SIMSETTINGS_FLAGS; /* COLLISION FLAGS */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 15896477a6a..c22778f5a30 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -208,7 +208,7 @@ void psys_free_boid_rules(struct ListBase *list); void psys_free_settings(struct ParticleSettings *part); void free_child_path_cache(struct ParticleSystem *psys); void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit); -void free_hair(struct ParticleSystem *psys, int softbody); +void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics); void free_keyed_keys(struct ParticleSystem *psys); void psys_free_particles(struct ParticleSystem *psys); void psys_free(struct Object * ob, struct ParticleSystem * psys); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 8be8df8e63b..d25c329f49f 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -496,9 +496,11 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, if(!do_init_cloth(ob, clmd, result, framenr)) return result; - if(framenr == startframe && cache->flag & PTCACHE_REDO_NEEDED) { + if(framenr == startframe) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + do_init_cloth(ob, clmd, result, framenr); cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; cache->flag &= ~PTCACHE_REDO_NEEDED; return result; } @@ -530,36 +532,25 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, return result; } - if(framenr == startframe) { - implicit_set_positions(clmd); + /* if on second frame, write cache for first frame */ + if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) + BKE_ptcache_write_cache(&pid, startframe); - cache->simframe= framenr; - cache->flag |= PTCACHE_SIMULATION_VALID; + clmd->sim_parms->timescale *= framenr - cache->simframe; - /* don't write cache on first frame, but on second frame write - * cache for frame 1 and 2 */ - } - else { - /* if on second frame, write cache for first frame */ - if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write_cache(&pid, startframe); + /* do simulation */ + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; - clmd->sim_parms->timescale *= framenr - cache->simframe; - - /* do simulation */ - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe= framenr; - - if(!do_step_cloth(ob, clmd, result, framenr)) { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe= 0; - cache->last_exact= 0; - } - else - BKE_ptcache_write_cache(&pid, framenr); - - cloth_to_object (ob, clmd, result); + if(!do_step_cloth(ob, clmd, result, framenr)) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + cache->last_exact= 0; } + else + BKE_ptcache_write_cache(&pid, framenr); + + cloth_to_object (ob, clmd, result); return result; } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index fc5213d5532..0bce71b57eb 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1183,7 +1183,8 @@ DO_INLINE void dfdx_spring(float to[3][3], float dir[3],float length,float L,fl //return ( (I-outerprod(dir,dir))*Min(1.0f,rest/length) - I) * -k; mul_fvectorT_fvector(to, dir, dir); sub_fmatrix_fmatrix(to, I, to); - mul_fmatrix_S(to, (((L/length)> 1.0f) ? (1.0f): (L/length))); + + mul_fmatrix_S(to, (L/length)); sub_fmatrix_fmatrix(to, to, I); mul_fmatrix_S(to, -k); } @@ -1218,6 +1219,8 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; float scaling = 0.0; + + int no_compress = clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1254,7 +1257,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, // calculate force of structural + shear springs if((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR)) { - if(length > L) // only on elonglation + if(length > L || no_compress) { s->flags |= CLOTH_SPRING_FLAG_NEEDED; @@ -1393,6 +1396,84 @@ float calculateVertexWindForce(float wind[3], float vertexnormal[3]) return (INPR(wind, vertexnormal)); } +typedef struct HairGridVert { + float velocity[3]; + float density; +} HairGridVert; +/* Smoothing of hair velocities: + * adapted from + Volumetric Methods for Simulation and Rendering of Hair + by Lena Petrovic, Mark Henne and John Anderson + * Pixar Technical Memo #06-08, Pixar Animation Studios + */ +static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, lfVector *lV, int numverts) +{ + /* TODO: this is an initial implementation and should be made much better in due time */ + + /* 10x10x10 grid gives nice initial results */ + HairGridVert grid[10][10][10]; + float gmin[3], gmax[3], density; + int v = 0; + int i = 0; + int j = 0; + int k = 0; + lfVector temp; + + INIT_MINMAX(gmin, gmax); + + for(i = 0; i < numverts; i++) + DO_MINMAX(lX[i], gmin, gmax); + + /* initialize grid */ + for(i = 0; i < 10; i++) { + for(j = 0; j < 10; j++) { + for(k = 0; k < 10; k++) { + grid[i][j][k].velocity[0] = 0.0f; + grid[i][j][k].velocity[1] = 0.0f; + grid[i][j][k].velocity[2] = 0.0f; + grid[i][j][k].density = 0.0f; + } + } + } + + /* gather velocities & density */ + for(v = 0; v < numverts; v++) { + i = (int)( (lX[v][0] - gmin[0]) / (gmax[0] - gmin[0]) * 9.99f ); + j = (int)( (lX[v][1] - gmin[1]) / (gmax[1] - gmin[1]) * 9.99f ); + k = (int)( (lX[v][2] - gmin[2]) / (gmax[2] - gmin[2]) * 9.99f ); + + grid[i][j][k].velocity[0] += lV[v][0]; + grid[i][j][k].velocity[1] += lV[v][1]; + grid[i][j][k].velocity[2] += lV[v][2]; + grid[i][j][k].density += 1.0f; + } + + /* divide velocity with density */ + for(i = 0; i < 10; i++) { + for(j = 0; j < 10; j++) { + for(k = 0; k < 10; k++) { + density = grid[i][j][k].density; + if(density > 0.0f) { + grid[i][j][k].velocity[0] /= density; + grid[i][j][k].velocity[1] /= density; + grid[i][j][k].velocity[2] /= density; + } + } + } + } + + /* calculate forces */ + for(v = 0; v < numverts; v++) { + i = (int)( (lX[v][0] - gmin[0]) / (gmax[0] - gmin[0]) * 9.99f ); + j = (int)( (lX[v][1] - gmin[1]) / (gmax[1] - gmin[1]) * 9.99f ); + k = (int)( (lX[v][2] - gmin[2]) / (gmax[2] - gmin[2]) * 9.99f ); + + /* 2.0f is an experimental value that seems to give good results */ + lF[v][0] += 2.0f * smoothfac * (grid[i][j][k].velocity[0] - lV[v][0]); + lF[v][1] += 2.0f * smoothfac * (grid[i][j][k].velocity[1] - lV[v][1]); + lF[v][2] += 2.0f * smoothfac * (grid[i][j][k].velocity[2] - lV[v][2]); + } +} static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M) { /* Collect forces and derivatives: F,dFdX,dFdV */ @@ -1416,6 +1497,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, init_lfvector(lF, gravity, numverts); + if(clmd->sim_parms->velocity_smooth > 0.0f) + hair_velocity_smoothing(clmd->sim_parms->velocity_smooth, lF, lX, lV, numverts); + /* multiply lF with mass matrix // force = mass * acceleration (in this case: gravity) */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index f10226f6f6b..a0004aaae49 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1113,9 +1113,10 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys) } } - if(psys->soft) { - psysn->soft= copy_softbody(psys->soft); - psysn->soft->particles = psysn; + if(psys->clmd) { + ClothModifierData *nclmd = modifier_new(eModifierType_Cloth); + modifier_copyData((ModifierData*)psys->clmd, (ModifierData*)nclmd); + psys->hair_in_dm = psys->hair_out_dm = NULL; } BLI_duplicatelist(&psysn->targets, &psys->targets); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 0ba2f357a1f..3b2125a7973 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -366,7 +366,7 @@ void psys_free_settings(ParticleSettings *part) boid_free_settings(part->boids); } -void free_hair(ParticleSystem *psys, int softbody) +void free_hair(Object *ob, ParticleSystem *psys, int dynamics) { PARTICLE_P; @@ -382,10 +382,28 @@ void free_hair(ParticleSystem *psys, int softbody) psys->flag &= ~PSYS_HAIR_DONE; - if(softbody && psys->soft) { - sbFree(psys->soft); - psys->soft = NULL; + if(psys->clmd) { + if(dynamics) { + BKE_ptcache_free_list(&psys->ptcaches); + psys->clmd->point_cache = psys->pointcache = NULL; + psys->clmd->ptcaches.first = psys->clmd->ptcaches.first = NULL; + + modifier_free((ModifierData*)psys->clmd); + + psys->clmd = NULL; + } + else { + cloth_free_modifier(ob, psys->clmd); + } } + + if(psys->hair_in_dm) + psys->hair_in_dm->release(psys->hair_in_dm); + psys->hair_in_dm = NULL; + + if(psys->hair_out_dm) + psys->hair_out_dm->release(psys->hair_out_dm); + psys->hair_out_dm = NULL; } void free_keyed_keys(ParticleSystem *psys) { @@ -468,6 +486,8 @@ void psys_free(Object *ob, ParticleSystem * psys) psys_free_path_cache(psys, NULL); + free_hair(ob, psys, 1); + psys_free_particles(psys); if(psys->edit && psys->free_edit) @@ -976,11 +996,11 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic typedef struct ParticleInterpolationData { HairKey *hkey[2]; + DerivedMesh *dm; + MVert *mvert[2]; + int keyed; ParticleKey *kkey[2]; - - SoftBody *soft; - BodyPoint *bp[2]; PointCache *cache; @@ -1049,12 +1069,12 @@ static void init_particle_interpolation(Object *ob, ParticleSystem *psys, Partic pind->birthtime = key->time; pind->dietime = (key + pa->totkey - 1)->time; - } - //if(pind->soft) { - // pind->bp[0] = pind->soft->bpoint + pa->bpi; - // pind->bp[1] = pind->soft->bpoint + pa->bpi + 1; - //} + if(pind->dm) { + pind->mvert[0] = CDDM_get_vert(pind->dm, pa->hair_index); + pind->mvert[1] = pind->mvert[0] + 1; + } + } } static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey) { @@ -1069,9 +1089,10 @@ static void hair_to_particle(ParticleKey *key, HairKey *hkey) VECCOPY(key->co, hkey->co); key->time = hkey->time; } -static void bp_to_particle(ParticleKey *key, BodyPoint *bp, HairKey *hkey) + +static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey) { - VECCOPY(key->co, bp->pos); + VECCOPY(key->co, mvert->co); key->time = hkey->time; } @@ -1145,7 +1166,7 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData while(pind->hkey[1]->time < real_t) { pind->hkey[1]++; - pind->bp[1]++; + pind->mvert[1]++; } pind->hkey[0] = pind->hkey[1] - 1; @@ -1156,10 +1177,10 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData edit_to_particle(keys + 1, pind->ekey[0]); edit_to_particle(keys + 2, pind->ekey[1]); } - else if(pind->soft) { - pind->bp[0] = pind->bp[1] - 1; - bp_to_particle(keys + 1, pind->bp[0], pind->hkey[0]); - bp_to_particle(keys + 2, pind->bp[1], pind->hkey[1]); + else if(pind->dm) { + pind->mvert[0] = pind->mvert[1] - 1; + mvert_to_particle(keys + 1, pind->mvert[0], pind->hkey[0]); + mvert_to_particle(keys + 2, pind->mvert[1], pind->hkey[1]); } else if(pind->keyed) { memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey)); @@ -1181,11 +1202,11 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData else edit_to_particle(keys, pind->ekey[0]); } - else if(pind->soft) { + else if(pind->dm) { if(pind->hkey[0] != pa->hair) - bp_to_particle(keys, pind->bp[0] - 1, pind->hkey[0] - 1); + mvert_to_particle(keys, pind->mvert[0] - 1, pind->hkey[0] - 1); else - bp_to_particle(keys, pind->bp[0], pind->hkey[0]); + mvert_to_particle(keys, pind->mvert[0], pind->hkey[0]); } else { if(pind->hkey[0] != pa->hair) @@ -1200,11 +1221,11 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData else edit_to_particle(keys + 3, pind->ekey[1]); } - else if(pind->soft) { + else if(pind->dm) { if(pind->hkey[1] != pa->hair + pa->totkey - 1) - bp_to_particle(keys + 3, pind->bp[1] + 1, pind->hkey[1] + 1); + mvert_to_particle(keys + 3, pind->mvert[1] + 1, pind->hkey[1] + 1); else - bp_to_particle(keys + 3, pind->bp[1], pind->hkey[1]); + mvert_to_particle(keys + 3, pind->mvert[1], pind->hkey[1]); } else { if(pind->hkey[1] != pa->hair + pa->totkey - 1) @@ -2110,7 +2131,11 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup) { float *vg=0; - if(psys->vgroup[vgroup]){ + if(vgroup < 0) { + /* hair dynamics pinning vgroup */ + + } + else if(psys->vgroup[vgroup]){ MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); if(dvert){ int totvert=dm->getNumVerts(dm), i; @@ -2639,12 +2664,11 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); ParticleSettings *part = psys->part; ParticleEditSettings *pset = &scene->toolsettings->particle; + + DerivedMesh *hair_dm = psys->hair_out_dm; ParticleData *pa = psys->particles; ParticleKey result; - - SoftBody *soft = NULL; - BodyPoint *bp[2] = {NULL, NULL}; Material *ma; ParticleInterpolationData pind; @@ -2663,7 +2687,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra int keyed, baked; /* we don't have anything valid to create paths from so let's quit here */ - if(!(psys->flag & PSYS_HAIR_DONE) && !(psys->flag & PSYS_KEYED) && !(psys->pointcache->flag & PTCACHE_BAKED)) + if((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) return; if(psys_in_edit_mode(scene, psys)) @@ -2673,24 +2697,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra BLI_srandom(psys->seed); keyed = psys->flag & PSYS_KEYED; - baked = psys->pointcache->flag & PTCACHE_BAKED; + baked = !hair_dm && psys->pointcache->flag & PTCACHE_BAKED; /* clear out old and create new empty path cache */ psys_free_path_cache(psys, psys->edit); cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1); - if(psys->soft && psys->softflag & OB_SB_ENABLE) { - soft = psys->soft; - if(!soft->bpoint) - soft= NULL; - } - psys->lattice = psys_get_lattice(scene, ob, psys); ma= give_current_material(ob, psys->part->omat); if(ma && (psys->part->draw & PART_DRAW_MAT_COL)) VECCOPY(col, &ma->r) - if(psys->part->from!=PART_FROM_PARTICLE) { + if(psys->part->from!=PART_FROM_PARTICLE && !(psys->flag & PSYS_GLOBAL_HAIR)) { if(!(psys->part->flag & PART_CHILD_EFFECT)) vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR); @@ -2700,11 +2718,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra /*---first main loop: create all actual particles' paths---*/ for(i=0; iflag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) { - if(soft) - bp[0] += pa->totkey; /* TODO use of initialized value? */ + if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue; - } if(!psys->totchild) { BLI_srandom(psys->seed + i); @@ -2715,9 +2730,9 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra pind.keyed = keyed; pind.cache = baked ? psys->pointcache : NULL; - pind.soft = soft; pind.epoint = NULL; pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE); + pind.dm = hair_dm; memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); @@ -2759,10 +2774,12 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); - /* keyed, baked and softbody are allready in global space */ - if(!keyed && !baked && !soft && !(psys->flag & PSYS_GLOBAL_HAIR)) { + /* dynamic hair is in object space */ + /* keyed and baked are allready in global space */ + if(hair_dm) + Mat4MulVecfl(ob->obmat, result.co); + else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) Mat4MulVecfl(hairmat, result.co); - } VECCOPY(ca->co, result.co); VECCOPY(ca->col, col); @@ -2778,64 +2795,66 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra effector*= psys_particle_value_from_verts(psmd->dm,psys->part->from,pa,vg_effector); for(k=0, ca=cache[i]; k<=steps; k++, ca++) { + if(!(psys->flag & PSYS_GLOBAL_HAIR)) { /* apply effectors */ - if(!(psys->part->flag & PART_CHILD_EFFECT) && k) - do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); + if(!(psys->part->flag & PART_CHILD_EFFECT) && k) + do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); - /* apply guide curves to path data */ - if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) - /* ca is safe to cast, since only co and vel are used */ - do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); + /* apply guide curves to path data */ + if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) + /* ca is safe to cast, since only co and vel are used */ + do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); - /* apply lattice */ - if(psys->lattice) - calc_latt_deform(psys->lattice, ca->co, 1.0f); + /* apply lattice */ + if(psys->lattice) + calc_latt_deform(psys->lattice, ca->co, 1.0f); - /* figure out rotation */ - - if(k) { - float cosangle, angle, tangent[3], normal[3], q[4]; - - if(k == 1) { - /* calculate initial tangent for incremental rotations */ - VECSUB(tangent, ca->co, (ca - 1)->co); - VECCOPY(prev_tangent, tangent); - Normalize(prev_tangent); - - /* First rotation is based on emitting face orientation. */ - /* This is way better than having flipping rotations resulting */ - /* from using a global axis as a rotation pole (vec_to_quat()). */ - /* It's not an ideal solution though since it disregards the */ - /* initial tangent, but taking that in to account will allow */ - /* the possibility of flipping again. -jahka */ - Mat3ToQuat_is_ok(rotmat, (ca-1)->rot); - } - else { - VECSUB(tangent, ca->co, (ca - 1)->co); - Normalize(tangent); - - cosangle= Inpf(tangent, prev_tangent); - - /* note we do the comparison on cosangle instead of - * angle, since floating point accuracy makes it give - * different results across platforms */ - if(cosangle > 0.999999f) { - QUATCOPY((ca - 1)->rot, (ca - 2)->rot); + /* figure out rotation */ + + if(k) { + float cosangle, angle, tangent[3], normal[3], q[4]; + + if(k == 1) { + /* calculate initial tangent for incremental rotations */ + VECSUB(tangent, ca->co, (ca - 1)->co); + VECCOPY(prev_tangent, tangent); + Normalize(prev_tangent); + + /* First rotation is based on emitting face orientation. */ + /* This is way better than having flipping rotations resulting */ + /* from using a global axis as a rotation pole (vec_to_quat()). */ + /* It's not an ideal solution though since it disregards the */ + /* initial tangent, but taking that in to account will allow */ + /* the possibility of flipping again. -jahka */ + Mat3ToQuat_is_ok(rotmat, (ca-1)->rot); } else { - angle= saacos(cosangle); - Crossf(normal, prev_tangent, tangent); - VecRotToQuat(normal, angle, q); - QuatMul((ca - 1)->rot, q, (ca - 2)->rot); + VECSUB(tangent, ca->co, (ca - 1)->co); + Normalize(tangent); + + cosangle= Inpf(tangent, prev_tangent); + + /* note we do the comparison on cosangle instead of + * angle, since floating point accuracy makes it give + * different results across platforms */ + if(cosangle > 0.999999f) { + QUATCOPY((ca - 1)->rot, (ca - 2)->rot); + } + else { + angle= saacos(cosangle); + Crossf(normal, prev_tangent, tangent); + VecRotToQuat(normal, angle, q); + QuatMul((ca - 1)->rot, q, (ca - 2)->rot); + } + + VECCOPY(prev_tangent, tangent); } - VECCOPY(prev_tangent, tangent); + if(k == steps) + QUATCOPY(ca->rot, (ca - 1)->rot); } - if(k == steps) - QUATCOPY(ca->rot, (ca - 1)->rot); } - /* set velocity */ @@ -2913,9 +2932,9 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf pind.keyed = 0; pind.cache = NULL; - pind.soft = NULL; pind.epoint = point; pind.bspline = psys ? (psys->part->flag & PART_HAIR_BSPLINE) : 0; + pind.dm = NULL; memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); @@ -3783,8 +3802,8 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i pa = psys->particles + p; pind.keyed = keyed; pind.cache = cached ? psys->pointcache : NULL; - pind.soft = NULL; pind.epoint = NULL; + pind.dm = psys->hair_out_dm; init_particle_interpolation(ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 1931b89af38..88b85bcfa29 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -73,7 +73,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_object.h" #include "BKE_material.h" -#include "BKE_softbody.h" +#include "BKE_cloth.h" #include "BKE_depsgraph.h" #include "BKE_lattice.h" #include "BKE_pointcache.h" @@ -126,7 +126,7 @@ void psys_reset(ParticleSystem *psys, int mode) PARTICLE_P; if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { - if(mode == PSYS_RESET_ALL || !(part->type == PART_HAIR && (psys->edit && psys->edit->edited))) { + if(mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) { psys_free_particles(psys); psys->totpart= 0; @@ -3432,6 +3432,190 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /************************************************/ /* Hair */ /************************************************/ +/* check if path cache or children need updating and do it if needed */ +static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +{ + ParticleSettings *part=psys->part; + ParticleEditSettings *pset=&scene->toolsettings->particle; + int distr=0,alloc=0,skip=0; + + if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) + alloc=1; + + if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))) + distr=1; + + if(distr){ + if(alloc) + realloc_particles(ob,psys,psys->totpart); + + if(get_psys_tot_child(scene, psys)) { + /* don't generate children while computing the hair keys */ + if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { + distribute_particles(scene, ob, psys, PART_FROM_CHILD); + + if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0) + psys_find_parents(ob,psmd,psys); + } + } + } + + if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) + skip = 1; /* only hair, keyed and baked stuff can have paths */ + else if(part->ren_as != PART_DRAW_PATH) + skip = 1; /* particle visualization must be set as path */ + else if(!psys->renderdata) { + if(part->draw_as != PART_DRAW_REND) + skip = 1; /* draw visualization */ + else if(psys->pointcache->flag & PTCACHE_BAKING) + skip = 1; /* no need to cache paths while baking dynamics */ + else if(psys_in_edit_mode(scene, psys)) { + if((pset->flag & PE_DRAW_PART)==0) + skip = 1; + else if(part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) + skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */ + } + } + + if(!skip) { + psys_cache_paths(scene, ob, psys, cfra); + + /* for render, child particle paths are computed on the fly */ + if(part->childtype) { + if(!psys->totchild) + skip = 1; + else if((psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DONE)==0) + skip = 1; + + if(!skip) + psys_cache_child_paths(scene, ob, psys, cfra, 0); + } + } + else if(psys->pathcache) + psys_free_path_cache(psys, NULL); +} + +static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +{ + DerivedMesh *dm = psys->hair_in_dm; + MVert *mvert = NULL; + MEdge *medge = NULL; + MDeformVert *dvert = NULL; + HairKey *key; + PARTICLE_P; + int totpoint = 0; + int totedge; + int k; + float hairmat[4][4]; + + if(!psys->clmd) { + psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth); + psys->clmd->sim_parms->goalspring = 0.0f; + psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; + psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; + } + + /* create a dm from hair vertices */ + LOOP_PARTICLES + totpoint += pa->totkey; + + totedge = totpoint - psys->totpart; + + if(dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) { + dm->release(dm); + dm = psys->hair_in_dm = NULL; + } + + if(!dm) { + dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0); + DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL); + } + + mvert = CDDM_get_verts(dm); + medge = CDDM_get_edges(dm); + dvert = DM_get_vert_data_layer(dm, CD_MDEFORMVERT); + + psys->clmd->sim_parms->vgroup_mass = 1; + + /* make vgroup for pin roots etc.. */ + psys->particles->hair_index = 0; + LOOP_PARTICLES { + if(p) + pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey; + + psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat); + + for(k=0, key=pa->hair; ktotkey; k++,key++) { + VECCOPY(mvert->co, key->co); + Mat4MulVecfl(hairmat, mvert->co); + mvert++; + + if(k) { + medge->v1 = pa->hair_index + k - 1; + medge->v2 = pa->hair_index + k; + medge++; + } + + if(dvert) { + if(!dvert->totweight) { + dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->totweight = 1; + } + + /* no special reason for the 0.5 */ + /* just seems like a nice value from experiments */ + dvert->dw->weight = k ? 0.5f : 1.0f; + dvert++; + } + } + } + + if(psys->hair_out_dm) + psys->hair_out_dm->release(psys->hair_out_dm); + + psys->clmd->point_cache = psys->pointcache; + + psys->hair_out_dm = clothModifier_do(psys->clmd, scene, ob, dm, 0, 0); +} +static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +{ + ParticleSettings *part = psys->part; + PARTICLE_P; + float disp = (float)get_current_display_percentage(psys)/100.0f; + + BLI_srandom(psys->seed); + + LOOP_PARTICLES { + if(BLI_frand() > disp) + pa->flag |= PARS_NO_DISP; + else + pa->flag &= ~PARS_NO_DISP; + } + + if(psys->recalc & PSYS_RECALC_RESET) { + /* need this for changing subsurf levels */ + psys_calc_dmcache(ob, psmd->dm, psys); + + if(psys->clmd) + cloth_free_modifier(ob, psys->clmd); + } + + if(psys->effectors.first) + psys_end_effectors(psys); + + /* dynamics with cloth simulation */ + if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) + do_hair_dynamics(scene, ob, psys, psmd); + + psys_init_effectors(scene, ob, part->eff_group, psys); + if(psys->effectors.first) + precalc_effectors(scene, ob,psys,psmd,cfra); + + psys_update_path_cache(scene, ob,psmd,psys,cfra); + + psys->flag |= PSYS_HAIR_UPDATED; +} + static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ HairKey *key, *root; PARTICLE_P; @@ -3692,79 +3876,6 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic BLI_kdtree_free(tree); } -/* check if path cache or children need updating and do it if needed */ -static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) -{ - ParticleSettings *part=psys->part; - ParticleEditSettings *pset=&scene->toolsettings->particle; - int distr=0,alloc=0; - - if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) - alloc=1; - - if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))) - distr=1; - - if(distr){ - if(alloc) - realloc_particles(ob,psys,psys->totpart); - - if(get_psys_tot_child(scene, psys)) { - /* don't generate children while computing the hair keys */ - if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { - distribute_particles(scene, ob, psys, PART_FROM_CHILD); - - if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0) - psys_find_parents(ob,psmd,psys); - } - } - } - - if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR - || (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){ - - psys_cache_paths(scene, ob, psys, cfra); - - /* for render, child particle paths are computed on the fly */ - if(part->childtype) { - if(((psys->totchild!=0)) || (psys_in_edit_mode(scene, psys) && (pset->flag&PE_DRAW_PART))) - if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) - psys_cache_child_paths(scene, ob, psys, cfra, 0); - } - } - else if(psys->pathcache) - psys_free_path_cache(psys, NULL); -} - -static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) -{ - ParticleSettings *part = psys->part; - PARTICLE_P; - float disp = (float)get_current_display_percentage(psys)/100.0f; - - BLI_srandom(psys->seed); - - LOOP_PARTICLES { - if(BLI_frand() > disp) - pa->flag |= PARS_NO_DISP; - else - pa->flag &= ~PARS_NO_DISP; - } - - if(psys->recalc & PSYS_RECALC_RESET) - /* need this for changing subsurf levels */ - psys_calc_dmcache(ob, psmd->dm, psys); - - if(psys->effectors.first) - psys_end_effectors(psys); - - psys_init_effectors(scene, ob, part->eff_group, psys); - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); - - psys_update_path_cache(scene, ob,psmd,psys,cfra); -} - /* updates cached particles' alive & other flags etc..*/ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) { @@ -3889,14 +4000,12 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys) BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { - free_hair(psys, 1); + free_hair(ob, psys, 1); CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime)); CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime)); } - psys->softflag= 0; - psys_reset(psys, PSYS_RESET_ALL); } void psys_check_boid_data(ParticleSystem *psys) @@ -4082,7 +4191,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle framedelta= framenr - cache->simframe; /* set suitable cache range automatically */ - if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0) + if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0 && !(psys->flag & PSYS_HAIR_DYNAMICS)) psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe); BKE_ptcache_id_from_particles(&pid, ob, psys); @@ -4307,39 +4416,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle } } -static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys) -{ - SoftBody *sb; - short softflag; - - if(!(psys->softflag & OB_SB_ENABLE)) - return; - - /* let's replace the object's own softbody with the particle softbody */ - /* a temporary solution before cloth simulation is implemented, jahka */ - - /* save these */ - sb= ob->soft; - softflag= ob->softflag; - - /* swich to new ones */ - ob->soft= psys->soft; - ob->softflag= psys->softflag; - - /* do softbody */ - sbObjectStep(scene, ob, (float)scene->r.cfra, NULL, psys_count_keys(psys)); - - /* return things back to normal */ - psys->soft= ob->soft; - psys->softflag= ob->softflag; - - ob->soft= sb; - ob->softflag= softflag; -} - static int hair_needs_recalc(ParticleSystem *psys) { - if((!psys->edit || !psys->edit->edited) && + if(!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) && ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) { return 1; } @@ -4380,7 +4459,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) float hcfra=0.0f; int i; - free_hair(psys, 0); + free_hair(ob, psys, 0); /* first step is negative so particles get killed and reset */ psys->cfra= 1.0f; @@ -4394,10 +4473,6 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) psys->flag |= PSYS_HAIR_DONE; } - /* handle softbody hair */ - if(psys->part->type==PART_HAIR && psys->soft) - psys_to_softbody(scene, ob, psys); - /* the main particle system step */ system_step(scene, ob, psys, psmd, cfra); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 5a14277d63b..f351f8a4335 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -382,8 +382,6 @@ static int ptcache_totpoint_cloth(void *cloth_v) /* Creating ID's */ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { - ParticleSystemModifierData *psmd; - memset(pid, 0, sizeof(PTCacheID)); pid->ob= ob; @@ -406,12 +404,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) pid->data_types= (1<info_types= 0; - if(sb->particles) { - psmd= psys_get_modifier(ob, sb->particles); - // pid->stack_index= modifiers_indexInObject(ob, (ModifierData*)psmd); XXX TODO - get other index DG - } - else - pid->stack_index = pid->cache->index; + pid->stack_index = pid->cache->index; } void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) @@ -426,7 +419,8 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p pid->cache_ptr= &psys->pointcache; pid->ptcaches= &psys->ptcaches; - pid->flag |= PTCACHE_VEL_PER_SEC; + if(psys->part->type != PART_HAIR) + pid->flag |= PTCACHE_VEL_PER_SEC; pid->write_elem= ptcache_write_particle; pid->write_stream = NULL; @@ -816,12 +810,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob) pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); BKE_ptcache_id_from_particles(pid, ob, psys); BLI_addtail(lb, pid); - - if(psys->soft) { - pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); - BKE_ptcache_id_from_softbody(pid, ob, psys->soft); - BLI_addtail(lb, pid); - } } } @@ -1828,9 +1816,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) else if(mode == PTCACHE_RESET_OUTDATED) { reset = 1; - if(cache->flag & PTCACHE_OUTDATED) - if(!(cache->flag & PTCACHE_BAKED)) - clear= 1; + if(cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) { + clear= 1; + cache->flag &= ~PTCACHE_OUTDATED; + } } if(reset) { @@ -1873,10 +1862,10 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - /* Baked softbody hair has to be checked first, because we don't want to reset */ - /* particles or softbody in that case -jahka */ - if(psys->soft) { - BKE_ptcache_id_from_softbody(&pid, ob, psys->soft); + /* Baked cloth hair has to be checked first, because we don't want to reset */ + /* particles or cloth in that case -jahka */ + if(psys->clmd) { + BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd); if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) reset |= BKE_ptcache_id_reset(scene, &pid, mode); else diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index fdbfe154fae..450a64d72eb 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -58,7 +58,6 @@ variables on the UI for now #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" /* here is the softbody struct */ -#include "DNA_particle_types.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -76,7 +75,6 @@ variables on the UI for now #include "BKE_global.h" #include "BKE_key.h" #include "BKE_object.h" -#include "BKE_particle.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -494,32 +492,21 @@ static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *h while (base) { /*Only proceed for mesh object in same layer */ if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) { - int particles=0; ob= base->object; if((vertexowner) && (ob == vertexowner)) { - if(vertexowner->soft->particles){ - particles=1; - } - else { - /* if vertexowner is given we don't want to check collision with owner object */ - base = base->next; - continue; - } + /* if vertexowner is given we don't want to check collision with owner object */ + base = base->next; + continue; } /*+++ only with deflecting set */ if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == 0) { DerivedMesh *dm= NULL; - if(particles) { - dm = psys_get_modifier(ob,psys_get_current(ob))->dm; - } - else { - if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */ - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); - else - dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); - } + if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */ + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + else + dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); if(dm){ ccd_Mesh *ccdmesh = ccd_mesh_make(ob, dm); @@ -3571,107 +3558,6 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob) } } - -static void springs_from_particles(Object *ob) -{ - ParticleSystem *psys; - ParticleSystemModifierData *psmd=0; - ParticleData *pa=0; - HairKey *key=0; - SoftBody *sb; - BodyPoint *bp; - BodySpring *bs; - int a,k; - float hairmat[4][4]; - - if(ob && ob->soft && ob->soft->particles) { - psys= ob->soft->particles; - sb= ob->soft; - psmd = psys_get_modifier(ob, psys); - - bp= sb->bpoint; - for(a=0, pa=psys->particles; atotpart; a++, pa++) { - for(k=0, key=pa->hair; ktotkey; k++, bp++, key++) { - VECCOPY(bp->origS, key->co); - - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); - - Mat4MulVecfl(hairmat, bp->origS); - } - } - - for(a=0, bs=sb->bspring; atotspring; a++, bs++) - bs->len= VecLenf(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS); - } -} - -static void particles_to_softbody(Scene *scene, Object *ob) -{ - SoftBody *sb; - BodyPoint *bp; - BodySpring *bs; - ParticleData *pa; - HairKey *key; - ParticleSystem *psys= ob->soft->particles; - float goalfac; - int a, k, curpoint; - int totpoint= psys_count_keys(psys); - int totedge= totpoint-psys->totpart; - - /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */ - renew_softbody(scene, ob, totpoint, totedge); - - /* find first BodyPoint index for each particle */ - if(psys->totpart > 0) { -// psys->particles->bpi = 0; -// for(a=1, pa=psys->particles+1; atotpart; a++, pa++) -// pa->bpi = (pa-1)->bpi + (pa-1)->totkey; - } - - /* we always make body points */ - sb= ob->soft; - bp= sb->bpoint; - bs= sb->bspring; - goalfac= ABS(sb->maxgoal - sb->mingoal); - - if((ob->softflag & OB_SB_GOAL)) { - for(a=0, pa=psys->particles; atotpart; a++, pa++) { - for(k=0, key=pa->hair; ktotkey; k++,bp++,key++) { - if(k) { - bp->goal= key->weight; - bp->goal= sb->mingoal + bp->goal*goalfac; - bp->goal= (float)pow(bp->goal, 4.0f); - } - else{ - /* hair roots are allways fixed fully to goal */ - bp->goal= 1.0f; - } - } - } - } - - bp= sb->bpoint; - curpoint=0; - for(a=0, pa=psys->particles; atotpart; a++, curpoint++, pa++) { - for(k=0; ktotkey-1; k++,bs++,curpoint++) { - bs->v1=curpoint; - bs->v2=curpoint+1; - bs->strength= 1.0; - bs->order=1; - } - } - - build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */ - /* insert *other second order* springs if desired */ - if(sb->secondspring > 0.0000001f) { - add_2nd_order_springs(ob,sb->secondspring*10.0); /* exploits the the first run of build_bps_springlist(ob);*/ - build_bps_springlist(ob); /* yes we need to do it again*/ - } - springs_from_particles(ob); /* write the 'rest'-lenght of the springs */ - if(ob->softflag & OB_SB_SELF) - calculate_collision_balls(ob); -} - /* copies softbody result back in object */ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, int local) { @@ -3795,44 +3681,16 @@ void sbSetInterruptCallBack(int (*f)(void)) static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts) { - ParticleSystemModifierData *psmd= NULL; - ParticleData *pa= NULL; - HairKey *key= NULL; BodyPoint *bp; - float hairmat[4][4]; int a; - /* update the vertex locations */ - if(sb->particles && sb->particles->totpart>0) { - psmd= psys_get_modifier(ob,sb->particles); - - pa= sb->particles->particles; - key= pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - for(a=0,bp=sb->bpoint; aorigS, bp->origE); /* copy the position of the goals at desired end time */ - if(sb->particles) { - if(key == pa->hair + pa->totkey) { - pa++; - key = pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - VECCOPY(bp->origE, key->co); - Mat4MulVecfl(hairmat,bp->origE); - - key++; - } - else{ - VECCOPY(bp->origE, vertexCos[a]); - /* vertexCos came from local world, go global */ - Mat4MulVecfl(ob->obmat, bp->origE); - } + VECCOPY(bp->origE, vertexCos[a]); + /* vertexCos came from local world, go global */ + Mat4MulVecfl(ob->obmat, bp->origE); /* just to be save give bp->origT a defined value will be calulated in interpolate_exciter()*/ VECCOPY(bp->origT, bp->origE); @@ -3841,37 +3699,12 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts) { - ParticleSystemModifierData *psmd= NULL; - HairKey *key= NULL; - ParticleData *pa= NULL; BodyPoint *bp; - float hairmat[4][4]; int a; - if(sb->particles && sb->particles->totpart>0) { - psmd= psys_get_modifier(ob, sb->particles); - pa= sb->particles->particles; - key= pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - for(a=0,bp=sb->bpoint; aparticles) { - if(key == pa->hair + pa->totkey) { - pa++; - key = pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - VECCOPY(bp->pos, key->co); - Mat4MulVecfl(hairmat, bp->pos); - key++; - } - else { - VECCOPY(bp->pos, vertexCos[a]); - Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/ - } + VECCOPY(bp->pos, vertexCos[a]); + Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/ VECCOPY(bp->origS, bp->pos); VECCOPY(bp->origE, bp->pos); VECCOPY(bp->origT, bp->pos); @@ -3900,20 +3733,18 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int sb_new_scratch(sb); /* make a new */ sb->scratch->needstobuildcollider=1; - if((sb->particles)==0) { - /* copy some info to scratch */ - switch(ob->type) { - case OB_MESH: - if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob); - break; - case OB_LATTICE: - break; - case OB_CURVE: - case OB_SURF: - break; - default: - break; - } + /* copy some info to scratch */ + switch(ob->type) { + case OB_MESH: + if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob); + break; + case OB_LATTICE: + break; + case OB_CURVE: + case OB_SURF: + break; + default: + break; } } @@ -4049,8 +3880,6 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) /* simulates one step. framenr is in frames */ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts) { - ParticleSystemModifierData *psmd=0; - ParticleData *pa=0; SoftBody *sb= ob->soft; PointCache *cache; PTCacheID pid; @@ -4091,25 +3920,20 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i if(sb->bpoint == NULL || ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) { - if(sb->particles){ - particles_to_softbody(scene, ob); - } - else { - switch(ob->type) { - case OB_MESH: - mesh_to_softbody(scene, ob); - break; - case OB_LATTICE: - lattice_to_softbody(scene, ob); - break; - case OB_CURVE: - case OB_SURF: - curve_surf_to_softbody(scene, ob); - break; - default: - renew_softbody(scene, ob, numVerts, 0); - break; - } + switch(ob->type) { + case OB_MESH: + mesh_to_softbody(scene, ob); + break; + case OB_LATTICE: + lattice_to_softbody(scene, ob); + break; + case OB_CURVE: + case OB_SURF: + curve_surf_to_softbody(scene, ob); + break; + default: + renew_softbody(scene, ob, numVerts, 0); + break; } softbody_update_positions(ob, sb, vertexCos, numVerts); @@ -4127,8 +3951,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i softbody_update_positions(ob, sb, vertexCos, numVerts); softbody_step(scene, ob, sb, dtime); - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, 0); + softbody_to_object(ob, vertexCos, numVerts, 0); return; } @@ -4136,14 +3959,14 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i /* still no points? go away */ if(sb->totpoint==0) return; - if(sb->particles){ - psmd= psys_get_modifier(ob, sb->particles); - pa= sb->particles->particles; - } - - if(framenr == startframe && cache->flag & PTCACHE_REDO_NEEDED) { + if(framenr == startframe) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + + /* first frame, no simulation to do, just set the positions */ + softbody_update_positions(ob, sb, vertexCos, numVerts); + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; cache->flag &= ~PTCACHE_REDO_NEEDED; return; } @@ -4152,8 +3975,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, sb->local); + softbody_to_object(ob, vertexCos, numVerts, sb->local); cache->simframe= framenr; cache->flag |= PTCACHE_SIMULATION_VALID; @@ -4174,36 +3996,23 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i return; } - if(framenr == startframe) { - /* first frame, no simulation to do, just set the positions */ - softbody_update_positions(ob, sb, vertexCos, numVerts); - - cache->simframe= framenr; - cache->flag |= PTCACHE_SIMULATION_VALID; + /* if on second frame, write cache for first frame */ + if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) + BKE_ptcache_write_cache(&pid, startframe); - /* don't write cache on first frame, but on second frame write - * cache for frame 1 and 2 */ - } - else { - /* if on second frame, write cache for first frame */ - if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write_cache(&pid, startframe); + softbody_update_positions(ob, sb, vertexCos, numVerts); - softbody_update_positions(ob, sb, vertexCos, numVerts); + /* checking time: */ + dtime = framedelta*timescale; - /* checking time: */ - dtime = framedelta*timescale; + softbody_step(scene, ob, sb, dtime); - softbody_step(scene, ob, sb, dtime); - - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, 0); + softbody_to_object(ob, vertexCos, numVerts, 0); - /* do simulation */ - cache->simframe= framenr; - cache->flag |= PTCACHE_SIMULATION_VALID; + /* do simulation */ + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; - BKE_ptcache_write_cache(&pid, framenr); - } + BKE_ptcache_write_cache(&pid, framenr); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 37031f4f82a..5b45a4219c7 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3114,17 +3114,6 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) psys->child=newdataadr(fd,psys->child); psys->effectors.first=psys->effectors.last=0; - psys->soft= newdataadr(fd, psys->soft); - if(psys->soft) { - SoftBody *sb = psys->soft; - sb->particles = psys; - sb->bpoint= NULL; // init pointers so it gets rebuilt nicely - sb->bspring= NULL; - sb->scratch= NULL; - - direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache); - } - link_list(fd, &psys->targets); psys->edit = NULL; @@ -3137,6 +3126,23 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache); + if(psys->clmd) { + psys->clmd = newdataadr(fd, psys->clmd); + psys->clmd->clothObject = NULL; + + psys->clmd->sim_parms= newdataadr(fd, psys->clmd->sim_parms); + psys->clmd->coll_parms= newdataadr(fd, psys->clmd->coll_parms); + + if(psys->clmd->sim_parms) { + if(psys->clmd->sim_parms->presets > 10) + psys->clmd->sim_parms->presets = 0; + } + + psys->hair_in_dm = psys->hair_out_dm = NULL; + + psys->clmd->point_cache = psys->pointcache; + } + psys->tree = NULL; } return; @@ -8342,8 +8348,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ob->soft->pointcache= BKE_ptcache_add(&ob->soft->ptcaches); for(psys=ob->particlesystem.first; psys; psys=psys->next) { - if(psys->soft && !psys->soft->pointcache) - psys->soft->pointcache= BKE_ptcache_add(&psys->soft->ptcaches); + //if(psys->soft && !psys->soft->pointcache) + // psys->soft->pointcache= BKE_ptcache_add(&psys->soft->ptcaches); if(!psys->pointcache) psys->pointcache= BKE_ptcache_add(&psys->ptcaches); } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 46cc62fff1c..98db27182ab 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -660,8 +660,13 @@ static void write_particlesystems(WriteData *wd, ListBase *particles) writestruct(wd, DATA, "ParticleTarget", 1, pt); if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child); - writestruct(wd, DATA, "SoftBody", 1, psys->soft); - if(psys->soft) write_pointcaches(wd, &psys->soft->ptcaches); + + if(psys->clmd) { + writestruct(wd, DATA, "ClothModifierData", 1, psys->clmd); + writestruct(wd, DATA, "ClothSimSettings", 1, psys->clmd->sim_parms); + writestruct(wd, DATA, "ClothCollSettings", 1, psys->clmd->coll_parms); + } + write_pointcaches(wd, &psys->ptcaches); } } diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c index 0f5e677b912..5acdcb40613 100644 --- a/source/blender/editors/physics/editparticle.c +++ b/source/blender/editors/physics/editparticle.c @@ -120,6 +120,20 @@ static int PE_poll(bContext *C) return (edit && (ob->mode & OB_MODE_PARTICLE_EDIT)); } +static int PE_hair_poll(bContext *C) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); + PTCacheEdit *edit; + + if(!scene || !ob) + return 0; + + edit= PE_get_current(scene, ob); + + return (edit && edit->psys && (ob->mode & OB_MODE_PARTICLE_EDIT)); +} + static int PE_poll_3dview(bContext *C) { return PE_poll(C) && CTX_wm_area(C)->spacetype == SPACE_VIEW3D && @@ -169,6 +183,8 @@ int PE_start_edit(PTCacheEdit *edit) { if(edit) { edit->edited = 1; + if(edit->psys) + edit->psys->flag |= PSYS_EDITED; return 1; } @@ -218,9 +234,16 @@ PTCacheEdit *PE_get_current(Scene *scene, Object *ob) if(psys->flag & PSYS_CURRENT) { if(psys->part && psys->part->type == PART_HAIR) { - if(!psys->edit && psys->flag & PSYS_HAIR_DONE) - PE_create_particle_edit(scene, ob, NULL, psys); - edit = psys->edit; + if(psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) { + if(!psys->pointcache->edit) + PE_create_particle_edit(scene, ob, pid->cache, NULL); + edit = pid->cache->edit; + } + else { + if(!psys->edit && psys->flag & PSYS_HAIR_DONE) + PE_create_particle_edit(scene, ob, NULL, psys); + edit = psys->edit; + } } else { if(pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) @@ -2387,7 +2410,7 @@ void PARTICLE_OT_delete(wmOperatorType *ot) /* api callbacks */ ot->exec= delete_exec; ot->invoke= WM_menu_invoke; - ot->poll= PE_poll; + ot->poll= PE_hair_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -3858,6 +3881,7 @@ static int clear_edited_exec(bContext *C, wmOperator *op) psys->recalc |= PSYS_RECALC_RESET; psys->flag &= ~PSYS_GLOBAL_HAIR; + psys->flag &= ~PSYS_EDITED; psys_reset(psys, PSYS_RESET_DEPSGRAPH); DAG_id_flush_update(&ob->id, OB_RECALC_DATA); @@ -3894,15 +3918,13 @@ static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event) pup= uiPupMenuBegin(C, "Specials", 0); layout= uiPupMenuLayout(pup); - if(edit->psys) { - uiItemO(layout, NULL, 0, "PARTICLE_OT_rekey"); - if(pset->selectmode & SCE_SELECT_POINT) { - uiItemO(layout, NULL, 0, "PARTICLE_OT_subdivide"); - uiItemO(layout, NULL, 0, "PARTICLE_OT_select_first"); - uiItemO(layout, NULL, 0, "PARTICLE_OT_select_last"); - } - uiItemO(layout, NULL, 0, "PARTICLE_OT_remove_doubles"); + uiItemO(layout, NULL, 0, "PARTICLE_OT_rekey"); + if(pset->selectmode & SCE_SELECT_POINT) { + uiItemO(layout, NULL, 0, "PARTICLE_OT_subdivide"); + uiItemO(layout, NULL, 0, "PARTICLE_OT_select_first"); + uiItemO(layout, NULL, 0, "PARTICLE_OT_select_last"); } + uiItemO(layout, NULL, 0, "PARTICLE_OT_remove_doubles"); uiPupMenuEnd(C, pup); @@ -3917,7 +3939,7 @@ void PARTICLE_OT_specials_menu(wmOperatorType *ot) /* api callbacks */ ot->invoke= specials_menu_invoke; - ot->poll= PE_poll; + ot->poll= PE_hair_poll; } /**************************** registration **********************************/ diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 0df6f6250ff..bc9b05dc12e 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -54,6 +54,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_modifier.h" #include "BKE_node.h" #include "BKE_particle.h" #include "BKE_pointcache.h" @@ -728,6 +729,7 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) PTCacheEdit *edit = psys->edit; PTCacheEditPoint *point = edit ? edit->points : NULL; PTCacheEditKey *ekey = NULL; + DerivedMesh *dm = NULL; HairKey *key; int i, k; float hairmat[4][4]; @@ -738,13 +740,18 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) if(!psys->part || psys->part->type != PART_HAIR) return; + if(psmd->dm->deformedOnly) + dm= psmd->dm; + else + dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + for(i=0; itotpart; i++,pa++) { if(point) { ekey = point->keys; point++; } - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, dm, psys->part->from, pa, hairmat); for(k=0,key=pa->hair; ktotkey; k++,key++) { Mat4MulVecfl(hairmat,key->co); @@ -758,6 +765,9 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) psys_free_path_cache(psys, psys->edit); + if(!psmd->dm->deformedOnly) + dm->release(dm); + psys->flag |= PSYS_GLOBAL_HAIR; PE_update_object(scene, ob, 0); @@ -814,8 +824,8 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) BVHTreeFromMesh bvhtree; BVHTreeNearest nearest; MFace *mface; - DerivedMesh *dm = CDDM_copy(psmd->dm); - int numverts = dm->getNumVerts (dm); + DerivedMesh *dm = NULL; + int numverts; int i, k; float hairmat[4][4], imat[4][4]; float v[4][3], vec[3]; @@ -823,6 +833,13 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) if(!psys || !psys->part || psys->part->type != PART_HAIR) return; + if(psmd->dm->deformedOnly) + dm= psmd->dm; + else + dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + + numverts = dm->getNumVerts (dm); + memset( &bvhtree, 0, sizeof(bvhtree) ); /* convert to global coordinates */ @@ -881,7 +898,8 @@ static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) } free_bvhtree_from_mesh(&bvhtree); - dm->release(dm); + if(!psmd->dm->deformedOnly) + dm->release(dm); psys_free_path_cache(psys, psys->edit); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 7ed029f3eaf..aa9c28dbef2 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3727,6 +3727,12 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj float nosel_col[3]; float *pathcol = NULL, *pcol; + + if(edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) { + PE_update_object(scene, ob, 0); + edit->psys->flag &= ~PSYS_HAIR_UPDATED; + } + /* create path and child path cache if it doesn't exist already */ if(edit->pathcache==0) psys_cache_edit_paths(scene, ob, edit, CFRA); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 33984582d7f..5cfecf7cc01 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -68,6 +68,7 @@ typedef struct ClothSimSettings float defgoal; float goalspring; float goalfrict; + float velocity_smooth; /* smoothing of velocities for hair */ int stepsPerFrame; /* Number of time steps per frame. */ int flags; /* flags, see CSIMSETT_FLAGS enum above. */ int preroll; /* How many frames of simulation to do before we start. */ @@ -78,7 +79,6 @@ typedef struct ClothSimSettings short vgroup_struct; /* vertex group for scaling structural stiffness */ short presets; /* used for presets on GUI */ short pad; - int pad2; } ClothSimSettings; diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 5696f82ab0d..986a75f1a96 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -184,8 +184,6 @@ typedef struct BulletSoftBody { typedef struct SoftBody { - struct ParticleSystem *particles; /* particlesystem softbody */ - /* dynamic data */ int totpoint, totspring; struct BodyPoint *bpoint; /* not saved in file */ diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index d4dc3df0965..6a0a0e1d912 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -105,7 +105,7 @@ typedef struct ParticleData { short flag; short alive; /* the life state of a particle */ short loop; /* how many times particle life has looped */ - short rt; + short hair_index; } ParticleData; typedef struct ParticleSettings { @@ -202,7 +202,8 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in struct ParticleCacheKey **childcache; /* child cache (runtime) */ ListBase pathcachebufs, childcachebufs; /* buffers for the above */ - struct SoftBody *soft; /* hair softbody */ + struct ClothModifierData *clmd; /* cloth simulation for hair */ + struct DerivedMesh *hair_in_dm, *hair_out_dm; /* input/output for cloth simulation */ struct Object *target_ob; struct Object *lattice; @@ -216,9 +217,9 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in float imat[4][4]; /* used for duplicators */ float cfra, tree_frame; - int seed; + int seed, rt; int flag, totpart, totchild, totcached, totchildcache; - short recalc, target_psys, totkeyed, softflag, bakespace, rt2; + short recalc, target_psys, totkeyed, bakespace; char bb_uvname[3][32]; /* billboard uv name */ @@ -411,16 +412,16 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in /* psys->flag */ #define PSYS_CURRENT 1 #define PSYS_GLOBAL_HAIR 2 -//#define PSYS_BAKE_UI 4 +#define PSYS_HAIR_DYNAMICS 4 #define PSYS_KEYED_TIMING 8 #define PSYS_ENABLED 16 /* deprecated */ -//#define PSYS_FIRST_KEYED 32 +#define PSYS_HAIR_UPDATED 32 /* signal for updating hair particle mode */ #define PSYS_DRAWING 64 //#define PSYS_SOFT_BAKE 128 #define PSYS_DELETE 256 /* remove particlesystem as soon as possible */ #define PSYS_HAIR_DONE 512 #define PSYS_KEYED 1024 -//#define PSYS_EDITED 2048 +#define PSYS_EDITED 2048 //#define PSYS_PROTECT_CACHE 4096 #define PSYS_DISABLED 8192 diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 38086502d6f..22cc2e2c9c3 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -152,7 +152,7 @@ static char *rna_ClothSettings_path(PointerRNA *ptr) Object *ob= (Object*)ptr->id.data; ModifierData *md= modifiers_findByType(ob, eModifierType_Cloth); - return BLI_sprintfN("modifiers[%s].settings", md->name); + return md ? BLI_sprintfN("modifiers[%s].settings", md->name) : NULL; } static char *rna_ClothCollisionSettings_path(PointerRNA *ptr) @@ -160,7 +160,7 @@ static char *rna_ClothCollisionSettings_path(PointerRNA *ptr) Object *ob= (Object*)ptr->id.data; ModifierData *md= modifiers_findByType(ob, eModifierType_Cloth); - return BLI_sprintfN("modifiers[%s].collision_settings", md->name); + return md ? BLI_sprintfN("modifiers[%s].collision_settings", md->name) : NULL; } #else @@ -207,6 +207,12 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction."); RNA_def_property_update(prop, 0, "rna_cloth_update"); + prop= RNA_def_property(srna, "internal_friction", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "velocity_smooth"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Internal Friction", ""); + RNA_def_property_update(prop, 0, "rna_cloth_update"); + /* mass */ prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 719e6f43eed..e6f0a462f03 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -33,6 +33,7 @@ #include "rna_internal.h" +#include "DNA_modifier_types.h" #include "DNA_particle_types.h" #include "DNA_object_force.h" #include "DNA_object_types.h" @@ -96,7 +97,9 @@ EnumPropertyItem part_hair_ren_as_items[] = { #ifdef RNA_RUNTIME #include "BKE_context.h" +#include "BKE_cloth.h" #include "BKE_depsgraph.h" +#include "BKE_modifier.h" #include "BKE_particle.h" #include "BKE_pointcache.h" @@ -249,6 +252,21 @@ static void rna_Particle_redo_child(bContext *C, PointerRNA *ptr) WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); } +static void rna_Particle_hair_dynamics(bContext *C, PointerRNA *ptr) +{ + Scene *scene = CTX_data_scene(C); + ParticleSystem *psys = (ParticleSystem*)ptr->data; + + if(psys && !psys->clmd) { + psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth); + psys->clmd->sim_parms->goalspring = 0.0f; + psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; + psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; + rna_Particle_redo(C, ptr); + } + else + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, NULL); +} static PointerRNA rna_particle_settings_get(PointerRNA *ptr) { Object *ob= (Object*)ptr->id.data; @@ -467,7 +485,7 @@ static int rna_ParticleSystem_edited_get(PointerRNA *ptr) ParticleSystem *psys= (ParticleSystem*)ptr->data; if(psys->part && psys->part->type==PART_HAIR) - return (psys->edit && psys->edit->edited); + return (psys->flag & PSYS_EDITED || (psys->edit && psys->edit->edited)); else return (psys->pointcache->edit && psys->pointcache->edit->edited); } @@ -1876,19 +1894,22 @@ static void rna_def_particle_system(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Particle_reset"); /* hair */ - prop= RNA_def_property(srna, "softbody", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "soft"); - RNA_def_property_ui_text(prop, "Soft Body", "Soft body settings for hair physics simulation."); - - prop= RNA_def_property(srna, "use_softbody", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "softflag", OB_SB_ENABLE); - RNA_def_property_ui_text(prop, "Use Soft Body", "Enable use of soft body for hair physics simulation."); - prop= RNA_def_property(srna, "global_hair", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_GLOBAL_HAIR); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Global Hair", "Hair keys are in global coordinate space"); + prop= RNA_def_property(srna, "hair_dynamics", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_HAIR_DYNAMICS); + RNA_def_property_ui_text(prop, "Hair Dynamics", "Enable hair dynamics using cloth simulation."); + RNA_def_property_update(prop, 0, "rna_Particle_hair_dynamics"); + + prop= RNA_def_property(srna, "cloth", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "clmd"); + RNA_def_property_struct_type(prop, "ClothModifier"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Cloth", "Cloth dynamics for hair"); + /* reactor */ prop= RNA_def_property(srna, "reactor_target_object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "target_ob"); -- cgit v1.2.3 From 71907c7e4c7c20575edcb50ec29025284a9f9bed Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Fri, 11 Sep 2009 00:23:08 +0000 Subject: Disconnect hair was using wrong derived mesh for the space conversion. --- source/blender/editors/space_buttons/buttons_ops.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index bc9b05dc12e..176611377eb 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -729,7 +729,6 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) PTCacheEdit *edit = psys->edit; PTCacheEditPoint *point = edit ? edit->points : NULL; PTCacheEditKey *ekey = NULL; - DerivedMesh *dm = NULL; HairKey *key; int i, k; float hairmat[4][4]; @@ -740,18 +739,13 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) if(!psys->part || psys->part->type != PART_HAIR) return; - if(psmd->dm->deformedOnly) - dm= psmd->dm; - else - dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); - for(i=0; itotpart; i++,pa++) { if(point) { ekey = point->keys; point++; } - psys_mat_hair_to_global(ob, dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); for(k=0,key=pa->hair; ktotkey; k++,key++) { Mat4MulVecfl(hairmat,key->co); @@ -765,9 +759,6 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys) psys_free_path_cache(psys, psys->edit); - if(!psmd->dm->deformedOnly) - dm->release(dm); - psys->flag |= PSYS_GLOBAL_HAIR; PE_update_object(scene, ob, 0); -- cgit v1.2.3 From fc11700628b56d77cfd57c35c04e07e00d46b10e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 11 Sep 2009 00:49:54 +0000 Subject: 2.5 - Bugfix for curve-following animation not working Optimisation for not working with AnimData when there were no actions meant that the special hack to set this value didn't get set. --- source/blender/blenkernel/intern/anim_sys.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 0e8450025da..2d6a97c48ae 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1450,7 +1450,6 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a * standard 'root') block are overridden by a larger 'user' */ -// FIXME?: we currently go over entire 'main' database... void BKE_animsys_evaluate_all_animation (Main *main, float ctime) { ID *id; @@ -1474,8 +1473,11 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) * when there are no actions, don't go over database and loop over heaps of datablocks, * which should ultimately be empty, since it is not possible for now to have any animation * without some actions, and drivers wouldn't get affected by any state changes + * + * however, if there are some curves, we will need to make sure that their 'ctime' property gets + * set correctly, so this optimisation must be skipped in that case... */ - if (main->action.first == NULL) { + if ((main->action.first == NULL) && (main->curve.first == NULL)) { if (G.f & G_DEBUG) printf("\tNo Actions, so no animation needs to be evaluated...\n"); @@ -1509,6 +1511,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) * value of the curve gets set in case there's no animation for that * - it needs to be set before animation is evaluated just so that * animation can successfully override... + * - it shouldn't get set when calculating drivers... */ for (id= main->curve.first; id; id= id->next) { AnimData *adt= BKE_animdata_from_id(id); -- cgit v1.2.3 From 40576677b1dff5373d5b673b599ea9beb094b1ea Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 11 Sep 2009 09:09:54 +0000 Subject: 2.5: Two Bugfixes * Mesh Deform modifier now correctly shows Bind/Unbind buttons. Previously, only Bind got shown... * Selecting keyframes in the Graph Editor using Border Select now allows the keyframes to be editable afterwards. Previously, the curves weren't getting selected afterwards, therefore, the poll operators would skip those curves. --- source/blender/editors/space_graph/graph_select.c | 9 ++++++++- source/blender/makesrna/intern/rna_modifier.c | 12 +++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 43f35862315..728c9310a47 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -234,6 +234,7 @@ static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, sho /* loop over data, doing border select */ for (ale= anim_data.first; ale; ale= ale->next) { AnimData *adt= ANIM_nla_mapping_get(ac, ale); + FCurve *fcu= (FCurve *)ale->key_data; /* set horizontal range (if applicable) */ if (mode != BEZT_OK_VALUERANGE) { @@ -253,7 +254,13 @@ static void borderselect_graphkeys (bAnimContext *ac, rcti rect, short mode, sho } /* select keyframes that are in the appropriate places */ - ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL); + ANIM_fcurve_keys_bezier_loop(&bed, fcu, ok_cb, select_cb, NULL); + + /* select the curve too + * NOTE: this should really only happen if the curve got touched... + */ + if (selectmode == SELECT_ADD) + fcu->flag |= FCURVE_SELECTED; } /* cleanup */ diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 28223d2f80b..32e34559f1f 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -384,6 +384,11 @@ static void rna_ArrayModifier_curve_set(PointerRNA *ptr, PointerRNA value) modifier_object_set(&((ArrayModifierData*)ptr->data)->curve_ob, OB_CURVE, value); } +static int rna_MeshDeformModifier_is_bound_get(PointerRNA *ptr) +{ + return (((MeshDeformModifierData*)ptr->data)->bindcos != NULL); +} + static PointerRNA rna_SoftBodyModifier_settings_get(PointerRNA *ptr) { Object *ob= (Object*)ptr->id.data; @@ -1368,7 +1373,12 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, NULL, "rna_MeshDeformModifier_object_set", NULL); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); - + + prop= RNA_def_property(srna, "is_bound", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_MeshDeformModifier_is_bound_get", NULL); + RNA_def_property_ui_text(prop, "Bound", "Whether geometry has been bound to control cage."); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop= RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MDEF_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence."); -- cgit v1.2.3 From d5009eb1423c3c0359cbc85c7346412c597b8663 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 11 Sep 2009 12:05:09 +0000 Subject: 2.5 Rotations: As a experiment, enabling Axis-Angle for Bones The support for this is really quite hacky, and I might disable this later if we cannot get some parts to work nicely. Some notes: * This is currently stored in the same variable that quaternions are stored in, since they both have 4 components. However, in RNA, I've added 2 properties specially for this. * There are some shearing issues using certain axes - i.e. (1,1,0) - that will need to be checked on. * Transform code is really quite temporary for this. Just a quick demo of what can be done... --- source/blender/blenkernel/intern/armature.c | 8 ++- source/blender/editors/transform/transform.c | 11 +++- .../editors/transform/transform_conversions.c | 4 +- source/blender/makesrna/intern/rna_pose.c | 74 ++++++++++++++++++++-- source/blender/windowmanager/intern/wm_files.c | 2 +- 5 files changed, 88 insertions(+), 11 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 95c4c2966c6..0c18817f8be 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1986,11 +1986,15 @@ void chan_calc_mat(bPoseChannel *chan) /* get scaling matrix */ SizeToMat3(chan->size, smat); - /* rotations may either be quats or eulers (no rotation modes for now...) */ + /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */ if (chan->rotmode > 0) { - /* euler rotations (will cause gimble lock... no rotation order to solve that yet) */ + /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ EulOToMat3(chan->eul, chan->rotmode, rmat); } + else if (chan->rotmode == PCHAN_ROT_AXISANGLE) { + /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ + VecRotToMat3(&chan->quat[1], chan->quat[0], rmat); + } else { /* quats are normalised before use to eliminate scaling issues */ NormalQuat(chan->quat); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f049566d640..ac5d688cd1c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2663,7 +2663,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short /* rotation */ if ((t->flag & T_V3D_ALIGN)==0) { // align mode doesn't rotate objects itself - /* euler or quaternion? */ + /* euler or quaternion/axis-angle? */ if (td->flag & TD_USEQUAT) { Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0); @@ -2672,6 +2672,15 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short QuatMul(td->ext->quat, quat, td->ext->iquat); /* this function works on end result */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + + /* if axis-angle, we now convert the quat representation to axis-angle again + * - this means that the math above is not totally correct, but it works well enough so far... + */ + if (td->rotOrder == PCHAN_ROT_AXISANGLE) { + /* make temp copy (since stored in same place) */ + QuatCopy(quat, td->ext->quat); + QuatToAxisAngle(quat, &td->ext->quat[1], &td->ext->quat[0]); + } } else { float eulmat[3][3]; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 504563b797b..7a37ffdeeca 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -552,8 +552,9 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ob = ob; td->flag = TD_SELECTED; - if (pchan->rotmode == PCHAN_ROT_QUAT) + if ((pchan->rotmode == PCHAN_ROT_QUAT) || (pchan->rotmode == PCHAN_ROT_AXISANGLE)) { + // XXX: for now, axis-angle will be treated like for quats (the only difference is the normalisation) td->flag |= TD_USEQUAT; } if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) @@ -587,6 +588,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ext->quat= pchan->quat; QUATCOPY(td->ext->iquat, pchan->quat); + td->rotOrder= pchan->rotmode; } diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 7d7f37a8f43..0a88b084307 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -110,26 +110,64 @@ IDProperty *rna_PoseChannel_idproperties(PointerRNA *ptr, int create) return pchan->prop; } +/* rotation - euler angles */ static void rna_PoseChannel_euler_rotation_get(PointerRNA *ptr, float *value) { bPoseChannel *pchan= ptr->data; - - if(pchan->rotmode == PCHAN_ROT_QUAT) + + if(pchan->rotmode == PCHAN_ROT_AXISANGLE) { + float m[3][3]; + + /* go through a 3x3 matrix */ + VecRotToMat3(&pchan->quat[1], pchan->quat[0], m); + Mat3ToEul(m, value); + } + else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers when using axis-angle... */ QuatToEul(pchan->quat, value); else VECCOPY(value, pchan->eul); } +/* rotation - euler angles */ static void rna_PoseChannel_euler_rotation_set(PointerRNA *ptr, const float *value) { bPoseChannel *pchan= ptr->data; - - if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers when using quats... */ + + if(pchan->rotmode == PCHAN_ROT_AXISANGLE) { /* default XYZ eulers when using axis-angle... */ + float q[4]; + + /* convert to temp quat, then to axis angle (since stored in same var) */ + EulToQuat((float *)value, q); + QuatToAxisAngle(q, &pchan->quat[1], &pchan->quat[0]); + } + else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers when using quats... */ EulToQuat((float*)value, pchan->quat); else VECCOPY(pchan->eul, value); } +/* rotation - axis angle only */ +static void rna_PoseChannel_rotation_axis_get(PointerRNA *ptr, float *value) +{ + bPoseChannel *pchan= ptr->data; + + if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + /* axis is stord in quat for now */ + VecCopyf(value, &pchan->quat[1]); + } +} + +/* rotation - axis angle only */ +static void rna_PoseChannel_rotation_axis_set(PointerRNA *ptr, const float *value) +{ + bPoseChannel *pchan= ptr->data; + + if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + /* axis is stored in quat for now */ + VecCopyf(&pchan->quat[1], (float *)value); + } +} + static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) { bPoseChannel *pchan= ptr->data; @@ -185,6 +223,12 @@ static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) QuatCopy(q, pchan->quat); QuatToAxisAngle(q, &pchan->quat[1], &pchan->quat[0]); } + + /* when converting to axis-angle, we need a special exception for the case when there is no axis */ + if (IS_EQ(pchan->quat[1], pchan->quat[2]) && IS_EQ(pchan->quat[2], pchan->quat[3])) { + /* for now, rotate around y-axis then (so that it simply becomes the roll) */ + pchan->quat[2]= 1.0f; + } } /* finally, set the new rotation type */ @@ -421,7 +465,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) {PCHAN_ROT_YZX, "YZX", 0, "YZX Euler", "YZX Rotation Order. Prone to Gimbal Lock"}, {PCHAN_ROT_ZXY, "ZXY", 0, "ZXY Euler", "ZXY Rotation Order. Prone to Gimbal Lock"}, {PCHAN_ROT_ZYX, "ZYX", 0, "ZYX Euler", "ZYX Rotation Order. Prone to Gimbal Lock"}, - //{PCHAN_ROT_AXISANGLE, "AXIS_ANGLE", 0, "Axis Angle", "Axis Angle (W+XYZ). Defines a rotation around some axis defined by 3D-Vector."}, + {PCHAN_ROT_AXISANGLE, "AXIS_ANGLE", 0, "Axis Angle", "Axis Angle (W+XYZ). Defines a rotation around some axis defined by 3D-Vector."}, {0, NULL, 0, NULL, NULL}}; StructRNA *srna; @@ -493,6 +537,18 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Rotation", "Rotation in Quaternions."); RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); + prop= RNA_def_property(srna, "rotation_angle", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "quat[0]"); + RNA_def_property_ui_text(prop, "Rotation Angle", "Angle of Rotation for Axis-Angle rotation representation."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); + + prop= RNA_def_property(srna, "rotation_axis", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "quat"); + RNA_def_property_float_funcs(prop, "rna_PoseChannel_rotation_axis_get", "rna_PoseChannel_rotation_axis_set", NULL); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Rotation Axis", "Axis for Axis-Angle rotation representation."); + RNA_def_property_update(prop, NC_OBJECT|ND_TRANSFORM, "rna_Pose_update"); + prop= RNA_def_property(srna, "euler_rotation", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "eul"); RNA_def_property_float_funcs(prop, "rna_PoseChannel_euler_rotation_get", "rna_PoseChannel_euler_rotation_set", NULL); @@ -662,8 +718,14 @@ static void rna_def_pose_channel(BlenderRNA *brna) prop= RNA_def_property(srna, "lock_rotation", PROP_BOOLEAN, PROP_XYZ); RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_ROTX); RNA_def_property_array(prop, 3); - RNA_def_property_ui_text(prop, "Lock Rotation", "Lock editing of rotation in the interface."); + RNA_def_property_ui_text(prop, "Lock Rotation", "Lock editing of rotation (with three components) in the interface."); RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); + + //prop= RNA_def_property(srna, "lock_rotation_4d", PROP_BOOLEAN, PROP_XYZ); + //RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_ROTW); + //RNA_def_property_array(prop, 4); + //RNA_def_property_ui_text(prop, "Lock Rotation (4D)", "Lock editing of rotations (with four components) in the interface."); + //RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update"); prop= RNA_def_property(srna, "lock_scale", PROP_BOOLEAN, PROP_XYZ); RNA_def_property_boolean_sdna(prop, NULL, "protectflag", OB_LOCK_SCALEX); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index a6e38a61e0f..9694a8fa1c6 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -281,7 +281,7 @@ void WM_read_file(bContext *C, char *name, ReportList *reports) /* called on startup, (context entirely filled with NULLs) */ -/* or called for 'Erase All' */ +/* or called for 'New File' */ /* op can be NULL */ int WM_read_homefile(bContext *C, wmOperator *op) { -- cgit v1.2.3 From baf12d3d1712235f94bf7db27aed21421d74efea Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 11 Sep 2009 12:44:09 +0000 Subject: 2.5 - Rotation work (axis angle bugfixes + cleanups) * Made transform work better with axis-angle * Corrected the rotation-type handling code in a few places --- source/blender/editors/armature/editarmature.c | 12 ++++++++++ source/blender/editors/armature/poselib.c | 16 ++++--------- source/blender/editors/armature/poseobject.c | 14 ++++++++--- .../blender/editors/space_view3d/view3d_buttons.c | 26 ++++++++++++++++++--- source/blender/editors/transform/transform.c | 27 +++++++++++++++------- .../editors/transform/transform_conversions.c | 3 +-- 6 files changed, 70 insertions(+), 28 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 4f5d8872384..3b6c9e9d13d 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -4856,9 +4856,13 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) QUATCOPY(quat1, pchan->quat); QuatToEul(pchan->quat, oldeul); } + else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + continue; // XXX + } else { VECCOPY(oldeul, pchan->eul); } + eul[0]= eul[1]= eul[2]= 0.0f; if (pchan->protectflag & OB_LOCK_ROTX) @@ -4875,6 +4879,9 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) QuatMulf(pchan->quat, -1.0f); } } + else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + // TODO... + } else { VECCOPY(pchan->eul, eul); } @@ -4884,6 +4891,11 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) pchan->quat[1]=pchan->quat[2]=pchan->quat[3]= 0.0f; pchan->quat[0]= 1.0f; } + else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + /* by default, make rotation of 0 radians around y-axis (roll) */ + pchan->quat[0]=pchan->quat[1]=pchan->quat[3]= 0.0f; + pchan->quat[2]= 1.0f; + } else { pchan->eul[0]= pchan->eul[1]= pchan->eul[2]= 0.0f; } diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index 56d714fd058..46d08afa656 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -278,8 +278,7 @@ void poselib_validate_act (bAction *act) /* ************************************************************* */ /* Pointers to the builtin KeyingSets that we want to use */ -static KeyingSet *poselib_ks_locrotscale = NULL; /* quaternion rotations */ -static KeyingSet *poselib_ks_locrotscale2 = NULL; /* euler rotations */ // XXX FIXME... +static KeyingSet *poselib_ks_locrotscale = NULL; /* the only keyingset we'll need*/ static short poselib_ks_need_init= 1; /* have the above been obtained yet? */ /* Make sure the builtin KeyingSets are initialised properly @@ -290,13 +289,9 @@ static void poselib_get_builtin_keyingsets (void) /* only if we haven't got these yet */ // FIXME: this assumes that we will always get the builtin sets... if (poselib_ks_need_init) { - /* LocRotScale (quaternions) */ + /* LocRotScale (quaternions or eulers depending on context) */ poselib_ks_locrotscale= ANIM_builtin_keyingset_get_named(NULL, "LocRotScale"); - /* LocRotScale (euler) */ - //ks_locrotscale2= ANIM_builtin_keyingset_get_named(ks_locrotscale, "LocRotScale"); - poselib_ks_locrotscale2= poselib_ks_locrotscale; // FIXME: for now, just use the same one... - /* clear flag requesting init */ poselib_ks_need_init= 0; } @@ -410,11 +405,8 @@ static int poselib_add_exec (bContext *C, wmOperator *op) /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */ cks.pchan= pchan; - /* KeyingSet to use depends on rotation mode */ - if (pchan->rotmode) - modify_keyframes(C, &dsources, act, poselib_ks_locrotscale2, MODIFYKEY_MODE_INSERT, (float)frame); - else - modify_keyframes(C, &dsources, act, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)frame); + /* KeyingSet to use depends on rotation mode (but that's handled by the templates code) */ + modify_keyframes(C, &dsources, act, poselib_ks_locrotscale, MODIFYKEY_MODE_INSERT, (float)frame); } } } diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 0ae92de4407..9a404e24e12 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -812,10 +812,17 @@ void pose_copy_menu(Scene *scene) armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat); - if (pchan->rotmode > 0) - Mat4ToEulO(delta_mat, pchan->eul, pchan->rotmode); - else + if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + float tmp_quat[4]; + + /* need to convert to quat first (in temp var)... */ + Mat4ToQuat(delta_mat, tmp_quat); + QuatToAxisAngle(tmp_quat, &pchan->quat[1], &pchan->quat[0]); + } + else if (pchan->rotmode == PCHAN_ROT_QUAT) Mat4ToQuat(delta_mat, pchan->quat); + else + Mat4ToEulO(delta_mat, pchan->eul, pchan->rotmode); } break; case 11: /* Visual Size */ @@ -991,6 +998,7 @@ static int pose_paste_exec (bContext *C, wmOperator *op) pchan->flag= chan->flag; /* check if rotation modes are compatible (i.e. do they need any conversions) */ + // FIXME: add axis-angle here too... if (pchan->rotmode == chan->rotmode) { /* copy the type of rotation in use */ if (pchan->rotmode > 0) { diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 06320f871da..d78928921e5 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -511,8 +511,17 @@ static void v3d_posearmature_buts(uiBlock *block, View3D *v3d, Object *ob, float but= uiDefBut(block, TEX, B_NOP, "Bone:", 160, 140, 140, 19, bone->name, 1, 31, 0, 0, ""); uiButSetFunc(but, validate_bonebutton_cb, bone, NULL); uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob); - - QuatToEulO(pchan->quat, tfp->ob_eul, pchan->rotmode); // XXX? + + if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + float quat[4]; + /* convert to euler, passing through quats... */ + AxisAngleToQuat(quat, &pchan->quat[1], pchan->quat[0]); + QuatToEul(quat, tfp->ob_eul); + } + else if (pchan->rotmode == PCHAN_ROT_QUAT) + QuatToEul(pchan->quat, tfp->ob_eul); + else + VecCopyf(tfp->ob_eul, pchan->eul); tfp->ob_eul[0]*= 180.0/M_PI; tfp->ob_eul[1]*= 180.0/M_PI; tfp->ob_eul[2]*= 180.0/M_PI; @@ -841,7 +850,18 @@ static void do_view3d_region_buttons(bContext *C, void *arg, int event) eul[0]= M_PI*tfp->ob_eul[0]/180.0; eul[1]= M_PI*tfp->ob_eul[1]/180.0; eul[2]= M_PI*tfp->ob_eul[2]/180.0; - EulOToQuat(eul, pchan->rotmode, pchan->quat); // xxx? + + if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + float quat[4]; + /* convert to axis-angle, passing through quats */ + EulToQuat(eul, quat); + QuatToAxisAngle(quat, &pchan->quat[1], &pchan->quat[0]); + } + else if (pchan->rotmode == PCHAN_ROT_QUAT) + EulToQuat(eul, pchan->quat); + else + VecCopyf(pchan->eul, eul); + } /* no break, pass on */ case B_ARMATUREPANEL2: diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ac5d688cd1c..6405e87c4c0 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2673,14 +2673,25 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short /* this function works on end result */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); - /* if axis-angle, we now convert the quat representation to axis-angle again - * - this means that the math above is not totally correct, but it works well enough so far... - */ - if (td->rotOrder == PCHAN_ROT_AXISANGLE) { - /* make temp copy (since stored in same place) */ - QuatCopy(quat, td->ext->quat); - QuatToAxisAngle(quat, &td->ext->quat[1], &td->ext->quat[0]); - } + } + else if (td->rotOrder == PCHAN_ROT_AXISANGLE) { + /* calculate effect based on quats */ + float iquat[4]; + + /* td->ext->(i)quat is in axis-angle form, not quats! */ + AxisAngleToQuat(iquat, &td->ext->iquat[1], td->ext->iquat[0]); + + Mat3MulSerie(fmat, td->mtx, mat, td->smtx, 0, 0, 0, 0, 0); + Mat3ToQuat(fmat, quat); // Actual transform + + QuatMul(td->ext->quat, quat, iquat); + + /* this function works on end result */ + protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + + /* make temp copy (since stored in same place) */ + QuatCopy(quat, td->ext->quat); + QuatToAxisAngle(quat, &td->ext->quat[1], &td->ext->quat[0]); } else { float eulmat[3][3]; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 7a37ffdeeca..e0d058f160f 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -552,9 +552,8 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ob = ob; td->flag = TD_SELECTED; - if ((pchan->rotmode == PCHAN_ROT_QUAT) || (pchan->rotmode == PCHAN_ROT_AXISANGLE)) + if (pchan->rotmode == PCHAN_ROT_QUAT) { - // XXX: for now, axis-angle will be treated like for quats (the only difference is the normalisation) td->flag |= TD_USEQUAT; } if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) -- cgit v1.2.3 From 042d3e595693ce0c280b46d13db921afbcf105a4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 11 Sep 2009 14:56:54 +0000 Subject: 2.5: fix for merge, forward_diff_bezier needed to be updated. --- source/blender/editors/interface/interface_widgets.c | 4 ++-- source/blender/editors/space_graph/graph_draw.c | 4 ++-- source/blender/editors/space_node/drawnode.c | 4 ++-- source/blender/python/generic/Geometry.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f0085f71373..2385b5ad15c 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1647,8 +1647,8 @@ static int ui_link_bezier_points(rcti *rect, float coord_array[][2], int resol) vec[2][0]= vec[3][0]-dist; vec[2][1]= vec[3][1]; - forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, 2); - forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, 2); + forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float)*2); + forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, sizeof(float)*2); return 1; } diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index f3aa0fac42b..9ae7e8263ee 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -675,8 +675,8 @@ static void draw_fcurve_curve_bezts (FCurve *fcu, View2D *v2d, View2DGrid *grid) correct_bezpart(v1, v2, v3, v4); - forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, 3); - forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, 3); + forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float)*3); + forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, sizeof(float)*3); for (fp= data; resol; resol--, fp+= 3) glVertex2fv(fp); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 98de32a105a..05adb5b75ca 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2598,8 +2598,8 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa else { /* always do all three, to prevent data hanging around */ - forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, 2); - forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, 2); + forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float)*2); + forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, sizeof(float)*2); return 1; } diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c index 70295d1c2d9..f7b7ee866f0 100644 --- a/source/blender/python/generic/Geometry.c +++ b/source/blender/python/generic/Geometry.c @@ -523,7 +523,7 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args ) coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "BezierInterp"); for(i=0; i Date: Fri, 11 Sep 2009 15:35:30 +0000 Subject: curve twist * added new twist method - "Tangent", suggested by Martin. the nice thing about this is its stable no matter how you rotate the data, rotation is local to each segment. * added smooth option that smooths the twisting (before applying user twist), to workaround Z-Up and Tangent's ugly curve twisting. Id prefer not to have this however it makes tangent much nicer. Possibly tangent can be improved some other way and this can be removed. A smooth value of 1.0 will iterate over and smooth the twisting by the resolution value of the spline. * Minimum-Twist method now corrects for cyclic twist by taking the roll difference between first and last, then increasingly counter rotate each segment over the entire curve. Previously it calculated from both directions and blended them. details * BevPoints use quats rather then 3x3 matrix. * added BevPoint direction "dir" and tangent "tan" used only for 3D curves. * don't calculate BevPoint->cosa, BevPoint->sina for 3D curves. * split bevel tilt calculation into functions. * nurbs curves currently don't generate tangents and wont work with tangent twist method. * some of the use of quats should be optimized. * smoothing is not animation safe, the higher the smoothing the higher the likelyhood of flipping. --- source/blender/blenkernel/BKE_utildefines.h | 1 + source/blender/blenkernel/intern/curve.c | 607 ++++++++++++++++------- source/blender/blenkernel/intern/displist.c | 2 +- source/blender/editors/space_view3d/drawobject.c | 22 +- source/blender/makesdna/DNA_curve_types.h | 16 +- source/blender/makesrna/intern/rna_curve.c | 24 +- 6 files changed, 474 insertions(+), 198 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 76e0da98f69..4d43518901e 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -107,6 +107,7 @@ #define VECSUB(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1); *(v1+2)= *(v2+2) - *(v3+2);} #define VECSUB2D(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1);} #define VECADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac);} +#define VECSUBFAC(v1,v2,v3,fac) {*(v1)= *(v2) - *(v3)*(fac); *(v1+1)= *(v2+1) - *(v3+1)*(fac); *(v1+2)= *(v2+2) - *(v3+2)*(fac);} #define QUATADDFAC(v1,v2,v3,fac) {*(v1)= *(v2) + *(v3)*(fac); *(v1+1)= *(v2+1) + *(v3+1)*(fac); *(v1+2)= *(v2+2) + *(v3+2)*(fac); *(v1+3)= *(v2+3) + *(v3+3)*(fac);} #define INPR(v1, v2) ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] ) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 802809b11e5..2b8c91fcbed 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -975,7 +975,26 @@ void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int i q1+= q2; q2+= q3; } -} +} + +void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float *p3, float *p, int it, int stride) +{ + /* note that these are not purpendicular to the curve + * they need to be rotated for this, + * + * This could also be optimized like forward_diff_bezier */ + int a; + for(a=0; a<=it; a++) { + float t = (float)a / (float)it; + + int i; + for(i=0; i<3; i++) { + p[i]= (-6*t + 6)*p0[i] + (18*t - 12)*p1[i] + (-18*t + 6)*p2[i] + (6*t)*p3[i]; + } + Normalize(p); + p = (float *)(((char *)p)+stride); + } +} /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -1545,6 +1564,348 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * } } +/* make_bevel_list_3D_* funcs, at a minimum these must + * fill in the bezp->quat and bezp->dir values */ + +/* correct non-cyclic cases by copying direction and rotation + * values onto the first & last end-points */ +static void bevel_list_cyclic_fix(BevList *bl) +{ + BevPoint *bevp, *bevp1; + + bevp= (BevPoint *)(bl+1); + bevp1= bevp+1; + QUATCOPY(bevp->quat, bevp1->quat); + VECCOPY(bevp->dir, bevp1->dir); + VECCOPY(bevp->tan, bevp1->tan); + bevp= (BevPoint *)(bl+1); + bevp+= (bl->nr-1); + bevp1= bevp-1; + QUATCOPY(bevp->quat, bevp1->quat); + VECCOPY(bevp->dir, bevp1->dir); + VECCOPY(bevp->tan, bevp1->tan); +} +/* utility for make_bevel_list_3D_* funcs */ +static void bevel_list_calc_bisect(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; + int nr; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + /* totally simple */ + VecBisect3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} +static void bevel_list_flip_tangents(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; + int nr; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + if(VecAngle2(bevp0->tan, bevp1->tan) > 90) + VecNegf(bevp1->tan); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} +/* apply user tilt */ +static void bevel_list_apply_tilt(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; + int nr; + float q[4]; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + AxisAngleToQuat(q, bevp1->dir, bevp1->alfa); + QuatMul(bevp1->quat, q, bevp1->quat); + NormalQuat(bevp1->quat); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} +/* smooth quats, this function should be optimized, it can get slow with many iterations. */ +static void bevel_list_smooth(BevList *bl, int smooth_iter) +{ + BevPoint *bevp2, *bevp1, *bevp0; + int nr; + + float q[4]; + float bevp0_quat[4]; + int a; + + for(a=0; a < smooth_iter; a++) { + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + + if(bl->poly== -1) { /* check its not cyclic */ + /* skip the first point */ + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + nr--; + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + nr--; + + } + + QUATCOPY(bevp0_quat, bevp0->quat); + + while(nr--) { + /* interpolate quats */ + float zaxis[3] = {0,0,1}, cross[3], q2[4]; + QuatInterpol(q, bevp0_quat, bevp2->quat, 0.5); + NormalQuat(q); + + QuatMulVecf(q, zaxis); + Crossf(cross, zaxis, bevp1->dir); + AxisAngleToQuat(q2, cross, NormalizedVecAngle2(zaxis, bevp1->dir)); + NormalQuat(q2); + + QUATCOPY(bevp0_quat, bevp1->quat); + QuatMul(q, q2, q); + QuatInterpol(bevp1->quat, bevp1->quat, q, 0.5); + NormalQuat(bevp1->quat); + + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + } +} + +static void make_bevel_list_3D_zup(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */ + int nr; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + /* totally simple */ + VecBisect3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec); + vectoquat(bevp1->dir, 5, 1, bevp1->quat); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} + +static void make_bevel_list_3D_minimum_twist(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */ + int nr; + float q[4]; + + float cross_tmp[3]; + + bevel_list_calc_bisect(bl); + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + + if(nr+4 > bl->nr) { /* first time and second time, otherwise first point adjusts last */ + vectoquat(bevp1->dir, 5, 1, bevp1->quat); + } + else { + float angle= NormalizedVecAngle2(bevp0->dir, bevp1->dir); + + if(angle > 0.0f) { /* otherwise we can keep as is */ + Crossf(cross_tmp, bevp0->dir, bevp1->dir); + AxisAngleToQuat(q, cross_tmp, angle); + QuatMul(bevp1->quat, q, bevp0->quat); + } + else { + QUATCOPY(bevp1->quat, bevp0->quat); + } + } + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + + if(bl->poly != -1) { /* check for cyclic */ + + /* Need to correct for the start/end points not matching + * do this by calculating the tilt angle difference, then apply + * the rotation gradually over the entire curve + * + * note that the split is between last and second last, rather then first/last as youd expect. + * + * real order is like this + * 0,1,2,3,4 --> 1,2,3,4,0 + * + * this is why we compare last with second last + * */ + float vec_1[3]= {0,1,0}, vec_2[3]= {0,1,0}, angle, ang_fac, cross_tmp[3]; + + BevPoint *bevp_first; + BevPoint *bevp_last; + + + bevp_first= (BevPoint *)(bl+1); + bevp_first+= bl->nr-1; + bevp_last = bevp_first; + bevp_last--; + + /* quats and vec's are normalized, should not need to re-normalize */ + QuatMulVecf(bevp_first->quat, vec_1); + QuatMulVecf(bevp_last->quat, vec_2); + Normalize(vec_1); + Normalize(vec_2); + + /* align the vector, can avoid this and it looks 98% OK but + * better to align the angle quat roll's before comparing */ + { + Crossf(cross_tmp, bevp_last->dir, bevp_first->dir); + angle = NormalizedVecAngle2(bevp_first->dir, bevp_last->dir); + AxisAngleToQuat(q, cross_tmp, angle); + QuatMulVecf(q, vec_2); + } + + angle= NormalizedVecAngle2(vec_1, vec_2); + + /* flip rotation if needs be */ + Crossf(cross_tmp, vec_1, vec_2); + Normalize(cross_tmp); + if(NormalizedVecAngle2(bevp_first->dir, cross_tmp) < 90/(180.0/M_PI)) + angle = -angle; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + ang_fac= angle * (1.0f-((float)nr/bl->nr)); /* also works */ + + AxisAngleToQuat(q, bevp1->dir, ang_fac); + QuatMul(bevp1->quat, q, bevp1->quat); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + } +} + +static void make_bevel_list_3D_tangent(BevList *bl) +{ + BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */ + int nr; + + float bevp0_tan[3], cross_tmp[3]; + + bevel_list_calc_bisect(bl); + if(bl->poly== -1) /* check its not cyclic */ + bevel_list_cyclic_fix(bl); // XXX - run this now so tangents will be right before doing the flipping + bevel_list_flip_tangents(bl); + + /* correct the tangents */ + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + nr= bl->nr; + while(nr--) { + + Crossf(cross_tmp, bevp1->tan, bevp1->dir); + Crossf(bevp1->tan, cross_tmp, bevp1->dir); + Normalize(bevp1->tan); + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + + + /* now for the real twist calc */ + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + VECCOPY(bevp0_tan, bevp0->tan); + + nr= bl->nr; + while(nr--) { + + /* make perpendicular, modify tan in place, is ok */ + float cross_tmp[3]; + float zero[3] = {0,0,0}; + + Crossf(cross_tmp, bevp1->tan, bevp1->dir); + Normalize(cross_tmp); + triatoquat(zero, cross_tmp, bevp1->tan, bevp1->quat); /* XXX - could be faster */ + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } +} + +void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode) +{ + switch(twist_mode) { + case CU_TWIST_TANGENT: + make_bevel_list_3D_tangent(bl); + break; + case CU_TWIST_MINIMUM: + make_bevel_list_3D_minimum_twist(bl); + break; + default: /* CU_TWIST_Z_UP default, pre 2.49c */ + make_bevel_list_3D_zup(bl); + } + + if(bl->poly== -1) /* check its not cyclic */ + bevel_list_cyclic_fix(bl); + + if(smooth_iter) + bevel_list_smooth(bl, smooth_iter); + + bevel_list_apply_tilt(bl); +} + + + void makeBevelList(Object *ob) { /* @@ -1559,7 +1920,7 @@ void makeBevelList(Object *ob) BPoint *bp; BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; - float min, inp, x1, x2, y1, y2, vec[3], vec_prev[3], q[4], quat[4], quat_prev[4], cross[3]; + float min, inp, x1, x2, y1, y2; struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu, len=0; int do_tilt, do_radius; @@ -1664,7 +2025,15 @@ void makeBevelList(Object *ob) do_tilt ? &bevp->alfa : NULL, do_radius ? &bevp->radius : NULL, resolu, sizeof(BevPoint)); + + if(cu->twist_mode==CU_TWIST_TANGENT) { + forward_diff_bezier_cotangent( + prevbezt->vec[1], prevbezt->vec[2], + bezt->vec[0], bezt->vec[1], + bevp->tan, resolu, sizeof(BevPoint)); + } + /* indicate with handlecodes double points */ if(prevbezt->h1==prevbezt->h2) { if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->split_tag= TRUE; @@ -1843,208 +2212,90 @@ void makeBevelList(Object *ob) MEM_freeN(sortdata); } - /* STEP 4: COSINES */ - bl= cu->bev.first; - while(bl) { - - if(bl->nr < 2) { - /* do nothing */ - } - else if(bl->nr==2) { /* 2 pnt, treat separate */ - bevp2= (BevPoint *)(bl+1); - bevp1= bevp2+1; - - x1= bevp1->vec[0]- bevp2->vec[0]; - y1= bevp1->vec[1]- bevp2->vec[1]; - - calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa)); - bevp2->sina= bevp1->sina; - bevp2->cosa= bevp1->cosa; + /* STEP 4: 2D-COSINES or 3D ORIENTATION */ + if((cu->flag & CU_3D)==0) { /* 3D */ + bl= cu->bev.first; + while(bl) { - if(cu->flag & CU_3D) { /* 3D */ - float quat[4], q[4]; - - VecSubf(vec, bevp1->vec, bevp2->vec); - - vectoquat(vec, 5, 1, quat); - - AxisAngleToQuat(q, vec, bevp1->alfa); - QuatMul(quat, q, quat); - - QuatToMat3(quat, bevp1->mat); - Mat3CpyMat3(bevp2->mat, bevp1->mat); + if(bl->nr < 2) { + /* do nothing */ } + else if(bl->nr==2) { /* 2 pnt, treat separate */ + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+1; - } /* this has to be >2 points */ - else if(cu->flag & CU_NO_TWIST && cu->flag & CU_3D && bl->poly != -1) { - - /* Special case, cyclic curve with no twist. tricky... */ - - float quat[4], q[4], cross[3]; - - /* correcting a cyclic curve is more complicated, need to be corrected from both ends */ - float *quat_tmp1, *quat_tmp2; /* store a quat in the matrix temporarily */ - int iter_dir; - BevPoint *bevp_start= (BevPoint *)(bl+1); - - /* loop over the points twice, once up, once back, accumulate the quat rotations - * in both directions, then blend them in the 3rd loop and apply the tilt */ - for(iter_dir = 0; iter_dir < 2; iter_dir++) { + x1= bevp1->vec[0]- bevp2->vec[0]; + y1= bevp1->vec[1]- bevp2->vec[1]; + calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa)); + bevp2->sina= bevp1->sina; + bevp2->cosa= bevp1->cosa; + } + else { bevp2= (BevPoint *)(bl+1); bevp1= bevp2+(bl->nr-1); bevp0= bevp1-1; nr= bl->nr; while(nr--) { - - /* Normalizes */ - VecBisect3(vec, bevp0->vec, bevp1->vec, bevp2->vec); + x1= bevp1->vec[0]- bevp0->vec[0]; + x2= bevp1->vec[0]- bevp2->vec[0]; + y1= bevp1->vec[1]- bevp0->vec[1]; + y2= bevp1->vec[1]- bevp2->vec[1]; - if(bl->nr==nr+1) { /* first time */ - vectoquat(vec, 5, 1, quat); - } - else { - float angle = NormalizedVecAngle2(vec_prev, vec); - - if(angle > 0.0f) { /* otherwise we can keep as is */ - Crossf(cross, vec_prev, vec); - AxisAngleToQuat(q, cross, angle); - QuatMul(quat, q, quat_prev); - } - else { - QUATCOPY(quat, quat_prev); - } - } - QUATCOPY(quat_prev, quat); /* quat_prev can't have the tilt applied */ - VECCOPY(vec_prev, vec); - - if(iter_dir==0) { /* up, first time */ - quat_tmp1= (float *)bevp1->mat; + calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); - bevp0= bevp1; - bevp1= bevp2; - bevp2++; - } - else { /* down second time */ - quat_tmp1= ((float *)bevp1->mat)+4; - - bevp2= bevp1; - bevp1= bevp0; - bevp0--; - - /* wrap around */ - if (bevp0 < bevp_start) - bevp0= bevp_start+(bl->nr-1); - } - - QUATCOPY(quat_tmp1, quat); + bevp0= bevp1; + bevp1= bevp2; + bevp2++; } - } - - /* Now interpolate the 2 quats and apply tilt */ - bevp2= (BevPoint *)(bl+1); - bevp1= bevp2+(bl->nr-1); - bevp0= bevp1-1; - - nr= bl->nr; - while(nr--) { - - VecBisect3(vec, bevp0->vec, bevp1->vec, bevp2->vec); - - quat_tmp1= (float *)bevp1->mat; - quat_tmp2= quat_tmp1+4; - - /* blend the 2 rotations gathered from both directions */ - QuatInterpol(quat, quat_tmp1, quat_tmp2, 1.0 - (((float)nr)/bl->nr)); - - AxisAngleToQuat(q, vec, bevp1->alfa); - QuatMul(quat, q, quat); - QuatToMat3(quat, bevp1->mat); - - /* generic */ - x1= bevp1->vec[0]- bevp0->vec[0]; - x2= bevp1->vec[0]- bevp2->vec[0]; - y1= bevp1->vec[1]- bevp0->vec[1]; - y2= bevp1->vec[1]- bevp2->vec[1]; - - calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); - - bevp0= bevp1; - bevp1= bevp2; - bevp2++; - } - } - else { - /* Any curve with 3 or more points */ - - bevp2= (BevPoint *)(bl+1); - bevp1= bevp2+(bl->nr-1); - bevp0= bevp1-1; - - nr= bl->nr; - while(nr--) { - - if(cu->flag & CU_3D) { /* 3D */ - - /* Normalizes */ - VecBisect3(vec, bevp0->vec, bevp1->vec, bevp2->vec); - - if(bl->nr==nr+1 || !(cu->flag & CU_NO_TWIST)) { /* first time */ - vectoquat(vec, 5, 1, quat); - } - else { - float angle = NormalizedVecAngle2(vec_prev, vec); - - if(angle > 0.0f) { /* otherwise we can keep as is */ - Crossf(cross, vec_prev, vec); - AxisAngleToQuat(q, cross, angle); - QuatMul(quat, q, quat_prev); - } - else { - QUATCOPY(quat, quat_prev); - } - } - QUATCOPY(quat_prev, quat); /* quat_prev can't have the tilt applied */ - VECCOPY(vec_prev, vec); - - AxisAngleToQuat(q, vec, bevp1->alfa); - QuatMul(quat, q, quat); - QuatToMat3(quat, bevp1->mat); - } - - x1= bevp1->vec[0]- bevp0->vec[0]; - x2= bevp1->vec[0]- bevp2->vec[0]; - y1= bevp1->vec[1]- bevp0->vec[1]; - y2= bevp1->vec[1]- bevp2->vec[1]; - - calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); - - - bevp0= bevp1; - bevp1= bevp2; - bevp2++; - } - - /* correct non-cyclic cases */ - if(bl->poly== -1) { - if(bl->nr>2) { + /* correct non-cyclic cases */ + if(bl->poly== -1) { bevp= (BevPoint *)(bl+1); bevp1= bevp+1; bevp->sina= bevp1->sina; bevp->cosa= bevp1->cosa; - Mat3CpyMat3(bevp->mat, bevp1->mat); bevp= (BevPoint *)(bl+1); bevp+= (bl->nr-1); bevp1= bevp-1; bevp->sina= bevp1->sina; bevp->cosa= bevp1->cosa; - Mat3CpyMat3(bevp->mat, bevp1->mat); } } + bl= bl->next; + } + } + else { /* 3D Curves */ + bl= cu->bev.first; + while(bl) { + + if(bl->nr < 2) { + /* do nothing */ + } + else if(bl->nr==2) { /* 2 pnt, treat separate */ + float q[4]; + + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+1; + + /* simple quat/dir */ + VecSubf(bevp1->dir, bevp1->vec, bevp2->vec); + Normalize(bevp1->dir); + + vectoquat(bevp1->dir, 5, 1, bevp1->quat); + + AxisAngleToQuat(q, bevp1->dir, bevp1->alfa); + QuatMul(bevp1->quat, q, bevp1->quat); + NormalQuat(bevp1->quat); + VECCOPY(bevp2->dir, bevp1->dir); + QUATCOPY(bevp2->quat, bevp1->quat); + } + else { + make_bevel_list_3D(bl, (int)(resolu*cu->twist_smooth), cu->twist_mode); + } + bl= bl->next; } - bl= bl->next; } } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 99baa17b582..d87dbc833c5 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -1599,7 +1599,7 @@ void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) vec[1]= fp1[2]; vec[2]= 0.0; - Mat3MulVecfl(bevp->mat, vec); + QuatMulVecf(bevp->quat, vec); data[0]= bevp->vec[0] + fac*vec[0]; data[1]= bevp->vec[1] + fac*vec[1]; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 53fd6972641..69bc8e1f67e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -4129,21 +4129,21 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, while (nr-->0) { /* accounts for empty bevel lists */ float fac= bevp->radius * ts->normalsize; - float ox,oy,oz; // Offset perpendicular to the curve - float dx,dy,dz; // Delta along the curve + float vec_a[3] = { fac,0, 0}; // Offset perpendicular to the curve + float vec_b[3] = {-fac,0, 0}; // Delta along the curve + + QuatMulVecf(bevp->quat, vec_a); + QuatMulVecf(bevp->quat, vec_b); + VecAddf(vec_a, vec_a, bevp->vec); + VecAddf(vec_b, vec_b, bevp->vec); - ox = fac*bevp->mat[0][0]; - oy = fac*bevp->mat[0][1]; - oz = fac*bevp->mat[0][2]; - - dx = fac*bevp->mat[2][0]; - dy = fac*bevp->mat[2][1]; - dz = fac*bevp->mat[2][2]; + VECSUBFAC(vec_a, vec_a, bevp->dir, fac); + VECSUBFAC(vec_b, vec_b, bevp->dir, fac); glBegin(GL_LINE_STRIP); - glVertex3f(bevp->vec[0] - ox - dx, bevp->vec[1] - oy - dy, bevp->vec[2] - oz - dz); + glVertex3fv(vec_a); glVertex3fv(bevp->vec); - glVertex3f(bevp->vec[0] + ox - dx, bevp->vec[1] + oy - dy, bevp->vec[2] + oz - dz); + glVertex3fv(vec_b); glEnd(); bevp += skip+1; diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 3a7cf874dbd..013491187ae 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -71,7 +71,9 @@ typedef struct BevList { # # typedef struct BevPoint { - float vec[3], mat[3][3], alfa, radius, sina, cosa; + float vec[3], alfa, radius; + float sina, cosa; /* 2D Only */ + float dir[3], tan[3], quat[4]; /* 3D Only */ short split_tag, dupe_tag; } BevPoint; @@ -165,7 +167,8 @@ typedef struct Curve { int texflag; /* keep an int because of give_obdata_texspace() */ - short drawflag, pad[3]; + short drawflag, twist_mode, pad[2]; + float twist_smooth, pad2; short pathlen, totcol; short flag, bevresol; @@ -174,7 +177,7 @@ typedef struct Curve { /* default */ short resolu, resolv; short resolu_ren, resolv_ren; - + /* edit, index in nurb list */ int actnu; /* edit, last selected bpoint */ @@ -231,7 +234,12 @@ typedef struct Curve { #define CU_RETOPO 1024 #define CU_DS_EXPAND 2048 -#define CU_NO_TWIST 4096 +/* twist mode */ +#define CU_TWIST_Z_UP 0 +// #define CU_TWIST_Y_UP 1 // not used yet +// #define CU_TWIST_X_UP 2 +#define CU_TWIST_MINIMUM 3 +#define CU_TWIST_TANGENT 4 /* spacemode */ #define CU_LEFT 0 diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 91628bab376..d09546231d5 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -664,6 +664,12 @@ static void rna_def_curve(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static EnumPropertyItem curve_twist_mode_items[] = { + {CU_TWIST_Z_UP, "Z_UP", 0, "Z-Up", "Use Z-Up axis to calculate the curve twist at each point"}, + {CU_TWIST_MINIMUM, "MINIMUM", 0, "Minimum", "Use the least twist over the entire curve"}, + {CU_TWIST_TANGENT, "TANGENT", 0, "Tangent", "Use the tangent to calculate twist"}, + {0, NULL, 0, NULL, NULL}}; + srna= RNA_def_struct(brna, "Curve", "ID"); RNA_def_struct_ui_text(srna, "Curve", "Curve datablock storing curves, splines and NURBS."); RNA_def_struct_ui_icon(srna, ICON_CURVE_DATA); @@ -782,12 +788,22 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_BACK); RNA_def_property_ui_text(prop, "Back", "Draw filled back for extruded/beveled curves."); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - - prop= RNA_def_property(srna, "use_twist_correction", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_NO_TWIST); - RNA_def_property_ui_text(prop, "Minimal Twist", "Correct for twisting."); + + prop= RNA_def_property(srna, "twist_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "twist_mode"); + RNA_def_property_enum_items(prop, curve_twist_mode_items); + RNA_def_property_ui_text(prop, "Twist Method", "The type of tilt calculation for 3D Curves."); + RNA_def_property_update(prop, 0, "rna_Curve_update_data"); + + // XXX - would be nice to have a better way to do this, only add for testing. + prop= RNA_def_property(srna, "twist_smooth", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "twist_smooth"); + RNA_def_property_ui_range(prop, 0, 100.0, 0.1, 0); + RNA_def_property_ui_text(prop, "Twist Smooth", "Smoothing iteration for tangents"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); + + prop= RNA_def_property(srna, "retopo", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_RETOPO); RNA_def_property_ui_text(prop, "Retopo", "Turn on the re-topology tool."); -- cgit v1.2.3