big softbody commit
some vertex group , weight painting stuff too /me crosses fingers it does not break anything
This commit is contained in:
@@ -35,8 +35,10 @@
|
||||
#define BKE_SOFTBODY_H
|
||||
|
||||
typedef struct BodyPoint {
|
||||
float orig[3], pos[3], vec[3], force[3];
|
||||
float origS[3], origE[3], origT[3], pos[3], vec[3], force[3];
|
||||
float weight, goal;
|
||||
float prevpos[3], prevvec[3], prevdx[3], prevdv[3]; /* used for Heun integration */
|
||||
int nofsprings; int *springs;
|
||||
} BodyPoint;
|
||||
|
||||
typedef struct BodySpring {
|
||||
@@ -57,7 +59,7 @@ typedef struct SoftBody {
|
||||
extern void free_softbody(SoftBody *sb);
|
||||
|
||||
/* makes totally fresh start situation */
|
||||
extern void object_to_softbody(Object *ob);
|
||||
extern void object_to_softbody(Object *ob,float ctime);
|
||||
|
||||
/* copy original (but new) situation in softbody, as result of matrices or deform */
|
||||
void object_update_softbody(Object *ob);
|
||||
|
||||
@@ -227,7 +227,7 @@ int mesh_modifier(Object *ob, char mode)
|
||||
else if(ob->effect.first); // weak... particles too
|
||||
else if(ob->parent && ob->parent->type==OB_LATTICE);
|
||||
else if(ob->parent && ob->partype==PARSKEL);
|
||||
else if(ob->softflag);
|
||||
else if(ob->softflag & 0x01);
|
||||
else return 0;
|
||||
|
||||
if(me->totvert==0) return 0;
|
||||
@@ -249,15 +249,21 @@ int mesh_modifier(Object *ob, char mode)
|
||||
}
|
||||
|
||||
if(ob->effect.first) done |= object_wave(ob);
|
||||
|
||||
if(ob->softflag) {
|
||||
|
||||
if((ob->softflag & 0x01) && !(ob->softflag & 0x08)) {
|
||||
float ctime= bsystem_time(ob, NULL, (float)G.scene->r.cfra, 0.0);
|
||||
done= 1;
|
||||
object_softbody_step(ob, ctime);
|
||||
}
|
||||
|
||||
|
||||
/* deform: input mesh, output ob dl_verts. is used by subsurf (output should be in mesh ton!) */
|
||||
done |= object_deform(ob);
|
||||
|
||||
if((ob->softflag & 0x01) && (ob->softflag & 0x08)) {
|
||||
float ctime= bsystem_time(ob, NULL, (float)G.scene->r.cfra, 0.0);
|
||||
done= 1;
|
||||
object_softbody_step(ob, ctime);
|
||||
}
|
||||
|
||||
/* put deformed vertices in dl->verts, optional subsurf will replace that */
|
||||
if(done) {
|
||||
|
||||
@@ -2405,7 +2405,7 @@ void test_all_displists(void)
|
||||
}
|
||||
}
|
||||
|
||||
if(ob->softflag) freedisplist_object(ob);
|
||||
if(ob->softflag & 0x01) freedisplist_object(ob);
|
||||
/* warn, ob pointer changed in case of OB_MALL */
|
||||
|
||||
if ELEM(ob->type, OB_CURVE, OB_SURF) {
|
||||
|
||||
@@ -31,6 +31,30 @@
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/*
|
||||
******
|
||||
variables on the UI for now
|
||||
typedef struct Object {
|
||||
.....
|
||||
float formfactor, softtime; softtime = #euler integrations steps per frame
|
||||
.....
|
||||
float sb_goalspring; softbody goal springs
|
||||
float sb_goalfrict; softbody goal springs friction
|
||||
float sb_inspring; softbody inner springs
|
||||
float sb_infrict; softbody inner springs friction
|
||||
float sb_nodemass; softbody mass of *vertex*
|
||||
float sb_grav; softbody amount of gravitaion to apply
|
||||
float sb_mingoal; quick limits for goal
|
||||
float sb_maxgoal;
|
||||
float sb_mediafrict; friction to env
|
||||
float sb_pad1; free
|
||||
|
||||
|
||||
|
||||
*****
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -51,7 +75,129 @@
|
||||
#include "BKE_softbody.h"
|
||||
#include "BKE_displist.h"
|
||||
|
||||
#include "BIF_editdeform.h"
|
||||
/* ********** soft body engine ******* */
|
||||
#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
|
||||
#define HEUNWARNLIMIT 1 // 50 would be fine i think for detecting severe *stiff* stuff
|
||||
|
||||
float SoftHeunTol = 1.0f; // humm .. this should be calculated from sb parameters and sizes
|
||||
float steptime = 1.0f/25.0f; // translate framerate to *real* time
|
||||
float rescale_grav_to_framerate = 1.0f; // since unit of g is [m/sec^2] we need translation from frames to physics time
|
||||
float rescale_friction_to_framerate = 1.0f; // since unit of drag is [kg/sec] we need translation from frames to physics time
|
||||
|
||||
short SB_ENABLE = 0; // quick hack to switch sb integration in 3d header
|
||||
|
||||
|
||||
void softbody_scale_time(float steptime)
|
||||
{
|
||||
rescale_grav_to_framerate = steptime*steptime;
|
||||
rescale_friction_to_framerate = steptime;
|
||||
}
|
||||
|
||||
|
||||
static int count_quads( Mesh *me)
|
||||
{
|
||||
int a,result = 0;
|
||||
MFace *mface= me->mface;
|
||||
if(mface ) {
|
||||
for(a=me->totface; a>0; a--, mface++) {if(mface->v4) result++;}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void add_quad_diag_springs(Object *ob)
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
MFace *mface= me->mface;
|
||||
BodyPoint *bp;
|
||||
BodySpring *bs, *bs_new;
|
||||
int a ;
|
||||
|
||||
if (ob->soft){
|
||||
int nofquads;
|
||||
nofquads = count_quads(me);
|
||||
if (nofquads) {
|
||||
/* resize spring-array to hold additional quad springs */
|
||||
bs_new= MEM_callocN( (ob->soft->totspring + nofquads *2 )*sizeof(BodySpring), "bodyspring");
|
||||
memcpy(bs_new,ob->soft->bspring,(ob->soft->totspring )*sizeof(BodySpring));
|
||||
MEM_freeN(ob->soft->bspring); /* do this before reassigning the pointer or have a 1st class memory leak */
|
||||
ob->soft->bspring = bs_new;
|
||||
/* fill the tail */
|
||||
a = 0;
|
||||
bs = bs_new+ob->soft->totspring;
|
||||
bp= ob->soft->bpoint;
|
||||
if(mface ) {
|
||||
for(a=me->totface; a>0; a--, mface++) {
|
||||
if(mface->v4)
|
||||
{
|
||||
bs->v1= mface->v1;
|
||||
bs->v2= mface->v3;
|
||||
bs->strength= 1.0;
|
||||
bs->len= VecLenf( (bp+bs->v1)->origS, (bp+bs->v2)->origS);
|
||||
bs++;
|
||||
bs->v1= mface->v2;
|
||||
bs->v2= mface->v4;
|
||||
bs->strength= 1.0;
|
||||
bs->len= VecLenf( (bp+bs->v1)->origS, (bp+bs->v2)->origS);
|
||||
bs++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now we can announce new springs */
|
||||
ob->soft->totspring += nofquads *2;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_bp_springlist(BodyPoint *bp,int springID)
|
||||
{
|
||||
int *newlist;
|
||||
if (bp->springs == NULL) {
|
||||
bp->springs = MEM_callocN( sizeof(int), "bpsprings");
|
||||
bp->springs[0] = springID;
|
||||
bp->nofsprings = 1;
|
||||
}
|
||||
else {
|
||||
bp->nofsprings++;
|
||||
newlist = MEM_callocN(bp->nofsprings * sizeof(int), "bpsprings");
|
||||
memcpy(newlist,bp->springs,(bp->nofsprings-1)* sizeof(int));
|
||||
MEM_freeN(bp->springs);
|
||||
bp->springs = newlist;
|
||||
bp->springs[bp->nofsprings-1] = springID;
|
||||
}
|
||||
}
|
||||
|
||||
/* do this once when sb is build
|
||||
it is O(N^2) so scanning for springs every iteration is too expensive
|
||||
*/
|
||||
static void build_bps_springlist(Object *ob)
|
||||
{
|
||||
SoftBody *sb= ob->soft; // is supposed to be there
|
||||
BodyPoint *bp;
|
||||
BodySpring *bs;
|
||||
|
||||
int a,b;
|
||||
if (!sb) return; // paranoya check
|
||||
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
|
||||
/* scan for attached inner springs */
|
||||
for(b=sb->totspring, bs= sb->bspring; b>0; b--, bs++) {
|
||||
if (( (sb->totpoint-a) == bs->v1) ){
|
||||
add_bp_springlist(bp,sb->totspring -b);
|
||||
}
|
||||
if (( (sb->totpoint-a) == bs->v2) ){
|
||||
add_bp_springlist(bp,sb->totspring -b);
|
||||
}
|
||||
}//for springs
|
||||
if (bp->nofsprings) printf(" node %d has %d spring links\n",a,bp->nofsprings);
|
||||
}//for bp
|
||||
}
|
||||
|
||||
|
||||
|
||||
static SoftBody *new_softbody(int totpoint, int totspring)
|
||||
@@ -73,80 +219,361 @@ static SoftBody *new_softbody(int totpoint, int totspring)
|
||||
void free_softbody(SoftBody *sb)
|
||||
{
|
||||
if(sb) {
|
||||
if(sb->bpoint) MEM_freeN(sb->bpoint);
|
||||
int a;
|
||||
BodyPoint *bp;
|
||||
if(sb->bpoint){
|
||||
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
|
||||
/* free spring list */
|
||||
if (bp->springs != NULL) {
|
||||
MEM_freeN(bp->springs);
|
||||
}
|
||||
}
|
||||
MEM_freeN(sb->bpoint);
|
||||
}
|
||||
if(sb->bspring) MEM_freeN(sb->bspring);
|
||||
|
||||
MEM_freeN(sb);
|
||||
}
|
||||
}
|
||||
/* ************ dynamics ********** */
|
||||
|
||||
static void softbody_calc_forces(Object *ob)
|
||||
/* aye this belongs to arith.c */
|
||||
void Vec3PlusStVec(float *v, float s, float *v1)
|
||||
{
|
||||
v[0] += s*v1[0];
|
||||
v[1] += s*v1[1];
|
||||
v[2] += s*v1[2];
|
||||
}
|
||||
|
||||
|
||||
static void softbody_calc_forces(Object *ob, float dtime)
|
||||
{
|
||||
SoftBody *sb= ob->soft; // is supposed to be there
|
||||
BodyPoint *bp;
|
||||
float ks;
|
||||
int a;
|
||||
|
||||
BodyPoint *bp;
|
||||
float iks,ks,kd,gravity,actspringlen,forcefactor,sd[3];
|
||||
int a,b;
|
||||
BodyPoint *bproot;
|
||||
BodySpring *bs;
|
||||
/* clear forces */
|
||||
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
|
||||
bp->force[0]= bp->force[1]= bp->force[2]= 0.0;
|
||||
}
|
||||
|
||||
/* spring constant */
|
||||
ks= ob->springf;
|
||||
|
||||
/* accumulate forces, vertex stiffness */
|
||||
|
||||
gravity = ob->sb_nodemass * ob->sb_grav * rescale_grav_to_framerate;
|
||||
iks = 1.0f/(1.0f-ob->sb_inspring)-1.0f ;/* inner spring constants function */
|
||||
bproot= sb->bpoint; /* need this for proper spring addressing */
|
||||
|
||||
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
|
||||
if(bp->goal < SOFTGOALSNAP){ // ommit this bp when i snaps
|
||||
float auxvect[3]; // aux unit vector
|
||||
float velgoal[3];
|
||||
float absvel =0, projvel= 0;
|
||||
|
||||
/* do goal stuff */
|
||||
/* true elastic goal */
|
||||
VecSubf(auxvect,bp->origT,bp->pos);
|
||||
ks = 1.0f/(1.0f- bp->goal*ob->sb_goalspring)-1.0f ;
|
||||
bp->force[0]= ks*(auxvect[0]);
|
||||
bp->force[1]= ks*(auxvect[1]);
|
||||
bp->force[2]= ks*(auxvect[2]);
|
||||
/* calulate damping forces generated by goals*/
|
||||
VecSubf(velgoal,bp->origS, bp->origE);
|
||||
kd = ob->sb_goalfrict * rescale_friction_to_framerate ;
|
||||
|
||||
bp->force[0]= ks*(bp->orig[0]-bp->pos[0]);
|
||||
bp->force[1]= ks*(bp->orig[1]-bp->pos[1]);
|
||||
bp->force[2]= ks*(bp->orig[2]-bp->pos[2]);
|
||||
if (dtime > 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]);
|
||||
}
|
||||
else {
|
||||
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]);
|
||||
}
|
||||
/* done goal stuff */
|
||||
|
||||
|
||||
/* gravitation */
|
||||
bp->force[2]-= gravity*ob->sb_nodemass; /* individual mass of node here */
|
||||
|
||||
/* friction in media */
|
||||
kd= ob->sb_mediafrict* rescale_friction_to_framerate;
|
||||
/* assume it to be proportional to actual velocity */
|
||||
bp->force[0]-= bp->vec[0]*kd;
|
||||
bp->force[1]-= bp->vec[1]*kd;
|
||||
bp->force[2]-= bp->vec[2]*kd;
|
||||
/* friction in media done */
|
||||
|
||||
/*other forces*/
|
||||
/* this is the place where other forces can be added
|
||||
yes, constraints and collision stuff should go here too (read baraff papers on that!)
|
||||
*/
|
||||
/*other forces done*/
|
||||
|
||||
/* nice things could be done with anisotropic friction
|
||||
like wind/air resistance in normal direction
|
||||
--> having a piece of cloth sailing down
|
||||
but this needs to have a *valid* vertex normal
|
||||
*valid* means to be calulated on time axis
|
||||
hrms .. may be a rough one could be used as well .. let's see
|
||||
*/
|
||||
|
||||
if (1){ /* big mesh optimization */
|
||||
/* run over attached inner spring list */
|
||||
if (sb->bspring){ // spring list exists at all ?
|
||||
for(b=bp->nofsprings;b>0;b--){
|
||||
bs = sb->bspring + bp->springs[b-1];
|
||||
if (( (sb->totpoint-a) == bs->v1) ){
|
||||
actspringlen= VecLenf( (bproot+bs->v2)->pos, bp->pos);
|
||||
VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
|
||||
Normalise(sd);
|
||||
|
||||
// friction stuff V1
|
||||
VecSubf(velgoal,bp->vec,(bproot+bs->v2)->vec);
|
||||
kd = ob->sb_infrict * rescale_friction_to_framerate ;
|
||||
absvel = Normalise(velgoal);
|
||||
projvel = ABS(Inpf(sd,velgoal));
|
||||
kd *= absvel * projvel;
|
||||
Vec3PlusStVec(bp->force,-kd,velgoal);
|
||||
|
||||
if(bs->len > 0.0) /* check for degenerated springs */
|
||||
forcefactor = (bs->len - actspringlen)/bs->len * iks;
|
||||
else
|
||||
forcefactor = actspringlen * iks;
|
||||
|
||||
Vec3PlusStVec(bp->force,-forcefactor,sd);
|
||||
|
||||
}
|
||||
|
||||
if (( (sb->totpoint-a) == bs->v2) ){
|
||||
actspringlen= VecLenf( (bproot+bs->v1)->pos, bp->pos);
|
||||
VecSubf(sd,bp->pos,(bproot+bs->v1)->pos);
|
||||
Normalise(sd);
|
||||
|
||||
// friction stuff V2
|
||||
VecSubf(velgoal,bp->vec,(bproot+bs->v1)->vec);
|
||||
kd = ob->sb_infrict * rescale_friction_to_framerate ;
|
||||
absvel = Normalise(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;
|
||||
Vec3PlusStVec(bp->force,+forcefactor,sd);
|
||||
}
|
||||
}
|
||||
} //if spring list exists at all ?
|
||||
}
|
||||
else{ // this branch is not completly uptaded for friction stuff
|
||||
/* scan for attached inner springs makes it a O(N^2) thing = bad !*/
|
||||
/* obsolete .. but if someone wants to try the effect :) */
|
||||
for(b=sb->totspring, bs= sb->bspring; b>0; b--, bs++) {
|
||||
if (( (sb->totpoint-a) == bs->v1) ){
|
||||
actspringlen= VecLenf( (bproot+bs->v2)->pos, bp->pos);
|
||||
VecSubf(sd,(bproot+bs->v2)->pos, bp->pos);
|
||||
Normalise(sd);
|
||||
|
||||
|
||||
if(bs->len > 0.0) /* check for degenerated springs */
|
||||
forcefactor = (bs->len - actspringlen)/bs->len * iks;
|
||||
else
|
||||
forcefactor = actspringlen * iks;
|
||||
Vec3PlusStVec(bp->force,-forcefactor,sd);
|
||||
}
|
||||
|
||||
if (( (sb->totpoint-a) == bs->v2) ){
|
||||
actspringlen= VecLenf( (bproot+bs->v1)->pos, bp->pos);
|
||||
VecSubf(sd,bp->pos,(bproot+bs->v1)->pos);
|
||||
Normalise(sd);
|
||||
|
||||
if(bs->len > 0.0)
|
||||
forcefactor = (bs->len - actspringlen)/bs->len * iks;
|
||||
else
|
||||
forcefactor = actspringlen * iks;
|
||||
Vec3PlusStVec(bp->force,+forcefactor,sd);
|
||||
}
|
||||
}// no snap
|
||||
}//for
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void softbody_apply_forces(Object *ob, float dtime)
|
||||
static void softbody_apply_forces(Object *ob, float dtime, int mode, float *err)
|
||||
{
|
||||
/* time evolution */
|
||||
/* actually does an explicit euler step mode == 0 */
|
||||
/* or heun ~ 2nd order runge-kutta steps, mode 1,2 */
|
||||
SoftBody *sb= ob->soft; // is supposed to be there
|
||||
BodyPoint *bp;
|
||||
float dx[3],dv[3];
|
||||
int a;
|
||||
float timeovermass;
|
||||
float maxerr = 0.0;
|
||||
|
||||
if (ob->sb_nodemass > 0.09999f) timeovermass = dtime/ob->sb_nodemass;
|
||||
else timeovermass = dtime/0.09999f;
|
||||
|
||||
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
|
||||
if(bp->goal < SOFTGOALSNAP){
|
||||
|
||||
/* so here is dv/dt = a = sum(F_springs)/m + gravitation + some friction forces */
|
||||
/* the euler step for velocity then becomes */
|
||||
/* v(t + dt) = v(t) + a(t) * dt */
|
||||
bp->force[0]*= timeovermass; /* individual mass of node here */
|
||||
bp->force[1]*= timeovermass;
|
||||
bp->force[2]*= timeovermass;
|
||||
/* some nasty if's to have heun in here too */
|
||||
VECCOPY(dv,bp->force);
|
||||
if (mode == 1){
|
||||
VECCOPY(bp->prevvec,bp->vec);
|
||||
VECCOPY(bp->prevdv ,dv);
|
||||
}
|
||||
if (mode ==2){
|
||||
/* be optimistic and execute step */
|
||||
bp->vec[0] = bp->prevvec[0] + 0.5f * (dv[0] + bp->prevdv[0]);
|
||||
bp->vec[1] = bp->prevvec[1] + 0.5f * (dv[1] + bp->prevdv[1]);
|
||||
bp->vec[2] = bp->prevvec[2] + 0.5f * (dv[2] + bp->prevdv[2]);
|
||||
/* compare euler to heun to estimate error for step sizing */
|
||||
maxerr = MAX2(maxerr,ABS(dv[0] - bp->prevdv[0]));
|
||||
maxerr = MAX2(maxerr,ABS(dv[1] - bp->prevdv[1]));
|
||||
maxerr = MAX2(maxerr,ABS(dv[2] - bp->prevdv[2]));
|
||||
}
|
||||
else {VECADD(bp->vec, bp->vec, bp->force);}
|
||||
|
||||
/* so here is dx/dt = v */
|
||||
/* the euler step for location then becomes */
|
||||
/* x(t + dt) = x(t) + v(t) * dt */
|
||||
|
||||
VECCOPY(dx,bp->vec);
|
||||
dx[0]*=dtime ;
|
||||
dx[1]*=dtime ;
|
||||
dx[2]*=dtime ;
|
||||
|
||||
/* again some nasty if's to have heun in here too */
|
||||
if (mode ==1){
|
||||
VECCOPY(bp->prevpos,bp->pos);
|
||||
VECCOPY(bp->prevdx ,dx);
|
||||
}
|
||||
|
||||
if (mode ==2){
|
||||
bp->pos[0] = bp->prevpos[0] + 0.5f * ( dx[0] + bp->prevdx[0]);
|
||||
bp->pos[1] = bp->prevpos[1] + 0.5f * ( dx[1] + bp->prevdx[1]);
|
||||
bp->pos[2] = bp->prevpos[2] + 0.5f* ( dx[2] + bp->prevdx[2]);
|
||||
maxerr = MAX2(maxerr,ABS(dx[0] - bp->prevdx[0]));
|
||||
maxerr = MAX2(maxerr,ABS(dx[1] - bp->prevdx[1]));
|
||||
maxerr = MAX2(maxerr,ABS(dx[2] - bp->prevdx[2]));
|
||||
}
|
||||
else { VECADD(bp->pos, bp->pos, dx);}
|
||||
|
||||
}//snap
|
||||
} //for
|
||||
if (err){ /* so step size will be controlled by biggest difference in slope */
|
||||
*err = maxerr;
|
||||
}
|
||||
}
|
||||
|
||||
/* used by heun when it overshoots */
|
||||
static void softbody_restore_prev_step(Object *ob)
|
||||
{
|
||||
SoftBody *sb= ob->soft; // is supposed to be there
|
||||
BodyPoint *bp;
|
||||
float kd;
|
||||
int a;
|
||||
|
||||
kd= 1.0-ob->damping;
|
||||
|
||||
int a;
|
||||
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
|
||||
// friction
|
||||
bp->vec[0]*= kd;
|
||||
bp->vec[1]*= kd;
|
||||
bp->vec[2]*= kd;
|
||||
|
||||
VECADD(bp->vec, bp->vec, bp->force); // mass here!?
|
||||
VECADD(bp->pos, bp->pos, bp->vec);
|
||||
VECCOPY(bp->vec,bp->prevvec);
|
||||
VECCOPY(bp->pos,bp->prevpos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* unused */
|
||||
static void softbody_apply_goal(Object *ob, float dtime)
|
||||
{
|
||||
|
||||
SoftBody *sb= ob->soft; // is supposed to be there
|
||||
BodyPoint *bp;
|
||||
float vec[3], ks;
|
||||
int a;
|
||||
|
||||
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
|
||||
ks= bp->goal;
|
||||
ks= bp->goal*dtime;
|
||||
// this is hackish, screws up physics but stabilizes
|
||||
vec[0]= ks*(bp->orig[0]-bp->pos[0]);
|
||||
vec[1]= ks*(bp->orig[1]-bp->pos[1]);
|
||||
vec[2]= ks*(bp->orig[2]-bp->pos[2]);
|
||||
vec[0]= ks*(bp->origT[0]-bp->pos[0]);
|
||||
vec[1]= ks*(bp->origT[1]-bp->pos[1]);
|
||||
vec[2]= ks*(bp->origT[2]-bp->pos[2]);
|
||||
|
||||
VECADD(bp->pos, bp->pos, vec);
|
||||
|
||||
ks= 1.0-ks;
|
||||
ks= 1.0f-ks;
|
||||
bp->vec[0]*= ks;
|
||||
bp->vec[1]*= ks;
|
||||
bp->vec[2]*= ks;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void softbody_apply_goalsnap(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++) {
|
||||
if (bp->goal >= SOFTGOALSNAP){
|
||||
VECCOPY(bp->prevpos,bp->pos);
|
||||
VECCOPY(bp->pos,bp->origT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void softbody_force_goal(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->pos,bp->origT);
|
||||
bp->vec[0] = bp->origE[0] - bp->origS[0];
|
||||
bp->vec[1] = bp->origE[1] - bp->origS[1];
|
||||
bp->vec[2] = bp->origE[2] - bp->origS[2];
|
||||
}
|
||||
}
|
||||
|
||||
static void interpolate_exciter(Object *ob, int timescale, int time)
|
||||
{
|
||||
Mesh *me= ob->data;
|
||||
//MEdge *medge= me->medge;
|
||||
int a;
|
||||
BodyPoint *bp;
|
||||
float f;
|
||||
|
||||
if(ob->soft) {
|
||||
f = (float)time/(float)timescale;
|
||||
bp= ob->soft->bpoint;
|
||||
for(a=0; a<me->totvert; a++, bp++) {
|
||||
bp->origT[0] = bp->origS[0] + f*(bp->origE[0] - bp->origS[0]);
|
||||
bp->origT[1] = bp->origS[1] + f*(bp->origE[1] - bp->origS[1]);
|
||||
bp->origT[2] = bp->origS[2] + f*(bp->origE[2] - bp->origS[2]);
|
||||
if (bp->goal >= SOFTGOALSNAP){
|
||||
bp->vec[0] = bp->origE[0] - bp->origS[0];
|
||||
bp->vec[1] = bp->origE[1] - bp->origS[1];
|
||||
bp->vec[2] = bp->origE[2] - bp->origS[2];
|
||||
}
|
||||
}
|
||||
/* hrms .. do springs alter their lenght ?
|
||||
if(medge) {
|
||||
bs= ob->soft->bspring;
|
||||
bp= ob->soft->bpoint;
|
||||
for(a=0; (a<me->totedge && a < ob->soft->totspring ); a++, medge++, bs++) {
|
||||
bs->len= VecLenf( (bp+bs->v1)->origT, (bp+bs->v2)->origT);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ************ convertors ********** */
|
||||
|
||||
@@ -157,27 +584,60 @@ static void mesh_update_softbody(Object *ob)
|
||||
MVert *mvert= me->mvert;
|
||||
MEdge *medge= me->medge;
|
||||
BodyPoint *bp;
|
||||
BodySpring *bs;
|
||||
int a;
|
||||
|
||||
if(ob->soft) {
|
||||
|
||||
bp= ob->soft->bpoint;
|
||||
for(a=0; a<me->totvert; a++, mvert++, bp++) {
|
||||
VECCOPY(bp->orig, mvert->co);
|
||||
Mat4MulVecfl(ob->obmat, bp->orig);
|
||||
VECCOPY(bp->origS, bp->origE);
|
||||
VECCOPY(bp->origE, mvert->co);
|
||||
Mat4MulVecfl(ob->obmat, bp->origE);
|
||||
VECCOPY(bp->origT, bp->origE);
|
||||
}
|
||||
/* hrms .. do springs alter their lenght ?
|
||||
if(medge) {
|
||||
bs= ob->soft->bspring;
|
||||
bp= ob->soft->bpoint;
|
||||
for(a=0; a<me->totedge; a++, medge++, bs++) {
|
||||
bs->len= VecLenf( (bp+bs->v1)->orig, (bp+bs->v2)->orig);
|
||||
for(a=0; (a<me->totedge && a < ob->soft->totspring ); a++, medge++, bs++) {
|
||||
bs->len= VecLenf( (bp+bs->v1)->origE, (bp+bs->v2)->origE);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int get_scalar_from_named_vertexgroup(Object *ob, char *name, int vertID, float *target)
|
||||
/* result 0 on success, else indicates error number
|
||||
-- kind of *inverse* result defintion,
|
||||
-- but this way we can signal error condition to caller
|
||||
-- and yes this function must not be here but in a *vertex group module*
|
||||
*/
|
||||
{
|
||||
int i,groupindex;
|
||||
bDeformGroup *locGroup = NULL;
|
||||
MDeformVert *dv;
|
||||
locGroup=get_named_vertexgroup (ob,name);
|
||||
if(locGroup){
|
||||
/* retrieve index for that group */
|
||||
groupindex = get_defgroup_num (ob,locGroup);
|
||||
/* spot the vert in deform vert list at mesh */
|
||||
/* todo (coder paranoya) what if ob->data is not a mesh .. */
|
||||
/* hrms.. would like to have the same for lattices anyhoo */
|
||||
dv = ((Mesh*)ob->data)->dvert + vertID;
|
||||
/* Lets see if this vert is in the weight group */
|
||||
for (i=0; i<dv->totweight; i++){
|
||||
if (dv->dw[i].def_nr == groupindex){
|
||||
*target=dv->dw[i].weight; /* got it ! */
|
||||
return 0;
|
||||
}
|
||||
}/*for*/
|
||||
return 2;
|
||||
}/*if(locGroup)*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* makes totally fresh start situation */
|
||||
static void mesh_to_softbody(Object *ob)
|
||||
{
|
||||
@@ -195,11 +655,44 @@ static void mesh_to_softbody(Object *ob)
|
||||
for(a=me->totvert; a>0; a--, mvert++, bp++) {
|
||||
VECCOPY(bp->pos, mvert->co);
|
||||
Mat4MulVecfl(ob->obmat, bp->pos); // yep, sofbody is global coords
|
||||
VECCOPY(bp->orig, bp->pos);
|
||||
VECCOPY(bp->origS, bp->pos);
|
||||
VECCOPY(bp->origE, bp->pos);
|
||||
VECCOPY(bp->origT, bp->pos);
|
||||
bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0;
|
||||
bp->weight= 1.0;
|
||||
bp->goal= 0.5;
|
||||
bp->nofsprings=0;
|
||||
bp->springs=NULL;
|
||||
if (1) { /* switch to vg scalars*/
|
||||
/* get scalar values needed *per vertex* from vertex group functions,
|
||||
so we can *paint* them nicly ..
|
||||
they are normalized [0.0..1.0] so may be we need amplitude for scale
|
||||
which can be done by caller
|
||||
but still .. i'd like it to go this way
|
||||
*/
|
||||
int error;
|
||||
char name[32] = "SOFTGOAL";
|
||||
float temp;
|
||||
error = get_scalar_from_named_vertexgroup(ob,name,me->totvert - a,&temp);
|
||||
if (!error) bp->goal = temp;
|
||||
if (bp->goal < ob->sb_mingoal) bp->goal = ob->sb_mingoal;
|
||||
if (bp->goal > ob->sb_maxgoal) bp->goal = ob->sb_maxgoal;
|
||||
/* a little ad hoc changing the goal control to be less *sharp* */
|
||||
bp->goal = (float)pow(bp->goal,4.0f);
|
||||
/* to proove the concept
|
||||
this would enable per vertex *mass painting*
|
||||
strcpy(name,"SOFTMASS");
|
||||
error = get_scalar_from_named_vertexgroup(ob,name,me->totvert - a,&temp);
|
||||
if (!error) bp->mass = temp * ob->rangeofmass;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
} /* switch to vg scalars */
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(medge) {
|
||||
bs= ob->soft->bspring;
|
||||
bp= ob->soft->bpoint;
|
||||
@@ -207,10 +700,20 @@ static void mesh_to_softbody(Object *ob)
|
||||
bs->v1= medge->v1;
|
||||
bs->v2= medge->v2;
|
||||
bs->strength= 1.0;
|
||||
bs->len= VecLenf( (bp+bs->v1)->orig, (bp+bs->v2)->orig);
|
||||
bs->len= VecLenf( (bp+bs->v1)->origS, (bp+bs->v2)->origS);
|
||||
}
|
||||
}
|
||||
|
||||
/* insert *diagonal* springs in quads if desired */
|
||||
if (ob->softflag & 0x02) {
|
||||
add_quad_diag_springs(ob);
|
||||
|
||||
}
|
||||
|
||||
build_bps_springlist(ob); /* big mesh optimization */
|
||||
|
||||
/* vertex colors are abused as weights here, however they're stored in faces... uhh */
|
||||
/* naah .. we don't do it any more bjornmose :-)
|
||||
if(mface && me->mcol) {
|
||||
char *mcol= (char *)me->mcol;
|
||||
for(a=me->totface; a>0; a--, mface++, mcol+=16) {
|
||||
@@ -234,6 +737,7 @@ static void mesh_to_softbody(Object *ob)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
bp= ob->soft->bpoint;
|
||||
for(a=me->totvert; a>0; a--, bp++) {
|
||||
//printf("a %d goal %f\n", a, bp->goal);
|
||||
@@ -292,7 +796,7 @@ void object_update_softbody(Object *ob)
|
||||
}
|
||||
|
||||
/* makes totally fresh start situation */
|
||||
void object_to_softbody(Object *ob)
|
||||
void object_to_softbody(Object *ob,float ctime)
|
||||
{
|
||||
|
||||
if(ob->soft) free_softbody(ob->soft);
|
||||
@@ -301,6 +805,7 @@ void object_to_softbody(Object *ob)
|
||||
switch(ob->type) {
|
||||
case OB_MESH:
|
||||
mesh_to_softbody(ob);
|
||||
ob->soft->ctime = ctime;
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
lattice_to_softbody(ob);
|
||||
@@ -326,32 +831,165 @@ void softbody_to_object(Object *ob)
|
||||
|
||||
|
||||
/* simulates one step. ctime is in frames not seconds */
|
||||
|
||||
void object_softbody_step(Object *ob, float ctime)
|
||||
{
|
||||
float dtime;
|
||||
|
||||
int timescale,t;
|
||||
float forcetime;
|
||||
float err;
|
||||
|
||||
/* this is a NO! NO!
|
||||
==========================
|
||||
if(ob->soft==NULL) {
|
||||
object_to_softbody(ob);
|
||||
if(ob->soft==NULL) return;
|
||||
ob->soft->ctime= ctime;
|
||||
}
|
||||
|
||||
dtime= ctime - ob->soft->ctime;
|
||||
dtime= ABS(dtime);
|
||||
if(dtime > 0.0) {
|
||||
/* desired vertex locations in oldloc */
|
||||
object_update_softbody(ob);
|
||||
|
||||
/* extra for desired vertex locations */
|
||||
softbody_apply_goal(ob, dtime);
|
||||
|
||||
softbody_calc_forces(ob);
|
||||
softbody_apply_forces(ob, dtime);
|
||||
// you can't create a soft object on the fly
|
||||
// 1. inner spings need a *default* length for crinkles/wrinkles,
|
||||
// surface area and volume preservation
|
||||
// 2. initial conditions for velocities and positions need to be defined
|
||||
// for a certain point of time .. say t0
|
||||
// 3. and since we have friction and *outer* movement
|
||||
// the history of the *outer* movements will affect where we end up
|
||||
// sooo atm going to edit mode and back ( back calls object_to_softbody(ob,1.0f)
|
||||
is the only way to create softbody data
|
||||
*/
|
||||
|
||||
/* and apply to vertices */
|
||||
/* first attempt to set initial conditions for softbodies
|
||||
rules
|
||||
1. ODE solving is disabled / via button in 3dview header /otherways do regular softbody stuff
|
||||
2. set SB positions to *goal*
|
||||
3. set SB velocities to match *goal* movement
|
||||
|
||||
*/
|
||||
if (SB_ENABLE == 0){
|
||||
if(ob->soft==NULL) {
|
||||
return; /* nothing to do */
|
||||
}
|
||||
object_update_softbody(ob);
|
||||
ob->soft->ctime= ctime;
|
||||
interpolate_exciter(ob,200,200);
|
||||
softbody_force_goal(ob);
|
||||
softbody_to_object(ob);
|
||||
return; /* no dynamics wanted */
|
||||
|
||||
}
|
||||
|
||||
if(ob->soft==NULL) {
|
||||
/* aye no soft object created bail out here */
|
||||
printf("Softbody Zombie \n");
|
||||
return;
|
||||
}
|
||||
|
||||
softbody_scale_time(steptime); // translate frames/sec and lenghts unit to SI system
|
||||
dtime= ctime - ob->soft->ctime;
|
||||
// dtime= ABS(dtime); no no we want to go back in time with IPOs
|
||||
timescale = (int)(ob->softtime * ABS(dtime));
|
||||
if(ABS(dtime) > 0.0) {
|
||||
object_update_softbody(ob);
|
||||
if (ob->softflag & 0x04){
|
||||
/* special case of 2nd order Runge-Kutta type AKA Heun */
|
||||
float timedone =0.0;
|
||||
/* counter for emergency brake
|
||||
* we don't want to lock up the system if physics fail
|
||||
*/
|
||||
int loops =0 ;
|
||||
SoftHeunTol = ob->softtime; // humm .. this should be calculated from sb parameters and sizes
|
||||
|
||||
forcetime = dtime; /* hope for integrating in one step */
|
||||
while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) )
|
||||
{
|
||||
if (ABS(dtime) > 3.0 ){
|
||||
printf("SB_STEPSIZE \n");
|
||||
break; // sorry but i must assume goal movement can't be interpolated any more
|
||||
}
|
||||
//set goals in time
|
||||
interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime)));
|
||||
// do predictive euler step
|
||||
softbody_calc_forces(ob,forcetime);
|
||||
softbody_apply_forces(ob,forcetime,1, NULL);
|
||||
// crop new slope values to do averaged slope step
|
||||
softbody_calc_forces(ob,forcetime);
|
||||
softbody_apply_forces(ob,forcetime,2, &err);
|
||||
softbody_apply_goalsnap(ob);
|
||||
|
||||
if (err > SoftHeunTol){ // error needs to be scaled to some quantity
|
||||
softbody_restore_prev_step(ob);
|
||||
forcetime /= 2.0;
|
||||
}
|
||||
else {
|
||||
|
||||
float newtime = forcetime * 1.1f; // hope for 1.1 times better conditions in next step
|
||||
if (err > SoftHeunTol/2.0){ // stay with this stepsize unless err really small
|
||||
newtime = forcetime;
|
||||
}
|
||||
timedone += forcetime;
|
||||
if (forcetime > 0.0)
|
||||
forcetime = MIN2(dtime - timedone,newtime);
|
||||
else
|
||||
forcetime = MAX2(dtime - timedone,newtime);
|
||||
}
|
||||
loops++;
|
||||
}
|
||||
// move snapped to final position
|
||||
interpolate_exciter(ob,2,2);
|
||||
softbody_apply_goalsnap(ob);
|
||||
if (loops > HEUNWARNLIMIT) /* monitor high loop counts say 1000 after testing */
|
||||
printf("%d heun integration loops/frame \n",loops);
|
||||
}
|
||||
else
|
||||
/* do brute force explicit euler */
|
||||
/* inner intagration loop */
|
||||
/* */
|
||||
// loop n times so that n*h = duration of one frame := 1
|
||||
// x(t+h) = x(t) + h*v(t);
|
||||
// v(t+h) = v(t) + h*f(x(t),t);
|
||||
for(t=1 ; t <= timescale; t++) {
|
||||
if (ABS(dtime) > 15 ) break;
|
||||
|
||||
/* the *goal* mesh must use the n*h timing too !
|
||||
use *cheap* linear intepolation for that */
|
||||
interpolate_exciter(ob,timescale,t);
|
||||
if (timescale > 0 )
|
||||
{
|
||||
forcetime = dtime/timescale;
|
||||
|
||||
/* does not fit the concept sloving ODEs :) */
|
||||
/* softbody_apply_goal(ob,forcetime ); */
|
||||
|
||||
/* explicit Euler integration */
|
||||
/* we are not controling a nuclear power plant!
|
||||
so rought *almost* physical behaviour is acceptable.
|
||||
in cases of *mild* stiffnes cranking up timscale -> decreasing stepsize *h*
|
||||
avoids instability */
|
||||
softbody_calc_forces(ob,forcetime);
|
||||
softbody_apply_forces(ob,forcetime,0, NULL);
|
||||
softbody_apply_goalsnap(ob);
|
||||
|
||||
|
||||
// if (0){
|
||||
/* ok here comes the <20>berhammer
|
||||
use a semi implicit euler integration to tackle *all* stiff conditions
|
||||
but i doubt the cost/benifit holds for most of the cases
|
||||
-- to be coded*/
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* and apply to vertices */
|
||||
softbody_to_object(ob);
|
||||
|
||||
ob->soft->ctime= ctime;
|
||||
} // if(ABS(dtime) > 0.0)
|
||||
else {
|
||||
// rule : you have asked for the current state of the softobject
|
||||
// since dtime= ctime - ob->soft->ctime;
|
||||
// and we were not notifified about any other time changes
|
||||
// so here it is !
|
||||
softbody_to_object(ob);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -451,6 +451,19 @@ enum {
|
||||
#define B_SHOWTEX 2832
|
||||
#define B_ASSIGNMESH 2833
|
||||
|
||||
#define B_WEIGHT0_0 2840
|
||||
#define B_WEIGHT1_4 2841
|
||||
#define B_WEIGHT1_2 2842
|
||||
#define B_WEIGHT3_4 2843
|
||||
#define B_WEIGHT1_0 2844
|
||||
|
||||
#define B_OPA0_0 2845
|
||||
#define B_OPA1_4 2846
|
||||
#define B_OPA1_2 2847
|
||||
#define B_OPA3_4 2848
|
||||
#define B_OPA1_0 2849
|
||||
|
||||
|
||||
|
||||
/* *********************** */
|
||||
#define B_RADIOBUTS 3000
|
||||
|
||||
@@ -150,7 +150,7 @@ typedef struct Object {
|
||||
* For a Sphere, the form factor is by default = 0.4
|
||||
*/
|
||||
|
||||
float formfactor, springf; /* springf temp for softbody */
|
||||
float formfactor, softtime; /* springf temp for softbody */
|
||||
float rdamping, sizefac;
|
||||
|
||||
char dt, dtx;
|
||||
@@ -186,7 +186,7 @@ typedef struct Object {
|
||||
* bit 15: Always ignore activity culling
|
||||
*/
|
||||
int gameflag2;
|
||||
short softflag, pad; /* temporal stuff softbody experiment */
|
||||
short softflag, dummy; /* temporal stuff softbody experiment */
|
||||
float anisotropicFriction[3];
|
||||
|
||||
ListBase constraints;
|
||||
@@ -201,6 +201,20 @@ typedef struct Object {
|
||||
LBuf port;
|
||||
|
||||
float toonedge, smoothresh; /* smoothresh is phong interpolation ray_shadow correction in render */
|
||||
/* this stuff MUST NOT be here
|
||||
is here for softbody devel purpose
|
||||
*/
|
||||
float sb_goalspring; /* softbody goal springs */
|
||||
float sb_goalfrict; /* softbody goal springs friction */
|
||||
float sb_inspring; /* softbody inner springs */
|
||||
float sb_infrict; /* softbody inner springs friction */
|
||||
float sb_nodemass; /* softbody mass of *vertex* */
|
||||
float sb_grav; /* softbody amount of gravitaion to apply */
|
||||
float sb_mingoal; /* quick limits for goal */
|
||||
float sb_maxgoal;
|
||||
float sb_mediafrict; /* friction to env */
|
||||
float sb_pad1; /* free */
|
||||
|
||||
} Object;
|
||||
|
||||
typedef struct ObHook {
|
||||
|
||||
@@ -1399,7 +1399,8 @@ void RE_animrender(struct View3D *ogl_render_view3d)
|
||||
}
|
||||
start_avi();
|
||||
}
|
||||
|
||||
// set initial conditions for softbodies here
|
||||
// ******************************************
|
||||
for((G.scene->r.cfra)=(G.scene->r.sfra); (G.scene->r.cfra)<=(G.scene->r.efra); (G.scene->r.cfra)++) {
|
||||
double starttime= PIL_check_seconds_timer();
|
||||
|
||||
|
||||
@@ -2318,6 +2318,7 @@ void do_fpaintbuts(unsigned short event)
|
||||
Mesh *me;
|
||||
Object *ob;
|
||||
extern TFace *lasttface; /* caches info on tface bookkeeping ?*/
|
||||
extern VPaint Gvp; /* from vpaint */
|
||||
|
||||
ob= OBACT;
|
||||
if(ob==0) return;
|
||||
@@ -2401,6 +2402,50 @@ void do_fpaintbuts(unsigned short event)
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
}
|
||||
break;
|
||||
case B_WEIGHT0_0:
|
||||
editbutvweight = 0.0f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
|
||||
case B_WEIGHT1_4:
|
||||
editbutvweight = 0.25f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
case B_WEIGHT1_2:
|
||||
editbutvweight = 0.5f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
case B_WEIGHT3_4:
|
||||
editbutvweight = 0.75f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
case B_WEIGHT1_0:
|
||||
editbutvweight = 1.0f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
|
||||
case B_OPA0_0:
|
||||
Gvp.a = 0.0f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
case B_OPA1_4:
|
||||
Gvp.a = 0.25f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
case B_OPA1_2:
|
||||
Gvp.a = 0.5f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
case B_OPA3_4:
|
||||
Gvp.a = 0.75f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
case B_OPA1_0:
|
||||
Gvp.a = 1.0f;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2411,40 +2456,70 @@ static void editing_panel_mesh_paint(void)
|
||||
{
|
||||
extern VPaint Gvp; /* from vpaint */
|
||||
uiBlock *block;
|
||||
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_paint", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
if(uiNewPanel(curarea, block, "Paint", "Editing", 640, 0, 318, 204)==0) return;
|
||||
|
||||
|
||||
if(G.f & ( G_WEIGHTPAINT))
|
||||
{
|
||||
Object *ob;
|
||||
ob= OBACT;
|
||||
if(ob==NULL) return;
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUMSLI, 0, "R ", 979,160,194,19, &Gvp.r, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of red used for painting");
|
||||
uiDefButF(block, NUMSLI, 0, "G ", 979,140,194,19, &Gvp.g, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of green used for painting");
|
||||
uiDefButF(block, NUMSLI, 0, "B ", 979,120,194,19, &Gvp.b, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of blue used for painting");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiDefButF(block, NUMSLI, 0, "Opacity ", 979,100,194,19, &Gvp.a, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
|
||||
uiDefButF(block, NUMSLI, 0, "Size ", 979,80,194,19, &Gvp.size, 2.0, 64.0, 0, 0, "The size of the brush");
|
||||
|
||||
uiDefButF(block, COL, B_REDR, "", 1176,99,28,80, &(Gvp.r), 0, 0, 0, B_VPCOLSLI, "");
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, ROW, B_DIFF, "Mix", 1212,160,63,19, &Gvp.mode, 1.0, 0.0, 0, 0, "Mix the vertex colours");
|
||||
uiDefButS(block, ROW, B_DIFF, "Add", 1212,140,63,19, &Gvp.mode, 1.0, 1.0, 0, 0, "Add the vertex colour");
|
||||
uiDefButS(block, ROW, B_DIFF, "Sub", 1212, 120,63,19, &Gvp.mode, 1.0, 2.0, 0, 0, "Subtract from the vertex colour");
|
||||
uiDefButS(block, ROW, B_DIFF, "Mul", 1212, 100,63,19, &Gvp.mode, 1.0, 3.0, 0, 0, "Multiply the vertex colour");
|
||||
uiDefButS(block, ROW, B_DIFF, "Filter", 1212, 80,63,19, &Gvp.mode, 1.0, 4.0, 0, 0, "Mix the colours with an alpha factor");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, TOG|BIT|1, 0, "Area", 979,50,81,19, &Gvp.flag, 0, 0, 0, 0, "Vertex paint evaluates the area of the face the brush covers (otherwise vertices only)");
|
||||
uiDefButS(block, TOG|BIT|2, 0, "Soft", 1061,50,112,19, &Gvp.flag, 0, 0, 0, 0, "Use a soft brush");
|
||||
uiDefButS(block, TOG|BIT|3, 0, "Normals", 1174,50,102,19, &Gvp.flag, 0, 0, 0, 0, "Vertex paint applies the vertex normal before painting");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefBut(block, BUT, B_VPGAMMA, "Set", 979,30,81,19, 0, 0, 0, 0, 0, "Apply Mul and Gamma to vertex colours");
|
||||
uiDefButF(block, NUM, B_DIFF, "Mul:", 1061,30,112,19, &Gvp.mul, 0.1, 50.0, 10, 0, "Set the number to multiply vertex colours with");
|
||||
uiDefButF(block, NUM, B_DIFF, "Gamma:", 1174,30,102,19, &Gvp.gamma, 0.1, 5.0, 10, 0, "Change the clarity of the vertex colours");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiDefBut(block, BUT, B_SET_VCOL, "Set VertCol", 979,5,81,20, 0, 0, 0, 0, 0, "Set Vertex colour of selection to current (Shift+K)");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUMSLI, REDRAWVIEW3D, "Weight:",979,160,194,19, &editbutvweight, 0, 1, 10, 0, "Sets the current vertex group's bone deformation strength");
|
||||
uiDefBut(block, BUT, B_WEIGHT0_0 , "0", 979,140,40,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, BUT, B_WEIGHT1_4 , "1/4", 1020,140,40,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, BUT, B_WEIGHT1_2 , "1/2", 1060,140,40,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, BUT, B_WEIGHT3_4 , "3/4", 1100,140,40,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, BUT, B_WEIGHT1_0 , "1", 1140,140,33,19, 0, 0, 0, 0, 0, "");
|
||||
|
||||
uiDefButF(block, NUMSLI, 0, "Opacity ", 979,120,194,19, &Gvp.a, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
|
||||
uiDefBut(block, BUT, B_OPA0_0 , "0", 979,100,40,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, BUT, B_OPA1_4 , "1/4", 1020,100,40,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, BUT, B_OPA1_2 , "1/2", 1060,100,40,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, BUT, B_OPA3_4 , "3/4", 1100,100,40,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, BUT, B_OPA1_0 , "1", 1140,100,33,19, 0, 0, 0, 0, 0, "");
|
||||
uiDefButF(block, NUMSLI, 0, "Size ", 979,80,194,19, &Gvp.size, 2.0, 64.0, 0, 0, "The size of the brush");
|
||||
uiBlockEndAlign(block);
|
||||
if(ob){
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitC(block, TOG, OB_DRAWWIRE, REDRAWVIEW3D, "Wire", 979,40,194,19 , &ob->dtx, 0, 0, 0, 0, "Displays the active object's wireframe in shaded drawing modes");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
}
|
||||
else{
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, NUMSLI, 0, "R ", 979,160,194,19, &Gvp.r, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of red used for painting");
|
||||
uiDefButF(block, NUMSLI, 0, "G ", 979,140,194,19, &Gvp.g, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of green used for painting");
|
||||
uiDefButF(block, NUMSLI, 0, "B ", 979,120,194,19, &Gvp.b, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of blue used for painting");
|
||||
uiBlockEndAlign(block);
|
||||
uiDefButF(block, NUMSLI, 0, "Opacity ", 979,100,194,19, &Gvp.a, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
|
||||
uiDefButF(block, NUMSLI, 0, "Size ", 979,80,194,19, &Gvp.size, 2.0, 64.0, 0, 0, "The size of the brush");
|
||||
|
||||
uiDefButF(block, COL, B_REDR, "", 1176,99,28,80, &(Gvp.r), 0, 0, 0, B_VPCOLSLI, "");
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, ROW, B_DIFF, "Mix", 1212,160,63,19, &Gvp.mode, 1.0, 0.0, 0, 0, "Mix the vertex colours");
|
||||
uiDefButS(block, ROW, B_DIFF, "Add", 1212,140,63,19, &Gvp.mode, 1.0, 1.0, 0, 0, "Add the vertex colour");
|
||||
uiDefButS(block, ROW, B_DIFF, "Sub", 1212, 120,63,19, &Gvp.mode, 1.0, 2.0, 0, 0, "Subtract from the vertex colour");
|
||||
uiDefButS(block, ROW, B_DIFF, "Mul", 1212, 100,63,19, &Gvp.mode, 1.0, 3.0, 0, 0, "Multiply the vertex colour");
|
||||
uiDefButS(block, ROW, B_DIFF, "Filter", 1212, 80,63,19, &Gvp.mode, 1.0, 4.0, 0, 0, "Mix the colours with an alpha factor");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, TOG|BIT|1, 0, "Area", 979,50,81,19, &Gvp.flag, 0, 0, 0, 0, "Vertex paint evaluates the area of the face the brush covers (otherwise vertices only)");
|
||||
uiDefButS(block, TOG|BIT|2, 0, "Soft", 1061,50,112,19, &Gvp.flag, 0, 0, 0, 0, "Use a soft brush");
|
||||
uiDefButS(block, TOG|BIT|3, 0, "Normals", 1174,50,102,19, &Gvp.flag, 0, 0, 0, 0, "Vertex paint applies the vertex normal before painting");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefBut(block, BUT, B_VPGAMMA, "Set", 979,30,81,19, 0, 0, 0, 0, 0, "Apply Mul and Gamma to vertex colours");
|
||||
uiDefButF(block, NUM, B_DIFF, "Mul:", 1061,30,112,19, &Gvp.mul, 0.1, 50.0, 10, 0, "Set the number to multiply vertex colours with");
|
||||
uiDefButF(block, NUM, B_DIFF, "Gamma:", 1174,30,102,19, &Gvp.gamma, 0.1, 5.0, 10, 0, "Change the clarity of the vertex colours");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiDefBut(block, BUT, B_SET_VCOL, "Set VertCol", 979,5,81,20, 0, 0, 0, 0, 0, "Set Vertex colour of selection to current (Shift+K)");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void editing_panel_mesh_texface(void)
|
||||
|
||||
@@ -1434,12 +1434,72 @@ static void object_panel_deflectors(Object *ob)
|
||||
}
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
|
||||
/*
|
||||
if(strncmp(ob->id.name+2, "soft", 4)==0) {
|
||||
uiDefButS(block, TOG|BIT|0, B_DIFF, "Soft Body", 220,160,200,20, &ob->softflag, 0, 0, 0, 0, "Sets object to become soft body");
|
||||
uiDefButF(block, NUM, B_DIFF, "Spring: ", 220,140,200,20, &ob->springf, 0.0, 1.0, 10, 0, "Spring constant");
|
||||
uiDefButF(block, NUM, B_DIFF, "Damp: ", 220,120,200,20, &ob->damping, 0.0, 1.0, 10, 0, "General damping in softbody on point movements");
|
||||
int ypos = 220;
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, TOG|BIT|0, B_DIFF, "Soft Body", 220,ypos,200,20, &ob->softflag, 0, 0, 0, 0, "Sets object to become soft body");
|
||||
|
||||
uiDefButS(block, TOG|BIT|1, B_DIFF, "Stiff Quads", 220,ypos -= 20,100,20, &ob->softflag, 0, 0, 0, 0, "Sets object to have diagonal springs on 4-gons");
|
||||
uiDefButS(block, TOG|BIT|2, B_DIFF, "R sol 1", 320,ypos,100,20, &ob->softflag, 0, 0, 0, 0, "Use Robust 2nd order solver");
|
||||
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "GSpring:", 220,ypos -= 20,200,20, &ob->sb_goalspring, 0.0, 0.999, 10, 0, "Goal Spring Constant");
|
||||
uiDefButF(block, NUM, B_DIFF, "GFrict:", 220,ypos -= 20,200,20, &ob->sb_goalfrict , 0.0, 10.0, 10, 0, "Goal Friction Constant");
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "ISpring:", 220,ypos -= 20,200,20, &ob->sb_inspring, 0.0, 0.999, 10, 0, "Inner Spring Constant");
|
||||
uiDefButF(block, NUM, B_DIFF, "IFrict:", 220,ypos -= 20,200,20, &ob->sb_infrict, 0.0, 10.0, 10, 0, "Inner Friction Constant");
|
||||
uiDefButF(block, NUM, B_DIFF, "MFrict:", 220,ypos -= 20,200,20, &ob->sb_mediafrict, 0.0, 10.0, 10, 0, "Friction in media");
|
||||
|
||||
if (ob->softflag & 0x4)
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "RKL:", 220,ypos -= 20,200,20, &ob->softtime , 0.01, 1.0, 10, 0, "ODE solver error limit");
|
||||
else
|
||||
uiDefButF(block, NUM, B_DIFF, "Steps:", 220,ypos -= 20,200,20, &ob->softtime , 1.0, 500.0, 10, 0, "Softbody time");
|
||||
|
||||
uiDefButF(block, NUM, B_DIFF, "NMass:", 220,ypos -= 20,200,20, &ob->sb_nodemass , 0.001, 50.0, 10, 0, "Node Mass");
|
||||
uiDefButF(block, NUM, B_DIFF, "Grav:", 220,ypos -= 20,200,20, &ob->sb_grav , 0.0, 10.0, 10, 0, "Gravitation");
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "GMin:", 220,ypos -= 20,200,20, &ob->sb_mingoal, 0.0, 1.0, 10, 0, "Min Goal bound");
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "GMax:", 220,ypos -= 20,200,20, &ob->sb_maxgoal, 0.0, 1.0, 10, 0, "Max Goal bound");
|
||||
uiDefButS(block, TOG|BIT|3, B_DIFF, "PostDef",220,ypos-= 20,100,20, &ob->softflag, 0, 0, 0, 0, "Apply Soft AFTER Deform");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* Panel for softbodies */
|
||||
|
||||
static void object_softbodies(Object *ob)
|
||||
{
|
||||
uiBlock *block;
|
||||
int ypos = 220;
|
||||
if(strncmp(ob->id.name+2, "soft", 4)!=0) {return;}
|
||||
block= uiNewBlock(&curarea->uiblocks, "object_softbodies", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
uiNewPanelTabbed("Constraints", "Object");
|
||||
if(uiNewPanel(curarea, block, "Softbodies", "Object", 640, 0, 318, 204)==0) return;
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, TOG|BIT|0, REDRAWBUTSOBJECT, "Soft Body", 220,ypos,200,20, &ob->softflag, 0, 0, 0, 0, "Sets object to become soft body");
|
||||
if ( ob->softflag & 0x01) {
|
||||
uiDefButS(block, TOG|BIT|1, B_DIFF, "Stiff Quads", 220,ypos -= 20,100,20, &ob->softflag, 0, 0, 0, 0, "Sets object to have diagonal springs on 4-gons");
|
||||
uiDefButS(block, TOG|BIT|2, B_DIFF, "R sol 1", 320,ypos,100,20, &ob->softflag, 0, 0, 0, 0, "Use Robust 2nd order solver");
|
||||
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "GSpring:", 220,ypos -= 20,200,20, &ob->sb_goalspring, 0.0, 0.999, 10, 0, "Goal Spring Constant");
|
||||
uiDefButF(block, NUM, B_DIFF, "GFrict:", 220,ypos -= 20,200,20, &ob->sb_goalfrict , 0.0, 10.0, 10, 0, "Goal Friction Constant");
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "ISpring:", 220,ypos -= 20,200,20, &ob->sb_inspring, 0.0, 0.999, 10, 0, "Inner Spring Constant");
|
||||
uiDefButF(block, NUM, B_DIFF, "IFrict:", 220,ypos -= 20,200,20, &ob->sb_infrict, 0.0, 10.0, 10, 0, "Inner Friction Constant");
|
||||
uiDefButF(block, NUM, B_DIFF, "MFrict:", 220,ypos -= 20,200,20, &ob->sb_mediafrict, 0.0, 10.0, 10, 0, "Friction in media");
|
||||
|
||||
if (ob->softflag & 0x4)
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "RKL:", 220,ypos -= 20,200,20, &ob->softtime , 0.01, 1.0, 10, 0, "ODE solver error limit");
|
||||
else
|
||||
uiDefButF(block, NUM, B_DIFF, "Steps:", 220,ypos -= 20,200,20, &ob->softtime , 1.0, 500.0, 10, 0, "Softbody time");
|
||||
|
||||
uiDefButF(block, NUM, B_DIFF, "NMass:", 220,ypos -= 20,200,20, &ob->sb_nodemass , 0.001, 50.0, 10, 0, "Node Mass");
|
||||
uiDefButF(block, NUM, B_DIFF, "Grav:", 220,ypos -= 20,200,20, &ob->sb_grav , 0.0, 10.0, 10, 0, "Gravitation");
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "GMin:", 220,ypos -= 20,200,20, &ob->sb_mingoal, 0.0, 1.0, 10, 0, "Min Goal bound");
|
||||
uiDefButF(block, NUMSLI, B_DIFF, "GMax:", 220,ypos -= 20,200,20, &ob->sb_maxgoal, 0.0, 1.0, 10, 0, "Max Goal bound");
|
||||
uiDefButS(block, TOG|BIT|3, B_DIFF, "PostDef",220,ypos-= 20,100,20, &ob->softflag, 0, 0, 0, 0, "Apply Soft AFTER Deform");
|
||||
}
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
}
|
||||
|
||||
void object_panel_effects(Object *ob)
|
||||
@@ -1451,7 +1511,7 @@ void object_panel_effects(Object *ob)
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "object_panel_effects", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
uiNewPanelTabbed("Constraints", "Object");
|
||||
if(uiNewPanel(curarea, block, "Effects", "Object", 640, 0, 418, 204)==0) return;
|
||||
if(uiNewPanel(curarea, block, "Effects", "Object", 640, 0, 318, 204)==0) return;
|
||||
|
||||
/* EFFECTS */
|
||||
|
||||
@@ -1604,6 +1664,7 @@ void object_panels()
|
||||
object_panel_effects(ob);
|
||||
}
|
||||
object_panel_deflectors(ob);
|
||||
object_softbodies(ob);
|
||||
|
||||
uiClearButLock();
|
||||
}
|
||||
|
||||
@@ -4322,7 +4322,7 @@ void draw_object(Base *base)
|
||||
if(ob->parent && ob->partype==PARSKEL) makeDispList(ob);
|
||||
else if(ob->parent && ob->parent->type==OB_LATTICE) makeDispList(ob);
|
||||
else if(ob->hooks.first) makeDispList(ob);
|
||||
else if(ob->softflag) makeDispList(ob);
|
||||
else if(ob->softflag & 0x01) makeDispList(ob);
|
||||
else if(me->disp.first==NULL && mesh_uses_displist(me)) makeDispList(ob);
|
||||
else if(ob->effect.first) { // as last check
|
||||
Effect *eff= ob->effect.first;
|
||||
|
||||
@@ -1063,6 +1063,54 @@ void fill_mesh(void)
|
||||
/* ******************** SUBDIVIDE ********************************** */
|
||||
|
||||
|
||||
static void merge_weights(EditVert * vt, EditVert *vs )
|
||||
{
|
||||
MDeformWeight *newdw;
|
||||
int i,j,done;
|
||||
for (j=0; j<vs->totweight; j++){
|
||||
done=0;
|
||||
/* Is vertex memeber of group */
|
||||
/* If so: Change its weight */
|
||||
for (i=0; i<vt->totweight; i++){
|
||||
if (vt->dw[i].def_nr == vs->dw[j].def_nr)
|
||||
{ /* taking the maximum makes it independant from order of occurance */
|
||||
if (vt->dw[i].weight < vs->dw[j].weight) vt->dw[i].weight = vs->dw[j].weight;
|
||||
done=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If not: Add the group and set its weight */
|
||||
if (!done){
|
||||
newdw = MEM_callocN (sizeof(MDeformWeight)*(vt->totweight+1), "deformWeight");
|
||||
if (vt->dw){
|
||||
memcpy (newdw, vt->dw, sizeof(MDeformWeight)*vt->totweight);
|
||||
MEM_freeN (vt->dw);
|
||||
}
|
||||
vt->dw=newdw;
|
||||
vt->dw[vt->totweight].weight=vs->dw[j].weight;
|
||||
vt->dw[vt->totweight].def_nr=vs->dw[j].def_nr;
|
||||
vt->totweight++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void set_weights(EditVert * vt, EditVert *vs1,EditVert *vs2,EditVert *vs3,EditVert *vs4 )
|
||||
{
|
||||
/*
|
||||
vt is a new generated vertex with empty deform group information
|
||||
vs1..v4 are egde neighbours holding group information
|
||||
so let the information ooze into the new one
|
||||
*/
|
||||
if (vs1) merge_weights(vt,vs1);
|
||||
if (vs2) merge_weights(vt,vs2);
|
||||
if (vs3) merge_weights(vt,vs3);
|
||||
if (vs4) merge_weights(vt,vs4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static unsigned int cpack_fact(unsigned int col1, unsigned int col2, float fact)
|
||||
{
|
||||
char *cp1, *cp2, *cp;
|
||||
@@ -1105,6 +1153,9 @@ static void face_pin_vertex(EditFace *efa, EditVert *vertex)
|
||||
else if(efa->v4 && vertex && efa->v4 == vertex) efa->tf.unwrap |= TF_PIN4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void set_wuv(int tot, EditFace *efa, int v1, int v2, int v3, int v4, EditFace *efapin)
|
||||
{
|
||||
/* this weird function only to be used for subdivide, the 'w' in the name has no meaning! */
|
||||
@@ -1486,6 +1537,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
/* add edges here, to copy correct edge data */
|
||||
eed= addedgelist(e1->v1, e1->vn, e1);
|
||||
eed= addedgelist(e1->vn, e1->v2, e1);
|
||||
set_weights(e1->vn, e1->v1,e1->v2,NULL,NULL);
|
||||
}
|
||||
if(e2 && e2->vn) {
|
||||
test+= 2;
|
||||
@@ -1493,6 +1545,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
/* add edges here, to copy correct edge data */
|
||||
eed= addedgelist(e2->v1, e2->vn, e2);
|
||||
eed= addedgelist(e2->vn, e2->v2, e2);
|
||||
set_weights(e2->vn, e2->v1,e2->v2,NULL,NULL);
|
||||
}
|
||||
if(e3 && e3->vn) {
|
||||
test+= 4;
|
||||
@@ -1500,6 +1553,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
/* add edges here, to copy correct edge data */
|
||||
eed= addedgelist(e3->v1, e3->vn, e3);
|
||||
eed= addedgelist(e3->vn, e3->v2, e3);
|
||||
set_weights(e3->vn, e3->v1,e3->v2,NULL,NULL);
|
||||
}
|
||||
if(e4 && e4->vn) {
|
||||
test+= 8;
|
||||
@@ -1507,6 +1561,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
/* add edges here, to copy correct edge data */
|
||||
eed= addedgelist(e4->v1, e4->vn, e4);
|
||||
eed= addedgelist(e4->vn, e4->v2, e4);
|
||||
set_weights(e4->vn, e4->v1,e4->v2,NULL,NULL);
|
||||
}
|
||||
if(test) {
|
||||
if(efa->v4==0) { /* All the permutations of 3 edges*/
|
||||
@@ -1564,7 +1619,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
smooth_subdiv_quad(efa, vec); /* adds */
|
||||
}
|
||||
eve= addvertlist(vec);
|
||||
|
||||
set_weights(eve, efa->v1,efa->v2,efa->v3,efa->v4);
|
||||
eve->f |= flag;
|
||||
|
||||
addface_subdiv(efa, 2, 2+4, 9, 1+4, eve, &efapin);
|
||||
@@ -1621,6 +1676,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
vec[1]=(e1->vn->co[1]+e2->vn->co[1])/2;
|
||||
vec[2]=(e1->vn->co[2]+e2->vn->co[2])/2;
|
||||
eve= addvertlist(vec);
|
||||
set_weights(eve, e1->vn,e2->vn,NULL,NULL);
|
||||
eve->f |= flag;
|
||||
/* Add new faces */
|
||||
addface_subdiv(efa, 4, 10, 2+4, 3, eve, &efapin);
|
||||
@@ -1639,6 +1695,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
vec[1]=(e2->vn->co[1]+e3->vn->co[1])/2;
|
||||
vec[2]=(e2->vn->co[2]+e3->vn->co[2])/2;
|
||||
eve= addvertlist(vec);
|
||||
set_weights(eve, e2->vn,e3->vn,NULL,NULL);
|
||||
eve->f |= flag;
|
||||
/*New faces*/
|
||||
addface_subdiv(efa, 1, 11, 3+4, 4, eve, &efapin);
|
||||
@@ -1657,6 +1714,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
vec[1]=(e3->vn->co[1]+e4->vn->co[1])/2;
|
||||
vec[2]=(e3->vn->co[2]+e4->vn->co[2])/2;
|
||||
eve= addvertlist(vec);
|
||||
set_weights(eve, e3->vn,e4->vn,NULL,NULL);
|
||||
eve->f |= flag;
|
||||
/*New Faces*/
|
||||
addface_subdiv(efa, 2, 12, 4+4, 1, eve, &efapin);
|
||||
@@ -1675,6 +1733,7 @@ void subdivideflag(int flag, float rad, int beauty)
|
||||
vec[1]=(e1->vn->co[1]+e4->vn->co[1])/2;
|
||||
vec[2]=(e1->vn->co[2]+e4->vn->co[2])/2;
|
||||
eve= addvertlist(vec);
|
||||
set_weights(eve, e1->vn,e4->vn,NULL,NULL);
|
||||
eve->f |= flag;
|
||||
/*New Faces*/
|
||||
addface_subdiv(efa, 3, 13, 1+4, 2, eve, &efapin);
|
||||
|
||||
@@ -1526,6 +1526,15 @@ void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do un
|
||||
|
||||
/* displist make is different in editmode */
|
||||
if(freedata) G.obedit= NULL;
|
||||
|
||||
// need to be here since
|
||||
// makeDispList(ob); calls
|
||||
// int mesh_modifier(Object *ob, char mode)..
|
||||
// calling object_softbody_step(ob, ctime);
|
||||
// needs a valid *up to date* softbody object or NULL pointer at "soft" member
|
||||
// anyhow *new* dependacy graph should take care for that :)
|
||||
if(ob->softflag & 0x01) object_to_softbody(ob,1.0f);
|
||||
|
||||
makeDispList(ob);
|
||||
|
||||
/* has this influence at other objects? */
|
||||
@@ -1563,8 +1572,8 @@ void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do un
|
||||
allqueue(REDRAWOOPS, 0);
|
||||
}
|
||||
scrarea_queue_headredraw(curarea);
|
||||
|
||||
if(ob->softflag) object_to_softbody(ob);
|
||||
// faaaaar to late
|
||||
// if(ob->softflag & 0x01) object_to_softbody(ob);
|
||||
|
||||
if(G.obedit==NULL && freedata==2)
|
||||
BIF_undo_push("Editmode");
|
||||
|
||||
@@ -3919,6 +3919,7 @@ void view3d_buttons(void)
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
xco+= XIC+8;
|
||||
|
||||
|
||||
/* LAYERS */
|
||||
if(G.vd->localview==0) {
|
||||
@@ -4002,6 +4003,11 @@ void view3d_buttons(void)
|
||||
"Pastes the mirrored pose from the buffer");
|
||||
}
|
||||
}
|
||||
{
|
||||
extern short SB_ENABLE;
|
||||
xco+= XIC+8;
|
||||
uiDefButS(block, TOG|BIT|1, B_DIFF, "Soft", xco,0,XIC*3,YIC, &SB_ENABLE, 0, 0, 0, 0, "Force Softbodies to goal");
|
||||
}
|
||||
|
||||
/* Always do this last */
|
||||
curarea->headbutlen= xco+2*XIC;
|
||||
|
||||
Reference in New Issue
Block a user