PageRenderTime 26ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/linden/indra/llcharacter/llkeyframemotionparam.cpp

https://github.com/WindBasevi/imprudence
C++ | 460 lines | 294 code | 62 blank | 104 comment | 75 complexity | 219cd34592d5482ab6bf500f9d4a7cd5 MD5 | raw file
  1. /**
  2. * @file llkeyframemotionparam.cpp
  3. * @brief Implementation of LLKeyframeMotion class.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. //-----------------------------------------------------------------------------
  33. // Header Files
  34. //-----------------------------------------------------------------------------
  35. #include "linden_common.h"
  36. #include "llkeyframemotionparam.h"
  37. #include "llcharacter.h"
  38. #include "llmath.h"
  39. #include "m3math.h"
  40. #include "lldir.h"
  41. #include "llanimationstates.h"
  42. //-----------------------------------------------------------------------------
  43. //-----------------------------------------------------------------------------
  44. // LLKeyframeMotionParam class
  45. //-----------------------------------------------------------------------------
  46. //-----------------------------------------------------------------------------
  47. //-----------------------------------------------------------------------------
  48. // LLKeyframeMotionParam()
  49. // Class Constructor
  50. //-----------------------------------------------------------------------------
  51. LLKeyframeMotionParam::LLKeyframeMotionParam( const LLUUID &id) : LLMotion(id)
  52. {
  53. mDefaultKeyframeMotion = NULL;
  54. mCharacter = NULL;
  55. mEaseInDuration = 0.f;
  56. mEaseOutDuration = 0.f;
  57. mDuration = 0.f;
  58. mPriority = LLJoint::LOW_PRIORITY;
  59. }
  60. //-----------------------------------------------------------------------------
  61. // ~LLKeyframeMotionParam()
  62. // Class Destructor
  63. //-----------------------------------------------------------------------------
  64. LLKeyframeMotionParam::~LLKeyframeMotionParam()
  65. {
  66. for (motion_map_t::iterator iter = mParameterizedMotions.begin();
  67. iter != mParameterizedMotions.end(); ++iter)
  68. {
  69. motion_list_t& motionList = iter->second;
  70. for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
  71. {
  72. const ParameterizedMotion& paramMotion = *iter2;
  73. delete paramMotion.mMotion;
  74. }
  75. motionList.clear();
  76. }
  77. mParameterizedMotions.clear();
  78. }
  79. //-----------------------------------------------------------------------------
  80. // LLKeyframeMotionParam::onInitialize(LLCharacter *character)
  81. //-----------------------------------------------------------------------------
  82. LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character)
  83. {
  84. mCharacter = character;
  85. if (!loadMotions())
  86. {
  87. return STATUS_FAILURE;
  88. }
  89. for (motion_map_t::iterator iter = mParameterizedMotions.begin();
  90. iter != mParameterizedMotions.end(); ++iter)
  91. {
  92. motion_list_t& motionList = iter->second;
  93. for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
  94. {
  95. const ParameterizedMotion& paramMotion = *iter2;
  96. LLMotion* motion = paramMotion.mMotion;
  97. motion->onInitialize(character);
  98. if (motion->getDuration() > mEaseInDuration)
  99. {
  100. mEaseInDuration = motion->getEaseInDuration();
  101. }
  102. if (motion->getEaseOutDuration() > mEaseOutDuration)
  103. {
  104. mEaseOutDuration = motion->getEaseOutDuration();
  105. }
  106. if (motion->getDuration() > mDuration)
  107. {
  108. mDuration = motion->getDuration();
  109. }
  110. if (motion->getPriority() > mPriority)
  111. {
  112. mPriority = motion->getPriority();
  113. }
  114. LLPose *pose = motion->getPose();
  115. mPoseBlender.addMotion(motion);
  116. for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState())
  117. {
  118. LLPose *blendedPose = mPoseBlender.getBlendedPose();
  119. blendedPose->addJointState(jsp);
  120. }
  121. }
  122. }
  123. return STATUS_SUCCESS;
  124. }
  125. //-----------------------------------------------------------------------------
  126. // LLKeyframeMotionParam::onActivate()
  127. //-----------------------------------------------------------------------------
  128. BOOL LLKeyframeMotionParam::onActivate()
  129. {
  130. for (motion_map_t::iterator iter = mParameterizedMotions.begin();
  131. iter != mParameterizedMotions.end(); ++iter)
  132. {
  133. motion_list_t& motionList = iter->second;
  134. for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
  135. {
  136. const ParameterizedMotion& paramMotion = *iter2;
  137. paramMotion.mMotion->activate(mActivationTimestamp);
  138. }
  139. }
  140. return TRUE;
  141. }
  142. //-----------------------------------------------------------------------------
  143. // LLKeyframeMotionParam::onUpdate()
  144. //-----------------------------------------------------------------------------
  145. BOOL LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask)
  146. {
  147. F32 weightFactor = 1.f / (F32)mParameterizedMotions.size();
  148. // zero out all pose weights
  149. for (motion_map_t::iterator iter = mParameterizedMotions.begin();
  150. iter != mParameterizedMotions.end(); ++iter)
  151. {
  152. motion_list_t& motionList = iter->second;
  153. for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
  154. {
  155. const ParameterizedMotion& paramMotion = *iter2;
  156. // llinfos << "Weight for pose " << paramMotion.mMotion->getName() << " is " << paramMotion.mMotion->getPose()->getWeight() << llendl;
  157. paramMotion.mMotion->getPose()->setWeight(0.f);
  158. }
  159. }
  160. for (motion_map_t::iterator iter = mParameterizedMotions.begin();
  161. iter != mParameterizedMotions.end(); ++iter)
  162. {
  163. const std::string& paramName = iter->first;
  164. F32* paramValue = (F32 *)mCharacter->getAnimationData(paramName);
  165. if (NULL == paramValue) // unexpected, but...
  166. {
  167. llwarns << "paramValue == NULL" << llendl;
  168. continue;
  169. }
  170. // DANGER! Do not modify mParameterizedMotions while using these pointers!
  171. const ParameterizedMotion* firstMotion = NULL;
  172. const ParameterizedMotion* secondMotion = NULL;
  173. motion_list_t& motionList = iter->second;
  174. for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
  175. {
  176. const ParameterizedMotion& paramMotion = *iter2;
  177. paramMotion.mMotion->onUpdate(time, joint_mask);
  178. F32 distToParam = paramMotion.mParam - *paramValue;
  179. if ( distToParam <= 0.f)
  180. {
  181. // keep track of the motion closest to the parameter value
  182. firstMotion = &paramMotion;
  183. }
  184. else
  185. {
  186. // we've passed the parameter value
  187. // so store the first motion we find as the second one we want to blend...
  188. if (firstMotion && !secondMotion )
  189. {
  190. secondMotion = &paramMotion;
  191. }
  192. //...or, if we've seen no other motion so far, make sure we blend to this only
  193. else if (!firstMotion)
  194. {
  195. firstMotion = &paramMotion;
  196. secondMotion = &paramMotion;
  197. }
  198. }
  199. }
  200. LLPose *firstPose;
  201. LLPose *secondPose;
  202. if (firstMotion)
  203. firstPose = firstMotion->mMotion->getPose();
  204. else
  205. firstPose = NULL;
  206. if (secondMotion)
  207. secondPose = secondMotion->mMotion->getPose();
  208. else
  209. secondPose = NULL;
  210. // now modify weight of the subanim (only if we are blending between two motions)
  211. if (firstMotion && secondMotion)
  212. {
  213. if (firstMotion == secondMotion)
  214. {
  215. firstPose->setWeight(weightFactor);
  216. }
  217. else if (firstMotion->mParam == secondMotion->mParam)
  218. {
  219. firstPose->setWeight(0.5f * weightFactor);
  220. secondPose->setWeight(0.5f * weightFactor);
  221. }
  222. else
  223. {
  224. F32 first_weight = 1.f -
  225. ((llclamp(*paramValue - firstMotion->mParam, 0.f, (secondMotion->mParam - firstMotion->mParam))) /
  226. (secondMotion->mParam - firstMotion->mParam));
  227. first_weight = llclamp(first_weight, 0.f, 1.f);
  228. F32 second_weight = 1.f - first_weight;
  229. firstPose->setWeight(first_weight * weightFactor);
  230. secondPose->setWeight(second_weight * weightFactor);
  231. // llinfos << "Parameter " << *paramName << ": " << *paramValue << llendl;
  232. // llinfos << "Weights " << firstPose->getWeight() << " " << secondPose->getWeight() << llendl;
  233. }
  234. }
  235. else if (firstMotion && !secondMotion)
  236. {
  237. firstPose->setWeight(weightFactor);
  238. }
  239. }
  240. // blend poses
  241. mPoseBlender.blendAndApply();
  242. llinfos << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << llendl;
  243. return TRUE;
  244. }
  245. //-----------------------------------------------------------------------------
  246. // LLKeyframeMotionParam::onDeactivate()
  247. //-----------------------------------------------------------------------------
  248. void LLKeyframeMotionParam::onDeactivate()
  249. {
  250. for (motion_map_t::iterator iter = mParameterizedMotions.begin();
  251. iter != mParameterizedMotions.end(); ++iter)
  252. {
  253. motion_list_t& motionList = iter->second;
  254. for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
  255. {
  256. const ParameterizedMotion& paramMotion = *iter2;
  257. paramMotion.mMotion->onDeactivate();
  258. }
  259. }
  260. }
  261. //-----------------------------------------------------------------------------
  262. // LLKeyframeMotionParam::addKeyframeMotion()
  263. //-----------------------------------------------------------------------------
  264. BOOL LLKeyframeMotionParam::addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value)
  265. {
  266. LLMotion *newMotion = mCharacter->createMotion( id );
  267. if (!newMotion)
  268. {
  269. return FALSE;
  270. }
  271. newMotion->setName(name);
  272. // now add motion to this list
  273. mParameterizedMotions[param].insert(ParameterizedMotion(newMotion, value));
  274. return TRUE;
  275. }
  276. //-----------------------------------------------------------------------------
  277. // LLKeyframeMotionParam::setDefaultKeyframeMotion()
  278. //-----------------------------------------------------------------------------
  279. void LLKeyframeMotionParam::setDefaultKeyframeMotion(char *name)
  280. {
  281. for (motion_map_t::iterator iter = mParameterizedMotions.begin();
  282. iter != mParameterizedMotions.end(); ++iter)
  283. {
  284. motion_list_t& motionList = iter->second;
  285. for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
  286. {
  287. const ParameterizedMotion& paramMotion = *iter2;
  288. if (paramMotion.mMotion->getName() == name)
  289. {
  290. mDefaultKeyframeMotion = paramMotion.mMotion;
  291. }
  292. }
  293. }
  294. }
  295. //-----------------------------------------------------------------------------
  296. // loadMotions()
  297. //-----------------------------------------------------------------------------
  298. BOOL LLKeyframeMotionParam::loadMotions()
  299. {
  300. //-------------------------------------------------------------------------
  301. // Load named file by concatenating the character prefix with the motion name.
  302. // Load data into a buffer to be parsed.
  303. //-------------------------------------------------------------------------
  304. std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix())
  305. + "_" + getName() + ".llp";
  306. //-------------------------------------------------------------------------
  307. // open the file
  308. //-------------------------------------------------------------------------
  309. S32 fileSize = 0;
  310. LLAPRFile infile ;
  311. infile.open(path, LL_APR_R, LLAPRFile::global, &fileSize);
  312. apr_file_t* fp = infile.getFileHandle() ;
  313. if (!fp || fileSize == 0)
  314. {
  315. llinfos << "ERROR: can't open: " << path << llendl;
  316. return FALSE;
  317. }
  318. // allocate a text buffer
  319. char *text = new char[ fileSize+1 ];
  320. if ( !text )
  321. {
  322. llinfos << "ERROR: can't allocated keyframe text buffer." << llendl;
  323. return FALSE;
  324. }
  325. //-------------------------------------------------------------------------
  326. // load data from file into buffer
  327. //-------------------------------------------------------------------------
  328. bool error = false;
  329. char *p = text;
  330. while ( 1 )
  331. {
  332. if (apr_file_eof(fp) == APR_EOF)
  333. {
  334. break;
  335. }
  336. if (apr_file_gets(p, 1024, fp) != APR_SUCCESS)
  337. {
  338. error = true;
  339. break;
  340. }
  341. while ( *(++p) )
  342. ;
  343. }
  344. //-------------------------------------------------------------------------
  345. // close the file
  346. //-------------------------------------------------------------------------
  347. infile.close();
  348. //-------------------------------------------------------------------------
  349. // check for error
  350. //-------------------------------------------------------------------------
  351. llassert( p <= (text+fileSize) );
  352. if ( error )
  353. {
  354. llinfos << "ERROR: error while reading from " << path << llendl;
  355. delete [] text;
  356. return FALSE;
  357. }
  358. llinfos << "Loading parametric keyframe data for: " << getName() << llendl;
  359. //-------------------------------------------------------------------------
  360. // parse the text and build keyframe data structures
  361. //-------------------------------------------------------------------------
  362. p = text;
  363. S32 num;
  364. char strA[80]; /* Flawfinder: ignore */
  365. char strB[80]; /* Flawfinder: ignore */
  366. F32 floatA = 0.0f;
  367. //-------------------------------------------------------------------------
  368. // get priority
  369. //-------------------------------------------------------------------------
  370. BOOL isFirstMotion = TRUE;
  371. num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */
  372. while(1)
  373. {
  374. if (num == 0 || num == EOF) break;
  375. if ((num != 3))
  376. {
  377. llinfos << "WARNING: can't read parametric motion" << llendl;
  378. delete [] text;
  379. return FALSE;
  380. }
  381. addKeyframeMotion(strA, gAnimLibrary.stringToAnimState(std::string(strA)), strB, floatA);
  382. if (isFirstMotion)
  383. {
  384. isFirstMotion = FALSE;
  385. setDefaultKeyframeMotion(strA);
  386. }
  387. p = strstr(p, "\n");
  388. if (!p)
  389. {
  390. break;
  391. }
  392. p++;
  393. num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */
  394. }
  395. delete [] text;
  396. return TRUE;
  397. }
  398. // End