forked from bartvdbraak/blender
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:
parent
d16bde417f
commit
f130f16fef
@ -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):
|
||||
|
@ -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")
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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){
|
||||
|
@ -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]);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user