diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llcharacter/llkeyframemotionparam.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 461 |
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 | //----------------------------------------------------------------------------- | ||
49 | BOOL 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 | //----------------------------------------------------------------------------- | ||
58 | LLKeyframeMotionParam::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 | //----------------------------------------------------------------------------- | ||
75 | LLKeyframeMotionParam::~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 | //----------------------------------------------------------------------------- | ||
93 | LLMotion::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 | //----------------------------------------------------------------------------- | ||
146 | BOOL 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 | //----------------------------------------------------------------------------- | ||
163 | BOOL 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 | //----------------------------------------------------------------------------- | ||
275 | void 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 | //----------------------------------------------------------------------------- | ||
290 | BOOL 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 | //----------------------------------------------------------------------------- | ||
326 | void 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 | //----------------------------------------------------------------------------- | ||
344 | BOOL 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 | ||