diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2008-01-09 15:04:54 +0300 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2008-01-09 15:04:54 +0300 |
commit | 43cd8a9f71da3e0d1a78a5c1e089afd464862a42 (patch) | |
tree | 3615d80057d47d114e0ff19e38d51cdb4710be09 | |
parent | 86d8ef3f9125b4439b5231a756cee5cb89e3f270 (diff) | |
parent | 048170bc6f8e20beec8aedb4753991b027c65f4f (diff) |
svn merge -r 13148:13177 https://svn.blender.org/svnroot/bf-blender/trunk/blender + fixed one crash on enabling deflection
24 files changed, 1282 insertions, 256 deletions
diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index 0f58b93730a..512ee67b36f 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -41,6 +41,7 @@ typedef struct BodyPoint { float origS[3], origE[3], origT[3], pos[3], vec[3], force[3]; float goal; float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */ + float impdv[3],impdx[3]; int nofsprings; int *springs; float choke; float colball; diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 355cd19da33..f8f2f0b9f57 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -9,6 +9,7 @@ incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes' incs += ' #/intern/iksolver/extern ../blenloader ../quicktime' incs += ' #/extern/bullet2/src' incs += ' #/intern/bmfont' +incs += ' #/intern/opennl/extern' incs += ' ' + env['BF_OPENGL_INC'] incs += ' ' + env['BF_ZLIB_INC'] diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 8651996515b..40c776248cf 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -47,6 +47,7 @@ #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" @@ -76,7 +77,7 @@ #define MAX_DUPLI_RECUR 4 -static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float (*par_space_mat)[][4], int level); +static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level); void free_path(Path *path) { @@ -327,7 +328,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level) if(go->ob->transflag & OB_DUPLI) { Mat4CpyMat4(dob->ob->obmat, dob->mat); - object_duplilist_recursive((ID *)group, go->ob, lb, &ob->obmat, level+1); + object_duplilist_recursive((ID *)group, go->ob, lb, ob->obmat, level+1); Mat4CpyMat4(dob->ob->obmat, dob->omat); } } @@ -412,12 +413,12 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n float tmpmat[4][4]; Mat4CpyMat4(tmpmat, vdd->ob->obmat); Mat4CpyMat4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->ob, vdd->lb, &obmat, vdd->level+1); + object_duplilist_recursive((ID *)vdd->id, vdd->ob, vdd->lb, obmat, vdd->level+1); Mat4CpyMat4(vdd->ob->obmat, tmpmat); } } -static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_mat)[][4], int level) +static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level) { Object *ob, *ob_iter; Base *base = NULL; @@ -473,11 +474,11 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_spac /* par_space_mat - only used for groups so we can modify the space dupli's are in when par_space_mat is NULL ob->obmat can be used instead of ob__obmat */ - if (par_space_mat) { - Mat4MulMat4(vdd.obmat, ob->obmat, *par_space_mat); - } else { + if(par_space_mat) + Mat4MulMat4(vdd.obmat, ob->obmat, par_space_mat); + else Mat4CpyMat4(vdd.obmat, ob->obmat); - } + vdd.id= id; vdd.level= level; vdd.lb= lb; @@ -512,7 +513,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float (*par_spac dm->release(dm); } -static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_mat)[][4], int level) +static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level) { Object *ob, *ob_iter; Base *base = NULL; @@ -583,11 +584,10 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_ /* par_space_mat - only used for groups so we can modify the space dupli's are in when par_space_mat is NULL ob->obmat can be used instead of ob__obmat */ - if (par_space_mat) { - Mat4MulMat4(ob__obmat, ob->obmat, *par_space_mat); - } else { + if(par_space_mat) + Mat4MulMat4(ob__obmat, ob->obmat, par_space_mat); + else Mat4CpyMat4(ob__obmat, ob->obmat); - } Mat3CpyMat4(imat, ob->parentinv); @@ -638,7 +638,7 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_ float tmpmat[4][4]; Mat4CpyMat4(tmpmat, ob->obmat); Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, ob, lb, &ob->obmat, level+1); + object_duplilist_recursive((ID *)id, ob, lb, ob->obmat, level+1); Mat4CpyMat4(ob->obmat, tmpmat); } } @@ -660,17 +660,46 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float (*par_space_ dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSystem *psys, int level) +static void particle_dupli_path_rotation(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) +{ + float loc[3], nor[3], vec[3], side[3], len; + + VecSubf(vec, (cache+cache->steps-1)->co, cache->co); + len= Normalize(vec); + + if(pa) + psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); + else + psys_particle_on_emitter(ob, psmd, + (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, + cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0); + + Crossf(side, nor, vec); + Normalize(side); + Crossf(nor, vec, side); + + Mat4One(mat); + VECCOPY(mat[0], vec); + VECCOPY(mat[1], side); + VECCOPY(mat[2], nor); + + *scale= len; +} + +static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level) { GroupObject *go; - Object *ob, **oblist=0; + Object *ob=0, **oblist=0; ParticleSettings *part; ParticleData *pa; ParticleKey state; - float ctime, pa_time; - float tmat[4][4], mat[3][3], obrotmat[3][3], parotmat[3][3], size=0.0; + ParticleCacheKey *cache; + ParticleSystemModifierData *psmd; + float ctime, pa_time, scale = 1.0f; + float tmat[4][4], mat[4][4], obrotmat[4][4], pamat[4][4], size=0.0; + float obmat[4][4], (*obmatlist)[4][4]=0; float xvec[3] = {-1.0, 0.0, 0.0}, *q; - int lay, a, k, step_nbr = 0, counter; + int lay, a, b, k, step_nbr = 0, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; if(psys==0) return; @@ -678,9 +707,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; - if (GS(id->name)!=ID_SCE) return; /* No support for groups YET! TODO */ - part=psys->part; + psmd= psys_get_modifier(par, psys); if(part==0) return; @@ -700,6 +728,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy else step_nbr = 0; + if(psys->flag & PSYS_HAIR_DONE) + hair= (totchild == 0 || psys->childcache) && psys->pathcache; + psys->lattice = psys_get_lattice(par, psys); if(part->draw_as==PART_DRAW_GR) { @@ -712,9 +743,16 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy } oblist= MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list"); + obmatlist= MEM_callocN(totgroup*sizeof(float)*4*4, "dupgroup obmat list"); go= part->dup_group->gobject.first; - for(a=0; a<totgroup; a++, go=go->next) + for(a=0; a<totgroup; a++, go=go->next) { oblist[a]=go->ob; + Mat4CpyMat4(obmatlist[a], go->ob->obmat); + } + } + else { + ob = part->dup_ob; + Mat4CpyMat4(obmat, ob->obmat); } if(totchild==0 || part->draw & PART_DRAW_PARENT) @@ -724,7 +762,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy for(pa=psys->particles,counter=0; a<totpart+totchild; a++,pa++,counter++) { if(a<totpart) { - if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; + if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) + continue; pa_num=pa->num; @@ -742,61 +781,91 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, ParticleSy if(part->draw_as==PART_DRAW_GR) { if(part->draw&PART_DRAW_RAND_GR) - ob = oblist[BLI_rand() % totgroup]; + b= BLI_rand() % totgroup; else if(part->from==PART_FROM_PARTICLE) - ob = oblist[pa_num % totgroup]; + b= pa_num % totgroup; else - ob = oblist[a % totgroup]; + b= a % totgroup; + + ob = oblist[b]; + Mat4CpyMat4(obmat, obmatlist[b]); } - else - ob = part->dup_ob; for(k=0; k<=step_nbr; k++, counter++) { - if(step_nbr) { + if(hair) { + if(a < totpart) { + cache = psys->pathcache[a]; + particle_dupli_path_rotation(par, part, psmd, pa, 0, cache, pamat, &scale); + } + else { + ChildParticle *cpa= psys->child+(a-totpart); + cache = psys->childcache[a-totpart]; + particle_dupli_path_rotation(par, part, psmd, 0, cpa, cache, pamat, &scale); + } + + VECCOPY(pamat[3], cache->co); + } + else if(step_nbr) { state.time = (float)k / (float)step_nbr; psys_get_particle_on_path(par, psys, a, &state, 0); + + QuatToMat4(state.rot, pamat); + VECCOPY(pamat[3], state.co); + pamat[3][3]= 1.0f; } else { state.time = -1.0; if(psys_get_particle_state(par, psys, a, &state, 0) == 0) continue; - } - QuatToMat3(state.rot, parotmat); + QuatToMat4(state.rot, pamat); + VECCOPY(pamat[3], state.co); + pamat[3][3]= 1.0f; + } if(part->draw_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { - for(go= part->dup_group->gobject.first; go; go= go->next) { - - Mat4CpyMat4(tmat, go->ob->obmat); - Mat4MulMat43(tmat, go->ob->obmat, parotmat); - Mat4MulFloat3((float *)tmat, size); + for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) { - VECADD(tmat[3], go->ob->obmat[3], state.co); + Mat4MulMat4(tmat, obmatlist[b], pamat); + Mat4MulFloat3((float *)tmat, size*scale); + if(par_space_mat) + Mat4MulMat4(mat, tmat, par_space_mat); + else + Mat4CpyMat4(mat, tmat); - new_dupli_object(lb, go->ob, tmat, par->lay, counter, OB_DUPLIPARTS); + new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS); } } else { /* to give ipos in object correct offset */ where_is_object_time(ob, ctime-pa_time); - q = vectoquat(xvec, ob->trackflag, ob->upflag); - QuatToMat3(q, obrotmat); + if(!hair) { + q = vectoquat(xvec, ob->trackflag, ob->upflag); + QuatToMat4(q, obrotmat); + obrotmat[3][3]= 1.0f; - Mat3MulMat3(mat, parotmat, obrotmat); - Mat4CpyMat4(tmat, ob->obmat); - Mat4MulMat43(tmat, ob->obmat, mat); - Mat4MulFloat3((float *)tmat, size); + Mat4MulMat4(mat, obrotmat, pamat); + } + else + Mat4CpyMat4(mat, pamat); - VECCOPY(tmat[3], state.co); + Mat4MulMat4(tmat, obmat, mat); + Mat4MulFloat3((float *)tmat, size*scale); + if(par_space_mat) + Mat4MulMat4(mat, tmat, par_space_mat); + else + Mat4CpyMat4(mat, tmat); - new_dupli_object(lb, ob, tmat, par->lay, counter, OB_DUPLIPARTS); + new_dupli_object(lb, ob, mat, par->lay, counter, OB_DUPLIPARTS); } } } } if(oblist) MEM_freeN(oblist); + if(obmatlist) + MEM_freeN(obmatlist); if(psys->lattice) { end_latt_deform(); @@ -877,7 +946,7 @@ static void font_duplilist(ListBase *lb, Object *par, int level) } /* ***************************** */ -static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float (*par_space_mat)[][4], int level) +static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level) { if((ob->transflag & OB_DUPLI)==0) return; @@ -896,7 +965,7 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, if(ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; for(; psys; psys=psys->next) - new_particle_duplilist(duplilist, id, ob, psys, level+1); + new_particle_duplilist(duplilist, id, ob, par_space_mat, psys, level+1); } else if(ob->transflag & OB_DUPLIVERTS) { if(ob->type==OB_MESH) { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 1235d9f5391..436d4d2210d 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1533,10 +1533,10 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi ParticleTexture ptex; ParticleKey state; IpoCurve *icu=0; - float fac, rotfac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],*q2=0; + float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],*q2=0; float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; - float q_one[4]={1.0,0.0,0.0,0.0}, q_phase[4]; + float q_phase[4]; part=psys->part; ptex.ivel=1.0; @@ -4241,7 +4241,7 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd, } if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && (psys_in_edit_mode(psys) - || part->draw_as==PART_DRAW_PATH || part->draw&PART_DRAW_KEYS)){ + || (part->type==PART_HAIR || part->draw_as==PART_DRAW_PATH) || part->draw&PART_DRAW_KEYS)){ psys_cache_paths(ob, psys, cfra, 0); /* for render, child particle paths are computed on the fly */ diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index f2258f0e1c4..b08b3e819d9 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -87,6 +87,7 @@ variables on the UI for now #include "BIF_editdeform.h" #include "BIF_graphics.h" #include "PIL_time.h" +#include "ONL_opennl.h" /* callbacks for errors and interrupts and some goo */ static int (*SB_localInterruptCallBack)(void) = NULL; @@ -97,7 +98,7 @@ static int (*SB_localInterruptCallBack)(void) = NULL; typedef struct BodySpring { int v1, v2; - float len, strength, cf; + float len, strength, cf,load; float ext_force[3]; /* edges colliding and sailing */ short order; short flag; @@ -120,6 +121,11 @@ typedef struct SBScratch { float aabbmin[3],aabbmax[3]; }SBScratch; +#define NLF_BUILD 1 +#define NLF_SOLVE 2 + +#define MID_PRESERVE 1 + #define SOFTGOALSNAP 0.999f /* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp removes *unnecessary* stiffnes from ODE system @@ -585,6 +591,7 @@ static void add_mesh_quad_diag_springs(Object *ob) if (ob->soft){ int nofquads; + float s_shear = ob->soft->shearstiff*ob->soft->shearstiff; nofquads = count_mesh_quads(me); if (nofquads) { @@ -605,12 +612,12 @@ static void add_mesh_quad_diag_springs(Object *ob) if(mface->v4) { bs->v1= mface->v1; bs->v2= mface->v3; - bs->strength= 1.0; + bs->strength= s_shear; bs->order =2; bs++; bs->v1= mface->v2; bs->v2= mface->v4; - bs->strength= 1.0; + bs->strength= s_shear; bs->order =2; bs++; @@ -692,6 +699,7 @@ static void add_2nd_order_springs(Object *ob,float stiffness) { int counter = 0; BodySpring *bs_new; + stiffness *=stiffness; add_2nd_order_roller(ob,stiffness,&counter,0); /* counting */ if (counter) { @@ -1450,6 +1458,7 @@ int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],float *damp } + void scan_for_ext_spring_forces(Object *ob,float timenow) { SoftBody *sb = ob->soft; @@ -2095,8 +2104,110 @@ static int sb_deflect_face(Object *ob,float *actpos,float *facenormal,float *for return(deflected); } +static void dfdx_spring(int ia, int ic, int op, float dir[3],float L,float len,float factor) +{ + float m,delta_ij; + int i ,j; + if (L < len){ + for(i=0;i<3;i++) + for(j=0;j<3;j++){ + delta_ij = (i==j ? (1.0f): (0.0f)); + m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j])); + nlMatrixAdd(ia+i,op+ic+j,m); + } + } + else{ + for(i=0;i<3;i++) + for(j=0;j<3;j++){ + m=factor*dir[i]*dir[j]; + nlMatrixAdd(ia+i,op+ic+j,m); + } + } +} -static void softbody_calc_forces(Object *ob, float forcetime, float timenow) + +static void dfdx_goal(int ia, int ic, int op, float factor) +{ + int i; + for(i=0;i<3;i++) nlMatrixAdd(ia+i,op+ic+i,factor); +} + +static void dfdv_goal(int ia, int ic,float factor) +{ + int i; + for(i=0;i<3;i++) nlMatrixAdd(ia+i,ic+i,factor); +} +static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags) +{ + SoftBody *sb= ob->soft; /* is supposed to be there */ + BodyPoint *bp1,*bp2; + + float dir[3],dvel[3]; + float distance,forcefactor,kd,absvel,projvel; + int ia,ic; + /* prepare depending on which side of the spring we are on */ + if (bpi == bs->v1){ + bp1 = &sb->bpoint[bs->v1]; + bp2 = &sb->bpoint[bs->v2]; + ia =3*bs->v1; + ic =3*bs->v2; + } + else if (bpi == bs->v2){ + bp1 = &sb->bpoint[bs->v2]; + bp2 = &sb->bpoint[bs->v1]; + ia =3*bs->v2; + ic =3*bs->v1; + } + else{ + /* TODO make this debug option */ + /**/ + printf("bodypoint <bpi> is not attached to spring <*bs> --> sb_spring_force()\n"); + return; + } + + /* do bp1 <--> bp2 elastic */ + VecSubf(dir,bp1->pos,bp2->pos); + distance = Normalize(dir); + if (bs->len < distance) + iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ + else + iks = 1.0f/(1.0f-sb->inpush)-1.0f ;/* inner spring constants function */ + + if(bs->len > 0.0f) /* check for degenerated springs */ + forcefactor = iks/bs->len; + else + forcefactor = iks; + forcefactor *= bs->strength; + Vec3PlusStVec(bp1->force,(bs->len - distance)*forcefactor,dir); + + /* do bp1 <--> bp2 viscous */ + VecSubf(dvel,bp1->vec,bp2->vec); + kd = sb->infrict * sb_fric_force_scale(ob); + absvel = Normalize(dvel); + projvel = Inpf(dir,dvel); + kd *= absvel * projvel; + Vec3PlusStVec(bp1->force,-kd,dir); + + /* do jacobian stuff if needed */ + if(nl_flags & NLF_BUILD){ + int op =3*sb->totpoint; + float mvel = -forcetime*kd; + float mpos = -forcetime*forcefactor; + /* depending on my pos */ + dfdx_spring(ia,ia,op,dir,bs->len,distance,-mpos); + /* depending on my vel */ + dfdv_goal(ia,ia,mvel); // well that ignores geometie + if(bp2->goal < SOFTGOALSNAP){ /* ommit this bp when it snaps */ + /* depending on other pos */ + dfdx_spring(ia,ic,op,dir,bs->len,distance,mpos); + /* depending on other vel */ + dfdv_goal(ia,ia,-mvel); // well that ignores geometie + } + } +} + + +static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags) { /* rule we never alter free variables :bp->vec bp->pos in here ! * this will ruin adaptive stepsize AKA heun! (BM) @@ -2106,10 +2217,20 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) BodyPoint *bproot; BodySpring *bs; ListBase *do_effector; - float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3]; + float iks, ks, kd, gravity; float fieldfactor = 1000.0f, windfactor = 250.0f; float tune = sb->ballstiff; int a, b, do_deflector,do_selfcollision,do_springcollision,do_aero; + + + + NLboolean success; + + if(nl_flags){ + nlBegin(NL_SYSTEM); + nlBegin(NL_MATRIX); + } + gravity = sb->grav * sb_grav_force_scale(ob); @@ -2131,7 +2252,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) float defforce[3]; do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow); } - +/* if (do_selfcollision ){ float ce[3]; VecMidf(ce,sb->scratch->aabbmax,sb->scratch->aabbmin); @@ -2139,10 +2260,33 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) bp->octantflag = set_octant_flags(ce,bp->pos,bp->colball); } } - +*/ for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { /* clear forces accumulator */ bp->force[0]= bp->force[1]= bp->force[2]= 0.0; + if(nl_flags & NLF_BUILD){ + int ia =3*(sb->totpoint-a); + int op =3*sb->totpoint; + /* dF/dV = v */ + + nlMatrixAdd(op+ia,ia,-forcetime); + nlMatrixAdd(op+ia+1,ia+1,-forcetime); + nlMatrixAdd(op+ia+2,ia+2,-forcetime); + + + /* we need [unit - h* dF/dy]^-1 */ + + nlMatrixAdd(ia,ia,1); + nlMatrixAdd(ia+1,ia+1,1); + nlMatrixAdd(ia+2,ia+2,1); + + nlMatrixAdd(op+ia,op+ia,1); + nlMatrixAdd(op+ia+1,op+ia+1,1); + nlMatrixAdd(op+ia+2,op+ia+2,1); + + + + } /* naive ball self collision */ /* needs to be done if goal snaps or not */ @@ -2156,7 +2300,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) for(c=sb->totpoint, obp= sb->bpoint; c>=a; c--, obp++) { - if ((bp->octantflag & obp->octantflag) == 0) continue; + //if ((bp->octantflag & obp->octantflag) == 0) continue; compare = (obp->colball + bp->colball); VecSubf(def, bp->pos, obp->pos); @@ -2182,8 +2326,33 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) VecSubf(dvel,velcenter,bp->vec); VecMulf(dvel,sb->nodemass); - Vec3PlusStVec(bp->force,sb->balldamp,dvel); Vec3PlusStVec(bp->force,f*(1.0f-sb->balldamp),def); + Vec3PlusStVec(bp->force,sb->balldamp,dvel); + + if(nl_flags & NLF_BUILD){ + int ia =3*(sb->totpoint-a); + int ic =3*(sb->totpoint-c); + int op =3*sb->totpoint; + float mvel = forcetime*sb->nodemass*sb->balldamp; + float mpos = forcetime*tune*(1.0f-sb->balldamp); + /*some quick and dirty entries to the jacobian*/ + dfdx_goal(ia,ia,op,mpos); + dfdv_goal(ia,ia,mvel); + /* exploit force(a,b) == -force(b,a) part1/2 */ + dfdx_goal(ic,ic,op,mpos); + dfdv_goal(ic,ic,mvel); + + + /*TODO sit down an X-out the true jacobian entries*/ + /*well does not make to much sense because the eigenvalues + of the jacobian go negative; and negative eigenvalues + on a complex iterative system z(n+1)=A * z(n) + give imaginary roots in the charcateristic polynom + --> solutions that to z(t)=u(t)* exp ( i omega t) --> oscilations we don't want here + where u(t) is a unknown amplitude function (worst case rising fast) + */ + } + /* exploit force(a,b) == -force(b,a) part2/2 */ VecSubf(dvel,velcenter,obp->vec); VecMulf(dvel,sb->nodemass); @@ -2191,6 +2360,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) Vec3PlusStVec(obp->force,sb->balldamp,dvel); Vec3PlusStVec(obp->force,-f*(1.0f-sb->balldamp),def); + } } } @@ -2201,23 +2371,39 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) float auxvect[3]; float velgoal[3]; float absvel =0, projvel= 0; - /* do goal stuff */ if(ob->softflag & OB_SB_GOAL) { /* true elastic goal */ - VecSubf(auxvect,bp->origT,bp->pos); + VecSubf(auxvect,bp->pos,bp->origT); ks = 1.0f/(1.0f- bp->goal*sb->goalspring)-1.0f ; - bp->force[0]+= ks*(auxvect[0]); - bp->force[1]+= ks*(auxvect[1]); - bp->force[2]+= ks*(auxvect[2]); + bp->force[0]+= -ks*(auxvect[0]); + bp->force[1]+= -ks*(auxvect[1]); + bp->force[2]+= -ks*(auxvect[2]); + + if(nl_flags & NLF_BUILD){ + int ia =3*(sb->totpoint-a); + int op =3*(sb->totpoint); + /* depending on my pos */ + dfdx_goal(ia,ia,op,ks*forcetime); + } + + /* calulate damping forces generated by goals*/ VecSubf(velgoal,bp->origS, bp->origE); kd = sb->goalfrict * sb_fric_force_scale(ob) ; + VecAddf(auxvect,velgoal,bp->vec); if (forcetime > 0.0 ) { /* make sure friction does not become rocket motor on time reversal */ - bp->force[0]-= kd * (velgoal[0] + bp->vec[0]); - bp->force[1]-= kd * (velgoal[1] + bp->vec[1]); - bp->force[2]-= kd * (velgoal[2] + bp->vec[2]); + bp->force[0]-= kd * (auxvect[0]); + bp->force[1]-= kd * (auxvect[1]); + bp->force[2]-= kd * (auxvect[2]); + if(nl_flags & NLF_BUILD){ + int ia =3*(sb->totpoint-a); + Normalize(auxvect); + /* depending on my vel */ + dfdv_goal(ia,ia,kd*forcetime); + } + } else { bp->force[0]-= kd * (velgoal[0] - bp->vec[0]); @@ -2230,6 +2416,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) /* gravitation */ bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */ + //bp->force[1]-= gravity*sb->nodemass; /* individual mass of node here */ /* particle field & vortex */ @@ -2260,6 +2447,16 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) bp->force[1]-= bp->vec[1]*kd; bp->force[2]-= bp->vec[2]*kd; /* friction in media done */ + if(nl_flags & NLF_BUILD){ + int ia =3*(sb->totpoint-a); + int op =3*sb->totpoint; + /* da/dv = */ + + nlMatrixAdd(ia,ia,forcetime*kd); + nlMatrixAdd(ia+1,ia+1,forcetime*kd); + nlMatrixAdd(ia+2,ia+2,forcetime*kd); + } + } /* +++cached collision targets */ bp->choke = 0.0f; @@ -2269,7 +2466,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) kd = 1.0f; if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){ - if (intrusion < 0.0f){ + if ((!nl_flags)&&(intrusion < 0.0f)){ /*bjornmose: uugh.. what an evil hack violation of the 'don't touch bp->pos in here' rule but works nice, like this--> @@ -2287,8 +2484,15 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) VECSUB(cfforce,bp->vec,vel); Vec3PlusStVec(bp->force,-cf*50.0f,cfforce); } - Vec3PlusStVec(bp->force,kd,defforce); + if (nl_flags & NLF_BUILD){ + int ia =3*(sb->totpoint-a); + int op =3*sb->totpoint; + //dfdx_goal(ia,ia,op,mpos); // don't do unless you know + //dfdv_goal(ia,ia,-cf); + + } + } } @@ -2305,48 +2509,8 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) bp->choke = bs->cf; } - - if (( (sb->totpoint-a) == bs->v1) ){ - VecSubf(sd,(bproot+bs->v2)->pos, bp->pos); - actspringlen=Normalize(sd); - - /* friction stuff V1 */ - VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec); - kd = sb->infrict * sb_fric_force_scale(ob); - absvel = Normalize(velgoal); - projvel = ABS(Inpf(sd,velgoal)); - kd *= absvel * projvel; - Vec3PlusStVec(bp->force,-kd,velgoal); - - if(bs->len > 0.0f) /* check for degenerated springs */ - forcefactor = (bs->len - actspringlen)/bs->len * iks; - else - forcefactor = actspringlen * iks; - forcefactor *= bs->strength; - - Vec3PlusStVec(bp->force,-forcefactor,sd); - - } - - if (( (sb->totpoint-a) == bs->v2) ){ - VecSubf(sd,bp->pos,(bproot+bs->v1)->pos); - actspringlen=Normalize(sd); - - /* friction stuff V2 */ - VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec); - kd = sb->infrict * sb_fric_force_scale(ob); - absvel = Normalize(velgoal); - projvel = ABS(Inpf(sd,velgoal)); - kd *= absvel * projvel; - Vec3PlusStVec(bp->force,-kd,velgoal); - - if(bs->len > 0.0) - forcefactor = (bs->len - actspringlen)/bs->len * iks; - else - forcefactor = actspringlen * iks; - forcefactor *= bs->strength; - Vec3PlusStVec(bp->force,+forcefactor,sd); - } + // sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float forcetime,int nl_flags) + sb_spring_force(ob,sb->totpoint-a,bs,iks,forcetime,nl_flags); }/* loop springs */ }/* existing spring list */ }/*any edges*/ @@ -2356,14 +2520,206 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow) /* finally add forces caused by face collision */ - if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow); + if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow); + + /* finish matrix and solve */ + if(nl_flags & NLF_SOLVE){ + //double sct,sst=PIL_check_seconds_timer(); + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + int iv =3*(sb->totpoint-a); + int ip =3*(2*sb->totpoint-a); + int n; + for (n=0;n<3;n++) {nlRightHandSideSet(0, iv+n, bp->force[0+n]);} + for (n=0;n<3;n++) {nlRightHandSideSet(0, ip+n, bp->vec[0+n]);} + } + nlEnd(NL_MATRIX); + nlEnd(NL_SYSTEM); + + if ((G.rt >0) && (nl_flags & NLF_BUILD)) + { + printf("####MEE#####\n"); + nlPrintMatrix(); + } + + success= nlSolveAdvanced(NULL, 1); + + // nlPrintMatrix(); /* for debug purpose .. anyhow cropping B vector looks like working */ + if(success){ + float f; + int index =0; + /* for debug purpose .. anyhow cropping B vector looks like working */ + if (G.rt >0) + for(a=2*sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + f=nlGetVariable(0,index); + printf("(%f ",f);index++; + f=nlGetVariable(0,index); + printf("%f ",f);index++; + f=nlGetVariable(0,index); + printf("%f)",f);index++; + } + + index =0; + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + f=nlGetVariable(0,index); + bp->impdv[0] = f; index++; + f=nlGetVariable(0,index); + bp->impdv[1] = f; index++; + f=nlGetVariable(0,index); + bp->impdv[2] = f; index++; + } + /* + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + f=nlGetVariable(0,index); + bp->impdx[0] = f; index++; + f=nlGetVariable(0,index); + bp->impdx[1] = f; index++; + f=nlGetVariable(0,index); + bp->impdx[2] = f; index++; + } + */ + } + else{ + printf("Matrix inversion failed \n"); + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + VECCOPY(bp->impdv,bp->force); + } + + } + + //sct=PIL_check_seconds_timer(); + //if (sct-sst > 0.01f) printf(" implicit solver time %f %s \r",sct-sst,ob->id.name); + } /* cleanup */ + if(do_effector) pdEndEffectors(do_effector); } +static void softbody_apply_fake_implicit_forces(Object *ob, float forcetime, float *err, float *err_ref_pos,float *err_ref_vel) +{ + /* time evolution */ + /* do semi implicit euler */ + SoftBody *sb= ob->soft; /* is supposed to be there */ + BodyPoint *bp; + float *perp,*perv; + float erp[3],erv[3],dx[3],dv[3],aabbmin[3],aabbmax[3],cm[3]={0.0f,0.0f,0.0f}; + float timeovermass; + float maxerrpos= 0.0f,maxerrvel = 0.0f,maxerrvel2 = 0.0f; + int a,fuzzy=0; + + forcetime *= sb_time_scale(ob); + + aabbmin[0]=aabbmin[1]=aabbmin[2] = 1e20f; + aabbmax[0]=aabbmax[1]=aabbmax[2] = -1e20f; + + /* claim a minimum mass for vertex */ + if (sb->nodemass > 0.009999f) timeovermass = forcetime/sb->nodemass; + else timeovermass = forcetime/0.009999f; + /* step along error reference vector */ + perp =err_ref_pos; + perv =err_ref_vel; -static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err) + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + /* step along error reference vector */ + if(perp) {VECCOPY(erp,perp);perp +=3;} + if(perv) {VECCOPY(erv,perv);perv +=3;} + if(bp->goal < SOFTGOALSNAP){ + + /* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces + more forces*/ + /* the ( ... )' operator denotes derivate respective time */ + /* the "implicit" euler step for velocity then becomes */ + /* v(t + dt) = v(t) + O * X(t) * dt */ + /* O = [1-dt*dA/d(X)]^1 */ + /* with X = (a[n],v[n]) */ + /* da/dv | da/dx */ + /* dA/d(X) = ( ------------- )*/ + /* dv/dv | dv/dx */ + /* note!! we did not solve any implicit system but looking forward more or less smart + what a implicit solution may look like by means of taylor expansion */ + VECCOPY(dx,bp->vec); + + bp->force[0]= timeovermass * bp->impdv[0]; /* individual mass of node here */ + bp->force[1]= timeovermass * bp->impdv[1]; + bp->force[2]= timeovermass * bp->impdv[2]; + VECCOPY(dv,bp->force); + if(perv){ + maxerrvel = MAX2(maxerrvel,ABS(dv[0] - erv[0])); + maxerrvel = MAX2(maxerrvel,ABS(dv[1] - erv[1])); + maxerrvel = MAX2(maxerrvel,ABS(dv[2] - erv[2])); + } + + maxerrvel2 = MAX2(maxerrvel2,ABS(dv[0])); + maxerrvel2 = MAX2(maxerrvel2,ABS(dv[1])); + maxerrvel2 = MAX2(maxerrvel2,ABS(dv[2])); + + VECADD(bp->vec, bp->vec, dv); + + /* so here is (x)'= v(elocity) */ + /* the euler step for location then becomes */ + /* x(t + dt) = x(t) + v(t) * dt */ + +// VECCOPY(dx,bp->vec); + + dx[0]*=forcetime; + dx[1]*=forcetime; + dx[2]*=forcetime; + + /* bp->choke is set when we need to pull a vertex or edge out of the collider. + the collider object signals to get out by pushing hard. on the other hand + we don't want to end up in deep space so we add some <viscosity> + to balance that out */ + if (bp->choke > 0.0f){ + dx[0]*=(1.0f - bp->choke); + dx[1]*=(1.0f - bp->choke); + dx[2]*=(1.0f - bp->choke); + } + + + /* should be possible to get more out of the matrix inversion + but not verified yet + dx[0]*=forcetime*forcetime*bp->impdx[0]; + dx[1]*=forcetime*forcetime*bp->impdx[1]; + dx[2]*=forcetime*forcetime*bp->impdx[2]; + */ + VECADD(bp->pos, bp->pos, dx); + if (perp){ + maxerrpos = MAX2(maxerrpos,ABS(bp->pos[0]-erp[0])); + maxerrpos = MAX2(maxerrpos,ABS(bp->pos[1]-erp[1])); + maxerrpos = MAX2(maxerrpos,ABS(bp->pos[2]-erp[2])); + } + + + }/*snap*/ + /* so while we are looping BPs anyway do statistics on the fly */ + aabbmin[0] = MIN2(aabbmin[0],bp->pos[0]); + aabbmin[1] = MIN2(aabbmin[1],bp->pos[1]); + aabbmin[2] = MIN2(aabbmin[2],bp->pos[2]); + aabbmax[0] = MAX2(aabbmax[0],bp->pos[0]); + aabbmax[1] = MAX2(aabbmax[1],bp->pos[1]); + aabbmax[2] = MAX2(aabbmax[2],bp->pos[2]); + if (bp->flag & SBF_DOFUZZY) fuzzy =1; + } /*for*/ + + if (sb->totpoint) VecMulf(cm,1.0f/sb->totpoint); + if (sb->scratch){ + VECCOPY(sb->scratch->aabbmin,aabbmin); + VECCOPY(sb->scratch->aabbmax,aabbmax); + } + + if (err){ /* so step size will be controlled by biggest difference in slope */ + if (sb->solverflags & SBSO_OLDERR) + *err = MAX2(maxerrpos,maxerrvel); + else + if (perp) *err = maxerrpos; + else *err = maxerrvel2; + //printf("EP %f EV %f \n",maxerrpos,maxerrvel); + if (fuzzy){ + *err /= sb->fuzzyness; + } + } +} + +static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err, int mid_flags) { /* time evolution */ /* actually does an explicit euler step mode == 0 */ @@ -2386,6 +2742,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float * for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { if(bp->goal < SOFTGOALSNAP){ + if(mid_flags & MID_PRESERVE) VECCOPY(dx,bp->vec); /* so here is (v)' = a(cceleration) = sum(F_springs)/m + gravitation + some friction forces + more forces*/ /* the ( ... )' operator denotes derivate respective time */ @@ -2417,8 +2774,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float * /* so here is (x)'= v(elocity) */ /* the euler step for location then becomes */ /* x(t + dt) = x(t) + v(t) * dt */ - - VECCOPY(dx,bp->vec); + if(!(mid_flags & MID_PRESERVE)) VECCOPY(dx,bp->vec); dx[0]*=forcetime; dx[1]*=forcetime; dx[2]*=forcetime; @@ -2490,6 +2846,79 @@ static void softbody_restore_prev_step(Object *ob) } } +static void softbody_store_step(Object *ob) +{ + SoftBody *sb= ob->soft; /* is supposed to be there*/ + BodyPoint *bp; + int a; + + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + VECCOPY(bp->prevvec,bp->vec); + VECCOPY(bp->prevpos,bp->pos); + } +} + + +/* used by predictors and correctors */ +static void softbody_store_state(Object *ob,float *ppos,float *pvel) +{ + SoftBody *sb= ob->soft; /* is supposed to be there*/ + BodyPoint *bp; + int a; + float *pp=ppos,*pv=pvel; + + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + + VECCOPY(pv, bp->vec); + pv+=3; + + VECCOPY(pp, bp->pos); + pp+=3; + } +} + +/* used by predictors and correctors */ +static void softbody_retrieve_state(Object *ob,float *ppos,float *pvel) +{ + SoftBody *sb= ob->soft; /* is supposed to be there*/ + BodyPoint *bp; + int a; + float *pp=ppos,*pv=pvel; + + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + + VECCOPY(bp->vec,pv); + pv+=3; + + VECCOPY(bp->pos,pp); + pp+=3; + } +} + +/* used by predictors and correctors */ +static void softbody_swap_state(Object *ob,float *ppos,float *pvel) +{ + SoftBody *sb= ob->soft; /* is supposed to be there*/ + BodyPoint *bp; + int a; + float *pp=ppos,*pv=pvel; + float temp[3]; + + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + + VECCOPY(temp, bp->vec); + VECCOPY(bp->vec,pv); + VECCOPY(pv,temp); + pv+=3; + + VECCOPY(temp, bp->pos); + VECCOPY(bp->pos,pp); + VECCOPY(pp,temp); + pp+=3; + } +} + + /* care for bodypoints taken out of the 'ordinary' solver step ** because they are screwed to goal by bolts ** they just need to move along with the goal in time @@ -3193,6 +3622,8 @@ SoftBody *sbNew(void) sb->inspring= 0.5f; sb->infrict= 0.5f; + /*todo backward file compat should copy infrict to inpush while reading old files*/ + sb->inpush = 0.5f; sb->interval= 10; sb->sfra= G.scene->r.sfra; @@ -3205,9 +3636,13 @@ SoftBody *sbNew(void) sb->minloops = 10; + sb->maxloops = 300; sb->choke = 3; sb_new_scratch(sb); + /*todo backward file compat should set sb->shearstiff = 1.0f while reading old files*/ + sb->shearstiff = 1.0f; + sb->solverflags |= SBSO_OLDERR; return sb; } @@ -3256,7 +3691,7 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts HairKey *key= NULL; BodyPoint *bp; int a; - float dtime,ctime,forcetime,err; + float dtime,ctime,forcetime; float hairmat[4][4]; /* This part only sets goals and springs, based on original mesh/curve/lattice data. @@ -3446,8 +3881,10 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts } - if (TRUE) { /* */ + if (sb->solver_ID < 2) { /* special case of 2nd order Runge-Kutta type AKA Heun */ + int mid_flags=0; + float err = 0; float forcetimemax = 1.0f; float forcetimemin = 0.001f; float timedone =0.0; /* how far did we get without violating error condition */ @@ -3459,7 +3896,8 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops; if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops; - + + if(sb->solver_ID>0) mid_flags |= MID_PRESERVE; //forcetime = dtime; /* hope for integrating in one step */ forcetime =forcetimemax; /* hope for integrating in one step */ @@ -3470,13 +3908,13 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts sb->scratch->flag &= ~SBF_DOFUZZY; /* do predictive euler step */ - softbody_calc_forces(ob, forcetime,timedone/dtime); - softbody_apply_forces(ob, forcetime, 1, NULL); + softbody_calc_forces(ob, forcetime,timedone/dtime,0); + softbody_apply_forces(ob, forcetime, 1, NULL,mid_flags); /* crop new slope values to do averaged slope step */ - softbody_calc_forces(ob, forcetime,timedone/dtime); - softbody_apply_forces(ob, forcetime, 2, &err); + softbody_calc_forces(ob, forcetime,timedone/dtime,0); + softbody_apply_forces(ob, forcetime, 2, &err,mid_flags); softbody_apply_goalsnap(ob); @@ -3517,6 +3955,7 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts sct=PIL_check_seconds_timer(); if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone); } + /* ask for user break */ if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break; } @@ -3531,11 +3970,263 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts } } + else if (sb->solver_ID == 2) + { + /* do semi "fake" implicit euler */ + float *predict_vel=NULL,*predict_pos=NULL; /* for BDF style stepping */ + NLContext *sb_nlc = NULL; + int npredict=0,predict_mem_size; + int nvar = 3*2*sb->totpoint; + int loops =0 ; + float forcetimemax = 1.0f; // this one needs 5 steps as a minimum + float forcetimemin = 0.001f; + float timedone =0.0; /* how far did we get without violating error condition */ + /* loops = counter for emergency brake + * we don't want to lock up the system if physics fail + */ + SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */ + if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops; + if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops; + + + forcetime =forcetimemax; /* hope for integrating as fast as possible */ + + //allocate predictor buffers + npredict =1; + predict_mem_size =3*sizeof(float)*npredict*sb->totpoint; + predict_pos = MEM_mallocN(predict_mem_size,"SB_predict_pos"); + predict_vel = MEM_mallocN(predict_mem_size,"SB_predict_vel"); + + + while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ){ + float loss_of_accuracy=0; + // create new solver context for this loop + sb_nlc = (NLContext*)nlNewContext(); + /* hum it smells like threading trouble */ + nlSolverParameteri(NL_NB_VARIABLES, nvar); + nlSolverParameteri(NL_LEAST_SQUARES, NL_FALSE); + + interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime))); + softbody_store_step(ob); /* used for rolling back step guessing */ + softbody_store_state(ob,predict_pos,predict_vel); + softbody_calc_forces(ob, forcetime,timedone/dtime,NLF_BUILD|NLF_SOLVE); + // go full step + softbody_apply_fake_implicit_forces(ob, forcetime, NULL,NULL,NULL); + + // restore old situation and store 1rst solution to predictors + softbody_swap_state(ob,predict_pos,predict_vel); + // the following is to find out how good we were + // may be we can do smarter + // so now using the forces and jacobian we calculated before + // go only 1/2 + softbody_apply_fake_implicit_forces(ob, forcetime/2.0f, NULL,NULL,NULL); + // explore situation here without redoing the jacobian + softbody_calc_forces(ob, forcetime,timedone/dtime,NLF_SOLVE); + // go next 1/2 + softbody_apply_fake_implicit_forces(ob, forcetime/2.0f,&loss_of_accuracy,predict_pos,predict_vel ); + // now we have "loss_of_accuracy" + + softbody_apply_goalsnap(ob); + + if (loss_of_accuracy > SoftHeunTol) { /* error needs to be scaled to some quantity */ + + if (forcetime > forcetimemin){ + forcetime = MAX2(forcetime / 2.0f,forcetimemin); + softbody_restore_prev_step(ob); + //printf("down,"); + } + else { + timedone += forcetime; + } + } + else { + float newtime = forcetime * 1.5f; /* hope for 1.1 times better conditions in next step */ + // all that 1/2 stepping was useless ... hum we know now .. + softbody_swap_state(ob,predict_pos,predict_vel); + if (0){//(sb->scratch->flag & SBF_DOFUZZY){ + //if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */ + newtime = forcetime; + //} + } + else { + if (loss_of_accuracy > SoftHeunTol/1.1f) { /* stay with this stepsize unless err really small */ + newtime = forcetime; + } + } + + timedone += forcetime; + newtime=MIN2(forcetimemax,MAX2(newtime,forcetimemin)); + //if (newtime > forcetime) printf("up,"); + if (forcetime > 0.0) + forcetime = MIN2(dtime - timedone,newtime); + else + forcetime = MAX2(dtime - timedone,newtime); + } + loops++; + // give away solver context within loop + if (sb_nlc) + { + if (sb_nlc != nlGetCurrent())printf("Aye NL context mismatch! in softbody.c !\n"); + nlDeleteContext(sb_nlc); + sb_nlc = NULL; + } + + if(sb->solverflags & SBSO_MONITOR ){ + sct=PIL_check_seconds_timer(); + if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone); + } + + /* ask for user break */ + if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break; + } + + // give away buffers + if (predict_pos) MEM_freeN(predict_pos); + if (predict_vel) MEM_freeN(predict_vel); + + if(sb->solverflags & SBSO_MONITOR ){ + if (loops > HEUNWARNLIMIT) /* monitor high loop counts */ + printf("\r needed %d steps/frame ",loops); + } + + + }/*SOLVER SELECT*/ + else if (sb->solver_ID == 4) + { + /* do semi "fake" implicit euler */ + NLContext *sb_nlc = NULL; + int nvar = 3*2*sb->totpoint; + int loops =0 ; + float forcetimemax = 1.0f; // this one needs 5 steps as a minimum + float forcetimemin = 0.001f; + float timedone =0.0; /* how far did we get without violating error condition */ + /* loops = counter for emergency brake + * we don't want to lock up the system if physics fail + */ + SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */ + if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops; + if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops; + + + forcetime =forcetimemax; /* hope for integrating as fast as possible */ + while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ){ + float loss_of_accuracy=0; + // create new solver context for this loop + sb_nlc = (NLContext*)nlNewContext(); + /* hum it smells like threading trouble */ + nlSolverParameteri(NL_NB_VARIABLES, nvar); + nlSolverParameteri(NL_LEAST_SQUARES, NL_FALSE); + + + interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime))); + softbody_store_step(ob); /* used for rolling back step guessing */ + softbody_calc_forces(ob, forcetime,timedone/dtime,NLF_BUILD|NLF_SOLVE); + softbody_apply_fake_implicit_forces(ob, forcetime,&loss_of_accuracy,NULL,NULL); + softbody_apply_goalsnap(ob); + + if (loss_of_accuracy > SoftHeunTol) { /* error needs to be scaled to some quantity */ + + if (forcetime > forcetimemin){ + forcetime = MAX2(forcetime / 2.0f,forcetimemin); + softbody_restore_prev_step(ob); + //printf("down,"); + } + else { + timedone += forcetime; + } + } + else { + float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */ + if (0){//(sb->scratch->flag & SBF_DOFUZZY){ + //if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */ + newtime = forcetime; + //} + } + else { + if (loss_of_accuracy > SoftHeunTol/2.0f) { /* stay with this stepsize unless err really small */ + newtime = forcetime; + } + } + + timedone += forcetime; + newtime=MIN2(forcetimemax,MAX2(newtime,forcetimemin)); + //if (newtime > forcetime) printf("up,"); + if (forcetime > 0.0) + forcetime = MIN2(dtime - timedone,newtime); + else + forcetime = MAX2(dtime - timedone,newtime); + } + loops++; + // give away solver context within loop + if (sb_nlc) + { + if (sb_nlc != nlGetCurrent())printf("Aye NL context mismatch! in softbody.c !\n"); + nlDeleteContext(sb_nlc); + sb_nlc = NULL; + } + + if(sb->solverflags & SBSO_MONITOR ){ + sct=PIL_check_seconds_timer(); + if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone); + } + + /* ask for user break */ + if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break; + } + + + if(sb->solverflags & SBSO_MONITOR ){ + if (loops > HEUNWARNLIMIT) /* monitor high loop counts */ + printf("\r needed %d steps/frame ",loops); + } + + + }/*SOLVER SELECT*/ + else if (sb->solver_ID == 3){ + /* do "stupid" semi "fake" implicit euler */ + NLContext *sb_nlc = NULL; + int nvar = 3*2*sb->totpoint; + int loops =0 ; + float forcetimemax = 1.0f; // this one needs 5 steps as a minimum + float timedone =0.0; /* how far did we get without violating error condition */ + /* loops = counter for emergency brake + * we don't want to lock up the system if physics fail + */ + if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops; + + + forcetime =forcetimemax; /* hope for integrating as fast as possible */ + + while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ){ + + sb_nlc = (NLContext*)nlNewContext(); + /* hum it smells like threading trouble */ + nlSolverParameteri(NL_NB_VARIABLES, nvar); + nlSolverParameteri(NL_LEAST_SQUARES, NL_FALSE); + + interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime))); + softbody_calc_forces(ob, forcetime,timedone/dtime,NLF_BUILD|NLF_SOLVE); + softbody_apply_fake_implicit_forces(ob, forcetime, NULL,NULL,NULL); + softbody_apply_goalsnap(ob); + timedone += forcetime; + loops++; + if (sb_nlc) + { + if (sb_nlc != nlGetCurrent())printf("Aye NL context mismatch! in softbody.c !\n"); + nlDeleteContext(sb_nlc); + sb_nlc = NULL; + } + /* ask for user break */ + if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break; + } + + + + }/*SOLVER SELECT*/ else{ - /* do brute force explicit euler */ - /* removed but left this branch for better integrators / solvers (BM) */ - /* yah! Nicholas Guttenberg (NichG) here is the place to plug in */ - } + printf("softbody no valid solver ID!"); + }/*SOLVER SELECT*/ + if(sb->solverflags & SBSO_MONITOR ){ sct=PIL_check_seconds_timer(); if (sct-sst > 0.5f) printf(" solver time %f %s \r",sct-sst,ob->id.name); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 96b0c372835..54d405132a9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6661,29 +6661,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main) World *wrld; if(main->versionfile != 244 || main->subversionfile < 2) { - Mesh *me; - for(sce= main->scene.first; sce; sce= sce->id.next) sce->r.mode |= R_SSS; - /* Copy over old per-level multires vertex data - into a single vertex array in struct Multires */ - - for(me = main->mesh.first; me; me=me->id.next) { - if(me->mr) { - MultiresLevel *lvl = me->mr->levels.last; - if(lvl) { - me->mr->verts = lvl->verts; - lvl->verts = NULL; - /* Don't need the other vert arrays */ - for(lvl = lvl->prev; lvl; lvl = lvl->prev) { - MEM_freeN(lvl->verts); - lvl->verts = NULL; - } - } - } - } - /* correct older action editors - incorrect scrolling */ for(sc= main->screen.first; sc; sc= sc->id.next) { ScrArea *sa; @@ -6737,6 +6717,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) Lamp *la; Material *ma; ParticleSettings *part; + Mesh *me; /* unless the file was created 2.44.3 but not 2.45, update the constraints */ if ( !(main->versionfile==244 && main->subversionfile==3) && @@ -6766,14 +6747,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) curcon->ownspace = CONSTRAINT_SPACE_LOCAL; } break; - case CONSTRAINT_TYPE_STRETCHTO: - { - bStretchToConstraint *data= (bStretchToConstraint *)curcon->data; - - /* force recalc of rest-length */ - data->orglength = 0; - } - break; } } } @@ -6805,14 +6778,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) curcon->tarspace = CONSTRAINT_SPACE_LOCAL; } break; - case CONSTRAINT_TYPE_STRETCHTO: - { - bStretchToConstraint *data= (bStretchToConstraint *)curcon->data; - - /* force recalc of rest-length */ - data->orglength = 0; - } - break; } } @@ -6876,6 +6841,23 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + + /* Copy over old per-level multires vertex data + into a single vertex array in struct Multires */ + for(me = main->mesh.first; me; me=me->id.next) { + if(me->mr && !me->mr->verts) { + MultiresLevel *lvl = me->mr->levels.last; + if(lvl) { + me->mr->verts = lvl->verts; + lvl->verts = NULL; + /* Don't need the other vert arrays */ + for(lvl = lvl->prev; lvl; lvl = lvl->prev) { + MEM_freeN(lvl->verts); + lvl->verts = NULL; + } + } + } + } if (main->versionfile != 245 || main->subversionfile < 1) { for(la=main->lamp.first; la; la= la->id.next) { diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index b32da691451..eb4adb4bbcf 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -112,6 +112,7 @@ void insertkey_action(void); void delete_action_keys(void); void delete_action_channels(void); void clean_action(void); +void sample_action_keys(void); /* Column/Channel Key select */ void column_select_action_keys(int mode); diff --git a/source/blender/include/BSE_node.h b/source/blender/include/BSE_node.h index 5862918953c..b1854e31d50 100644 --- a/source/blender/include/BSE_node.h +++ b/source/blender/include/BSE_node.h @@ -54,6 +54,8 @@ struct Material *editnode_get_active_material(struct Material *ma); struct bNode *editnode_get_active_idnode(struct bNodeTree *ntree, short id_code); struct bNode *editnode_get_active(struct bNodeTree *ntree); +void node_rename(struct SpaceNode *snode); + void snode_tag_dirty(struct SpaceNode *snode); void snode_set_context(struct SpaceNode *snode); @@ -72,7 +74,7 @@ void snode_make_group_editable(struct SpaceNode *snode, struct bNode *gnode); void node_hide(struct SpaceNode *snode); void node_read_renderlayers(struct SpaceNode *snode); void clear_scene_in_nodes(struct Scene *sce); -void node_toggle_link(struct SpaceNode *snode); +void node_make_link(struct SpaceNode *snode); void node_transform_ext(int mode, int unused); void node_shader_default(struct Material *ma); @@ -97,6 +99,8 @@ struct SpaceNode; struct bNodeLink; void node_draw_link(struct SpaceNode *snode, struct bNodeLink *link); +void node_rename_but(char *s); + void init_node_butfuncs(void); /* exported to CMP and SHD nodes */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 7ec81cfcf35..1f591894a90 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -90,7 +90,6 @@ typedef struct bPoseChannel { */ typedef struct bPose { ListBase chanbase; /* list of pose channels */ - struct bAction *poselib; /* poselib-action for this pose */ short flag, proxy_layer; /* proxy layer: copy from armature, gets synced */ @@ -104,6 +103,7 @@ typedef struct bPose { */ typedef struct bActionChannel { struct bActionChannel *next, *prev; + struct Ipo *ipo; /* IPO block this action channel references */ ListBase constraintChannels; /* Constraint Channels (when Action Channel represents an Object or Bone) */ diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index ceab9a1c9c1..d13ec7df8ca 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -107,6 +107,7 @@ typedef struct bNode { struct bNode *next, *prev, *new_node; char name[32]; + char username[32]; /* custom name defined by user */ short type, flag; short done, level; /* both for dependency and sorting */ short lasty, menunr; /* lasty: check preview render status, menunr: browse ID blocks */ @@ -196,11 +197,13 @@ typedef struct NodeImageAnim { } NodeImageAnim; typedef struct NodeBlurData { - short sizex, sizey, samples, maxspeed, minspeed, pad1; - float fac; + short sizex, sizey; + short samples, maxspeed, minspeed, relative; + float fac, percentx, percenty; short filtertype; char bokeh, gamma; - int pad2; + int pad; + int image_in_width, image_in_height; /* needed for absolute/relative conversions */ } NodeBlurData; typedef struct NodeDBlurData { diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 9a6a477bb47..b0408f2f4d9 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -129,10 +129,13 @@ typedef struct SoftBody { minloops, maxloops, choke, - pad3,pad4,pad5 + solver_ID, + pad4,pad5 ; struct SBScratch *scratch; /* scratch pad/cache on live time not saved in file */ + float shearstiff; + float inpush; } SoftBody; /* pd->forcefield: Effector Fields types */ diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c index 8ef4af4d219..3d6b3dd2955 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_blur.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_blur.c @@ -22,7 +22,8 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Campbell Barton, Alfredo de Greef, David Millan Escriva, + * Juho Vepsäläinen * * ***** END GPL LICENSE BLOCK ***** */ @@ -556,16 +557,20 @@ static void blur_with_reference(bNode *node, CompBuf *new, CompBuf *img, CompBuf static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { CompBuf *new, *img= in[0]->data; + NodeBlurData *nbd= node->storage; - if(img==NULL || out[0]->hasoutput==0) - return; + if(img==NULL) return; + + /* store image in size that is needed for absolute/relative conversions on ui level */ + nbd->image_in_width= img->x; + nbd->image_in_height= img->y; + + if(out[0]->hasoutput==0) return; if (((NodeBlurData *)node->storage)->filtertype == R_FILTER_FAST_GAUSS) { CompBuf *new, *img = in[0]->data; /*from eeshlo's original patch, removed to fit in with the existing blur node */ /*const float sx = in[1]->vec[0], sy = in[2]->vec[0];*/ - - NodeBlurData *nbd= node->storage; const float sx = ((float)nbd->sizex)/2.0f, sy = ((float)nbd->sizey)/2.0f; int c; diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_curves.c b/source/blender/nodes/intern/CMP_nodes/CMP_curves.c index 17d9821a5ef..01af0e1db1d 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_curves.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_curves.c @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Björn C. Schaefer * * ***** END GPL LICENSE BLOCK ***** */ @@ -123,6 +123,8 @@ bNodeType cmp_node_curve_vec= { static bNodeSocketType cmp_node_curve_rgb_in[]= { { SOCK_VALUE, 1, "Fac", 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, { SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, + { SOCK_RGBA, 1, "Black Level", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, + { SOCK_RGBA, 1, "White Level", 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f}, { -1, 0, "" } }; @@ -157,7 +159,7 @@ static void do_curves_fac(bNode *node, float *out, float *in, float *fac) static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { - /* stack order input: fac, image */ + /* stack order input: fac, image, black level, white level */ /* stack order output: image */ if(out[0]->hasoutput==0) @@ -172,6 +174,8 @@ static void node_composit_exec_curve_rgb(void *data, bNode *node, bNodeStack **i CompBuf *cbuf= in[1]->data; CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ + curvemapping_set_black_white(node->storage, in[2]->vec, in[3]->vec); + if(in[0]->vec[0] == 1.0) composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA); else diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index c0ebab1390a..56e7265b69e 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1496,7 +1496,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time; float *orco=0,*surfnor=0,*uvco=0, strandlen=0.0f, curlen=0.0f; float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); - float loc_tex[3], size_tex[3], adapt_angle=0.0, adapt_pix=0.0, random; + float adapt_angle=0.0, adapt_pix=0.0, random; float simplify[2]; int i, a, k, max_k=0, totpart, totuv=0, override_uv=-1, dosimplify = 0; int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; @@ -1608,8 +1608,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem totpart=psys->totpart; - mesh_get_texspace(ob->data, loc_tex, NULL, size_tex); - if(psys->pathcache){ path_possible=1; keys_possible=1; @@ -1789,12 +1787,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem } } - if(orco) { - orco[0] = (orco[0]-loc_tex[0])/size_tex[0]; - orco[1] = (orco[1]-loc_tex[1])/size_tex[1]; - orco[2] = (orco[2]-loc_tex[2])/size_tex[2]; - } - /* surface normal shading setup */ if(ma->mode_l & MA_STR_SURFDIFF) { Mat3MulVecfl(nmat, nor); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 3883db39c74..f1b75d075f3 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3181,7 +3181,7 @@ static void object_panel_deflection(Object *ob) PartDeflect *pd= ob->pd; but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision"); - uiButSetFunc(but, object_collision__enabletoggle, ob, NULL); + // uiButSetFunc(but, object_collision__enabletoggle, ob, NULL); if(pd->deflect) { uiDefBut(block, LABEL, 0, "Particles", 160,140,75,20, NULL, 0.0, 0, 0, 0, ""); @@ -3445,6 +3445,12 @@ static void object_softbodies__enable_psys(void *ob_v, void *psys_v) allqueue(REDRAWBUTSEDIT, 0); } + +#ifdef _work_on_sb_solver +static char sbsolvers[] = "Solver %t|RKP almost SOFT not usable but for some german teachers %x1|STU ip semi implicit euler%x3|SI1 (half step)adaptive semi implict euler %x2|SI2 (use dv)adaptive semi implict euler %x4|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; +#else +static char sbsolvers[] = "STU PID semi implicit euler%x3|SOFT step size controlled midpoint(1rst choice for real softbodies)%x0"; +#endif static void object_softbodies_II(Object *ob) { SoftBody *sb=ob->soft; @@ -3462,7 +3468,7 @@ static void object_softbodies_II(Object *ob) } block= uiNewBlock(&curarea->uiblocks, "object_softbodies_II", UI_EMBOSS, UI_HELV, curarea->win); uiNewPanelTabbed("Soft Body", "Physics"); - if(uiNewPanel(curarea, block, "Soft Body Collision", "Physics", 651, 0, 318, 204)==0) return; + if(uiNewPanel(curarea, block, "Soft Body Col&Solv", "Physics", 651, 0, 318, 204)==0) return; uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); @@ -3534,10 +3540,13 @@ static void object_softbodies_II(Object *ob) uiBlockEndAlign(block); /*SOLVER SETTINGS*/ - uiDefButF(block, NUM, B_DIFF, "Error Lim:", 10,100,130,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed"); - uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"O", 140,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Old Error Calculation"); - uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 160,100,130,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); - uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 290,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); + uiBlockBeginAlign(block); + uiDefButS(block, MENU, B_DIFF, sbsolvers,10,100,50,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver"); + uiDefButF(block, NUM, B_DIFF, "Error Lim:", 60,100,130,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed"); + uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"O", 190,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Old Error Calculation"); + uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 210,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); + uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 300,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); + uiBlockEndAlign(block); uiDefButS(block, NUM, B_DIFF, "MinS:", 10,80,100,20, &sb->minloops, 0.00, 30000.0, 10, 0, "Minimal # solver steps/frame "); uiDefButS(block, NUM, B_DIFF, "MaxS:", 110,80,100,20, &sb->maxloops, 0.00, 30000.0, 10, 0, "Maximal # solver steps/frame "); uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); @@ -3619,6 +3628,7 @@ static void object_softbodies(Object *ob) else but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Soft Body", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become soft body"); + uiButSetFunc(but, object_softbodies__enable, ob, NULL); } @@ -3721,11 +3731,15 @@ static void object_softbodies(Object *ob) uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads", 110,50,90,20, softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons"); uiDefButBitS(block, TOG, OB_SB_EDGECOLL, B_DIFF, "CEdge", 220,50,45,20, softflag, 0, 0, 0, 0, "Edge collide too"); uiDefButBitS(block, TOG, OB_SB_FACECOLL, B_DIFF, "CFace", 265,50,45,20, softflag, 0, 0, 0, 0, "Faces collide too SLOOOOOW warning "); - uiDefButF(block, NUM, B_DIFF, "E Stiff:", 10,30,150,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness"); - uiDefButF(block, NUM, B_DIFF, "E Damp:", 160,30,150,20, &sb->infrict, 0.0, 50.0, 10, 0, "Edge spring friction"); - uiDefButS(block, NUM, B_DIFF, "Aero:", 10,10,150,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'"); + uiDefButF(block, NUM, B_DIFF, "E Pull:", 10,30,100,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness"); + uiDefButF(block, NUM, B_DIFF, "E Push:", 110,30,100,20, &sb->inpush, 0.0, 0.999, 10, 0, "Edge spring stiffness"); + uiDefButF(block, NUM, B_DIFF, "E Damp:", 210,30,100,20, &sb->infrict, 0.0, 50.0, 10, 0, "Edge spring friction"); + uiDefButS(block, NUM, B_DIFF, "Aero:", 10,10,100,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'"); if(ob->type==OB_MESH) { - uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Rigidity:", 160,10,150,20, &sb->secondspring, 0.0, 10.0, 10, 0, "Strenght of Springs over 2 Edges"); + uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Bend:", 110,10,100,20, &sb->secondspring, 0.0, 10.0, 10, 0, "Strenght of Springs over 2 Edges"); + if (*softflag & OB_SB_QUADS){ + uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Shear:", 210,10,100,20, &sb->shearstiff, 0.0, 1.0, 10, 0, "Strenght of Springs over 2 Edges"); + } } else sb->secondspring = 0; uiDefBut(block, LABEL, 0, "",10,10,1,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c index 491ecb6e741..961cad5f840 100644 --- a/source/blender/src/drawnode.c +++ b/source/blender/src/drawnode.c @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): David Millan Escriva, Juho Vepsäläinen * * ***** END GPL LICENSE BLOCK ***** */ @@ -1047,12 +1047,41 @@ static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNo return 19; } +static void node_blur_relative_cb(void *node, void *poin2) +{ + bNode *nodev= node; + NodeBlurData *nbd= nodev->storage; + if(nbd->image_in_width != 0){ + if(nbd->relative){ /* convert absolute values to relative */ + nbd->percentx= (float)(nbd->sizex)/nbd->image_in_width; + nbd->percenty= (float)(nbd->sizey)/nbd->image_in_height; + }else{ /* convert relative values to absolute */ + nbd->sizex= (int)(nbd->percentx*nbd->image_in_width); + nbd->sizey= (int)(nbd->percenty*nbd->image_in_height); + } + } + allqueue(REDRAWNODE, 0); +} +static void node_blur_update_sizex_cb(void *node, void *poin2) +{ + bNode *nodev= node; + NodeBlurData *nbd= nodev->storage; + + nbd->sizex= (int)(nbd->percentx*nbd->image_in_width); +} +static void node_blur_update_sizey_cb(void *node, void *poin2) +{ + bNode *nodev= node; + NodeBlurData *nbd= nodev->storage; + + nbd->sizey= (int)(nbd->percenty*nbd->image_in_height); +} static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) { if(block) { NodeBlurData *nbd= node->storage; uiBut *bt; - short dy= butr->ymin+38; + short dy= butr->ymin+58; short dx= (butr->xmax-butr->xmin)/2; char str[256]; @@ -1074,15 +1103,33 @@ static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node uiBlockBeginAlign(block); } dy-=19; - bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:", - butr->xmin, dy, dx, 19, - &nbd->sizex, 0, 256, 0, 0, ""); - bt=uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:", - butr->xmin+dx, dy, dx, 19, - &nbd->sizey, 0, 256, 0, 0, ""); + bt= uiDefButS(block, TOG, B_NOP, "Relative", + butr->xmin, dy, dx*2, 19, + &nbd->relative, 0, 0, 0, 0, "Use relative (percent) values to define blur radius"); + uiButSetFunc(bt, node_blur_relative_cb, node, NULL); + + dy-=19; + if(nbd->relative) { + bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "X:", + butr->xmin, dy, dx, 19, + &nbd->percentx, 0.0f, 1.0f, 0, 0, ""); + uiButSetFunc(bt, node_blur_update_sizex_cb, node, NULL); + bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Y:", + butr->xmin+dx, dy, dx, 19, + &nbd->percenty, 0.0f, 1.0f, 0, 0, ""); + uiButSetFunc(bt, node_blur_update_sizey_cb, node, NULL); + } + else { + uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:", + butr->xmin, dy, dx, 19, + &nbd->sizex, 0, 256, 0, 0, ""); + uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:", + butr->xmin+dx, dy, dx, 19, + &nbd->sizey, 0, 256, 0, 0, ""); + } uiBlockEndAlign(block); } - return 57; + return 77; } static int node_composit_buts_dblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) @@ -1996,6 +2043,45 @@ void init_node_butfuncs(void) /* ************** Generic drawing ************** */ +void node_rename_but(char *s) +{ + uiBlock *block; + ListBase listb={0, 0}; + int dy, x1, y1, sizex=80, sizey=30; + short pivot[2], mval[2], ret=0; + + getmouseco_sc(mval); + + pivot[0]= CLAMPIS(mval[0], (sizex+10), G.curscreen->sizex-30); + pivot[1]= CLAMPIS(mval[1], (sizey/2)+10, G.curscreen->sizey-(sizey/2)-10); + + if (pivot[0]!=mval[0] || pivot[1]!=mval[1]) + warp_pointer(pivot[0], pivot[1]); + + mywinset(G.curscreen->mainwin); + + x1= pivot[0]-sizex+10; + y1= pivot[1]-sizey/2; + dy= sizey/2; + + block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin); + uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_ENTER_OK); + + /* buttons have 0 as return event, to prevent menu to close on hotkeys */ + uiBlockBeginAlign(block); + + uiDefBut(block, TEX, B_NOP, "Name: ", (short)(x1),(short)(y1+dy), 150, 19, s, 0.0, 19.0, 0, 0, "Node user name"); + + uiBlockEndAlign(block); + + uiDefBut(block, BUT, 32767, "OK", (short)(x1+150), (short)(y1+dy), 29, 19, NULL, 0, 0, 0, 0, ""); + + uiBoundsBlock(block, 2); + + ret= uiDoBlocks(&listb, 0, 0); +} + + static void draw_nodespace_grid(SpaceNode *snode) { float start, step= 25.0f; @@ -2439,6 +2525,7 @@ static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node) rctf *rct= &node->totr; float slen, iconofs; int ofs, color_id= node_get_colorid(node); + char showname[128]; uiSetRoundBox(15-4); ui_dropshadow(rct, BASIS_RAD, snode->aspect, node->flag & SELECT); @@ -2517,8 +2604,18 @@ static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node) BIF_ThemeColor(TH_TEXT); ui_rasterpos_safe(rct->xmin+19.0f, rct->ymax-NODE_DY+5.0f, snode->aspect); - snode_drawstring(snode, node->name, (int)(iconofs - rct->xmin-18.0f)); - + + if(node->username[0]) { + strcpy(showname,"("); + strcat(showname, node->username); + strcat(showname,") "); + strcat(showname, node->name); + } + else + strcpy(showname, node->name); + + snode_drawstring(snode, showname, (int)(iconofs - rct->xmin-18.0f)); + /* body */ BIF_ThemeColor4(TH_NODE); glEnable(GL_BLEND); @@ -2633,13 +2730,14 @@ static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node) } -void node_draw_hidden(SpaceNode *snode, bNode *node) +static void node_draw_hidden(SpaceNode *snode, bNode *node) { bNodeSocket *sock; rctf *rct= &node->totr; float dx, centy= 0.5f*(rct->ymax+rct->ymin); float hiddenrad= 0.5f*(rct->ymax-rct->ymin); int color_id= node_get_colorid(node); + char showname[128]; /* shadow */ uiSetRoundBox(15); @@ -2673,7 +2771,17 @@ void node_draw_hidden(SpaceNode *snode, bNode *node) if(node->miniwidth>0.0f) { ui_rasterpos_safe(rct->xmin+21.0f, centy-4.0f, snode->aspect); - snode_drawstring(snode, node->name, (int)(rct->xmax - rct->xmin-18.0f -12.0f)); + + if(node->username[0]) { + strcpy(showname,"("); + strcat(showname, node->username); + strcat(showname,") "); + strcat(showname, node->name); + } + else + strcpy(showname, node->name); + + snode_drawstring(snode, showname, (int)(rct->xmax - rct->xmin-18.0f -12.0f)); } /* scale widget thing */ @@ -2875,6 +2983,7 @@ static void node_draw_group(ScrArea *sa, SpaceNode *snode, bNode *gnode) bNodeTree *ngroup= (bNodeTree *)gnode->id; bNodeSocket *sock; rctf rect= gnode->totr; + char showname[128]; /* backdrop header */ glEnable(GL_BLEND); @@ -2898,7 +3007,17 @@ static void node_draw_group(ScrArea *sa, SpaceNode *snode, bNode *gnode) /* backdrop title */ BIF_ThemeColor(TH_TEXT_HI); ui_rasterpos_safe(rect.xmin+8.0f, rect.ymax+5.0f, snode->aspect); - BIF_DrawString(snode->curfont, ngroup->id.name+2, 0); + + if(gnode->username[0]) { + strcpy(showname,"("); + strcat(showname, gnode->username); + strcat(showname,") "); + strcat(showname, ngroup->id.name+2); + } + else + strcpy(showname, ngroup->id.name+2); + + BIF_DrawString(snode->curfont, showname, 0); /* links from groupsockets to the internal nodes */ node_draw_group_links(snode, gnode); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 61e4c6d5660..56eaeae29c9 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -3860,8 +3860,8 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys) if(psys->childcache==0) psys_cache_child_paths(ob, psys, CFRA, 0); } - else if(psys->childcache) - free_child_path_cache(psys); + else if(!(pset->flag & PE_SHOW_CHILD) && psys->childcache) + free_child_path_cache(psys); if((G.vd->flag & V3D_ZBUF_SELECT)==0) glDisable(GL_DEPTH_TEST); @@ -3905,13 +3905,14 @@ static void draw_particle_edit(Object *ob, ParticleSystem *psys) } glEnable(GL_LIGHTING); + if(psys->part->draw_as == PART_DRAW_PATH) { + for(i=0, path=psys->childcache; i<totchild; i++,path++){ + glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co); + glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel); + glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col); - for(i=0, path=psys->childcache; i<totchild; i++,path++){ - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->co); - glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), (*path)->vel); - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), (*path)->col); - - glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1); + glDrawArrays(GL_LINE_STRIP, 0, (int)(*path)->steps + 1); + } } glDisable(GL_COLOR_MATERIAL); diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 3d8f70824aa..62ee9563b3f 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -160,9 +160,9 @@ void remake_action_ipos (bAction *act) testhandles_ipocurve(icu); } } - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){ + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { if (conchan->ipo) { - for (icu = conchan->ipo->curve.first; icu; icu=icu->next){ + for (icu = conchan->ipo->curve.first; icu; icu=icu->next) { sort_time_ipocurve(icu); testhandles_ipocurve(icu); } @@ -962,7 +962,7 @@ void insertkey_action(void) ListBase act_data = {NULL, NULL}; bActListElem *ale; int filter; - + /* ask user what to keyframe */ mode = pupmenu("Insert Key%t|All Channels%x1|Only Selected Channels%x2"); if (mode <= 0) return; @@ -1047,7 +1047,7 @@ void delete_action_keys (void) allqueue(REDRAWNLA, 0); } -/* delete selected keyframes */ +/* delete selected action-channels (only achans and conchans are considered) */ void delete_action_channels (void) { ListBase act_data = {NULL, NULL}; @@ -1142,6 +1142,99 @@ void clean_action (void) allqueue(REDRAWNLA, 0); } + +/* little cache for values... */ +typedef struct tempFrameValCache { + float frame, val; +} tempFrameValCache; + +/* Evaluates the curves between each selected keyframe on each frame, and keys the value */ +void sample_action_keys (void) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + + /* sanity checks */ + data= get_action_context(&datatype); + if (data == NULL) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU); + actdata_filter(&act_data, filter, data, datatype); + + /* loop through filtered data and add keys between selected keyframes on every frame */ + for (ale= act_data.first; ale; ale= ale->next) { + IpoCurve *icu= (IpoCurve *)ale->key_data; + BezTriple *bezt, *start=NULL, *end=NULL; + tempFrameValCache *value_cache, *fp; + int sfra, range; + int i, n; + + /* find selected keyframes... once pair has been found, add keyframes */ + for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { + /* check if selected, and which end this is */ + if (BEZSELECTED(bezt)) { + if (start) { + /* set end */ + end= bezt; + + /* cache values then add keyframes using these values, as adding + * keyframes while sampling will affect the outcome... + */ + range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) ); + sfra= (int)( floor(start->vec[1][0]) ); + + if (range) { + value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache"); + + /* sample values */ + for (n=0, fp=value_cache; n<range && fp; n++, fp++) { + fp->frame= (float)(sfra + n); + fp->val= eval_icu(icu, fp->frame); + } + + /* add keyframes with these */ + for (n=0, fp=value_cache; n<range && fp; n++, fp++) { + insert_vert_icu(icu, fp->frame, fp->val, 1); + } + + /* free temp cache */ + MEM_freeN(value_cache); + } + + /* as we added keyframes, we need to compensate so that bezt is at the right place */ + bezt = icu->bezt + i + range - 1; + i += (range - 1); + + /* bezt was selected, so it now marks the start of a whole new chain to search */ + start= bezt; + end= NULL; + } + else { + /* just set start keyframe */ + start= bezt; + end= NULL; + } + } + } + + /* recalculate channel's handles? */ + calchandles_ipocurve(icu); + } + + /* admin and redraws */ + BLI_freelistN(&act_data); + + BIF_undo_push("Sample Action Keys"); + allqueue(REMAKEIPO, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); +} + /* **************************************************** */ /* COPY/PASTE FOR ACTIONS */ /* - The copy/paste buffer currently stores a set of Action Channels, with temporary @@ -3087,7 +3180,10 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case OKEY: - clean_action(); + if (G.qual & LR_ALTKEY) + sample_action_keys(); + else + clean_action(); break; case PKEY: diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index 8d75090d911..f66e3bfc22c 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -5653,22 +5653,24 @@ void delete_ipo_keys(Ipo *ipo) IpoCurve *icu, *next; int i; - if (!ipo) + if (ipo == NULL) return; - for (icu=ipo->curve.first; icu; icu=next){ + for (icu= ipo->curve.first; icu; icu= next) { next = icu->next; - for (i=0; i<icu->totvert; i++){ - if (icu->bezt[i].f2 & 1){ - // Delete the item - memcpy (&icu->bezt[i], &icu->bezt[i+1], sizeof (BezTriple)*(icu->totvert-i-1)); + + /* Delete selected BezTriples */ + for (i=0; i<icu->totvert; i++) { + if (icu->bezt[i].f2 & SELECT) { + memcpy(&icu->bezt[i], &icu->bezt[i+1], sizeof(BezTriple)*(icu->totvert-i-1)); icu->totvert--; i--; } } - if (!icu->totvert){ - /* Delete the curve */ - BLI_remlink( &(ipo->curve), icu); + + /* Only delete if there isn't an ipo-driver still hanging around on an empty curve */ + if (icu->totvert==0 && icu->driver==NULL) { + BLI_remlink(&ipo->curve, icu); free_ipo_curve(icu); } } diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index d035908994c..645dc77c337 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -22,7 +22,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): David Millan Escriva, Juho Vepsäläinen * * ***** END GPL LICENSE BLOCK ***** */ @@ -1083,7 +1083,29 @@ static void scale_node(SpaceNode *snode, bNode *node) allqueue(REDRAWNODE, 1); } +/* ******************** rename ******************* */ +void node_rename(SpaceNode *snode) +{ + bNode *node, *rename_node; + short found_node= 0; + + /* check if a node is selected */ + for(node= snode->edittree->nodes.first; node; node= node->next) { + if(node->flag & SELECT) { + found_node= 1; + break; + } + } + + if(found_node) { + rename_node= nodeGetActive(snode->edittree); + node_rename_but((char *)rename_node->username); + BIF_undo_push("Rename Node"); + + allqueue(REDRAWNODE, 1); + } +} /* ********************** select ******************** */ @@ -1855,34 +1877,31 @@ void node_select_linked(SpaceNode *snode, int out) allqueue(REDRAWNODE, 1); } -void node_toggle_link(SpaceNode *snode) +/* makes a link between selected output and input sockets */ +void node_make_link(SpaceNode *snode) { bNode *fromnode, *tonode; - bNodeLink *remlink, *link; + bNodeLink *link; bNodeSocket *outsock= snode->edittree->selout; bNodeSocket *insock= snode->edittree->selin; if(!insock || !outsock) return; + if(nodeFindLink(snode->edittree, outsock, insock)) return; - remlink= nodeFindLink(snode->edittree, outsock, insock); - - if(remlink) nodeRemLink(snode->edittree, remlink); - else { - if(nodeFindNode(snode->edittree, outsock, &fromnode, NULL) && - nodeFindNode(snode->edittree, insock, &tonode, NULL)) { - link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock); - NodeTagChanged(snode->edittree, tonode); - node_remove_extra_links(snode, insock, link); - } - else return; + if(nodeFindNode(snode->edittree, outsock, &fromnode, NULL) && + nodeFindNode(snode->edittree, insock, &tonode, NULL)) { + link= nodeAddLink(snode->edittree, fromnode, outsock, tonode, insock); + NodeTagChanged(snode->edittree, tonode); + node_remove_extra_links(snode, insock, link); } + else return; ntreeSolveOrder(snode->edittree); snode_verify_groups(snode); snode_handle_recalc(snode); allqueue(REDRAWNODE, 0); - BIF_undo_push("Toggle Link"); + BIF_undo_push("Make Link Between Sockets"); } static void node_border_link_delete(SpaceNode *snode) @@ -2278,7 +2297,7 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) snode_handle_recalc(snode); break; case FKEY: - node_toggle_link(snode); + node_make_link(snode); break; case GKEY: if(fromlib) fromlib= -1; @@ -2308,8 +2327,12 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt) node_select_linked(snode, G.qual==LR_SHIFTKEY); break; case RKEY: - if(okee("Read saved Render Layers")) - node_read_renderlayers(snode); + if(G.qual==LR_CTRLKEY) { + node_rename(snode); + } else{ + if(okee("Read saved Render Layers")) + node_read_renderlayers(snode); + } break; case DELKEY: case XKEY: diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index 2274cc63980..eb98f3243f7 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -2392,6 +2392,7 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe ekey->time = &hkey->time; } + pa->size= 1.0f; initialize_particle(pa,i,ob,psys,psmd); reset_particle(pa,psys,psmd,ob,0.0,1.0,0,0,0); pa->flag |= PARS_EDIT_RECALC; diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index 1707dc82870..ab30c4cad52 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -117,7 +117,8 @@ enum { enum { ACTMENU_KEY_DUPLICATE = 0, ACTMENU_KEY_DELETE, - ACTMENU_KEY_CLEAN + ACTMENU_KEY_CLEAN, + ACTMENU_KEY_SAMPLEKEYS }; enum { @@ -1006,11 +1007,14 @@ static void do_action_keymenu(void *arg, int event) duplicate_action_keys(); break; case ACTMENU_KEY_DELETE: - delete_action_keys (); + delete_action_keys(); break; case ACTMENU_KEY_CLEAN: clean_action(); break; + case ACTMENU_KEY_SAMPLEKEYS: + sample_action_keys(); + break; } } @@ -1052,6 +1056,11 @@ static uiBlock *action_keymenu(void *arg_unused) "Clean Action|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_CLEAN, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, + "Sample Keys|Alt O", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 0, + ACTMENU_KEY_SAMPLEKEYS, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/header_node.c b/source/blender/src/header_node.c index 7255dcd3286..a00cbd1290b 100644 --- a/source/blender/src/header_node.c +++ b/source/blender/src/header_node.c @@ -23,7 +23,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): David Millan Escriva, Juho Vepsäläinen * * ***** END GPL LICENSE BLOCK ***** */ @@ -513,8 +513,11 @@ static void do_node_nodemenu(void *arg, int event) case 10: /* execute */ addqueue(curarea->win, UI_BUT_EVENT, B_NODE_TREE_EXEC); break; - case 11: /* toggle link */ - node_toggle_link(snode); + case 11: /* make link */ + node_make_link(snode); + break; + case 12: /* rename */ + node_rename(snode); break; } @@ -541,7 +544,7 @@ static uiBlock *node_nodemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Toggle Link|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Link|F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -552,6 +555,7 @@ static uiBlock *node_nodemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Hide/Unhide|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename|Ctrl R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index f56434c8c4e..615cb1900bc 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -1674,13 +1674,14 @@ static TBitem tb_node_node[]= { { 0, "Duplicate|Shift D", TB_SHIFT|'d', NULL}, { 0, "Delete|X", 'x', NULL}, { 0, "SEPR", 0, NULL}, - { 0, "Toggle Link|F", 'f', NULL}, + { 0, "Make Link|F", 'f', NULL}, { 0, "SEPR", 0, NULL}, { 0, "Make Group|Ctrl G", TB_CTRL|'g', NULL}, { 0, "Ungroup|Alt G", TB_ALT|'g', NULL}, { 0, "Edit Group|Tab", TB_TAB, NULL}, { 0, "SEPR", 0, NULL}, { 0, "Hide/Unhide|H", 'h', NULL}, + { 0, "Rename|Ctrl R", TB_CTRL|'r', NULL}, { 0, "SEPR", 0, NULL}, { 0, "Read Saved Render Results|R", 'r', NULL}, { 0, "Show Cyclic Dependencies|C", 'c', NULL}, |