diff options
Diffstat (limited to 'indra/newview/llfollowcam.cpp')
-rw-r--r-- | indra/newview/llfollowcam.cpp | 1756 |
1 files changed, 878 insertions, 878 deletions
diff --git a/indra/newview/llfollowcam.cpp b/indra/newview/llfollowcam.cpp index 8ce6dc6ef4..89f77414a1 100644 --- a/indra/newview/llfollowcam.cpp +++ b/indra/newview/llfollowcam.cpp @@ -1,878 +1,878 @@ -/**
- * @file llfollowcam.cpp
- * @author Jeffrey Ventrella
- * @brief LLFollowCam class implementation
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llfollowcam.h"
-#include "llagent.h"
-
-//-------------------------------------------------------
-// constants
-//-------------------------------------------------------
-const F32 FOLLOW_CAM_ZOOM_FACTOR = 0.1f;
-const F32 FOLLOW_CAM_MIN_ZOOM_AMOUNT = 0.1f;
-const F32 DISTANCE_EPSILON = 0.0001f;
-const F32 DEFAULT_MAX_DISTANCE_FROM_SUBJECT = 1000.0; // this will be correctly set on me by my caller
-
-//----------------------------------------------------------------------------------------
-// This is how slowly the camera position moves to its ideal position
-//----------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_POSITION_LAG = 0.0f;
-const F32 FOLLOW_CAM_DEFAULT_POSITION_LAG = 0.1f;
-const F32 FOLLOW_CAM_MAX_POSITION_LAG = 3.0f;
-
-//----------------------------------------------------------------------------------------
-// This is how slowly the camera focus moves to its subject
-//----------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_FOCUS_LAG = 0.0f;
-const F32 FOLLOW_CAM_DEFAULT_FOCUS_LAG = 0.1f;
-const F32 FOLLOW_CAM_MAX_FOCUS_LAG = 3.0f;
-
-//----------------------------------------------------------------------------------------
-// This is far the position can get from its IDEAL POSITION before it starts getting pulled
-//----------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_POSITION_THRESHOLD = 0.0f;
-const F32 FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD = 1.0f;
-const F32 FOLLOW_CAM_MAX_POSITION_THRESHOLD = 4.0f;
-
-//----------------------------------------------------------------------------------------
-// This is far the focus can get from the subject before it starts getting pulled
-//----------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_FOCUS_THRESHOLD = 0.0f;
-const F32 FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD = 1.0f;
-const F32 FOLLOW_CAM_MAX_FOCUS_THRESHOLD = 4.0f;
-
-//----------------------------------------------------------------------------------------
-// This is the distance the camera wants to be from the subject
-//----------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_DISTANCE = 0.5f;
-const F32 FOLLOW_CAM_DEFAULT_DISTANCE = 3.0f;
-//const F32 FOLLOW_CAM_MAX_DISTANCE = 10.0f; // from now on I am using mMaxCameraDistantFromSubject
-
-//----------------------------------------------------------------------------------------
-// this is an angluar value
-// It affects the angle that the camera rises (pitches) in relation
-// to the horizontal plane
-//----------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_PITCH = -45.0f;
-const F32 FOLLOW_CAM_DEFAULT_PITCH = 0.0f;
-const F32 FOLLOW_CAM_MAX_PITCH = 80.0f; // keep under 90 degrees - avoid gimble lock!
-
-
-//----------------------------------------------------------------------------------------
-// how high or low the camera considers its ideal focus to be (relative to its subject)
-//----------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_FOCUS_OFFSET = -10.0f;
-const LLVector3 FOLLOW_CAM_DEFAULT_FOCUS_OFFSET = LLVector3(1.0f, 0.f, 0.f);
-const F32 FOLLOW_CAM_MAX_FOCUS_OFFSET = 10.0f;
-
-//----------------------------------------------------------------------------------------
-// This affects the rate at which the camera adjusts to stay behind the subject
-//----------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_BEHINDNESS_LAG = 0.0f;
-const F32 FOLLOW_CAM_DEFAULT_BEHINDNESS_LAG = 0.f;
-const F32 FOLLOW_CAM_MAX_BEHINDNESS_LAG = 3.0f;
-
-//---------------------------------------------------------------------------------------------------------------------
-// in degrees: This is the size of the pie slice behind the subject matter within which the camera is free to move
-//---------------------------------------------------------------------------------------------------------------------
-const F32 FOLLOW_CAM_MIN_BEHINDNESS_ANGLE = 0.0f;
-const F32 FOLLOW_CAM_DEFAULT_BEHINDNESS_ANGLE = 10.0f;
-const F32 FOLLOW_CAM_MAX_BEHINDNESS_ANGLE = 180.0f;
-const F32 FOLLOW_CAM_BEHINDNESS_EPSILON = 1.0f;
-
-//------------------------------------
-// Constructor
-//------------------------------------
-LLFollowCamParams::LLFollowCamParams()
-{
- mMaxCameraDistantFromSubject = DEFAULT_MAX_DISTANCE_FROM_SUBJECT;
- mPositionLocked = false;
- mFocusLocked = false;
- mUsePosition = false;
- mUseFocus = false;
-
- //------------------------------------------------------
- // setting the attributes to their defaults
- //------------------------------------------------------
- setPositionLag ( FOLLOW_CAM_DEFAULT_POSITION_LAG );
- setFocusLag ( FOLLOW_CAM_DEFAULT_FOCUS_LAG );
- setPositionThreshold( FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD );
- setFocusThreshold ( FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD );
- setBehindnessLag ( FOLLOW_CAM_DEFAULT_BEHINDNESS_LAG );
- setDistance ( FOLLOW_CAM_DEFAULT_DISTANCE );
- setPitch ( FOLLOW_CAM_DEFAULT_PITCH );
- setFocusOffset ( FOLLOW_CAM_DEFAULT_FOCUS_OFFSET );
- setBehindnessAngle ( FOLLOW_CAM_DEFAULT_BEHINDNESS_ANGLE );
- setPositionThreshold( FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD );
- setFocusThreshold ( FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD );
-
-}
-
-LLFollowCamParams::~LLFollowCamParams() { }
-
-//---------------------------------------------------------
-// buncho set methods
-//---------------------------------------------------------
-
-//---------------------------------------------------------
-void LLFollowCamParams::setPositionLag( F32 p )
-{
- mPositionLag = llclamp(p, FOLLOW_CAM_MIN_POSITION_LAG, FOLLOW_CAM_MAX_POSITION_LAG);
-}
-
-
-//---------------------------------------------------------
-void LLFollowCamParams::setFocusLag( F32 f )
-{
- mFocusLag = llclamp(f, FOLLOW_CAM_MIN_FOCUS_LAG, FOLLOW_CAM_MAX_FOCUS_LAG);
-}
-
-
-//---------------------------------------------------------
-void LLFollowCamParams::setPositionThreshold( F32 p )
-{
- mPositionThreshold = llclamp(p, FOLLOW_CAM_MIN_POSITION_THRESHOLD, FOLLOW_CAM_MAX_POSITION_THRESHOLD);
-}
-
-
-//---------------------------------------------------------
-void LLFollowCamParams::setFocusThreshold( F32 f )
-{
- mFocusThreshold = llclamp(f, FOLLOW_CAM_MIN_FOCUS_THRESHOLD, FOLLOW_CAM_MAX_FOCUS_THRESHOLD);
-}
-
-
-//---------------------------------------------------------
-void LLFollowCamParams::setPitch( F32 p )
-{
- mPitch = llclamp(p, FOLLOW_CAM_MIN_PITCH, FOLLOW_CAM_MAX_PITCH);
-}
-
-
-//---------------------------------------------------------
-void LLFollowCamParams::setBehindnessLag( F32 b )
-{
- mBehindnessLag = llclamp(b, FOLLOW_CAM_MIN_BEHINDNESS_LAG, FOLLOW_CAM_MAX_BEHINDNESS_LAG);
-}
-
-//---------------------------------------------------------
-void LLFollowCamParams::setBehindnessAngle( F32 b )
-{
- mBehindnessMaxAngle = llclamp(b, FOLLOW_CAM_MIN_BEHINDNESS_ANGLE, FOLLOW_CAM_MAX_BEHINDNESS_ANGLE);
-}
-
-//---------------------------------------------------------
-void LLFollowCamParams::setDistance( F32 d )
-{
- mDistance = llclamp(d, FOLLOW_CAM_MIN_DISTANCE, mMaxCameraDistantFromSubject);
-}
-
-//---------------------------------------------------------
-void LLFollowCamParams::setPositionLocked( bool l )
-{
- mPositionLocked = l;
-}
-
-//---------------------------------------------------------
-void LLFollowCamParams::setFocusLocked( bool l )
-{
- mFocusLocked = l;
-
-}
-
-//---------------------------------------------------------
-void LLFollowCamParams::setFocusOffset( const LLVector3& v )
-{
- mFocusOffset = v;
- mFocusOffset.clamp(FOLLOW_CAM_MIN_FOCUS_OFFSET, FOLLOW_CAM_MAX_FOCUS_OFFSET);
-}
-
-//---------------------------------------------------------
-void LLFollowCamParams::setPosition( const LLVector3& p )
-{
- mUsePosition = true;
- mPosition = p;
-}
-
-//---------------------------------------------------------
-void LLFollowCamParams::setFocus( const LLVector3& f )
-{
- mUseFocus = true;
- mFocus = f;
-}
-
-//---------------------------------------------------------
-// buncho get methods
-//---------------------------------------------------------
-F32 LLFollowCamParams::getPositionLag () const { return mPositionLag; }
-F32 LLFollowCamParams::getFocusLag () const { return mFocusLag; }
-F32 LLFollowCamParams::getPositionThreshold () const { return mPositionThreshold; }
-F32 LLFollowCamParams::getFocusThreshold () const { return mFocusThreshold; }
-F32 LLFollowCamParams::getDistance () const { return mDistance; }
-F32 LLFollowCamParams::getPitch () const { return mPitch; }
-LLVector3 LLFollowCamParams::getFocusOffset () const { return mFocusOffset; }
-F32 LLFollowCamParams::getBehindnessAngle () const { return mBehindnessMaxAngle; }
-F32 LLFollowCamParams::getBehindnessLag () const { return mBehindnessLag; }
-LLVector3 LLFollowCamParams::getPosition () const { return mPosition; }
-LLVector3 LLFollowCamParams::getFocus () const { return mFocus; }
-bool LLFollowCamParams::getPositionLocked () const { return mPositionLocked; }
-bool LLFollowCamParams::getFocusLocked () const { return mFocusLocked; }
-
-//------------------------------------
-// Constructor
-//------------------------------------
-LLFollowCam::LLFollowCam() : LLFollowCamParams()
-{
- mUpVector = LLVector3::z_axis;
- mSubjectPosition = LLVector3::zero;
- mSubjectRotation = LLQuaternion::DEFAULT;
-
- mZoomedToMinimumDistance = false;
- mPitchCos = mPitchSin = 0.f;
- mPitchSineAndCosineNeedToBeUpdated = true;
-
- mSimulatedDistance = mDistance;
-}
-
-void LLFollowCam::copyParams(LLFollowCamParams& params)
-{
- setPositionLag(params.getPositionLag());
- setFocusLag(params.getFocusLag());
- setFocusThreshold( params.getFocusThreshold());
- setPositionThreshold(params.getPositionThreshold());
- setPitch(params.getPitch());
- setFocusOffset(params.getFocusOffset());
- setBehindnessAngle(params.getBehindnessAngle());
- setBehindnessLag(params.getBehindnessLag());
-
- setPositionLocked(params.getPositionLocked());
- setFocusLocked(params.getFocusLocked());
-
- setDistance(params.getDistance());
- if (params.getUsePosition())
- {
- setPosition(params.getPosition());
- }
- if (params.getUseFocus())
- {
- setFocus(params.getFocus());
- }
-}
-
-//---------------------------------------------------------------------------------------------------------
-void LLFollowCam::update()
-{
- //####################################################################################
- // update Focus
- //####################################################################################
- LLVector3 offsetSubjectPosition = mSubjectPosition + (mFocusOffset * mSubjectRotation);
-
- LLVector3 simulated_pos_agent = gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal);
- LLVector3 vectorFromCameraToSubject = offsetSubjectPosition - simulated_pos_agent;
- F32 distanceFromCameraToSubject = vectorFromCameraToSubject.magVec();
-
- LLVector3 whereFocusWantsToBe = mFocus;
- LLVector3 focus_pt_agent = gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal);
- if ( mFocusLocked ) // if focus is locked, only relative focus needs to be updated
- {
- mRelativeFocus = (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation;
- }
- else
- {
- LLVector3 focusOffset = offsetSubjectPosition - focus_pt_agent;
- F32 focusOffsetDistance = focusOffset.magVec();
-
- LLVector3 focusOffsetDirection = focusOffset / focusOffsetDistance;
- whereFocusWantsToBe = focus_pt_agent +
- (focusOffsetDirection * (focusOffsetDistance - mFocusThreshold));
- if ( focusOffsetDistance > mFocusThreshold )
- {
- // this version normalizes focus threshold by distance
- // so that the effect is not changed with distance
- /*
- F32 focusThresholdNormalizedByDistance = distanceFromCameraToSubject * mFocusThreshold;
- if ( focusOffsetDistance > focusThresholdNormalizedByDistance )
- {
- LLVector3 focusOffsetDirection = focusOffset / focusOffsetDistance;
- F32 force = focusOffsetDistance - focusThresholdNormalizedByDistance;
- */
-
- F32 focusLagLerp = LLSmoothInterpolation::getInterpolant( mFocusLag );
- focus_pt_agent = lerp( focus_pt_agent, whereFocusWantsToBe, focusLagLerp );
- mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(focus_pt_agent);
- }
- mRelativeFocus = lerp(mRelativeFocus, (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation, LLSmoothInterpolation::getInterpolant(0.05f));
- }// if focus is not locked ---------------------------------------------
-
-
- LLVector3 whereCameraPositionWantsToBe = gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal);
- if ( mPositionLocked )
- {
- mRelativePos = (whereCameraPositionWantsToBe - mSubjectPosition) * ~mSubjectRotation;
- }
- else
- {
- //####################################################################################
- // update Position
- //####################################################################################
- //-------------------------------------------------------------------------
- // I determine the horizontal vector from the camera to the subject
- //-------------------------------------------------------------------------
- LLVector3 horizontalVectorFromCameraToSubject = vectorFromCameraToSubject;
- horizontalVectorFromCameraToSubject.mV[VZ] = 0.0f;
-
- //---------------------------------------------------------
- // Now I determine the horizontal distance
- //---------------------------------------------------------
- F32 horizontalDistanceFromCameraToSubject = horizontalVectorFromCameraToSubject.magVec();
-
- //---------------------------------------------------------
- // Then I get the (normalized) horizontal direction...
- //---------------------------------------------------------
- LLVector3 horizontalDirectionFromCameraToSubject;
- if ( horizontalDistanceFromCameraToSubject < DISTANCE_EPSILON )
- {
- // make sure we still have a normalized vector if distance is really small
- // (this case is rare and fleeting)
- horizontalDirectionFromCameraToSubject = LLVector3::z_axis;
- }
- else
- {
- // I'm not using the "normalize" method, because I can just divide by horizontalDistanceFromCameraToSubject
- horizontalDirectionFromCameraToSubject = horizontalVectorFromCameraToSubject / horizontalDistanceFromCameraToSubject;
- }
-
- //------------------------------------------------------------------------------------------------------------
- // Here is where I determine an offset relative to subject position in oder to set the ideal position.
- //------------------------------------------------------------------------------------------------------------
- if ( mPitchSineAndCosineNeedToBeUpdated )
- {
- calculatePitchSineAndCosine();
- mPitchSineAndCosineNeedToBeUpdated = false;
- }
-
- LLVector3 positionOffsetFromSubject;
- positionOffsetFromSubject.setVec
- (
- horizontalDirectionFromCameraToSubject.mV[ VX ] * mPitchCos,
- horizontalDirectionFromCameraToSubject.mV[ VY ] * mPitchCos,
- -mPitchSin
- );
-
- positionOffsetFromSubject *= mSimulatedDistance;
-
- //----------------------------------------------------------------------
- // Finally, ideal position is set by taking the subject position and
- // extending the positionOffsetFromSubject from that
- //----------------------------------------------------------------------
- LLVector3 idealCameraPosition = offsetSubjectPosition - positionOffsetFromSubject;
-
- //--------------------------------------------------------------------------------
- // Now I prepare to move the current camera position towards its ideal position...
- //--------------------------------------------------------------------------------
- LLVector3 vectorFromPositionToIdealPosition = idealCameraPosition - simulated_pos_agent;
- F32 distanceFromPositionToIdealPosition = vectorFromPositionToIdealPosition.magVec();
-
- //put this inside of the block?
- LLVector3 normalFromPositionToIdealPosition = vectorFromPositionToIdealPosition / distanceFromPositionToIdealPosition;
-
- whereCameraPositionWantsToBe = simulated_pos_agent +
- (normalFromPositionToIdealPosition * (distanceFromPositionToIdealPosition - mPositionThreshold));
- //-------------------------------------------------------------------------------------------------
- // The following method takes the target camera position and resets it so that it stays "behind" the subject,
- // using behindness angle and behindness force as parameters affecting the exact behavior
- //-------------------------------------------------------------------------------------------------
- if ( distanceFromPositionToIdealPosition > mPositionThreshold )
- {
- F32 positionPullLerp = LLSmoothInterpolation::getInterpolant( mPositionLag );
- simulated_pos_agent = lerp( simulated_pos_agent, whereCameraPositionWantsToBe, positionPullLerp );
- }
-
- //--------------------------------------------------------------------
- // don't let the camera get farther than its official max distance
- //--------------------------------------------------------------------
- if ( distanceFromCameraToSubject > mMaxCameraDistantFromSubject )
- {
- LLVector3 directionFromCameraToSubject = vectorFromCameraToSubject / distanceFromCameraToSubject;
- simulated_pos_agent = offsetSubjectPosition - directionFromCameraToSubject * mMaxCameraDistantFromSubject;
- }
-
- ////-------------------------------------------------------------------------------------------------
- //// The following method takes mSimulatedPositionGlobal and resets it so that it stays "behind" the subject,
- //// using behindness angle and behindness force as parameters affecting the exact behavior
- ////-------------------------------------------------------------------------------------------------
- updateBehindnessConstraint(gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal), simulated_pos_agent);
- mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(simulated_pos_agent);
-
- mRelativePos = lerp(mRelativePos, (simulated_pos_agent - mSubjectPosition) * ~mSubjectRotation, LLSmoothInterpolation::getInterpolant(0.05f));
- } // if position is not locked -----------------------------------------------------------
-
-
- //####################################################################################
- // update UpVector
- //####################################################################################
- // this just points upward for now, but I anticipate future effects requiring
- // some rolling ("banking" effects for fun, swoopy vehicles, etc.)
- mUpVector = LLVector3::z_axis;
-}
-
-
-
-//-------------------------------------------------------------------------------------
-bool LLFollowCam::updateBehindnessConstraint(LLVector3 focus, LLVector3& cam_position)
-{
- bool constraint_active = false;
- // only apply this stuff if the behindness angle is something other than opened up all the way
- if ( mBehindnessMaxAngle < FOLLOW_CAM_MAX_BEHINDNESS_ANGLE - FOLLOW_CAM_BEHINDNESS_EPSILON )
- {
- //--------------------------------------------------------------
- // horizontalized vector from focus to camera
- //--------------------------------------------------------------
- LLVector3 horizontalVectorFromFocusToCamera;
- horizontalVectorFromFocusToCamera.setVec(cam_position - focus);
- horizontalVectorFromFocusToCamera.mV[ VZ ] = 0.0f;
- F32 cameraZ = cam_position.mV[ VZ ];
-
- //--------------------------------------------------------------
- // distance of horizontalized vector
- //--------------------------------------------------------------
- F32 horizontalDistance = horizontalVectorFromFocusToCamera.magVec();
-
- //--------------------------------------------------------------------------------------------------
- // calculate horizontalized back vector of the subject and scale by horizontalDistance
- //--------------------------------------------------------------------------------------------------
- LLVector3 horizontalSubjectBack( -1.0f, 0.0f, 0.0f );
- horizontalSubjectBack *= mSubjectRotation;
- horizontalSubjectBack.mV[ VZ ] = 0.0f;
- horizontalSubjectBack.normVec(); // because horizontalizing might make it shorter than 1
- horizontalSubjectBack *= horizontalDistance;
-
- //--------------------------------------------------------------------------------------------------
- // find the angle (in degrees) between these vectors
- //--------------------------------------------------------------------------------------------------
- F32 cameraOffsetAngle = 0.f;
- LLVector3 cameraOffsetRotationAxis;
- LLQuaternion camera_offset_rotation;
- camera_offset_rotation.shortestArc(horizontalSubjectBack, horizontalVectorFromFocusToCamera);
- camera_offset_rotation.getAngleAxis(&cameraOffsetAngle, cameraOffsetRotationAxis);
- cameraOffsetAngle *= RAD_TO_DEG;
-
- if ( cameraOffsetAngle > mBehindnessMaxAngle )
- {
- F32 fraction = ((cameraOffsetAngle - mBehindnessMaxAngle) / cameraOffsetAngle) * LLSmoothInterpolation::getInterpolant(mBehindnessLag);
- cam_position = focus + horizontalSubjectBack * (slerp(fraction, camera_offset_rotation, LLQuaternion::DEFAULT));
- cam_position.mV[VZ] = cameraZ; // clamp z value back to what it was before we started messing with it
- constraint_active = true;
- }
- }
- return constraint_active;
-}
-
-
-//---------------------------------------------------------
-void LLFollowCam::calculatePitchSineAndCosine()
-{
- F32 radian = mPitch * DEG_TO_RAD;
- mPitchCos = cos( radian );
- mPitchSin = sin( radian );
-}
-
-//---------------------------------------------------------
-void LLFollowCam::setSubjectPositionAndRotation( const LLVector3 p, const LLQuaternion r )
-{
- mSubjectPosition = p;
- mSubjectRotation = r;
-}
-
-
-//---------------------------------------------------------
-void LLFollowCam::zoom( S32 z )
-{
- F32 zoomAmount = z * mSimulatedDistance * FOLLOW_CAM_ZOOM_FACTOR;
-
- if (( zoomAmount < FOLLOW_CAM_MIN_ZOOM_AMOUNT )
- && ( zoomAmount > -FOLLOW_CAM_MIN_ZOOM_AMOUNT ))
- {
- if ( zoomAmount < 0.0f )
- {
- zoomAmount = -FOLLOW_CAM_MIN_ZOOM_AMOUNT;
- }
- else
- {
- zoomAmount = FOLLOW_CAM_MIN_ZOOM_AMOUNT;
- }
- }
-
- mSimulatedDistance += zoomAmount;
-
- mZoomedToMinimumDistance = false;
- if ( mSimulatedDistance < FOLLOW_CAM_MIN_DISTANCE )
- {
- mSimulatedDistance = FOLLOW_CAM_MIN_DISTANCE;
-
- // if zoomAmount is negative (i.e., getting closer), then
- // this signifies having hit the minimum:
- if ( zoomAmount < 0.0f )
- {
- mZoomedToMinimumDistance = true;
- }
- }
- else if ( mSimulatedDistance > mMaxCameraDistantFromSubject )
- {
- mSimulatedDistance = mMaxCameraDistantFromSubject;
- }
-}
-
-
-//---------------------------------------------------------
-bool LLFollowCam::isZoomedToMinimumDistance()
-{
- return mZoomedToMinimumDistance;
-}
-
-
-//---------------------------------------------------------
-void LLFollowCam::reset( const LLVector3 p, const LLVector3 f , const LLVector3 u )
-{
- setPosition(p);
- setFocus(f);
- mUpVector = u;
-}
-
-//---------------------------------------------------------
-void LLFollowCam::setMaxCameraDistantFromSubject( F32 m )
-{
- mMaxCameraDistantFromSubject = m;
-}
-
-
-void LLFollowCam::setPitch( F32 p )
-{
- LLFollowCamParams::setPitch(p);
- mPitchSineAndCosineNeedToBeUpdated = true; // important
-}
-
-void LLFollowCam::setDistance( F32 d )
-{
- if (d != mDistance)
- {
- LLFollowCamParams::setDistance(d);
- mSimulatedDistance = d;
- mZoomedToMinimumDistance = false;
- }
-}
-
-void LLFollowCam::setPosition( const LLVector3& p )
-{
- if (p != mPosition)
- {
- LLFollowCamParams::setPosition(p);
- mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(mPosition);
- if (mPositionLocked)
- {
- mRelativePos = (mPosition - mSubjectPosition) * ~mSubjectRotation;
- }
- }
-}
-
-void LLFollowCam::setFocus( const LLVector3& f )
-{
- if (f != mFocus)
- {
- LLFollowCamParams::setFocus(f);
- mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(f);
- if (mFocusLocked)
- {
- mRelativeFocus = (mFocus - mSubjectPosition) * ~mSubjectRotation;
- }
- }
-}
-
-void LLFollowCam::setPositionLocked( bool locked )
-{
- LLFollowCamParams::setPositionLocked(locked);
- if (locked)
- {
- // propagate set position to relative position
- mRelativePos = (gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal) - mSubjectPosition) * ~mSubjectRotation;
- }
-}
-
-void LLFollowCam::setFocusLocked( bool locked )
-{
- LLFollowCamParams::setFocusLocked(locked);
- if (locked)
- {
- // propagate set position to relative position
- mRelativeFocus = (gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal) - mSubjectPosition) * ~mSubjectRotation;
- }
-}
-
-
-LLVector3 LLFollowCam::getSimulatedPosition() const
-{
- // return simulated position
- return mSubjectPosition + (mRelativePos * mSubjectRotation);
-}
-
-LLVector3 LLFollowCam::getSimulatedFocus() const
-{
- // return simulated focus point
- return mSubjectPosition + (mRelativeFocus * mSubjectRotation);
-}
-
-LLVector3 LLFollowCam::getUpVector()
-{
- return mUpVector;
-}
-
-
-//------------------------------------
-// Destructor
-//------------------------------------
-LLFollowCam::~LLFollowCam()
-{
-}
-
-
-//-------------------------------------------------------
-// LLFollowCamMgr
-//-------------------------------------------------------
-LLFollowCamMgr::LLFollowCamMgr()
-{
-}
-
-LLFollowCamMgr::~LLFollowCamMgr()
-{
- for (param_map_t::iterator iter = mParamMap.begin(); iter != mParamMap.end(); ++iter)
- {
- LLFollowCamParams* params = iter->second;
- delete params;
- }
- mParamMap.clear();
-}
-
-void LLFollowCamMgr::setPositionLag( const LLUUID& source, F32 lag)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setPositionLag(lag);
- }
-}
-
-void LLFollowCamMgr::setFocusLag( const LLUUID& source, F32 lag)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setFocusLag(lag);
- }
-}
-
-void LLFollowCamMgr::setFocusThreshold( const LLUUID& source, F32 threshold)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setFocusThreshold(threshold);
- }
-
-}
-
-void LLFollowCamMgr::setPositionThreshold( const LLUUID& source, F32 threshold)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setPositionThreshold(threshold);
- }
-}
-
-void LLFollowCamMgr::setDistance( const LLUUID& source, F32 distance)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setDistance(distance);
- }
-}
-
-void LLFollowCamMgr::setPitch( const LLUUID& source, F32 pitch)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setPitch(pitch);
- }
-}
-
-void LLFollowCamMgr::setFocusOffset( const LLUUID& source, const LLVector3& offset)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setFocusOffset(offset);
- }
-}
-
-void LLFollowCamMgr::setBehindnessAngle( const LLUUID& source, F32 angle)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setBehindnessAngle(angle);
- }
-}
-
-void LLFollowCamMgr::setBehindnessLag( const LLUUID& source, F32 force)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setBehindnessLag(force);
- }
-}
-
-void LLFollowCamMgr::setPosition( const LLUUID& source, const LLVector3 position)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setPosition(position);
- }
-}
-
-void LLFollowCamMgr::setFocus( const LLUUID& source, const LLVector3 focus)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setFocus(focus);
- }
-}
-
-void LLFollowCamMgr::setPositionLocked( const LLUUID& source, bool locked)
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setPositionLocked(locked);
- }
-}
-
-void LLFollowCamMgr::setFocusLocked( const LLUUID& source, bool locked )
-{
- LLFollowCamParams* paramsp = getParamsForID(source);
- if (paramsp)
- {
- paramsp->setFocusLocked(locked);
- }
-}
-
-LLFollowCamParams* LLFollowCamMgr::getParamsForID(const LLUUID& source)
-{
- LLFollowCamParams* params = NULL;
-
- param_map_t::iterator found_it = mParamMap.find(source);
- if (found_it == mParamMap.end()) // didn't find it?
- {
- params = new LLFollowCamParams();
- mParamMap[source] = params;
- }
- else
- {
- params = found_it->second;
- }
-
- return params;
-}
-
-LLFollowCamParams* LLFollowCamMgr::getActiveFollowCamParams()
-{
- if (mParamStack.empty())
- {
- return NULL;
- }
-
- return mParamStack.back();
-}
-
-void LLFollowCamMgr::setCameraActive( const LLUUID& source, bool active )
-{
- LLFollowCamParams* params = getParamsForID(source);
- param_stack_t::iterator found_it = std::find(mParamStack.begin(), mParamStack.end(), params);
- if (found_it != mParamStack.end())
- {
- mParamStack.erase(found_it);
- }
- // put on top of stack
- if(active)
- {
- mParamStack.push_back(params);
- }
-}
-
-void LLFollowCamMgr::removeFollowCamParams(const LLUUID& source)
-{
- setCameraActive(source, false);
- LLFollowCamParams* params = getParamsForID(source);
- mParamMap.erase(source);
- delete params;
-}
-
-bool LLFollowCamMgr::isScriptedCameraSource(const LLUUID& source)
-{
- param_map_t::iterator found_it = mParamMap.find(source);
- return (found_it != mParamMap.end());
-}
-
-void LLFollowCamMgr::dump()
-{
- S32 param_count = 0;
- LL_INFOS() << "Scripted camera active stack" << LL_ENDL;
- for (param_stack_t::iterator param_it = mParamStack.begin();
- param_it != mParamStack.end();
- ++param_it)
- {
- LL_INFOS() << param_count++ <<
- " rot_limit: " << (*param_it)->getBehindnessAngle() <<
- " rot_lag: " << (*param_it)->getBehindnessLag() <<
- " distance: " << (*param_it)->getDistance() <<
- " focus: " << (*param_it)->getFocus() <<
- " foc_lag: " << (*param_it)->getFocusLag() <<
- " foc_lock: " << ((*param_it)->getFocusLocked() ? "Y" : "N") <<
- " foc_offset: " << (*param_it)->getFocusOffset() <<
- " foc_thresh: " << (*param_it)->getFocusThreshold() <<
- " pitch: " << (*param_it)->getPitch() <<
- " pos: " << (*param_it)->getPosition() <<
- " pos_lag: " << (*param_it)->getPositionLag() <<
- " pos_lock: " << ((*param_it)->getPositionLocked() ? "Y" : "N") <<
- " pos_thresh: " << (*param_it)->getPositionThreshold() << LL_ENDL;
- }
-}
-
+/** + * @file llfollowcam.cpp + * @author Jeffrey Ventrella + * @brief LLFollowCam class implementation + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfollowcam.h" +#include "llagent.h" + +//------------------------------------------------------- +// constants +//------------------------------------------------------- +const F32 FOLLOW_CAM_ZOOM_FACTOR = 0.1f; +const F32 FOLLOW_CAM_MIN_ZOOM_AMOUNT = 0.1f; +const F32 DISTANCE_EPSILON = 0.0001f; +const F32 DEFAULT_MAX_DISTANCE_FROM_SUBJECT = 1000.0; // this will be correctly set on me by my caller + +//---------------------------------------------------------------------------------------- +// This is how slowly the camera position moves to its ideal position +//---------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_POSITION_LAG = 0.0f; +const F32 FOLLOW_CAM_DEFAULT_POSITION_LAG = 0.1f; +const F32 FOLLOW_CAM_MAX_POSITION_LAG = 3.0f; + +//---------------------------------------------------------------------------------------- +// This is how slowly the camera focus moves to its subject +//---------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_FOCUS_LAG = 0.0f; +const F32 FOLLOW_CAM_DEFAULT_FOCUS_LAG = 0.1f; +const F32 FOLLOW_CAM_MAX_FOCUS_LAG = 3.0f; + +//---------------------------------------------------------------------------------------- +// This is far the position can get from its IDEAL POSITION before it starts getting pulled +//---------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_POSITION_THRESHOLD = 0.0f; +const F32 FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD = 1.0f; +const F32 FOLLOW_CAM_MAX_POSITION_THRESHOLD = 4.0f; + +//---------------------------------------------------------------------------------------- +// This is far the focus can get from the subject before it starts getting pulled +//---------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_FOCUS_THRESHOLD = 0.0f; +const F32 FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD = 1.0f; +const F32 FOLLOW_CAM_MAX_FOCUS_THRESHOLD = 4.0f; + +//---------------------------------------------------------------------------------------- +// This is the distance the camera wants to be from the subject +//---------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_DISTANCE = 0.5f; +const F32 FOLLOW_CAM_DEFAULT_DISTANCE = 3.0f; +//const F32 FOLLOW_CAM_MAX_DISTANCE = 10.0f; // from now on I am using mMaxCameraDistantFromSubject + +//---------------------------------------------------------------------------------------- +// this is an angluar value +// It affects the angle that the camera rises (pitches) in relation +// to the horizontal plane +//---------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_PITCH = -45.0f; +const F32 FOLLOW_CAM_DEFAULT_PITCH = 0.0f; +const F32 FOLLOW_CAM_MAX_PITCH = 80.0f; // keep under 90 degrees - avoid gimble lock! + + +//---------------------------------------------------------------------------------------- +// how high or low the camera considers its ideal focus to be (relative to its subject) +//---------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_FOCUS_OFFSET = -10.0f; +const LLVector3 FOLLOW_CAM_DEFAULT_FOCUS_OFFSET = LLVector3(1.0f, 0.f, 0.f); +const F32 FOLLOW_CAM_MAX_FOCUS_OFFSET = 10.0f; + +//---------------------------------------------------------------------------------------- +// This affects the rate at which the camera adjusts to stay behind the subject +//---------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_BEHINDNESS_LAG = 0.0f; +const F32 FOLLOW_CAM_DEFAULT_BEHINDNESS_LAG = 0.f; +const F32 FOLLOW_CAM_MAX_BEHINDNESS_LAG = 3.0f; + +//--------------------------------------------------------------------------------------------------------------------- +// in degrees: This is the size of the pie slice behind the subject matter within which the camera is free to move +//--------------------------------------------------------------------------------------------------------------------- +const F32 FOLLOW_CAM_MIN_BEHINDNESS_ANGLE = 0.0f; +const F32 FOLLOW_CAM_DEFAULT_BEHINDNESS_ANGLE = 10.0f; +const F32 FOLLOW_CAM_MAX_BEHINDNESS_ANGLE = 180.0f; +const F32 FOLLOW_CAM_BEHINDNESS_EPSILON = 1.0f; + +//------------------------------------ +// Constructor +//------------------------------------ +LLFollowCamParams::LLFollowCamParams() +{ + mMaxCameraDistantFromSubject = DEFAULT_MAX_DISTANCE_FROM_SUBJECT; + mPositionLocked = false; + mFocusLocked = false; + mUsePosition = false; + mUseFocus = false; + + //------------------------------------------------------ + // setting the attributes to their defaults + //------------------------------------------------------ + setPositionLag ( FOLLOW_CAM_DEFAULT_POSITION_LAG ); + setFocusLag ( FOLLOW_CAM_DEFAULT_FOCUS_LAG ); + setPositionThreshold( FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD ); + setFocusThreshold ( FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD ); + setBehindnessLag ( FOLLOW_CAM_DEFAULT_BEHINDNESS_LAG ); + setDistance ( FOLLOW_CAM_DEFAULT_DISTANCE ); + setPitch ( FOLLOW_CAM_DEFAULT_PITCH ); + setFocusOffset ( FOLLOW_CAM_DEFAULT_FOCUS_OFFSET ); + setBehindnessAngle ( FOLLOW_CAM_DEFAULT_BEHINDNESS_ANGLE ); + setPositionThreshold( FOLLOW_CAM_DEFAULT_POSITION_THRESHOLD ); + setFocusThreshold ( FOLLOW_CAM_DEFAULT_FOCUS_THRESHOLD ); + +} + +LLFollowCamParams::~LLFollowCamParams() { } + +//--------------------------------------------------------- +// buncho set methods +//--------------------------------------------------------- + +//--------------------------------------------------------- +void LLFollowCamParams::setPositionLag( F32 p ) +{ + mPositionLag = llclamp(p, FOLLOW_CAM_MIN_POSITION_LAG, FOLLOW_CAM_MAX_POSITION_LAG); +} + + +//--------------------------------------------------------- +void LLFollowCamParams::setFocusLag( F32 f ) +{ + mFocusLag = llclamp(f, FOLLOW_CAM_MIN_FOCUS_LAG, FOLLOW_CAM_MAX_FOCUS_LAG); +} + + +//--------------------------------------------------------- +void LLFollowCamParams::setPositionThreshold( F32 p ) +{ + mPositionThreshold = llclamp(p, FOLLOW_CAM_MIN_POSITION_THRESHOLD, FOLLOW_CAM_MAX_POSITION_THRESHOLD); +} + + +//--------------------------------------------------------- +void LLFollowCamParams::setFocusThreshold( F32 f ) +{ + mFocusThreshold = llclamp(f, FOLLOW_CAM_MIN_FOCUS_THRESHOLD, FOLLOW_CAM_MAX_FOCUS_THRESHOLD); +} + + +//--------------------------------------------------------- +void LLFollowCamParams::setPitch( F32 p ) +{ + mPitch = llclamp(p, FOLLOW_CAM_MIN_PITCH, FOLLOW_CAM_MAX_PITCH); +} + + +//--------------------------------------------------------- +void LLFollowCamParams::setBehindnessLag( F32 b ) +{ + mBehindnessLag = llclamp(b, FOLLOW_CAM_MIN_BEHINDNESS_LAG, FOLLOW_CAM_MAX_BEHINDNESS_LAG); +} + +//--------------------------------------------------------- +void LLFollowCamParams::setBehindnessAngle( F32 b ) +{ + mBehindnessMaxAngle = llclamp(b, FOLLOW_CAM_MIN_BEHINDNESS_ANGLE, FOLLOW_CAM_MAX_BEHINDNESS_ANGLE); +} + +//--------------------------------------------------------- +void LLFollowCamParams::setDistance( F32 d ) +{ + mDistance = llclamp(d, FOLLOW_CAM_MIN_DISTANCE, mMaxCameraDistantFromSubject); +} + +//--------------------------------------------------------- +void LLFollowCamParams::setPositionLocked( bool l ) +{ + mPositionLocked = l; +} + +//--------------------------------------------------------- +void LLFollowCamParams::setFocusLocked( bool l ) +{ + mFocusLocked = l; + +} + +//--------------------------------------------------------- +void LLFollowCamParams::setFocusOffset( const LLVector3& v ) +{ + mFocusOffset = v; + mFocusOffset.clamp(FOLLOW_CAM_MIN_FOCUS_OFFSET, FOLLOW_CAM_MAX_FOCUS_OFFSET); +} + +//--------------------------------------------------------- +void LLFollowCamParams::setPosition( const LLVector3& p ) +{ + mUsePosition = true; + mPosition = p; +} + +//--------------------------------------------------------- +void LLFollowCamParams::setFocus( const LLVector3& f ) +{ + mUseFocus = true; + mFocus = f; +} + +//--------------------------------------------------------- +// buncho get methods +//--------------------------------------------------------- +F32 LLFollowCamParams::getPositionLag () const { return mPositionLag; } +F32 LLFollowCamParams::getFocusLag () const { return mFocusLag; } +F32 LLFollowCamParams::getPositionThreshold () const { return mPositionThreshold; } +F32 LLFollowCamParams::getFocusThreshold () const { return mFocusThreshold; } +F32 LLFollowCamParams::getDistance () const { return mDistance; } +F32 LLFollowCamParams::getPitch () const { return mPitch; } +LLVector3 LLFollowCamParams::getFocusOffset () const { return mFocusOffset; } +F32 LLFollowCamParams::getBehindnessAngle () const { return mBehindnessMaxAngle; } +F32 LLFollowCamParams::getBehindnessLag () const { return mBehindnessLag; } +LLVector3 LLFollowCamParams::getPosition () const { return mPosition; } +LLVector3 LLFollowCamParams::getFocus () const { return mFocus; } +bool LLFollowCamParams::getPositionLocked () const { return mPositionLocked; } +bool LLFollowCamParams::getFocusLocked () const { return mFocusLocked; } + +//------------------------------------ +// Constructor +//------------------------------------ +LLFollowCam::LLFollowCam() : LLFollowCamParams() +{ + mUpVector = LLVector3::z_axis; + mSubjectPosition = LLVector3::zero; + mSubjectRotation = LLQuaternion::DEFAULT; + + mZoomedToMinimumDistance = false; + mPitchCos = mPitchSin = 0.f; + mPitchSineAndCosineNeedToBeUpdated = true; + + mSimulatedDistance = mDistance; +} + +void LLFollowCam::copyParams(LLFollowCamParams& params) +{ + setPositionLag(params.getPositionLag()); + setFocusLag(params.getFocusLag()); + setFocusThreshold( params.getFocusThreshold()); + setPositionThreshold(params.getPositionThreshold()); + setPitch(params.getPitch()); + setFocusOffset(params.getFocusOffset()); + setBehindnessAngle(params.getBehindnessAngle()); + setBehindnessLag(params.getBehindnessLag()); + + setPositionLocked(params.getPositionLocked()); + setFocusLocked(params.getFocusLocked()); + + setDistance(params.getDistance()); + if (params.getUsePosition()) + { + setPosition(params.getPosition()); + } + if (params.getUseFocus()) + { + setFocus(params.getFocus()); + } +} + +//--------------------------------------------------------------------------------------------------------- +void LLFollowCam::update() +{ + //#################################################################################### + // update Focus + //#################################################################################### + LLVector3 offsetSubjectPosition = mSubjectPosition + (mFocusOffset * mSubjectRotation); + + LLVector3 simulated_pos_agent = gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal); + LLVector3 vectorFromCameraToSubject = offsetSubjectPosition - simulated_pos_agent; + F32 distanceFromCameraToSubject = vectorFromCameraToSubject.magVec(); + + LLVector3 whereFocusWantsToBe = mFocus; + LLVector3 focus_pt_agent = gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal); + if ( mFocusLocked ) // if focus is locked, only relative focus needs to be updated + { + mRelativeFocus = (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation; + } + else + { + LLVector3 focusOffset = offsetSubjectPosition - focus_pt_agent; + F32 focusOffsetDistance = focusOffset.magVec(); + + LLVector3 focusOffsetDirection = focusOffset / focusOffsetDistance; + whereFocusWantsToBe = focus_pt_agent + + (focusOffsetDirection * (focusOffsetDistance - mFocusThreshold)); + if ( focusOffsetDistance > mFocusThreshold ) + { + // this version normalizes focus threshold by distance + // so that the effect is not changed with distance + /* + F32 focusThresholdNormalizedByDistance = distanceFromCameraToSubject * mFocusThreshold; + if ( focusOffsetDistance > focusThresholdNormalizedByDistance ) + { + LLVector3 focusOffsetDirection = focusOffset / focusOffsetDistance; + F32 force = focusOffsetDistance - focusThresholdNormalizedByDistance; + */ + + F32 focusLagLerp = LLSmoothInterpolation::getInterpolant( mFocusLag ); + focus_pt_agent = lerp( focus_pt_agent, whereFocusWantsToBe, focusLagLerp ); + mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(focus_pt_agent); + } + mRelativeFocus = lerp(mRelativeFocus, (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation, LLSmoothInterpolation::getInterpolant(0.05f)); + }// if focus is not locked --------------------------------------------- + + + LLVector3 whereCameraPositionWantsToBe = gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal); + if ( mPositionLocked ) + { + mRelativePos = (whereCameraPositionWantsToBe - mSubjectPosition) * ~mSubjectRotation; + } + else + { + //#################################################################################### + // update Position + //#################################################################################### + //------------------------------------------------------------------------- + // I determine the horizontal vector from the camera to the subject + //------------------------------------------------------------------------- + LLVector3 horizontalVectorFromCameraToSubject = vectorFromCameraToSubject; + horizontalVectorFromCameraToSubject.mV[VZ] = 0.0f; + + //--------------------------------------------------------- + // Now I determine the horizontal distance + //--------------------------------------------------------- + F32 horizontalDistanceFromCameraToSubject = horizontalVectorFromCameraToSubject.magVec(); + + //--------------------------------------------------------- + // Then I get the (normalized) horizontal direction... + //--------------------------------------------------------- + LLVector3 horizontalDirectionFromCameraToSubject; + if ( horizontalDistanceFromCameraToSubject < DISTANCE_EPSILON ) + { + // make sure we still have a normalized vector if distance is really small + // (this case is rare and fleeting) + horizontalDirectionFromCameraToSubject = LLVector3::z_axis; + } + else + { + // I'm not using the "normalize" method, because I can just divide by horizontalDistanceFromCameraToSubject + horizontalDirectionFromCameraToSubject = horizontalVectorFromCameraToSubject / horizontalDistanceFromCameraToSubject; + } + + //------------------------------------------------------------------------------------------------------------ + // Here is where I determine an offset relative to subject position in oder to set the ideal position. + //------------------------------------------------------------------------------------------------------------ + if ( mPitchSineAndCosineNeedToBeUpdated ) + { + calculatePitchSineAndCosine(); + mPitchSineAndCosineNeedToBeUpdated = false; + } + + LLVector3 positionOffsetFromSubject; + positionOffsetFromSubject.setVec + ( + horizontalDirectionFromCameraToSubject.mV[ VX ] * mPitchCos, + horizontalDirectionFromCameraToSubject.mV[ VY ] * mPitchCos, + -mPitchSin + ); + + positionOffsetFromSubject *= mSimulatedDistance; + + //---------------------------------------------------------------------- + // Finally, ideal position is set by taking the subject position and + // extending the positionOffsetFromSubject from that + //---------------------------------------------------------------------- + LLVector3 idealCameraPosition = offsetSubjectPosition - positionOffsetFromSubject; + + //-------------------------------------------------------------------------------- + // Now I prepare to move the current camera position towards its ideal position... + //-------------------------------------------------------------------------------- + LLVector3 vectorFromPositionToIdealPosition = idealCameraPosition - simulated_pos_agent; + F32 distanceFromPositionToIdealPosition = vectorFromPositionToIdealPosition.magVec(); + + //put this inside of the block? + LLVector3 normalFromPositionToIdealPosition = vectorFromPositionToIdealPosition / distanceFromPositionToIdealPosition; + + whereCameraPositionWantsToBe = simulated_pos_agent + + (normalFromPositionToIdealPosition * (distanceFromPositionToIdealPosition - mPositionThreshold)); + //------------------------------------------------------------------------------------------------- + // The following method takes the target camera position and resets it so that it stays "behind" the subject, + // using behindness angle and behindness force as parameters affecting the exact behavior + //------------------------------------------------------------------------------------------------- + if ( distanceFromPositionToIdealPosition > mPositionThreshold ) + { + F32 positionPullLerp = LLSmoothInterpolation::getInterpolant( mPositionLag ); + simulated_pos_agent = lerp( simulated_pos_agent, whereCameraPositionWantsToBe, positionPullLerp ); + } + + //-------------------------------------------------------------------- + // don't let the camera get farther than its official max distance + //-------------------------------------------------------------------- + if ( distanceFromCameraToSubject > mMaxCameraDistantFromSubject ) + { + LLVector3 directionFromCameraToSubject = vectorFromCameraToSubject / distanceFromCameraToSubject; + simulated_pos_agent = offsetSubjectPosition - directionFromCameraToSubject * mMaxCameraDistantFromSubject; + } + + ////------------------------------------------------------------------------------------------------- + //// The following method takes mSimulatedPositionGlobal and resets it so that it stays "behind" the subject, + //// using behindness angle and behindness force as parameters affecting the exact behavior + ////------------------------------------------------------------------------------------------------- + updateBehindnessConstraint(gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal), simulated_pos_agent); + mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(simulated_pos_agent); + + mRelativePos = lerp(mRelativePos, (simulated_pos_agent - mSubjectPosition) * ~mSubjectRotation, LLSmoothInterpolation::getInterpolant(0.05f)); + } // if position is not locked ----------------------------------------------------------- + + + //#################################################################################### + // update UpVector + //#################################################################################### + // this just points upward for now, but I anticipate future effects requiring + // some rolling ("banking" effects for fun, swoopy vehicles, etc.) + mUpVector = LLVector3::z_axis; +} + + + +//------------------------------------------------------------------------------------- +bool LLFollowCam::updateBehindnessConstraint(LLVector3 focus, LLVector3& cam_position) +{ + bool constraint_active = false; + // only apply this stuff if the behindness angle is something other than opened up all the way + if ( mBehindnessMaxAngle < FOLLOW_CAM_MAX_BEHINDNESS_ANGLE - FOLLOW_CAM_BEHINDNESS_EPSILON ) + { + //-------------------------------------------------------------- + // horizontalized vector from focus to camera + //-------------------------------------------------------------- + LLVector3 horizontalVectorFromFocusToCamera; + horizontalVectorFromFocusToCamera.setVec(cam_position - focus); + horizontalVectorFromFocusToCamera.mV[ VZ ] = 0.0f; + F32 cameraZ = cam_position.mV[ VZ ]; + + //-------------------------------------------------------------- + // distance of horizontalized vector + //-------------------------------------------------------------- + F32 horizontalDistance = horizontalVectorFromFocusToCamera.magVec(); + + //-------------------------------------------------------------------------------------------------- + // calculate horizontalized back vector of the subject and scale by horizontalDistance + //-------------------------------------------------------------------------------------------------- + LLVector3 horizontalSubjectBack( -1.0f, 0.0f, 0.0f ); + horizontalSubjectBack *= mSubjectRotation; + horizontalSubjectBack.mV[ VZ ] = 0.0f; + horizontalSubjectBack.normVec(); // because horizontalizing might make it shorter than 1 + horizontalSubjectBack *= horizontalDistance; + + //-------------------------------------------------------------------------------------------------- + // find the angle (in degrees) between these vectors + //-------------------------------------------------------------------------------------------------- + F32 cameraOffsetAngle = 0.f; + LLVector3 cameraOffsetRotationAxis; + LLQuaternion camera_offset_rotation; + camera_offset_rotation.shortestArc(horizontalSubjectBack, horizontalVectorFromFocusToCamera); + camera_offset_rotation.getAngleAxis(&cameraOffsetAngle, cameraOffsetRotationAxis); + cameraOffsetAngle *= RAD_TO_DEG; + + if ( cameraOffsetAngle > mBehindnessMaxAngle ) + { + F32 fraction = ((cameraOffsetAngle - mBehindnessMaxAngle) / cameraOffsetAngle) * LLSmoothInterpolation::getInterpolant(mBehindnessLag); + cam_position = focus + horizontalSubjectBack * (slerp(fraction, camera_offset_rotation, LLQuaternion::DEFAULT)); + cam_position.mV[VZ] = cameraZ; // clamp z value back to what it was before we started messing with it + constraint_active = true; + } + } + return constraint_active; +} + + +//--------------------------------------------------------- +void LLFollowCam::calculatePitchSineAndCosine() +{ + F32 radian = mPitch * DEG_TO_RAD; + mPitchCos = cos( radian ); + mPitchSin = sin( radian ); +} + +//--------------------------------------------------------- +void LLFollowCam::setSubjectPositionAndRotation( const LLVector3 p, const LLQuaternion r ) +{ + mSubjectPosition = p; + mSubjectRotation = r; +} + + +//--------------------------------------------------------- +void LLFollowCam::zoom( S32 z ) +{ + F32 zoomAmount = z * mSimulatedDistance * FOLLOW_CAM_ZOOM_FACTOR; + + if (( zoomAmount < FOLLOW_CAM_MIN_ZOOM_AMOUNT ) + && ( zoomAmount > -FOLLOW_CAM_MIN_ZOOM_AMOUNT )) + { + if ( zoomAmount < 0.0f ) + { + zoomAmount = -FOLLOW_CAM_MIN_ZOOM_AMOUNT; + } + else + { + zoomAmount = FOLLOW_CAM_MIN_ZOOM_AMOUNT; + } + } + + mSimulatedDistance += zoomAmount; + + mZoomedToMinimumDistance = false; + if ( mSimulatedDistance < FOLLOW_CAM_MIN_DISTANCE ) + { + mSimulatedDistance = FOLLOW_CAM_MIN_DISTANCE; + + // if zoomAmount is negative (i.e., getting closer), then + // this signifies having hit the minimum: + if ( zoomAmount < 0.0f ) + { + mZoomedToMinimumDistance = true; + } + } + else if ( mSimulatedDistance > mMaxCameraDistantFromSubject ) + { + mSimulatedDistance = mMaxCameraDistantFromSubject; + } +} + + +//--------------------------------------------------------- +bool LLFollowCam::isZoomedToMinimumDistance() +{ + return mZoomedToMinimumDistance; +} + + +//--------------------------------------------------------- +void LLFollowCam::reset( const LLVector3 p, const LLVector3 f , const LLVector3 u ) +{ + setPosition(p); + setFocus(f); + mUpVector = u; +} + +//--------------------------------------------------------- +void LLFollowCam::setMaxCameraDistantFromSubject( F32 m ) +{ + mMaxCameraDistantFromSubject = m; +} + + +void LLFollowCam::setPitch( F32 p ) +{ + LLFollowCamParams::setPitch(p); + mPitchSineAndCosineNeedToBeUpdated = true; // important +} + +void LLFollowCam::setDistance( F32 d ) +{ + if (d != mDistance) + { + LLFollowCamParams::setDistance(d); + mSimulatedDistance = d; + mZoomedToMinimumDistance = false; + } +} + +void LLFollowCam::setPosition( const LLVector3& p ) +{ + if (p != mPosition) + { + LLFollowCamParams::setPosition(p); + mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(mPosition); + if (mPositionLocked) + { + mRelativePos = (mPosition - mSubjectPosition) * ~mSubjectRotation; + } + } +} + +void LLFollowCam::setFocus( const LLVector3& f ) +{ + if (f != mFocus) + { + LLFollowCamParams::setFocus(f); + mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(f); + if (mFocusLocked) + { + mRelativeFocus = (mFocus - mSubjectPosition) * ~mSubjectRotation; + } + } +} + +void LLFollowCam::setPositionLocked( bool locked ) +{ + LLFollowCamParams::setPositionLocked(locked); + if (locked) + { + // propagate set position to relative position + mRelativePos = (gAgent.getPosAgentFromGlobal(mSimulatedPositionGlobal) - mSubjectPosition) * ~mSubjectRotation; + } +} + +void LLFollowCam::setFocusLocked( bool locked ) +{ + LLFollowCamParams::setFocusLocked(locked); + if (locked) + { + // propagate set position to relative position + mRelativeFocus = (gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal) - mSubjectPosition) * ~mSubjectRotation; + } +} + + +LLVector3 LLFollowCam::getSimulatedPosition() const +{ + // return simulated position + return mSubjectPosition + (mRelativePos * mSubjectRotation); +} + +LLVector3 LLFollowCam::getSimulatedFocus() const +{ + // return simulated focus point + return mSubjectPosition + (mRelativeFocus * mSubjectRotation); +} + +LLVector3 LLFollowCam::getUpVector() +{ + return mUpVector; +} + + +//------------------------------------ +// Destructor +//------------------------------------ +LLFollowCam::~LLFollowCam() +{ +} + + +//------------------------------------------------------- +// LLFollowCamMgr +//------------------------------------------------------- +LLFollowCamMgr::LLFollowCamMgr() +{ +} + +LLFollowCamMgr::~LLFollowCamMgr() +{ + for (param_map_t::iterator iter = mParamMap.begin(); iter != mParamMap.end(); ++iter) + { + LLFollowCamParams* params = iter->second; + delete params; + } + mParamMap.clear(); +} + +void LLFollowCamMgr::setPositionLag( const LLUUID& source, F32 lag) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setPositionLag(lag); + } +} + +void LLFollowCamMgr::setFocusLag( const LLUUID& source, F32 lag) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setFocusLag(lag); + } +} + +void LLFollowCamMgr::setFocusThreshold( const LLUUID& source, F32 threshold) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setFocusThreshold(threshold); + } + +} + +void LLFollowCamMgr::setPositionThreshold( const LLUUID& source, F32 threshold) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setPositionThreshold(threshold); + } +} + +void LLFollowCamMgr::setDistance( const LLUUID& source, F32 distance) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setDistance(distance); + } +} + +void LLFollowCamMgr::setPitch( const LLUUID& source, F32 pitch) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setPitch(pitch); + } +} + +void LLFollowCamMgr::setFocusOffset( const LLUUID& source, const LLVector3& offset) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setFocusOffset(offset); + } +} + +void LLFollowCamMgr::setBehindnessAngle( const LLUUID& source, F32 angle) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setBehindnessAngle(angle); + } +} + +void LLFollowCamMgr::setBehindnessLag( const LLUUID& source, F32 force) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setBehindnessLag(force); + } +} + +void LLFollowCamMgr::setPosition( const LLUUID& source, const LLVector3 position) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setPosition(position); + } +} + +void LLFollowCamMgr::setFocus( const LLUUID& source, const LLVector3 focus) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setFocus(focus); + } +} + +void LLFollowCamMgr::setPositionLocked( const LLUUID& source, bool locked) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setPositionLocked(locked); + } +} + +void LLFollowCamMgr::setFocusLocked( const LLUUID& source, bool locked ) +{ + LLFollowCamParams* paramsp = getParamsForID(source); + if (paramsp) + { + paramsp->setFocusLocked(locked); + } +} + +LLFollowCamParams* LLFollowCamMgr::getParamsForID(const LLUUID& source) +{ + LLFollowCamParams* params = NULL; + + param_map_t::iterator found_it = mParamMap.find(source); + if (found_it == mParamMap.end()) // didn't find it? + { + params = new LLFollowCamParams(); + mParamMap[source] = params; + } + else + { + params = found_it->second; + } + + return params; +} + +LLFollowCamParams* LLFollowCamMgr::getActiveFollowCamParams() +{ + if (mParamStack.empty()) + { + return NULL; + } + + return mParamStack.back(); +} + +void LLFollowCamMgr::setCameraActive( const LLUUID& source, bool active ) +{ + LLFollowCamParams* params = getParamsForID(source); + param_stack_t::iterator found_it = std::find(mParamStack.begin(), mParamStack.end(), params); + if (found_it != mParamStack.end()) + { + mParamStack.erase(found_it); + } + // put on top of stack + if(active) + { + mParamStack.push_back(params); + } +} + +void LLFollowCamMgr::removeFollowCamParams(const LLUUID& source) +{ + setCameraActive(source, false); + LLFollowCamParams* params = getParamsForID(source); + mParamMap.erase(source); + delete params; +} + +bool LLFollowCamMgr::isScriptedCameraSource(const LLUUID& source) +{ + param_map_t::iterator found_it = mParamMap.find(source); + return (found_it != mParamMap.end()); +} + +void LLFollowCamMgr::dump() +{ + S32 param_count = 0; + LL_INFOS() << "Scripted camera active stack" << LL_ENDL; + for (param_stack_t::iterator param_it = mParamStack.begin(); + param_it != mParamStack.end(); + ++param_it) + { + LL_INFOS() << param_count++ << + " rot_limit: " << (*param_it)->getBehindnessAngle() << + " rot_lag: " << (*param_it)->getBehindnessLag() << + " distance: " << (*param_it)->getDistance() << + " focus: " << (*param_it)->getFocus() << + " foc_lag: " << (*param_it)->getFocusLag() << + " foc_lock: " << ((*param_it)->getFocusLocked() ? "Y" : "N") << + " foc_offset: " << (*param_it)->getFocusOffset() << + " foc_thresh: " << (*param_it)->getFocusThreshold() << + " pitch: " << (*param_it)->getPitch() << + " pos: " << (*param_it)->getPosition() << + " pos_lag: " << (*param_it)->getPositionLag() << + " pos_lock: " << ((*param_it)->getPositionLocked() ? "Y" : "N") << + " pos_thresh: " << (*param_it)->getPositionThreshold() << LL_ENDL; + } +} + |