Softbody:

- Added browsing for vertex group for "Goal" in SoftBody buttons.
- Means the default name "SOFTGOAL" isn't needed anymore
- temporally, on file read, the "SOFTGOAL" vertex group is set, if exists
- removing vertex group possible too
- changed softbody.c code to use this
This commit is contained in:
Ton Roosendaal 2005-04-16 14:01:49 +00:00
parent 097726eb50
commit 7943f7990e
6 changed files with 128 additions and 94 deletions

@ -90,8 +90,6 @@ extern int get_defgroup_num (Object *ob, bDeformGroup *dg);
float SoftHeunTol = 1.0f; // humm .. this should be calculated from sb parameters and sizes
/* local prototypes */
//static void softbody_scale_time(float steptime);
static int get_scalar_from_named_vertexgroup(Object *ob, char *name, int vertID, float *target);
static void free_softbody_intern(SoftBody *sb);
@ -321,7 +319,7 @@ static int sb_deflect_particle(Object *ob,float *actpos, float *futurepos,float
}
#if 0
static int sb_deflect_test(float *actpos, float *futurepos,float *collisionpos, float *facenormal,float *slip ,float *bounce)
{
@ -465,7 +463,7 @@ static int sb_deflect_test(float *actpos, float *futurepos,float *collisionpos,
return 0;
}
#endif
@ -728,7 +726,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
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 ( ... )' operator denotes derivate respective time */
/* the euler step for velocity then becomes */
/* v(t + dt) = v(t) + a(t) * dt */
bp->force[0]*= timeovermass; /* individual mass of node here */
@ -1018,37 +1016,29 @@ static void mesh_update_softbody(Object *ob)
}
static int get_scalar_from_named_vertexgroup(Object *ob, char *name, int vertID, float *target)
static void get_scalar_from_vertexgroup(Object *ob, int vertID, short groupindex, 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*
*/
{
bDeformGroup *locGroup = NULL;
MDeformVert *dv;
int i, groupindex;
int i;
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 */
/* spot the vert in deform vert list at mesh */
if(ob->type==OB_MESH) {
if (((Mesh *)ob->data)->dvert) {
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;
break;
}
}
}
return 2;
}/*if(locGroup)*/
return 1;
}
}
/* makes totally fresh start situation */
@ -1078,38 +1068,26 @@ static void mesh_to_softbody(Object *ob)
set_body_point(ob, bp, mvert->co);
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;
/* 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
*/
if(sb->vertgroup) {
get_scalar_from_vertexgroup(ob, me->totvert - a, sb->vertgroup-1, &bp->goal);
// do this always, regardless successfull read from vertex group
bp->goal= sb->mingoal + bp->goal*goalfac;
}
/* a little ad hoc changing the goal control to be less *sharp* */
bp->goal = (float)pow(bp->goal, 4.0f);
error = get_scalar_from_named_vertexgroup(ob, name, me->totvert - a, &temp);
if (!error) {
bp->goal = temp;
/* works assuming goal is <0.0, 1.0> */
bp->goal= sb->mingoal + bp->goal*goalfac;
}
/* 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 */
/* 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;
*/
}
/* but we only optionally add body edge springs */

@ -110,6 +110,7 @@
#include "BKE_action.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_deform.h"
#include "BKE_effect.h" // for give_parteff
#include "BKE_global.h" // for G
#include "BKE_property.h" // for get_property
@ -4681,6 +4682,13 @@ static void do_versions(Main *main)
ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
}
if(ob->soft && ob->soft->vertgroup==0) {
bDeformGroup *locGroup = get_named_vertexgroup(ob, "SOFTGOAL");
if(locGroup){
/* retrieve index for that group */
ob->soft->vertgroup = 1 + get_defgroup_num(ob, locGroup);
}
}
}
}

