PageRenderTime 169ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcharacter/llkeyframemotionparam.cpp

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