149 lines
4.8 KiB
C++
149 lines
4.8 KiB
C++
#include "camera.h"
|
|
#include <SDL3/SDL_gamepad.h>
|
|
#include <iostream>
|
|
|
|
|
|
/*
|
|
I bought a very cheap ps4 knockoff controller and for some reason
|
|
AXIS_RIGHTX and AXIS_RIGHTY are swapped with the triggers?
|
|
this should be defined as 0 for a working one
|
|
*/
|
|
#define WEIRD_JOYSTICK_BEHAVIOR 1
|
|
|
|
vec3 Camera::dir() const {
|
|
return normalize(vec3(
|
|
cos(radians(yaw)) * cos(radians(pitch)),
|
|
sin(radians(pitch)),
|
|
sin(radians(yaw)) * cos(radians(pitch))
|
|
));
|
|
}
|
|
|
|
void Camera::update() {
|
|
if (look_up) pitch += look_speed;
|
|
if (look_down) pitch -= look_speed;
|
|
if (look_left) yaw -= look_speed;
|
|
if (look_right) yaw += look_speed;
|
|
pitch = clamp(pitch, -89.0f, 89.0f);
|
|
|
|
vec3 d = dir();
|
|
vec3 right = normalize(cross(d, up));
|
|
target = pos + d;
|
|
|
|
float shift_speed = shifted? 10.0 : 1.0;
|
|
float speed = move_speed * shift_speed;
|
|
|
|
if (move_forward) { pos += d * speed; target += d * speed; }
|
|
if (move_backward) { pos -= d * speed; target -= d * speed; }
|
|
if (move_left) { pos -= right * speed; target -= right * speed; }
|
|
if (move_right) { pos += right * speed; target += right * speed; }
|
|
if (move_up) { pos += up * speed; target += up * speed; }
|
|
if (move_down) { pos -= up * speed; target -= up * speed; }
|
|
}
|
|
|
|
void Camera::on_key(SDL_Scancode scancode, bool pressed) {
|
|
switch (scancode) {
|
|
case SDL_SCANCODE_W: move_forward = pressed; break;
|
|
case SDL_SCANCODE_S: move_backward = pressed; break;
|
|
case SDL_SCANCODE_A: move_left = pressed; break;
|
|
case SDL_SCANCODE_D: move_right = pressed; break;
|
|
case SDL_SCANCODE_SPACE: move_up = pressed; break;
|
|
case SDL_SCANCODE_LCTRL: move_down = pressed; break;
|
|
case SDL_SCANCODE_UP: look_up = pressed; break;
|
|
case SDL_SCANCODE_DOWN: look_down = pressed; break;
|
|
case SDL_SCANCODE_LEFT: look_left = pressed; break;
|
|
case SDL_SCANCODE_RIGHT: look_right = pressed; break;
|
|
case SDL_SCANCODE_LSHIFT:
|
|
case SDL_SCANCODE_RSHIFT:
|
|
shifted = pressed;
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef WEIRD_JOYSTICK_BEHAVIOR
|
|
#define WEIRD_JOYSTICK_BEHAVIOR 0
|
|
#endif
|
|
static float normalize_stick(SDL_Gamepad* gamepad, SDL_GamepadAxis axis) {
|
|
if(axis == SDL_GAMEPAD_AXIS_COUNT || axis == SDL_GAMEPAD_AXIS_INVALID)
|
|
return 0.0f;
|
|
|
|
|
|
float d = static_cast<float>(SDL_GetGamepadAxis(gamepad, axis));
|
|
|
|
bool reported_trigger = (axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER || axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER);
|
|
bool really_trigger = (WEIRD_JOYSTICK_BEHAVIOR)? (axis == SDL_GAMEPAD_AXIS_RIGHTX || axis == SDL_GAMEPAD_AXIS_RIGHTY) : reported_trigger;
|
|
|
|
float min = (reported_trigger)? 0 : SDL_JOYSTICK_AXIS_MIN;
|
|
float max = SDL_JOYSTICK_AXIS_MAX;
|
|
float n = (d - min) / (max - min);
|
|
|
|
return really_trigger? n : ((n - 0.5) * 2.0);
|
|
}
|
|
|
|
void Camera::on_gamepad(SDL_Gamepad* gamepad) {
|
|
if (!gamepad) return;
|
|
|
|
float lx = normalize_stick(gamepad, SDL_GAMEPAD_AXIS_LEFTX);
|
|
float ly = normalize_stick(gamepad, SDL_GAMEPAD_AXIS_LEFTY);
|
|
float ry = normalize_stick(gamepad, (WEIRD_JOYSTICK_BEHAVIOR)? SDL_GAMEPAD_AXIS_RIGHT_TRIGGER : SDL_GAMEPAD_AXIS_RIGHTY);
|
|
float rx = normalize_stick(gamepad, (WEIRD_JOYSTICK_BEHAVIOR)? SDL_GAMEPAD_AXIS_LEFT_TRIGGER : SDL_GAMEPAD_AXIS_RIGHTX);
|
|
static uint8_t frame = 0;
|
|
if(frame++ == 64) {
|
|
std::cout << "lx: " << lx << " ly: " << ly << " rx: " << rx << " ry: " << ry << std::endl;
|
|
}
|
|
|
|
//float lt = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER) / 32767.0f;
|
|
//float rt = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) / 32767.0f;
|
|
|
|
const float dead = 0.1f;
|
|
if (abs(lx) < dead) lx = 0.0f;
|
|
if (abs(ly) < dead) ly = 0.0f;
|
|
if (abs(rx) < dead) rx = 0.0f;
|
|
if (abs(ry) < dead) ry = 0.0f;
|
|
// if (lt < dead) lt = 0.0f;
|
|
// if (rt < dead) rt = 0.0f;
|
|
|
|
|
|
// look — right stick only
|
|
yaw += rx * look_speed;
|
|
pitch -= ry * look_speed;
|
|
pitch = clamp(pitch, -89.0f, 89.0f);
|
|
|
|
|
|
vec3 d = dir();
|
|
vec3 right = normalize(cross(d, up));
|
|
float speed = move_speed * (shifted ? 4.0f : 1.0f);
|
|
|
|
// move — left stick
|
|
pos += d * (-ly * speed);
|
|
pos += right * ( lx * speed);
|
|
|
|
// up/down — triggers
|
|
//pos += up * (rt - lt) * speed;
|
|
|
|
target = pos + d;
|
|
|
|
shifted = SDL_GetGamepadButton(gamepad, SDL_GAMEPAD_BUTTON_LEFT_SHOULDER);
|
|
}
|
|
|
|
void Camera::on_mouse_motion(float dx, float dy) {
|
|
yaw += dx * look_speed * 0.1f;
|
|
pitch -= dy * look_speed * 0.1f;
|
|
pitch = clamp(pitch, -89.0f, 89.0f);
|
|
}
|
|
|
|
CameraUBO Camera::ubo(float aspect) const {
|
|
mat4 v = lookAt(pos, target, up);
|
|
mat4 p = perspective(radians(fov), aspect, 0.01f, 1000.0f);
|
|
return CameraUBO {
|
|
.model = mat4(1.0f),
|
|
.view = v,
|
|
.proj = p,
|
|
.inv_view = inverse(v),
|
|
.inv_proj = inverse(p),
|
|
.cam_pos = vec4(pos, 1.0),
|
|
.time = (float)SDL_GetTicks() / 1000.0f,
|
|
};
|
|
}
|