PageRenderTime 30ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llfollowcam.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 901 lines | 578 code | 125 blank | 198 comment | 52 complexity | ea9ba0c768ec279fbee200909c827cbc MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llfollowcam.cpp
  3. * @author Jeffrey Ventrella
  4. * @brief LLFollowCam class implementation
  5. *
  6. * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include "llviewerprecompiledheaders.h"
  28. #include "llfollowcam.h"
  29. #include "llagent.h"
  30. //-------------------------------------------------------
  31. // class statics
  32. //-------------------------------------------------------
  33. std::map<LLUUID, LLFollowCamParams*> LLFollowCamMgr::sParamMap;
  34. std::vector<LLFollowCamParams*> LLFollowCamMgr::sParamStack;
  35. //-------------------------------------------------------
  36. // constants
  37. //-------------------------------------------------------
  38. const F32 ONE_HALF = 0.5;
  39. const F32 FOLLOW_CAM_ZOOM_FACTOR = 0.1f;
  40. const F32 FOLLOW_CAM_MIN_ZOOM_AMOUNT = 0.1f;
  41. const F32 DISTANCE_EPSILON = 0.0001f;
  42. const F32 DEFAULT_MAX_DISTANCE_FROM_SUBJECT = 1000.0; // this will be correctly set on me by my caller
  43. //----------------------------------------------------------------------------------------
  44. // This is how slowly the camera position moves to its ideal position
  45. //----------------------------------------------------------------------------------------
  46. const F32 FOLLOW_CAM_MIN_POSITION_LAG = 0.0f;
  47. const F32 FOLLOW_CAM_DEFAULT_POSITION_LAG = 0.1f;
  48. const F32 FOLLOW_CAM_MAX_POSITION_LAG = 3.0f;
  49. //----------------------------------------------------------------------------------------
  50. // This is how slowly the camera focus moves to its subject
  51. //----------------------------------------------------------------------------------------
  52. const F32 FOLLOW_CAM_MIN_FOCUS_LAG = 0.0f;
  53. const F32 FOLLOW_CAM_DEFAULT_FOCUS_LAG = 0.1f;
  54. const F32 FOLLOW_CAM_MAX_FOCUS_LAG = 3.0f;
  55. //----------------------------------------------------------------------------------------
  56. // This is far the position can get from its IDEAL POSITION before it starts getting pulled
  57. //----------------------------------------------------------------------------------------
  58. const F32 FOLLOW_CAM_MIN_POSITION_THRESHOLD = 0.0f;
  59. const F32 FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD = 1.0f;
  60. const F32 FOLLOW_CAM_MAX_POSITION_THRESHOLD = 4.0f;
  61. //----------------------------------------------------------------------------------------
  62. // This is far the focus can get from the subject before it starts getting pulled
  63. //----------------------------------------------------------------------------------------
  64. const F32 FOLLOW_CAM_MIN_FOCUS_THRESHOLD = 0.0f;
  65. const F32 FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD = 1.0f;
  66. const F32 FOLLOW_CAM_MAX_FOCUS_THRESHOLD = 4.0f;
  67. //----------------------------------------------------------------------------------------
  68. // This is the distance the camera wants to be from the subject
  69. //----------------------------------------------------------------------------------------
  70. const F32 FOLLOW_CAM_MIN_DISTANCE = 0.5f;
  71. const F32 FOLLOW_CAM_DEFAULT_DISTANCE = 3.0f;
  72. //const F32 FOLLOW_CAM_MAX_DISTANCE = 10.0f; // from now on I am using mMaxCameraDistantFromSubject
  73. //----------------------------------------------------------------------------------------
  74. // this is an angluar value
  75. // It affects the angle that the camera rises (pitches) in relation
  76. // to the horizontal plane
  77. //----------------------------------------------------------------------------------------
  78. const F32 FOLLOW_CAM_MIN_PITCH = -45.0f;
  79. const F32 FOLLOW_CAM_DEFAULT_PITCH = 0.0f;
  80. const F32 FOLLOW_CAM_MAX_PITCH = 80.0f; // keep under 90 degrees - avoid gimble lock!
  81. //----------------------------------------------------------------------------------------
  82. // how high or low the camera considers its ideal focus to be (relative to its subject)
  83. //----------------------------------------------------------------------------------------
  84. const F32 FOLLOW_CAM_MIN_FOCUS_OFFSET = -10.0f;
  85. const LLVector3 FOLLOW_CAM_DEFAULT_FOCUS_OFFSET = LLVector3(1.0f, 0.f, 0.f);
  86. const F32 FOLLOW_CAM_MAX_FOCUS_OFFSET = 10.0f;
  87. //----------------------------------------------------------------------------------------
  88. // This affects the rate at which the camera adjusts to stay behind the subject
  89. //----------------------------------------------------------------------------------------
  90. const F32 FOLLOW_CAM_MIN_BEHINDNESS_LAG = 0.0f;
  91. const F32 FOLLOW_CAM_DEFAULT_BEHINDNESS_LAG = 0.f;
  92. const F32 FOLLOW_CAM_MAX_BEHINDNESS_LAG = 3.0f;
  93. //---------------------------------------------------------------------------------------------------------------------
  94. // in degrees: This is the size of the pie slice behind the subject matter within which the camera is free to move
  95. //---------------------------------------------------------------------------------------------------------------------
  96. const F32 FOLLOW_CAM_MIN_BEHINDNESS_ANGLE = 0.0f;
  97. const F32 FOLLOW_CAM_DEFAULT_BEHINDNESS_ANGLE = 10.0f;
  98. const F32 FOLLOW_CAM_MAX_BEHINDNESS_ANGLE = 180.0f;
  99. const F32 FOLLOW_CAM_BEHINDNESS_EPSILON = 1.0f;
  100. //------------------------------------
  101. // Constructor
  102. //------------------------------------
  103. LLFollowCamParams::LLFollowCamParams()
  104. {
  105. mMaxCameraDistantFromSubject = DEFAULT_MAX_DISTANCE_FROM_SUBJECT;
  106. mPositionLocked = false;
  107. mFocusLocked = false;
  108. mUsePosition = false;
  109. mUseFocus = false;
  110. //------------------------------------------------------
  111. // setting the attributes to their defaults
  112. //------------------------------------------------------
  113. setPositionLag ( FOLLOW_CAM_DEFAULT_POSITION_LAG );
  114. setFocusLag ( FOLLOW_CAM_DEFAULT_FOCUS_LAG );
  115. setPositionThreshold( FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD );
  116. setFocusThreshold ( FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD );
  117. setBehindnessLag ( FOLLOW_CAM_DEFAULT_BEHINDNESS_LAG );
  118. setDistance ( FOLLOW_CAM_DEFAULT_DISTANCE );
  119. setPitch ( FOLLOW_CAM_DEFAULT_PITCH );
  120. setFocusOffset ( FOLLOW_CAM_DEFAULT_FOCUS_OFFSET );
  121. setBehindnessAngle ( FOLLOW_CAM_DEFAULT_BEHINDNESS_ANGLE );
  122. setPositionThreshold( FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD );
  123. setFocusThreshold ( FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD );
  124. }
  125. LLFollowCamParams::~LLFollowCamParams() { }
  126. //---------------------------------------------------------
  127. // buncho set methods
  128. //---------------------------------------------------------
  129. //---------------------------------------------------------
  130. void LLFollowCamParams::setPositionLag( F32 p )
  131. {
  132. mPositionLag = llclamp(p, FOLLOW_CAM_MIN_POSITION_LAG, FOLLOW_CAM_MAX_POSITION_LAG);
  133. }
  134. //---------------------------------------------------------
  135. void LLFollowCamParams::setFocusLag( F32 f )
  136. {
  137. mFocusLag = llclamp(f, FOLLOW_CAM_MIN_FOCUS_LAG, FOLLOW_CAM_MAX_FOCUS_LAG);
  138. }
  139. //---------------------------------------------------------
  140. void LLFollowCamParams::setPositionThreshold( F32 p )
  141. {
  142. mPositionThreshold = llclamp(p, FOLLOW_CAM_MIN_POSITION_THRESHOLD, FOLLOW_CAM_MAX_POSITION_THRESHOLD);
  143. }
  144. //---------------------------------------------------------
  145. void LLFollowCamParams::setFocusThreshold( F32 f )
  146. {
  147. mFocusThreshold = llclamp(f, FOLLOW_CAM_MIN_FOCUS_THRESHOLD, FOLLOW_CAM_MAX_FOCUS_THRESHOLD);
  148. }
  149. //---------------------------------------------------------
  150. void LLFollowCamParams::setPitch( F32 p )
  151. {
  152. mPitch = llclamp(p, FOLLOW_CAM_MIN_PITCH, FOLLOW_CAM_MAX_PITCH);
  153. }
  154. //---------------------------------------------------------
  155. void LLFollowCamParams::setBehindnessLag( F32 b )
  156. {
  157. mBehindnessLag = llclamp(b, FOLLOW_CAM_MIN_BEHINDNESS_LAG, FOLLOW_CAM_MAX_BEHINDNESS_LAG);
  158. }
  159. //---------------------------------------------------------
  160. void LLFollowCamParams::setBehindnessAngle( F32 b )
  161. {
  162. mBehindnessMaxAngle = llclamp(b, FOLLOW_CAM_MIN_BEHINDNESS_ANGLE, FOLLOW_CAM_MAX_BEHINDNESS_ANGLE);
  163. }
  164. //---------------------------------------------------------
  165. void LLFollowCamParams::setDistance( F32 d )
  166. {
  167. mDistance = llclamp(d, FOLLOW_CAM_MIN_DISTANCE, mMaxCameraDistantFromSubject);
  168. }
  169. //---------------------------------------------------------
  170. void LLFollowCamParams::setPositionLocked( bool l )
  171. {
  172. mPositionLocked = l;
  173. }
  174. //---------------------------------------------------------
  175. void LLFollowCamParams::setFocusLocked( bool l )
  176. {
  177. mFocusLocked = l;
  178. }
  179. //---------------------------------------------------------
  180. void LLFollowCamParams::setFocusOffset( const LLVector3& v )
  181. {
  182. mFocusOffset = v;
  183. mFocusOffset.clamp(FOLLOW_CAM_MIN_FOCUS_OFFSET, FOLLOW_CAM_MAX_FOCUS_OFFSET);
  184. }
  185. //---------------------------------------------------------
  186. void LLFollowCamParams::setPosition( const LLVector3& p )
  187. {
  188. mUsePosition = true;
  189. mPosition = p;
  190. }
  191. //---------------------------------------------------------
  192. void LLFollowCamParams::setFocus( const LLVector3& f )
  193. {
  194. mUseFocus = true;
  195. mFocus = f;
  196. }
  197. //---------------------------------------------------------
  198. // buncho get methods
  199. //---------------------------------------------------------
  200. F32 LLFollowCamParams::getPositionLag () const { return mPositionLag; }
  201. F32 LLFollowCamParams::getFocusLag () const { return mFocusLag; }
  202. F32 LLFollowCamParams::getPositionThreshold () const { return mPositionThreshold; }
  203. F32 LLFollowCamParams::getFocusThreshold () const { return mFocusThreshold; }
  204. F32 LLFollowCamParams::getDistance () const { return mDistance; }
  205. F32 LLFollowCamParams::getPitch () const { return mPitch; }
  206. LLVector3 LLFollowCamParams::getFocusOffset () const { return mFocusOffset; }
  207. F32 LLFollowCamParams::getBehindnessAngle () const { return mBehindnessMaxAngle; }
  208. F32 LLFollowCamParams::getBehindnessLag () const { return mBehindnessLag; }
  209. LLVector3 LLFollowCamParams::getPosition () const { return mPosition; }
  210. LLVector3 LLFollowCamParams::getFocus () const { return mFocus; }
  211. bool LLFollowCamParams::getPositionLocked () const { return mPositionLocked; }
  212. bool LLFollowCamParams::getFocusLocked () const { return mFocusLocked; }
  213. //------------------------------------
  214. // Constructor
  215. //------------------------------------
  216. LLFollowCam::LLFollowCam() : LLFollowCamParams()
  217. {
  218. mUpVector = LLVector3::z_axis;
  219. mSubjectPosition = LLVector3::zero;
  220. mSubjectRotation = LLQuaternion::DEFAULT;
  221. mZoomedToMinimumDistance = false;
  222. mPitchCos = mPitchSin = 0.f;
  223. mPitchSineAndCosineNeedToBeUpdated = true;
  224. mSimulatedDistance = mDistance;
  225. }
  226. void LLFollowCam::copyParams(LLFollowCamParams& params)
  227. {
  228. setPositionLag(params.getPositionLag());
  229. setFocusLag(params.getFocusLag());
  230. setFocusThreshold( params.getFocusThreshold());
  231. setPositionThreshold(params.getPositionThreshold());
  232. setPitch(params.getPitch());
  233. setFocusOffset(params.getFocusOffset());
  234. setBehindnessAngle(params.getBehindnessAngle());
  235. setBehindnessLag(params.getBehindnessLag());
  236. setPositionLocked(params.getPositionLocked());
  237. setFocusLocked(params.getFocusLocked());
  238. setDistance(params.getDistance());
  239. if (params.getUsePosition())
  240. {
  241. setPosition(params.getPosition());
  242. }
  243. if (params.getUseFocus())
  244. {
  245. setFocus(params.getFocus());
  246. }
  247. }
  248. //---------------------------------------------------------------------------------------------------------
  249. void LLFollowCam::update()
  250. {
  251. //####################################################################################
  252. // update Focus
  253. //####################################################################################
  254. LLVector3 offsetSubjectPosition = mSubjectPosition + (mFocusOffset * mSubjectRotation);
  255. LLVector3 simulated_pos_agent = gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal);
  256. LLVector3 vectorFromCameraToSubject = offsetSubjectPosition - simulated_pos_agent;
  257. F32 distanceFromCameraToSubject = vectorFromCameraToSubject.magVec();
  258. LLVector3 whereFocusWantsToBe = mFocus;
  259. LLVector3 focus_pt_agent = gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal);
  260. if ( mFocusLocked ) // if focus is locked, only relative focus needs to be updated
  261. {
  262. mRelativeFocus = (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation;
  263. }
  264. else
  265. {
  266. LLVector3 focusOffset = offsetSubjectPosition - focus_pt_agent;
  267. F32 focusOffsetDistance = focusOffset.magVec();
  268. LLVector3 focusOffsetDirection = focusOffset / focusOffsetDistance;
  269. whereFocusWantsToBe = focus_pt_agent +
  270. (focusOffsetDirection * (focusOffsetDistance - mFocusThreshold));
  271. if ( focusOffsetDistance > mFocusThreshold )
  272. {
  273. // this version normalizes focus threshold by distance
  274. // so that the effect is not changed with distance
  275. /*
  276. F32 focusThresholdNormalizedByDistance = distanceFromCameraToSubject * mFocusThreshold;
  277. if ( focusOffsetDistance > focusThresholdNormalizedByDistance )
  278. {
  279. LLVector3 focusOffsetDirection = focusOffset / focusOffsetDistance;
  280. F32 force = focusOffsetDistance - focusThresholdNormalizedByDistance;
  281. */
  282. F32 focusLagLerp = LLCriticalDamp::getInterpolant( mFocusLag );
  283. focus_pt_agent = lerp( focus_pt_agent, whereFocusWantsToBe, focusLagLerp );
  284. mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(focus_pt_agent);
  285. }
  286. mRelativeFocus = lerp(mRelativeFocus, (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation, LLCriticalDamp::getInterpolant(0.05f));
  287. }// if focus is not locked ---------------------------------------------
  288. LLVector3 whereCameraPositionWantsToBe = gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal);
  289. if ( mPositionLocked )
  290. {
  291. mRelativePos = (whereCameraPositionWantsToBe - mSubjectPosition) * ~mSubjectRotation;
  292. }
  293. else
  294. {
  295. //####################################################################################
  296. // update Position
  297. //####################################################################################
  298. //-------------------------------------------------------------------------
  299. // I determine the horizontal vector from the camera to the subject
  300. //-------------------------------------------------------------------------
  301. LLVector3 horizontalVectorFromCameraToSubject = vectorFromCameraToSubject;
  302. horizontalVectorFromCameraToSubject.mV[VZ] = 0.0f;
  303. //---------------------------------------------------------
  304. // Now I determine the horizontal distance
  305. //---------------------------------------------------------
  306. F32 horizontalDistanceFromCameraToSubject = horizontalVectorFromCameraToSubject.magVec();
  307. //---------------------------------------------------------
  308. // Then I get the (normalized) horizontal direction...
  309. //---------------------------------------------------------
  310. LLVector3 horizontalDirectionFromCameraToSubject;
  311. if ( horizontalDistanceFromCameraToSubject < DISTANCE_EPSILON )
  312. {
  313. // make sure we still have a normalized vector if distance is really small
  314. // (this case is rare and fleeting)
  315. horizontalDirectionFromCameraToSubject = LLVector3::z_axis;
  316. }
  317. else
  318. {
  319. // I'm not using the "normalize" method, because I can just divide by horizontalDistanceFromCameraToSubject
  320. horizontalDirectionFromCameraToSubject = horizontalVectorFromCameraToSubject / horizontalDistanceFromCameraToSubject;
  321. }
  322. //------------------------------------------------------------------------------------------------------------
  323. // Here is where I determine an offset relative to subject position in oder to set the ideal position.
  324. //------------------------------------------------------------------------------------------------------------
  325. if ( mPitchSineAndCosineNeedToBeUpdated )
  326. {
  327. calculatePitchSineAndCosine();
  328. mPitchSineAndCosineNeedToBeUpdated = false;
  329. }
  330. LLVector3 positionOffsetFromSubject;
  331. positionOffsetFromSubject.setVec
  332. (
  333. horizontalDirectionFromCameraToSubject.mV[ VX ] * mPitchCos,
  334. horizontalDirectionFromCameraToSubject.mV[ VY ] * mPitchCos,
  335. -mPitchSin
  336. );
  337. positionOffsetFromSubject *= mSimulatedDistance;
  338. //----------------------------------------------------------------------
  339. // Finally, ideal position is set by taking the subject position and
  340. // extending the positionOffsetFromSubject from that
  341. //----------------------------------------------------------------------
  342. LLVector3 idealCameraPosition = offsetSubjectPosition - positionOffsetFromSubject;
  343. //--------------------------------------------------------------------------------
  344. // Now I prepare to move the current camera position towards its ideal position...
  345. //--------------------------------------------------------------------------------
  346. LLVector3 vectorFromPositionToIdealPosition = idealCameraPosition - simulated_pos_agent;
  347. F32 distanceFromPositionToIdealPosition = vectorFromPositionToIdealPosition.magVec();
  348. //put this inside of the block?
  349. LLVector3 normalFromPositionToIdealPosition = vectorFromPositionToIdealPosition / distanceFromPositionToIdealPosition;
  350. whereCameraPositionWantsToBe = simulated_pos_agent +
  351. (normalFromPositionToIdealPosition * (distanceFromPositionToIdealPosition - mPositionThreshold));
  352. //-------------------------------------------------------------------------------------------------
  353. // The following method takes the target camera position and resets it so that it stays "behind" the subject,
  354. // using behindness angle and behindness force as parameters affecting the exact behavior
  355. //-------------------------------------------------------------------------------------------------
  356. if ( distanceFromPositionToIdealPosition > mPositionThreshold )
  357. {
  358. F32 positionPullLerp = LLCriticalDamp::getInterpolant( mPositionLag );
  359. simulated_pos_agent = lerp( simulated_pos_agent, whereCameraPositionWantsToBe, positionPullLerp );
  360. }
  361. //--------------------------------------------------------------------
  362. // don't let the camera get farther than its official max distance
  363. //--------------------------------------------------------------------
  364. if ( distanceFromCameraToSubject > mMaxCameraDistantFromSubject )
  365. {
  366. LLVector3 directionFromCameraToSubject = vectorFromCameraToSubject / distanceFromCameraToSubject;
  367. simulated_pos_agent = offsetSubjectPosition - directionFromCameraToSubject * mMaxCameraDistantFromSubject;
  368. }
  369. ////-------------------------------------------------------------------------------------------------
  370. //// The following method takes mSimulatedPositionGlobal and resets it so that it stays "behind" the subject,
  371. //// using behindness angle and behindness force as parameters affecting the exact behavior
  372. ////-------------------------------------------------------------------------------------------------
  373. updateBehindnessConstraint(gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal), simulated_pos_agent);
  374. mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(simulated_pos_agent);
  375. mRelativePos = lerp(mRelativePos, (simulated_pos_agent - mSubjectPosition) * ~mSubjectRotation, LLCriticalDamp::getInterpolant(0.05f));
  376. } // if position is not locked -----------------------------------------------------------
  377. //####################################################################################
  378. // update UpVector
  379. //####################################################################################
  380. // this just points upward for now, but I anticipate future effects requiring
  381. // some rolling ("banking" effects for fun, swoopy vehicles, etc.)
  382. mUpVector = LLVector3::z_axis;
  383. }
  384. //-------------------------------------------------------------------------------------
  385. BOOL LLFollowCam::updateBehindnessConstraint(LLVector3 focus, LLVector3& cam_position)
  386. {
  387. BOOL constraint_active = FALSE;
  388. // only apply this stuff if the behindness angle is something other than opened up all the way
  389. if ( mBehindnessMaxAngle < FOLLOW_CAM_MAX_BEHINDNESS_ANGLE - FOLLOW_CAM_BEHINDNESS_EPSILON )
  390. {
  391. //--------------------------------------------------------------
  392. // horizontalized vector from focus to camera
  393. //--------------------------------------------------------------
  394. LLVector3 horizontalVectorFromFocusToCamera;
  395. horizontalVectorFromFocusToCamera.setVec(cam_position - focus);
  396. horizontalVectorFromFocusToCamera.mV[ VZ ] = 0.0f;
  397. F32 cameraZ = cam_position.mV[ VZ ];
  398. //--------------------------------------------------------------
  399. // distance of horizontalized vector
  400. //--------------------------------------------------------------
  401. F32 horizontalDistance = horizontalVectorFromFocusToCamera.magVec();
  402. //--------------------------------------------------------------------------------------------------
  403. // calculate horizontalized back vector of the subject and scale by horizontalDistance
  404. //--------------------------------------------------------------------------------------------------
  405. LLVector3 horizontalSubjectBack( -1.0f, 0.0f, 0.0f );
  406. horizontalSubjectBack *= mSubjectRotation;
  407. horizontalSubjectBack.mV[ VZ ] = 0.0f;
  408. horizontalSubjectBack.normVec(); // because horizontalizing might make it shorter than 1
  409. horizontalSubjectBack *= horizontalDistance;
  410. //--------------------------------------------------------------------------------------------------
  411. // find the angle (in degrees) between these vectors
  412. //--------------------------------------------------------------------------------------------------
  413. F32 cameraOffsetAngle = 0.f;
  414. LLVector3 cameraOffsetRotationAxis;
  415. LLQuaternion camera_offset_rotation;
  416. camera_offset_rotation.shortestArc(horizontalSubjectBack, horizontalVectorFromFocusToCamera);
  417. camera_offset_rotation.getAngleAxis(&cameraOffsetAngle, cameraOffsetRotationAxis);
  418. cameraOffsetAngle *= RAD_TO_DEG;
  419. if ( cameraOffsetAngle > mBehindnessMaxAngle )
  420. {
  421. F32 fraction = ((cameraOffsetAngle - mBehindnessMaxAngle) / cameraOffsetAngle) * LLCriticalDamp::getInterpolant(mBehindnessLag);
  422. cam_position = focus + horizontalSubjectBack * (slerp(fraction, camera_offset_rotation, LLQuaternion::DEFAULT));
  423. cam_position.mV[VZ] = cameraZ; // clamp z value back to what it was before we started messing with it
  424. constraint_active = TRUE;
  425. }
  426. }
  427. return constraint_active;
  428. }
  429. //---------------------------------------------------------
  430. void LLFollowCam::calculatePitchSineAndCosine()
  431. {
  432. F32 radian = mPitch * DEG_TO_RAD;
  433. mPitchCos = cos( radian );
  434. mPitchSin = sin( radian );
  435. }
  436. //---------------------------------------------------------
  437. void LLFollowCam::setSubjectPositionAndRotation( const LLVector3 p, const LLQuaternion r )
  438. {
  439. mSubjectPosition = p;
  440. mSubjectRotation = r;
  441. }
  442. //---------------------------------------------------------
  443. void LLFollowCam::zoom( S32 z )
  444. {
  445. F32 zoomAmount = z * mSimulatedDistance * FOLLOW_CAM_ZOOM_FACTOR;
  446. if (( zoomAmount < FOLLOW_CAM_MIN_ZOOM_AMOUNT )
  447. && ( zoomAmount > -FOLLOW_CAM_MIN_ZOOM_AMOUNT ))
  448. {
  449. if ( zoomAmount < 0.0f )
  450. {
  451. zoomAmount = -FOLLOW_CAM_MIN_ZOOM_AMOUNT;
  452. }
  453. else
  454. {
  455. zoomAmount = FOLLOW_CAM_MIN_ZOOM_AMOUNT;
  456. }
  457. }
  458. mSimulatedDistance += zoomAmount;
  459. mZoomedToMinimumDistance = false;
  460. if ( mSimulatedDistance < FOLLOW_CAM_MIN_DISTANCE )
  461. {
  462. mSimulatedDistance = FOLLOW_CAM_MIN_DISTANCE;
  463. // if zoomAmount is negative (i.e., getting closer), then
  464. // this signifies having hit the minimum:
  465. if ( zoomAmount < 0.0f )
  466. {
  467. mZoomedToMinimumDistance = true;
  468. }
  469. }
  470. else if ( mSimulatedDistance > mMaxCameraDistantFromSubject )
  471. {
  472. mSimulatedDistance = mMaxCameraDistantFromSubject;
  473. }
  474. }
  475. //---------------------------------------------------------
  476. bool LLFollowCam::isZoomedToMinimumDistance()
  477. {
  478. return mZoomedToMinimumDistance;
  479. }
  480. //---------------------------------------------------------
  481. void LLFollowCam::reset( const LLVector3 p, const LLVector3 f , const LLVector3 u )
  482. {
  483. setPosition(p);
  484. setFocus(f);
  485. mUpVector = u;
  486. }
  487. //---------------------------------------------------------
  488. void LLFollowCam::setMaxCameraDistantFromSubject( F32 m )
  489. {
  490. mMaxCameraDistantFromSubject = m;
  491. }
  492. void LLFollowCam::setPitch( F32 p )
  493. {
  494. LLFollowCamParams::setPitch(p);
  495. mPitchSineAndCosineNeedToBeUpdated = true; // important
  496. }
  497. void LLFollowCam::setDistance( F32 d )
  498. {
  499. if (d != mDistance)
  500. {
  501. LLFollowCamParams::setDistance(d);
  502. mSimulatedDistance = d;
  503. mZoomedToMinimumDistance = false;
  504. }
  505. }
  506. void LLFollowCam::setPosition( const LLVector3& p )
  507. {
  508. if (p != mPosition)
  509. {
  510. LLFollowCamParams::setPosition(p);
  511. mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(mPosition);
  512. if (mPositionLocked)
  513. {
  514. mRelativePos = (mPosition - mSubjectPosition) * ~mSubjectRotation;
  515. }
  516. }
  517. }
  518. void LLFollowCam::setFocus( const LLVector3& f )
  519. {
  520. if (f != mFocus)
  521. {
  522. LLFollowCamParams::setFocus(f);
  523. mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(f);
  524. if (mFocusLocked)
  525. {
  526. mRelativeFocus = (mFocus - mSubjectPosition) * ~mSubjectRotation;
  527. }
  528. }
  529. }
  530. void LLFollowCam::setPositionLocked( bool locked )
  531. {
  532. LLFollowCamParams::setPositionLocked(locked);
  533. if (locked)
  534. {
  535. // propagate set position to relative position
  536. mRelativePos = (gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal) - mSubjectPosition) * ~mSubjectRotation;
  537. }
  538. }
  539. void LLFollowCam::setFocusLocked( bool locked )
  540. {
  541. LLFollowCamParams::setFocusLocked(locked);
  542. if (locked)
  543. {
  544. // propagate set position to relative position
  545. mRelativeFocus = (gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal) - mSubjectPosition) * ~mSubjectRotation;
  546. }
  547. }
  548. LLVector3 LLFollowCam::getSimulatedPosition() const
  549. {
  550. // return simulated position
  551. return mSubjectPosition + (mRelativePos * mSubjectRotation);
  552. }
  553. LLVector3 LLFollowCam::getSimulatedFocus() const
  554. {
  555. // return simulated focus point
  556. return mSubjectPosition + (mRelativeFocus * mSubjectRotation);
  557. }
  558. LLVector3 LLFollowCam::getUpVector()
  559. {
  560. return mUpVector;
  561. }
  562. //------------------------------------
  563. // Destructor
  564. //------------------------------------
  565. LLFollowCam::~LLFollowCam()
  566. {
  567. }
  568. //-------------------------------------------------------
  569. // LLFollowCamMgr
  570. //-------------------------------------------------------
  571. //static
  572. void LLFollowCamMgr::cleanupClass()
  573. {
  574. for (param_map_t::iterator iter = sParamMap.begin(); iter != sParamMap.end(); ++iter)
  575. {
  576. LLFollowCamParams* params = iter->second;
  577. delete params;
  578. }
  579. sParamMap.clear();
  580. }
  581. //static
  582. void LLFollowCamMgr::setPositionLag( const LLUUID& source, F32 lag)
  583. {
  584. LLFollowCamParams* paramsp = getParamsForID(source);
  585. if (paramsp)
  586. {
  587. paramsp->setPositionLag(lag);
  588. }
  589. }
  590. //static
  591. void LLFollowCamMgr::setFocusLag( const LLUUID& source, F32 lag)
  592. {
  593. LLFollowCamParams* paramsp = getParamsForID(source);
  594. if (paramsp)
  595. {
  596. paramsp->setFocusLag(lag);
  597. }
  598. }
  599. //static
  600. void LLFollowCamMgr::setFocusThreshold( const LLUUID& source, F32 threshold)
  601. {
  602. LLFollowCamParams* paramsp = getParamsForID(source);
  603. if (paramsp)
  604. {
  605. paramsp->setFocusThreshold(threshold);
  606. }
  607. }
  608. //static
  609. void LLFollowCamMgr::setPositionThreshold( const LLUUID& source, F32 threshold)
  610. {
  611. LLFollowCamParams* paramsp = getParamsForID(source);
  612. if (paramsp)
  613. {
  614. paramsp->setPositionThreshold(threshold);
  615. }
  616. }
  617. //static
  618. void LLFollowCamMgr::setDistance( const LLUUID& source, F32 distance)
  619. {
  620. LLFollowCamParams* paramsp = getParamsForID(source);
  621. if (paramsp)
  622. {
  623. paramsp->setDistance(distance);
  624. }
  625. }
  626. //static
  627. void LLFollowCamMgr::setPitch( const LLUUID& source, F32 pitch)
  628. {
  629. LLFollowCamParams* paramsp = getParamsForID(source);
  630. if (paramsp)
  631. {
  632. paramsp->setPitch(pitch);
  633. }
  634. }
  635. //static
  636. void LLFollowCamMgr::setFocusOffset( const LLUUID& source, const LLVector3& offset)
  637. {
  638. LLFollowCamParams* paramsp = getParamsForID(source);
  639. if (paramsp)
  640. {
  641. paramsp->setFocusOffset(offset);
  642. }
  643. }
  644. //static
  645. void LLFollowCamMgr::setBehindnessAngle( const LLUUID& source, F32 angle)
  646. {
  647. LLFollowCamParams* paramsp = getParamsForID(source);
  648. if (paramsp)
  649. {
  650. paramsp->setBehindnessAngle(angle);
  651. }
  652. }
  653. //static
  654. void LLFollowCamMgr::setBehindnessLag( const LLUUID& source, F32 force)
  655. {
  656. LLFollowCamParams* paramsp = getParamsForID(source);
  657. if (paramsp)
  658. {
  659. paramsp->setBehindnessLag(force);
  660. }
  661. }
  662. //static
  663. void LLFollowCamMgr::setPosition( const LLUUID& source, const LLVector3 position)
  664. {
  665. LLFollowCamParams* paramsp = getParamsForID(source);
  666. if (paramsp)
  667. {
  668. paramsp->setPosition(position);
  669. }
  670. }
  671. //static
  672. void LLFollowCamMgr::setFocus( const LLUUID& source, const LLVector3 focus)
  673. {
  674. LLFollowCamParams* paramsp = getParamsForID(source);
  675. if (paramsp)
  676. {
  677. paramsp->setFocus(focus);
  678. }
  679. }
  680. //static
  681. void LLFollowCamMgr::setPositionLocked( const LLUUID& source, bool locked)
  682. {
  683. LLFollowCamParams* paramsp = getParamsForID(source);
  684. if (paramsp)
  685. {
  686. paramsp->setPositionLocked(locked);
  687. }
  688. }
  689. //static
  690. void LLFollowCamMgr::setFocusLocked( const LLUUID& source, bool locked )
  691. {
  692. LLFollowCamParams* paramsp = getParamsForID(source);
  693. if (paramsp)
  694. {
  695. paramsp->setFocusLocked(locked);
  696. }
  697. }
  698. //static
  699. LLFollowCamParams* LLFollowCamMgr::getParamsForID(const LLUUID& source)
  700. {
  701. LLFollowCamParams* params = NULL;
  702. param_map_t::iterator found_it = sParamMap.find(source);
  703. if (found_it == sParamMap.end()) // didn't find it?
  704. {
  705. params = new LLFollowCamParams();
  706. sParamMap[source] = params;
  707. }
  708. else
  709. {
  710. params = found_it->second;
  711. }
  712. return params;
  713. }
  714. //static
  715. LLFollowCamParams* LLFollowCamMgr::getActiveFollowCamParams()
  716. {
  717. if (sParamStack.empty())
  718. {
  719. return NULL;
  720. }
  721. return sParamStack.back();
  722. }
  723. //static
  724. void LLFollowCamMgr::setCameraActive( const LLUUID& source, bool active )
  725. {
  726. LLFollowCamParams* params = getParamsForID(source);
  727. param_stack_t::iterator found_it = std::find(sParamStack.begin(), sParamStack.end(), params);
  728. if (found_it != sParamStack.end())
  729. {
  730. sParamStack.erase(found_it);
  731. }
  732. // put on top of stack
  733. if(active)
  734. {
  735. sParamStack.push_back(params);
  736. }
  737. }
  738. //static
  739. void LLFollowCamMgr::removeFollowCamParams(const LLUUID& source)
  740. {
  741. setCameraActive(source, FALSE);
  742. LLFollowCamParams* params = getParamsForID(source);
  743. sParamMap.erase(source);
  744. delete params;
  745. }
  746. //static
  747. bool LLFollowCamMgr::isScriptedCameraSource(const LLUUID& source)
  748. {
  749. param_map_t::iterator found_it = sParamMap.find(source);
  750. return (found_it != sParamMap.end());
  751. }
  752. //static
  753. void LLFollowCamMgr::dump()
  754. {
  755. S32 param_count = 0;
  756. llinfos << "Scripted camera active stack" << llendl;
  757. for (param_stack_t::iterator param_it = sParamStack.begin();
  758. param_it != sParamStack.end();
  759. ++param_it)
  760. {
  761. llinfos << param_count++ <<
  762. " rot_limit: " << (*param_it)->getBehindnessAngle() <<
  763. " rot_lag: " << (*param_it)->getBehindnessLag() <<
  764. " distance: " << (*param_it)->getDistance() <<
  765. " focus: " << (*param_it)->getFocus() <<
  766. " foc_lag: " << (*param_it)->getFocusLag() <<
  767. " foc_lock: " << ((*param_it)->getFocusLocked() ? "Y" : "N") <<
  768. " foc_offset: " << (*param_it)->getFocusOffset() <<
  769. " foc_thresh: " << (*param_it)->getFocusThreshold() <<
  770. " pitch: " << (*param_it)->getPitch() <<
  771. " pos: " << (*param_it)->getPosition() <<
  772. " pos_lag: " << (*param_it)->getPositionLag() <<
  773. " pos_lock: " << ((*param_it)->getPositionLocked() ? "Y" : "N") <<
  774. " pos_thresh: " << (*param_it)->getPositionThreshold() << llendl;
  775. }
  776. }