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 | |
parent | fece367b9b6b351d112f9036ce445c52397c9b03 (diff) |
#1611 Regression in anti-flipping mechanism for mouselook camera
-rw-r--r-- | indra/newview/llagent.cpp | 98 | ||||
-rw-r--r-- | indra/newview/llagentcamera.cpp | 18 | ||||
-rw-r--r-- | indra/newview/llagentcamera.h | 12 | ||||
-rw-r--r-- | indra/newview/llviewercamera.cpp | 34 | ||||
-rw-r--r-- | indra/newview/llviewercamera.h | 24 |
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 ¢er, const LLVector3 &up_direction, const LLVector3 &point_of_interest) +bool LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, 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 ¢er, 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 ¢er, 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 ¢er, + bool updateCameraLocation(const LLVector3 ¢er, 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; |