Still buggy but somewhat workable FPS control.

master
Martin Felis 2021-10-29 13:08:44 +02:00
parent 90d9ac3961
commit 23d7cf03f6
3 changed files with 88 additions and 35 deletions

View File

@ -11,16 +11,34 @@ inline void CameraState_Init(CameraState* camera_state) {
}; };
// clang-format on // 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)); 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) { 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->forward[0] = mtx->x[2];
camera_state->pitch = asin(-forward[1]); 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; simd4x4f rot_mat = *mtx;
rot_mat.w = simd4f_create(0.f, 0.f, 0.f, 1.f); 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[1] = -simd4f_get_y(eye);
camera_state->pos[2] = -simd4f_get_z(eye); camera_state->pos[2] = -simd4f_get_z(eye);
// gLog ("ViewMat"); // 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->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]); // 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 up = simd4f_cross3(right, forward);
simd4f center = simd4f_add(simd4f_mul(forward, simd4f_splat(d)), eye); 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); simd4x4f_lookat(mtx, eye, center, up);
} }
@ -64,25 +89,25 @@ inline void CameraState_Update(
float mouse_dx, float mouse_dx,
float mouse_dy, float mouse_dy,
float accel[3]) { 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) { if (camera_state->heading < -M_PI) {
camera_state->heading += M_PI; camera_state->heading += M_PI;
} else if (camera_state->heading > M_PI) { } else if (camera_state->heading > M_PI) {
camera_state->heading -= M_PI; camera_state->heading -= M_PI;
} }
camera_state->heading = dt * mouse_dy * M_PI / 180.f; camera_state->pitch += dt * mouse_dy * mouse_sensitivity * M_PI / 180.f;
if (camera_state->heading < -M_PI * 0.49) { if (camera_state->pitch < -M_PI * 0.49) {
camera_state->heading = -M_PI * 0.49; camera_state->pitch = -M_PI * 0.49;
} else if (camera_state->heading > M_PI * 0.49) { } else if (camera_state->pitch > M_PI * 0.49) {
camera_state->heading = M_PI * 0.49; camera_state->pitch = M_PI * 0.49;
} }
for (int i = 0; i < 3; i++) { 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->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); CameraState_CalcToMatrix(camera_state, &camera_state->mtxView);

View File

@ -17,6 +17,9 @@ typedef struct {
float pitch; float pitch;
float vel[3]; float vel[3];
float pos[3]; float pos[3];
float forward[3];
float right[3];
float up[3];
} CameraState; } CameraState;
void CameraState_Init(CameraState* camera_state); void CameraState_Init(CameraState* camera_state);

View File

@ -61,6 +61,9 @@ enum ViewMode { ViewModeSimulation = 0, ViewModeGuizmoTest = 1 };
ViewMode gViewMode = ViewModeSimulation; ViewMode gViewMode = ViewModeSimulation;
bool gGizmoEnabled = true; bool gGizmoEnabled = true;
enum ControlMode { ControlModeNone = 0, ControlModeFirstPersonView = 1 };
ControlMode gControlMode = ControlModeNone;
using namespace std; using namespace std;
static void error_callback(int error, const char* description) { static void error_callback(int error, const char* description) {
@ -519,7 +522,7 @@ int main(void) {
simulator_init(); simulator_init();
simd4x4f_translation(&gCameraState->mtxView, 0.1f, 0.1f, -0.5f); 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( simd4x4f_lookat(
&gCameraState->mtxView, &gCameraState->mtxView,
@ -580,34 +583,56 @@ int main(void) {
float menu_bar_height = ImGui::GetWindowHeight(); float menu_bar_height = ImGui::GetWindowHeight();
ImGui::EndMainMenuBar(); 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; bool changed = false;
changed = ImGui::SliderFloat("Heading", &gCameraState->heading, -M_PI * 0.98, M_PI * 0.98); 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}; changed = ImGui::SliderFloat3("Forward", gCameraState->forward, -1.f, 1.f) || changed;
if (glfwGetKey(gWindow, GLFW_KEY_W)) { changed = ImGui::SliderFloat3("Right", gCameraState->right, -1.f, 1.f) || changed;
camera_accel[0] -= 100.f; changed = ImGui::SliderFloat3("Up", gCameraState->up, -1.f, 1.f) || changed;
} changed = ImGui::SliderFloat3("Pos", gCameraState->pos, -100.f, 100.f) || changed;
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;
}
if (changed) { if (changed) {
CameraState_CalcToMatrix(gCameraState, &gCameraState->mtxView); CameraState_CalcToMatrix(gCameraState, &gCameraState->mtxView);
} else {
CameraState_Update(gCameraState, frame_delta_time, 0.f, 0.f, camera_accel);
} }
ImGui::End(); ImGui::End();
if (show_demo_window) ImGui::ShowDemoWindow(); if (show_demo_window) ImGui::ShowDemoWindow();