@ -35,6 +35,7 @@
/* all internal calls and event codes for buttons space */
struct Base;
struct Object;
struct ID;
@ -76,6 +77,7 @@ extern void do_fontbuts(unsigned short event);
extern void do_mballbuts(unsigned short event);
extern void do_latticebuts(unsigned short event);
extern void do_fpaintbuts(unsigned short event);
extern char *get_vertexgroup_menustr(struct Object *ob); // used in object buttons
/* shading */
extern void material_panels(void);
@ -219,6 +221,7 @@ void test_idbutton_cb(void *namev, void *arg2_unused);
#define B_CURVECHECK 1416
#define B_SOFTBODY_CHANGE 1420
#define B_SOFTBODY_DEL_VG 1421
/* this has MAX_EFFECT settings! Next free define is 1450... */
#define B_SELEFFECT 1430

@ -121,6 +121,8 @@ typedef struct SoftBody {
float goalfrict; /* softbody goal springs friction */
float mingoal; /* quick limits for goal */
float maxgoal;
short vertgroup; /* index starting at 1 */
short pad1, pad2, pad3;
float inspring; /* softbody inner springs */
float infrict; /* softbody inner springs friction */

@ -2165,6 +2165,49 @@ static void editing_panel_mesh_tools1(Object *ob, Mesh *me)
}
char *get_vertexgroup_menustr(Object *ob)
{
bDeformGroup *dg;
int defCount, min, index;
char (*qsort_ptr)[32] = NULL;
char *s, *menustr;
defCount=BLI_countlist(&ob->defbase);
if (!defCount) min=0;
else min=1;
if (defCount > 0) {
/*
* This will hold the group names temporarily
* so we can sort them
*/
qsort_ptr = MEM_callocN (defCount * sizeof (qsort_ptr[0]),
"qsort_ptr");
for (index = 1, dg = ob->defbase.first; dg; index++, dg=dg->next) {
snprintf (qsort_ptr[index - 1], sizeof (qsort_ptr[0]),
"%s%%x%d|", dg->name, index);
}
qsort (qsort_ptr, defCount, sizeof (qsort_ptr[0]),
( int (*)(const void *, const void *) ) strcmp);
}
s= menustr = MEM_callocN((32 * defCount)+30, "menustr"); // plus 30 for when defCount==0
if(defCount) {
for (index = 0; index < defCount; index++) {
int cnt= sprintf (s, "%s", qsort_ptr[index]);
if (cnt>0) s+= cnt;
}
}
else strcpy(menustr, "No Vertex Groups in Object");
if (qsort_ptr)
MEM_freeN (qsort_ptr);
return menustr;
}
static void editing_panel_links(Object *ob)
{
uiBlock *block;
@ -2264,52 +2307,20 @@ static void editing_panel_links(Object *ob)
uiBut *but;
int defCount;
bDeformGroup *defGroup;
char *s, *menustr;
bDeformGroup *dg;
int min, index;
char (*qsort_ptr)[32] = NULL;
uiDefBut(block, LABEL,0,"Vertex Groups",
143,153,130,20, 0, 0, 0, 0, 0, "");
defCount=BLI_countlist(&ob->defbase);
if (!defCount) min=0;
else min=1;
if (defCount > 0) {
/*
* This will hold the group names temporarily
* so we can sort them
*/
qsort_ptr = MEM_callocN (defCount * sizeof (qsort_ptr[0]),
"qsort_ptr");
for (index = 1, dg = ob->defbase.first; dg; index++, dg=dg->next) {
snprintf (qsort_ptr[index - 1], sizeof (qsort_ptr[0]),
"%s%%x%d|", dg->name, index);
}
qsort (qsort_ptr, defCount, sizeof (qsort_ptr[0]),
( int (*)(const void *, const void *) ) strcmp);
}
s= menustr = MEM_callocN((32 * defCount)+20, "menustr");
for (index = 0; index < defCount; index++) {
int cnt= sprintf (s, "%s", qsort_ptr[index]);
if (cnt>0) s+= cnt;
}
if (qsort_ptr)
MEM_freeN (qsort_ptr);
uiBlockBeginAlign(block);
if (defCount)
uiDefButS(block, MENU, REDRAWBUTSEDIT, menustr,
143, 132,18,21, &ob->actdef, min, defCount, 0, 0,
"Browses available vertex groups");
MEM_freeN (menustr);
if (defCount) {
char *menustr= get_vertexgroup_menustr(ob);
uiDefButS(block, MENU, REDRAWBUTSEDIT, menustr, 143, 132,18,21, &ob->actdef, 1, defCount, 0, 0, "Browses available vertex groups");
MEM_freeN (menustr);
}
if (ob->actdef){
defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
but= uiDefBut(block, TEX,REDRAWBUTSEDIT,"", 161,132,140-18,21, defGroup->name, 0, 32, 0, 0, "Displays current vertex group name. Click to change. (Match bone name for deformation.)");

@ -1192,8 +1192,20 @@ void do_object_panels(unsigned short event)
case B_SOFTBODY_CHANGE:
ob= OBACT;
if(ob) ob->softflag |= OB_SB_REDO;
allqueue(REDRAWVIEW3D, 0);
if(ob) {
ob->softflag |= OB_SB_REDO;
allqueue(REDRAWBUTSOBJECT, 0);
allqueue(REDRAWVIEW3D, 0);
}
break;
case B_SOFTBODY_DEL_VG:
ob= OBACT;
if(ob && ob->soft) {
ob->soft->vertgroup= 0;
ob->softflag |= OB_SB_REDO;
allqueue(REDRAWBUTSOBJECT, 0);
allqueue(REDRAWVIEW3D, 0);
}
break;
default:
@ -1469,6 +1481,8 @@ static void object_softbodies(Object *ob)
if(ob->softflag & OB_SB_ENABLE) {
SoftBody *sb= ob->soft;
int defCount;
char *menustr;
if(sb==NULL) {
sb= ob->soft= sbNew();
@ -1491,8 +1505,26 @@ static void object_softbodies(Object *ob)
/* GOAL STUFF */
uiBlockBeginAlign(block);
uiDefButBitS(block, TOG, OB_SB_GOAL, B_DIFF, "Use Goal", 10,100,150,20, &ob->softflag, 0, 0, 0, 0, "Define forces for vertices to stick to animated position");
uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Goal:", 160,100,150,20, &sb->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
uiDefButBitS(block, TOG, OB_SB_GOAL, B_DIFF, "Use Goal", 10,100,130,20, &ob->softflag, 0, 0, 0, 0, "Define forces for vertices to stick to animated position");
menustr= get_vertexgroup_menustr(ob);
defCount=BLI_countlist(&ob->defbase);
if(defCount==0) sb->vertgroup= 0;
uiDefButS(block, MENU, B_SOFTBODY_CHANGE, menustr, 140,100,20,20, &sb->vertgroup, 0, defCount, 0, 0, "Browses available vertex groups");
if(sb->vertgroup) {
bDeformGroup *defGroup = BLI_findlink(&ob->defbase, sb->vertgroup-1);
if(defGroup)
uiDefBut(block, BUT, B_DIFF, defGroup->name, 160,100,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group");
else
uiDefBut(block, BUT, B_DIFF, "(no group)", 160,100,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore");
uiDefIconBut(block, BUT, B_SOFTBODY_DEL_VG, ICON_X, 290,100,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group");
}
else {
uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Goal:", 160,100,150,20, &sb->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
}
MEM_freeN (menustr);
uiDefButF(block, NUM, B_DIFF, "GSpring:", 10,80,150,20, &sb->goalspring, 0.0, 0.999, 10, 0, "Goal (vertex target position) Spring Constant");
uiDefButF(block, NUM, B_DIFF, "GFrict:", 160,80,150,20, &sb->goalfrict , 0.0, 10.0, 10, 0, "Goal (vertex target position) Friction Constant");
uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "GMin:", 10,60,150,20, &sb->mingoal, 0.0, 1.0, 10, 0, "Min Goal bound");