diff options
Diffstat (limited to 'indra/newview/llagentcamera.cpp')
| -rw-r--r-- | indra/newview/llagentcamera.cpp | 4567 | 
1 files changed, 2284 insertions, 2283 deletions
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index fd6901a783..25e777191f 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -1,31 +1,31 @@ -/**  +/**   * @file llagentcamera.cpp   * @brief LLAgent class implementation   *   * $LicenseInfo:firstyear=2001&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 "llagentcamera.h"  +#include "llagentcamera.h"  #include "pipeline.h" @@ -60,8 +60,8 @@ const F32 MIN_ZOOM_FRACTION = 0.25f;  const F32 INITIAL_ZOOM_FRACTION = 1.f;  const F32 MAX_ZOOM_FRACTION = 8.f; -const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f;	// seconds -const F32 FOV_ZOOM_HALF_LIFE = 0.07f;	// seconds +const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f;    // seconds +const F32 FOV_ZOOM_HALF_LIFE = 0.07f;   // seconds  const F32 CAMERA_FOCUS_HALF_LIFE = 0.f;//0.02f;  const F32 CAMERA_LAG_HALF_LIFE = 0.25f; @@ -102,8 +102,8 @@ const F32 OBJECT_EXTENTS_PADDING = 0.5f;  static bool isDisableCameraConstraints()  { -	static LLCachedControl<bool> sDisableCameraConstraints(gSavedSettings, "DisableCameraConstraints", false); -	return sDisableCameraConstraints; +    static LLCachedControl<bool> sDisableCameraConstraints(gSavedSettings, "DisableCameraConstraints", false); +    return sDisableCameraConstraints;  }  // The agent instance. @@ -113,84 +113,84 @@ LLAgentCamera gAgentCamera;  // LLAgentCamera()  //-----------------------------------------------------------------------------  LLAgentCamera::LLAgentCamera() : -	mInitialized(false), - -	mDrawDistance( DEFAULT_FAR_PLANE ), - -	mLookAt(NULL), -	mPointAt(NULL), - -	mHUDTargetZoom(1.f), -	mHUDCurZoom(1.f), - -	mForceMouselook(false), - -	mCameraMode( CAMERA_MODE_THIRD_PERSON ), -	mLastCameraMode( CAMERA_MODE_THIRD_PERSON ), - -	mCameraPreset(CAMERA_PRESET_REAR_VIEW), - -	mCameraAnimating( false ), -	mAnimationCameraStartGlobal(), -	mAnimationFocusStartGlobal(), -	mAnimationTimer(), -	mAnimationDuration(0.33f), -	 -	mCameraFOVZoomFactor(0.f), -	mCameraCurrentFOVZoomFactor(0.f), -	mCameraFocusOffset(), - -	mCameraCollidePlane(), - -	mCurrentCameraDistance(2.f),		// meters, set in init() -	mTargetCameraDistance(2.f), -	mCameraZoomFraction(1.f),			// deprecated -	mThirdPersonHeadOffset(0.f, 0.f, 1.f), -	mSitCameraEnabled(false), -	mCameraSmoothingLastPositionGlobal(), -	mCameraSmoothingLastPositionAgent(), -	mCameraSmoothingStop(false), - -	mCameraUpVector(LLVector3::z_axis), // default is straight up - -	mFocusOnAvatar(true), -	mAllowChangeToFollow(false), -	mFocusGlobal(), -	mFocusTargetGlobal(), -	mFocusObject(NULL), -	mFocusObjectDist(0.f), -	mFocusObjectOffset(), -	mTrackFocusObject(true), - -	mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed -	mWalkKey(0), // like AtKey, but causes less forward thrust -	mLeftKey(0), -	mUpKey(0), -	mYawKey(0.f), -	mPitchKey(0.f), - -	mOrbitLeftKey(0.f), -	mOrbitRightKey(0.f), -	mOrbitUpKey(0.f), -	mOrbitDownKey(0.f), -	mOrbitInKey(0.f), -	mOrbitOutKey(0.f), - -	mPanUpKey(0.f), -	mPanDownKey(0.f), -	mPanLeftKey(0.f), -	mPanRightKey(0.f), -	mPanInKey(0.f), -	mPanOutKey(0.f) -{ -	mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); - -	clearGeneralKeys(); -	clearOrbitKeys(); -	clearPanKeys(); - -	resetPanDiff(); -	resetOrbitDiff(); +    mInitialized(false), + +    mDrawDistance( DEFAULT_FAR_PLANE ), + +    mLookAt(NULL), +    mPointAt(NULL), + +    mHUDTargetZoom(1.f), +    mHUDCurZoom(1.f), + +    mForceMouselook(false), + +    mCameraMode( CAMERA_MODE_THIRD_PERSON ), +    mLastCameraMode( CAMERA_MODE_THIRD_PERSON ), + +    mCameraPreset(CAMERA_PRESET_REAR_VIEW), + +    mCameraAnimating( false ), +    mAnimationCameraStartGlobal(), +    mAnimationFocusStartGlobal(), +    mAnimationTimer(), +    mAnimationDuration(0.33f), + +    mCameraFOVZoomFactor(0.f), +    mCameraCurrentFOVZoomFactor(0.f), +    mCameraFocusOffset(), + +    mCameraCollidePlane(), + +    mCurrentCameraDistance(2.f),        // meters, set in init() +    mTargetCameraDistance(2.f), +    mCameraZoomFraction(1.f),           // deprecated +    mThirdPersonHeadOffset(0.f, 0.f, 1.f), +    mSitCameraEnabled(false), +    mCameraSmoothingLastPositionGlobal(), +    mCameraSmoothingLastPositionAgent(), +    mCameraSmoothingStop(false), + +    mCameraUpVector(LLVector3::z_axis), // default is straight up + +    mFocusOnAvatar(true), +    mAllowChangeToFollow(false), +    mFocusGlobal(), +    mFocusTargetGlobal(), +    mFocusObject(NULL), +    mFocusObjectDist(0.f), +    mFocusObjectOffset(), +    mTrackFocusObject(true), + +    mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed +    mWalkKey(0), // like AtKey, but causes less forward thrust +    mLeftKey(0), +    mUpKey(0), +    mYawKey(0.f), +    mPitchKey(0.f), + +    mOrbitLeftKey(0.f), +    mOrbitRightKey(0.f), +    mOrbitUpKey(0.f), +    mOrbitDownKey(0.f), +    mOrbitInKey(0.f), +    mOrbitOutKey(0.f), + +    mPanUpKey(0.f), +    mPanDownKey(0.f), +    mPanLeftKey(0.f), +    mPanRightKey(0.f), +    mPanInKey(0.f), +    mPanOutKey(0.f) +{ +    mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); + +    clearGeneralKeys(); +    clearOrbitKeys(); +    clearPanKeys(); + +    resetPanDiff(); +    resetOrbitDiff();  }  // Requires gSavedSettings to be initialized. @@ -199,28 +199,28 @@ LLAgentCamera::LLAgentCamera() :  //-----------------------------------------------------------------------------  void LLAgentCamera::init()  { -	// *Note: this is where LLViewerCamera::getInstance() used to be constructed. +    // *Note: this is where LLViewerCamera::getInstance() used to be constructed. -	mDrawDistance = gSavedSettings.getF32("RenderFarClip"); +    mDrawDistance = gSavedSettings.getF32("RenderFarClip"); -	LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW); -	// Leave at 0.1 meters until we have real near clip management -	LLViewerCamera::getInstance()->setNear(0.1f); -	LLViewerCamera::getInstance()->setFar(mDrawDistance);			// if you want to change camera settings, do so in camera.h -	LLViewerCamera::getInstance()->setAspect( gViewerWindow->getWorldViewAspectRatio() );		// default, overridden in LLViewerWindow::reshape -	LLViewerCamera::getInstance()->setViewHeightInPixels(768);			// default, overridden in LLViewerWindow::reshape +    LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW); +    // Leave at 0.1 meters until we have real near clip management +    LLViewerCamera::getInstance()->setNear(0.1f); +    LLViewerCamera::getInstance()->setFar(mDrawDistance);           // if you want to change camera settings, do so in camera.h +    LLViewerCamera::getInstance()->setAspect( gViewerWindow->getWorldViewAspectRatio() );       // default, overridden in LLViewerWindow::reshape +    LLViewerCamera::getInstance()->setViewHeightInPixels(768);          // default, overridden in LLViewerWindow::reshape -	mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); -	 -	mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPresetType"); +    mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); -	mCameraCollidePlane.clearVec(); -	mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"); -	mTargetCameraDistance = mCurrentCameraDistance; -	mCameraZoomFraction = 1.f; -	mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); +    mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPresetType"); -	mInitialized = true; +    mCameraCollidePlane.clearVec(); +    mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"); +    mTargetCameraDistance = mCurrentCameraDistance; +    mCameraZoomFraction = 1.f; +    mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); + +    mInitialized = true;  }  //----------------------------------------------------------------------------- @@ -228,40 +228,40 @@ void LLAgentCamera::init()  //-----------------------------------------------------------------------------  void LLAgentCamera::cleanup()  { -	setSitCamera(LLUUID::null); +    setSitCamera(LLUUID::null); -	if(mLookAt) -	{ -		mLookAt->markDead() ; -		mLookAt = NULL; -	} -	if(mPointAt) -	{ -		mPointAt->markDead() ; -		mPointAt = NULL; -	} -	setFocusObject(NULL); +    if(mLookAt) +    { +        mLookAt->markDead() ; +        mLookAt = NULL; +    } +    if(mPointAt) +    { +        mPointAt->markDead() ; +        mPointAt = NULL; +    } +    setFocusObject(NULL);  }  void LLAgentCamera::setAvatarObject(LLVOAvatarSelf* avatar)  { -	if (!mLookAt) -	{ -		mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); -	} -	if (!mPointAt) -	{ -		mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); -	} -	 -	if (!mLookAt.isNull()) -	{ -		mLookAt->setSourceObject(avatar); -	} -	if (!mPointAt.isNull()) -	{ -		mPointAt->setSourceObject(avatar); -	}	 +    if (!mLookAt) +    { +        mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); +    } +    if (!mPointAt) +    { +        mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); +    } + +    if (!mLookAt.isNull()) +    { +        mLookAt->setSourceObject(avatar); +    } +    if (!mPointAt.isNull()) +    { +        mPointAt->setSourceObject(avatar); +    }  }  //----------------------------------------------------------------------------- @@ -269,9 +269,9 @@ void LLAgentCamera::setAvatarObject(LLVOAvatarSelf* avatar)  //-----------------------------------------------------------------------------  LLAgentCamera::~LLAgentCamera()  { -	cleanup(); +    cleanup(); -	// *Note: this is where LLViewerCamera::getInstance() used to be deleted. +    // *Note: this is where LLViewerCamera::getInstance() used to be deleted.  }  // Change camera back to third person, stop the autopilot, @@ -281,80 +281,80 @@ LLAgentCamera::~LLAgentCamera()  //-----------------------------------------------------------------------------  void LLAgentCamera::resetView(bool reset_camera, bool change_camera)  { -	if (gDisconnected) -	{ -		return; -	} - -	if (gAgent.getAutoPilot()) -	{ -		gAgent.stopAutoPilot(true); -	} - -	LLSelectMgr::getInstance()->unhighlightAll(); - -	// By popular request, keep land selection while walking around. JC -	// LLViewerParcelMgr::getInstance()->deselectLand(); - -	// force deselect when walking and attachment is selected -	// this is so people don't wig out when their avatar moves without animating -	if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) -	{ -		LLSelectMgr::getInstance()->deselectAll(); -	} - -	if (gMenuHolder != NULL) -	{ -		// Hide all popup menus -		gMenuHolder->hideMenus(); -	} - -	if (change_camera && !gSavedSettings.getBOOL("FreezeTime")) -	{ -		changeCameraToDefault(); -		 -		if (LLViewerJoystick::getInstance()->getOverrideCamera()) -		{ -			handle_toggle_flycam(); -		} - -		// reset avatar mode from eventual residual motion -		if (LLToolMgr::getInstance()->inBuildMode()) -		{ -			LLViewerJoystick::getInstance()->moveAvatar(true); -		} - -		//Camera Tool is needed for Free Camera Control Mode -		if (!LLFloaterCamera::inFreeCameraMode()) -		{ -			LLFloaterReg::hideInstance("build"); - -			// Switch back to basic toolset -			LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); -		} -		 -		gViewerWindow->showCursor(); -	} - - -	if (reset_camera && !gSavedSettings.getBOOL("FreezeTime")) -	{ -		if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson()) -		{ -			// leaving mouse-steer mode -			LLVector3 agent_at_axis = gAgent.getAtAxis(); -			agent_at_axis -= projected_vec(agent_at_axis, gAgent.getReferenceUpVector()); -			agent_at_axis.normalize(); -			gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLSmoothInterpolation::getInterpolant(0.3f))); -		} - -		setFocusOnAvatar(true, ANIMATE); - -		mCameraFOVZoomFactor = 0.f; -	} -	resetPanDiff(); -	resetOrbitDiff(); -	mHUDTargetZoom = 1.f; +    if (gDisconnected) +    { +        return; +    } + +    if (gAgent.getAutoPilot()) +    { +        gAgent.stopAutoPilot(true); +    } + +    LLSelectMgr::getInstance()->unhighlightAll(); + +    // By popular request, keep land selection while walking around. JC +    // LLViewerParcelMgr::getInstance()->deselectLand(); + +    // force deselect when walking and attachment is selected +    // this is so people don't wig out when their avatar moves without animating +    if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) +    { +        LLSelectMgr::getInstance()->deselectAll(); +    } + +    if (gMenuHolder != NULL) +    { +        // Hide all popup menus +        gMenuHolder->hideMenus(); +    } + +    if (change_camera && !gSavedSettings.getBOOL("FreezeTime")) +    { +        changeCameraToDefault(); + +        if (LLViewerJoystick::getInstance()->getOverrideCamera()) +        { +            handle_toggle_flycam(); +        } + +        // reset avatar mode from eventual residual motion +        if (LLToolMgr::getInstance()->inBuildMode()) +        { +            LLViewerJoystick::getInstance()->moveAvatar(true); +        } + +        //Camera Tool is needed for Free Camera Control Mode +        if (!LLFloaterCamera::inFreeCameraMode()) +        { +            LLFloaterReg::hideInstance("build"); + +            // Switch back to basic toolset +            LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); +        } + +        gViewerWindow->showCursor(); +    } + + +    if (reset_camera && !gSavedSettings.getBOOL("FreezeTime")) +    { +        if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson()) +        { +            // leaving mouse-steer mode +            LLVector3 agent_at_axis = gAgent.getAtAxis(); +            agent_at_axis -= projected_vec(agent_at_axis, gAgent.getReferenceUpVector()); +            agent_at_axis.normalize(); +            gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLSmoothInterpolation::getInterpolant(0.3f))); +        } + +        setFocusOnAvatar(true, ANIMATE); + +        mCameraFOVZoomFactor = 0.f; +    } +    resetPanDiff(); +    resetOrbitDiff(); +    mHUDTargetZoom = 1.f;      if (LLSelectMgr::getInstance()->mAllowSelectAvatar)      { @@ -375,14 +375,14 @@ void LLAgentCamera::resetView(bool reset_camera, bool change_camera)  //-----------------------------------------------------------------------------  void LLAgentCamera::unlockView()  { -	if (getFocusOnAvatar()) -	{ -		if (isAgentAvatarValid()) -		{ -			setFocusGlobal(LLVector3d::zero, gAgentAvatarp->mID); -		} -		setFocusOnAvatar(false, false);	// no animation -	} +    if (getFocusOnAvatar()) +    { +        if (isAgentAvatarValid()) +        { +            setFocusGlobal(LLVector3d::zero, gAgentAvatarp->mID); +        } +        setFocusOnAvatar(false, false); // no animation +    }  }  //----------------------------------------------------------------------------- @@ -390,10 +390,10 @@ void LLAgentCamera::unlockView()  //-----------------------------------------------------------------------------  void LLAgentCamera::slamLookAt(const LLVector3 &look_at)  { -	LLVector3 look_at_norm = look_at; -	look_at_norm.mV[VZ] = 0.f; -	look_at_norm.normalize(); -	gAgent.resetAxes(look_at_norm); +    LLVector3 look_at_norm = look_at; +    look_at_norm.mV[VZ] = 0.f; +    look_at_norm.normalize(); +    gAgent.resetAxes(look_at_norm);  }  //----------------------------------------------------------------------------- @@ -401,172 +401,172 @@ void LLAgentCamera::slamLookAt(const LLVector3 &look_at)  //-----------------------------------------------------------------------------  LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 original_focus_point, S32 x, S32 y)  { -	LLMatrix4 obj_matrix = object->getRenderMatrix(); -	LLQuaternion obj_rot = object->getRenderRotation(); -	LLVector3 obj_pos = object->getRenderPosition(); +    LLMatrix4 obj_matrix = object->getRenderMatrix(); +    LLQuaternion obj_rot = object->getRenderRotation(); +    LLVector3 obj_pos = object->getRenderPosition(); -	// if is avatar - don't do any funk heuristics to position the focal point -	// see DEV-30589 -	if ((object->isAvatar() && !object->isRoot()) || (object->isAnimatedObject() && object->getControlAvatar())) -	{ -		return original_focus_point - obj_pos; -	} +    // if is avatar - don't do any funk heuristics to position the focal point +    // see DEV-30589 +    if ((object->isAvatar() && !object->isRoot()) || (object->isAnimatedObject() && object->getControlAvatar())) +    { +        return original_focus_point - obj_pos; +    }      if (object->isAvatar())      {          LLVOAvatar* av = object->asAvatar();          return original_focus_point - av->getCharacterPosition();      } -	 -	LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation -	LLVector3 object_extents = object->getScale();	 -	 -	// make sure they object extents are non-zero -	object_extents.clamp(0.001f, F32_MAX); - -	// obj_to_cam_ray is unit vector pointing from object center to camera, in the coordinate frame of the object -	LLVector3 obj_to_cam_ray = obj_pos - LLViewerCamera::getInstance()->getOrigin(); -	obj_to_cam_ray.rotVec(inv_obj_rot); -	obj_to_cam_ray.normalize(); - -	// obj_to_cam_ray_proportions are the (positive) ratios of  -	// the obj_to_cam_ray x,y,z components with the x,y,z object dimensions. -	LLVector3 obj_to_cam_ray_proportions; -	obj_to_cam_ray_proportions.mV[VX] = llabs(obj_to_cam_ray.mV[VX] / object_extents.mV[VX]); -	obj_to_cam_ray_proportions.mV[VY] = llabs(obj_to_cam_ray.mV[VY] / object_extents.mV[VY]); -	obj_to_cam_ray_proportions.mV[VZ] = llabs(obj_to_cam_ray.mV[VZ] / object_extents.mV[VZ]); - -	// find the largest ratio stored in obj_to_cam_ray_proportions -	// this corresponds to the object's local axial plane (XY, YZ, XZ) that is *most* facing the camera -	LLVector3 longest_object_axis; -	// is x-axis longest? -	if (obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VY]  -		&& obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VZ]) -	{ -		// then grab it -		longest_object_axis.setVec(obj_matrix.getFwdRow4()); -	} -	// is y-axis longest? -	else if (obj_to_cam_ray_proportions.mV[VY] > obj_to_cam_ray_proportions.mV[VZ]) -	{ -		// then grab it -		longest_object_axis.setVec(obj_matrix.getLeftRow4()); -	} -	// otherwise, use z axis -	else -	{ -		longest_object_axis.setVec(obj_matrix.getUpRow4()); -	} - -	// Use this axis as the normal to project mouse click on to plane with that normal, at the object center. -	// This generates a point behind the mouse cursor that is approximately in the middle of the object in -	// terms of depth.   -	// We do this to allow the camera rotation tool to "tumble" the object by rotating the camera. -	// If the focus point were the object surface under the mouse, camera rotation would introduce an undesirable -	// eccentricity to the object orientation -	LLVector3 focus_plane_normal(longest_object_axis); -	focus_plane_normal.normalize(); - -	LLVector3d focus_pt_global; -	gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), focus_plane_normal); -	LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global); - -	// find vector from camera to focus point in object space -	LLVector3 camera_to_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin(); -	camera_to_focus_vec.rotVec(inv_obj_rot); - -	// find vector from object origin to focus point in object coordinates -	LLVector3 focus_offset_from_object_center = focus_pt - obj_pos; -	// convert to object-local space -	focus_offset_from_object_center.rotVec(inv_obj_rot); - -	// We need to project the focus point back into the bounding box of the focused object. -	// Do this by calculating the XYZ scale factors needed to get focus offset back in bounds along the camera_focus axis -	LLVector3 clip_fraction; - -	// for each axis... -	for (U32 axis = VX; axis <= VZ; axis++) -	{ -		//...calculate distance that focus offset sits outside of bounding box along that axis... -		//NOTE: dist_out_of_bounds keeps the sign of focus_offset_from_object_center  -		F32 dist_out_of_bounds; -		if (focus_offset_from_object_center.mV[axis] > 0.f) -		{ -			dist_out_of_bounds = llmax(0.f, focus_offset_from_object_center.mV[axis] - (object_extents.mV[axis] * 0.5f)); -		} -		else -		{ -			dist_out_of_bounds = llmin(0.f, focus_offset_from_object_center.mV[axis] + (object_extents.mV[axis] * 0.5f)); -		} - -		//...then calculate the scale factor needed to push camera_to_focus_vec back in bounds along current axis -		if (llabs(camera_to_focus_vec.mV[axis]) < 0.0001f) -		{ -			// don't divide by very small number -			clip_fraction.mV[axis] = 0.f; -		} -		else -		{ -			clip_fraction.mV[axis] = dist_out_of_bounds / camera_to_focus_vec.mV[axis]; -		} -	} - -	LLVector3 abs_clip_fraction = clip_fraction; -	abs_clip_fraction.abs(); - -	// find axis of focus offset that is *most* outside the bounding box and use that to -	// rescale focus offset to inside object extents -	if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY] -		&& abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ]) -	{ -		focus_offset_from_object_center -= clip_fraction.mV[VX] * camera_to_focus_vec; -	} -	else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ]) -	{ -		focus_offset_from_object_center -= clip_fraction.mV[VY] * camera_to_focus_vec; -	} -	else -	{ -		focus_offset_from_object_center -= clip_fraction.mV[VZ] * camera_to_focus_vec; -	} - -	// convert back to world space -	focus_offset_from_object_center.rotVec(obj_rot); -	 -	// now, based on distance of camera from object relative to object size -	// push the focus point towards the near surface of the object when (relatively) close to the objcet -	// or keep the focus point in the object middle when (relatively) far -	// NOTE: leave focus point in middle of avatars, since the behavior you want when alt-zooming on avatars -	// is almost always "tumble about middle" and not "spin around surface point" -	{ -		LLVector3 obj_rel = original_focus_point - object->getRenderPosition(); -		 -		//now that we have the object relative position, we should bias toward the center of the object  -		//based on the distance of the camera to the focus point vs. the distance of the camera to the focus - -		F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis()); -		F32 viewDist = dist_vec(obj_pos + obj_rel, LLViewerCamera::getInstance()->getOrigin()); - - -		LLBBox obj_bbox = object->getBoundingBoxAgent(); -		F32 bias = 0.f; - -		// virtual_camera_pos is the camera position we are simulating by backing the camera off -		// and adjusting the FOV -		LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor)); - -		// if the camera is inside the object (large, hollow objects, for example) -		// leave focus point all the way to destination depth, away from object center -		if(!obj_bbox.containsPointAgent(virtual_camera_pos)) -		{ -			// perform magic number biasing of focus point towards surface vs. planar center -			bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f); -			obj_rel = lerp(focus_offset_from_object_center, obj_rel, bias); -		} -			 -		focus_offset_from_object_center = obj_rel; -	} - -	return focus_offset_from_object_center; + +    LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation +    LLVector3 object_extents = object->getScale(); + +    // make sure they object extents are non-zero +    object_extents.clamp(0.001f, F32_MAX); + +    // obj_to_cam_ray is unit vector pointing from object center to camera, in the coordinate frame of the object +    LLVector3 obj_to_cam_ray = obj_pos - LLViewerCamera::getInstance()->getOrigin(); +    obj_to_cam_ray.rotVec(inv_obj_rot); +    obj_to_cam_ray.normalize(); + +    // obj_to_cam_ray_proportions are the (positive) ratios of +    // the obj_to_cam_ray x,y,z components with the x,y,z object dimensions. +    LLVector3 obj_to_cam_ray_proportions; +    obj_to_cam_ray_proportions.mV[VX] = llabs(obj_to_cam_ray.mV[VX] / object_extents.mV[VX]); +    obj_to_cam_ray_proportions.mV[VY] = llabs(obj_to_cam_ray.mV[VY] / object_extents.mV[VY]); +    obj_to_cam_ray_proportions.mV[VZ] = llabs(obj_to_cam_ray.mV[VZ] / object_extents.mV[VZ]); + +    // find the largest ratio stored in obj_to_cam_ray_proportions +    // this corresponds to the object's local axial plane (XY, YZ, XZ) that is *most* facing the camera +    LLVector3 longest_object_axis; +    // is x-axis longest? +    if (obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VY] +        && obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VZ]) +    { +        // then grab it +        longest_object_axis.setVec(obj_matrix.getFwdRow4()); +    } +    // is y-axis longest? +    else if (obj_to_cam_ray_proportions.mV[VY] > obj_to_cam_ray_proportions.mV[VZ]) +    { +        // then grab it +        longest_object_axis.setVec(obj_matrix.getLeftRow4()); +    } +    // otherwise, use z axis +    else +    { +        longest_object_axis.setVec(obj_matrix.getUpRow4()); +    } + +    // Use this axis as the normal to project mouse click on to plane with that normal, at the object center. +    // This generates a point behind the mouse cursor that is approximately in the middle of the object in +    // terms of depth. +    // We do this to allow the camera rotation tool to "tumble" the object by rotating the camera. +    // If the focus point were the object surface under the mouse, camera rotation would introduce an undesirable +    // eccentricity to the object orientation +    LLVector3 focus_plane_normal(longest_object_axis); +    focus_plane_normal.normalize(); + +    LLVector3d focus_pt_global; +    gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), focus_plane_normal); +    LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global); + +    // find vector from camera to focus point in object space +    LLVector3 camera_to_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin(); +    camera_to_focus_vec.rotVec(inv_obj_rot); + +    // find vector from object origin to focus point in object coordinates +    LLVector3 focus_offset_from_object_center = focus_pt - obj_pos; +    // convert to object-local space +    focus_offset_from_object_center.rotVec(inv_obj_rot); + +    // We need to project the focus point back into the bounding box of the focused object. +    // Do this by calculating the XYZ scale factors needed to get focus offset back in bounds along the camera_focus axis +    LLVector3 clip_fraction; + +    // for each axis... +    for (U32 axis = VX; axis <= VZ; axis++) +    { +        //...calculate distance that focus offset sits outside of bounding box along that axis... +        //NOTE: dist_out_of_bounds keeps the sign of focus_offset_from_object_center +        F32 dist_out_of_bounds; +        if (focus_offset_from_object_center.mV[axis] > 0.f) +        { +            dist_out_of_bounds = llmax(0.f, focus_offset_from_object_center.mV[axis] - (object_extents.mV[axis] * 0.5f)); +        } +        else +        { +            dist_out_of_bounds = llmin(0.f, focus_offset_from_object_center.mV[axis] + (object_extents.mV[axis] * 0.5f)); +        } + +        //...then calculate the scale factor needed to push camera_to_focus_vec back in bounds along current axis +        if (llabs(camera_to_focus_vec.mV[axis]) < 0.0001f) +        { +            // don't divide by very small number +            clip_fraction.mV[axis] = 0.f; +        } +        else +        { +            clip_fraction.mV[axis] = dist_out_of_bounds / camera_to_focus_vec.mV[axis]; +        } +    } + +    LLVector3 abs_clip_fraction = clip_fraction; +    abs_clip_fraction.abs(); + +    // find axis of focus offset that is *most* outside the bounding box and use that to +    // rescale focus offset to inside object extents +    if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY] +        && abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ]) +    { +        focus_offset_from_object_center -= clip_fraction.mV[VX] * camera_to_focus_vec; +    } +    else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ]) +    { +        focus_offset_from_object_center -= clip_fraction.mV[VY] * camera_to_focus_vec; +    } +    else +    { +        focus_offset_from_object_center -= clip_fraction.mV[VZ] * camera_to_focus_vec; +    } + +    // convert back to world space +    focus_offset_from_object_center.rotVec(obj_rot); + +    // now, based on distance of camera from object relative to object size +    // push the focus point towards the near surface of the object when (relatively) close to the objcet +    // or keep the focus point in the object middle when (relatively) far +    // NOTE: leave focus point in middle of avatars, since the behavior you want when alt-zooming on avatars +    // is almost always "tumble about middle" and not "spin around surface point" +    { +        LLVector3 obj_rel = original_focus_point - object->getRenderPosition(); + +        //now that we have the object relative position, we should bias toward the center of the object +        //based on the distance of the camera to the focus point vs. the distance of the camera to the focus + +        F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis()); +        F32 viewDist = dist_vec(obj_pos + obj_rel, LLViewerCamera::getInstance()->getOrigin()); + + +        LLBBox obj_bbox = object->getBoundingBoxAgent(); +        F32 bias = 0.f; + +        // virtual_camera_pos is the camera position we are simulating by backing the camera off +        // and adjusting the FOV +        LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor)); + +        // if the camera is inside the object (large, hollow objects, for example) +        // leave focus point all the way to destination depth, away from object center +        if(!obj_bbox.containsPointAgent(virtual_camera_pos)) +        { +            // perform magic number biasing of focus point towards surface vs. planar center +            bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f); +            obj_rel = lerp(focus_offset_from_object_center, obj_rel, bias); +        } + +        focus_offset_from_object_center = obj_rel; +    } + +    return focus_offset_from_object_center;  }  //----------------------------------------------------------------------------- @@ -574,276 +574,276 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi  //-----------------------------------------------------------------------------  bool LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance)  { -	bool soft_limit = false; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) +    bool soft_limit = false; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) -	if (!mFocusObject || mFocusObject->isDead() || -		mFocusObject->isMesh() || -		isDisableCameraConstraints()) -	{ -		obj_min_distance = 0.f; -		return true; -	} +    if (!mFocusObject || mFocusObject->isDead() || +        mFocusObject->isMesh() || +        isDisableCameraConstraints()) +    { +        obj_min_distance = 0.f; +        return true; +    } -	if (mFocusObject->mDrawable.isNull()) -	{ +    if (mFocusObject->mDrawable.isNull()) +    {  #ifdef LL_RELEASE_FOR_DOWNLOAD -		LL_WARNS() << "Focus object with no drawable!" << LL_ENDL; +        LL_WARNS() << "Focus object with no drawable!" << LL_ENDL;  #else -		mFocusObject->dump(); -		LL_ERRS() << "Focus object with no drawable!" << LL_ENDL; +        mFocusObject->dump(); +        LL_ERRS() << "Focus object with no drawable!" << LL_ENDL;  #endif -		obj_min_distance = 0.f; -		return true; -	} -	 -	LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation(); -	LLVector3 target_offset_origin = mFocusObjectOffset; -	LLVector3 camera_offset_target(getCameraPositionAgent() - gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); - -	// convert offsets into object local space -	camera_offset_target.rotVec(inv_object_rot); -	target_offset_origin.rotVec(inv_object_rot); - -	// push around object extents based on target offset -	LLVector3 object_extents = mFocusObject->getScale(); -	if (mFocusObject->isAvatar()) -	{ -		// fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom) -		object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR; -		object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR; -		object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR; -		soft_limit = true; -	} -	LLVector3 abs_target_offset = target_offset_origin; -	abs_target_offset.abs(); - -	LLVector3 target_offset_dir = target_offset_origin; - -	bool target_outside_object_extents = false; - -	for (U32 i = VX; i <= VZ; i++) -	{ -		if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING) -		{ -			target_outside_object_extents = true; -		} -		if (camera_offset_target.mV[i] > 0.f) -		{ -			object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f; -		} -		else -		{ -			object_extents.mV[i] += target_offset_origin.mV[i] * 2.f; -		} -	} - -	// don't shrink the object extents so far that the object inverts -	object_extents.clamp(0.001f, F32_MAX); - -	// move into first octant -	LLVector3 camera_offset_target_abs_norm = camera_offset_target; -	camera_offset_target_abs_norm.abs(); -	// make sure offset is non-zero -	camera_offset_target_abs_norm.clamp(0.001f, F32_MAX); -	camera_offset_target_abs_norm.normalize(); - -	// find camera position relative to normalized object extents -	LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm; -	camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX]; -	camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY]; -	camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ]; - -	if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] &&  -		camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ]) -	{ -		if (camera_offset_target_abs_norm.mV[VX] < 0.001f) -		{ -			obj_min_distance = object_extents.mV[VX] * 0.5f; -		} -		else -		{ -			obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX]; -		} -	} -	else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ]) -	{ -		if (camera_offset_target_abs_norm.mV[VY] < 0.001f) -		{ -			obj_min_distance = object_extents.mV[VY] * 0.5f; -		} -		else -		{ -			obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY]; -		} -	} -	else -	{ -		if (camera_offset_target_abs_norm.mV[VZ] < 0.001f) -		{ -			obj_min_distance = object_extents.mV[VZ] * 0.5f; -		} -		else -		{ -			obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ]; -		} -	} - -	LLVector3 object_split_axis; -	LLVector3 target_offset_scaled = target_offset_origin; -	target_offset_scaled.abs(); -	target_offset_scaled.normalize(); -	target_offset_scaled.mV[VX] /= object_extents.mV[VX]; -	target_offset_scaled.mV[VY] /= object_extents.mV[VY]; -	target_offset_scaled.mV[VZ] /= object_extents.mV[VZ]; - -	if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] &&  -		target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ]) -	{ -		object_split_axis = LLVector3::x_axis; -	} -	else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ]) -	{ -		object_split_axis = LLVector3::y_axis; -	} -	else -	{ -		object_split_axis = LLVector3::z_axis; -	} - -	LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent()); - - -	F32 camera_offset_clip = camera_offset_object * object_split_axis; -	F32 target_offset_clip = target_offset_dir * object_split_axis; - -	// target has moved outside of object extents -	// check to see if camera and target are on same side  -	if (target_outside_object_extents) -	{ -		if (camera_offset_clip > 0.f && target_offset_clip > 0.f) -		{ -			return false; -		} -		else if (camera_offset_clip < 0.f && target_offset_clip < 0.f) -		{ -			return false; -		} -	} - -	// clamp obj distance to diagonal of 10 by 10 cube -	obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3); - -	obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f); -	 -	return true; +        obj_min_distance = 0.f; +        return true; +    } + +    LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation(); +    LLVector3 target_offset_origin = mFocusObjectOffset; +    LLVector3 camera_offset_target(getCameraPositionAgent() - gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); + +    // convert offsets into object local space +    camera_offset_target.rotVec(inv_object_rot); +    target_offset_origin.rotVec(inv_object_rot); + +    // push around object extents based on target offset +    LLVector3 object_extents = mFocusObject->getScale(); +    if (mFocusObject->isAvatar()) +    { +        // fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom) +        object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR; +        object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR; +        object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR; +        soft_limit = true; +    } +    LLVector3 abs_target_offset = target_offset_origin; +    abs_target_offset.abs(); + +    LLVector3 target_offset_dir = target_offset_origin; + +    bool target_outside_object_extents = false; + +    for (U32 i = VX; i <= VZ; i++) +    { +        if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING) +        { +            target_outside_object_extents = true; +        } +        if (camera_offset_target.mV[i] > 0.f) +        { +            object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f; +        } +        else +        { +            object_extents.mV[i] += target_offset_origin.mV[i] * 2.f; +        } +    } + +    // don't shrink the object extents so far that the object inverts +    object_extents.clamp(0.001f, F32_MAX); + +    // move into first octant +    LLVector3 camera_offset_target_abs_norm = camera_offset_target; +    camera_offset_target_abs_norm.abs(); +    // make sure offset is non-zero +    camera_offset_target_abs_norm.clamp(0.001f, F32_MAX); +    camera_offset_target_abs_norm.normalize(); + +    // find camera position relative to normalized object extents +    LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm; +    camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX]; +    camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY]; +    camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ]; + +    if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] && +        camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ]) +    { +        if (camera_offset_target_abs_norm.mV[VX] < 0.001f) +        { +            obj_min_distance = object_extents.mV[VX] * 0.5f; +        } +        else +        { +            obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX]; +        } +    } +    else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ]) +    { +        if (camera_offset_target_abs_norm.mV[VY] < 0.001f) +        { +            obj_min_distance = object_extents.mV[VY] * 0.5f; +        } +        else +        { +            obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY]; +        } +    } +    else +    { +        if (camera_offset_target_abs_norm.mV[VZ] < 0.001f) +        { +            obj_min_distance = object_extents.mV[VZ] * 0.5f; +        } +        else +        { +            obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ]; +        } +    } + +    LLVector3 object_split_axis; +    LLVector3 target_offset_scaled = target_offset_origin; +    target_offset_scaled.abs(); +    target_offset_scaled.normalize(); +    target_offset_scaled.mV[VX] /= object_extents.mV[VX]; +    target_offset_scaled.mV[VY] /= object_extents.mV[VY]; +    target_offset_scaled.mV[VZ] /= object_extents.mV[VZ]; + +    if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] && +        target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ]) +    { +        object_split_axis = LLVector3::x_axis; +    } +    else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ]) +    { +        object_split_axis = LLVector3::y_axis; +    } +    else +    { +        object_split_axis = LLVector3::z_axis; +    } + +    LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent()); + + +    F32 camera_offset_clip = camera_offset_object * object_split_axis; +    F32 target_offset_clip = target_offset_dir * object_split_axis; + +    // target has moved outside of object extents +    // check to see if camera and target are on same side +    if (target_outside_object_extents) +    { +        if (camera_offset_clip > 0.f && target_offset_clip > 0.f) +        { +            return false; +        } +        else if (camera_offset_clip < 0.f && target_offset_clip < 0.f) +        { +            return false; +        } +    } + +    // clamp obj distance to diagonal of 10 by 10 cube +    obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3); + +    obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f); + +    return true;  }  F32 LLAgentCamera::getCameraZoomFraction(bool get_third_person)  { -	// 0.f -> camera zoomed all the way out -	// 1.f -> camera zoomed all the way in -	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); -	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) -	{ -		// already [0,1] -		return mHUDTargetZoom; -	} - -	if (get_third_person || (mFocusOnAvatar && cameraThirdPerson())) -	{ -		return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f); -	} - -	if (cameraCustomizeAvatar()) -	{ -		F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); -		return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f ); -	} - -	F32 min_zoom; -	F32 max_zoom = getCameraMaxZoomDistance(); +    // 0.f -> camera zoomed all the way out +    // 1.f -> camera zoomed all the way in +    LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); +    if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) +    { +        // already [0,1] +        return mHUDTargetZoom; +    } + +    if (get_third_person || (mFocusOnAvatar && cameraThirdPerson())) +    { +        return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f); +    } + +    if (cameraCustomizeAvatar()) +    { +        F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); +        return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f ); +    } + +    F32 min_zoom; +    F32 max_zoom = getCameraMaxZoomDistance();      if (isDisableCameraConstraints())      {          max_zoom = MAX_CAMERA_DISTANCE_FROM_OBJECT;      } -	F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); -	if (mFocusObject.notNull()) -	{ -		if (mFocusObject->isAvatar()) -		{ -			min_zoom = AVATAR_MIN_ZOOM; -		} -		else -		{ -			min_zoom = OBJECT_MIN_ZOOM; -		} -	} -	else -	{ -		min_zoom = LAND_MIN_ZOOM; -	} +    F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); +    if (mFocusObject.notNull()) +    { +        if (mFocusObject->isAvatar()) +        { +            min_zoom = AVATAR_MIN_ZOOM; +        } +        else +        { +            min_zoom = OBJECT_MIN_ZOOM; +        } +    } +    else +    { +        min_zoom = LAND_MIN_ZOOM; +    } -	return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f); +    return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f);  }  void LLAgentCamera::setCameraZoomFraction(F32 fraction)  { -	// 0.f -> camera zoomed all the way out -	// 1.f -> camera zoomed all the way in -	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - -	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) -	{ -		mHUDTargetZoom = fraction; -	} -	else if (mFocusOnAvatar && cameraThirdPerson()) -	{ -		mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION); -	} -	else if (cameraCustomizeAvatar()) -	{ -		LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; -		camera_offset_dir.normalize(); -		mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM); -	} -	else -	{ -		F32 min_zoom = LAND_MIN_ZOOM; -		F32 max_zoom = getCameraMaxZoomDistance(); +    // 0.f -> camera zoomed all the way out +    // 1.f -> camera zoomed all the way in +    LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + +    if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) +    { +        mHUDTargetZoom = fraction; +    } +    else if (mFocusOnAvatar && cameraThirdPerson()) +    { +        mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION); +    } +    else if (cameraCustomizeAvatar()) +    { +        LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; +        camera_offset_dir.normalize(); +        mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM); +    } +    else +    { +        F32 min_zoom = LAND_MIN_ZOOM; +        F32 max_zoom = getCameraMaxZoomDistance();          if (isDisableCameraConstraints())          {              max_zoom = MAX_CAMERA_DISTANCE_FROM_OBJECT;          } -		if (mFocusObject.notNull()) -		{ -			if (mFocusObject.notNull()) -			{ -				if (mFocusObject->isAvatar()) -				{ -					min_zoom = AVATAR_MIN_ZOOM; -				} -				else -				{ -					min_zoom = OBJECT_MIN_ZOOM; -				} -			} -		} +        if (mFocusObject.notNull()) +        { +            if (mFocusObject.notNull()) +            { +                if (mFocusObject->isAvatar()) +                { +                    min_zoom = AVATAR_MIN_ZOOM; +                } +                else +                { +                    min_zoom = OBJECT_MIN_ZOOM; +                } +            } +        } -		LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; -		camera_offset_dir.normalize(); -		mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); -	} +        LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; +        camera_offset_dir.normalize(); +        mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); +    } -	startCameraAnimation(); +    startCameraAnimation();  }  F32 LLAgentCamera::getAgentHUDTargetZoom()  { -	static LLCachedControl<F32> hud_scale_factor(gSavedSettings, "HUDScaleFactor"); -	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); -	return (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) ? hud_scale_factor*gAgentCamera.mHUDTargetZoom : hud_scale_factor; +    static LLCachedControl<F32> hud_scale_factor(gSavedSettings, "HUDScaleFactor"); +    LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); +    return (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) ? hud_scale_factor*gAgentCamera.mHUDTargetZoom : hud_scale_factor;  }  //----------------------------------------------------------------------------- @@ -851,22 +851,22 @@ F32 LLAgentCamera::getAgentHUDTargetZoom()  //-----------------------------------------------------------------------------  void LLAgentCamera::cameraOrbitAround(const F32 radians)  { -	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); -	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) -	{ -		// do nothing for hud selection -	} -	else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW)) -	{ -		gAgent.yaw(radians); -	} -	else -	{ -		mOrbitAroundRadians += radians; -		mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f); -		 -		cameraZoomIn(1.f); -	} +    LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); +    if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) +    { +        // do nothing for hud selection +    } +    else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW)) +    { +        gAgent.yaw(radians); +    } +    else +    { +        mOrbitAroundRadians += radians; +        mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f); + +        cameraZoomIn(1.f); +    }  } @@ -875,51 +875,51 @@ void LLAgentCamera::cameraOrbitAround(const F32 radians)  //-----------------------------------------------------------------------------  void LLAgentCamera::cameraOrbitOver(const F32 angle)  { -	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); -	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) -	{ -		// do nothing for hud selection -	} -	else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) -	{ -		gAgent.pitch(angle); -	} -	else -	{ -		LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); -		camera_offset_unit.normalize(); +    LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); +    if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) +    { +        // do nothing for hud selection +    } +    else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) +    { +        gAgent.pitch(angle); +    } +    else +    { +        LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); +        camera_offset_unit.normalize(); -		F32 angle_from_up = acos( camera_offset_unit * gAgent.getReferenceUpVector() ); +        F32 angle_from_up = acos( camera_offset_unit * gAgent.getReferenceUpVector() ); -		LLVector3d left_axis; -		left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); -		F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD); -		mOrbitOverAngle += angle_from_up - new_angle; -		mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis); +        LLVector3d left_axis; +        left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); +        F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD); +        mOrbitOverAngle += angle_from_up - new_angle; +        mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis); -		cameraZoomIn(1.f); -	} +        cameraZoomIn(1.f); +    }  }  void LLAgentCamera::resetCameraOrbit()  { -	LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); -	camera_offset_unit.normalize(); +    LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); +    camera_offset_unit.normalize(); -	LLVector3d left_axis; -	left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); -	mCameraFocusOffsetTarget.rotVec(-mOrbitOverAngle, left_axis); -	 -	mCameraFocusOffsetTarget.rotVec(-mOrbitAroundRadians, 0.f, 0.f, 1.f); +    LLVector3d left_axis; +    left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); +    mCameraFocusOffsetTarget.rotVec(-mOrbitOverAngle, left_axis); -	cameraZoomIn(1.f); -	resetOrbitDiff(); +    mCameraFocusOffsetTarget.rotVec(-mOrbitAroundRadians, 0.f, 0.f, 1.f); + +    cameraZoomIn(1.f); +    resetOrbitDiff();  }  void LLAgentCamera::resetOrbitDiff()  { -	mOrbitAroundRadians = 0; -	mOrbitOverAngle = 0; +    mOrbitAroundRadians = 0; +    mOrbitOverAngle = 0;  }  //----------------------------------------------------------------------------- @@ -927,56 +927,56 @@ void LLAgentCamera::resetOrbitDiff()  //-----------------------------------------------------------------------------  void LLAgentCamera::cameraZoomIn(const F32 fraction)  { -	if (gDisconnected) -	{ -		return; -	} - -	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); -	if (LLToolMgr::getInstance()->inBuildMode() && selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) -	{ -		// just update hud zoom level -		mHUDTargetZoom /= fraction; -		return; -	} +    if (gDisconnected) +    { +        return; +    } -	LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); -	F32 current_distance = (F32)camera_offset_unit.normalize(); -	F32 new_distance = current_distance * fraction; +    LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); +    if (LLToolMgr::getInstance()->inBuildMode() && selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) +    { +        // just update hud zoom level +        mHUDTargetZoom /= fraction; +        return; +    } -	// Unless camera is unlocked -	if (!isDisableCameraConstraints()) -	{ -		F32 min_zoom = LAND_MIN_ZOOM; +    LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); +    F32 current_distance = (F32)camera_offset_unit.normalize(); +    F32 new_distance = current_distance * fraction; -		// Don't move through focus point -		if (mFocusObject) -		{ -			LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]); +    // Unless camera is unlocked +    if (!isDisableCameraConstraints()) +    { +        F32 min_zoom = LAND_MIN_ZOOM; -			if (mFocusObject->isAvatar()) -			{ -				calcCameraMinDistance(min_zoom); -			} -			else -			{ -				min_zoom = OBJECT_MIN_ZOOM; -			} -		} +        // Don't move through focus point +        if (mFocusObject) +        { +            LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]); + +            if (mFocusObject->isAvatar()) +            { +                calcCameraMinDistance(min_zoom); +            } +            else +            { +                min_zoom = OBJECT_MIN_ZOOM; +            } +        } -		new_distance = llmax(new_distance, min_zoom); +        new_distance = llmax(new_distance, min_zoom); -		F32 max_distance = getCameraMaxZoomDistance(); -		max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance.  MAINT-3154 -		new_distance = llmin(new_distance, max_distance); +        F32 max_distance = getCameraMaxZoomDistance(); +        max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance.  MAINT-3154 +        new_distance = llmin(new_distance, max_distance); -		if (cameraCustomizeAvatar()) -		{ -			new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); -		} -	} +        if (cameraCustomizeAvatar()) +        { +            new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); +        } +    } -	mCameraFocusOffsetTarget = new_distance * camera_offset_unit; +    mCameraFocusOffsetTarget = new_distance * camera_offset_unit;  }  //----------------------------------------------------------------------------- @@ -984,62 +984,62 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction)  //-----------------------------------------------------------------------------  void LLAgentCamera::cameraOrbitIn(const F32 meters)  { -	if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) -	{ -		F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale")); -		 -		mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist; - -		if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f) -		{ -			// No need to animate, camera is already there. -			changeCameraToMouselook(false); -		} - -		if (!isDisableCameraConstraints()) -		{ -			mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION); -		} -	} -	else -	{ -		LLVector3d	camera_offset_unit(mCameraFocusOffsetTarget); -		F32 current_distance = (F32)camera_offset_unit.normalize(); -		F32 new_distance = current_distance - meters; - -		// Unless camera is unlocked -		if (!isDisableCameraConstraints()) -		{ -			F32 min_zoom = LAND_MIN_ZOOM; - -			// Don't move through focus point -			if (mFocusObject.notNull()) -			{ -				if (mFocusObject->isAvatar()) -				{ -					min_zoom = AVATAR_MIN_ZOOM; -				} -				else -				{ -					min_zoom = OBJECT_MIN_ZOOM; -				} -			} - -			new_distance = llmax(new_distance, min_zoom); - -			F32 max_distance = getCameraMaxZoomDistance(); -			new_distance = llmin(new_distance, max_distance); - -			if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) -			{ -				new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); -			} -		} - -		// Compute new camera offset -		mCameraFocusOffsetTarget = new_distance * camera_offset_unit; -		cameraZoomIn(1.f); -	} +    if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) +    { +        F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale")); + +        mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist; + +        if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f) +        { +            // No need to animate, camera is already there. +            changeCameraToMouselook(false); +        } + +        if (!isDisableCameraConstraints()) +        { +            mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION); +        } +    } +    else +    { +        LLVector3d  camera_offset_unit(mCameraFocusOffsetTarget); +        F32 current_distance = (F32)camera_offset_unit.normalize(); +        F32 new_distance = current_distance - meters; + +        // Unless camera is unlocked +        if (!isDisableCameraConstraints()) +        { +            F32 min_zoom = LAND_MIN_ZOOM; + +            // Don't move through focus point +            if (mFocusObject.notNull()) +            { +                if (mFocusObject->isAvatar()) +                { +                    min_zoom = AVATAR_MIN_ZOOM; +                } +                else +                { +                    min_zoom = OBJECT_MIN_ZOOM; +                } +            } + +            new_distance = llmax(new_distance, min_zoom); + +            F32 max_distance = getCameraMaxZoomDistance(); +            new_distance = llmin(new_distance, max_distance); + +            if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) +            { +                new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); +            } +        } + +        // Compute new camera offset +        mCameraFocusOffsetTarget = new_distance * camera_offset_unit; +        cameraZoomIn(1.f); +    }  }  //----------------------------------------------------------------------------- @@ -1047,17 +1047,17 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters)  //-----------------------------------------------------------------------------  void LLAgentCamera::cameraPanIn(F32 meters)  { -	LLVector3d at_axis; -	at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis()); +    LLVector3d at_axis; +    at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis()); -	mPanFocusDiff += meters * at_axis; +    mPanFocusDiff += meters * at_axis; -	mFocusTargetGlobal += meters * at_axis; -	mFocusGlobal = mFocusTargetGlobal; -	// don't enforce zoom constraints as this is the only way for users to get past them easily -	updateFocusOffset(); -	// NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx -	mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); +    mFocusTargetGlobal += meters * at_axis; +    mFocusGlobal = mFocusTargetGlobal; +    // don't enforce zoom constraints as this is the only way for users to get past them easily +    updateFocusOffset(); +    // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx +    mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();  }  //----------------------------------------------------------------------------- @@ -1065,21 +1065,21 @@ void LLAgentCamera::cameraPanIn(F32 meters)  //-----------------------------------------------------------------------------  void LLAgentCamera::cameraPanLeft(F32 meters)  { -	LLVector3d left_axis; -	left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); +    LLVector3d left_axis; +    left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + +    mPanFocusDiff += meters * left_axis; -	mPanFocusDiff += meters * left_axis; +    mFocusTargetGlobal += meters * left_axis; +    mFocusGlobal = mFocusTargetGlobal; -	mFocusTargetGlobal += meters * left_axis; -	mFocusGlobal = mFocusTargetGlobal; +    // disable smoothing for camera pan, which causes some residents unhappiness +    mCameraSmoothingStop = true; -	// disable smoothing for camera pan, which causes some residents unhappiness -	mCameraSmoothingStop = true; -	 -	cameraZoomIn(1.f); -	updateFocusOffset(); -	// NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx -	mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); +    cameraZoomIn(1.f); +    updateFocusOffset(); +    // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx +    mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();  }  //----------------------------------------------------------------------------- @@ -1087,41 +1087,41 @@ void LLAgentCamera::cameraPanLeft(F32 meters)  //-----------------------------------------------------------------------------  void LLAgentCamera::cameraPanUp(F32 meters)  { -	LLVector3d up_axis; -	up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis()); +    LLVector3d up_axis; +    up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis()); -	mPanFocusDiff += meters * up_axis; +    mPanFocusDiff += meters * up_axis; -	mFocusTargetGlobal += meters * up_axis; -	mFocusGlobal = mFocusTargetGlobal; +    mFocusTargetGlobal += meters * up_axis; +    mFocusGlobal = mFocusTargetGlobal; -	// disable smoothing for camera pan, which causes some residents unhappiness -	mCameraSmoothingStop = true; +    // disable smoothing for camera pan, which causes some residents unhappiness +    mCameraSmoothingStop = true; -	cameraZoomIn(1.f); -	updateFocusOffset(); -	// NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx -	mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); +    cameraZoomIn(1.f); +    updateFocusOffset(); +    // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx +    mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();  }  void LLAgentCamera::resetCameraPan()  { -	mFocusTargetGlobal -= mPanFocusDiff; +    mFocusTargetGlobal -= mPanFocusDiff; -	mFocusGlobal = mFocusTargetGlobal; -	mCameraSmoothingStop = true; +    mFocusGlobal = mFocusTargetGlobal; +    mCameraSmoothingStop = true; -	cameraZoomIn(1.f); -	updateFocusOffset(); +    cameraZoomIn(1.f); +    updateFocusOffset(); -	mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); +    mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); -	resetPanDiff(); +    resetPanDiff();  }  void LLAgentCamera::resetPanDiff()  { -	mPanFocusDiff.clear(); +    mPanFocusDiff.clear();  }  //----------------------------------------------------------------------------- @@ -1129,67 +1129,67 @@ void LLAgentCamera::resetPanDiff()  //-----------------------------------------------------------------------------  void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y)  { -	static LLVector3 last_at_axis; - -	if (!isAgentAvatarValid()) return; - -	LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot->getWorldRotation(); -	LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot->getWorldRotation(); - -	if 	(LLTrace::get_frame_recording().getLastRecording().getLastValue(*gViewerWindow->getMouseVelocityStat()) < 0.01f -		&& (root_at * last_at_axis > 0.95f)) -	{ -		LLVector3 vel = gAgentAvatarp->getVelocity(); -		if (vel.magVecSquared() > 4.f) -		{ -			setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, vel * av_inv_rot); -		} -		else -		{ -			// *FIX: rotate mframeagent by sit object's rotation? -			LLQuaternion look_rotation = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); // use camera's current rotation -			LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot; -			setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, look_offset); -		} -		last_at_axis = root_at; -		return; -	} - -	last_at_axis = root_at; -	 -	if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) -	{ -		setLookAt(LOOKAT_TARGET_NONE, gAgentAvatarp, LLVector3(-2.f, 0.f, 0.f));	 -	} -	else -	{ -		// Move head based on cursor position -		ELookAtType lookAtType = LOOKAT_TARGET_NONE; -		LLVector3 headLookAxis; -		LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance()); - -		if (cameraMouselook()) -		{ -			lookAtType = LOOKAT_TARGET_MOUSELOOK; -		} -		else if (cameraThirdPerson()) -		{ -			// range from -.5 to .5 -			F32 x_from_center =  -				((F32) mouse_x / (F32) gViewerWindow->getWorldViewWidthScaled() ) - 0.5f; -			F32 y_from_center =  -				((F32) mouse_y / (F32) gViewerWindow->getWorldViewHeightScaled() ) - 0.5f; - -			frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD); -			frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD); -			lookAtType = LOOKAT_TARGET_FREELOOK; -		} - -		headLookAxis = frameCamera.getAtAxis(); -		// RN: we use world-space offset for mouselook and freelook -		//headLookAxis = headLookAxis * av_inv_rot; -		setLookAt(lookAtType, gAgentAvatarp, headLookAxis); -	} +    static LLVector3 last_at_axis; + +    if (!isAgentAvatarValid()) return; + +    LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot->getWorldRotation(); +    LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot->getWorldRotation(); + +    if  (LLTrace::get_frame_recording().getLastRecording().getLastValue(*gViewerWindow->getMouseVelocityStat()) < 0.01f +        && (root_at * last_at_axis > 0.95f)) +    { +        LLVector3 vel = gAgentAvatarp->getVelocity(); +        if (vel.magVecSquared() > 4.f) +        { +            setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, vel * av_inv_rot); +        } +        else +        { +            // *FIX: rotate mframeagent by sit object's rotation? +            LLQuaternion look_rotation = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); // use camera's current rotation +            LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot; +            setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, look_offset); +        } +        last_at_axis = root_at; +        return; +    } + +    last_at_axis = root_at; + +    if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) +    { +        setLookAt(LOOKAT_TARGET_NONE, gAgentAvatarp, LLVector3(-2.f, 0.f, 0.f)); +    } +    else +    { +        // Move head based on cursor position +        ELookAtType lookAtType = LOOKAT_TARGET_NONE; +        LLVector3 headLookAxis; +        LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance()); + +        if (cameraMouselook()) +        { +            lookAtType = LOOKAT_TARGET_MOUSELOOK; +        } +        else if (cameraThirdPerson()) +        { +            // range from -.5 to .5 +            F32 x_from_center = +                ((F32) mouse_x / (F32) gViewerWindow->getWorldViewWidthScaled() ) - 0.5f; +            F32 y_from_center = +                ((F32) mouse_y / (F32) gViewerWindow->getWorldViewHeightScaled() ) - 0.5f; + +            frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD); +            frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD); +            lookAtType = LOOKAT_TARGET_FREELOOK; +        } + +        headLookAxis = frameCamera.getAtAxis(); +        // RN: we use world-space offset for mouselook and freelook +        //headLookAxis = headLookAxis * av_inv_rot; +        setLookAt(lookAtType, gAgentAvatarp, headLookAxis); +    }  }  static LLTrace::BlockTimerStatHandle FTM_UPDATE_CAMERA("Camera"); @@ -1201,377 +1201,377 @@ extern bool gCubeSnapshot;  //-----------------------------------------------------------------------------  void LLAgentCamera::updateCamera()  { -	LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA); +    LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA);      if (gCubeSnapshot)      {          return;      } -	// - changed camera_skyward to the new global "mCameraUpVector" -	mCameraUpVector = LLVector3::z_axis; -	//LLVector3	camera_skyward(0.f, 0.f, 1.f); - -	U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; - -	validateFocusObject(); - -	if (isAgentAvatarValid() &&  -		gAgentAvatarp->isSitting() && -		camera_mode == CAMERA_MODE_MOUSELOOK) -	{ -		//changed camera_skyward to the new global "mCameraUpVector" -		mCameraUpVector = mCameraUpVector * gAgentAvatarp->getRenderRotation(); -	} - -	if (cameraThirdPerson() && (mFocusOnAvatar || mAllowChangeToFollow) && LLFollowCamMgr::getInstance()->getActiveFollowCamParams()) -	{ -		mAllowChangeToFollow = false; -		mFocusOnAvatar = true; -		changeCameraToFollow(); -	} - -	//NOTE - this needs to be integrated into a general upVector system here within llAgent.  -	if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) -	{ -		mCameraUpVector = mFollowCam.getUpVector(); -	} - -	if (mSitCameraEnabled) -	{ -		if (mSitCameraReferenceObject->isDead()) -		{ -			setSitCamera(LLUUID::null); -		} -	} - -	// Update UI with our camera inputs -	LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera"); -	if (camera_floater) -	{ -		camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f,	// left -												gAgentCamera.getOrbitUpKey() > 0.f,		// top -												gAgentCamera.getOrbitLeftKey() > 0.f,	// right -												gAgentCamera.getOrbitDownKey() > 0.f);	// bottom -		 -		camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f,		// left -											   gAgentCamera.getPanUpKey() > 0.f,			// top -											   gAgentCamera.getPanRightKey() > 0.f,		// right -											   gAgentCamera.getPanDownKey() > 0.f);		// bottom -	} - -	// Handle camera movement based on keyboard. -	const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD;			// radians per second -	const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD;		// radians per second -	const F32 PAN_RATE = 5.f;								// meters per second - -	if (gAgentCamera.getOrbitUpKey() || gAgentCamera.getOrbitDownKey()) -	{ -		F32 input_rate = gAgentCamera.getOrbitUpKey() - gAgentCamera.getOrbitDownKey(); -		cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped ); -	} - -	if (gAgentCamera.getOrbitLeftKey() || gAgentCamera.getOrbitRightKey()) -	{ -		F32 input_rate = gAgentCamera.getOrbitLeftKey() - gAgentCamera.getOrbitRightKey(); -		cameraOrbitAround(input_rate * ORBIT_AROUND_RATE / gFPSClamped); -	} - -	if (gAgentCamera.getOrbitInKey() || gAgentCamera.getOrbitOutKey()) -	{ -		F32 input_rate = gAgentCamera.getOrbitInKey() - gAgentCamera.getOrbitOutKey(); -		 -		LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal(); -		F32 distance_to_focus = (F32)to_focus.magVec(); -		// Move at distance (in meters) meters per second -		cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped ); -	} - -	if (gAgentCamera.getPanInKey() || gAgentCamera.getPanOutKey()) -	{ -		F32 input_rate = gAgentCamera.getPanInKey() - gAgentCamera.getPanOutKey(); -		cameraPanIn(input_rate * PAN_RATE / gFPSClamped); -	} - -	if (gAgentCamera.getPanRightKey() || gAgentCamera.getPanLeftKey()) -	{ -		F32 input_rate = gAgentCamera.getPanRightKey() - gAgentCamera.getPanLeftKey(); -		cameraPanLeft(input_rate * -PAN_RATE / gFPSClamped ); -	} - -	if (gAgentCamera.getPanUpKey() || gAgentCamera.getPanDownKey()) -	{ -		F32 input_rate = gAgentCamera.getPanUpKey() - gAgentCamera.getPanDownKey(); -		cameraPanUp(input_rate * PAN_RATE / gFPSClamped ); -	} - -	// Clear camera keyboard keys. -	gAgentCamera.clearOrbitKeys(); -	gAgentCamera.clearPanKeys(); - -	// lerp camera focus offset -	mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLSmoothInterpolation::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); - -	if ( mCameraMode == CAMERA_MODE_FOLLOW ) -	{ -		if (isAgentAvatarValid()) -		{ -			//-------------------------------------------------------------------------------- -			// this is where the avatar's position and rotation are given to followCam, and  -			// where it is updated. All three of its attributes are updated: (1) position,  -			// (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent. -			//-------------------------------------------------------------------------------- -			// *TODO: use combined rotation of frameagent and sit object -			LLQuaternion avatarRotationForFollowCam = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); - -			LLFollowCamParams* current_cam = LLFollowCamMgr::getInstance()->getActiveFollowCamParams(); -			if (current_cam) -			{ -				mFollowCam.copyParams(*current_cam); -				mFollowCam.setSubjectPositionAndRotation( gAgentAvatarp->getRenderPosition(), avatarRotationForFollowCam ); -				mFollowCam.update(); -				LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); -			} -			else -			{ -				changeCameraToThirdPerson(true); -			} -		} -	} - -	bool hit_limit; -	LLVector3d camera_pos_global; -	LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit); -	mCameraVirtualPositionAgent = gAgent.getPosAgentFromGlobal(camera_target_global); -	LLVector3d focus_target_global = calcFocusPositionTargetGlobal(); - -	// perform field of view correction -	mCameraFOVZoomFactor = calcCameraFOVZoomFactor(); -	camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor); - -	gAgent.setShowAvatar(true); // can see avatar by default - -	// Adjust position for animation -	if (mCameraAnimating) -	{ -		F32 time = mAnimationTimer.getElapsedTimeF32(); - -		// yet another instance of critically damped motion, hooray! -		// F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE); - -		// linear interpolation -		F32 fraction_of_animation = time / mAnimationDuration; - -		bool isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK; -		bool wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK; -		F32 fraction_animation_to_skip; - -		if (mAnimationCameraStartGlobal == camera_target_global) -		{ -			fraction_animation_to_skip = 0.f; -		} -		else -		{ -			LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global; -			fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec(); -		} -		F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f; -		F32 animation_finish_fraction =  (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f; -	 -		if (fraction_of_animation < animation_finish_fraction) -		{ -			if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction ) -			{ -				gAgent.setShowAvatar(false); -			} - -			// ...adjust position for animation -			F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation); -			camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation); -			mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation); -		} -		else -		{ -			// ...animation complete -			mCameraAnimating = false; - -			camera_pos_global = camera_target_global; -			mFocusGlobal = focus_target_global; - -			gAgent.endAnimationUpdateUI(); -			gAgent.setShowAvatar(true); -		} - -		if (isAgentAvatarValid() && (mCameraMode != CAMERA_MODE_MOUSELOOK)) -		{ -			gAgentAvatarp->updateAttachmentVisibility(mCameraMode); -		} -	} -	else  -	{ -		camera_pos_global = camera_target_global; -		mFocusGlobal = focus_target_global; -		gAgent.setShowAvatar(true); -	} - -	// smoothing -	if (true) -	{ -		LLVector3d agent_pos = gAgent.getPositionGlobal(); -		LLVector3d camera_pos_agent = camera_pos_global - agent_pos; -		// Sitting on what you're manipulating can cause camera jitter with smoothing.  -		// This turns off smoothing while editing. -MG -		bool in_build_mode = LLToolMgr::getInstance()->inBuildMode(); -		mCameraSmoothingStop = mCameraSmoothingStop || in_build_mode; -		 -		if (cameraThirdPerson() && !mCameraSmoothingStop) -		{ -			const F32 SMOOTHING_HALF_LIFE = 0.02f; -			 -			F32 smoothing = LLSmoothInterpolation::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, false); -					 -			if (mFocusOnAvatar && !mFocusObject) // we differentiate on avatar mode  -			{ -				// for avatar-relative focus, we smooth in avatar space - -				// the avatar moves too jerkily w/r/t global space to smooth there. - -				LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent; -				if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE)  // only smooth over short distances please -				{ -					camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing); -					camera_pos_global = camera_pos_agent + agent_pos; -				} -			} -			else -			{ -				LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; -				if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please -				{ -					camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing); -				} -			} -		} -								  -		mCameraSmoothingLastPositionGlobal = camera_pos_global; -		mCameraSmoothingLastPositionAgent = camera_pos_agent; -		mCameraSmoothingStop = false; -	} - -	 -	mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLSmoothInterpolation::getInterpolant(FOV_ZOOM_HALF_LIFE)); - -//	LL_INFOS() << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << LL_ENDL; - -	LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal); -	 -	mCameraPositionAgent = gAgent.getPosAgentFromGlobal(camera_pos_global); - -	// Move the camera - -	LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent); -	//LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); -	 -	// Change FOV -	LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); - -	// follow camera when in customize mode -	if (cameraCustomizeAvatar())	 -	{ -		setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); -	} - -	// update the travel distance stat -	// this isn't directly related to the camera -	// but this seemed like the best place to do this -	LLVector3d global_pos = gAgent.getPositionGlobal();  -	if (!gAgent.getLastPositionGlobal().isExactlyZero()) -	{ -		LLVector3d delta = global_pos - gAgent.getLastPositionGlobal(); -		gAgent.setDistanceTraveled(gAgent.getDistanceTraveled() + delta.magVec()); -	} -	gAgent.setLastPositionGlobal(global_pos); -	 -	if (LLVOAvatar::sVisibleInFirstPerson && isAgentAvatarValid() && !gAgentAvatarp->isSitting() && cameraMouselook()) -	{ -		LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() +  -			LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() +  -			LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation(); -		LLVector3 diff = mCameraPositionAgent - head_pos; -		diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation(); - -		LLJoint* torso_joint = gAgentAvatarp->mTorsop; -		LLJoint* chest_joint = gAgentAvatarp->mChestp; -		LLVector3 torso_scale = torso_joint->getScale(); -		LLVector3 chest_scale = chest_joint->getScale(); - -		// shorten avatar skeleton to avoid foot interpenetration -		if (!gAgentAvatarp->mInAir) -		{ -			LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation(); -			F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f); -			F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f); -			torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); - -			LLJoint* neck_joint = gAgentAvatarp->mNeckp; -			LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation(); -			scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f); -			chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); -			diff.mV[VZ] = 0.f; -		} - -		// SL-315 -		gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff); - -		gAgentAvatarp->mRoot->updateWorldMatrixChildren(); - -		for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();  -			 iter != gAgentAvatarp->mAttachmentPoints.end(); ) -		{ -			LLVOAvatar::attachment_map_t::iterator curiter = iter++; -			LLViewerJointAttachment* attachment = curiter->second; -			for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); -				 attachment_iter != attachment->mAttachedObjects.end(); -				 ++attachment_iter) -			{ -				LLViewerObject *attached_object = attachment_iter->get(); -				if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) -				{ -					// clear any existing "early" movements of attachment -					attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE); -					gPipeline.updateMoveNormalAsync(attached_object->mDrawable); -					attached_object->updateText(); -				} -			} -		} - -		torso_joint->setScale(torso_scale); -		chest_joint->setScale(chest_scale); -	} +    // - changed camera_skyward to the new global "mCameraUpVector" +    mCameraUpVector = LLVector3::z_axis; +    //LLVector3 camera_skyward(0.f, 0.f, 1.f); + +    U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; + +    validateFocusObject(); + +    if (isAgentAvatarValid() && +        gAgentAvatarp->isSitting() && +        camera_mode == CAMERA_MODE_MOUSELOOK) +    { +        //changed camera_skyward to the new global "mCameraUpVector" +        mCameraUpVector = mCameraUpVector * gAgentAvatarp->getRenderRotation(); +    } + +    if (cameraThirdPerson() && (mFocusOnAvatar || mAllowChangeToFollow) && LLFollowCamMgr::getInstance()->getActiveFollowCamParams()) +    { +        mAllowChangeToFollow = false; +        mFocusOnAvatar = true; +        changeCameraToFollow(); +    } + +    //NOTE - this needs to be integrated into a general upVector system here within llAgent. +    if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) +    { +        mCameraUpVector = mFollowCam.getUpVector(); +    } + +    if (mSitCameraEnabled) +    { +        if (mSitCameraReferenceObject->isDead()) +        { +            setSitCamera(LLUUID::null); +        } +    } + +    // Update UI with our camera inputs +    LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera"); +    if (camera_floater) +    { +        camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f,  // left +                                                gAgentCamera.getOrbitUpKey() > 0.f,     // top +                                                gAgentCamera.getOrbitLeftKey() > 0.f,   // right +                                                gAgentCamera.getOrbitDownKey() > 0.f);  // bottom + +        camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f,      // left +                                               gAgentCamera.getPanUpKey() > 0.f,            // top +                                               gAgentCamera.getPanRightKey() > 0.f,     // right +                                               gAgentCamera.getPanDownKey() > 0.f);     // bottom +    } + +    // Handle camera movement based on keyboard. +    const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD;          // radians per second +    const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD;        // radians per second +    const F32 PAN_RATE = 5.f;                               // meters per second + +    if (gAgentCamera.getOrbitUpKey() || gAgentCamera.getOrbitDownKey()) +    { +        F32 input_rate = gAgentCamera.getOrbitUpKey() - gAgentCamera.getOrbitDownKey(); +        cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped ); +    } + +    if (gAgentCamera.getOrbitLeftKey() || gAgentCamera.getOrbitRightKey()) +    { +        F32 input_rate = gAgentCamera.getOrbitLeftKey() - gAgentCamera.getOrbitRightKey(); +        cameraOrbitAround(input_rate * ORBIT_AROUND_RATE / gFPSClamped); +    } + +    if (gAgentCamera.getOrbitInKey() || gAgentCamera.getOrbitOutKey()) +    { +        F32 input_rate = gAgentCamera.getOrbitInKey() - gAgentCamera.getOrbitOutKey(); + +        LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal(); +        F32 distance_to_focus = (F32)to_focus.magVec(); +        // Move at distance (in meters) meters per second +        cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped ); +    } + +    if (gAgentCamera.getPanInKey() || gAgentCamera.getPanOutKey()) +    { +        F32 input_rate = gAgentCamera.getPanInKey() - gAgentCamera.getPanOutKey(); +        cameraPanIn(input_rate * PAN_RATE / gFPSClamped); +    } + +    if (gAgentCamera.getPanRightKey() || gAgentCamera.getPanLeftKey()) +    { +        F32 input_rate = gAgentCamera.getPanRightKey() - gAgentCamera.getPanLeftKey(); +        cameraPanLeft(input_rate * -PAN_RATE / gFPSClamped ); +    } + +    if (gAgentCamera.getPanUpKey() || gAgentCamera.getPanDownKey()) +    { +        F32 input_rate = gAgentCamera.getPanUpKey() - gAgentCamera.getPanDownKey(); +        cameraPanUp(input_rate * PAN_RATE / gFPSClamped ); +    } + +    // Clear camera keyboard keys. +    gAgentCamera.clearOrbitKeys(); +    gAgentCamera.clearPanKeys(); + +    // lerp camera focus offset +    mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLSmoothInterpolation::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); + +    if ( mCameraMode == CAMERA_MODE_FOLLOW ) +    { +        if (isAgentAvatarValid()) +        { +            //-------------------------------------------------------------------------------- +            // this is where the avatar's position and rotation are given to followCam, and +            // where it is updated. All three of its attributes are updated: (1) position, +            // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent. +            //-------------------------------------------------------------------------------- +            // *TODO: use combined rotation of frameagent and sit object +            LLQuaternion avatarRotationForFollowCam = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); + +            LLFollowCamParams* current_cam = LLFollowCamMgr::getInstance()->getActiveFollowCamParams(); +            if (current_cam) +            { +                mFollowCam.copyParams(*current_cam); +                mFollowCam.setSubjectPositionAndRotation( gAgentAvatarp->getRenderPosition(), avatarRotationForFollowCam ); +                mFollowCam.update(); +                LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); +            } +            else +            { +                changeCameraToThirdPerson(true); +            } +        } +    } + +    bool hit_limit; +    LLVector3d camera_pos_global; +    LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit); +    mCameraVirtualPositionAgent = gAgent.getPosAgentFromGlobal(camera_target_global); +    LLVector3d focus_target_global = calcFocusPositionTargetGlobal(); + +    // perform field of view correction +    mCameraFOVZoomFactor = calcCameraFOVZoomFactor(); +    camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor); + +    gAgent.setShowAvatar(true); // can see avatar by default + +    // Adjust position for animation +    if (mCameraAnimating) +    { +        F32 time = mAnimationTimer.getElapsedTimeF32(); + +        // yet another instance of critically damped motion, hooray! +        // F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE); + +        // linear interpolation +        F32 fraction_of_animation = time / mAnimationDuration; + +        bool isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK; +        bool wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK; +        F32 fraction_animation_to_skip; + +        if (mAnimationCameraStartGlobal == camera_target_global) +        { +            fraction_animation_to_skip = 0.f; +        } +        else +        { +            LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global; +            fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec(); +        } +        F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f; +        F32 animation_finish_fraction =  (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f; + +        if (fraction_of_animation < animation_finish_fraction) +        { +            if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction ) +            { +                gAgent.setShowAvatar(false); +            } + +            // ...adjust position for animation +            F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation); +            camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation); +            mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation); +        } +        else +        { +            // ...animation complete +            mCameraAnimating = false; + +            camera_pos_global = camera_target_global; +            mFocusGlobal = focus_target_global; + +            gAgent.endAnimationUpdateUI(); +            gAgent.setShowAvatar(true); +        } + +        if (isAgentAvatarValid() && (mCameraMode != CAMERA_MODE_MOUSELOOK)) +        { +            gAgentAvatarp->updateAttachmentVisibility(mCameraMode); +        } +    } +    else +    { +        camera_pos_global = camera_target_global; +        mFocusGlobal = focus_target_global; +        gAgent.setShowAvatar(true); +    } + +    // smoothing +    if (true) +    { +        LLVector3d agent_pos = gAgent.getPositionGlobal(); +        LLVector3d camera_pos_agent = camera_pos_global - agent_pos; +        // Sitting on what you're manipulating can cause camera jitter with smoothing. +        // This turns off smoothing while editing. -MG +        bool in_build_mode = LLToolMgr::getInstance()->inBuildMode(); +        mCameraSmoothingStop = mCameraSmoothingStop || in_build_mode; + +        if (cameraThirdPerson() && !mCameraSmoothingStop) +        { +            const F32 SMOOTHING_HALF_LIFE = 0.02f; + +            F32 smoothing = LLSmoothInterpolation::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, false); + +            if (mFocusOnAvatar && !mFocusObject) // we differentiate on avatar mode +            { +                // for avatar-relative focus, we smooth in avatar space - +                // the avatar moves too jerkily w/r/t global space to smooth there. + +                LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent; +                if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE)  // only smooth over short distances please +                { +                    camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing); +                    camera_pos_global = camera_pos_agent + agent_pos; +                } +            } +            else +            { +                LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; +                if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please +                { +                    camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing); +                } +            } +        } + +        mCameraSmoothingLastPositionGlobal = camera_pos_global; +        mCameraSmoothingLastPositionAgent = camera_pos_agent; +        mCameraSmoothingStop = false; +    } + + +    mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLSmoothInterpolation::getInterpolant(FOV_ZOOM_HALF_LIFE)); + +//  LL_INFOS() << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << LL_ENDL; + +    LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal); + +    mCameraPositionAgent = gAgent.getPosAgentFromGlobal(camera_pos_global); + +    // Move the camera + +    LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent); +    //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); + +    // Change FOV +    LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); + +    // follow camera when in customize mode +    if (cameraCustomizeAvatar()) +    { +        setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); +    } + +    // update the travel distance stat +    // this isn't directly related to the camera +    // but this seemed like the best place to do this +    LLVector3d global_pos = gAgent.getPositionGlobal(); +    if (!gAgent.getLastPositionGlobal().isExactlyZero()) +    { +        LLVector3d delta = global_pos - gAgent.getLastPositionGlobal(); +        gAgent.setDistanceTraveled(gAgent.getDistanceTraveled() + delta.magVec()); +    } +    gAgent.setLastPositionGlobal(global_pos); + +    if (LLVOAvatar::sVisibleInFirstPerson && isAgentAvatarValid() && !gAgentAvatarp->isSitting() && cameraMouselook()) +    { +        LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() + +            LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() + +            LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation(); +        LLVector3 diff = mCameraPositionAgent - head_pos; +        diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation(); + +        LLJoint* torso_joint = gAgentAvatarp->mTorsop; +        LLJoint* chest_joint = gAgentAvatarp->mChestp; +        LLVector3 torso_scale = torso_joint->getScale(); +        LLVector3 chest_scale = chest_joint->getScale(); + +        // shorten avatar skeleton to avoid foot interpenetration +        if (!gAgentAvatarp->mInAir) +        { +            LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation(); +            F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f); +            F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f); +            torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); + +            LLJoint* neck_joint = gAgentAvatarp->mNeckp; +            LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation(); +            scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f); +            chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); +            diff.mV[VZ] = 0.f; +        } + +        // SL-315 +        gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff); + +        gAgentAvatarp->mRoot->updateWorldMatrixChildren(); + +        for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); +             iter != gAgentAvatarp->mAttachmentPoints.end(); ) +        { +            LLVOAvatar::attachment_map_t::iterator curiter = iter++; +            LLViewerJointAttachment* attachment = curiter->second; +            for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); +                 attachment_iter != attachment->mAttachedObjects.end(); +                 ++attachment_iter) +            { +                LLViewerObject *attached_object = attachment_iter->get(); +                if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) +                { +                    // clear any existing "early" movements of attachment +                    attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE); +                    gPipeline.updateMoveNormalAsync(attached_object->mDrawable); +                    attached_object->updateText(); +                } +            } +        } + +        torso_joint->setScale(torso_scale); +        chest_joint->setScale(chest_scale); +    }  }  void LLAgentCamera::updateLastCamera()  { -	mLastCameraMode = mCameraMode; +    mLastCameraMode = mCameraMode;  }  void LLAgentCamera::updateFocusOffset()  { -	validateFocusObject(); -	if (mFocusObject.notNull()) -	{ -		LLVector3d obj_pos = gAgent.getPosGlobalFromAgent(mFocusObject->getRenderPosition()); -		mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos); -	} +    validateFocusObject(); +    if (mFocusObject.notNull()) +    { +        LLVector3d obj_pos = gAgent.getPosGlobalFromAgent(mFocusObject->getRenderPosition()); +        mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos); +    }  }  void LLAgentCamera::validateFocusObject()  { -	if (mFocusObject.notNull() &&  -		mFocusObject->isDead()) -	{ -		mFocusObjectOffset.clearVec(); -		clearFocusObject(); -		mCameraFOVZoomFactor = 0.f; -	} +    if (mFocusObject.notNull() && +        mFocusObject->isDead()) +    { +        mFocusObjectOffset.clearVec(); +        clearFocusObject(); +        mCameraFOVZoomFactor = 0.f; +    }  }  //----------------------------------------------------------------------------- @@ -1579,124 +1579,124 @@ void LLAgentCamera::validateFocusObject()  //-----------------------------------------------------------------------------  LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal()  { -	if (mFocusObject.notNull() && mFocusObject->isDead()) -	{ -		clearFocusObject(); -	} - -	if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) -	{ -		mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus()); -		return mFocusTargetGlobal; -	} -	else if (mCameraMode == CAMERA_MODE_MOUSELOOK) -	{ -		LLVector3d at_axis(1.0, 0.0, 0.0); -		LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); -		if (isAgentAvatarValid() && gAgentAvatarp->getParent()) -		{ -			LLViewerObject* root_object = (LLViewerObject*)gAgentAvatarp->getRoot(); -			if (!root_object->flagCameraDecoupled()) -			{ -				agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); -			} -		} -		at_axis = at_axis * agent_rot; -		mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis; -		return mFocusTargetGlobal; -	} -	else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) -	{ -		if (mFocusOnAvatar) -		{ -			LLVector3 focus_target = isAgentAvatarValid() -				? gAgentAvatarp->mHeadp->getWorldPosition() -				: gAgent.getPositionAgent(); -			LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); -			mFocusTargetGlobal = focus_target_global; -		} -		return mFocusTargetGlobal; -	} -	else if (!mFocusOnAvatar) -	{ -		if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull()) -		{ -			LLDrawable* drawablep = mFocusObject->mDrawable; -			 -			if (mTrackFocusObject && -				drawablep &&  -				drawablep->isActive()) -			{ -				if (!mFocusObject->isAvatar()) -				{ -					if (mFocusObject->isSelected()) -					{ -						gPipeline.updateMoveNormalAsync(drawablep); -					} -					else -					{ -						if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) -						{ -							gPipeline.updateMoveNormalAsync(drawablep); -						} -						else -						{ -							gPipeline.updateMoveDampedAsync(drawablep); -						} -					} -				} -			} -			// if not tracking object, update offset based on new object position -			else -			{ -				updateFocusOffset(); -			} -			LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; -			mFocusTargetGlobal.setVec(gAgent.getPosGlobalFromAgent(focus_agent)); -		} -		return mFocusTargetGlobal; -	} -	else if (mSitCameraEnabled && isAgentAvatarValid() && gAgentAvatarp->isSitting() && mSitCameraReferenceObject.notNull()) -	{ -		// sit camera -		LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); -		LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); - -		LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot); -		return gAgent.getPosGlobalFromAgent(target_pos); -	} -	else -	{ -		return gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(); -	} +    if (mFocusObject.notNull() && mFocusObject->isDead()) +    { +        clearFocusObject(); +    } + +    if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) +    { +        mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus()); +        return mFocusTargetGlobal; +    } +    else if (mCameraMode == CAMERA_MODE_MOUSELOOK) +    { +        LLVector3d at_axis(1.0, 0.0, 0.0); +        LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); +        if (isAgentAvatarValid() && gAgentAvatarp->getParent()) +        { +            LLViewerObject* root_object = (LLViewerObject*)gAgentAvatarp->getRoot(); +            if (!root_object->flagCameraDecoupled()) +            { +                agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); +            } +        } +        at_axis = at_axis * agent_rot; +        mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis; +        return mFocusTargetGlobal; +    } +    else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) +    { +        if (mFocusOnAvatar) +        { +            LLVector3 focus_target = isAgentAvatarValid() +                ? gAgentAvatarp->mHeadp->getWorldPosition() +                : gAgent.getPositionAgent(); +            LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); +            mFocusTargetGlobal = focus_target_global; +        } +        return mFocusTargetGlobal; +    } +    else if (!mFocusOnAvatar) +    { +        if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull()) +        { +            LLDrawable* drawablep = mFocusObject->mDrawable; + +            if (mTrackFocusObject && +                drawablep && +                drawablep->isActive()) +            { +                if (!mFocusObject->isAvatar()) +                { +                    if (mFocusObject->isSelected()) +                    { +                        gPipeline.updateMoveNormalAsync(drawablep); +                    } +                    else +                    { +                        if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) +                        { +                            gPipeline.updateMoveNormalAsync(drawablep); +                        } +                        else +                        { +                            gPipeline.updateMoveDampedAsync(drawablep); +                        } +                    } +                } +            } +            // if not tracking object, update offset based on new object position +            else +            { +                updateFocusOffset(); +            } +            LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; +            mFocusTargetGlobal.setVec(gAgent.getPosGlobalFromAgent(focus_agent)); +        } +        return mFocusTargetGlobal; +    } +    else if (mSitCameraEnabled && isAgentAvatarValid() && gAgentAvatarp->isSitting() && mSitCameraReferenceObject.notNull()) +    { +        // sit camera +        LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); +        LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); + +        LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot); +        return gAgent.getPosGlobalFromAgent(target_pos); +    } +    else +    { +        return gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(); +    }  }  LLVector3d LLAgentCamera::calcThirdPersonFocusOffset()  { -	// ...offset from avatar -	LLVector3d focus_offset; -	LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); -	if (isAgentAvatarValid() && gAgentAvatarp->getParent()) -	{ -		agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); -	} +    // ...offset from avatar +    LLVector3d focus_offset; +    LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); +    if (isAgentAvatarValid() && gAgentAvatarp->getParent()) +    { +        agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); +    }      static LLCachedControl<LLVector3d> focus_offset_initial(gSavedSettings, "FocusOffsetRearView", LLVector3d()); -	return focus_offset_initial * agent_rot; +    return focus_offset_initial * agent_rot;  }  void LLAgentCamera::setupSitCamera()  { -	// agent frame entering this function is in world coordinates -	if (isAgentAvatarValid() && gAgentAvatarp->getParent()) -	{ -		LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); -		// slam agent coordinate frame to proper parent local version -		LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis(); -		at_axis.mV[VZ] = 0.f; -		at_axis.normalize(); -		gAgent.resetAxes(at_axis * ~parent_rot); -	} +    // agent frame entering this function is in world coordinates +    if (isAgentAvatarValid() && gAgentAvatarp->getParent()) +    { +        LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); +        // slam agent coordinate frame to proper parent local version +        LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis(); +        at_axis.mV[VZ] = 0.f; +        at_axis.normalize(); +        gAgent.resetAxes(at_axis * ~parent_rot); +    }  }  //----------------------------------------------------------------------------- @@ -1704,7 +1704,7 @@ void LLAgentCamera::setupSitCamera()  //-----------------------------------------------------------------------------  const LLVector3 &LLAgentCamera::getCameraPositionAgent() const  { -	return LLViewerCamera::getInstance()->getOrigin(); +    return LLViewerCamera::getInstance()->getOrigin();  }  //----------------------------------------------------------------------------- @@ -1712,39 +1712,39 @@ const LLVector3 &LLAgentCamera::getCameraPositionAgent() const  //-----------------------------------------------------------------------------  LLVector3d LLAgentCamera::getCameraPositionGlobal() const  { -	return gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()); +    return gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin());  }  //-----------------------------------------------------------------------------  // calcCameraFOVZoomFactor()  //----------------------------------------------------------------------------- -F32	LLAgentCamera::calcCameraFOVZoomFactor() +F32 LLAgentCamera::calcCameraFOVZoomFactor()  { -	LLVector3 camera_offset_dir; -	camera_offset_dir.setVec(mCameraFocusOffset); +    LLVector3 camera_offset_dir; +    camera_offset_dir.setVec(mCameraFocusOffset); -	if (mCameraMode == CAMERA_MODE_MOUSELOOK) -	{ -		return 0.f; -	} -	else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar) -	{ -		// don't FOV zoom on mostly transparent objects -		F32 obj_min_dist = 0.f; -		calcCameraMinDistance(obj_min_dist); -		F32 current_distance = llmax(0.001f, camera_offset_dir.magVec()); +    if (mCameraMode == CAMERA_MODE_MOUSELOOK) +    { +        return 0.f; +    } +    else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar) +    { +        // don't FOV zoom on mostly transparent objects +        F32 obj_min_dist = 0.f; +        calcCameraMinDistance(obj_min_dist); +        F32 current_distance = llmax(0.001f, camera_offset_dir.magVec()); -		mFocusObjectDist = obj_min_dist - current_distance; +        mFocusObjectDist = obj_min_dist - current_distance; -		F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f); -		return new_fov_zoom; -	} -	else // focusing on land or avatar -	{ -		// keep old field of view until user changes focus explicitly -		return mCameraFOVZoomFactor; -		//return 0.f; -	} +        F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f); +        return new_fov_zoom; +    } +    else // focusing on land or avatar +    { +        // keep old field of view until user changes focus explicitly +        return mCameraFOVZoomFactor; +        //return 0.f; +    }  }  //----------------------------------------------------------------------------- @@ -1752,307 +1752,308 @@ F32	LLAgentCamera::calcCameraFOVZoomFactor()  //-----------------------------------------------------------------------------  LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(bool *hit_limit)  { -	// Compute base camera position and look-at points. -	F32			camera_land_height; -	LLVector3d	frame_center_global = !isAgentAvatarValid() ?  -		gAgent.getPositionGlobal() : -		gAgent.getPosGlobalFromAgent(getAvatarRootPosition()); -	 -	bool		isConstrained = false; -	LLVector3d	head_offset; -	head_offset.setVec(mThirdPersonHeadOffset); - -	LLVector3d camera_position_global; - -	if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) -	{ -		camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); -	} -	else if (mCameraMode == CAMERA_MODE_MOUSELOOK) -	{ -		if (!isAgentAvatarValid() || gAgentAvatarp->mDrawable.isNull()) -		{ -			LL_WARNS() << "Null avatar drawable!" << LL_ENDL; -			return LLVector3d::zero; -		} - -		head_offset.clearVec(); -		F32 fixup; +    // Compute base camera position and look-at points. +    F32         camera_land_height; +    LLVector3d  frame_center_global = !isAgentAvatarValid() ? +        gAgent.getPositionGlobal() : +        gAgent.getPosGlobalFromAgent(getAvatarRootPosition()); + +    bool        isConstrained = false; +    LLVector3d  head_offset; +    head_offset.setVec(mThirdPersonHeadOffset); + +    LLVector3d camera_position_global; + +    if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) +    { +        camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); +    } +    else if (mCameraMode == CAMERA_MODE_MOUSELOOK) +    { +        if (!isAgentAvatarValid() || gAgentAvatarp->mDrawable.isNull()) +        { +            LL_WARNS() << "Null avatar drawable!" << LL_ENDL; +            return LLVector3d::zero; +        } + +        head_offset.clearVec(); +        F32 fixup;          if (gAgentAvatarp->hasPelvisFixup(fixup) && !gAgentAvatarp->isSitting()) -		{ -			head_offset[VZ] -= fixup; -		} -		if (gAgentAvatarp->isSitting()) -		{ -			head_offset.mdV[VZ] += 0.1; -		} - -		if (gAgentAvatarp->isSitting() && gAgentAvatarp->getParent()) -		{ -			gAgentAvatarp->updateHeadOffset(); -			head_offset.mdV[VX] += gAgentAvatarp->mHeadOffset.mV[VX]; -			head_offset.mdV[VY] += gAgentAvatarp->mHeadOffset.mV[VY]; -			head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; -			const LLMatrix4& mat = ((LLViewerObject*) gAgentAvatarp->getParent())->getRenderMatrix(); -			camera_position_global = gAgent.getPosGlobalFromAgent -								((gAgentAvatarp->getPosition()+ -								 LLVector3(head_offset)*gAgentAvatarp->getRotation()) * mat); -		} -		else -		{ -			head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; -			camera_position_global = gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());//frame_center_global; -			head_offset = head_offset * gAgentAvatarp->getRenderRotation(); -			camera_position_global = camera_position_global + head_offset; -		} -	} -	else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar) -	{ -		LLVector3 local_camera_offset; -		F32 camera_distance = 0.f; - -		if (mSitCameraEnabled  -			&& isAgentAvatarValid()  -			&& gAgentAvatarp->isSitting()  -			&& mSitCameraReferenceObject.notNull()) -		{ -			// sit camera -			LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); -			LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); - -			LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot); - -			camera_position_global = gAgent.getPosGlobalFromAgent(target_pos); -		} -		else -		{ +        { +            head_offset[VZ] -= fixup; +        } +        if (gAgentAvatarp->isSitting()) +        { +            head_offset.mdV[VZ] += 0.1; +        } + +        if (gAgentAvatarp->isSitting() && gAgentAvatarp->getParent()) +        { +            gAgentAvatarp->updateHeadOffset(); +            head_offset.mdV[VX] += gAgentAvatarp->mHeadOffset.mV[VX]; +            head_offset.mdV[VY] += gAgentAvatarp->mHeadOffset.mV[VY]; +            head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; +            const LLMatrix4& mat = ((LLViewerObject*) gAgentAvatarp->getParent())->getRenderMatrix(); +            camera_position_global = gAgent.getPosGlobalFromAgent +                                ((gAgentAvatarp->getPosition()+ +                                 LLVector3(head_offset)*gAgentAvatarp->getRotation()) * mat); +        } +        else +        { +            head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; +            camera_position_global = gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());//frame_center_global; +            head_offset = head_offset * gAgentAvatarp->getRenderRotation(); +            camera_position_global = camera_position_global + head_offset; +        } +    } +    else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar) +    { +        LLVector3 local_camera_offset; +        F32 camera_distance = 0.f; + +        if (mSitCameraEnabled +            && isAgentAvatarValid() +            && gAgentAvatarp->isSitting() +            && mSitCameraReferenceObject.notNull()) +        { +            // sit camera +            LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); +            LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); + +            LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot); + +            camera_position_global = gAgent.getPosGlobalFromAgent(target_pos); +        } +        else +        {              static LLCachedControl<F32> camera_offset_scale(gSavedSettings, "CameraOffsetScale");              local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * camera_offset_scale; -			// are we sitting down? -			if (isAgentAvatarValid() && gAgentAvatarp->getParent()) -			{ -				LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); -				// slam agent coordinate frame to proper parent local version -				LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis() * parent_rot; -				at_axis.mV[VZ] = 0.f; -				at_axis.normalize(); -				gAgent.resetAxes(at_axis * ~parent_rot); -				 -				local_camera_offset = local_camera_offset * gAgent.getFrameAgent().getQuaternion() * parent_rot; -			} -			else -			{ -				local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset ); -			} - -			if (!isDisableCameraConstraints() && !mCameraCollidePlane.isExactlyZero() && -				(!isAgentAvatarValid() || !gAgentAvatarp->isSitting())) -			{ -				LLVector3 plane_normal; -				plane_normal.setVec(mCameraCollidePlane.mV); - -				F32 offset_dot_norm = local_camera_offset * plane_normal; -				if (llabs(offset_dot_norm) < 0.001f) -				{ -					offset_dot_norm = 0.001f; -				} -				 -				camera_distance = local_camera_offset.normalize(); - -				F32 pos_dot_norm = gAgent.getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal; -				 -				// if agent is outside the colliding half-plane -				if (pos_dot_norm > mCameraCollidePlane.mV[VW]) -				{ -					// check to see if camera is on the opposite side (inside) the half-plane -					if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW]) -					{ -						// diminish offset by factor to push it back outside the half-plane -						camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm; -					} -				} -				else -				{ -					if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW]) -					{ -						camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm; -					} -				} -			} -			else -			{ -				camera_distance = local_camera_offset.normalize(); -			} - -			mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE); - -			if (mTargetCameraDistance != mCurrentCameraDistance) -			{ -				F32 camera_lerp_amt = LLSmoothInterpolation::getInterpolant(CAMERA_ZOOM_HALF_LIFE); - -				mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); -			} - -			// Make the camera distance current -			local_camera_offset *= mCurrentCameraDistance; - -			// set the global camera position -			LLVector3d camera_offset; -			 -			camera_offset.setVec( local_camera_offset ); -			camera_position_global = frame_center_global + head_offset + camera_offset; - -			if (isAgentAvatarValid()) -			{ -				LLVector3d camera_lag_d; -				F32 lag_interp = LLSmoothInterpolation::getInterpolant(CAMERA_LAG_HALF_LIFE); -				LLVector3 target_lag; -				LLVector3 vel = gAgent.getVelocity(); - -				// lag by appropriate amount for flying -				F32 time_in_air = gAgentAvatarp->mTimeInAir.getElapsedTimeF32(); -				if(!mCameraAnimating && gAgentAvatarp->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) -				{ -					LLVector3 frame_at_axis = gAgent.getFrameAgent().getAtAxis(); -					frame_at_axis -= projected_vec(frame_at_axis, gAgent.getReferenceUpVector()); -					frame_at_axis.normalize(); - -					//transition smoothly in air mode, to avoid camera pop -					F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME; -					u = llclamp(u, 0.f, 1.f); - -					lag_interp *= u; - -					if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == gAgentAvatarp->getID()) -					{ -						// disable camera lag when using mouse-directed steering -						target_lag.clearVec(); -					} -					else -					{ -						target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f; -					} - -					mCameraLag = lerp(mCameraLag, target_lag, lag_interp); - -					F32 lag_dist = mCameraLag.magVec(); -					if (lag_dist > MAX_CAMERA_LAG) -					{ -						mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist; -					} - -					// clamp camera lag so that avatar is always in front -					F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis; -					if (dot < -(MIN_CAMERA_LAG * u)) -					{ -						mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis; -					} -				} -				else -				{ -					mCameraLag = lerp(mCameraLag, LLVector3::zero, LLSmoothInterpolation::getInterpolant(0.15f)); -				} - -				camera_lag_d.setVec(mCameraLag); -				camera_position_global = camera_position_global - camera_lag_d; -			} -		} -	} -	else -	{ -		LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal(); -		// camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value -		camera_position_global = focusPosGlobal + mCameraFocusOffset; -	} - -	if (!isDisableCameraConstraints() && !gAgent.isGodlike()) -	{ -		LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); -		bool constrain = true; -		if(regionp && regionp->canManageEstate()) -		{ -			constrain = false; -		} -		if(constrain) -		{ -			F32 max_dist = (CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode) ? APPEARANCE_MAX_ZOOM : mDrawDistance; - -			LLVector3d camera_offset = camera_position_global - gAgent.getPositionGlobal(); -			F32 camera_distance = (F32)camera_offset.magVec(); - -			if(camera_distance > max_dist) -			{ -				camera_position_global = gAgent.getPositionGlobal() + (max_dist/camera_distance)*camera_offset; -				isConstrained = true; -			} -		} +            // are we sitting down? +            if (isAgentAvatarValid() && gAgentAvatarp->getParent()) +            { +                LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); +                // slam agent coordinate frame to proper parent local version +                LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis() * parent_rot; +                at_axis.mV[VZ] = 0.f; +                at_axis.normalize(); +                gAgent.resetAxes(at_axis * ~parent_rot); + +                local_camera_offset = local_camera_offset * gAgent.getFrameAgent().getQuaternion() * parent_rot; +            } +            else +            { +                local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset ); +            } + +            if (!isDisableCameraConstraints() && !mCameraCollidePlane.isExactlyZero() && +                (!isAgentAvatarValid() || !gAgentAvatarp->isSitting())) +            { +                LLVector3 plane_normal; +                plane_normal.setVec(mCameraCollidePlane.mV); + +                F32 offset_dot_norm = local_camera_offset * plane_normal; +                if (llabs(offset_dot_norm) < 0.001f) +                { +                    offset_dot_norm = 0.001f; +                } + +                camera_distance = local_camera_offset.normalize(); + +                F32 pos_dot_norm = gAgent.getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal; + +                // if agent is outside the colliding half-plane +                if (pos_dot_norm > mCameraCollidePlane.mV[VW]) +                { +                    // check to see if camera is on the opposite side (inside) the half-plane +                    if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW]) +                    { +                        // diminish offset by factor to push it back outside the half-plane +                        camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm; +                    } +                } +                else +                { +                    if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW]) +                    { +                        camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm; +                    } +                } +            } +            else +            { +                camera_distance = local_camera_offset.normalize(); +            } + +            mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE); + +            if (mTargetCameraDistance != mCurrentCameraDistance) +            { +                F32 camera_lerp_amt = LLSmoothInterpolation::getInterpolant(CAMERA_ZOOM_HALF_LIFE); + +                mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); +            } + +            // Make the camera distance current +            local_camera_offset *= mCurrentCameraDistance; + +            // set the global camera position +            LLVector3d camera_offset; + +            camera_offset.setVec( local_camera_offset ); +            camera_position_global = frame_center_global + head_offset + camera_offset; + +            if (isAgentAvatarValid()) +            { +                LLVector3d camera_lag_d; +                F32 lag_interp = LLSmoothInterpolation::getInterpolant(CAMERA_LAG_HALF_LIFE); +                LLVector3 target_lag; +                LLVector3 vel = gAgent.getVelocity(); + +                // lag by appropriate amount for flying +                F32 time_in_air = gAgentAvatarp->mTimeInAir.getElapsedTimeF32(); +                if(!mCameraAnimating && gAgentAvatarp->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) +                { +                    LLVector3 frame_at_axis = gAgent.getFrameAgent().getAtAxis(); +                    frame_at_axis -= projected_vec(frame_at_axis, gAgent.getReferenceUpVector()); +                    frame_at_axis.normalize(); + +                    //transition smoothly in air mode, to avoid camera pop +                    F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME; +                    u = llclamp(u, 0.f, 1.f); + +                    lag_interp *= u; + +                    if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == gAgentAvatarp->getID()) +                    { +                        // disable camera lag when using mouse-directed steering +                        target_lag.clearVec(); +                    } +                    else +                    { +                        LLCachedControl<F32> dynamic_camera_strength(gSavedSettings, "DynamicCameraStrength"); +                        target_lag = vel * dynamic_camera_strength / 30.f; +                    } + +                    mCameraLag = lerp(mCameraLag, target_lag, lag_interp); + +                    F32 lag_dist = mCameraLag.magVec(); +                    if (lag_dist > MAX_CAMERA_LAG) +                    { +                        mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist; +                    } + +                    // clamp camera lag so that avatar is always in front +                    F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis; +                    if (dot < -(MIN_CAMERA_LAG * u)) +                    { +                        mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis; +                    } +                } +                else +                { +                    mCameraLag = lerp(mCameraLag, LLVector3::zero, LLSmoothInterpolation::getInterpolant(0.15f)); +                } + +                camera_lag_d.setVec(mCameraLag); +                camera_position_global = camera_position_global - camera_lag_d; +            } +        } +    } +    else +    { +        LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal(); +        // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value +        camera_position_global = focusPosGlobal + mCameraFocusOffset; +    } + +    if (!isDisableCameraConstraints() && !gAgent.isGodlike()) +    { +        LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); +        bool constrain = true; +        if(regionp && regionp->canManageEstate()) +        { +            constrain = false; +        } +        if(constrain) +        { +            F32 max_dist = (CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode) ? APPEARANCE_MAX_ZOOM : mDrawDistance; + +            LLVector3d camera_offset = camera_position_global - gAgent.getPositionGlobal(); +            F32 camera_distance = (F32)camera_offset.magVec(); + +            if(camera_distance > max_dist) +            { +                camera_position_global = gAgent.getPositionGlobal() + (max_dist/camera_distance)*camera_offset; +                isConstrained = true; +            } +        }  // JC - Could constrain camera based on parcel stuff here. -//			LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); -//			 -//			if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global))) -//			{ -//				camera_position_global = last_position_global; +//          LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); +// +//          if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global))) +//          { +//              camera_position_global = last_position_global;  // -//				isConstrained = true; -//			} -	} +//              isConstrained = true; +//          } +    } -	// Don't let camera go underground -	F32 camera_min_off_ground = getCameraMinOffGround(); -	camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global); -	F32 minZ = llmax(F_ALMOST_ZERO, camera_land_height + camera_min_off_ground); -	if (camera_position_global.mdV[VZ] < minZ) -	{ -		camera_position_global.mdV[VZ] = minZ; -		isConstrained = true; -	} +    // Don't let camera go underground +    F32 camera_min_off_ground = getCameraMinOffGround(); +    camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global); +    F32 minZ = llmax(F_ALMOST_ZERO, camera_land_height + camera_min_off_ground); +    if (camera_position_global.mdV[VZ] < minZ) +    { +        camera_position_global.mdV[VZ] = minZ; +        isConstrained = true; +    } -	if (hit_limit) -	{ -		*hit_limit = isConstrained; -	} +    if (hit_limit) +    { +        *hit_limit = isConstrained; +    } -	return camera_position_global; +    return camera_position_global;  }  LLVector3 LLAgentCamera::getCurrentCameraOffset()  { -	return (LLViewerCamera::getInstance()->getOrigin() - getAvatarRootPosition() - mThirdPersonHeadOffset) * ~getCurrentAvatarRotation(); +    return (LLViewerCamera::getInstance()->getOrigin() - getAvatarRootPosition() - mThirdPersonHeadOffset) * ~getCurrentAvatarRotation();  }  LLVector3d LLAgentCamera::getCurrentFocusOffset()  { -	return (mFocusTargetGlobal - gAgent.getPositionGlobal()) * ~getCurrentAvatarRotation(); +    return (mFocusTargetGlobal - gAgent.getPositionGlobal()) * ~getCurrentAvatarRotation();  }  LLQuaternion LLAgentCamera::getCurrentAvatarRotation()  { -	LLViewerObject* sit_object = (LLViewerObject*)gAgentAvatarp->getParent(); -	 -	LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion(); -	LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT; -	return av_rot * obj_rot; +    LLViewerObject* sit_object = (LLViewerObject*)gAgentAvatarp->getParent(); + +    LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion(); +    LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT; +    return av_rot * obj_rot;  }  bool LLAgentCamera::isJoystickCameraUsed()  { -	return ((mOrbitAroundRadians != 0) || (mOrbitOverAngle != 0) || !mPanFocusDiff.isNull()); +    return ((mOrbitAroundRadians != 0) || (mOrbitOverAngle != 0) || !mPanFocusDiff.isNull());  }  LLVector3 LLAgentCamera::getCameraOffsetInitial()  {      // getCameraOffsetInitial and getFocusOffsetInitial can be called on update from idle before init()      static LLCachedControl<LLVector3> camera_offset_initial (gSavedSettings, "CameraOffsetRearView", LLVector3()); -	return camera_offset_initial; +    return camera_offset_initial;  }  LLVector3d LLAgentCamera::getFocusOffsetInitial()  {      static LLCachedControl<LLVector3d> focus_offset_initial(gSavedSettings, "FocusOffsetRearView", LLVector3d()); -	return focus_offset_initial; +    return focus_offset_initial;  }  F32 LLAgentCamera::getCameraMaxZoomDistance() @@ -2081,48 +2082,48 @@ LLVector3 LLAgentCamera::getAvatarRootPosition()  //-----------------------------------------------------------------------------  void LLAgentCamera::handleScrollWheel(S32 clicks)  { -	if (mCameraMode == CAMERA_MODE_FOLLOW && getFocusOnAvatar()) -	{ -		if (!mFollowCam.getPositionLocked()) // not if the followCam position is locked in place -		{ -			mFollowCam.zoom(clicks);  -			if (mFollowCam.isZoomedToMinimumDistance()) -			{ -				changeCameraToMouselook(false); -			} -		} -	} -	else -	{ -		LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); -		const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); - -		// Block if camera is animating -		if (mCameraAnimating) -		{ -			return; -		} - -		if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) -		{ -			F32 zoom_factor = (F32)pow(0.8, -clicks); -			cameraZoomIn(zoom_factor); -		} -		else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON)) -		{ -			F32 camera_offset_initial_mag = getCameraOffsetInitial().magVec(); -			 -			F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); -			current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); -			 -			cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); -		} -		else -		{ -			F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec(); -			cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks))); -		} -	} +    if (mCameraMode == CAMERA_MODE_FOLLOW && getFocusOnAvatar()) +    { +        if (!mFollowCam.getPositionLocked()) // not if the followCam position is locked in place +        { +            mFollowCam.zoom(clicks); +            if (mFollowCam.isZoomedToMinimumDistance()) +            { +                changeCameraToMouselook(false); +            } +        } +    } +    else +    { +        LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); +        const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); + +        // Block if camera is animating +        if (mCameraAnimating) +        { +            return; +        } + +        if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) +        { +            F32 zoom_factor = (F32)pow(0.8, -clicks); +            cameraZoomIn(zoom_factor); +        } +        else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON)) +        { +            F32 camera_offset_initial_mag = getCameraOffsetInitial().magVec(); + +            F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); +            current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); + +            cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); +        } +        else +        { +            F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec(); +            cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks))); +        } +    }  } @@ -2131,17 +2132,17 @@ void LLAgentCamera::handleScrollWheel(S32 clicks)  //-----------------------------------------------------------------------------  F32 LLAgentCamera::getCameraMinOffGround()  { -	if (mCameraMode == CAMERA_MODE_MOUSELOOK) -	{ -		return 0.f; -	} +    if (mCameraMode == CAMERA_MODE_MOUSELOOK) +    { +        return 0.f; +    } -	if (isDisableCameraConstraints()) -	{ -		return -1000.f; -	} +    if (isDisableCameraConstraints()) +    { +        return -1000.f; +    } -	return 0.5f; +    return 0.5f;  } @@ -2150,15 +2151,15 @@ F32 LLAgentCamera::getCameraMinOffGround()  //-----------------------------------------------------------------------------  void LLAgentCamera::resetCamera()  { -	// Remove any pitch from the avatar -	LLVector3 at = gAgent.getFrameAgent().getAtAxis(); -	at.mV[VZ] = 0.f; -	at.normalize(); -	gAgent.resetAxes(at); -	// have to explicitly clear field of view zoom now -	mCameraFOVZoomFactor = 0.f; +    // Remove any pitch from the avatar +    LLVector3 at = gAgent.getFrameAgent().getAtAxis(); +    at.mV[VZ] = 0.f; +    at.normalize(); +    gAgent.resetAxes(at); +    // have to explicitly clear field of view zoom now +    mCameraFOVZoomFactor = 0.f; -	updateCamera(); +    updateCamera();  }  //----------------------------------------------------------------------------- @@ -2166,58 +2167,58 @@ void LLAgentCamera::resetCamera()  //-----------------------------------------------------------------------------  void LLAgentCamera::changeCameraToMouselook(bool animate)  { -	if (!gSavedSettings.getBOOL("EnableMouselook")  -		|| LLViewerJoystick::getInstance()->getOverrideCamera()) -	{ -		return; -	} -	 -	// visibility changes at end of animation -	gViewerWindow->getWindow()->resetBusyCount(); - -	// Menus should not remain open on switching to mouselook... -	LLMenuGL::sMenuContainer->hideMenus(); -	LLUI::getInstance()->clearPopups(); - -	// unpause avatar animation -	gAgent.unpauseAnimation(); - -	LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); - -	if (isAgentAvatarValid()) -	{ -		gAgentAvatarp->stopMotion(ANIM_AGENT_BODY_NOISE); -		gAgentAvatarp->stopMotion(ANIM_AGENT_BREATHE_ROT); -	} - -	//gViewerWindow->stopGrab(); -	LLSelectMgr::getInstance()->deselectAll(); -	gViewerWindow->hideCursor(); -	gViewerWindow->moveCursorToCenter(); - -	if (mCameraMode != CAMERA_MODE_MOUSELOOK) -	{ -		gFocusMgr.setKeyboardFocus(NULL); -		 -		updateLastCamera(); -		mCameraMode = CAMERA_MODE_MOUSELOOK; -		const U32 old_flags = gAgent.getControlFlags(); -		gAgent.setControlFlags(AGENT_CONTROL_MOUSELOOK); -		if (old_flags != gAgent.getControlFlags()) -		{ -			gAgent.setFlagsDirty(); -		} - -		if (animate) -		{ -			startCameraAnimation(); -		} -		else -		{ -			mCameraAnimating = false; -			gAgent.endAnimationUpdateUI(); -		} -	} +    if (!gSavedSettings.getBOOL("EnableMouselook") +        || LLViewerJoystick::getInstance()->getOverrideCamera()) +    { +        return; +    } + +    // visibility changes at end of animation +    gViewerWindow->getWindow()->resetBusyCount(); + +    // Menus should not remain open on switching to mouselook... +    LLMenuGL::sMenuContainer->hideMenus(); +    LLUI::getInstance()->clearPopups(); + +    // unpause avatar animation +    gAgent.unpauseAnimation(); + +    LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); + +    if (isAgentAvatarValid()) +    { +        gAgentAvatarp->stopMotion(ANIM_AGENT_BODY_NOISE); +        gAgentAvatarp->stopMotion(ANIM_AGENT_BREATHE_ROT); +    } + +    //gViewerWindow->stopGrab(); +    LLSelectMgr::getInstance()->deselectAll(); +    gViewerWindow->hideCursor(); +    gViewerWindow->moveCursorToCenter(); + +    if (mCameraMode != CAMERA_MODE_MOUSELOOK) +    { +        gFocusMgr.setKeyboardFocus(NULL); + +        updateLastCamera(); +        mCameraMode = CAMERA_MODE_MOUSELOOK; +        const U32 old_flags = gAgent.getControlFlags(); +        gAgent.setControlFlags(AGENT_CONTROL_MOUSELOOK); +        if (old_flags != gAgent.getControlFlags()) +        { +            gAgent.setFlagsDirty(); +        } + +        if (animate) +        { +            startCameraAnimation(); +        } +        else +        { +            mCameraAnimating = false; +            gAgent.endAnimationUpdateUI(); +        } +    }  } @@ -2226,24 +2227,24 @@ void LLAgentCamera::changeCameraToMouselook(bool animate)  //-----------------------------------------------------------------------------  void LLAgentCamera::changeCameraToDefault()  { -	if (LLViewerJoystick::getInstance()->getOverrideCamera()) -	{ -		return; -	} +    if (LLViewerJoystick::getInstance()->getOverrideCamera()) +    { +        return; +    } -	if (LLFollowCamMgr::getInstance()->getActiveFollowCamParams()) -	{ -		changeCameraToFollow(); -	} -	else -	{ -		changeCameraToThirdPerson(); -	} -	if (gSavedSettings.getBOOL("HideUIControls")) -	{ -		gViewerWindow->setUIVisibility(false); -		LLPanelStandStopFlying::getInstance()->setVisible(false); -	} +    if (LLFollowCamMgr::getInstance()->getActiveFollowCamParams()) +    { +        changeCameraToFollow(); +    } +    else +    { +        changeCameraToThirdPerson(); +    } +    if (gSavedSettings.getBOOL("HideUIControls")) +    { +        gViewerWindow->setUIVisibility(false); +        LLPanelStandStopFlying::getInstance()->setVisible(false); +    }  } @@ -2252,53 +2253,53 @@ void LLAgentCamera::changeCameraToDefault()  //-----------------------------------------------------------------------------  void LLAgentCamera::changeCameraToFollow(bool animate)  { -	if (LLViewerJoystick::getInstance()->getOverrideCamera()) -	{ -		return; -	} - -	if(mCameraMode != CAMERA_MODE_FOLLOW) -	{ -		if (mCameraMode == CAMERA_MODE_MOUSELOOK) -		{ -			animate = false; -		} -		startCameraAnimation(); - -		updateLastCamera(); -		mCameraMode = CAMERA_MODE_FOLLOW; - -		// bang-in the current focus, position, and up vector of the follow cam -		mFollowCam.reset(mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis); -		 -		if (gBasicToolset) -		{ -			LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); -		} - -		if (isAgentAvatarValid()) -		{ -			// SL-315 -			gAgentAvatarp->mPelvisp->setPosition(LLVector3::zero); -			gAgentAvatarp->startMotion( ANIM_AGENT_BODY_NOISE ); -			gAgentAvatarp->startMotion( ANIM_AGENT_BREATHE_ROT ); -		} - -		// unpause avatar animation -		gAgent.unpauseAnimation(); - -		gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); - -		if (animate) -		{ -			startCameraAnimation(); -		} -		else -		{ -			mCameraAnimating = false; -			gAgent.endAnimationUpdateUI(); -		} -	} +    if (LLViewerJoystick::getInstance()->getOverrideCamera()) +    { +        return; +    } + +    if(mCameraMode != CAMERA_MODE_FOLLOW) +    { +        if (mCameraMode == CAMERA_MODE_MOUSELOOK) +        { +            animate = false; +        } +        startCameraAnimation(); + +        updateLastCamera(); +        mCameraMode = CAMERA_MODE_FOLLOW; + +        // bang-in the current focus, position, and up vector of the follow cam +        mFollowCam.reset(mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis); + +        if (gBasicToolset) +        { +            LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); +        } + +        if (isAgentAvatarValid()) +        { +            // SL-315 +            gAgentAvatarp->mPelvisp->setPosition(LLVector3::zero); +            gAgentAvatarp->startMotion( ANIM_AGENT_BODY_NOISE ); +            gAgentAvatarp->startMotion( ANIM_AGENT_BREATHE_ROT ); +        } + +        // unpause avatar animation +        gAgent.unpauseAnimation(); + +        gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); + +        if (animate) +        { +            startCameraAnimation(); +        } +        else +        { +            mCameraAnimating = false; +            gAgent.endAnimationUpdateUI(); +        } +    }  }  //----------------------------------------------------------------------------- @@ -2306,69 +2307,69 @@ void LLAgentCamera::changeCameraToFollow(bool animate)  //-----------------------------------------------------------------------------  void LLAgentCamera::changeCameraToThirdPerson(bool animate)  { -	if (LLViewerJoystick::getInstance()->getOverrideCamera()) -	{ -		return; -	} - -	gViewerWindow->getWindow()->resetBusyCount(); - -	mCameraZoomFraction = INITIAL_ZOOM_FRACTION; - -	if (isAgentAvatarValid()) -	{ -		if (!gAgentAvatarp->isSitting()) -		{ -			// SL-315 -			gAgentAvatarp->mPelvisp->setPosition(LLVector3::zero); -		} -		gAgentAvatarp->startMotion(ANIM_AGENT_BODY_NOISE); -		gAgentAvatarp->startMotion(ANIM_AGENT_BREATHE_ROT); -	} - -	LLVector3 at_axis; - -	// unpause avatar animation -	gAgent.unpauseAnimation(); - -	if (mCameraMode != CAMERA_MODE_THIRD_PERSON) -	{ -		if (gBasicToolset) -		{ -			LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); -		} - -		mCameraLag.clearVec(); -		if (mCameraMode == CAMERA_MODE_MOUSELOOK) -		{ -			mCurrentCameraDistance = MIN_CAMERA_DISTANCE; -			mTargetCameraDistance = MIN_CAMERA_DISTANCE; -			animate = false; -		} -		updateLastCamera(); -		mCameraMode = CAMERA_MODE_THIRD_PERSON; -		gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); -	} - -	// Remove any pitch from the avatar -	if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) -	{ -		at_axis = gAgent.getFrameAgent().getAtAxis(); -		at_axis.mV[VZ] = 0.f; -		at_axis.normalize(); -		gAgent.resetAxes(at_axis); -	} - - -	if (animate) -	{ -		startCameraAnimation(); -	} -	else -	{ -		mCameraAnimating = false; -		gAgent.endAnimationUpdateUI(); -	} +    if (LLViewerJoystick::getInstance()->getOverrideCamera()) +    { +        return; +    } + +    gViewerWindow->getWindow()->resetBusyCount(); + +    mCameraZoomFraction = INITIAL_ZOOM_FRACTION; + +    if (isAgentAvatarValid()) +    { +        if (!gAgentAvatarp->isSitting()) +        { +            // SL-315 +            gAgentAvatarp->mPelvisp->setPosition(LLVector3::zero); +        } +        gAgentAvatarp->startMotion(ANIM_AGENT_BODY_NOISE); +        gAgentAvatarp->startMotion(ANIM_AGENT_BREATHE_ROT); +    } + +    LLVector3 at_axis; + +    // unpause avatar animation +    gAgent.unpauseAnimation(); + +    if (mCameraMode != CAMERA_MODE_THIRD_PERSON) +    { +        if (gBasicToolset) +        { +            LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); +        } + +        mCameraLag.clearVec(); +        if (mCameraMode == CAMERA_MODE_MOUSELOOK) +        { +            mCurrentCameraDistance = MIN_CAMERA_DISTANCE; +            mTargetCameraDistance = MIN_CAMERA_DISTANCE; +            animate = false; +        } +        updateLastCamera(); +        mCameraMode = CAMERA_MODE_THIRD_PERSON; +        gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); +    } + +    // Remove any pitch from the avatar +    if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) +    { +        at_axis = gAgent.getFrameAgent().getAtAxis(); +        at_axis.mV[VZ] = 0.f; +        at_axis.normalize(); +        gAgent.resetAxes(at_axis); +    } + + +    if (animate) +    { +        startCameraAnimation(); +    } +    else +    { +        mCameraAnimating = false; +        gAgent.endAnimationUpdateUI(); +    }  }  //----------------------------------------------------------------------------- @@ -2376,89 +2377,89 @@ void LLAgentCamera::changeCameraToThirdPerson(bool animate)  //-----------------------------------------------------------------------------  void LLAgentCamera::changeCameraToCustomizeAvatar()  { -	if (LLViewerJoystick::getInstance()->getOverrideCamera() || !isAgentAvatarValid()) -	{ -		return; -	} +    if (LLViewerJoystick::getInstance()->getOverrideCamera() || !isAgentAvatarValid()) +    { +        return; +    } -	gAgent.standUp(); // force stand up -	gViewerWindow->getWindow()->resetBusyCount(); +    gAgent.standUp(); // force stand up +    gViewerWindow->getWindow()->resetBusyCount();      if (LLSelectMgr::getInstance()->getSelection()->isAttachment())      {          LLSelectMgr::getInstance()->deselectAll();      } -	if (gFaceEditToolset) -	{ -		LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); -	} - -	startCameraAnimation(); - -	if (mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR) -	{ -		updateLastCamera(); -		mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR; -		gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); - -		gFocusMgr.setKeyboardFocus( NULL ); -		gFocusMgr.setMouseCapture( NULL ); -		if( gMorphView ) -		{ -			gMorphView->setVisible( true ); -		} -		// Remove any pitch or rotation from the avatar -		LLVector3 at = gAgent.getAtAxis(); -		at.mV[VZ] = 0.f; -		at.normalize(); -		gAgent.resetAxes(at); - -		gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); -		gAgent.setCustomAnim(true); -		gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); -		LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); - -		if (turn_motion) -		{ -			// delay camera animation long enough to play through turn animation -			setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); -		} -	} - -	LLVector3 agent_at = gAgent.getAtAxis(); -	agent_at.mV[VZ] = 0.f; -	agent_at.normalize(); - -	// default focus point for customize avatar -	LLVector3 focus_target = isAgentAvatarValid()  -		? gAgentAvatarp->mHeadp->getWorldPosition() -		: gAgent.getPositionAgent(); - -	LLVector3d camera_offset(agent_at * -1.0); -	// push camera up and out from avatar -	camera_offset.mdV[VZ] = 0.1f;  -	camera_offset *= CUSTOMIZE_AVATAR_CAMERA_DEFAULT_DIST; -	LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); -	setAnimationDuration(gSavedSettings.getF32("ZoomTime")); -	setCameraPosAndFocusGlobal(focus_target_global + camera_offset, focus_target_global, gAgent.getID()); +    if (gFaceEditToolset) +    { +        LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); +    } + +    startCameraAnimation(); + +    if (mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR) +    { +        updateLastCamera(); +        mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR; +        gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); + +        gFocusMgr.setKeyboardFocus( NULL ); +        gFocusMgr.setMouseCapture( NULL ); +        if( gMorphView ) +        { +            gMorphView->setVisible( true ); +        } +        // Remove any pitch or rotation from the avatar +        LLVector3 at = gAgent.getAtAxis(); +        at.mV[VZ] = 0.f; +        at.normalize(); +        gAgent.resetAxes(at); + +        gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); +        gAgent.setCustomAnim(true); +        gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); +        LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); + +        if (turn_motion) +        { +            // delay camera animation long enough to play through turn animation +            setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); +        } +    } + +    LLVector3 agent_at = gAgent.getAtAxis(); +    agent_at.mV[VZ] = 0.f; +    agent_at.normalize(); + +    // default focus point for customize avatar +    LLVector3 focus_target = isAgentAvatarValid() +        ? gAgentAvatarp->mHeadp->getWorldPosition() +        : gAgent.getPositionAgent(); + +    LLVector3d camera_offset(agent_at * -1.0); +    // push camera up and out from avatar +    camera_offset.mdV[VZ] = 0.1f; +    camera_offset *= CUSTOMIZE_AVATAR_CAMERA_DEFAULT_DIST; +    LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); +    setAnimationDuration(gSavedSettings.getF32("ZoomTime")); +    setCameraPosAndFocusGlobal(focus_target_global + camera_offset, focus_target_global, gAgent.getID());  }  void LLAgentCamera::switchCameraPreset(ECameraPreset preset)  { -	//zoom is supposed to be reset for the front and group views -	mCameraZoomFraction = 1.f; +    //zoom is supposed to be reset for the front and group views +    mCameraZoomFraction = 1.f; -	//focusing on avatar in that case means following him on movements -	mFocusOnAvatar = true; +    //focusing on avatar in that case means following him on movements +    mFocusOnAvatar = true; -	mCameraPreset = preset; +    mCameraPreset = preset; -	resetPanDiff(); -	resetOrbitDiff(); +    resetPanDiff(); +    resetOrbitDiff(); -	gSavedSettings.setU32("CameraPresetType", mCameraPreset); +    gSavedSettings.setU32("CameraPresetType", mCameraPreset);  } @@ -2467,17 +2468,17 @@ void LLAgentCamera::switchCameraPreset(ECameraPreset preset)  //  void LLAgentCamera::setAnimationDuration(F32 duration) -{  -	if (mCameraAnimating) -	{ -		// do not cut any existing camera animation short -		F32 animation_left = llmax(0.f, mAnimationDuration - mAnimationTimer.getElapsedTimeF32()); -		mAnimationDuration = llmax(duration, animation_left); -	} -	else -	{ -		mAnimationDuration = duration;  -	} +{ +    if (mCameraAnimating) +    { +        // do not cut any existing camera animation short +        F32 animation_left = llmax(0.f, mAnimationDuration - mAnimationTimer.getElapsedTimeF32()); +        mAnimationDuration = llmax(duration, animation_left); +    } +    else +    { +        mAnimationDuration = duration; +    }  }  //----------------------------------------------------------------------------- @@ -2485,11 +2486,11 @@ void LLAgentCamera::setAnimationDuration(F32 duration)  //-----------------------------------------------------------------------------  void LLAgentCamera::startCameraAnimation()  { -	mAnimationCameraStartGlobal = getCameraPositionGlobal(); -	mAnimationFocusStartGlobal = mFocusGlobal; -	setAnimationDuration(gSavedSettings.getF32("ZoomTime")); -	mAnimationTimer.reset(); -	mCameraAnimating = true; +    mAnimationCameraStartGlobal = getCameraPositionGlobal(); +    mAnimationFocusStartGlobal = mFocusGlobal; +    setAnimationDuration(gSavedSettings.getF32("ZoomTime")); +    mAnimationTimer.reset(); +    mCameraAnimating = true;  }  //----------------------------------------------------------------------------- @@ -2497,23 +2498,23 @@ void LLAgentCamera::startCameraAnimation()  //-----------------------------------------------------------------------------  void LLAgentCamera::stopCameraAnimation()  { -	mCameraAnimating = false; +    mCameraAnimating = false;  }  void LLAgentCamera::clearFocusObject()  { -	if (mFocusObject.notNull()) -	{ -		startCameraAnimation(); +    if (mFocusObject.notNull()) +    { +        startCameraAnimation(); -		setFocusObject(NULL); -		mFocusObjectOffset.clearVec(); -	} +        setFocusObject(NULL); +        mFocusObjectOffset.clearVec(); +    }  }  void LLAgentCamera::setFocusObject(LLViewerObject* object)  { -	mFocusObject = object; +    mFocusObject = object;  }  // Focus on a point, but try to keep camera position stable. @@ -2522,104 +2523,104 @@ void LLAgentCamera::setFocusObject(LLViewerObject* object)  //-----------------------------------------------------------------------------  void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick)  { -	LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); +    LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); -	if (objectp && pick.mGLTFNodeIndex == -1) -	{ -		// focus on object plus designated offset -		// which may or may not be same as pick.mPosGlobal -		setFocusGlobal(objectp->getPositionGlobal() + LLVector3d(pick.mObjectOffset), pick.mObjectID); -	} -	else -	{ -		// focus directly on point where user clicked -		setFocusGlobal(pick.mPosGlobal, pick.mObjectID); -	} +    if (objectp && pick.mGLTFNodeIndex == -1) +    { +        // focus on object plus designated offset +        // which may or may not be same as pick.mPosGlobal +        setFocusGlobal(objectp->getPositionGlobal() + LLVector3d(pick.mObjectOffset), pick.mObjectID); +    } +    else +    { +        // focus directly on point where user clicked +        setFocusGlobal(pick.mPosGlobal, pick.mObjectID); +    }  }  void LLAgentCamera::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id)  { -	setFocusObject(gObjectList.findObject(object_id)); -	LLVector3d old_focus = mFocusTargetGlobal; -	LLViewerObject *focus_obj = mFocusObject; - -	// if focus has changed -	if (old_focus != focus) -	{ -		if (focus.isExactlyZero()) -		{ -			if (isAgentAvatarValid()) -			{ -				mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); -			} -			else -			{ -				mFocusTargetGlobal = gAgent.getPositionGlobal(); -			} -			mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal; -			mCameraFocusOffset = mCameraFocusOffsetTarget; -			setLookAt(LOOKAT_TARGET_CLEAR); -		} -		else -		{ -			mFocusTargetGlobal = focus; -			if (!focus_obj) -			{ -				mCameraFOVZoomFactor = 0.f; -			} - -			mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal; - -			startCameraAnimation(); - -			if (focus_obj) -			{ -				if (focus_obj->isAvatar()) -				{ -					setLookAt(LOOKAT_TARGET_FOCUS, focus_obj); -				} -				else -				{ -					setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (gAgent.getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation()); -				} -			} -			else -			{ -				setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); -			} -		} -	} -	else // focus == mFocusTargetGlobal -	{ -		if (focus.isExactlyZero()) -		{ -			if (isAgentAvatarValid()) -			{ -				mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); -			} -			else -			{ -				mFocusTargetGlobal = gAgent.getPositionGlobal(); -			} -		} -		mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);; -		mCameraFocusOffset = mCameraFocusOffsetTarget; -	} - -	if (mFocusObject.notNull()) -	{ -		// for attachments, make offset relative to avatar, not the attachment -		if (mFocusObject->isAttachment()) -		{ -			while (mFocusObject.notNull() && !mFocusObject->isAvatar()) -			{ -				mFocusObject = (LLViewerObject*) mFocusObject->getParent(); -			} -			setFocusObject((LLViewerObject*)mFocusObject); -		} -		updateFocusOffset(); -	} +    setFocusObject(gObjectList.findObject(object_id)); +    LLVector3d old_focus = mFocusTargetGlobal; +    LLViewerObject *focus_obj = mFocusObject; + +    // if focus has changed +    if (old_focus != focus) +    { +        if (focus.isExactlyZero()) +        { +            if (isAgentAvatarValid()) +            { +                mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); +            } +            else +            { +                mFocusTargetGlobal = gAgent.getPositionGlobal(); +            } +            mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal; +            mCameraFocusOffset = mCameraFocusOffsetTarget; +            setLookAt(LOOKAT_TARGET_CLEAR); +        } +        else +        { +            mFocusTargetGlobal = focus; +            if (!focus_obj) +            { +                mCameraFOVZoomFactor = 0.f; +            } + +            mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal; + +            startCameraAnimation(); + +            if (focus_obj) +            { +                if (focus_obj->isAvatar()) +                { +                    setLookAt(LOOKAT_TARGET_FOCUS, focus_obj); +                } +                else +                { +                    setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (gAgent.getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation()); +                } +            } +            else +            { +                setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); +            } +        } +    } +    else // focus == mFocusTargetGlobal +    { +        if (focus.isExactlyZero()) +        { +            if (isAgentAvatarValid()) +            { +                mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); +            } +            else +            { +                mFocusTargetGlobal = gAgent.getPositionGlobal(); +            } +        } +        mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);; +        mCameraFocusOffset = mCameraFocusOffsetTarget; +    } + +    if (mFocusObject.notNull()) +    { +        // for attachments, make offset relative to avatar, not the attachment +        if (mFocusObject->isAttachment()) +        { +            while (mFocusObject.notNull() && !mFocusObject->isAvatar()) +            { +                mFocusObject = (LLViewerObject*) mFocusObject->getParent(); +            } +            setFocusObject((LLViewerObject*)mFocusObject); +        } +        updateFocusOffset(); +    }  }  // Used for avatar customization @@ -2628,48 +2629,48 @@ void LLAgentCamera::setFocusGlobal(const LLVector3d& focus, const LLUUID &object  //-----------------------------------------------------------------------------  void LLAgentCamera::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, const LLVector3d& focus, const LLUUID &object_id)  { -	LLVector3d old_focus = mFocusTargetGlobal.isExactlyZero() ? focus : mFocusTargetGlobal; - -	F64 focus_delta_squared = (old_focus - focus).magVecSquared(); -	const F64 ANIM_EPSILON_SQUARED = 0.0001; -	if (focus_delta_squared > ANIM_EPSILON_SQUARED) -	{ -		startCameraAnimation(); -	} -	 -	//LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) ); -	setFocusObject(gObjectList.findObject(object_id)); -	mFocusTargetGlobal = focus; -	mCameraFocusOffsetTarget = camera_pos - focus; -	mCameraFocusOffset = mCameraFocusOffsetTarget; - -	if (mFocusObject) -	{ -		if (mFocusObject->isAvatar()) -		{ -			setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject); -		} -		else -		{ -			setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (gAgent.getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation()); -		} -	} -	else -	{ -		setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); -	} - -	if (mCameraAnimating) -	{ -		const F64 ANIM_METERS_PER_SECOND = 10.0; -		const F64 MIN_ANIM_SECONDS = 0.5; -		const F64 MAX_ANIM_SECONDS = 10.0; -		F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); -		anim_duration = llmin( anim_duration, MAX_ANIM_SECONDS ); -		setAnimationDuration( (F32)anim_duration ); -	} - -	updateFocusOffset(); +    LLVector3d old_focus = mFocusTargetGlobal.isExactlyZero() ? focus : mFocusTargetGlobal; + +    F64 focus_delta_squared = (old_focus - focus).magVecSquared(); +    const F64 ANIM_EPSILON_SQUARED = 0.0001; +    if (focus_delta_squared > ANIM_EPSILON_SQUARED) +    { +        startCameraAnimation(); +    } + +    //LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) ); +    setFocusObject(gObjectList.findObject(object_id)); +    mFocusTargetGlobal = focus; +    mCameraFocusOffsetTarget = camera_pos - focus; +    mCameraFocusOffset = mCameraFocusOffsetTarget; + +    if (mFocusObject) +    { +        if (mFocusObject->isAvatar()) +        { +            setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject); +        } +        else +        { +            setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (gAgent.getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation()); +        } +    } +    else +    { +        setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); +    } + +    if (mCameraAnimating) +    { +        const F64 ANIM_METERS_PER_SECOND = 10.0; +        const F64 MIN_ANIM_SECONDS = 0.5; +        const F64 MAX_ANIM_SECONDS = 10.0; +        F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); +        anim_duration = llmin( anim_duration, MAX_ANIM_SECONDS ); +        setAnimationDuration( (F32)anim_duration ); +    } + +    updateFocusOffset();  }  //----------------------------------------------------------------------------- @@ -2677,27 +2678,27 @@ void LLAgentCamera::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, con  //-----------------------------------------------------------------------------  void LLAgentCamera::setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos, const LLVector3 &camera_focus)  { -	bool camera_enabled = !object_id.isNull(); - -	if (camera_enabled) -	{ -		LLViewerObject *reference_object = gObjectList.findObject(object_id); -		if (reference_object) -		{ -			//convert to root object relative? -			mSitCameraPos = camera_pos; -			mSitCameraFocus = camera_focus; -			mSitCameraReferenceObject = reference_object; -			mSitCameraEnabled = true; -		} -	} -	else -	{ -		mSitCameraPos.clearVec(); -		mSitCameraFocus.clearVec(); -		mSitCameraReferenceObject = NULL; -		mSitCameraEnabled = false; -	} +    bool camera_enabled = !object_id.isNull(); + +    if (camera_enabled) +    { +        LLViewerObject *reference_object = gObjectList.findObject(object_id); +        if (reference_object) +        { +            //convert to root object relative? +            mSitCameraPos = camera_pos; +            mSitCameraFocus = camera_focus; +            mSitCameraReferenceObject = reference_object; +            mSitCameraEnabled = true; +        } +    } +    else +    { +        mSitCameraPos.clearVec(); +        mSitCameraFocus.clearVec(); +        mSitCameraReferenceObject = NULL; +        mSitCameraEnabled = false; +    }  }  //----------------------------------------------------------------------------- @@ -2705,30 +2706,30 @@ void LLAgentCamera::setSitCamera(const LLUUID &object_id, const LLVector3 &camer  //-----------------------------------------------------------------------------  void LLAgentCamera::setFocusOnAvatar(bool focus_on_avatar, bool animate, bool reset_axes)  { -	if (focus_on_avatar != mFocusOnAvatar) -	{ -		if (animate) -		{ -			startCameraAnimation(); -		} -		else -		{ -			stopCameraAnimation(); -		} -	} -	 -	//RN: when focused on the avatar, we're not "looking" at it -	// looking implies intent while focusing on avatar means -	// you're just walking around with a camera on you...eesh. -	if (!mFocusOnAvatar && focus_on_avatar && reset_axes) -	{ -		setFocusGlobal(LLVector3d::zero); -		mCameraFOVZoomFactor = 0.f; -		if (mCameraMode == CAMERA_MODE_THIRD_PERSON) -		{ -			LLVector3 at_axis; -			if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) -			{ +    if (focus_on_avatar != mFocusOnAvatar) +    { +        if (animate) +        { +            startCameraAnimation(); +        } +        else +        { +            stopCameraAnimation(); +        } +    } + +    //RN: when focused on the avatar, we're not "looking" at it +    // looking implies intent while focusing on avatar means +    // you're just walking around with a camera on you...eesh. +    if (!mFocusOnAvatar && focus_on_avatar && reset_axes) +    { +        setFocusGlobal(LLVector3d::zero); +        mCameraFOVZoomFactor = 0.f; +        if (mCameraMode == CAMERA_MODE_THIRD_PERSON) +        { +            LLVector3 at_axis; +            if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) +            {                  // In case of front view rotate agent to look into direction opposite to camera                  // In case of rear view rotate agent into diraction same as camera, e t c                  LLVector3 vect = getCameraOffsetInitial(); @@ -2742,44 +2743,44 @@ void LLAgentCamera::setFocusOnAvatar(bool focus_on_avatar, bool animate, bool re                  at_axis.normalize();                  gAgent.resetAxes(at_axis);                  gAgent.yaw(0); -			} -		} -	} -	// unlocking camera from avatar -	else if (mFocusOnAvatar && !focus_on_avatar) -	{ -		// keep camera focus point consistent, even though it is now unlocked -		setFocusGlobal(gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); -		mAllowChangeToFollow = false; -	} -	 -	mFocusOnAvatar = focus_on_avatar; +            } +        } +    } +    // unlocking camera from avatar +    else if (mFocusOnAvatar && !focus_on_avatar) +    { +        // keep camera focus point consistent, even though it is now unlocked +        setFocusGlobal(gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); +        mAllowChangeToFollow = false; +    } + +    mFocusOnAvatar = focus_on_avatar;  }  bool LLAgentCamera::setLookAt(ELookAtType target_type, LLViewerObject *object, LLVector3 position)  { -	if(object && object->isAttachment()) -	{ -		LLViewerObject* parent = object; -		while(parent) -		{ -			if (parent == gAgentAvatarp) -			{ -				// looking at an attachment on ourselves, which we don't want to do -				object = gAgentAvatarp; -				position.clearVec(); -			} -			parent = (LLViewerObject*)parent->getParent(); -		} -	} -	if(!mLookAt || mLookAt->isDead()) -	{ -		mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); -		mLookAt->setSourceObject(gAgentAvatarp); -	} - -	return mLookAt->setLookAt(target_type, object, position); +    if(object && object->isAttachment()) +    { +        LLViewerObject* parent = object; +        while(parent) +        { +            if (parent == gAgentAvatarp) +            { +                // looking at an attachment on ourselves, which we don't want to do +                object = gAgentAvatarp; +                position.clearVec(); +            } +            parent = (LLViewerObject*)parent->getParent(); +        } +    } +    if(!mLookAt || mLookAt->isDead()) +    { +        mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); +        mLookAt->setSourceObject(gAgentAvatarp); +    } + +    return mLookAt->setLookAt(target_type, object, position);  }  //----------------------------------------------------------------------------- @@ -2787,168 +2788,168 @@ bool LLAgentCamera::setLookAt(ELookAtType target_type, LLViewerObject *object, L  //-----------------------------------------------------------------------------  void LLAgentCamera::lookAtLastChat()  { -	// Block if camera is animating or not in normal third person camera mode -	if (mCameraAnimating || !cameraThirdPerson()) -	{ -		return; -	} - -	LLViewerObject *chatter = gObjectList.findObject(gAgent.getLastChatter()); -	if (!chatter) -	{ -		return; -	} - -	LLVector3 delta_pos; -	if (chatter->isAvatar()) -	{ -		LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; -		if (isAgentAvatarValid() && chatter_av->mHeadp) -		{ -			delta_pos = chatter_av->mHeadp->getWorldPosition() - gAgentAvatarp->mHeadp->getWorldPosition(); -		} -		else -		{ -			delta_pos = chatter->getPositionAgent() - gAgent.getPositionAgent(); -		} -		delta_pos.normalize(); - -		gAgent.setControlFlags(AGENT_CONTROL_STOP); - -		changeCameraToThirdPerson(); - -		LLVector3 new_camera_pos = gAgentAvatarp->mHeadp->getWorldPosition(); -		LLVector3 left = delta_pos % LLVector3::z_axis; -		left.normalize(); -		LLVector3 up = left % delta_pos; -		up.normalize(); -		new_camera_pos -= delta_pos * 0.4f; -		new_camera_pos += left * 0.3f; -		new_camera_pos += up * 0.2f; - -		setFocusOnAvatar(false, false); - -		if (chatter_av->mHeadp) -		{ -			setFocusGlobal(gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), gAgent.getLastChatter()); -			mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); -		} -		else -		{ -			setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); -			mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); -		} -	} -	else -	{ -		delta_pos = chatter->getRenderPosition() - gAgent.getPositionAgent(); -		delta_pos.normalize(); - -		gAgent.setControlFlags(AGENT_CONTROL_STOP); - -		changeCameraToThirdPerson(); - -		LLVector3 new_camera_pos = gAgentAvatarp->mHeadp->getWorldPosition(); -		LLVector3 left = delta_pos % LLVector3::z_axis; -		left.normalize(); -		LLVector3 up = left % delta_pos; -		up.normalize(); -		new_camera_pos -= delta_pos * 0.4f; -		new_camera_pos += left * 0.3f; -		new_camera_pos += up * 0.2f; - -		setFocusOnAvatar(false, false); - -		setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); -		mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); -	} +    // Block if camera is animating or not in normal third person camera mode +    if (mCameraAnimating || !cameraThirdPerson()) +    { +        return; +    } + +    LLViewerObject *chatter = gObjectList.findObject(gAgent.getLastChatter()); +    if (!chatter) +    { +        return; +    } + +    LLVector3 delta_pos; +    if (chatter->isAvatar()) +    { +        LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; +        if (isAgentAvatarValid() && chatter_av->mHeadp) +        { +            delta_pos = chatter_av->mHeadp->getWorldPosition() - gAgentAvatarp->mHeadp->getWorldPosition(); +        } +        else +        { +            delta_pos = chatter->getPositionAgent() - gAgent.getPositionAgent(); +        } +        delta_pos.normalize(); + +        gAgent.setControlFlags(AGENT_CONTROL_STOP); + +        changeCameraToThirdPerson(); + +        LLVector3 new_camera_pos = gAgentAvatarp->mHeadp->getWorldPosition(); +        LLVector3 left = delta_pos % LLVector3::z_axis; +        left.normalize(); +        LLVector3 up = left % delta_pos; +        up.normalize(); +        new_camera_pos -= delta_pos * 0.4f; +        new_camera_pos += left * 0.3f; +        new_camera_pos += up * 0.2f; + +        setFocusOnAvatar(false, false); + +        if (chatter_av->mHeadp) +        { +            setFocusGlobal(gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), gAgent.getLastChatter()); +            mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); +        } +        else +        { +            setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); +            mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); +        } +    } +    else +    { +        delta_pos = chatter->getRenderPosition() - gAgent.getPositionAgent(); +        delta_pos.normalize(); + +        gAgent.setControlFlags(AGENT_CONTROL_STOP); + +        changeCameraToThirdPerson(); + +        LLVector3 new_camera_pos = gAgentAvatarp->mHeadp->getWorldPosition(); +        LLVector3 left = delta_pos % LLVector3::z_axis; +        left.normalize(); +        LLVector3 up = left % delta_pos; +        up.normalize(); +        new_camera_pos -= delta_pos * 0.4f; +        new_camera_pos += left * 0.3f; +        new_camera_pos += up * 0.2f; + +        setFocusOnAvatar(false, false); + +        setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); +        mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); +    }  }  bool LLAgentCamera::isfollowCamLocked()  { -	return mFollowCam.getPositionLocked(); +    return mFollowCam.getPositionLocked();  }  bool LLAgentCamera::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position)  { -	// disallow pointing at attachments and avatars -	if (object && (object->isAttachment() || object->isAvatar())) -	{ -		return false; -	} -	if (!mPointAt || mPointAt->isDead()) -	{ -		mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); -		mPointAt->setSourceObject(gAgentAvatarp); -	} -	return mPointAt->setPointAt(target_type, object, position); +    // disallow pointing at attachments and avatars +    if (object && (object->isAttachment() || object->isAvatar())) +    { +        return false; +    } +    if (!mPointAt || mPointAt->isDead()) +    { +        mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); +        mPointAt->setSourceObject(gAgentAvatarp); +    } +    return mPointAt->setPointAt(target_type, object, position);  }  void LLAgentCamera::rotateToInitSitRot()  { -	gAgent.rotate(~gAgent.getFrameAgent().getQuaternion()); -	gAgent.rotate(mInitSitRot); +    gAgent.rotate(~gAgent.getFrameAgent().getQuaternion()); +    gAgent.rotate(mInitSitRot);  }  void LLAgentCamera::resetCameraZoomFraction() -{  -	mCameraZoomFraction = INITIAL_ZOOM_FRACTION;  +{ +    mCameraZoomFraction = INITIAL_ZOOM_FRACTION;  }  ELookAtType LLAgentCamera::getLookAtType()  { -	if (mLookAt)  -	{ -		return mLookAt->getLookAtType(); -	} -	return LOOKAT_TARGET_NONE; +    if (mLookAt) +    { +        return mLookAt->getLookAtType(); +    } +    return LOOKAT_TARGET_NONE;  }  EPointAtType LLAgentCamera::getPointAtType() -{  -	if (mPointAt)  -	{ -		return mPointAt->getPointAtType(); -	} -	return POINTAT_TARGET_NONE; +{ +    if (mPointAt) +    { +        return mPointAt->getPointAtType(); +    } +    return POINTAT_TARGET_NONE;  }  void LLAgentCamera::clearGeneralKeys()  { -	mAtKey 				= 0; -	mWalkKey 			= 0; -	mLeftKey 			= 0; -	mUpKey 				= 0; -	mYawKey 			= 0.f; -	mPitchKey 			= 0.f; +    mAtKey              = 0; +    mWalkKey            = 0; +    mLeftKey            = 0; +    mUpKey              = 0; +    mYawKey             = 0.f; +    mPitchKey           = 0.f;  }  void LLAgentCamera::clearOrbitKeys()  { -	mOrbitLeftKey		= 0.f; -	mOrbitRightKey		= 0.f; -	mOrbitUpKey			= 0.f; -	mOrbitDownKey		= 0.f; -	mOrbitInKey			= 0.f; -	mOrbitOutKey		= 0.f; +    mOrbitLeftKey       = 0.f; +    mOrbitRightKey      = 0.f; +    mOrbitUpKey         = 0.f; +    mOrbitDownKey       = 0.f; +    mOrbitInKey         = 0.f; +    mOrbitOutKey        = 0.f;  }  void LLAgentCamera::clearPanKeys()  { -	mPanRightKey		= 0.f; -	mPanLeftKey			= 0.f; -	mPanUpKey			= 0.f; -	mPanDownKey			= 0.f; -	mPanInKey			= 0.f; -	mPanOutKey			= 0.f; +    mPanRightKey        = 0.f; +    mPanLeftKey         = 0.f; +    mPanUpKey           = 0.f; +    mPanDownKey         = 0.f; +    mPanInKey           = 0.f; +    mPanOutKey          = 0.f;  }  // static  S32 LLAgentCamera::directionToKey(S32 direction)  { -	if (direction > 0) return 1; -	if (direction < 0) return -1; -	return 0; +    if (direction > 0) return 1; +    if (direction < 0) return -1; +    return 0;  }  | 
