diff options
author | Ton Roosendaal <ton@blender.org> | 2004-10-01 18:10:30 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2004-10-01 18:10:30 +0400 |
commit | f2b785296ed5b91b3484bc282966226bcc4073dc (patch) | |
tree | e068a63601b3b739d364ad97ee8953e8c5cef5ec | |
parent | 04f5baee3a8ccfbe21c3f9eed49809f24fd7fddf (diff) |
Added 2 files for softbody plus sconscript!
-rw-r--r-- | source/blender/blenkernel/BKE_softbody.h | 72 | ||||
-rw-r--r-- | source/blender/blenkernel/SConscript | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/softbody.c | 357 |
3 files changed, 430 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h new file mode 100644 index 00000000000..77a68317818 --- /dev/null +++ b/source/blender/blenkernel/BKE_softbody.h @@ -0,0 +1,72 @@ +/** + * BKE_softbody.h + * + * $Id: BKE_softbody.h + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_SOFTBODY_H +#define BKE_SOFTBODY_H + +typedef struct BodyPoint { + float orig[3], pos[3], vec[3], force[3]; + float weight, goal; +} BodyPoint; + +typedef struct BodySpring { + int v1, v2; + float len, strength; +} BodySpring; + +typedef struct SoftBody { + int totpoint, totspring; + + BodyPoint *bpoint; + BodySpring *bspring; + + float ctime; // last time calculated +} SoftBody; + +/* temporal data, nothing saved in file */ +extern void free_softbody(SoftBody *sb); + +/* makes totally fresh start situation */ +extern void object_to_softbody(Object *ob); + +/* copy original (but new) situation in softbody, as result of matrices or deform */ +void object_update_softbody(Object *ob); + +/* copies softbody result back to object (in displist) */ +extern void softbody_to_object(Object *ob); + +/* go one step in simulation */ +extern void object_softbody_step(Object *ob, float ctime); + +#endif + diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 0b5abbc2346..d71dd38f7ad 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -39,6 +39,7 @@ source_files = ['intern/constraint.c', 'intern/font.c', 'intern/library.c', 'intern/property.c', + 'intern/softbody.c', 'intern/texture.c'] blenkernel_env.Append (CPPPATH = ['.', diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c new file mode 100644 index 00000000000..0c785041bb9 --- /dev/null +++ b/source/blender/blenkernel/intern/softbody.c @@ -0,0 +1,357 @@ +/* softbody.c + * + * $Id: + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +/* types */ +#include "DNA_ika_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_global.h" +#include "BKE_utildefines.h" +#include "BKE_softbody.h" +#include "BKE_displist.h" + +/* ********** soft body engine ******* */ + + +static SoftBody *new_softbody(int totpoint, int totspring) +{ + SoftBody *sb= NULL; + + if(totpoint) { + sb= MEM_callocN(sizeof(SoftBody), "softbody"); + sb->totpoint= totpoint; + sb->totspring= totspring; + + sb->bpoint= MEM_mallocN( totpoint*sizeof(BodyPoint), "bodypoint"); + if(totspring) + sb->bspring= MEM_mallocN( totspring*sizeof(BodySpring), "bodyspring"); + } + return sb; +} + +void free_softbody(SoftBody *sb) +{ + if(sb) { + if(sb->bpoint) MEM_freeN(sb->bpoint); + if(sb->bspring) MEM_freeN(sb->bspring); + + MEM_freeN(sb); + } +} + +static void softbody_calc_forces(Object *ob) +{ + SoftBody *sb= ob->soft; // is supposed to be there + BodyPoint *bp; + float ks; + int a; + + /* 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 */ + for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { + + 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]); + } +} + +static void softbody_apply_forces(Object *ob, float dtime) +{ + SoftBody *sb= ob->soft; // is supposed to be there + BodyPoint *bp; + float kd; + int a; + + kd= 1.0-ob->damping; + + 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); + } +} + +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; + // 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]); + + VECADD(bp->pos, bp->pos, vec); + + ks= 1.0-ks; + bp->vec[0]*= ks; + bp->vec[1]*= ks; + bp->vec[2]*= ks; + } +} + + +/* ************ convertors ********** */ + +/* copy original (new) situation in softbody, as result of matrices or deform */ +static void mesh_update_softbody(Object *ob) +{ + Mesh *me= ob->data; + 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); + } + 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); + } + } + } + +} + +/* makes totally fresh start situation */ +static void mesh_to_softbody(Object *ob) +{ + Mesh *me= ob->data; + MVert *mvert= me->mvert; + MEdge *medge= me->medge; + MFace *mface= me->mface; + BodyPoint *bp; + BodySpring *bs; + int a; + + ob->soft= new_softbody(me->totvert, me->totedge); + if(ob->soft) { + bp= ob->soft->bpoint; + 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); + bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0; + bp->weight= 1.0; + bp->goal= 0.5; + } + if(medge) { + bs= ob->soft->bspring; + bp= ob->soft->bpoint; + for(a=me->totedge; a>0; a--, medge++, bs++) { + bs->v1= medge->v1; + bs->v2= medge->v2; + bs->strength= 1.0; + bs->len= VecLenf( (bp+bs->v1)->orig, (bp+bs->v2)->orig); + } + } + /* vertex colors are abused as weights here, however they're stored in faces... uhh */ + if(mface && me->mcol) { + char *mcol= (char *)me->mcol; + for(a=me->totface; a>0; a--, mface++, mcol+=16) { + bp= ob->soft->bpoint+mface->v1; + if(bp->goal==0.5) { + bp->goal= ( (float)( (mcol + 0)[1] ) )/255.0; + } + bp= ob->soft->bpoint+mface->v2; + if(bp->goal==0.5) { + bp->goal= ( (float)( (mcol + 4)[1] ) )/255.0; + } + bp= ob->soft->bpoint+mface->v3; + if(bp->goal==0.5) { + bp->goal= ( (float)( (mcol + 8)[1]) )/255.0; + } + if(mface->v4) { + bp= ob->soft->bpoint+mface->v4; + if(bp->goal==0.5) { + bp->goal= ( (float)( (mcol + 12)[1]) )/255.0; + } + } + } + } + bp= ob->soft->bpoint; + for(a=me->totvert; a>0; a--, bp++) { + //printf("a %d goal %f\n", a, bp->goal); + } + + } +} + +/* copies current sofbody position in mesh, so do this within modifier stacks! */ +static void softbody_to_mesh(Object *ob) +{ + Mesh *me= ob->data; + MVert *mvert; + BodyPoint *bp; + int a; + + Mat4Invert(ob->imat, ob->obmat); + + bp= ob->soft->bpoint; + mvert= me->mvert; + for(a=me->totvert; a>0; a--, mvert++, bp++) { + VECCOPY(mvert->co, bp->pos); + Mat4MulVecfl(ob->imat, mvert->co); // softbody is in global coords + } + +} + +/* makes totally fresh start situation */ +static void lattice_to_softbody(Object *ob) +{ + +} + +/* copies current sofbody position */ +static void softbody_to_lattice(Object *ob) +{ + +} + + + +/* ************ Object level, exported functions *************** */ + +/* copy original (new) situation in softbody, as result of matrices or deform */ +void object_update_softbody(Object *ob) +{ + switch(ob->type) { + case OB_MESH: + mesh_update_softbody(ob); + break; + case OB_LATTICE: + //lattice_update_softbody(ob); + break; + } + +} + +/* makes totally fresh start situation */ +void object_to_softbody(Object *ob) +{ + + if(ob->soft) free_softbody(ob->soft); + ob->soft= NULL; + + switch(ob->type) { + case OB_MESH: + mesh_to_softbody(ob); + break; + case OB_LATTICE: + lattice_to_softbody(ob); + break; + } +} + +/* copies softbody result back in object */ +void softbody_to_object(Object *ob) +{ + + if(ob->soft==NULL) return; + + switch(ob->type) { + case OB_MESH: + softbody_to_mesh(ob); + break; + case OB_LATTICE: + softbody_to_lattice(ob); + break; + } +} + + +/* simulates one step. ctime is in frames not seconds */ +void object_softbody_step(Object *ob, float ctime) +{ + float dtime; + + 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); + + /* and apply to vertices */ + softbody_to_object(ob); + + ob->soft->ctime= ctime; + } +} + |