aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcharacter/llkeyframemotionparam.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llcharacter/llkeyframemotionparam.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llcharacter/llkeyframemotionparam.cpp')
-rw-r--r--linden/indra/llcharacter/llkeyframemotionparam.cpp461
1 files changed, 461 insertions, 0 deletions
diff --git a/linden/indra/llcharacter/llkeyframemotionparam.cpp b/linden/indra/llcharacter/llkeyframemotionparam.cpp
new file mode 100644
index 0000000..0bdc723
--- /dev/null
+++ b/linden/indra/llcharacter/llkeyframemotionparam.cpp
@@ -0,0 +1,461 @@
1/**
2 * @file llkeyframemotionparam.cpp
3 * @brief Implementation of LLKeyframeMotion 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 "llkeyframemotionparam.h"
34#include "llcharacter.h"
35#include "llmath.h"
36#include "m3math.h"
37#include "lldir.h"
38#include "llanimationstates.h"
39
40//-----------------------------------------------------------------------------
41//-----------------------------------------------------------------------------
42// LLKeyframeMotionParam class
43//-----------------------------------------------------------------------------
44//-----------------------------------------------------------------------------
45
46//-----------------------------------------------------------------------------
47// sortFunc()
48//-----------------------------------------------------------------------------
49BOOL LLKeyframeMotionParam::sortFunc(ParameterizedMotion *new_motion, ParameterizedMotion *tested_motion)
50{
51 return (new_motion->second < tested_motion->second);
52}
53
54//-----------------------------------------------------------------------------
55// LLKeyframeMotionParam()
56// Class Constructor
57//-----------------------------------------------------------------------------
58LLKeyframeMotionParam::LLKeyframeMotionParam( const LLUUID &id) : LLMotion(id)
59{
60 mJointStates = NULL;
61 mDefaultKeyframeMotion = NULL;
62 mCharacter = NULL;
63
64 mEaseInDuration = 0.f;
65 mEaseOutDuration = 0.f;
66 mDuration = 0.f;
67 mPriority = LLJoint::LOW_PRIORITY;
68}
69
70
71//-----------------------------------------------------------------------------
72// ~LLKeyframeMotionParam()
73// Class Destructor
74//-----------------------------------------------------------------------------
75LLKeyframeMotionParam::~LLKeyframeMotionParam()
76{
77 for (U32 i = 0; i < mParameterizedMotions.length(); i++)
78 {
79 LLLinkedList< ParameterizedMotion > *motionList = *mParameterizedMotions.getValueAt(i);
80 for (ParameterizedMotion* paramMotion = motionList->getFirstData(); paramMotion; paramMotion = motionList->getNextData())
81 {
82 delete paramMotion->first;
83 }
84 delete motionList;
85 }
86
87 mParameterizedMotions.removeAll();
88}
89
90//-----------------------------------------------------------------------------
91// LLKeyframeMotionParam::onInitialize(LLCharacter *character)
92//-----------------------------------------------------------------------------
93LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character)
94{
95 mCharacter = character;
96
97 if (!loadMotions())
98 {
99 return STATUS_FAILURE;
100 }
101
102 for (U32 i = 0; i < mParameterizedMotions.length(); i++)
103 {
104 LLLinkedList< ParameterizedMotion > *motionList = *mParameterizedMotions.getValueAt(i);
105 for (ParameterizedMotion* paramMotion = motionList->getFirstData(); paramMotion; paramMotion = motionList->getNextData())
106 {
107 paramMotion->first->onInitialize(character);
108
109 if (paramMotion->first->getDuration() > mEaseInDuration)
110 {
111 mEaseInDuration = paramMotion->first->getEaseInDuration();
112 }
113
114 if (paramMotion->first->getEaseOutDuration() > mEaseOutDuration)
115 {
116 mEaseOutDuration = paramMotion->first->getEaseOutDuration();
117 }
118
119 if (paramMotion->first->getDuration() > mDuration)
120 {
121 mDuration = paramMotion->first->getDuration();
122 }
123
124 if (paramMotion->first->getPriority() > mPriority)
125 {
126 mPriority = paramMotion->first->getPriority();
127 }
128
129 LLPose *pose = paramMotion->first->getPose();
130
131 mPoseBlender.addMotion(paramMotion->first);
132 for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState())
133 {
134 LLPose *blendedPose = mPoseBlender.getBlendedPose();
135 blendedPose->addJointState(jsp);
136 }
137 }
138 }
139
140 return STATUS_SUCCESS;
141}
142
143//-----------------------------------------------------------------------------
144// LLKeyframeMotionParam::onActivate()
145//-----------------------------------------------------------------------------
146BOOL LLKeyframeMotionParam::onActivate()
147{
148 for (U32 i = 0; i < mParameterizedMotions.length(); i++)
149 {
150 LLLinkedList< ParameterizedMotion > *motionList = *mParameterizedMotions.getValueAt(i);
151 for (ParameterizedMotion* paramMotion = motionList->getFirstData(); paramMotion; paramMotion = motionList->getNextData())
152 {
153 paramMotion->first->activate();
154 }
155 }
156 return TRUE;
157}
158
159
160//-----------------------------------------------------------------------------
161// LLKeyframeMotionParam::onUpdate()
162//-----------------------------------------------------------------------------
163BOOL LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask)
164{
165 F32 weightFactor = 1.f / (F32)mParameterizedMotions.length();
166 U32 i;
167
168 // zero out all pose weights
169 for (i = 0; i < mParameterizedMotions.length(); i++)
170 {
171 LLLinkedList< ParameterizedMotion > *motionList = *mParameterizedMotions.getValueAt(i);
172
173 for (ParameterizedMotion* paramMotion = motionList->getFirstData(); paramMotion; paramMotion = motionList->getNextData())
174 {
175// llinfos << "Weight for pose " << paramMotion->first->getName() << " is " << paramMotion->first->getPose()->getWeight() << llendl;
176 paramMotion->first->getPose()->setWeight(0.f);
177 }
178 }
179
180
181 for (i = 0; i < mParameterizedMotions.length(); i++)
182 {
183 LLLinkedList< ParameterizedMotion > *motionList = *mParameterizedMotions.getValueAt(i);
184 std::string *paramName = mParameterizedMotions.getIndexAt(i);
185 F32* paramValue = (F32 *)mCharacter->getAnimationData(*paramName);
186 ParameterizedMotion* firstMotion = NULL;
187 ParameterizedMotion* secondMotion = NULL;
188
189 for (ParameterizedMotion* paramMotion = motionList->getFirstData(); paramMotion; paramMotion = motionList->getNextData())
190 {
191 paramMotion->first->onUpdate(time, joint_mask);
192
193 F32 distToParam = paramMotion->second - *paramValue;
194
195 if ( distToParam <= 0.f)
196 {
197 // keep track of the motion closest to the parameter value
198 firstMotion = paramMotion;
199 }
200 else
201 {
202 // we've passed the parameter value
203 // so store the first motion we find as the second one we want to blend...
204 if (firstMotion && !secondMotion )
205 {
206 secondMotion = paramMotion;
207 }
208 //...or, if we've seen no other motion so far, make sure we blend to this only
209 else if (!firstMotion)
210 {
211 firstMotion = paramMotion;
212 secondMotion = paramMotion;
213 }
214 }
215 }
216
217 LLPose *firstPose;
218 LLPose *secondPose;
219
220 if (firstMotion)
221 firstPose = firstMotion->first->getPose();
222 else
223 firstPose = NULL;
224
225 if (secondMotion)
226 secondPose = secondMotion->first->getPose();
227 else
228 secondPose = NULL;
229
230 // now modify weight of the subanim (only if we are blending between two motions)
231 if (firstMotion && secondMotion)
232 {
233 if (firstMotion == secondMotion)
234 {
235 firstPose->setWeight(weightFactor);
236 }
237 else if (firstMotion->second == secondMotion->second)
238 {
239 firstPose->setWeight(0.5f * weightFactor);
240 secondPose->setWeight(0.5f * weightFactor);
241 }
242 else
243 {
244 F32 first_weight = 1.f -
245 ((llclamp(*paramValue - firstMotion->second, 0.f, (secondMotion->second - firstMotion->second))) /
246 (secondMotion->second - firstMotion->second));
247 first_weight = llclamp(first_weight, 0.f, 1.f);
248
249 F32 second_weight = 1.f - first_weight;
250
251 firstPose->setWeight(first_weight * weightFactor);
252 secondPose->setWeight(second_weight * weightFactor);
253
254// llinfos << "Parameter " << *paramName << ": " << *paramValue << llendl;
255// llinfos << "Weights " << firstPose->getWeight() << " " << secondPose->getWeight() << llendl;
256 }
257 }
258 else if (firstMotion && !secondMotion)
259 {
260 firstPose->setWeight(weightFactor);
261 }
262 }
263
264 // blend poses
265 mPoseBlender.blendAndApply();
266
267 llinfos << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << llendl;
268
269 return TRUE;
270}
271
272//-----------------------------------------------------------------------------
273// LLKeyframeMotionParam::onDeactivate()
274//-----------------------------------------------------------------------------
275void LLKeyframeMotionParam::onDeactivate()
276{
277 for (U32 i = 0; i < mParameterizedMotions.length(); i++)
278 {
279 LLLinkedList< ParameterizedMotion > *motionList = *mParameterizedMotions.getValueAt(i);
280 for (ParameterizedMotion* paramMotion = motionList->getFirstData(); paramMotion; paramMotion = motionList->getNextData())
281 {
282 paramMotion->first->onDeactivate();
283 }
284 }
285}
286
287//-----------------------------------------------------------------------------
288// LLKeyframeMotionParam::addKeyframeMotion()
289//-----------------------------------------------------------------------------
290BOOL LLKeyframeMotionParam::addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value)
291{
292 LLMotion *newMotion = mCharacter->createMotion( id );
293
294 if (!newMotion)
295 {
296 return FALSE;
297 }
298
299 newMotion->setName(name);
300
301 // make sure a list of motions exists for this parameter
302 LLLinkedList< ParameterizedMotion > *motionList;
303 if (mParameterizedMotions.getValue(param))
304 {
305 motionList = *mParameterizedMotions.getValue(param);
306 }
307 else
308 {
309 motionList = new LLLinkedList< ParameterizedMotion >;
310 motionList->setInsertBefore(sortFunc);
311 mParameterizedMotions.addToHead(param, motionList);
312 }
313
314 // now add motion to this list
315 ParameterizedMotion *parameterizedMotion = new ParameterizedMotion(newMotion, value);
316
317 motionList->addDataSorted(parameterizedMotion);
318
319 return TRUE;
320}
321
322
323//-----------------------------------------------------------------------------
324// LLKeyframeMotionParam::setDefaultKeyframeMotion()
325//-----------------------------------------------------------------------------
326void LLKeyframeMotionParam::setDefaultKeyframeMotion(char *name)
327{
328 for (U32 i = 0; i < mParameterizedMotions.length(); i++)
329 {
330 LLLinkedList< ParameterizedMotion > *motionList = *mParameterizedMotions.getValueAt(i);
331 for (ParameterizedMotion* paramMotion = motionList->getFirstData(); paramMotion; paramMotion = motionList->getNextData())
332 {
333 if (paramMotion->first->getName() == name)
334 {
335 mDefaultKeyframeMotion = paramMotion->first;
336 }
337 }
338 }
339}
340
341//-----------------------------------------------------------------------------
342// loadMotions()
343//-----------------------------------------------------------------------------
344BOOL LLKeyframeMotionParam::loadMotions()
345{
346 //-------------------------------------------------------------------------
347 // Load named file by concatenating the character prefix with the motion name.
348 // Load data into a buffer to be parsed.
349 //-------------------------------------------------------------------------
350 char path[LL_MAX_PATH]; /* Flawfinder: ignore */
351 snprintf( path, sizeof(path), "%s_%s.llp",
352 gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix()).c_str(),
353 getName().c_str() ); /* Flawfinder: ignore */
354
355 //-------------------------------------------------------------------------
356 // open the file
357 //-------------------------------------------------------------------------
358 S32 fileSize = 0;
359 apr_file_t* fp = ll_apr_file_open(path, LL_APR_R, &fileSize);
360 if (!fp || fileSize == 0)
361 {
362 llinfos << "ERROR: can't open: " << path << llendl;
363 return FALSE;
364 }
365
366 // allocate a text buffer
367 char *text = new char[ fileSize+1 ];
368 if ( !text )
369 {
370 llinfos << "ERROR: can't allocated keyframe text buffer." << llendl;
371 apr_file_close(fp);
372 return FALSE;
373 }
374
375 //-------------------------------------------------------------------------
376 // load data from file into buffer
377 //-------------------------------------------------------------------------
378 bool error = false;
379 char *p = text;
380 while ( 1 )
381 {
382 if (apr_file_eof(fp) == APR_EOF)
383 {
384 break;
385 }
386 if (apr_file_gets(p, 1024, fp) != APR_SUCCESS)
387 {
388 error = true;
389 break;
390 }
391 while ( *(++p) )
392 ;
393 }
394
395 //-------------------------------------------------------------------------
396 // close the file
397 //-------------------------------------------------------------------------
398 apr_file_close( fp );
399
400 //-------------------------------------------------------------------------
401 // check for error
402 //-------------------------------------------------------------------------
403 llassert( p <= (text+fileSize) );
404
405 if ( error )
406 {
407 llinfos << "ERROR: error while reading from " << path << llendl;
408 delete [] text;
409 return FALSE;
410 }
411
412 llinfos << "Loading parametric keyframe data for: " << getName() << llendl;
413
414 //-------------------------------------------------------------------------
415 // parse the text and build keyframe data structures
416 //-------------------------------------------------------------------------
417 p = text;
418 S32 num;
419 char strA[80]; /* Flawfinder: ignore */
420 char strB[80]; /* Flawfinder: ignore */
421 F32 floatA = 0.0f;
422
423
424 //-------------------------------------------------------------------------
425 // get priority
426 //-------------------------------------------------------------------------
427 BOOL isFirstMotion = TRUE;
428 num = sscanf(p, "%79s %79s %f", strA, strB, &floatA);
429
430 while(1)
431 {
432 if (num == 0 || num == EOF) break;
433 if ((num != 3))
434 {
435 llinfos << "WARNING: can't read parametric motion" << llendl;
436 delete [] text;
437 return FALSE;
438 }
439
440 addKeyframeMotion(strA, gAnimLibrary.stringToAnimState(strA), strB, floatA);
441 if (isFirstMotion)
442 {
443 isFirstMotion = FALSE;
444 setDefaultKeyframeMotion(strA);
445 }
446
447 p = strstr(p, "\n");
448 if (!p)
449 {
450 break;
451 }
452
453 p++;
454 num = sscanf(p, "%79s %79s %f", strA, strB, &floatA);
455 }
456
457 delete [] text;
458 return TRUE;
459}
460
461// End