summaryrefslogtreecommitdiff
path: root/indra/newview/llagent.cpp
diff options
context:
space:
mode:
authorLeviathan Linden <leviathan@lindenlab.com>2023-11-16 13:53:37 -0800
committerAndrew Meadows <andrew.l.meadows@gmail.com>2024-10-03 09:01:12 -0700
commited6ecca2a45e52d9be1d91107b9643b5ecdfb8bf (patch)
tree2b9d241bf5cb0520de13ee10f729d2b58278ce33 /indra/newview/llagent.cpp
parent13221f67c465017f44ca46aeca23b0d820935825 (diff)
avatar_motion-->GameControl translation and flycam
Diffstat (limited to 'indra/newview/llagent.cpp')
-rw-r--r--indra/newview/llagent.cpp271
1 files changed, 253 insertions, 18 deletions
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index c8b0adbaf8..406734ab61 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -1463,7 +1463,7 @@ LLVector3 LLAgent::getReferenceUpVector()
}
-// Radians, positive is forward into ground
+// Radians, positive is downward toward ground
//-----------------------------------------------------------------------------
// pitch()
//-----------------------------------------------------------------------------
@@ -1477,27 +1477,23 @@ void LLAgent::pitch(F32 angle)
LLVector3 skyward = getReferenceUpVector();
+ // SL-19286 Avatar is upside down when viewed from below
+ // after left-clicking the mouse on the avatar and dragging down
+ //
+ // The issue is observed on angle below 10 degrees
+ const F32 look_down_limit = 179.f * DEG_TO_RAD;
+ const F32 look_up_limit = 10.f * DEG_TO_RAD;
+
+ F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward);
+
// clamp pitch to limits
- if (angle >= 0.f)
+ if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit))
{
- const F32 look_down_limit = 179.f * DEG_TO_RAD;
- F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward);
- if (angle_from_skyward + angle > look_down_limit)
- {
- angle = look_down_limit - angle_from_skyward;
- }
+ angle = look_down_limit - angle_from_skyward;
}
- else if (angle < 0.f)
+ else if ((angle < 0.f) && (angle_from_skyward + angle < look_up_limit))
{
- const F32 look_up_limit = 5.f * DEG_TO_RAD;
- 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 angle_from_skyward = angle_between(look_dir, skyward);
- if (angle_from_skyward + angle < look_up_limit)
- {
- angle = look_up_limit - angle_from_skyward;
- }
+ angle = look_up_limit - angle_from_skyward;
}
if (fabs(angle) > 1e-4)
@@ -4986,6 +4982,245 @@ void LLAgent::renderAutoPilotTarget()
}
}
+void LLAgent::setExternalActionFlags(U32 outer_flags)
+{
+ if (LLGameControl::willControlAvatar())
+ {
+ // save these flags for later, for when we're ready
+ // to actually send an AgentUpdate packet
+ mExternalActionFlags = outer_flags;
+ mbFlagsDirty = TRUE;
+ }
+}
+
+static U64 g_lastUpdateTime { 0 };
+static F32 g_deltaTime { 0.0f };
+static S32 g_lastUpdateFrame { 0 };
+static S32 g_deltaFrame { 0 };
+
+void LLAgent::applyExternalActionFlags()
+{
+ if (! LLGameControl::willControlAvatar())
+ {
+ return;
+ }
+
+ // HACK: AGENT_CONTROL_NUDGE_AT_NEG is used to toggle Flycam
+ if ((mExternalActionFlags & AGENT_CONTROL_NUDGE_AT_NEG) > 0)
+ {
+ if (mToggleFlycam)
+ {
+ mUsingFlycam = !mUsingFlycam;
+ if (mUsingFlycam)
+ {
+ // copy main camera transform to flycam
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ mFlycam.setTransform(camera->getOrigin(), camera->getQuaternion());
+ mLastFlycamUpdate = LLFrameTimer::getTotalTime();
+ }
+ /*
+ else
+ {
+ // do we need to reset main camera?
+ }
+ */
+ }
+ mToggleFlycam = false;
+ }
+ else
+ {
+ mToggleFlycam = true;
+ }
+
+ // measure delta time and frame
+ // Note: it is possible for the deltas to be very large
+ // and it is the duty of the code that uses them to clamp as necessary
+ U64 now = LLFrameTimer::getTotalTime();
+ g_deltaTime = F32(now - g_lastUpdateTime) / (F32)(USEC_PER_SEC);
+ g_lastUpdateTime = now;
+
+ S32 frame_count = LLFrameTimer::getFrameCount();
+ g_deltaFrame = frame_count - g_lastUpdateFrame;
+ g_lastUpdateFrame = frame_count;
+
+ if (mUsingFlycam)
+ {
+ updateFlycam();
+ return;
+ }
+
+ S32 direction = (S32)(mExternalActionFlags & AGENT_CONTROL_AT_POS)
+ - (S32)((mExternalActionFlags & AGENT_CONTROL_AT_NEG) >> 1);
+ if (direction != 0)
+ {
+ moveAt(direction);
+ }
+
+ static U32 last_non_fly_frame = 0;
+ static U64 last_non_fly_time = 0;
+ direction = (S32)(mExternalActionFlags & AGENT_CONTROL_UP_POS)
+ - (S32)((mExternalActionFlags & AGENT_CONTROL_UP_NEG) >> 1);
+ if (direction != 0)
+ {
+ // HACK: this auto-fly logic based on original code still extant in llviewerinput.cpp::agent_jump()
+ // but has been cleaned up.
+ // TODO?: DRY this logic
+ if (direction > 0)
+ {
+ if (!getFlying()
+ && !upGrabbed()
+ && gSavedSettings.getBOOL("AutomaticFly"))
+ {
+ constexpr F32 FLY_TIME = 0.5f;
+ constexpr U32 FLY_FRAMES = 4;
+ F32 delta_time = (F32)(now - last_non_fly_time) / (F32)(USEC_PER_SEC);
+ U32 delta_frames = frame_count - last_non_fly_frame;
+ if( delta_time > FLY_TIME
+ && delta_frames > FLY_FRAMES)
+ {
+ setFlying(TRUE);
+ }
+ }
+ }
+ else
+ {
+ last_non_fly_frame = frame_count;
+ last_non_fly_time = now;
+ }
+
+ moveUp(direction);
+ }
+ else if (!getFlying())
+ {
+ last_non_fly_frame = frame_count;
+ last_non_fly_time = now;
+ }
+
+ direction = (S32)(mExternalActionFlags & AGENT_CONTROL_LEFT_POS)
+ - (S32)((mExternalActionFlags & AGENT_CONTROL_LEFT_NEG) >> 1);
+ if (direction != 0)
+ {
+ moveLeft(direction);
+ }
+
+ direction = (S32)(mExternalActionFlags & AGENT_CONTROL_YAW_POS)
+ - (S32)((mExternalActionFlags & AGENT_CONTROL_YAW_NEG) >> 1);
+ if (direction != 0)
+ {
+ F32 sign = (direction < 0 ? -1.0f : 1.0f);
+ // HACK: hard-code 3.0 seconds for YawRate measure. It is simpler,
+ // and the missing variable yaw rate is unnoticeable.
+ moveYaw(sign * LLFloaterMove::getYawRate(3.0f));
+ }
+
+ {
+ F32 pitch = ((mExternalActionFlags & AGENT_CONTROL_PITCH_POS) > 0 ? 1.0f : 0.0f)
+ - ((mExternalActionFlags & AGENT_CONTROL_PITCH_NEG) > 0 ? 1.0f : 0.0f);
+ movePitch(pitch);
+ }
+
+ if ((mExternalActionFlags & AGENT_CONTROL_FLY) > 0)
+ {
+ if (mToggleFly)
+ {
+ setFlying(!getFlying());
+ }
+ mToggleFly = false;
+ }
+ else
+ {
+ mToggleFly = true;
+ }
+
+ if (mExternalActionFlags & AGENT_CONTROL_STOP)
+ {
+ setControlFlags(AGENT_CONTROL_STOP);
+ }
+
+ if ((mExternalActionFlags & AGENT_CONTROL_SIT_ON_GROUND) > 0)
+ {
+ if (mToggleSit)
+ {
+ if (isSitting())
+ {
+ standUp();
+ }
+ else
+ {
+ sitDown();
+ }
+ }
+ mToggleSit = false;
+ }
+ else
+ {
+ mToggleSit = true;
+ }
+
+ // HACK: AGENT_CONTROL_NUDGE_AT_POS is used to toggle running
+ if ((mExternalActionFlags & AGENT_CONTROL_NUDGE_AT_POS) > 0)
+ {
+ if (mToggleRun)
+ {
+ if (getRunning())
+ {
+ clearRunning();
+ sendWalkRun(false);
+ }
+ else
+ {
+ setRunning();
+ sendWalkRun(true);
+ }
+ }
+ mToggleRun = false;
+ }
+ else
+ {
+ mToggleRun = true;
+ }
+}
+
+void LLAgent::updateFlycam()
+{
+ // Note: no matter how camera_inputs are mapped to the controller
+ // they arrive in the following order:
+ enum FLYCAM_AXIS {
+ FLYCAM_FORWARD = 0,
+ FLYCAM_LEFT,
+ FLYCAM_UP,
+ FLYCAM_PITCH,
+ FLYCAM_YAW,
+ FLYCAM_ZOOM
+ };
+ std::vector<F32> camera_inputs;
+ LLGameControl::getCameraInputs(camera_inputs);
+
+ LLVector3 linear_velocity(
+ camera_inputs[FLYCAM_FORWARD],
+ camera_inputs[FLYCAM_LEFT],
+ camera_inputs[FLYCAM_UP]);
+ constexpr F32 MAX_FLYCAM_SPEED = 10.0f;
+ mFlycam.setLinearVelocity(MAX_FLYCAM_SPEED * linear_velocity);
+
+ mFlycam.setPitchRate(camera_inputs[FLYCAM_PITCH]);
+ mFlycam.setYawRate(camera_inputs[FLYCAM_PITCH]);
+
+ mFlycam.integrate(g_deltaTime);
+
+ LLVector3 pos;
+ LLQuaternion rot;
+ mFlycam.getTransform(pos, rot);
+
+ // copy flycam transform to main camera
+ LLMatrix3 mat(rot);
+ //LLViewerCamera::getInstance()->setView(sFlycamZoom);
+ LLViewerCamera::getInstance()->setOrigin(pos);
+ LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]);
+ LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
+ LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);
+}
+
/********************************************************************************/
//-----------------------------------------------------------------------------