From ed6ecca2a45e52d9be1d91107b9643b5ecdfb8bf Mon Sep 17 00:00:00 2001 From: Leviathan Linden Date: Thu, 16 Nov 2023 13:53:37 -0800 Subject: avatar_motion-->GameControl translation and flycam --- indra/newview/llagent.cpp | 271 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 253 insertions(+), 18 deletions(-) (limited to 'indra/newview/llagent.cpp') 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 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]); +} + /********************************************************************************/ //----------------------------------------------------------------------------- -- cgit v1.2.3