From 23d7cf03f6130e848279aba262f400b090adb46f Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Fri, 29 Oct 2021 13:08:44 +0200 Subject: [PATCH] Still buggy but somewhat workable FPS control. --- src/render_utils.c | 55 ++++++++++++++++++++++++++++----------- src/render_utils.h | 3 +++ src/vissim.cc | 65 ++++++++++++++++++++++++++++++++-------------- 3 files changed, 88 insertions(+), 35 deletions(-) diff --git a/src/render_utils.c b/src/render_utils.c index 05333a8..806a7af 100644 --- a/src/render_utils.c +++ b/src/render_utils.c @@ -11,16 +11,34 @@ inline void CameraState_Init(CameraState* camera_state) { }; // clang-format on + camera_state->forward[0] = 0.f; + camera_state->forward[1] = 0.f; + camera_state->forward[2] = -1.f; + + camera_state->right[0] = 1.f; + camera_state->right[1] = 0.f; + camera_state->right[2] = 0.f; + + camera_state->up[0] = 0.f; + camera_state->up[1] = 1.f; + camera_state->up[2] = 0.f; + memcpy(&camera_state->mtxView, &mtx_identity, sizeof(camera_state->mtxView)); + CameraState_CalcFromMatrix(camera_state, &camera_state->mtxView); } void CameraState_CalcFromMatrix(CameraState* camera_state, simd4x4f* mtx) { - float right[3] = {mtx->x[0], mtx->y[0], mtx->z[0]}; - float up[3] = {mtx->x[1], mtx->y[1], mtx->z[1]}; - float forward[3] = {-mtx->x[2], -mtx->y[2], -mtx->z[2]}; - camera_state->heading = atan2(forward[2], -forward[0]); - camera_state->pitch = asin(-forward[1]); + camera_state->forward[0] = mtx->x[2]; + camera_state->forward[1] = mtx->y[2]; + camera_state->forward[2] = mtx->z[2]; + + camera_state->right[0] = mtx->x[0]; + camera_state->right[1] = mtx->y[0]; + camera_state->right[2] = mtx->z[0]; + + camera_state->heading = atan2(-camera_state->forward[2], camera_state->forward[0]); + camera_state->pitch = asin(camera_state->forward[1]); simd4x4f rot_mat = *mtx; rot_mat.w = simd4f_create(0.f, 0.f, 0.f, 1.f); @@ -33,7 +51,6 @@ void CameraState_CalcFromMatrix(CameraState* camera_state, simd4x4f* mtx) { camera_state->pos[1] = -simd4f_get_y(eye); camera_state->pos[2] = -simd4f_get_z(eye); - // gLog ("ViewMat"); // gLog ("%f, %f, %f, %f", mtx->x[0], mtx->x[1], mtx->x[2], mtx->x[3]); // gLog ("%f, %f, %f, %f", mtx->y[0], mtx->y[1], mtx->y[2], mtx->y[3]); @@ -55,6 +72,14 @@ void CameraState_CalcToMatrix(CameraState* camera_state, simd4x4f* mtx) { simd4f up = simd4f_cross3(right, forward); simd4f center = simd4f_add(simd4f_mul(forward, simd4f_splat(d)), eye); + camera_state->forward[0] = -simd4f_get_x(forward); + camera_state->forward[1] = -simd4f_get_y(forward); + camera_state->forward[2] = -simd4f_get_z(forward); + + camera_state->right[0] = simd4f_get_x(right); + camera_state->right[1] = simd4f_get_y(right); + camera_state->right[2] = simd4f_get_z(right); + simd4x4f_lookat(mtx, eye, center, up); } @@ -64,25 +89,25 @@ inline void CameraState_Update( float mouse_dx, float mouse_dy, float accel[3]) { - CameraState_CalcFromMatrix(camera_state, &camera_state->mtxView); + const float mouse_sensitivity = 15.0f; - camera_state->heading += dt * mouse_dx * M_PI / 180.f; + camera_state->heading -= dt * mouse_dx * mouse_sensitivity * M_PI / 180.f; if (camera_state->heading < -M_PI) { camera_state->heading += M_PI; } else if (camera_state->heading > M_PI) { camera_state->heading -= M_PI; } - camera_state->heading = dt * mouse_dy * M_PI / 180.f; - if (camera_state->heading < -M_PI * 0.49) { - camera_state->heading = -M_PI * 0.49; - } else if (camera_state->heading > M_PI * 0.49) { - camera_state->heading = M_PI * 0.49; + camera_state->pitch += dt * mouse_dy * mouse_sensitivity * M_PI / 180.f; + if (camera_state->pitch < -M_PI * 0.49) { + camera_state->pitch = -M_PI * 0.49; + } else if (camera_state->pitch > M_PI * 0.49) { + camera_state->pitch = M_PI * 0.49; } for (int i = 0; i < 3; i++) { - camera_state->vel[i] += dt * accel[i]; + camera_state->vel[i] += dt * accel[0] * camera_state->forward[i] + dt * accel[2] * camera_state->right[i] + dt * accel[1] * camera_state->up[i]; camera_state->pos[i] += dt * camera_state->vel[i]; - camera_state->vel[i] = camera_state->vel[i] * 0.5; + camera_state->vel[i] = camera_state->vel[i] * 0.1; } CameraState_CalcToMatrix(camera_state, &camera_state->mtxView); diff --git a/src/render_utils.h b/src/render_utils.h index 4286212..3a1ad95 100644 --- a/src/render_utils.h +++ b/src/render_utils.h @@ -17,6 +17,9 @@ typedef struct { float pitch; float vel[3]; float pos[3]; + float forward[3]; + float right[3]; + float up[3]; } CameraState; void CameraState_Init(CameraState* camera_state); diff --git a/src/vissim.cc b/src/vissim.cc index f1ca68b..9c170e1 100644 --- a/src/vissim.cc +++ b/src/vissim.cc @@ -61,6 +61,9 @@ enum ViewMode { ViewModeSimulation = 0, ViewModeGuizmoTest = 1 }; ViewMode gViewMode = ViewModeSimulation; bool gGizmoEnabled = true; +enum ControlMode { ControlModeNone = 0, ControlModeFirstPersonView = 1 }; +ControlMode gControlMode = ControlModeNone; + using namespace std; static void error_callback(int error, const char* description) { @@ -519,7 +522,7 @@ int main(void) { simulator_init(); simd4x4f_translation(&gCameraState->mtxView, 0.1f, 0.1f, -0.5f); - simd4f eye = simd4f_create(0.f, 3.f, 10.f, 1.f); + simd4f eye = simd4f_create(0.f, 0.f, 10.f, 1.f); simd4x4f_lookat( &gCameraState->mtxView, @@ -580,34 +583,56 @@ int main(void) { float menu_bar_height = ImGui::GetWindowHeight(); ImGui::EndMainMenuBar(); - CameraState_CalcFromMatrix(gCameraState, &gCameraState->mtxView); + if (glfwGetMouseButton(gWindow, GLFW_MOUSE_BUTTON_RIGHT)) { + if (gControlMode == ControlModeNone) { + gControlMode = ControlModeFirstPersonView; + CameraState_CalcFromMatrix(gCameraState, &gCameraState->mtxView); + glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + } + } else { + gControlMode = ControlModeNone; + glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } - ImGui::Begin("HeadingPitch"); + if (gControlMode == ControlModeFirstPersonView) { + float camera_accel[3] = {0.f, 0.f, 0.f}; + + if (glfwGetKey(gWindow, GLFW_KEY_W)) { + camera_accel[0] -= 100.f; + } + if (glfwGetKey(gWindow, GLFW_KEY_S)) { + camera_accel[0] += 100.f; + } + if (glfwGetKey(gWindow, GLFW_KEY_C)) { + camera_accel[1] -= 100.f; + } + if (glfwGetKey(gWindow, GLFW_KEY_SPACE)) { + camera_accel[1] += 100.f; + } + if (glfwGetKey(gWindow, GLFW_KEY_A)) { + camera_accel[2] -= 100.f; + } + if (glfwGetKey(gWindow, GLFW_KEY_D)) { + camera_accel[2] += 100.f; + } + + CameraState_Update(gCameraState, frame_delta_time, gGuiInputState->mousedX, gGuiInputState->mousedY, camera_accel); + } + + ImGui::Begin("Camera Controls"); bool changed = false; changed = ImGui::SliderFloat("Heading", &gCameraState->heading, -M_PI * 0.98, M_PI * 0.98); - changed = changed || ImGui::SliderFloat("Pitch", &gCameraState->pitch, -M_PI * 0.49, M_PI * 0.49); + changed = ImGui::SliderFloat("Pitch", &gCameraState->pitch, -M_PI * 0.49, M_PI * 0.49) || changed; - float camera_accel[3] = {0.f, 0.f, 0.f}; - if (glfwGetKey(gWindow, GLFW_KEY_W)) { - camera_accel[0] -= 100.f; - } - if (glfwGetKey(gWindow, GLFW_KEY_S)) { - camera_accel[0] += 100.f; - } - if (glfwGetKey(gWindow, GLFW_KEY_A)) { - camera_accel[2] += 100.f; - } - if (glfwGetKey(gWindow, GLFW_KEY_D)) { - camera_accel[2] -= 100.f; - } + changed = ImGui::SliderFloat3("Forward", gCameraState->forward, -1.f, 1.f) || changed; + changed = ImGui::SliderFloat3("Right", gCameraState->right, -1.f, 1.f) || changed; + changed = ImGui::SliderFloat3("Up", gCameraState->up, -1.f, 1.f) || changed; + changed = ImGui::SliderFloat3("Pos", gCameraState->pos, -100.f, 100.f) || changed; if (changed) { CameraState_CalcToMatrix(gCameraState, &gCameraState->mtxView); - } else { - CameraState_Update(gCameraState, frame_delta_time, 0.f, 0.f, camera_accel); } - ImGui::End(); if (show_demo_window) ImGui::ShowDemoWindow();