Still buggy but somewhat workable FPS control.
parent
90d9ac3961
commit
23d7cf03f6
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
|
||||
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_A)) {
|
||||
camera_accel[2] += 100.f;
|
||||
if (glfwGetKey(gWindow, GLFW_KEY_C)) {
|
||||
camera_accel[1] -= 100.f;
|
||||
}
|
||||
if (glfwGetKey(gWindow, GLFW_KEY_D)) {
|
||||
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 = ImGui::SliderFloat("Pitch", &gCameraState->pitch, -M_PI * 0.49, M_PI * 0.49) || changed;
|
||||
|
||||
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();
|
||||
|
|
Loading…
Reference in New Issue