diff options
author | Ton Roosendaal <ton@blender.org> | 2005-11-16 01:39:20 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2005-11-16 01:39:20 +0300 |
commit | b474f95c84a91399ec28ebaaf05bbde88aa73c69 (patch) | |
tree | b6aeae105d2573cb8ac7e89fc86724daede91dbe /source | |
parent | a8df21833545d43128a0f56a03042294fbc77c85 (diff) |
Revision of NLA stride option.
Previously, using the "Stride Bone" tried to get that Bone motionless on
the path by correcting the internal time of the Action. This however caused
too many problems, especially with irregular walks.
The new system also tries to keep the Stride Bone motionless, but this by
moving the entire armature, and not changing the timing of the Action.
Give much nicer results. :)
To make editing Strides easier, I've added a new option in the NLA
panel to disable the path. This way you can quickly switch to editing the
action itself (keying the stride bone) and viewing the result.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_action.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 63 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 6 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_types.h | 2 | ||||
-rw-r--r-- | source/blender/src/drawnla.c | 20 |
6 files changed, 58 insertions, 38 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 996b033f3e9..b6e0aded1b8 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -133,7 +133,7 @@ struct bActionChannel *get_action_channel(struct bAction *act, const char *name struct bActionChannel *verify_action_channel(struct bAction *act, const char *name); /* exported for game engine */ -void blend_poses(struct bPose *dst, const struct bPose *src, float srcweight, short mode); +void blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode); void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); /* map global time (frame nr) to strip converted time, doesn't clip */ diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 03f5a9903ef..3074656d761 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -357,7 +357,7 @@ bActionChannel *verify_action_channel(bAction *act, const char *name) /* Only allowed for Poses with identical channels */ -void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode) +void blend_poses(bPose *dst, bPose *src, float srcweight, short mode) { bPoseChannel *dchan; const bPoseChannel *schan; @@ -407,6 +407,8 @@ void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode) dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight; } } + + VecLerpf(dst->stride_offset, dst->stride_offset, src->stride_offset, srcweight); } @@ -504,6 +506,10 @@ static void rest_pose(bPose *pose) if (!pose) return; + pose->stride_offset[0]= 0.0f; + pose->stride_offset[1]= 0.0f; + pose->stride_offset[2]= 0.0f; + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){ for (i=0; i<3; i++){ pchan->loc[i]=0.0; @@ -715,9 +721,12 @@ static float nla_time(float cfra, float unit) return cfra; } -static float stridechannel_frame(bAction *act, int stride_axis, char *name, float pdist) +static float stridechannel_frame(Object *ob, bActionStrip *strip, Path *path, float pathdist, float *stride_offset) { + bAction *act= strip->act; + char *name= strip->stridechannel; bActionChannel *achan= get_action_channel(act, name); + int stride_axis= strip->stride_axis; if(achan && achan->ipo) { IpoCurve *icu= NULL; @@ -745,29 +754,23 @@ static float stridechannel_frame(bAction *act, int stride_axis, char *name, floa if(foundvert && miny!=maxy) { float stridelen= fabs(maxy-miny), striptime; - float actiondist, step= 0.5, error, threshold=0.00001f*stridelen; - int max= 20; + float actiondist, pdist; + float vec1[4], vec2[4], dir[3]; /* amount path moves object */ - pdist = (float)fmod (pdist, stridelen); + pdist = (float)fmod (pathdist, stridelen); + striptime= pdist/stridelen; - /* wanted; the (0-1) factor that cancels out this distance, do simple newton-raphson */ - striptime= step; - do { - actiondist= eval_icu(icu, minx + striptime*(maxx-minx)) - miny; - - error= pdist - fabs(actiondist); - - step*=0.5f; - if(error > 0.0) - striptime += step; - else - striptime -= step; - - max--; - } - while( fabs(error) > threshold && max>0); + /* amount stride bone moves */ + actiondist= eval_icu(icu, minx + striptime*(maxx-minx)) - miny; + pdist = pdist - fabs(actiondist); + + /* now we need to go pdist further (or less) on cu path */ + where_on_path(ob, (pathdist)/path->totdist, vec1, dir); /* vec needs size 4 */ + where_on_path(ob, (pathdist+pdist)/path->totdist, vec2, dir); /* vec needs size 4 */ + VecSubf(stride_offset, vec1, vec2); + Mat4Mul3Vecfl(ob->obmat, stride_offset); return striptime; } } @@ -811,7 +814,7 @@ static void do_nla(Object *ob, int blocktype) rest_pose(tpose); /* Handle path */ - if (strip->flag & ACTSTRIP_USESTRIDE){ + if ((strip->flag & ACTSTRIP_USESTRIDE) && (blocktype==ID_AR) && (ob->ipoflag & OB_DISABLE_PATH)==0){ if (ob->parent && ob->parent->type==OB_CURVE){ Curve *cu = ob->parent->data; float ctime, pdist; @@ -830,8 +833,9 @@ static void do_nla(Object *ob, int blocktype) } pdist = ctime*cu->path->totdist; - if(strip->stridechannel[0]) - striptime= stridechannel_frame(strip->act, strip->stride_axis, strip->stridechannel, pdist); + if(tpose && strip->stridechannel[0]) { + striptime= stridechannel_frame(ob->parent, strip, cu->path, pdist, tpose->stride_offset); + } else { if (strip->stridelen) { striptime = pdist / strip->stridelen; @@ -844,8 +848,9 @@ static void do_nla(Object *ob, int blocktype) frametime = (striptime * actlength) + strip->actstart; frametime= bsystem_time(ob, 0, frametime, 0.0); - if(blocktype==ID_AR) + if(blocktype==ID_AR) { extract_pose_from_action (tpose, strip->act, frametime); + } else if(blocktype==ID_OB) { extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); if(key) @@ -921,7 +926,12 @@ static void do_nla(Object *ob, int blocktype) if(blocktype==ID_OB) { execute_ipochannels(&chanbase); } - + else if(blocktype==ID_AR) { + /* apply stride offset to object */ + VecAddf(ob->obmat[3], ob->obmat[3], ob->pose->stride_offset); + } + + /* free */ if (tpose){ free_pose_channels(tpose); MEM_freeN(tpose); @@ -929,7 +939,6 @@ static void do_nla(Object *ob, int blocktype) if(chanbase.first) BLI_freelistN(&chanbase); - } void do_all_pose_actions(Object *ob) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 8917178fea9..2b0920754cf 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1075,8 +1075,12 @@ void ob_parcurve(Object *ob, Object *par, float mat[][4]) SWAP(float, timeoffs, ob->sf); } + /* catch exceptions: feature for nla stride editing */ + if(ob->ipoflag & OB_DISABLE_PATH) { + ctime= 0.0f; + } /* catch exceptions: curve paths used as a duplicator */ - if(enable_cu_speed) { + else if(enable_cu_speed) { ctime= bsystem_time(ob, par, (float)G.scene->r.cfra, 0.0); if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 2f60045e9ea..db9926d4653 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -79,7 +79,8 @@ typedef struct bPoseChannel { typedef struct bPose{ ListBase chanbase; - int flag, pad; + int flag; + float stride_offset[3]; } bPose; typedef struct bActionChannel { diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 86bcbbf791a..4a9a4bf1784 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -282,6 +282,8 @@ extern Object workob; /* get ipo from from action or not? */ #define OB_ACTION_OB 256 #define OB_ACTION_KEY 512 + /* for stride edit */ +#define OB_DISABLE_PATH 1024 /* (short) trackflag / upflag */ #define OB_POSX 0 diff --git a/source/blender/src/drawnla.c b/source/blender/src/drawnla.c index 007238224de..2b0ba1a7ad3 100644 --- a/source/blender/src/drawnla.c +++ b/source/blender/src/drawnla.c @@ -398,15 +398,17 @@ static void draw_nla_strips_keys(SpaceNla *snla) #define B_NLA_LOCK 122 /* For now just returns the first selected strip */ -bActionStrip *get_active_nlastrip(void) +bActionStrip *get_active_nlastrip(Object **obpp) { Base *base; bActionStrip *strip; for (base=G.scene->base.first; base; base=base->next){ for (strip=base->object->nlastrips.first; strip; strip=strip->next){ - if (strip->flag & ACTSTRIP_SELECT) + if (strip->flag & ACTSTRIP_SELECT) { + *obpp= base->object; return strip; + } } } @@ -415,10 +417,11 @@ bActionStrip *get_active_nlastrip(void) void do_nlabuts(unsigned short event) { + Object *ob; bActionStrip *strip; /* Determine if an nla strip has been selected */ - strip = get_active_nlastrip(); + strip = get_active_nlastrip(&ob); if (!strip) return; switch(event) { @@ -427,8 +430,7 @@ void do_nlabuts(unsigned short event) allqueue(REDRAWNLA, 0); break; case B_NLA_PANEL: - - DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA); + DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA); allqueue (REDRAWNLA, 0); allqueue (REDRAWVIEW3D, 0); break; @@ -443,6 +445,7 @@ void do_nlabuts(unsigned short event) static void nla_panel_properties(short cntrl) // NLA_HANDLER_PROPERTIES { + Object *ob; bActionStrip *strip; uiBlock *block; @@ -452,7 +455,7 @@ static void nla_panel_properties(short cntrl) // NLA_HANDLER_PROPERTIES if(uiNewPanel(curarea, block, "Transform Properties", "NLA", 10, 230, 318, 204)==0) return; /* Determine if an nla strip has been selected */ - strip = get_active_nlastrip(); + strip = get_active_nlastrip(&ob); if (!strip) return; /* first labels, for simpler align code :) */ @@ -488,8 +491,9 @@ static void nla_panel_properties(short cntrl) // NLA_HANDLER_PROPERTIES uiDefButS(block, TOG, B_NLA_PANEL, "Add", 230,60,75,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode"); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_NLA_PANEL, "Use Path", 10,20,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride"); - uiDefButF(block, NUM, B_NLA_PANEL, "Stride:", 110,20,200,19, &strip->stridelen, 0.0001, 1000.0, 100, 0, "Distance covered by one complete cycle of the action specified in the Action Range"); + uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_NLA_PANEL, "Stride Path", 10,20,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride"); + uiDefButBitS(block, TOG, OB_DISABLE_PATH, B_NLA_PANEL, "Disable Path", 110,20,100,19, &ob->ipoflag, 0, 0, 0, 0, "Plays action based on path position & stride"); + uiDefButF(block, NUM, B_NLA_PANEL, "Stride:", 210,20,100,19, &strip->stridelen, 0.0001, 1000.0, 100, 0, "Distance covered by one complete cycle of the action specified in the Action Range"); uiDefButS(block, ROW, B_NLA_PANEL, "X", 10, 0, 33, 19, &strip->stride_axis, 1, 0, 0, 0, "Dominant axis for Stride Bone"); uiDefButS(block, ROW, B_NLA_PANEL, "Y", 43, 0, 33, 19, &strip->stride_axis, 1, 1, 0, 0, "Dominant axis for Stride Bone"); |