summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gavriliuk <alexandrgproductengine@lindenlab.com>2024-06-06 12:10:10 +0200
committerGuru <alexandrgproductengine@lindenlab.com>2024-06-15 00:18:49 +0200
commit3fc8d4b232a60931849e674b48273eb07157b4e1 (patch)
tree4c1e7bd1c348d43c2597f97fca3b3c2a8242ecc2
parentfece367b9b6b351d112f9036ce445c52397c9b03 (diff)
#1611 Regression in anti-flipping mechanism for mouselook camera
-rw-r--r--indra/newview/llagent.cpp98
-rw-r--r--indra/newview/llagentcamera.cpp18
-rw-r--r--indra/newview/llagentcamera.h12
-rw-r--r--indra/newview/llviewercamera.cpp34
-rw-r--r--indra/newview/llviewercamera.h24
5 files changed, 99 insertions, 87 deletions
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index c3643dcc62..25a3690162 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -1459,69 +1459,65 @@ LLVector3 LLAgent::getReferenceUpVector()
//-----------------------------------------------------------------------------
void LLAgent::pitch(F32 angle)
{
- if (fabs(angle) <= 1e-4)
- return;
-
- LLCoordFrame newCoordFrame(mFrameAgent);
- newCoordFrame.pitch(angle);
-
- // don't let user pitch if rotated 180 degree around the vertical axis
- if ((newCoordFrame.getXAxis()[VX] * mFrameAgent.getXAxis()[VX] < 0) &&
- (newCoordFrame.getXAxis()[VY] * mFrameAgent.getXAxis()[VY] < 0))
- return;
-
- // don't let user pitch if pointed almost all the way down or up
- LLVector3 skyward = getReferenceUpVector();
+ if (gAgentCamera.getCameraMode() == CAMERA_MODE_THIRD_PERSON ||
+ gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+ {
+ // Backup the current orientation
+ LLCoordFrame saved_frame_agent(mFrameAgent);
- // A dot B = mag(A) * mag(B) * cos(angle between A and B)
- // so... cos(angle between A and B) = A dot B / mag(A) / mag(B)
- // = A dot B for unit vectors
- F32 agent_camera_angle_from_skyward = acos(newCoordFrame.getAtAxis() * skyward) * RAD_TO_DEG;
+ // Optimistic rotation up/down (vertical angle can reach and exceed 0 or 180)
+ mFrameAgent.pitch(angle);
- F32 min_angle = 1;
- F32 max_angle = 179;
- bool check_viewer_camera = false;
+ // Cosine of the angle between current agent At and Up directions
+ F32 agent_at_to_up_now_cos = saved_frame_agent.mXAxis * gAgentCamera.getCameraUpVector();
+ bool pitch_away_from_horizont = (angle < 0) ^ (agent_at_to_up_now_cos < 0);
+ // We always allow to pitch in direction to horizont (from zenith or from nadir)
+ if (!pitch_away_from_horizont)
+ return;
- if (gAgentCamera.getCameraMode() == CAMERA_MODE_THIRD_PERSON)
- {
- // These values of min_angle and max_angle are obtained purely empirically
- if (gAgentCamera.getCameraPreset() == CAMERA_PRESET_REAR_VIEW)
+ // Current angle between agent At and Up directions
+ F32 agent_at_to_up_now = acos(agent_at_to_up_now_cos);
+ // Requested angle between agent At and Up directions
+ F32 agent_at_to_up_new = agent_at_to_up_now + angle;
+ F32 agent_at_to_up_new_sin = sin(agent_at_to_up_new);
+ // Overpitched? Then rollback
+ if (agent_at_to_up_new_sin < 1e-4)
{
- min_angle = 10;
- check_viewer_camera = true;
+ mFrameAgent = saved_frame_agent;
+ return;
}
- else if (gAgentCamera.getCameraPreset() == CAMERA_PRESET_GROUP_VIEW)
+
+ if (gAgentCamera.getCameraMode() == CAMERA_MODE_THIRD_PERSON ||
+ (isAgentAvatarValid() && gAgentAvatarp->getParent()))
{
- min_angle = 10;
- max_angle = 170;
- check_viewer_camera = true;
+ // Camera sight relative to agent frame (focus - offset)
+ LLVector3 camera_offset(gAgentCamera.getCameraOffsetInitial());
+ LLVector3 camera_focus(gAgentCamera.getFocusOffsetInitial());
+ LLVector3 camera_sight(camera_focus - camera_offset);
+ // 2D projection of the camera sight to the XZ plane
+ LLVector2 camera_sight_2d_vert(1, camera_sight[VZ]);
+ camera_sight_2d_vert.normalize();
+ // Cosine of the 2D angle between initial camera At and X axis (in the XZ plane)
+ F32 camera_sight_to_at_2d_vert_cos = camera_sight_2d_vert * LLVector2(LLVector3::x_axis);
+ F32 camera_sight_to_at_2d_vert = acos(camera_sight_to_at_2d_vert_cos);
+ // Requested angle between camera At and Up directions
+ F32 camera_at_to_up_new = agent_at_to_up_new - camera_sight_to_at_2d_vert;
+ F32 camera_at_to_up_new_sin = sin(camera_at_to_up_new);
+ // Overpitched? Then rollback
+ if (camera_at_to_up_new_sin < 1e-4)
+ {
+ mFrameAgent = saved_frame_agent;
+ return;
+ }
}
}
- else if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
- {
- min_angle = 0.1;
- max_angle = 179.9;
- }
-
- if ((angle < 0 && agent_camera_angle_from_skyward < min_angle) ||
- (angle > 0 && agent_camera_angle_from_skyward > max_angle))
- return;
-
- if (check_viewer_camera)
+ else
{
- const LLVector3& viewer_camera_pos = LLViewerCamera::getInstance()->getOrigin();
- LLVector3 agent_focus_pos = getPosAgentFromGlobal(gAgentCamera.calcFocusPositionTargetGlobal());
- LLVector3 look_dir = agent_focus_pos - viewer_camera_pos;
- F32 viewer_camera_angle_from_skyward = angle_between(look_dir, skyward) * RAD_TO_DEG;
- if ((angle < 0 && viewer_camera_angle_from_skyward < min_angle) ||
- (angle > 0 && viewer_camera_angle_from_skyward > max_angle))
- return;
+ // No limitations in other modes
+ mFrameAgent.pitch(angle);
}
-
- mFrameAgent = newCoordFrame;
}
-
//-----------------------------------------------------------------------------
// roll()
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 1912d9d1d5..2045f8d7a0 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -1463,13 +1463,12 @@ void LLAgentCamera::updateCamera()
// LL_INFOS() << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << LL_ENDL;
LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal);
+ LLVector3 position_agent = gAgent.getPosAgentFromGlobal(camera_pos_global);
- mCameraPositionAgent = gAgent.getPosAgentFromGlobal(camera_pos_global);
+ // Try to move the camera
- // Move the camera
-
- LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent);
- //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent);
+ if (!LLViewerCamera::getInstance()->updateCameraLocation(position_agent, mCameraUpVector, focus_agent))
+ return;
// Change FOV
LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor));
@@ -1477,7 +1476,7 @@ void LLAgentCamera::updateCamera()
// follow camera when in customize mode
if (cameraCustomizeAvatar())
{
- setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent);
+ setLookAt(LOOKAT_TARGET_FOCUS, NULL, position_agent);
}
// update the travel distance stat
@@ -1496,7 +1495,7 @@ void LLAgentCamera::updateCamera()
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;
+ LLVector3 diff = position_agent - head_pos;
diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation();
LLJoint* torso_joint = gAgentAvatarp->mTorsop;
@@ -2259,7 +2258,7 @@ void LLAgentCamera::changeCameraToFollow(BOOL animate)
return;
}
- if(mCameraMode != CAMERA_MODE_FOLLOW)
+ if (mCameraMode != CAMERA_MODE_FOLLOW)
{
if (mCameraMode == CAMERA_MODE_MOUSELOOK)
{
@@ -2271,7 +2270,8 @@ void LLAgentCamera::changeCameraToFollow(BOOL animate)
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);
+ const LLViewerCamera& camera = LLViewerCamera::instance();
+ mFollowCam.reset(camera.getOrigin(), camera.getPointOfInterest(), LLVector3::z_axis);
if (gBasicToolset)
{
diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h
index a88d425724..a2c8a6891a 100644
--- a/indra/newview/llagentcamera.h
+++ b/indra/newview/llagentcamera.h
@@ -139,13 +139,14 @@ private:
//--------------------------------------------------------------------
public:
LLVector3d getCameraPositionGlobal() const;
- const LLVector3 &getCameraPositionAgent() const;
+ const LLVector3& getCameraPositionAgent() const;
LLVector3d calcCameraPositionTargetGlobal(BOOL *hit_limit = NULL); // Calculate the camera position target
F32 getCameraMinOffGround(); // Minimum height off ground for this mode, meters
void setCameraCollidePlane(const LLVector4 &plane) { mCameraCollidePlane = plane; }
BOOL calcCameraMinDistance(F32 &obj_min_distance);
- F32 getCurrentCameraBuildOffset() { return (F32)mCameraFocusOffset.length(); }
+ F32 getCurrentCameraBuildOffset() const { return (F32)mCameraFocusOffset.length(); }
void clearCameraLag() { mCameraLag.clearVec(); }
+ const LLVector3& getCameraUpVector() const { return mCameraUpVector; }
private:
LLVector3 getAvatarRootPosition();
@@ -155,7 +156,6 @@ private:
F32 mCameraCurrentFOVZoomFactor; // Interpolated fov zoom
LLVector4 mCameraCollidePlane; // Colliding plane for camera
F32 mCameraZoomFraction; // Mousewheel driven fraction of zoom
- LLVector3 mCameraPositionAgent; // Camera position in agent coordinates
LLVector3 mCameraVirtualPositionAgent; // Camera virtual position (target) before performing FOV zoom
LLVector3d mCameraSmoothingLastPositionGlobal;
LLVector3d mCameraSmoothingLastPositionAgent;
@@ -189,8 +189,8 @@ private:
// Animation
//--------------------------------------------------------------------
public:
- void setCameraAnimating(BOOL b) { mCameraAnimating = b; }
- BOOL getCameraAnimating() { return mCameraAnimating; }
+ void setCameraAnimating(BOOL b) { mCameraAnimating = b; }
+ BOOL getCameraAnimating() const { return mCameraAnimating; }
void setAnimationDuration(F32 seconds);
void startCameraAnimation();
void stopCameraAnimation();
@@ -279,7 +279,7 @@ public:
F32 getAgentHUDTargetZoom();
void resetCameraZoomFraction();
- F32 getCurrentCameraZoomFraction() { return mCameraZoomFraction; }
+ F32 getCurrentCameraZoomFraction() const { return mCameraZoomFraction; }
//--------------------------------------------------------------------
// Pan
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index bda1a20fdd..836bcad784 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -103,18 +103,16 @@ LLViewerCamera::~LLViewerCamera()
mCameraAngleChangedSignal.disconnect();
}
-void LLViewerCamera::updateCameraLocation(const LLVector3 &center, const LLVector3 &up_direction, const LLVector3 &point_of_interest)
+bool LLViewerCamera::updateCameraLocation(const LLVector3 &center, const LLVector3 &up_direction, const LLVector3 &point_of_interest)
{
// do not update if avatar didn't move
if (!LLViewerJoystick::getInstance()->getCameraNeedsUpdate())
{
- return;
+ return true;
}
- LLVector3 last_position;
- LLVector3 last_axis;
- last_position = getOrigin();
- last_axis = getAtAxis();
+ LLVector3 last_position = getOrigin();
+ LLVector3 last_axis = getAtAxis();
mLastPointOfInterest = point_of_interest;
@@ -139,10 +137,26 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center, const LLVecto
}
}
- setOriginAndLookAt(origin, up_direction, point_of_interest);
+ LLVector3 at(point_of_interest - origin);
+ at.normalize();
+ if (at.isNull() || !at.isFinite())
+ return false;
- mVelocityDir = origin - last_position ;
- F32 dpos = mVelocityDir.normVec() ;
+ LLVector3 left(up_direction % at);
+ left.normalize();
+ if (left.isNull() || !left.isFinite())
+ return false;
+
+ LLVector3 up = at % left;
+ up.normalize();
+ if (up.isNull() || !up.isFinite())
+ return false;
+
+ setOrigin(origin);
+ setAxes(at, left, up);
+
+ mVelocityDir = origin - last_position;
+ F32 dpos = mVelocityDir.normVec();
LLQuaternion rotation;
rotation.shortestArc(last_axis, getAtAxis());
@@ -161,6 +175,8 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center, const LLVecto
mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5));
// update screen pixel area
mScreenPixelArea =(S32)((F32)getViewHeightInPixels() * ((F32)getViewHeightInPixels() * getAspect()));
+
+ return true;
}
const LLMatrix4 &LLViewerCamera::getProjection() const
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 8ac9101165..ce006b49cf 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -61,7 +61,7 @@ public:
static eCameraID sCurCameraID;
- void updateCameraLocation(const LLVector3 &center,
+ bool updateCameraLocation(const LLVector3 &center,
const LLVector3 &up_direction,
const LLVector3 &point_of_interest);
@@ -77,12 +77,12 @@ public:
BOOL projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp = TRUE) const;
BOOL projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const;
- LLVector3 getVelocityDir() const {return mVelocityDir;}
- static LLTrace::CountStatHandle<>* getVelocityStat() {return &sVelocityStat; }
- static LLTrace::CountStatHandle<>* getAngularVelocityStat() {return &sAngularVelocityStat; }
- F32 getCosHalfFov() {return mCosHalfCameraFOV;}
- F32 getAverageSpeed() {return mAverageSpeed ;}
- F32 getAverageAngularSpeed() {return mAverageAngularSpeed;}
+ LLVector3 getVelocityDir() const { return mVelocityDir; }
+ static LLTrace::CountStatHandle<>* getVelocityStat() { return &sVelocityStat; }
+ static LLTrace::CountStatHandle<>* getAngularVelocityStat() { return &sAngularVelocityStat; }
+ F32 getCosHalfFov() const { return mCosHalfCameraFOV; }
+ F32 getAverageSpeed() const { return mAverageSpeed; }
+ F32 getAverageAngularSpeed() const { return mAverageAngularSpeed; }
void getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right);
LLVector3 roundToPixel(const LLVector3 &pos_agent);
@@ -90,21 +90,21 @@ public:
// Sets the current matrix
/* virtual */ void setView(F32 vertical_fov_rads); // NOTE: broadcasts to simulator
void setViewNoBroadcast(F32 vertical_fov_rads); // set FOV without broadcasting to simulator (for temporary local cameras)
- void setDefaultFOV(F32 fov) ;
- F32 getDefaultFOV() { return mCameraFOVDefault; }
+ void setDefaultFOV(F32 fov);
+ F32 getDefaultFOV() const { return mCameraFOVDefault; }
BOOL isDefaultFOVChanged();
BOOL cameraUnderWater() const;
BOOL areVertsVisible(LLViewerObject* volumep, BOOL all_verts);
- const LLVector3 &getPointOfInterest() { return mLastPointOfInterest; }
+ const LLVector3& getPointOfInterest() const { return mLastPointOfInterest; }
F32 getPixelMeterRatio() const { return mPixelMeterRatio; }
S32 getScreenPixelArea() const { return mScreenPixelArea; }
void setZoomParameters(F32 factor, S16 subregion) { mZoomFactor = factor; mZoomSubregion = subregion; }
- F32 getZoomFactor() { return mZoomFactor; }
- S16 getZoomSubRegion() { return mZoomSubregion; }
+ F32 getZoomFactor() const { return mZoomFactor; }
+ S16 getZoomSubRegion() const { return mZoomSubregion; }
protected:
void calcProjection(const F32 far_distance) const;