Started implementing "first person controls".

This commit is contained in:
Patrick 2024-09-25 15:47:17 +02:00
parent 161dfc95bf
commit 9a5638670a
6 changed files with 58 additions and 44 deletions

View File

@ -14,8 +14,8 @@ namespace sdl_gpu_test
{
namespace
{
inline constexpr float Y_POS_MIN = -10.f;
inline constexpr float Y_POS_MAX = 10.f;
inline constexpr float PITCH_MIN = -89.f;
inline constexpr float PITCH_MAX = 89.f;
inline constexpr Uint16 AXIS_DEADZONE = 5000;
}
@ -67,6 +67,8 @@ void ThreeDSceneApp::init(const AppInitArgs& args)
{
mButton->setText("Thanks!");
});
mWindow.setRelativeMouseMode(true);
}
void ThreeDSceneApp::update(const AppUpdateArgs& args)
@ -74,7 +76,7 @@ void ThreeDSceneApp::update(const AppUpdateArgs& args)
Application::update(args);
processInput(args);
mLabel->setText(std::format("Rotation: {}{}\n$rUI vertices: $f8c{}", mRotation > 180.f ? "$8cf": "$fff" , mRotation, mUIRenderer.getNumVertices()));
mLabel->setText(std::format("Pitch: {:.1f}\nYaw: {:.1f}", mPitch, mYaw));
mWidgetTree.revalidateWidgets();
// begin rendering
@ -97,6 +99,11 @@ void ThreeDSceneApp::update(const AppUpdateArgs& args)
// render the scene
mSceneRenderer.render({
.camera = {
.position = mPosition,
.pitch = glm::radians(mPitch),
.yaw = glm::radians(mYaw)
},
.cmdBuffer = &cmdBuffer,
.targetTexture = &swapchainTexture,
.depthTexture = &mDepthBuffer,
@ -134,11 +141,8 @@ void ThreeDSceneApp::handleMouseMotionEvent(const sdlpp::MouseMotionEvent& event
{
mWidgetTree.notifyMouseMoved(event);
if (event.state.left)
{
mRotation += 0.5f * event.xrel;
mYPos = std::clamp(mYPos + 0.02f * event.yrel, Y_POS_MIN, Y_POS_MAX);
}
mYaw -= 0.5f * event.xrel;
mPitch -= 0.5f * event.yrel;
}
void ThreeDSceneApp::handleMouseButtonEvent(const sdlpp::MouseButtonEvent& event)
@ -148,39 +152,30 @@ void ThreeDSceneApp::handleMouseButtonEvent(const sdlpp::MouseButtonEvent& event
void ThreeDSceneApp::processInput(const AppUpdateArgs& args)
{
const std::span<const SDL_bool> keystates = sdlpp::getKeyboardState();
if (keystates[SDL_SCANCODE_LEFT])
{
mRotation -= 40.f * args.tickSeconds;
}
if (keystates[SDL_SCANCODE_RIGHT])
{
mRotation += 40.f * args.tickSeconds;
}
if (keystates[SDL_SCANCODE_UP])
{
mYPos -= 2.f * args.tickSeconds;
}
if (keystates[SDL_SCANCODE_DOWN])
{
mYPos += 2.f * args.tickSeconds;
}
if (mGamepad)
{
const Sint16 xAxis = mGamepad.getAxis(sdlpp::GamepadAxis::LEFTX);
if (std::abs(xAxis) > AXIS_DEADZONE)
Sint16 axisValue = mGamepad.getAxis(sdlpp::GamepadAxis::RIGHTX);
if (std::abs(axisValue) > AXIS_DEADZONE)
{
mRotation += 0.001f * args.tickSeconds * static_cast<float>(xAxis);
mYaw -= 0.005f * args.tickSeconds * static_cast<float>(axisValue);
}
const Sint16 yAxis = mGamepad.getAxis(sdlpp::GamepadAxis::LEFTY);
if (std::abs(yAxis) > AXIS_DEADZONE)
axisValue = mGamepad.getAxis(sdlpp::GamepadAxis::RIGHTY);
if (std::abs(axisValue) > AXIS_DEADZONE)
{
mYPos += 0.0002f * args.tickSeconds * yAxis;
mPitch -= 0.005f * args.tickSeconds * static_cast<float>(axisValue);
}
axisValue = mGamepad.getAxis(sdlpp::GamepadAxis::LEFTY);
if (std::abs(axisValue) > AXIS_DEADZONE)
{
mPosition.x += 0.0005f * args.tickSeconds * std::sin(mYaw) * static_cast<float>(axisValue);
mPosition.z += 0.0005f * args.tickSeconds * std::cos(mYaw) * static_cast<float>(axisValue);
}
}
while (mRotation >= 360.f) { mRotation -= 360.f; }
while (mRotation < 0.f) { mRotation += 360.f; }
mYPos = std::clamp(mYPos, Y_POS_MIN, Y_POS_MAX);
while (mYaw >= 360.f) { mYaw -= 360.f; }
while (mYaw < 0.f) { mYaw += 360.f; }
mPitch = std::clamp(mPitch, PITCH_MIN, PITCH_MAX);
}
}

View File

@ -32,8 +32,9 @@ private:
sdlpp::Gamepad mGamepad;
Uint32 mLastSwapchainWidth = 1280;
Uint32 mLastSwapchainHeight = 720;
float mRotation = 0.f;
float mYPos = 1.5f;
glm::vec3 mPosition = {0.f, 0.f, 5.f};
float mYaw = 0.f;
float mPitch = 0.f;
public:
void init(const AppInitArgs& args) override;
void update(const AppUpdateArgs& args) override;

View File

@ -6,6 +6,7 @@
#include <glm/vec2.hpp>
#include <glm/vec4.hpp>
#include "../application.hpp"
#include "../sdlpp/gpu.hpp"
#include "../util/font_map.hpp"

View File

@ -3,6 +3,7 @@
#include <glm/mat4x4.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/euler_angles.hpp>
#include "./mesh.hpp"
#include "../util/bitmap.hpp"
@ -75,19 +76,18 @@ std::shared_ptr<SceneTexture> SceneRenderer::getTexture(const std::string& resou
void SceneRenderer::render(const SceneRendererRenderArgs& args)
{
// just temporary
const float mYPos = 1.5f;
const float mRotation = 0.f;
VertexShaderParameters vertexShaderParameters = {
.worldToView = glm::lookAt(glm::vec3(2.f, mYPos, 2.f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 1.f, 0.f))
* glm::rotate(glm::mat4(1.f), glm::radians(mRotation), glm::vec3(0.f, 1.f, 0.f)),
// note that we are transforming the world, but are passed the camera transform, so invert it
.worldToView = glm::translate(
glm::yawPitchRoll(-args.camera.yaw, -args.camera.pitch, -args.camera.roll),
-args.camera.position
),
.viewToClip = glm::perspectiveFov(
/* fov = */ glm::radians(90.f),
/* width = */ static_cast<float>(args.targetTextureWidth),
/* height = */ static_cast<float>(args.targetTextureHeight),
/* zNear = */ 0.1f,
/* zFar = */ 100.f
/* zNear = */ args.camera.zNear,
/* zFar = */ args.camera.zFar
)
};

View File

@ -26,8 +26,20 @@ struct SceneTexture
sdlpp::GPUTexture texture;
};
struct CameraOptions
{
glm::vec3 position = glm::vec3(0.f);
float roll = 0.f;
float pitch = 0.f;
float yaw = 0.f;
float fovh = glm::radians(90.f);
float zNear = 0.f;
float zFar = 100.f;
};
struct SceneRendererRenderArgs
{
CameraOptions camera;
const sdlpp::GPUCommandBuffer* cmdBuffer;
const sdlpp::GPUTexture* targetTexture;
const sdlpp::GPUTexture* depthTexture;

View File

@ -90,6 +90,11 @@ public:
mHandle = nullptr;
}
}
bool setRelativeMouseMode(bool enabled)
{
return SDL_SetWindowRelativeMouseMode(mHandle, enabled);
}
};
} // namespace sdlpp