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