From a35c3d4026e1be1a111ef8d85766a8338895f0c3 Mon Sep 17 00:00:00 2001 From: Viscerous Date: Sat, 5 Sep 2026 20:43:00 +0200 Subject: Fix moving linksets lagging when alt-cammed Camera focus calculations ran updateMove after the pipeline movement pass, advancing the focused drawable out of phase and leaking EARLY_MOVE into the next frame. This left the rest of the linkset, seated avatars, attachments, and nametags one frame behind. Remove the late camera-owned movement update so the camera only consumes the completed render state. Also use an existing drawable for getRenderPosition regardless of its movement generation: child drawables can legitimately remain at generation -1 after their transform is initialized, so generation is not a render-transform validity check. --- indra/newview/llagentcamera.cpp | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'indra/newview/llagentcamera.cpp') diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 56f1ac6b81..4ab03b34ee 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -1645,33 +1645,8 @@ LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal() { 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 + if (!mTrackFocusObject) { updateFocusOffset(); } -- cgit v1.3 From 7412083c86a2d47b70f93a6395792a67255bbf33 Mon Sep 17 00:00:00 2001 From: Viscerous Date: Mon, 14 Sep 2026 23:38:46 +0200 Subject: #6253 Smooth tracked cameras relative to their focus --- indra/newview/llagentcamera.cpp | 34 +++++++++++++++++++++++++++++----- indra/newview/llagentcamera.h | 3 +++ 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'indra/newview/llagentcamera.cpp') diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 4ab03b34ee..0fe5f622e3 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -150,6 +150,8 @@ LLAgentCamera::LLAgentCamera() : mSitCameraEnabled(false), mCameraSmoothingLastPositionGlobal(), mCameraSmoothingLastPositionAgent(), + mCameraSmoothingLastFocusGlobal(), + mCameraSmoothingLastFocusValid(false), mCameraSmoothingStop(false), mCameraUpVector(LLVector3::z_axis), // default is straight up @@ -1052,6 +1054,13 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters) } } +void LLAgentCamera::setCameraSmoothingLastPositionGlobal(const LLVector3d& camera_position_global) +{ + mCameraSmoothingLastPositionGlobal = camera_position_global; + mCameraSmoothingLastFocusGlobal = mFocusGlobal; + mCameraSmoothingLastFocusValid = true; +} + //----------------------------------------------------------------------------- // cameraPanIn() //----------------------------------------------------------------------------- @@ -1067,7 +1076,7 @@ void LLAgentCamera::cameraPanIn(F32 meters) // 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(); + setCameraSmoothingLastPositionGlobal(calcCameraPositionTargetGlobal()); } //----------------------------------------------------------------------------- @@ -1089,7 +1098,7 @@ void LLAgentCamera::cameraPanLeft(F32 meters) cameraZoomIn(1.f); updateFocusOffset(); // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); + setCameraSmoothingLastPositionGlobal(calcCameraPositionTargetGlobal()); } //----------------------------------------------------------------------------- @@ -1111,7 +1120,7 @@ void LLAgentCamera::cameraPanUp(F32 meters) cameraZoomIn(1.f); updateFocusOffset(); // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); + setCameraSmoothingLastPositionGlobal(calcCameraPositionTargetGlobal()); } void LLAgentCamera::resetCameraPan() @@ -1124,7 +1133,7 @@ void LLAgentCamera::resetCameraPan() cameraZoomIn(1.f); updateFocusOffset(); - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); + setCameraSmoothingLastPositionGlobal(calcCameraPositionTargetGlobal()); resetPanDiff(); } @@ -1466,6 +1475,21 @@ void LLAgentCamera::updateCamera() camera_pos_global = camera_pos_agent + agent_pos; } } + else if (mTrackFocusObject && mFocusObject.notNull()) + { + // Keep tracked-object translation exact and smooth only changes + // to the camera offset, as is done in avatar-relative mode. + LLVector3d camera_pos_focus = camera_pos_global - mFocusGlobal; + LLVector3d last_camera_pos_focus = + mCameraSmoothingLastPositionGlobal - mCameraSmoothingLastFocusGlobal; + LLVector3d delta = camera_pos_focus - last_camera_pos_focus; + if (mCameraSmoothingLastFocusValid && + delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) + { + camera_pos_focus = lerp(last_camera_pos_focus, camera_pos_focus, smoothing); + camera_pos_global = camera_pos_focus + mFocusGlobal; + } + } else { LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; @@ -1476,7 +1500,7 @@ void LLAgentCamera::updateCamera() } } - mCameraSmoothingLastPositionGlobal = camera_pos_global; + setCameraSmoothingLastPositionGlobal(camera_pos_global); mCameraSmoothingLastPositionAgent = camera_pos_agent; mCameraSmoothingStop = false; } diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index 384ed29245..4b5afb544e 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -149,6 +149,7 @@ public: const LLVector3& getCameraUpVector() const { return mCameraUpVector; } private: LLVector3 getAvatarRootPosition(); + void setCameraSmoothingLastPositionGlobal(const LLVector3d& camera_position_global); F32 mCurrentCameraDistance; // Current camera offset from avatar F32 mTargetCameraDistance; // Target camera offset from avatar @@ -159,6 +160,8 @@ private: LLVector3 mCameraVirtualPositionAgent; // Camera virtual position (target) before performing FOV zoom LLVector3d mCameraSmoothingLastPositionGlobal; LLVector3d mCameraSmoothingLastPositionAgent; + LLVector3d mCameraSmoothingLastFocusGlobal; + bool mCameraSmoothingLastFocusValid; bool mCameraSmoothingStop; LLVector3 mCameraLag; // Third person camera lag LLVector3 mCameraUpVector; // Camera's up direction in world coordinates (determines the 'roll' of the view) -- cgit v1.3