Another Orange sneak-in feature: SoftBody support for Curves & Surfaces.

Well, it already worked a bit, but without weight options or edge
stiffness. You now can set the weights using the "Properties" Panel in
the 3D Window (allows multiple selections too) or with Wkey in Edit Mode.
Bezier curves have this too.

NOTE: Lattice SoftBody Goal created yesterday won't work anymore!
I've had to recode weight support for Nurbs Points, using a new weight
variable... this because the existing W variable was in use for Nurbs
already. Also Lattices have this new Weight variable, so the code is nice
uniform. Sorry for the artists who already created complex Lattices... :)

NOTE2: Surface Objects don't support edge stiffness yet

NOTE3: I've removed ancient screen coordinates from the Bezier struct,
which makes - even with added weight and padding - the struct smaller!

Demo file:
http://download.blender.org/demo/test/2.40/softbody_curve_lattice.blend
This commit is contained in:
2005-11-17 11:40:57 +00:00
parent 96221a5331
commit ec477f7a63
8 changed files with 173 additions and 89 deletions

View File

@@ -1429,7 +1429,7 @@ static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int ed
if (editmode && !(md->mode&eModifierMode_Editmode)) continue;
if (mti->isDisabled && mti->isDisabled(md)) continue;
if (md->type==eModifierType_Hook) {
if (md->type==eModifierType_Hook || md->type==eModifierType_Softbody) {
preTesselatePoint = md;
}
}
@@ -1464,6 +1464,7 @@ void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float (
deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
originalVerts = MEM_dupallocN(deformedVerts);
}
mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
if (md==preTesselatePoint)

View File

