llfollowcam.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /**
  2. * @file llfollowcam.cpp
  3. * @author Jeffrey Ventrella
  4. * @brief LLFollowCam class implementation
  5. *
  6. * $LicenseInfo:firstyear=2005&license=viewergpl$
  7. *
  8. * Copyright (c) 2005-2009, Linden Research, Inc.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #include "llviewerprecompiledheaders.h"
  34. #include "llfollowcam.h"
  35. #include "llagent.h"
  36. //-----------------------------------------------------------------------------
  37. // Static variables
  38. //-----------------------------------------------------------------------------
  39. LLFollowCamMgr::param_map_t LLFollowCamMgr::sParamMap;
  40. LLFollowCamMgr::param_stack_t LLFollowCamMgr::sParamStack;
  41. //-----------------------------------------------------------------------------
  42. // Constants
  43. //-----------------------------------------------------------------------------
  44. constexpr F32 FOLLOW_CAM_ZOOM_FACTOR = 0.1f;
  45. constexpr F32 FOLLOW_CAM_MIN_ZOOM_AMOUNT = 0.1f;
  46. constexpr F32 DISTANCE_EPSILON = 0.0001f;
  47. // this will be correctly set on me by my caller
  48. constexpr F32 DEFAULT_MAX_DISTANCE_FROM_SUBJECT = 1000.f;
  49. // This is how slowly the camera position moves to its ideal position
  50. constexpr F32 FOLLOW_CAM_MIN_POSITION_LAG = 0.f;
  51. constexpr F32 FOLLOW_CAM_DEFAULT_POSITION_LAG = 0.1f;
  52. constexpr F32 FOLLOW_CAM_MAX_POSITION_LAG = 3.f;
  53. // This is how slowly the camera focus moves to its subject
  54. constexpr F32 FOLLOW_CAM_MIN_FOCUS_LAG = 0.f;
  55. constexpr F32 FOLLOW_CAM_DEFAULT_FOCUS_LAG = 0.1f;
  56. constexpr F32 FOLLOW_CAM_MAX_FOCUS_LAG = 3.f;
  57. // This is far the position can get from its IDEAL POSITION before it starts
  58. // getting pulled
  59. constexpr F32 FOLLOW_CAM_MIN_POSITION_THRESHOLD = 0.f;
  60. constexpr F32 FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD = 1.f;
  61. constexpr F32 FOLLOW_CAM_MAX_POSITION_THRESHOLD = 4.f;
  62. // This is far the focus can get from the subject before it starts getting
  63. // pulled
  64. constexpr F32 FOLLOW_CAM_MIN_FOCUS_THRESHOLD = 0.f;
  65. constexpr F32 FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD = 1.f;
  66. constexpr F32 FOLLOW_CAM_MAX_FOCUS_THRESHOLD = 4.f;
  67. // This is the distance the camera wants to be from the subject
  68. constexpr F32 FOLLOW_CAM_MIN_DISTANCE = 0.5f;
  69. constexpr F32 FOLLOW_CAM_DEFAULT_DISTANCE = 3.f;
  70. // This is an angluar value. It affects the angle that the camera rises
  71. // (pitches) in relation to the horizontal plane
  72. constexpr F32 FOLLOW_CAM_MIN_PITCH = -45.f;
  73. constexpr F32 FOLLOW_CAM_DEFAULT_PITCH = 0.f;
  74. // Keep under 90 degrees TO avoid gimbal lock !
  75. constexpr F32 FOLLOW_CAM_MAX_PITCH = 80.f;
  76. // How high or low the camera considers its ideal focus to be (relative to its
  77. // subject)
  78. constexpr F32 FOLLOW_CAM_MIN_FOCUS_OFFSET = -10.f;
  79. const LLVector3 FOLLOW_CAM_DEFAULT_FOCUS_OFFSET = LLVector3(1.f, 0.f, 0.f);
  80. constexpr F32 FOLLOW_CAM_MAX_FOCUS_OFFSET = 10.f;
  81. // This affects the rate at which the camera adjusts to stay behind the subject
  82. constexpr F32 FOLLOW_CAM_MIN_BEHINDNESS_LAG = 0.f;
  83. constexpr F32 FOLLOW_CAM_DEFAULT_BEHINDNESS_LAG = 0.f;
  84. constexpr F32 FOLLOW_CAM_MAX_BEHINDNESS_LAG = 3.f;
  85. // In degrees: this is the size of the pie slice behind the subject matter
  86. // within which the camera is free to move
  87. constexpr F32 FOLLOW_CAM_MIN_BEHINDNESS_ANGLE = 0.f;
  88. constexpr F32 FOLLOW_CAM_DEFAULT_BEHINDNESS_ANGLE = 10.f;
  89. constexpr F32 FOLLOW_CAM_MAX_BEHINDNESS_ANGLE = 180.f;
  90. constexpr F32 FOLLOW_CAM_BEHINDNESS_EPSILON = 1.f;
  91. //-----------------------------------------------------------------------------
  92. // LLFollowCamParams
  93. //-----------------------------------------------------------------------------
  94. LLFollowCamParams::LLFollowCamParams()
  95. : mMaxCameraDistantFromSubject(DEFAULT_MAX_DISTANCE_FROM_SUBJECT),
  96. mPositionLocked(false),
  97. mFocusLocked(false),
  98. mUsePosition(false),
  99. mUseFocus(false),
  100. mPositionLag(FOLLOW_CAM_DEFAULT_POSITION_LAG),
  101. mFocusLag(FOLLOW_CAM_DEFAULT_FOCUS_LAG),
  102. mPositionThreshold(FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD),
  103. mFocusThreshold(FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD),
  104. mBehindnessLag(FOLLOW_CAM_DEFAULT_BEHINDNESS_LAG),
  105. mPitch(FOLLOW_CAM_DEFAULT_PITCH),
  106. mFocusOffset(FOLLOW_CAM_DEFAULT_FOCUS_OFFSET),
  107. mBehindnessMaxAngle(FOLLOW_CAM_DEFAULT_BEHINDNESS_ANGLE)
  108. {
  109. setDistance(FOLLOW_CAM_DEFAULT_DISTANCE);
  110. }
  111. void LLFollowCamParams::setPositionLag(F32 p)
  112. {
  113. mPositionLag = llclamp(p, FOLLOW_CAM_MIN_POSITION_LAG,
  114. FOLLOW_CAM_MAX_POSITION_LAG);
  115. }
  116. void LLFollowCamParams::setFocusLag(F32 f)
  117. {
  118. mFocusLag = llclamp(f, FOLLOW_CAM_MIN_FOCUS_LAG,
  119. FOLLOW_CAM_MAX_FOCUS_LAG);
  120. }
  121. void LLFollowCamParams::setPositionThreshold(F32 p)
  122. {
  123. mPositionThreshold = llclamp(p, FOLLOW_CAM_MIN_POSITION_THRESHOLD,
  124. FOLLOW_CAM_MAX_POSITION_THRESHOLD);
  125. }
  126. void LLFollowCamParams::setFocusThreshold(F32 f)
  127. {
  128. mFocusThreshold = llclamp(f, FOLLOW_CAM_MIN_FOCUS_THRESHOLD,
  129. FOLLOW_CAM_MAX_FOCUS_THRESHOLD);
  130. }
  131. void LLFollowCamParams::setPitch(F32 p)
  132. {
  133. mPitch = llclamp(p, FOLLOW_CAM_MIN_PITCH, FOLLOW_CAM_MAX_PITCH);
  134. }
  135. void LLFollowCamParams::setBehindnessLag(F32 b)
  136. {
  137. mBehindnessLag = llclamp(b, FOLLOW_CAM_MIN_BEHINDNESS_LAG,
  138. FOLLOW_CAM_MAX_BEHINDNESS_LAG);
  139. }
  140. void LLFollowCamParams::setBehindnessAngle(F32 b)
  141. {
  142. mBehindnessMaxAngle = llclamp(b, FOLLOW_CAM_MIN_BEHINDNESS_ANGLE,
  143. FOLLOW_CAM_MAX_BEHINDNESS_ANGLE);
  144. }
  145. void LLFollowCamParams::setDistance(F32 d)
  146. {
  147. mDistance = llclamp(d, FOLLOW_CAM_MIN_DISTANCE,
  148. mMaxCameraDistantFromSubject);
  149. }
  150. void LLFollowCamParams::setFocusOffset(const LLVector3& v)
  151. {
  152. mFocusOffset = v;
  153. mFocusOffset.clamp(FOLLOW_CAM_MIN_FOCUS_OFFSET,
  154. FOLLOW_CAM_MAX_FOCUS_OFFSET);
  155. }
  156. //-----------------------------------------------------------------------------
  157. // LLFollowCam
  158. //-----------------------------------------------------------------------------
  159. LLFollowCam::LLFollowCam()
  160. : LLFollowCamParams(),
  161. mUpVector(LLVector3::z_axis),
  162. mSubjectPosition(LLVector3::zero),
  163. mSubjectRotation(LLQuaternion::DEFAULT),
  164. mZoomedToMinimumDistance(false),
  165. mPitchCos(0.f),
  166. mPitchSin(0.f),
  167. mPitchSineAndCosineNeedToBeUpdated(true)
  168. {
  169. mSimulatedDistance = mDistance;
  170. }
  171. void LLFollowCam::copyParams(LLFollowCamParams& params)
  172. {
  173. setPositionLag(params.getPositionLag());
  174. setFocusLag(params.getFocusLag());
  175. setFocusThreshold(params.getFocusThreshold());
  176. setPositionThreshold(params.getPositionThreshold());
  177. setPitch(params.getPitch());
  178. setFocusOffset(params.getFocusOffset());
  179. setBehindnessAngle(params.getBehindnessAngle());
  180. setBehindnessLag(params.getBehindnessLag());
  181. setPositionLocked(params.getPositionLocked());
  182. setFocusLocked(params.getFocusLocked());
  183. setDistance(params.getDistance());
  184. if (params.getUsePosition())
  185. {
  186. setPosition(params.getPosition());
  187. }
  188. if (params.getUseFocus())
  189. {
  190. setFocus(params.getFocus());
  191. }
  192. }
  193. void LLFollowCam::update()
  194. {
  195. // Update Focus
  196. LLVector3 offset_subject_pos = mSubjectPosition +
  197. (mFocusOffset * mSubjectRotation);
  198. LLVector3 simulated_pos_agent =
  199. gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal);
  200. LLVector3 vec_to_subject = offset_subject_pos - simulated_pos_agent;
  201. F32 dist_to_subject = vec_to_subject.length();
  202. LLVector3 desired_focus = mFocus;
  203. LLVector3 focus_pt_agent =
  204. gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal);
  205. if (mFocusLocked)
  206. {
  207. // If focus is locked, only relative focus needs to be updated
  208. mRelativeFocus = (focus_pt_agent - mSubjectPosition) *
  209. ~mSubjectRotation;
  210. }
  211. else
  212. {
  213. LLVector3 focus_offset = offset_subject_pos - focus_pt_agent;
  214. F32 focus_offset_dist = focus_offset.length();
  215. LLVector3 focus_offsetDirection = focus_offset / focus_offset_dist;
  216. desired_focus = focus_pt_agent +
  217. (focus_offsetDirection *
  218. (focus_offset_dist - mFocusThreshold));
  219. if (focus_offset_dist > mFocusThreshold)
  220. {
  221. F32 lag_lerp = LLCriticalDamp::getInterpolant(mFocusLag);
  222. focus_pt_agent = lerp(focus_pt_agent, desired_focus, lag_lerp);
  223. mSimulatedFocusGlobal =
  224. gAgent.getPosGlobalFromAgent(focus_pt_agent);
  225. }
  226. mRelativeFocus = lerp(mRelativeFocus,
  227. (focus_pt_agent - mSubjectPosition) *
  228. ~mSubjectRotation,
  229. LLCriticalDamp::getInterpolant(0.05f));
  230. }
  231. LLVector3 desired_cam_pos =
  232. gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal);
  233. if (mPositionLocked)
  234. {
  235. mRelativePos = (desired_cam_pos - mSubjectPosition) *
  236. ~mSubjectRotation;
  237. }
  238. else
  239. {
  240. // Update Position
  241. //---------------------------------------------------------------------
  242. // Determine the horizontal vector from the camera to the subject
  243. //---------------------------------------------------------------------
  244. LLVector3 horiz_vector_to_subject = vec_to_subject;
  245. horiz_vector_to_subject.mV[VZ] = 0.f;
  246. //---------------------------------------------------------------------
  247. // Now I determine the horizontal distance
  248. //---------------------------------------------------------------------
  249. F32 horiz_distance_to_subject = horiz_vector_to_subject.length();
  250. //---------------------------------------------------------------------
  251. // Then I get the (normalized) horizontal direction...
  252. //---------------------------------------------------------------------
  253. LLVector3 horiz_dir_to_subject;
  254. if (horiz_distance_to_subject < DISTANCE_EPSILON)
  255. {
  256. // make sure we still have a normalized vector if distance is
  257. // really small (this case is rare and fleeting)
  258. horiz_dir_to_subject = LLVector3::z_axis;
  259. }
  260. else
  261. {
  262. // Not using the "normalize" method, because we can just divide
  263. // by horiz_distance_to_subject
  264. horiz_dir_to_subject = horiz_vector_to_subject /
  265. horiz_distance_to_subject;
  266. }
  267. //---------------------------------------------------------------------
  268. // Here is where we determine an offset relative to subject position in
  269. // oder to set the ideal position.
  270. //---------------------------------------------------------------------
  271. if (mPitchSineAndCosineNeedToBeUpdated)
  272. {
  273. calculatePitchSineAndCosine();
  274. mPitchSineAndCosineNeedToBeUpdated = false;
  275. }
  276. LLVector3 offset_from_subject(horiz_dir_to_subject.mV[VX] *
  277. mPitchCos,
  278. horiz_dir_to_subject.mV[VY] *
  279. mPitchCos, -mPitchSin);
  280. offset_from_subject *= mSimulatedDistance;
  281. //---------------------------------------------------------------------
  282. // Finally, ideal position is set by taking the subject position and
  283. // extending the offset_from_subject from that
  284. //---------------------------------------------------------------------
  285. LLVector3 ideal_cam_pos = offset_subject_pos - offset_from_subject;
  286. //---------------------------------------------------------------------
  287. // Now I prepare to move the current camera position towards its ideal
  288. // position...
  289. //---------------------------------------------------------------------
  290. LLVector3 vec_to_ideal_pos = ideal_cam_pos - simulated_pos_agent;
  291. F32 dist_to_ideal_pos = vec_to_ideal_pos.length();
  292. // Put this inside of the block ?
  293. LLVector3 normal_to_ideal_pos = vec_to_ideal_pos / dist_to_ideal_pos;
  294. desired_cam_pos = simulated_pos_agent +
  295. normal_to_ideal_pos *
  296. (dist_to_ideal_pos - mPositionThreshold);
  297. //---------------------------------------------------------------------
  298. // The following method takes the target camera position and resets it
  299. // so that it stays "behind" the subject, using behindness angle and
  300. // behindness force as parameters affecting the exact behavior
  301. //---------------------------------------------------------------------
  302. if (dist_to_ideal_pos > mPositionThreshold)
  303. {
  304. F32 pos_pull_lerp = LLCriticalDamp::getInterpolant(mPositionLag);
  305. simulated_pos_agent = lerp(simulated_pos_agent, desired_cam_pos,
  306. pos_pull_lerp);
  307. }
  308. //--------------------------------------------------------------------
  309. // Do not let the camera get farther than its official max distance
  310. //--------------------------------------------------------------------
  311. if (dist_to_subject > mMaxCameraDistantFromSubject)
  312. {
  313. LLVector3 dir_to_subject = vec_to_subject / dist_to_subject;
  314. simulated_pos_agent = offset_subject_pos -
  315. dir_to_subject *
  316. mMaxCameraDistantFromSubject;
  317. }
  318. //---------------------------------------------------------------------
  319. // The following method takes mSimulatedPositionGlobal and resets it so
  320. // that it stays "behind" the subject, using behindness angle and
  321. // behindness force as parameters affecting the exact behavior
  322. //---------------------------------------------------------------------
  323. updateBehindnessConstraint(gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal),
  324. simulated_pos_agent);
  325. mSimulatedPositionGlobal =
  326. gAgent.getPosGlobalFromAgent(simulated_pos_agent);
  327. mRelativePos = lerp(mRelativePos,
  328. (simulated_pos_agent - mSubjectPosition) *
  329. ~mSubjectRotation,
  330. LLCriticalDamp::getInterpolant(0.05f));
  331. }
  332. // Update UpVector. This just points upward for now, but I anticipate
  333. // future effects requiring some rolling ("banking" effects for fun, swoopy
  334. // vehicles, etc)
  335. mUpVector = LLVector3::z_axis;
  336. }
  337. bool LLFollowCam::updateBehindnessConstraint(LLVector3 focus,
  338. LLVector3& cam_position)
  339. {
  340. bool constraint_active = false;
  341. // Only apply this stuff if the behindness angle is something other than
  342. // opened up all the way
  343. if (mBehindnessMaxAngle < FOLLOW_CAM_MAX_BEHINDNESS_ANGLE -
  344. FOLLOW_CAM_BEHINDNESS_EPSILON)
  345. {
  346. //---------------------------------------------------------------------
  347. // Horizontalized vector from focus to camera
  348. //---------------------------------------------------------------------
  349. LLVector3 horiz_vec_to_cam;
  350. horiz_vec_to_cam.set(cam_position - focus);
  351. horiz_vec_to_cam.mV[VZ] = 0.f;
  352. F32 cameraZ = cam_position.mV[VZ];
  353. //---------------------------------------------------------------------
  354. // Distance of horizontalized vector
  355. //---------------------------------------------------------------------
  356. F32 horizontalDistance = horiz_vec_to_cam.length();
  357. //---------------------------------------------------------------------
  358. // Calculate horizontalized back vector of the subject and scale by
  359. // horizontalDistance
  360. //---------------------------------------------------------------------
  361. LLVector3 horiz_subject_back(-1.f, 0.f, 0.f);
  362. horiz_subject_back *= mSubjectRotation;
  363. horiz_subject_back.mV[VZ] = 0.f;
  364. // because horizontalizing might make it shorter than 1
  365. horiz_subject_back.normalize();
  366. horiz_subject_back *= horizontalDistance;
  367. //---------------------------------------------------------------------
  368. // Find the angle (in degrees) between these vectors
  369. //---------------------------------------------------------------------
  370. F32 cam_offset_angle = 0.f;
  371. LLQuaternion camera_offset_rot;
  372. camera_offset_rot.shortestArc(horiz_subject_back, horiz_vec_to_cam);
  373. LLVector3 cam_offset_rot_axis;
  374. camera_offset_rot.getAngleAxis(&cam_offset_angle, cam_offset_rot_axis);
  375. cam_offset_angle *= RAD_TO_DEG;
  376. if (cam_offset_angle > mBehindnessMaxAngle)
  377. {
  378. F32 fraction = ((cam_offset_angle - mBehindnessMaxAngle) /
  379. cam_offset_angle) *
  380. LLCriticalDamp::getInterpolant(mBehindnessLag);
  381. cam_position = focus + horiz_subject_back *
  382. (slerp(fraction, camera_offset_rot,
  383. LLQuaternion::DEFAULT));
  384. // clamp z value back to what it was before we started messing with
  385. // it
  386. cam_position.mV[VZ] = cameraZ;
  387. constraint_active = true;
  388. }
  389. }
  390. return constraint_active;
  391. }
  392. void LLFollowCam::calculatePitchSineAndCosine()
  393. {
  394. F32 radian = mPitch * DEG_TO_RAD;
  395. mPitchCos = cosf(radian);
  396. mPitchSin = sinf(radian);
  397. }
  398. void LLFollowCam::zoom(S32 z)
  399. {
  400. F32 zoomAmount = z * mSimulatedDistance * FOLLOW_CAM_ZOOM_FACTOR;
  401. if (zoomAmount < FOLLOW_CAM_MIN_ZOOM_AMOUNT &&
  402. zoomAmount > -FOLLOW_CAM_MIN_ZOOM_AMOUNT)
  403. {
  404. if (zoomAmount < 0.f)
  405. {
  406. zoomAmount = -FOLLOW_CAM_MIN_ZOOM_AMOUNT;
  407. }
  408. else
  409. {
  410. zoomAmount = FOLLOW_CAM_MIN_ZOOM_AMOUNT;
  411. }
  412. }
  413. mSimulatedDistance += zoomAmount;
  414. mZoomedToMinimumDistance = false;
  415. if (mSimulatedDistance < FOLLOW_CAM_MIN_DISTANCE)
  416. {
  417. mSimulatedDistance = FOLLOW_CAM_MIN_DISTANCE;
  418. // If zoomAmount is negative (i.e. getting closer), then we hit the
  419. // minimum:
  420. if (zoomAmount < 0.f)
  421. {
  422. mZoomedToMinimumDistance = true;
  423. }
  424. }
  425. else if (mSimulatedDistance > mMaxCameraDistantFromSubject)
  426. {
  427. mSimulatedDistance = mMaxCameraDistantFromSubject;
  428. }
  429. }
  430. void LLFollowCam::reset(const LLVector3 p, const LLVector3 f,
  431. const LLVector3 u)
  432. {
  433. setPosition(p);
  434. setFocus(f);
  435. mUpVector = u;
  436. }
  437. void LLFollowCam::setPitch(F32 p)
  438. {
  439. LLFollowCamParams::setPitch(p);
  440. mPitchSineAndCosineNeedToBeUpdated = true; // important
  441. }
  442. void LLFollowCam::setDistance(F32 d)
  443. {
  444. if (d != mDistance)
  445. {
  446. LLFollowCamParams::setDistance(d);
  447. mSimulatedDistance = d;
  448. mZoomedToMinimumDistance = false;
  449. }
  450. }
  451. void LLFollowCam::setPosition(const LLVector3& p)
  452. {
  453. if (p != mPosition)
  454. {
  455. LLFollowCamParams::setPosition(p);
  456. mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(mPosition);
  457. if (mPositionLocked)
  458. {
  459. mRelativePos = (mPosition - mSubjectPosition) * ~mSubjectRotation;
  460. }
  461. }
  462. }
  463. void LLFollowCam::setFocus(const LLVector3& f)
  464. {
  465. if (f != mFocus)
  466. {
  467. LLFollowCamParams::setFocus(f);
  468. mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(f);
  469. if (mFocusLocked)
  470. {
  471. mRelativeFocus = (mFocus - mSubjectPosition) * ~mSubjectRotation;
  472. }
  473. }
  474. }
  475. void LLFollowCam::setPositionLocked(bool locked)
  476. {
  477. LLFollowCamParams::setPositionLocked(locked);
  478. if (locked)
  479. {
  480. // Propagate set position to relative position
  481. mRelativePos =
  482. (gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal) -
  483. mSubjectPosition) * ~mSubjectRotation;
  484. }
  485. }
  486. void LLFollowCam::setFocusLocked(bool locked)
  487. {
  488. LLFollowCamParams::setFocusLocked(locked);
  489. if (locked)
  490. {
  491. // Propagate set position to relative position
  492. mRelativeFocus = (gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal) -
  493. mSubjectPosition) * ~mSubjectRotation;
  494. }
  495. }
  496. //-----------------------------------------------------------------------------
  497. // LLFollowCamMgr class
  498. //-----------------------------------------------------------------------------
  499. //static
  500. void LLFollowCamMgr::cleanupClass()
  501. {
  502. for (auto it = sParamMap.begin(), end = sParamMap.end(); it != end; ++it)
  503. {
  504. delete it->second;
  505. }
  506. sParamMap.clear();
  507. sParamStack.clear();
  508. }
  509. //static
  510. void LLFollowCamMgr::setPositionLag(const LLUUID& source, F32 lag)
  511. {
  512. LLFollowCamParams* paramsp = getParamsForID(source);
  513. if (paramsp)
  514. {
  515. paramsp->setPositionLag(lag);
  516. }
  517. }
  518. //static
  519. void LLFollowCamMgr::setFocusLag(const LLUUID& source, F32 lag)
  520. {
  521. LLFollowCamParams* paramsp = getParamsForID(source);
  522. if (paramsp)
  523. {
  524. paramsp->setFocusLag(lag);
  525. }
  526. }
  527. //static
  528. void LLFollowCamMgr::setFocusThreshold(const LLUUID& source, F32 threshold)
  529. {
  530. LLFollowCamParams* paramsp = getParamsForID(source);
  531. if (paramsp)
  532. {
  533. paramsp->setFocusThreshold(threshold);
  534. }
  535. }
  536. //static
  537. void LLFollowCamMgr::setPositionThreshold(const LLUUID& source, F32 threshold)
  538. {
  539. LLFollowCamParams* paramsp = getParamsForID(source);
  540. if (paramsp)
  541. {
  542. paramsp->setPositionThreshold(threshold);
  543. }
  544. }
  545. //static
  546. void LLFollowCamMgr::setDistance(const LLUUID& source, F32 distance)
  547. {
  548. LLFollowCamParams* paramsp = getParamsForID(source);
  549. if (paramsp)
  550. {
  551. paramsp->setDistance(distance);
  552. }
  553. }
  554. //static
  555. void LLFollowCamMgr::setPitch(const LLUUID& source, F32 pitch)
  556. {
  557. LLFollowCamParams* paramsp = getParamsForID(source);
  558. if (paramsp)
  559. {
  560. paramsp->setPitch(pitch);
  561. }
  562. }
  563. //static
  564. void LLFollowCamMgr::setFocusOffset(const LLUUID& source,
  565. const LLVector3& offset)
  566. {
  567. LLFollowCamParams* paramsp = getParamsForID(source);
  568. if (paramsp)
  569. {
  570. paramsp->setFocusOffset(offset);
  571. }
  572. }
  573. //static
  574. void LLFollowCamMgr::setBehindnessAngle(const LLUUID& source, F32 angle)
  575. {
  576. LLFollowCamParams* paramsp = getParamsForID(source);
  577. if (paramsp)
  578. {
  579. paramsp->setBehindnessAngle(angle);
  580. }
  581. }
  582. //static
  583. void LLFollowCamMgr::setBehindnessLag(const LLUUID& source, F32 force)
  584. {
  585. LLFollowCamParams* paramsp = getParamsForID(source);
  586. if (paramsp)
  587. {
  588. paramsp->setBehindnessLag(force);
  589. }
  590. }
  591. //static
  592. void LLFollowCamMgr::setPosition(const LLUUID& source,
  593. const LLVector3 position)
  594. {
  595. LLFollowCamParams* paramsp = getParamsForID(source);
  596. if (paramsp)
  597. {
  598. paramsp->setPosition(position);
  599. }
  600. }
  601. //static
  602. void LLFollowCamMgr::setFocus(const LLUUID& source, const LLVector3 focus)
  603. {
  604. LLFollowCamParams* paramsp = getParamsForID(source);
  605. if (paramsp)
  606. {
  607. paramsp->setFocus(focus);
  608. }
  609. }
  610. //static
  611. void LLFollowCamMgr::setPositionLocked(const LLUUID& source, bool locked)
  612. {
  613. LLFollowCamParams* paramsp = getParamsForID(source);
  614. if (paramsp)
  615. {
  616. paramsp->setPositionLocked(locked);
  617. }
  618. }
  619. //static
  620. void LLFollowCamMgr::setFocusLocked(const LLUUID& source, bool locked)
  621. {
  622. LLFollowCamParams* paramsp = getParamsForID(source);
  623. if (paramsp)
  624. {
  625. paramsp->setFocusLocked(locked);
  626. }
  627. }
  628. //static
  629. LLFollowCamParams* LLFollowCamMgr::getParamsForID(const LLUUID& source)
  630. {
  631. LLFollowCamParams* params = NULL;
  632. param_map_t::iterator found_it = sParamMap.find(source);
  633. if (found_it == sParamMap.end()) // didn't find it?
  634. {
  635. params = new LLFollowCamParams();
  636. sParamMap[source] = params;
  637. }
  638. else
  639. {
  640. params = found_it->second;
  641. }
  642. return params;
  643. }
  644. //static
  645. void LLFollowCamMgr::setCameraActive(const LLUUID& source, bool active)
  646. {
  647. LLFollowCamParams* params = getParamsForID(source);
  648. param_stack_t::iterator found_it = std::find(sParamStack.begin(),
  649. sParamStack.end(), params);
  650. if (found_it != sParamStack.end())
  651. {
  652. sParamStack.erase(found_it);
  653. }
  654. // Put on top of stack
  655. if (active)
  656. {
  657. sParamStack.push_back(params);
  658. }
  659. }
  660. //static
  661. void LLFollowCamMgr::removeFollowCamParams(const LLUUID& source)
  662. {
  663. setCameraActive(source, false);
  664. LLFollowCamParams* params = getParamsForID(source);
  665. sParamMap.erase(source);
  666. delete params;
  667. }
  668. //static
  669. void LLFollowCamMgr::dump()
  670. {
  671. S32 param_count = 0;
  672. llinfos << "Scripted camera active stack" << llendl;
  673. for (S32 i = 0, count = sParamStack.size(); i < count; ++i)
  674. {
  675. LLFollowCamParams* params = sParamStack[i];
  676. llinfos << param_count++
  677. << " - rot_limit: " << params->getBehindnessAngle()
  678. << " - rot_lag: " << params->getBehindnessLag()
  679. << " - distance: " << params->getDistance()
  680. << " - focus: " << params->getFocus()
  681. << " - foc_lag: " << params->getFocusLag()
  682. << " - foc_lock: " << (params->getFocusLocked() ? "Y" : "N")
  683. << " - foc_offset: " << params->getFocusOffset()
  684. << " - foc_thresh: " << params->getFocusThreshold()
  685. << " - pitch: " << params->getPitch()
  686. << " - pos: " << params->getPosition()
  687. << " - pos_lag: " << params->getPositionLag()
  688. << " - pos_lock: " << (params->getPositionLocked() ? "Y" : "N")
  689. << " - pos_thresh: " << params->getPositionThreshold()
  690. << llendl;
  691. }
  692. }