Use curve radius for paths

- use_radius option, off by default for 2.4x files, on by default on new curves.
- curve deform modifiers (think tentacles)
- follow path (parent mode and constraint)
- curve guides
- added back Alt+S to scale point radius
- Mat3Scale and Mat4Scale arithb.c functions to make a new uniform scale matrix.

- TODO, effectors, looks like they have no way to scale from the radius yet.
This commit is contained in:
Campbell Barton 2009-09-12 16:25:49 +00:00
parent d16bde417f
commit f130f16fef
15 changed files with 99 additions and 30 deletions

View File

@ -142,6 +142,7 @@ class DATA_PT_pathanim(DataButtonsPanelCurve):
col = split.column()
col.itemR(curve, "use_stretch")
col.itemR(curve, "use_radius")
col.itemR(curve, "use_time_offset", text="Offset Children")
class DATA_PT_active_spline(DataButtonsPanelActive):

View File

@ -124,11 +124,12 @@ class ConstraintButtonsPanel(bpy.types.Panel):
split = layout.split()
col = split.column()
col.itemR(con, "curve_follow")
col.itemR(con, "use_curve_follow")
col.itemR(con, "use_curve_radius")
col = split.column()
col.itemR(con, "fixed_position")
if con.fixed_position:
col.itemR(con, "use_fixed_position")
if con.use_fixed_position:
col.itemR(con, "offset_percentage", text="Offset")
else:
col.itemR(con, "offset")

View File