@@ -70,6 +70,7 @@ variables on the UI for now
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_global.h"
@@ -1043,7 +1044,7 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff)
static void lattice_to_softbody(Object *ob,int *rcs)
{
Lattice *lt= ob->data;
SoftBody *sb= ob->soft;
SoftBody *sb;
int totvert, totspring = 0;
totvert= lt->pntsu*lt->pntsv*lt->pntsw;
@@ -1059,7 +1060,8 @@ static void lattice_to_softbody(Object *ob,int *rcs)
/* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
renew_softbody(ob, totvert, totspring,rcs);
renew_softbody(ob, totvert, totspring, rcs);
sb= ob->soft; /* can be created in renew_softbody() */
/* weights from bpoints, same code used as for mesh vertices */
if((ob->softflag & OB_SB_GOAL) && sb->vertgroup) {
@@ -1069,9 +1071,7 @@ static void lattice_to_softbody(Object *ob,int *rcs)
int a;
for(a=0; a<totvert; a++, bp++, bpnt++) {
bp->goal= sb->mingoal + bpnt->vec[3]*goalfac;
bp->goal= sb->mingoal + bpnt->weight*goalfac;
/* a little ad hoc changing the goal control to be less *sharp* */
bp->goal = (float)pow(bp->goal, 4.0f);
}
@@ -1084,6 +1084,87 @@ static void lattice_to_softbody(Object *ob,int *rcs)
}
}
/* makes totally fresh start situation */
static void curve_surf_to_softbody(Object *ob, int *rcs)
{
Curve *cu= ob->data;
SoftBody *sb;
int totvert, totspring = 0;
totvert= count_curveverts(&cu->nurb);
if (ob->softflag & OB_SB_EDGES){
if(ob->type==OB_CURVE) {
totspring= totvert - BLI_countlist(&cu->nurb);
}
}
/* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
renew_softbody(ob, totvert, totspring, rcs);
sb= ob->soft; /* can be created in renew_softbody() */
/* weights from bpoints, same code used as for mesh vertices */
if((ob->softflag & OB_SB_GOAL) && sb->vertgroup) {
BodyPoint *bp= sb->bpoint;
BodySpring *bs= sb->bspring;
Nurb *nu;
BezTriple *bezt;
BPoint *bpnt;
float goalfac= ABS(sb->maxgoal - sb->mingoal);
int a, curindex=0;
for(nu= cu->nurb.first; nu; nu= nu->next) {
if(nu->bezt) {
for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++, bp++, curindex+=3) {
bp->goal= sb->mingoal + bezt->weight*goalfac;
/* a little ad hoc changing the goal control to be less *sharp* */
bp->goal = (float)pow(bp->goal, 4.0f);
/* all three triples */
bp++;
bp->goal= (bp-1)->goal;
bp++;
bp->goal= (bp-1)->goal;
if(totspring) {
if(a>0) {
bs->v1= curindex-1;
bs->v2= curindex;
bs->strength= 1.0;
bs++;
}
bs->v1= curindex;
bs->v2= curindex+1;
bs->strength= 1.0;
bs++;
bs->v1= curindex+1;
bs->v2= curindex+2;
bs->strength= 1.0;
bs++;
}
}
}
else {
for(bpnt=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bpnt++, bp++, curindex++) {
bp->goal= sb->mingoal + bpnt->weight*goalfac;
/* a little ad hoc changing the goal control to be less *sharp* */
bp->goal = (float)pow(bp->goal, 4.0f);
if(totspring && a>0) {
bs->v1= curindex-1;
bs->v2= curindex;
bs->strength= 1.0;
bs++;
}
}
}
}
}
if(totspring)
build_bps_springlist(ob); /* link bps to springs */
}
/* copies softbody result back in object */
static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts)
@@ -1288,13 +1369,17 @@ void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts
{
switch(ob->type) {
case OB_MESH:
mesh_to_softbody(ob,&rcs);
mesh_to_softbody(ob, &rcs);
break;
case OB_LATTICE:
lattice_to_softbody(ob,&rcs);
lattice_to_softbody(ob, &rcs);
break;
case OB_CURVE:
case OB_SURF:
curve_surf_to_softbody(ob, &rcs);
break;
default:
renew_softbody(ob, numVerts, 0,&rcs);
renew_softbody(ob, numVerts, 0, &rcs);
break;
}

View File

@@ -75,8 +75,7 @@ typedef struct BevPoint {
/* note; alfa location in struct is abused by Key system */
typedef struct BezTriple {
float vec[3][3];
float alfa;
short s[3][2]; /* screen coordinates */
float alfa, weight, pad;
short h1, h2;
char f1, f2, f3, hide;
} BezTriple;
@@ -84,8 +83,7 @@ typedef struct BezTriple {
/* note; alfa location in struct is abused by Key system */
typedef struct BPoint {
float vec[4];
float alfa;
short s[2];
float alfa, weight;
short f1, hide;
} BPoint;

View File

@@ -1907,12 +1907,14 @@ static void object_softbodies(Object *ob)
uiBlockEndAlign(block);
/* EDGE SPRING STUFF */
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, OB_SB_EDGES, B_SOFTBODY_CHANGE, "Use Edges", 10,30,150,20, &ob->softflag, 0, 0, 0, 0, "Use Edges as springs");
uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads", 160,30,150,20, &ob->softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons");
uiDefButF(block, NUM, B_DIFF, "E Stiff:", 10,10,150,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness");
uiDefButF(block, NUM, B_DIFF, "E Damp:", 160,10,150,20, &sb->infrict, 0.0, 10.0, 10, 0, "Edge spring friction");
uiBlockEndAlign(block);
if(ob->type!=OB_SURF) {
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, OB_SB_EDGES, B_SOFTBODY_CHANGE, "Use Edges", 10,30,150,20, &ob->softflag, 0, 0, 0, 0, "Use Edges as springs");
uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads", 160,30,150,20, &ob->softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons");
uiDefButF(block, NUM, B_DIFF, "E Stiff:", 10,10,150,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness");
uiDefButF(block, NUM, B_DIFF, "E Damp:", 160,10,150,20, &sb->infrict, 0.0, 10.0, 10, 0, "Edge spring friction");
uiBlockEndAlign(block);
}
}
}
uiBlockEndAlign(block);

View File

