engine/test/src/camera_controller.cpp

109 lines
3.3 KiB
C++
Raw Normal View History

2022-11-07 20:15:26 +00:00
#include "camera_controller.hpp"
#include <glm/gtc/constants.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/rotate_vector.hpp>
2023-05-02 11:02:43 +00:00
#include <glm/trigonometric.hpp>
2022-11-07 20:15:26 +00:00
2023-05-02 11:02:43 +00:00
#include "application.h"
#include "components/transform.h"
#include "input_manager.h"
#include "log.h"
#include "scene.h"
#include "scene_manager.h"
#include "window.h"
2023-02-12 14:50:29 +00:00
2023-05-02 11:02:43 +00:00
CameraControllerSystem::CameraControllerSystem(engine::Scene* scene)
: System(scene, {typeid(engine::TransformComponent).hash_code(),
typeid(CameraControllerComponent).hash_code()}) {}
void CameraControllerSystem::OnUpdate(float ts) {
2023-07-04 16:08:28 +00:00
if (t == nullptr || c == nullptr) {
2023-05-02 11:02:43 +00:00
for (uint32_t entity : entities_) {
t = scene_->GetComponent<engine::TransformComponent>(entity);
c = scene_->GetComponent<CameraControllerComponent>(entity);
break;
}
if (t == nullptr) return;
if (c == nullptr) return;
}
const float dt = ts;
// in metres per second
float speed = c->kWalkSpeed;
if (scene_->app()->input_manager()->GetButton("sprint")) speed *= 10.0f;
float dx = scene_->app()->input_manager()->GetAxis("movex");
float dz = (-scene_->app()->input_manager()->GetAxis("movey"));
// calculate new pitch and yaw
constexpr float kMaxPitch = glm::half_pi<float>();
constexpr float kMinPitch = -kMaxPitch;
float d_pitch = scene_->app()->input_manager()->GetAxis("looky") * -1.0f *
c->kCameraSensitivity;
c->pitch += d_pitch;
if (c->pitch <= kMinPitch || c->pitch >= kMaxPitch) {
c->pitch -= d_pitch;
}
c->yaw += scene_->app()->input_manager()->GetAxis("lookx") * -1.0f *
c->kCameraSensitivity;
// update position relative to camera direction in xz plane
const glm::vec3 d2x_rotated = glm::rotateY(glm::vec3{dx, 0.0f, 0.0f}, c->yaw);
2023-07-04 16:08:28 +00:00
const glm::vec3 d2z_rotated =
glm::rotateY(glm::rotateX(glm::vec3{0.0f, 0.0f, dz}, c->pitch), c->yaw);
2023-05-02 11:02:43 +00:00
glm::vec3 h_vel = (d2x_rotated + d2z_rotated);
h_vel *= speed;
t->position += h_vel * dt;
constexpr float kMaxDistanceFromOrigin = 10000.0f;
if (glm::length(t->position) > kMaxDistanceFromOrigin) {
t->position = {0.0f, 5.0f, 0.0f};
}
/* ROTATION STUFF */
// pitch quaternion
const float half_pitch = c->pitch / 2.0f;
glm::quat pitch_quat{};
pitch_quat.x = glm::sin(half_pitch);
pitch_quat.y = 0.0f;
pitch_quat.z = 0.0f;
pitch_quat.w = glm::cos(half_pitch);
// yaw quaternion
const float half_yaw = c->yaw / 2.0f;
glm::quat yaw_quat{};
yaw_quat.x = 0.0f;
yaw_quat.y = glm::sin(half_yaw);
yaw_quat.z = 0.0f;
yaw_quat.w = glm::cos(half_yaw);
// update rotation
t->rotation = yaw_quat * pitch_quat;
/* user interface inputs */
if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_P)) {
std::string pos_string{"x: " + std::to_string(t->position.x) +
" y: " + std::to_string(t->position.y) +
" z: " + std::to_string(t->position.z)};
LOG_INFO("position {}", pos_string);
}
if (scene_->app()->window()->GetKeyPress(engine::inputs::Key::K_R)) {
t->position = {0.0f, 5.0f, 0.0f};
}
if (scene_->app()->input_manager()->GetButtonPress("fullscreen")) {
scene_->app()->window()->ToggleFullscreen();
}
if (scene_->app()->input_manager()->GetButtonPress("exit")) {
scene_->app()->window()->SetCloseFlag();
}
2023-07-04 16:08:28 +00:00
}