svn merge -r 13148:13177 https://svn.blender.org/svnroot/bf-blender/trunk/blender + fixed one crash on enabling deflection
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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;
|
||||
|
||||
QuatToMat4(state.rot, pamat);
|
||||
VECCOPY(pamat[3], state.co);
|
||||
pamat[3][3]= 1.0f;
|
||||
}
|
||||
|
||||
QuatToMat3(state.rot, parotmat);
|
||||
|
||||
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) {
|
||||
for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) {
|
||||
|
||||
Mat4CpyMat4(tmat, go->ob->obmat);
|
||||
Mat4MulMat43(tmat, go->ob->obmat, parotmat);
|
||||
Mat4MulFloat3((float *)tmat, size);
|
||||
Mat4MulMat4(tmat, obmatlist[b], pamat);
|
||||
Mat4MulFloat3((float *)tmat, size*scale);
|
||||
if(par_space_mat)
|
||||
Mat4MulMat4(mat, tmat, par_space_mat);
|
||||
else
|
||||
Mat4CpyMat4(mat, tmat);
|
||||
|
||||
VECADD(tmat[3], go->ob->obmat[3], state.co);
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err)
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) */
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, "");
|
||||
|
||||
@@ -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, "");
|
||||
|
||||
|
||||
@@ -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},
|
||||
|
||||
Reference in New Issue
Block a user