diff options
| author | Alexander Gavriliuk <alexandrgproductengine@lindenlab.com> | 2024-06-06 12:10:10 +0200 |
|---|---|---|
| committer | Guru <alexandrgproductengine@lindenlab.com> | 2024-06-15 00:18:49 +0200 |
| commit | 3fc8d4b232a60931849e674b48273eb07157b4e1 (patch) | |
| tree | 4c1e7bd1c348d43c2597f97fca3b3c2a8242ecc2 /indra/newview/llagent.cpp | |
| parent | fece367b9b6b351d112f9036ce445c52397c9b03 (diff) | |
#1611 Regression in anti-flipping mechanism for mouselook camera
Diffstat (limited to 'indra/newview/llagent.cpp')
| -rw-r--r-- | indra/newview/llagent.cpp | 98 |
1 files changed, 47 insertions, 51 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() //----------------------------------------------------------------------------- |