@@ -1004,40 +1004,6 @@ static void draw_ipobuts(SpaceIpo *sipo)
uiDrawBlock(block);
}
static void calc_ipoverts(SpaceIpo *sipo)
{
View2D *v2d= &sipo->v2d;
EditIpo *ei;
BezTriple *bezt;
BPoint *bp;
int a, b;
ei= G.sipo->editipo;
for(a=0; a<sipo->totipo; a++, ei++) {
if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
if(ei->icu->bezt) {
bezt= ei->icu->bezt;
b= ei->icu->totvert;
while(b--) {
ipoco_to_areaco(v2d, bezt->vec[0], bezt->s[0]);
ipoco_to_areaco(v2d, bezt->vec[1], bezt->s[1]);
ipoco_to_areaco(v2d, bezt->vec[2], bezt->s[2]);
bezt++;
}
}
else if(ei->icu->bp) {
bp= ei->icu->bp;
b= ei->icu->totvert;
while(b--) {
ipoco_to_areaco(v2d, bp->vec, bp->s);
bp++;
}
}
}
}
}
static void draw_ipovertices(int sel)
{
EditIpo *ei;
@@ -2022,8 +1988,6 @@ void drawipospace(ScrArea *sa, void *spacedata)
calc_ipogrid();
draw_ipogrid();
calc_ipoverts(sipo);
draw_cfra(sipo);
/* ipokeys */

View File

@@ -1184,7 +1184,7 @@ static void load_bgpic_image(char *name)
/* this one assumes there is only one global active object in blender... (for object panel) */
static float ob_eul[4]; // used for quat too....
/* this one assumes there is only one editmode in blender... (for object panel) */
static float ve_median[4];
static float ve_median[5];
/* is used for both read and write... */
static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
@@ -1194,12 +1194,12 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
EditMesh *em = G.editMesh;
EditVert *eve, *evedef=NULL;
EditEdge *eed;
float median[4];
int tot, totw, totedge;
float median[5];
int tot, totw, totweight, totedge;
char defstr[320];
median[0]= median[1]= median[2]= median[3]= 0.0;
tot= totw= totedge= 0;
median[0]= median[1]= median[2]= median[3]= median[4]= 0.0;
tot= totw= totweight= totedge= 0;
defstr[0]= 0;
if(ob->type==OB_MESH) {
@@ -1259,6 +1259,8 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
if(bezt->f2 & 1) {
VecAddf(median, median, bezt->vec[1]);
tot++;
median[4]+= bezt->weight;
totweight++;
}
else {
if(bezt->f1 & 1) {
@@ -1282,6 +1284,8 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
median[3]+= bp->vec[3];
totw++;
tot++;
median[4]+= bp->weight;
totweight++;
}
bp++;
}
@@ -1298,9 +1302,9 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
while(a--) {
if(bp->f1 & SELECT) {
VecAddf(median, median, bp->vec);
median[3]+= bp->vec[3];
tot++;
totw++;
median[4]+= bp->weight;
totweight++;
}
bp++;
}
@@ -1312,51 +1316,51 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
median[1] /= (float)tot;
median[2] /= (float)tot;
if(totedge) median[3] /= (float)totedge;
else median[3] /= (float)tot;
else if(totw) median[3] /= (float)totw;
if(totweight) median[4] /= (float)totweight;
if(G.vd->flag & V3D_GLOBAL_STATS)
Mat4MulVecfl(ob->obmat, median);
if(block) { // buttons
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Global", 160, 150, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays global values");
uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, REDRAWVIEW3D, "Local", 230, 150, 70, 19, &G.vd->flag, 0, 0, 0, 0, "Displays local values");
QUATCOPY(ve_median, median);
memcpy(ve_median, median, sizeof(ve_median));
uiBlockBeginAlign(block);
if(tot==1) {
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex X:", 10, 110, 290, 19, &(ve_median[0]), -lim, lim, 10, 3, "");
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Y:", 10, 90, 290, 19, &(ve_median[1]), -lim, lim, 10, 3, "");
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex Z:", 10, 70, 290, 19, &(ve_median[2]), -lim, lim, 10, 3, "");
if(totw==1) {
if(ob->type==OB_LATTICE)
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex W:", 10, 50, 290, 19, &(ve_median[3]), 0.0, 1.0, 10, 3, "");
else
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex W:", 10, 50, 290, 19, &(ve_median[3]), 0.01, 100.0, 10, 3, "");
}
if(totw==1)
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Vertex W:", 10, 50, 290, 19, &(ve_median[3]), 0.01, 100.0, 10, 3, "");
uiBlockEndAlign(block);
if(defstr[0]) {
uiDefBut(block, LABEL, 1, "Vertex Deform Groups", 10, 40, 290, 20, NULL, 0.0, 0.0, 0, 0, "");
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_NOP, "Weight:", 10, 20, 150, 19, defweightp, 0.0f, 1.0f, 10, 3, "Weight value");
uiDefButI(block, MENU, REDRAWVIEW3D, defstr, 160, 20, 140, 19, &curdef, 0.0, 0.0, 0, 0, "Current Vertex Group");
uiBlockEndAlign(block);
}
else if(totweight)
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 10, 20, 290, 19, &(ve_median[4]), 0.0, 1.0, 10, 3, "");
}
else {
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median X:", 10, 110, 290, 19, &(ve_median[0]), -lim, lim, 10, 3, "");
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Y:", 10, 90, 290, 19, &(ve_median[1]), -lim, lim, 10, 3, "");
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Z:", 10, 70, 290, 19, &(ve_median[2]), -lim, lim, 10, 3, "");
if(totw==tot) {
if(ob->type==OB_LATTICE)
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median W:", 10, 50, 290, 19, &(ve_median[3]), 0.0, 1.0, 10, 3, "");
else
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median W:", 10, 50, 290, 19, &(ve_median[3]), 0.01, 100.0, 10, 3, "");
}
if(totw==tot)
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median W:", 10, 50, 290, 19, &(ve_median[3]), 0.01, 100.0, 10, 3, "");
uiBlockEndAlign(block);
if(totweight)
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:", 10, 20, 290, 19, &(ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
}
uiBlockEndAlign(block);
if(totedge==1)
uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease W:", 10, 30, 290, 19, &(ve_median[3]), 0.0, 1.0, 10, 3, "");
@@ -1373,6 +1377,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
}
VecSubf(median, ve_median, median);
median[3]= ve_median[3]-median[3];
median[4]= ve_median[4]-median[4];
if(ob->type==OB_MESH) {
float diffac= 1.0;
@@ -1429,6 +1434,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
VecAddf(bezt->vec[0], bezt->vec[0], median);
VecAddf(bezt->vec[1], bezt->vec[1], median);
VecAddf(bezt->vec[2], bezt->vec[2], median);
bezt->weight+= median[4];
}
else {
if(bezt->f1 & 1) {
@@ -1448,6 +1454,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
if(bp->f1 & 1) {
VecAddf(bp->vec, bp->vec, median);
bp->vec[3]+= median[3];
bp->weight+= median[4];
}
bp++;
}
@@ -1467,7 +1474,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
while(a--) {
if(bp->f1 & SELECT) {
VecAddf(bp->vec, bp->vec, median);
bp->vec[3]+= median[3];
bp->weight+= median[4];
}
bp++;
}

View File

@@ -1241,7 +1241,7 @@ static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
EditIpo *ei;
BezTriple *bezt1;
int dist= 100, temp, a, b;
short mval[2], hpoint=0;
short mval[2], hpoint=0, sco[3][2];
*icu= 0;
*bezt= 0;
@@ -1257,14 +1257,14 @@ static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
b= ei->icu->totvert;
while(b--) {
ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], bezt1->s[0]);
ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], bezt1->s[1]);
ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], bezt1->s[2]);
ipoco_to_areaco_noclip(G.v2d, bezt1->vec[0], sco[0]);
ipoco_to_areaco_noclip(G.v2d, bezt1->vec[1], sco[1]);
ipoco_to_areaco_noclip(G.v2d, bezt1->vec[2], sco[2]);
if(ei->disptype==IPO_DISPBITS) {
temp= abs(mval[0]- bezt1->s[1][0]);
temp= abs(mval[0]- sco[1][0]);
}
else temp= abs(mval[0]- bezt1->s[1][0])+ abs(mval[1]- bezt1->s[1][1]);
else temp= abs(mval[0]- sco[1][0])+ abs(mval[1]- sco[1][1]);
if( bezt1->f2 & 1) temp+=5;
if(temp<dist) {
@@ -1276,7 +1276,7 @@ static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
if(ei->disptype!=IPO_DISPBITS && ei->icu->ipo==IPO_BEZ) {
/* middle points get an advantage */
temp= -3+abs(mval[0]- bezt1->s[0][0])+ abs(mval[1]- bezt1->s[0][1]);
temp= -3+abs(mval[0]- sco[0][0])+ abs(mval[1]- sco[0][1]);
if( bezt1->f1 & 1) temp+=5;
if(temp<dist) {
hpoint= 0;
@@ -1285,7 +1285,7 @@ static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
*icu= ei->icu;
}
temp= abs(mval[0]- bezt1->s[2][0])+ abs(mval[1]- bezt1->s[2][1]);
temp= abs(mval[0]- sco[2][0])+ abs(mval[1]- sco[2][1]);
if( bezt1->f3 & 1) temp+=5;
if(temp<dist) {
hpoint= 2;

View File

@@ -2138,7 +2138,7 @@ void special_editmenu(void)
}
else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2");
nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2|Set Goal Weight %x3");
switch(nr) {
case 1:
@@ -2147,6 +2147,33 @@ void special_editmenu(void)
case 2:
switchdirectionNurb2();
break;
case 3:
{
static float weight= 1.0f;
extern ListBase editNurb;
Nurb *nu;
BezTriple *bezt;
BPoint *bp;
int a;
if(fbutton(&weight, 0.0f, 1.0f, 10, 10, "Set Weight")) {
for(nu= editNurb.first; nu; nu= nu->next) {
if(nu->bezt) {
for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++) {
if(bezt->f2 & SELECT)
bezt->weight= weight;
}
}
else if(nu->bp) {
for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
if(bp->f1 & SELECT)
bp->weight= weight;
}
}
}
}
}
break;
}
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
@@ -2166,7 +2193,7 @@ void special_editmenu(void)
while(a--) {
if(bp->f1 & SELECT)
bp->vec[3]= weight;
bp->weight= weight;
bp++;
}
}