diff options
author | Ton Roosendaal <ton@blender.org> | 2004-11-11 16:17:32 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2004-11-11 16:17:32 +0300 |
commit | 2e4a10253b8f96b631eee8af5e1e711f372612ae (patch) | |
tree | f7ac4c363e22d2085397ca9410acdceb424c5476 | |
parent | 11fe49227b8b3dbcc6dbafbde16ee84c1a2e5af7 (diff) |
Fix for bug #1756
This was caused by a very primitive method of interpolating quaternions.
It was converting quats to mat and back to quat, and then just doing
a linear interpolation. That whilst quaternions are renowned for having
good interpolation possible.
I've experimented with 2 quaternion interpolation methods, and can only
get one to work correctly... the "official" version from Watt brothers
I can't get working, both are in arithb.c now.
Will arrange *close* review with experienced NLAers for it! But testing
here gives fully predictable results.
Also changed;
- added pointer check in drawaction
- changed puldown menu for correct hotkeys for move NLA strips up/down
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 32 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_arithb.h | 5 | ||||
-rw-r--r-- | source/blender/blenlib/intern/arithb.c | 86 | ||||
-rw-r--r-- | source/blender/src/drawaction.c | 17 | ||||
-rw-r--r-- | source/blender/src/header_nla.c | 4 |
5 files changed, 124 insertions, 20 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 673c5080f2e..1740fe70247 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -178,26 +178,38 @@ void blend_poses(bPose *dst, const bPose *src, float srcweight, short mode) * This sucks because it is slow and stupid */ - QuatToMat3(dchan->quat, mat); - Mat3ToQuat(mat, dquat); - QuatToMat3(schan->quat, mat); - Mat3ToQuat(mat, squat); + //QuatToMat3(dchan->quat, mat); + //Mat3ToQuat(mat, dquat); + //QuatToMat3(schan->quat, mat); + //Mat3ToQuat(mat, squat); + /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */ /* Do the transformation blend */ + if (schan->flag & POSE_ROT) { + QUATCOPY(dquat, dchan->quat); + QUATCOPY(squat, schan->quat); + if(mode==POSE_BLEND) + QuatInterpol(dchan->quat, dquat, squat, srcweight); + else + QuatAdd(dchan->quat, dquat, squat, srcweight); + NormalQuat (dchan->quat); + } + for (i=0; i<3; i++){ if (schan->flag & POSE_LOC) dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); if (schan->flag & POSE_SIZE) dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); - if (schan->flag & POSE_ROT) - dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight); + //if (schan->flag & POSE_ROT) + // dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight); } /* Do one more iteration for the quaternions only and normalize the quaternion if needed */ - if (schan->flag & POSE_ROT) - dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight); - if (mode==POSE_BLEND) - NormalQuat (dchan->quat); + //if (schan->flag & POSE_ROT) + // dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight); + //if (mode==POSE_BLEND) + // NormalQuat (dchan->quat); + dchan->flag |= schan->flag; } } diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 9935932ca31..77081f99246 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -178,6 +178,11 @@ QuatSub( float *q2 ); + +void QuatInterpol(float *result, float *quat1, float *quat2, float t); +void QuatAdd(float *result, float *quat1, float *quat2, float t); + + /** * @section matrix multiplication can copying routines */ diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 08a26821ccd..caa4771ff4b 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -1386,6 +1386,92 @@ void VecUpMat3(float *vec, float mat[][3], short axis) } +/* A & M Watt, Advanced animation and rendering techniques, 1992 ACM press */ + +void QuatInterpolW(float *result, float *quat1, float *quat2, float t) +{ + float omega, cosom, sinom, sc1, sc2; + + cosom = quat1[0]*quat2[0] + quat1[1]*quat2[1] + quat1[2]*quat2[2] + quat1[3]*quat2[3] ; + + /* rotate around shortest angle */ + if ((1.0 + cosom) > 0.0001) { + + if ((1.0 - cosom) > 0.0001) { + omega = acos(cosom); + sinom = sin(omega); + sc1 = sin((1.0 - t) * omega) / sinom; + sc2 = sin(t * omega) / sinom; + } + else { + sc1 = 1.0 - t; + sc2 = t; + } + result[0] = sc1*quat1[0] + sc2*quat2[0]; + result[1] = sc1*quat1[1] + sc2*quat2[1]; + result[2] = sc1*quat1[2] + sc2*quat2[2]; + result[3] = sc1*quat1[3] + sc2*quat2[3]; + } + else { + result[0] = quat2[3]; + result[1] = -quat2[2]; + result[2] = quat2[1]; + result[3] = -quat2[0]; + + sc1 = sin((1.0 - t)*M_PI_2); + sc2 = sin(t*M_PI_2); + + result[0] = sc1*quat1[0] + sc2*result[0]; + result[1] = sc1*quat1[1] + sc2*result[1]; + result[2] = sc1*quat1[2] + sc2*result[2]; + result[3] = sc1*quat1[3] + sc2*result[3]; + } +} + +void QuatInterpol(float *result, float *quat1, float *quat2, float t) +{ + float quat[4], omega, cosom, sinom, sc1, sc2; + + cosom = quat1[0]*quat2[0] + quat1[1]*quat2[1] + quat1[2]*quat2[2] + quat1[3]*quat2[3] ; + + /* rotate around shortest angle */ + if (cosom < 0.0) { + cosom = -cosom; + quat[0]= -quat1[0]; + quat[1]= -quat1[1]; + quat[2]= -quat1[2]; + quat[3]= -quat1[3]; + } + else { + quat[0]= quat1[0]; + quat[1]= quat1[1]; + quat[2]= quat1[2]; + quat[3]= quat1[3]; + } + + if ((1.0 - cosom) > 0.0001) { + omega = acos(cosom); + sinom = sin(omega); + sc1 = sin((1 - t) * omega) / sinom; + sc2 = sin(t * omega) / sinom; + } else { + sc1= 1.0 - t; + sc2= t; + } + + result[0] = sc1 * quat[0] + sc2 * quat2[0]; + result[1] = sc1 * quat[1] + sc2 * quat2[1]; + result[2] = sc1 * quat[2] + sc2 * quat2[2]; + result[3] = sc1 * quat[3] + sc2 * quat2[3]; +} + +void QuatAdd(float *result, float *quat1, float *quat2, float t) +{ + result[0]= quat1[0] + t*quat2[0]; + result[1]= quat1[1] + t*quat2[1]; + result[2]= quat1[2] + t*quat2[2]; + result[3]= quat1[3] + t*quat2[3]; +} /* **************** VIEW / PROJECTION ******************************** */ diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 402f7684215..278be07b65b 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -877,15 +877,16 @@ static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert) /* Count required keys */ for (achan=act->chanbase.first; achan; achan=achan->next){ /* Count transformation keys */ - for (icu=achan->ipo->curve.first; icu; icu=icu->next) - count+=icu->totvert; - - /* Count constraint keys */ - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) - for (icu=conchan->ipo->curve.first; icu; icu=icu->next) + if(achan->ipo) { + for (icu=achan->ipo->curve.first; icu; icu=icu->next) count+=icu->totvert; - - + + /* Count constraint keys */ + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) + for (icu=conchan->ipo->curve.first; icu; icu=icu->next) + count+=icu->totvert; + + } } /* Build the list */ diff --git a/source/blender/src/header_nla.c b/source/blender/src/header_nla.c index 332c0bece86..cdf2763eeab 100644 --- a/source/blender/src/header_nla.c +++ b/source/blender/src/header_nla.c @@ -289,8 +289,8 @@ static uiBlock *nla_stripmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Up|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Down|NumPad +", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Up|Page Down", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Move Down|Page Up", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); // uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Convert Action to NLA Strip|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); |