2022-11-07 20:15:26 +00:00
|
|
|
#include "camera_controller.hpp"
|
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
#include "application.hpp"
|
2022-11-07 20:15:26 +00:00
|
|
|
#include "window.hpp"
|
2023-01-05 13:21:33 +00:00
|
|
|
#include "input_manager.hpp"
|
|
|
|
#include "scene.hpp"
|
|
|
|
|
|
|
|
#include "components/transform.hpp"
|
2023-01-22 18:20:10 +00:00
|
|
|
#include "components/collider.hpp"
|
2022-11-07 20:15:26 +00:00
|
|
|
|
|
|
|
#include <glm/trigonometric.hpp>
|
|
|
|
#include <glm/gtc/constants.hpp>
|
|
|
|
#include <glm/gtc/quaternion.hpp>
|
|
|
|
#include <glm/gtx/rotate_vector.hpp>
|
|
|
|
|
|
|
|
#include <log.hpp>
|
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
CameraControllerSystem::CameraControllerSystem(engine::Scene* scene)
|
|
|
|
: System(scene, { typeid(engine::TransformComponent).hash_code(), typeid(CameraControllerComponent).hash_code() })
|
2022-11-07 20:15:26 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
void CameraControllerSystem::onUpdate(float ts)
|
2022-11-07 20:15:26 +00:00
|
|
|
{
|
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
engine::TransformComponent* t = nullptr;
|
2023-01-22 18:20:10 +00:00
|
|
|
engine::ColliderComponent* col = nullptr;
|
2023-01-05 13:21:33 +00:00
|
|
|
CameraControllerComponent* c = nullptr;
|
|
|
|
for (uint32_t entity : m_entities) {
|
|
|
|
t = m_scene->getComponent<engine::TransformComponent>(entity);
|
2023-01-22 18:20:10 +00:00
|
|
|
col = m_scene->getComponent<engine::ColliderComponent>(entity);
|
2023-01-05 13:21:33 +00:00
|
|
|
c = m_scene->getComponent<CameraControllerComponent>(entity);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (t == nullptr) return;
|
|
|
|
if (c == nullptr) return;
|
2023-01-22 18:20:10 +00:00
|
|
|
if (col == nullptr) return;
|
2023-01-05 13:21:33 +00:00
|
|
|
|
2022-11-07 20:15:26 +00:00
|
|
|
// calculate new position
|
|
|
|
|
|
|
|
// use one unit per meter
|
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
const float dt = ts;
|
2022-11-07 20:15:26 +00:00
|
|
|
|
|
|
|
constexpr float G = 9.8f;
|
2023-01-26 23:52:25 +00:00
|
|
|
constexpr float MAX_SLOPE_ANGLE = glm::radians(20.0f);
|
2022-11-07 20:15:26 +00:00
|
|
|
|
2023-01-26 23:52:25 +00:00
|
|
|
glm::vec3 norm = col->getLastCollisionNormal();
|
2022-11-07 20:15:26 +00:00
|
|
|
|
2023-01-26 23:52:25 +00:00
|
|
|
norm.y = 0.0f;
|
|
|
|
|
|
|
|
glm::vec3 dir = glm::normalize(glm::rotateY(glm::vec3{ 1.0f, 0.0f, 0.0f }, c->m_yaw) + glm::rotateY(glm::vec3{ 0.0f, 0.0f, 1.0f }, c->m_yaw));
|
|
|
|
const float slope = glm::half_pi<float>() - glm::acos(glm::dot(dir, norm));
|
|
|
|
|
|
|
|
bool isSliding = false;
|
|
|
|
|
|
|
|
if (col->getIsColliding()) {
|
|
|
|
if (c->dy != 0.0f && slope <= MAX_SLOPE_ANGLE) {
|
|
|
|
t->position.y = m_scene->getComponent<engine::TransformComponent>(col->getLastEntityCollided())->worldMatrix[3][1] + 1.8f;
|
2023-01-05 13:21:33 +00:00
|
|
|
c->dy = 0.0f;
|
2023-01-26 23:52:25 +00:00
|
|
|
} else {
|
|
|
|
// slide across wall
|
|
|
|
isSliding = true;
|
2023-01-22 18:20:10 +00:00
|
|
|
}
|
|
|
|
} else {
|
2023-01-26 23:52:25 +00:00
|
|
|
c->dy -= G * dt;
|
2022-11-07 20:15:26 +00:00
|
|
|
}
|
2023-01-26 23:52:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
// jumping
|
|
|
|
constexpr float JUMPVEL = (float)2.82231110971133017648; //std::sqrt(2 * G * JUMPHEIGHT);
|
|
|
|
if (m_scene->app()->inputManager()->getButton("jump") && c->isJumping == false) {
|
|
|
|
if (col->getIsColliding())
|
|
|
|
c->dy = JUMPVEL;
|
2023-01-22 18:20:10 +00:00
|
|
|
}
|
2022-11-07 20:15:26 +00:00
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
if (m_scene->app()->window()->getButton(engine::inputs::MouseButton::M_LEFT)) {
|
|
|
|
c->dy += dt * c->thrust;
|
|
|
|
c->isJumping = true;
|
2022-11-07 20:15:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// in metres per second
|
|
|
|
//constexpr float SPEED = 1.5f;
|
2023-01-05 13:21:33 +00:00
|
|
|
float SPEED = c->walk_speed;
|
|
|
|
if (m_scene->app()->inputManager()->getButton("sprint")) SPEED *= 10.0f;
|
2022-11-07 20:15:26 +00:00
|
|
|
|
2023-01-26 23:52:25 +00:00
|
|
|
float dx = m_scene->app()->inputManager()->getAxis("movex");
|
|
|
|
float dz = (-m_scene->app()->inputManager()->getAxis("movey"));
|
2022-11-07 20:15:26 +00:00
|
|
|
|
|
|
|
// calculate new pitch and yaw
|
|
|
|
|
|
|
|
constexpr float MAX_PITCH = glm::half_pi<float>();
|
|
|
|
constexpr float MIN_PITCH = -MAX_PITCH;
|
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
float dPitch = m_scene->app()->inputManager()->getAxis("looky") * -1.0f * c->m_cameraSensitivity;
|
|
|
|
c->m_pitch += dPitch;
|
|
|
|
if (c->m_pitch <= MIN_PITCH || c->m_pitch >= MAX_PITCH) {
|
|
|
|
c->m_pitch -= dPitch;
|
2022-11-07 20:15:26 +00:00
|
|
|
}
|
2023-01-05 13:21:33 +00:00
|
|
|
c->m_yaw += m_scene->app()->inputManager()->getAxis("lookx") * -1.0f * c->m_cameraSensitivity;
|
2022-11-07 20:15:26 +00:00
|
|
|
|
|
|
|
// update position relative to camera direction in xz plane
|
2023-01-05 13:21:33 +00:00
|
|
|
const glm::vec3 d2xRotated = glm::rotateY(glm::vec3{ dx, 0.0f, 0.0f }, c->m_yaw);
|
|
|
|
const glm::vec3 d2zRotated = glm::rotateY(glm::vec3{ 0.0f, 0.0f, dz }, c->m_yaw);
|
2023-01-26 23:52:25 +00:00
|
|
|
glm::vec3 hVel = (d2xRotated + d2zRotated);
|
|
|
|
if (isSliding) {
|
|
|
|
hVel = glm::vec3{norm.z, 0.0f, norm.x};
|
|
|
|
}
|
|
|
|
hVel *= SPEED;
|
|
|
|
t->position += hVel * dt;
|
2023-01-05 13:21:33 +00:00
|
|
|
t->position.y += c->dy * dt;
|
2022-11-07 20:15:26 +00:00
|
|
|
|
2022-11-23 15:40:10 +00:00
|
|
|
constexpr float MAX_DISTANCE_FROM_ORIGIN = 1000.0f;
|
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
if (glm::length(t->position) > MAX_DISTANCE_FROM_ORIGIN) {
|
2023-01-22 18:20:10 +00:00
|
|
|
t->position = { 0.0f, 5.0f, 0.0f };
|
2023-01-05 13:21:33 +00:00
|
|
|
c->dy = 0.0f;
|
2023-01-22 18:20:10 +00:00
|
|
|
c->isJumping = true;
|
2022-11-23 15:40:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ROTATION STUFF */
|
|
|
|
|
2022-11-07 20:15:26 +00:00
|
|
|
// pitch quaternion
|
2023-01-05 13:21:33 +00:00
|
|
|
const float halfPitch = c->m_pitch / 2.0f;
|
2022-11-07 20:15:26 +00:00
|
|
|
glm::quat pitchQuat{};
|
|
|
|
pitchQuat.x = glm::sin(halfPitch);
|
|
|
|
pitchQuat.y = 0.0f;
|
|
|
|
pitchQuat.z = 0.0f;
|
|
|
|
pitchQuat.w = glm::cos(halfPitch);
|
|
|
|
|
|
|
|
// yaw quaternion
|
2023-01-05 13:21:33 +00:00
|
|
|
const float halfYaw = c->m_yaw / 2.0f;
|
2022-11-07 20:15:26 +00:00
|
|
|
glm::quat yawQuat{};
|
|
|
|
yawQuat.x = 0.0f;
|
|
|
|
yawQuat.y = glm::sin(halfYaw);
|
|
|
|
yawQuat.z = 0.0f;
|
|
|
|
yawQuat.w = glm::cos(halfYaw);
|
|
|
|
|
|
|
|
// update rotation
|
2023-01-05 13:21:33 +00:00
|
|
|
t->rotation = yawQuat * pitchQuat;
|
2022-11-07 20:15:26 +00:00
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* user interface inputs */
|
|
|
|
|
|
|
|
if (m_scene->app()->window()->getKeyPress(engine::inputs::Key::K_P)) {
|
2022-11-07 20:15:26 +00:00
|
|
|
std::string pos_string{
|
2023-01-05 13:21:33 +00:00
|
|
|
"x: " + std::to_string(t->position.x) +
|
|
|
|
" y: " + std::to_string(t->position.y) +
|
|
|
|
" z: " + std::to_string(t->position.z)
|
2022-11-07 20:15:26 +00:00
|
|
|
};
|
2023-01-26 23:52:25 +00:00
|
|
|
// m_scene->app()->window()->infoBox("POSITION", pos_string);
|
|
|
|
m_scene->app()->window()->infoBox("POSITION", std::to_string(slope));
|
2022-11-07 20:15:26 +00:00
|
|
|
INFO("position: " + pos_string);
|
|
|
|
}
|
|
|
|
|
2023-01-05 13:21:33 +00:00
|
|
|
if (m_scene->app()->inputManager()->getButtonPress("fullscreen")) {
|
|
|
|
m_scene->app()->window()->toggleFullscreen();
|
|
|
|
}
|
|
|
|
|
2022-11-07 20:15:26 +00:00
|
|
|
}
|