llheadrotmotion.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /**
  2. * @file llheadrotmotion.cpp
  3. * @brief Implementation of LLHeadRotMotion 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. #include "linden_common.h"
  33. #include "llheadrotmotion.h"
  34. #include "llcharacter.h"
  35. #include "llrand.h"
  36. #include "llmatrix3.h"
  37. #include "llvector3d.h"
  38. #include "llcriticaldamp.h"
  39. // Torso rotation factor
  40. constexpr F32 TORSO_LAG = 0.35f;
  41. // Neck rotation factor
  42. constexpr F32 NECK_LAG = 0.5f;
  43. // Half-life of lookat targeting for head
  44. constexpr F32 HEAD_LOOKAT_LAG_HALF_LIFE = 0.15f;
  45. // Half-life of lookat targeting for torso
  46. constexpr F32 TORSO_LOOKAT_LAG_HALF_LIFE = 0.27f;
  47. // Limit angle for head rotation
  48. constexpr F32 HEAD_ROTATION_CONSTRAINT = F_PI_BY_TWO * 0.8f;
  49. // Minimum distance from head before we turn to look at it
  50. constexpr F32 MIN_HEAD_LOOKAT_DISTANCE = 0.3f;
  51. // Minimum amount of time between eye "jitter" motions
  52. constexpr F32 EYE_JITTER_MIN_TIME = 0.3f;
  53. // Maximum amount of time between eye "jitter" motions
  54. constexpr F32 EYE_JITTER_MAX_TIME = 2.5f;
  55. // Maximum yaw of eye jitter motion
  56. constexpr F32 EYE_JITTER_MAX_YAW = 0.08f;
  57. // Maximum pitch of eye jitter motion
  58. constexpr F32 EYE_JITTER_MAX_PITCH = 0.015f;
  59. // Minimum amount of time between eye "look away" motions
  60. constexpr F32 EYE_LOOK_AWAY_MIN_TIME = 5.f;
  61. // Maximum amount of time between eye "look away" motions
  62. constexpr F32 EYE_LOOK_AWAY_MAX_TIME = 15.f;
  63. // Minimum amount of time before looking back after looking away
  64. constexpr F32 EYE_LOOK_BACK_MIN_TIME = 1.f;
  65. // Maximum amount of time before looking back after looking away
  66. constexpr F32 EYE_LOOK_BACK_MAX_TIME = 5.f;
  67. // Maximum yaw of eye look away motion
  68. constexpr F32 EYE_LOOK_AWAY_MAX_YAW = 0.15f;
  69. // Maximum pitch of look away motion
  70. constexpr F32 EYE_LOOK_AWAY_MAX_PITCH = 0.12f;
  71. // Maximum angle in radians for eye rotation
  72. constexpr F32 EYE_ROT_LIMIT_ANGLE = F_PI_BY_TWO * 0.3f;
  73. // Minimum amount of time between blinks
  74. constexpr F32 EYE_BLINK_MIN_TIME = 0.5f;
  75. // Maximum amount of time between blinks
  76. constexpr F32 EYE_BLINK_MAX_TIME = 8.f;
  77. // How long the eye stays closed in a blink
  78. constexpr F32 EYE_BLINK_CLOSE_TIME = 0.03f;
  79. // Seconds it takes for a eye open/close movement
  80. constexpr F32 EYE_BLINK_SPEED = 0.015f;
  81. // Time between one eye starting a blink and the other following
  82. constexpr F32 EYE_BLINK_TIME_DELTA = 0.005f;
  83. //-----------------------------------------------------------------------------
  84. // LLHeadRotMotion() class
  85. //-----------------------------------------------------------------------------
  86. LLHeadRotMotion::LLHeadRotMotion(const LLUUID& id)
  87. : LLMotion(id),
  88. mCharacter(NULL),
  89. mTorsoJoint(NULL),
  90. mHeadJoint(NULL),
  91. mEnabled(true)
  92. {
  93. mName = "head_rot";
  94. mTorsoState = new LLJointState;
  95. mNeckState = new LLJointState;
  96. mHeadState = new LLJointState;
  97. }
  98. LLMotion::LLMotionInitStatus LLHeadRotMotion::onInitialize(LLCharacter* character)
  99. {
  100. if (!character)
  101. {
  102. return STATUS_FAILURE;
  103. }
  104. mCharacter = character;
  105. mPelvisJoint = character->getJoint(LL_JOINT_KEY_PELVIS);
  106. if (!mPelvisJoint)
  107. {
  108. llinfos << getName() << ": cannot get pelvis joint." << llendl;
  109. return STATUS_FAILURE;
  110. }
  111. mRootJoint = character->getJoint(LL_JOINT_KEY_ROOT);
  112. if (!mRootJoint)
  113. {
  114. llinfos << getName() << ": cannot get root joint." << llendl;
  115. return STATUS_FAILURE;
  116. }
  117. mTorsoJoint = character->getJoint(LL_JOINT_KEY_TORSO);
  118. if (!mTorsoJoint)
  119. {
  120. llinfos << getName() << ": cannot get torso joint." << llendl;
  121. return STATUS_FAILURE;
  122. }
  123. mHeadJoint = character->getJoint(LL_JOINT_KEY_HEAD);
  124. if (!mHeadJoint)
  125. {
  126. llinfos << getName() << ": cannot get head joint." << llendl;
  127. return STATUS_FAILURE;
  128. }
  129. mTorsoState->setJoint(mTorsoJoint);
  130. if (!mTorsoState->getJoint())
  131. {
  132. llinfos << getName() << ": cannot set torso joint." << llendl;
  133. return STATUS_FAILURE;
  134. }
  135. mNeckState->setJoint(character->getJoint(LL_JOINT_KEY_NECK));
  136. if (!mNeckState->getJoint())
  137. {
  138. llinfos << getName() << ": cannot set neck joint." << llendl;
  139. return STATUS_FAILURE;
  140. }
  141. mHeadState->setJoint(character->getJoint(LL_JOINT_KEY_HEAD));
  142. if (!mHeadState->getJoint())
  143. {
  144. llinfos << getName() << ": cannot set head joint." << llendl;
  145. return STATUS_FAILURE;
  146. }
  147. mTorsoState->setUsage(LLJointState::ROT);
  148. mNeckState->setUsage(LLJointState::ROT);
  149. mHeadState->setUsage(LLJointState::ROT);
  150. addJointState(mTorsoState);
  151. addJointState(mNeckState);
  152. addJointState(mHeadState);
  153. mLastHeadRot.loadIdentity();
  154. return STATUS_SUCCESS;
  155. }
  156. bool LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask)
  157. {
  158. if (!mEnabled)
  159. {
  160. // Yes, return true even when not enabled since this motion relays the
  161. // target position to code that moves the eyes and such; we want to
  162. // keep the targeting working but bypass the head motion effects.
  163. return true;
  164. }
  165. LLQuaternion target_head_rot;
  166. LLQuaternion cur_root_rot = mRootJoint->getWorldRotation();
  167. LLQuaternion cur_inv_root_rot = ~cur_root_rot;
  168. F32 head_slerp_amt = LLCriticalDamp::getInterpolant(HEAD_LOOKAT_LAG_HALF_LIFE);
  169. F32 torso_slerp_amt = LLCriticalDamp::getInterpolant(TORSO_LOOKAT_LAG_HALF_LIFE);
  170. LLVector3* target_pos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");
  171. if (target_pos)
  172. {
  173. LLVector3 headLookAt = *target_pos;
  174. F32 lookatDistance = headLookAt.normalize();
  175. if (lookatDistance < MIN_HEAD_LOOKAT_DISTANCE)
  176. {
  177. target_head_rot = mPelvisJoint->getWorldRotation();
  178. }
  179. else
  180. {
  181. LLVector3 root_up = LLVector3(0.f, 0.f, 1.f) * cur_root_rot;
  182. LLVector3 left(root_up % headLookAt);
  183. // If look_at has zero length, fail; if look_at and skyward are
  184. // parallel, fail. Test both of these conditions with a cross
  185. // product.
  186. if (left.lengthSquared() < 0.15f)
  187. {
  188. LLVector3 root_at = LLVector3(1.f, 0.f, 0.f) *
  189. cur_root_rot;
  190. root_at.mV[VZ] = 0.f;
  191. root_at.normalize();
  192. headLookAt = lerp(headLookAt, root_at, 0.4f);
  193. headLookAt.normalize();
  194. left = root_up % headLookAt;
  195. }
  196. // Make sure look_at and skyward and not parallel and neither are
  197. // zero length
  198. LLVector3 up(headLookAt % left);
  199. target_head_rot = LLQuaternion(headLookAt, left, up);
  200. }
  201. }
  202. else
  203. {
  204. target_head_rot = cur_root_rot;
  205. }
  206. LLQuaternion head_rot_local = target_head_rot * cur_inv_root_rot;
  207. head_rot_local.constrain(HEAD_ROTATION_CONSTRAINT);
  208. // Set final torso rotation and torso target rotation such that it lags
  209. // behind the head rotation by a fixed amount.
  210. LLQuaternion torso_rot_local = nlerp(TORSO_LAG, LLQuaternion::DEFAULT,
  211. head_rot_local);
  212. mTorsoState->setRotation(nlerp(torso_slerp_amt, mTorsoState->getRotation(),
  213. torso_rot_local));
  214. head_rot_local = nlerp(head_slerp_amt, mLastHeadRot, head_rot_local);
  215. mLastHeadRot = head_rot_local;
  216. // Set the head rotation.
  217. if (mNeckState->getJoint() && mNeckState->getJoint()->getParent())
  218. {
  219. LLQuaternion torsoRotLocal =
  220. mNeckState->getJoint()->getParent()->getWorldRotation() *
  221. cur_inv_root_rot;
  222. head_rot_local = head_rot_local * ~torsoRotLocal;
  223. mNeckState->setRotation(nlerp(NECK_LAG, LLQuaternion::DEFAULT,
  224. head_rot_local));
  225. mHeadState->setRotation(nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT,
  226. head_rot_local));
  227. }
  228. return true;
  229. }
  230. //-----------------------------------------------------------------------------
  231. // LLEyeMotion() class
  232. //-----------------------------------------------------------------------------
  233. LLEyeMotion::LLEyeMotion(const LLUUID& id)
  234. : LLMotion(id)
  235. {
  236. mCharacter = NULL;
  237. mEyeJitterTime = 0.f;
  238. mEyeJitterYaw = 0.f;
  239. mEyeJitterPitch = 0.f;
  240. mEyeLookAwayTime = 0.f;
  241. mEyeLookAwayYaw = 0.f;
  242. mEyeLookAwayPitch = 0.f;
  243. mEyeBlinkTime = 0.f;
  244. mEyesClosed = false;
  245. mHeadJoint = NULL;
  246. mName = "eye_rot";
  247. mLeftEyeState = new LLJointState;
  248. mAltLeftEyeState = new LLJointState;
  249. mRightEyeState = new LLJointState;
  250. mAltRightEyeState = new LLJointState;
  251. }
  252. LLMotion::LLMotionInitStatus LLEyeMotion::onInitialize(LLCharacter* character)
  253. {
  254. if (!character)
  255. {
  256. return STATUS_FAILURE;
  257. }
  258. mCharacter = character;
  259. mHeadJoint = character->getJoint(LL_JOINT_KEY_HEAD);
  260. if (!mHeadJoint)
  261. {
  262. llinfos << getName() << ": cannot get head joint." << llendl;
  263. return STATUS_FAILURE;
  264. }
  265. mLeftEyeState->setJoint(character->getJoint(LL_JOINT_KEY_EYELEFT));
  266. if (!mLeftEyeState->getJoint())
  267. {
  268. llinfos << getName() << ": cannot get left eyeball joint." << llendl;
  269. return STATUS_FAILURE;
  270. }
  271. mAltLeftEyeState->setJoint(character->getJoint(LL_JOINT_KEY_EYEALTLEFT));
  272. if (!mLeftEyeState->getJoint())
  273. {
  274. llinfos << getName() << ": cannot get alt left eyeball joint."
  275. << llendl;
  276. return STATUS_FAILURE;
  277. }
  278. mRightEyeState->setJoint(character->getJoint(LL_JOINT_KEY_EYERIGHT));
  279. if (!mRightEyeState->getJoint())
  280. {
  281. llinfos << getName() << ": cannot set right eyeball joint." << llendl;
  282. return STATUS_FAILURE;
  283. }
  284. mAltRightEyeState->setJoint(character->getJoint(LL_JOINT_KEY_EYEALTRIGHT));
  285. if (!mRightEyeState->getJoint())
  286. {
  287. llinfos << getName() << ": cannot get alt right eyeball joint."
  288. << llendl;
  289. return STATUS_FAILURE;
  290. }
  291. mLeftEyeState->setUsage(LLJointState::ROT);
  292. mAltLeftEyeState->setUsage(LLJointState::ROT);
  293. mRightEyeState->setUsage(LLJointState::ROT);
  294. mAltRightEyeState->setUsage(LLJointState::ROT);
  295. addJointState(mLeftEyeState);
  296. addJointState(mAltLeftEyeState);
  297. addJointState(mRightEyeState);
  298. addJointState(mAltRightEyeState);
  299. return STATUS_SUCCESS;
  300. }
  301. void LLEyeMotion::adjustEyeTarget(LLVector3* target_pos,
  302. LLJointState& left_eye_state,
  303. LLJointState& right_eye_state)
  304. {
  305. // Compute eye rotation.
  306. bool has_eye_target = false;
  307. LLQuaternion target_eye_rot;
  308. LLVector3 eye_look_at;
  309. F32 vergence;
  310. if (target_pos)
  311. {
  312. LLVector3 skyward(0.f, 0.f, 1.f);
  313. LLVector3 left, up;
  314. eye_look_at = *target_pos;
  315. has_eye_target = true;
  316. F32 look_at_dist = eye_look_at.normalize();
  317. left.set(skyward % eye_look_at);
  318. up.set(eye_look_at % left);
  319. target_eye_rot = LLQuaternion(eye_look_at, left, up);
  320. // Convert target rotation to head-local coordinates
  321. target_eye_rot *= ~mHeadJoint->getWorldRotation();
  322. // Eliminate any Euler roll - we are lucky that roll is applied last.
  323. F32 roll, pitch, yaw;
  324. target_eye_rot.getEulerAngles(&roll, &pitch, &yaw);
  325. target_eye_rot.setEulerAngles(0.f, pitch, yaw);
  326. // constrain target orientation to be in front of avatar's face
  327. target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE);
  328. // Calculate vergence
  329. F32 interocular_dist = (left_eye_state.getJoint()->getWorldPosition() -
  330. right_eye_state.getJoint()->getWorldPosition()).length();
  331. vergence = -atan2f((interocular_dist / 2.f), look_at_dist);
  332. llclamp(vergence, -F_PI_BY_TWO, 0.f);
  333. }
  334. else
  335. {
  336. target_eye_rot = LLQuaternion::DEFAULT;
  337. vergence = 0.f;
  338. }
  339. // RN: subtract 4 degrees to account for foveal angular offset relative to
  340. // pupil
  341. vergence += 4.f * DEG_TO_RAD;
  342. // calculate eye jitter
  343. LLQuaternion eye_jitter_rot;
  344. // vergence not too high...
  345. if (vergence > -0.05f)
  346. {
  347. //...go ahead and jitter
  348. eye_jitter_rot.setEulerAngles(0.f, mEyeJitterPitch + mEyeLookAwayPitch,
  349. mEyeJitterYaw + mEyeLookAwayYaw);
  350. }
  351. else
  352. {
  353. //...or don't
  354. eye_jitter_rot.loadIdentity();
  355. }
  356. // calculate vergence of eyes as an object gets closer to the avatar's head
  357. LLQuaternion vergence_quat;
  358. if (has_eye_target)
  359. {
  360. vergence_quat.setAngleAxis(vergence, LLVector3(0.f, 0.f, 1.f));
  361. }
  362. else
  363. {
  364. vergence_quat.loadIdentity();
  365. }
  366. // calculate eye rotations
  367. LLQuaternion left_eye_rot = target_eye_rot;
  368. left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot;
  369. LLQuaternion right_eye_rot = target_eye_rot;
  370. vergence_quat.transpose();
  371. right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot;
  372. left_eye_state.setRotation(left_eye_rot);
  373. right_eye_state.setRotation(right_eye_rot);
  374. }
  375. bool LLEyeMotion::onUpdate(F32 time, U8* joint_mask)
  376. {
  377. // Calculate jitter
  378. if (mEyeJitterTimer.getElapsedTimeF32() > mEyeJitterTime)
  379. {
  380. mEyeJitterTime = EYE_JITTER_MIN_TIME +
  381. ll_frand(EYE_JITTER_MAX_TIME - EYE_JITTER_MIN_TIME);
  382. mEyeJitterYaw = (ll_frand(2.f) - 1.f) * EYE_JITTER_MAX_YAW;
  383. mEyeJitterPitch = (ll_frand(2.f) - 1.f) * EYE_JITTER_MAX_PITCH;
  384. // Make sure lookaway time count gets updated, because we are resetting
  385. // the timer
  386. mEyeLookAwayTime -= llmax(0.f, mEyeJitterTimer.getElapsedTimeF32());
  387. mEyeJitterTimer.reset();
  388. }
  389. else if (mEyeJitterTimer.getElapsedTimeF32() > mEyeLookAwayTime)
  390. {
  391. if (ll_frand() > 0.1f)
  392. {
  393. // Blink while moving eyes some percentage of the time
  394. mEyeBlinkTime = mEyeBlinkTimer.getElapsedTimeF32();
  395. }
  396. if (mEyeLookAwayYaw == 0.f && mEyeLookAwayPitch == 0.f)
  397. {
  398. mEyeLookAwayYaw = (ll_frand(2.f) - 1.f) * EYE_LOOK_AWAY_MAX_YAW;
  399. mEyeLookAwayPitch = (ll_frand(2.f) - 1.f) * EYE_LOOK_AWAY_MAX_PITCH;
  400. mEyeLookAwayTime = EYE_LOOK_BACK_MIN_TIME +
  401. ll_frand(EYE_LOOK_BACK_MAX_TIME -
  402. EYE_LOOK_BACK_MIN_TIME);
  403. }
  404. else
  405. {
  406. mEyeLookAwayYaw = 0.f;
  407. mEyeLookAwayPitch = 0.f;
  408. mEyeLookAwayTime = EYE_LOOK_AWAY_MIN_TIME +
  409. ll_frand(EYE_LOOK_AWAY_MAX_TIME -
  410. EYE_LOOK_AWAY_MIN_TIME);
  411. }
  412. }
  413. // Do blinking
  414. if (!mEyesClosed && mEyeBlinkTimer.getElapsedTimeF32() >= mEyeBlinkTime)
  415. {
  416. F32 leftEyeBlinkMorph = mEyeBlinkTimer.getElapsedTimeF32() - mEyeBlinkTime;
  417. F32 rightEyeBlinkMorph = leftEyeBlinkMorph - EYE_BLINK_TIME_DELTA;
  418. leftEyeBlinkMorph = llclamp(leftEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
  419. rightEyeBlinkMorph = llclamp(rightEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
  420. mCharacter->setVisualParamWeight("Blink_Left", leftEyeBlinkMorph);
  421. mCharacter->setVisualParamWeight("Blink_Right", rightEyeBlinkMorph);
  422. mCharacter->updateVisualParams();
  423. if (rightEyeBlinkMorph == 1.f)
  424. {
  425. mEyesClosed = true;
  426. mEyeBlinkTime = EYE_BLINK_CLOSE_TIME;
  427. mEyeBlinkTimer.reset();
  428. }
  429. }
  430. else if (mEyesClosed)
  431. {
  432. if (mEyeBlinkTimer.getElapsedTimeF32() >= mEyeBlinkTime)
  433. {
  434. F32 leftEyeBlinkMorph = mEyeBlinkTimer.getElapsedTimeF32() - mEyeBlinkTime;
  435. F32 rightEyeBlinkMorph = leftEyeBlinkMorph - EYE_BLINK_TIME_DELTA;
  436. leftEyeBlinkMorph = 1.f - llclamp(leftEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
  437. rightEyeBlinkMorph = 1.f - llclamp(rightEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
  438. mCharacter->setVisualParamWeight("Blink_Left", leftEyeBlinkMorph);
  439. mCharacter->setVisualParamWeight("Blink_Right", rightEyeBlinkMorph);
  440. mCharacter->updateVisualParams();
  441. if (rightEyeBlinkMorph == 0.f)
  442. {
  443. mEyesClosed = false;
  444. mEyeBlinkTime = EYE_BLINK_MIN_TIME +
  445. ll_frand(EYE_BLINK_MAX_TIME -
  446. EYE_BLINK_MIN_TIME);
  447. mEyeBlinkTimer.reset();
  448. }
  449. }
  450. }
  451. LLVector3* target_pos =
  452. (LLVector3*)mCharacter->getAnimationData("LookAtPoint");
  453. adjustEyeTarget(target_pos, *mLeftEyeState, *mRightEyeState);
  454. adjustEyeTarget(target_pos, *mAltLeftEyeState, *mAltRightEyeState);
  455. return true;
  456. }
  457. void LLEyeMotion::onDeactivate()
  458. {
  459. LLJoint* joint = mLeftEyeState->getJoint();
  460. if (joint)
  461. {
  462. joint->setRotation(LLQuaternion::DEFAULT);
  463. }
  464. joint = mAltLeftEyeState->getJoint();
  465. if (joint)
  466. {
  467. joint->setRotation(LLQuaternion::DEFAULT);
  468. }
  469. joint = mRightEyeState->getJoint();
  470. if (joint)
  471. {
  472. joint->setRotation(LLQuaternion::DEFAULT);
  473. }
  474. joint = mAltRightEyeState->getJoint();
  475. if (joint)
  476. {
  477. joint->setRotation(LLQuaternion::DEFAULT);
  478. }
  479. }