aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcharacter/llkeyframestandmotion.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llcharacter/llkeyframestandmotion.cpp')
-rw-r--r--linden/indra/llcharacter/llkeyframestandmotion.cpp339
1 files changed, 339 insertions, 0 deletions
diff --git a/linden/indra/llcharacter/llkeyframestandmotion.cpp b/linden/indra/llcharacter/llkeyframestandmotion.cpp
new file mode 100644
index 0000000..4fcb76c
--- /dev/null
+++ b/linden/indra/llcharacter/llkeyframestandmotion.cpp
@@ -0,0 +1,339 @@
1/**
2 * @file llkeyframestandmotion.cpp
3 * @brief Implementation of LLKeyframeStandMotion class.
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28//-----------------------------------------------------------------------------
29// Header Files
30//-----------------------------------------------------------------------------
31#include "linden_common.h"
32
33#include "llkeyframestandmotion.h"
34#include "llcharacter.h"
35
36//-----------------------------------------------------------------------------
37// Macros and consts
38//-----------------------------------------------------------------------------
39#define GO_TO_KEY_POSE 1
40#define MIN_TRACK_SPEED 0.01f
41const F32 ROTATION_THRESHOLD = 0.6f;
42const F32 POSITION_THRESHOLD = 0.1f;
43
44//-----------------------------------------------------------------------------
45// LLKeyframeStandMotion()
46// Class Constructor
47//-----------------------------------------------------------------------------
48LLKeyframeStandMotion::LLKeyframeStandMotion(const LLUUID &id) : LLKeyframeMotion(id)
49{
50 mFlipFeet = FALSE;
51 mCharacter = NULL;
52
53 // create kinematic hierarchy
54 mPelvisJoint.addChild( &mHipLeftJoint );
55 mHipLeftJoint.addChild( &mKneeLeftJoint );
56 mKneeLeftJoint.addChild( &mAnkleLeftJoint );
57 mPelvisJoint.addChild( &mHipRightJoint );
58 mHipRightJoint.addChild( &mKneeRightJoint );
59 mKneeRightJoint.addChild( &mAnkleRightJoint );
60
61 mPelvisState = NULL;
62
63 mHipLeftState = NULL;
64 mKneeLeftState = NULL;
65 mAnkleLeftState = NULL;
66
67 mHipRightState = NULL;
68 mKneeRightState = NULL;
69 mAnkleRightState = NULL;
70
71 mTrackAnkles = TRUE;
72
73 mFrameNum = 0;
74}
75
76
77//-----------------------------------------------------------------------------
78// ~LLKeyframeStandMotion()
79// Class Destructor
80//-----------------------------------------------------------------------------
81LLKeyframeStandMotion::~LLKeyframeStandMotion()
82{
83}
84
85
86//-----------------------------------------------------------------------------
87// LLKeyframeStandMotion::onInitialize()
88//-----------------------------------------------------------------------------
89LLMotion::LLMotionInitStatus LLKeyframeStandMotion::onInitialize(LLCharacter *character)
90{
91 // save character pointer for later use
92 mCharacter = character;
93
94 mFlipFeet = FALSE;
95
96 // load keyframe data, setup pose and joint states
97 LLMotion::LLMotionInitStatus status = LLKeyframeMotion::onInitialize(character);
98 if ( status == STATUS_FAILURE )
99 {
100 return status;
101 }
102
103 // find the necessary joint states
104 LLPose *pose = getPose();
105 mPelvisState = pose->findJointState("mPelvis");
106
107 mHipLeftState = pose->findJointState("mHipLeft");
108 mKneeLeftState = pose->findJointState("mKneeLeft");
109 mAnkleLeftState = pose->findJointState("mAnkleLeft");
110
111 mHipRightState = pose->findJointState("mHipRight");
112 mKneeRightState = pose->findJointState("mKneeRight");
113 mAnkleRightState = pose->findJointState("mAnkleRight");
114
115 if ( !mPelvisState ||
116 !mHipLeftState ||
117 !mKneeLeftState ||
118 !mAnkleLeftState ||
119 !mHipRightState ||
120 !mKneeRightState ||
121 !mAnkleRightState )
122 {
123 llinfos << getName() << ": Can't find necessary joint states" << llendl;
124 return STATUS_FAILURE;
125 }
126
127 return STATUS_SUCCESS;
128}
129
130//-----------------------------------------------------------------------------
131// LLKeyframeStandMotion::onActivate()
132//-----------------------------------------------------------------------------
133BOOL LLKeyframeStandMotion::onActivate()
134{
135 //-------------------------------------------------------------------------
136 // setup the IK solvers
137 //-------------------------------------------------------------------------
138 mIKLeft.setPoleVector( LLVector3(1.0f, 0.0f, 0.0f));
139 mIKRight.setPoleVector( LLVector3(1.0f, 0.0f, 0.0f));
140 mIKLeft.setBAxis( LLVector3(0.05f, 1.0f, 0.0f));
141 mIKRight.setBAxis( LLVector3(-0.05f, 1.0f, 0.0f));
142
143 mLastGoodPelvisRotation.loadIdentity();
144 mLastGoodPosition.clearVec();
145
146 mFrameNum = 0;
147
148 return LLKeyframeMotion::onActivate();
149}
150
151//-----------------------------------------------------------------------------
152// LLKeyframeStandMotion::onDeactivate()
153//-----------------------------------------------------------------------------
154void LLKeyframeStandMotion::onDeactivate()
155{
156 LLKeyframeMotion::onDeactivate();
157}
158
159//-----------------------------------------------------------------------------
160// LLKeyframeStandMotion::onUpdate()
161//-----------------------------------------------------------------------------
162BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask)
163{
164 //-------------------------------------------------------------------------
165 // let the base class update the cycle
166 //-------------------------------------------------------------------------
167 BOOL status = LLKeyframeMotion::onUpdate(time, joint_mask);
168 if (!status)
169 {
170 return FALSE;
171 }
172
173 LLVector3 root_world_pos = mPelvisState->getJoint()->getParent()->getWorldPosition();
174
175 // have we received a valid world position for this avatar?
176 if (root_world_pos.isExactlyZero())
177 {
178 return TRUE;
179 }
180
181 //-------------------------------------------------------------------------
182 // Stop tracking (start locking) ankles once ease in is done.
183 // Setting this here ensures we track until we get valid foot position.
184 //-------------------------------------------------------------------------
185 if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD)
186 {
187 mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation();
188 mLastGoodPelvisRotation.normQuat();
189 mTrackAnkles = TRUE;
190 }
191 else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD)
192 {
193 mLastGoodPosition = mCharacter->getCharacterPosition();
194 mTrackAnkles = TRUE;
195 }
196 else if (mPose.getWeight() < 1.f)
197 {
198 mTrackAnkles = TRUE;
199 }
200
201
202 //-------------------------------------------------------------------------
203 // propagate joint positions to internal versions
204 //-------------------------------------------------------------------------
205 mPelvisJoint.setPosition(
206 root_world_pos +
207 mPelvisState->getPosition() );
208
209 mHipLeftJoint.setPosition( mHipLeftState->getJoint()->getPosition() );
210 mKneeLeftJoint.setPosition( mKneeLeftState->getJoint()->getPosition() );
211 mAnkleLeftJoint.setPosition( mAnkleLeftState->getJoint()->getPosition() );
212
213 mHipLeftJoint.setScale( mHipLeftState->getJoint()->getScale() );
214 mKneeLeftJoint.setScale( mKneeLeftState->getJoint()->getScale() );
215 mAnkleLeftJoint.setScale( mAnkleLeftState->getJoint()->getScale() );
216
217 mHipRightJoint.setPosition( mHipRightState->getJoint()->getPosition() );
218 mKneeRightJoint.setPosition( mKneeRightState->getJoint()->getPosition() );
219 mAnkleRightJoint.setPosition( mAnkleRightState->getJoint()->getPosition() );
220
221 mHipRightJoint.setScale( mHipRightState->getJoint()->getScale() );
222 mKneeRightJoint.setScale( mKneeRightState->getJoint()->getScale() );
223 mAnkleRightJoint.setScale( mAnkleRightState->getJoint()->getScale() );
224 //-------------------------------------------------------------------------
225 // propagate joint rotations to internal versions
226 //-------------------------------------------------------------------------
227 mPelvisJoint.setRotation( mPelvisState->getJoint()->getWorldRotation() );
228
229#if GO_TO_KEY_POSE
230 mHipLeftJoint.setRotation( mHipLeftState->getRotation() );
231 mKneeLeftJoint.setRotation( mKneeLeftState->getRotation() );
232 mAnkleLeftJoint.setRotation( mAnkleLeftState->getRotation() );
233
234 mHipRightJoint.setRotation( mHipRightState->getRotation() );
235 mKneeRightJoint.setRotation( mKneeRightState->getRotation() );
236 mAnkleRightJoint.setRotation( mAnkleRightState->getRotation() );
237#else
238 mHipLeftJoint.setRotation( mHipLeftState->getJoint()->getRotation() );
239 mKneeLeftJoint.setRotation( mKneeLeftState->getJoint()->getRotation() );
240 mAnkleLeftJoint.setRotation( mAnkleLeftState->getJoint()->getRotation() );
241
242 mHipRightJoint.setRotation( mHipRightState->getJoint()->getRotation() );
243 mKneeRightJoint.setRotation( mKneeRightState->getJoint()->getRotation() );
244 mAnkleRightJoint.setRotation( mAnkleRightState->getJoint()->getRotation() );
245#endif
246
247 // need to wait for underlying keyframe motion to affect the skeleton
248 if (mFrameNum == 2)
249 {
250 mIKLeft.setupJoints( &mHipLeftJoint, &mKneeLeftJoint, &mAnkleLeftJoint, &mTargetLeft );
251 mIKRight.setupJoints( &mHipRightJoint, &mKneeRightJoint, &mAnkleRightJoint, &mTargetRight );
252 }
253 else if (mFrameNum < 2)
254 {
255 mFrameNum++;
256 return TRUE;
257 }
258
259 mFrameNum++;
260
261 //-------------------------------------------------------------------------
262 // compute target position by projecting ankles to the ground
263 //-------------------------------------------------------------------------
264 if ( mTrackAnkles )
265 {
266 mCharacter->getGround( mAnkleLeftJoint.getWorldPosition(), mPositionLeft, mNormalLeft);
267 mCharacter->getGround( mAnkleRightJoint.getWorldPosition(), mPositionRight, mNormalRight);
268
269 mTargetLeft.setPosition( mPositionLeft );
270 mTargetRight.setPosition( mPositionRight );
271 }
272
273 //-------------------------------------------------------------------------
274 // update solvers
275 //-------------------------------------------------------------------------
276 mIKLeft.solve();
277 mIKRight.solve();
278
279 //-------------------------------------------------------------------------
280 // make ankle rotation conform to the ground
281 //-------------------------------------------------------------------------
282 if ( mTrackAnkles )
283 {
284 LLVector4 dirLeft4 = mAnkleLeftJoint.getWorldMatrix().getFwdRow4();
285 LLVector4 dirRight4 = mAnkleRightJoint.getWorldMatrix().getFwdRow4();
286 LLVector3 dirLeft = vec4to3( dirLeft4 );
287 LLVector3 dirRight = vec4to3( dirRight4 );
288
289 LLVector3 up;
290 LLVector3 dir;
291 LLVector3 left;
292
293 up = mNormalLeft;
294 up.normVec();
295 if (mFlipFeet)
296 {
297 up *= -1.0f;
298 }
299 dir = dirLeft;
300 dir.normVec();
301 left = up % dir;
302 left.normVec();
303 dir = left % up;
304 mRotationLeft = LLQuaternion( dir, left, up );
305
306 up = mNormalRight;
307 up.normVec();
308 if (mFlipFeet)
309 {
310 up *= -1.0f;
311 }
312 dir = dirRight;
313 dir.normVec();
314 left = up % dir;
315 left.normVec();
316 dir = left % up;
317 mRotationRight = LLQuaternion( dir, left, up );
318 }
319 mAnkleLeftJoint.setWorldRotation( mRotationLeft );
320 mAnkleRightJoint.setWorldRotation( mRotationRight );
321
322 //-------------------------------------------------------------------------
323 // propagate joint rotations to joint states
324 //-------------------------------------------------------------------------
325 mHipLeftState->setRotation( mHipLeftJoint.getRotation() );
326 mKneeLeftState->setRotation( mKneeLeftJoint.getRotation() );
327 mAnkleLeftState->setRotation( mAnkleLeftJoint.getRotation() );
328
329 mHipRightState->setRotation( mHipRightJoint.getRotation() );
330 mKneeRightState->setRotation( mKneeRightJoint.getRotation() );
331 mAnkleRightState->setRotation( mAnkleRightJoint.getRotation() );
332
333 //llinfos << "Stand drift amount " << (mCharacter->getCharacterPosition() - mLastGoodPosition).magVec() << llendl;
334
335// llinfos << "DEBUG: " << speed << " : " << mTrackAnkles << llendl;
336 return TRUE;
337}
338
339// End