@ -1162,7 +1162,7 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
if (VALID_CONS_TARGET(ct)) {
Curve *cu= ct->tar->data;
float q[4], vec[4], dir[3], quat[4], x1;
float q[4], vec[4], dir[3], quat[4], radius, x1;
float totmat[4][4];
float curvetime;
@ -1196,7 +1196,7 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
curvetime= data->offset; // XXX might need a more sensible value
}
if ( where_on_path(ct->tar, curvetime, vec, dir, NULL, NULL) ) {
if ( where_on_path(ct->tar, curvetime, vec, dir, NULL, &radius) ) {
if (data->followflag & FOLLOWPATH_FOLLOW) {
vectoquat(dir, (short) data->trackflag, (short) data->upflag, quat);
@ -1210,6 +1210,14 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr
QuatToMat4(quat, totmat);
}
if (data->followflag & FOLLOWPATH_RADIUS) {
float tmat[4][4], rmat[4][4];
Mat4Scale(tmat, radius);
Mat4MulMat4(rmat, totmat, tmat);
Mat4CpyMat4(totmat, rmat);
}
VECCOPY(totmat[3], vec);
Mat4MulSerie(ct->matrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
@ -1227,7 +1235,8 @@ static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
/* only evaluate if there is a target */
if (VALID_CONS_TARGET(ct)) {
float obmat[4][4];
float size[3], obsize[3];
float size[3];
bFollowPathConstraint *data= con->data;
/* get Object local transform (loc/rot/size) to determine transformation from path */
//object_to_mat4(ob, obmat);
@ -1240,13 +1249,17 @@ static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase
Mat4MulSerie(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
/* un-apply scaling caused by path */
Mat4ToSize(cob->matrix, obsize);
if (obsize[0])
VecMulf(cob->matrix[0], size[0] / obsize[0]);
if (obsize[1])
VecMulf(cob->matrix[1], size[1] / obsize[1]);
if (obsize[2])
VecMulf(cob->matrix[2], size[2] / obsize[2]);
if ((data->followflag & FOLLOWPATH_RADIUS)==0) { /* XXX - assume that scale correction means that radius will have some scale error in it - Campbell */
float obsize[3];
Mat4ToSize(cob->matrix, obsize);
if (obsize[0])
VecMulf(cob->matrix[0], size[0] / obsize[0]);
if (obsize[1])
VecMulf(cob->matrix[1], size[1] / obsize[1]);
if (obsize[2])
VecMulf(cob->matrix[2], size[2] / obsize[2]);
}
}
}

View File

@ -136,7 +136,7 @@ Curve *add_curve(char *name, int type)
cu= alloc_libblock(&G.main->curve, ID_CU, name);
cu->size[0]= cu->size[1]= cu->size[2]= 1.0;
cu->flag= CU_FRONT+CU_BACK;
cu->flag= CU_FRONT|CU_BACK|CU_PATH_RADIUS;
cu->pathlen= 100;
cu->resolu= cu->resolv= 12;
cu->width= 1.0;

View File

@ -524,7 +524,7 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir,
static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, CurveDeform *cd, float *quatp)
{
Curve *cu= par->data;
float fac, loc[4], dir[3], cent[3];
float fac, loc[4], dir[3], cent[3], radius;
short upflag, index;
if(axis==MOD_CURVE_POSX || axis==MOD_CURVE_NEGX) {
@ -579,7 +579,7 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C
}
#endif // XXX old animation system
if( where_on_path_deform(par, fac, loc, dir, NULL, NULL)) { /* returns OK */
if( where_on_path_deform(par, fac, loc, dir, NULL, &radius)) { /* returns OK */
float q[4], mat[3][3], quat[4];
if(cd->no_rot_axis) /* set by caller */
@ -599,7 +599,14 @@ static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, C
QuatMul(quat, q, quat);
}
QuatToMat3(quat, mat);
if(cu->flag & CU_PATH_RADIUS) {
float tmat[3][3], rmat[3][3];
Mat3Scale(tmat, radius);
Mat3MulMat3(rmat, mat, tmat);
Mat3CpyMat3(mat, rmat);
}
/* local rotation */
Mat3MulVecfl(mat, cent);

View File

@ -1646,7 +1646,7 @@ int enable_cu_speed= 1;
static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
{
Curve *cu;
float q[4], vec[4], dir[3], quat[4], x1, ctime;
float q[4], vec[4], dir[3], quat[4], radius, x1, ctime;
float timeoffs = 0.0, sf_orig = 0.0;
Mat4One(mat);
@ -1694,7 +1694,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
/* vec: 4 items! */
if( where_on_path(par, ctime, vec, dir, NULL, NULL) ) {
if( where_on_path(par, ctime, vec, dir, NULL, &radius) ) {
if(cu->flag & CU_FOLLOW) {
vectoquat(dir, ob->trackflag, ob->upflag, quat);
@ -1711,6 +1711,13 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4])
QuatToMat4(quat, mat);
}
if(cu->flag & CU_PATH_RADIUS) {
float tmat[4][4], rmat[4][4];
Mat4Scale(tmat, radius);
Mat4MulMat4(rmat, mat, tmat);
Mat4CpyMat4(mat, rmat);
}
VECCOPY(mat[3], vec);
}

View File

@ -1932,7 +1932,7 @@ int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase
ParticleKey key, par;
float effect[3]={0.0,0.0,0.0}, distance, f_force, mindist, totforce=0.0;
float guidevec[4], guidedir[3], rot2[4], temp[3], angle, pa_loc[3], pa_zero[3]={0.0f,0.0f,0.0f};
float guidevec[4], guidedir[3], rot2[4], radius, temp[3], angle, pa_loc[3], pa_zero[3]={0.0f,0.0f,0.0f};
float veffect[3]={0.0,0.0,0.0}, guidetime;
effect[0]=effect[1]=effect[2]=0.0;
@ -1975,9 +1975,9 @@ int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase
}
if(pd->flag & PFIELD_GUIDE_PATH_ADD)
where_on_path(eob, f_force*guidetime, guidevec, guidedir, NULL, NULL);
where_on_path(eob, f_force*guidetime, guidevec, guidedir, NULL, &radius);
else
where_on_path(eob, guidetime, guidevec, guidedir, NULL, NULL);
where_on_path(eob, guidetime, guidevec, guidedir, NULL, &radius);
Mat4MulVecfl(ec->ob->obmat,guidevec);
Mat4Mul3Vecfl(ec->ob->obmat,guidedir);
@ -2007,10 +2007,12 @@ int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase
/* curve taper */
if(cu->taperobj)
VecMulf(pa_loc, calc_taper(scene, cu->taperobj, (int)(f_force*guidetime*100.0), 100));
/* TODO */
//else{
///* curve size*/
//}
else{ /* curve size*/
if(cu->flag & CU_PATH_RADIUS) {
VecMulf(pa_loc, radius);
}
}
par.co[0]=par.co[1]=par.co[2]=0.0f;
VECCOPY(key.co,pa_loc);
do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0);

View File

@ -2526,7 +2526,7 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa
ParticleSettings *part=psys->part;
PARTICLE_P;
int totpart;
float vec2[3],loc[3],*co=0;
float vec2[3],loc[3],radius,*co=0;
for(ec= lb->first; ec; ec= ec->next) {
PartDeflect *pd= ec->ob->pd;
@ -2536,7 +2536,7 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa
&& part->phystype!=PART_PHYS_BOIDS) {
float vec[4];
where_on_path(ec->ob, 0.0, vec, vec2, NULL, NULL);
where_on_path(ec->ob, 0.0, vec, vec2, NULL, &radius);
Mat4MulVecfl(ec->ob->obmat,vec);
Mat4Mul3Vecfl(ec->ob->obmat,vec2);
@ -2544,6 +2544,8 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa
QUATCOPY(ec->firstloc,vec);
VECCOPY(ec->firstdir,vec2);
/* TODO - use 'radius' to adjust the effector */
totpart=psys->totpart;
if(totpart){

View File

@ -320,6 +320,9 @@ void Mat3Clr(float *m);
void Mat3One(float m[][3]);
void Mat4One(float m[][4]);
void Mat3Scale(float m[][3], float scale);
void Mat4Scale(float m[][4], float scale);
void Mat3Ortho(float mat[][3]);
void Mat4Ortho(float mat[][4]);

View File

@ -854,6 +854,26 @@ void Mat3One(float m[][3])
m[2][0]= m[2][1]= 0.0;
}
void Mat4Scale(float m[][4], float scale)
{
m[0][0]= m[1][1]= m[2][2]= scale;
m[3][3]= 1.0;
m[0][1]= m[0][2]= m[0][3]= 0.0;
m[1][0]= m[1][2]= m[1][3]= 0.0;
m[2][0]= m[2][1]= m[2][3]= 0.0;
m[3][0]= m[3][1]= m[3][2]= 0.0;
}
void Mat3Scale(float m[][3], float scale)
{
m[0][0]= m[1][1]= m[2][2]= scale;
m[0][1]= m[0][2]= 0.0;
m[1][0]= m[1][2]= 0.0;
m[2][0]= m[2][1]= 0.0;
}
void Mat4MulVec( float mat[][4], int *vec)
{
int x,y;

View File

@ -234,6 +234,7 @@ void ED_keymap_curve(wmWindowManager *wm)
WM_keymap_add_item(keymap, "CURVE_OT_tilt_clear", TKEY, KM_PRESS, KM_ALT, 0);
RNA_enum_set(WM_keymap_add_item(keymap, "TFM_OT_transform", TKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", TFM_TILT);
RNA_enum_set(WM_keymap_add_item(keymap, "TFM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", TFM_CURVE_SHRINKFATTEN);
RNA_enum_set(WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", HKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", 1);
RNA_enum_set(WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", HKEY, KM_PRESS, 0, 0)->ptr, "type", 3);
RNA_enum_set(WM_keymap_add_item(keymap, "CURVE_OT_handle_type_set", VKEY, KM_PRESS, 0, 0)->ptr, "type", 2);

View File

@ -453,6 +453,7 @@ typedef enum B_CONSTRAINTCHANNEL_FLAG {
/* FollowPath flags */
#define FOLLOWPATH_FOLLOW 0x01
#define FOLLOWPATH_STATIC 0x02
#define FOLLOWPATH_RADIUS 0x04
/* bTrackToConstraint->flags */
#define TARGET_Z_UP 0x01

View File

@ -242,6 +242,7 @@ typedef struct Curve {
#define CU_FAST 512 /* Font: no filling inside editmode */
#define CU_RETOPO 1024
#define CU_DS_EXPAND 2048
#define CU_PATH_RADIUS 4096 /* make use of the path radius if this is enabled (default for new curves) */
/* twist mode */
#define CU_TWIST_Z_UP 0

View File

@ -893,16 +893,21 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Up Axis", "Axis that points upward.");
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
prop= RNA_def_property(srna, "curve_follow", PROP_BOOLEAN, PROP_NONE);
prop= RNA_def_property(srna, "use_curve_follow", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "followflag", FOLLOWPATH_FOLLOW);
RNA_def_property_ui_text(prop, "Follow Curve", "Object will follow the heading and banking of the curve.");
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
// TODO: do we need to do some special trickery to get offset sane for this?
prop= RNA_def_property(srna, "fixed_position", PROP_BOOLEAN, PROP_NONE);
prop= RNA_def_property(srna, "use_fixed_position", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "followflag", FOLLOWPATH_STATIC);
RNA_def_property_ui_text(prop, "Fixed Position", "Object will stay locked to a single point somewhere along the length of the curve regardless of time.");
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
prop= RNA_def_property(srna, "use_curve_radius", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "followflag", FOLLOWPATH_RADIUS);
RNA_def_property_ui_text(prop, "Curve Radius", "Objects scale by the curve radius.");
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_stretch_to(BlenderRNA *brna)

View File

@ -426,6 +426,11 @@ static void rna_def_path(BlenderRNA *brna, StructRNA *srna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_OFFS_PATHDIST);
RNA_def_property_ui_text(prop, "Offset Path Distance", "Children will use TimeOffs value as path distance offset.");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop= RNA_def_property(srna, "use_radius", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_PATH_RADIUS);
RNA_def_property_ui_text(prop, "Radius", "Option for paths: apply the curve radius with path following it and deforming.");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
}
static void rna_def_nurbs(BlenderRNA *brna, StructRNA *srna)