First implementation of new camera systems

This commit is contained in:
2022-10-22 14:52:22 +02:00
parent e9dec68cb1
commit e6ea33e5b7
12 changed files with 246 additions and 95 deletions

View File

@@ -1,11 +1,15 @@
#include "Scene.h"
#include "ShaderProgram.h"
#include "camera.h"
#include "mesh.h"
#include "name.h"
#include "relationship.h"
#include "transform.h"
#include "util/Log.h"
#include <GLFW/glfw3.h>
#include <algorithm>
using namespace entt::literals;
// TODO: make scene initialization part of gltf loader as seen in bevy
@@ -87,29 +91,40 @@ Scene::Scene()
// Remove Material resource as it is no longer needed.
m_registry.erase<entt::resource<Material>>(entity);
}
// Spawn the camera
auto entity = m_registry.create();
m_registry.emplace<Name>(entity, "Camera");
m_registry.emplace<Transform>(entity, Transform{.translation = glm::vec3(0.0, 0.5, -2.0)});
m_registry.emplace<GlobalTransform>(entity, GlobalTransform{});
m_registry.emplace<Camera>(entity,
Camera{.projection = Camera::Perspective{.aspect_ratio = 1.6}});
}
void Scene::update(std::chrono::duration<float> delta,
ShaderProgram *shaderprogram,
glm::mat4 viewProjMatrix,
glm::vec3 viewPosition)
KeyInput const &key_input,
MouseCursorInput const &mouse_cursor_input,
float aspect_ratio)
{
// Update GlobalTransform components
// TODO: Only do this when the Transform changed.
auto root_transform_view =
m_registry.view<Transform const, GlobalTransform>(entt::exclude<Parent>);
auto transform_view = m_registry.view<Transform const, GlobalTransform, Parent const>();
{
// Update GlobalTransform components
// TODO: Only do this when the Transform changed.
auto root_transform_view =
m_registry.view<Transform const, GlobalTransform>(entt::exclude<Parent>);
auto transform_view = m_registry.view<Transform const, GlobalTransform, Parent const>();
for (auto [entity, transform, global_transform] : root_transform_view.each()) {
global_transform = transform;
for (auto [entity, transform, global_transform] : root_transform_view.each()) {
global_transform = transform;
auto parent_global_transform = global_transform;
if (auto *children = m_registry.try_get<Children>(entity)) {
for (auto child : children->children) {
std::function<void(entt::entity entity, GlobalTransform parent_global_transform)>
transform_propagate =
[this, &transform_propagate, &transform_view](
entt::entity entity, GlobalTransform parent_global_transform) {
auto parent_global_transform = global_transform;
if (auto *children = m_registry.try_get<Children>(entity)) {
for (auto child : children->children) {
std::function<void(entt::entity entity,
GlobalTransform parent_global_transform)>
transform_propagate = [this, &transform_propagate, &transform_view](
entt::entity entity,
GlobalTransform parent_global_transform) {
auto [transform, global_transform, parent] = transform_view.get(entity);
global_transform.transform = parent_global_transform.transform *
GlobalTransform(transform).transform;
@@ -121,30 +136,120 @@ void Scene::update(std::chrono::duration<float> delta,
}
};
transform_propagate(child, parent_global_transform);
transform_propagate(child, parent_global_transform);
}
}
}
}
auto mesh_view = m_registry.view<GpuMesh const, GpuMaterial const, GlobalTransform const>();
for (auto [entity, mesh, material, transform] : mesh_view.each()) {
shaderprogram->bind();
{
auto mesh_view = m_registry.view<GpuMesh const, GpuMaterial const, GlobalTransform const>();
auto camera_view = m_registry.view<Camera const, GlobalTransform const>();
auto camera_entity = camera_view.front();
auto [camera, camera_transform] = camera_view.get(camera_entity);
glm::mat4 view_projection_matrix =
camera.projection_matrix() * Camera::view_matrix(camera_transform);
// Bind textures
material.bind(*shaderprogram);
for (auto [entity, mesh, material, transform] : mesh_view.each()) {
shaderprogram->bind();
// Bind modelview matrix uniform
{
glm::mat4 modelViewProj = viewProjMatrix * transform.transform;
shaderprogram->setUniform("u_modelViewProjMatrix", modelViewProj);
shaderprogram->setUniform("u_modelMatrix", transform.transform);
shaderprogram->setUniform("u_viewPosition", viewPosition);
// Bind textures
material.bind(*shaderprogram);
// Bind modelview matrix uniform
{
glm::mat4 modelViewProj = view_projection_matrix * transform.transform;
shaderprogram->setUniform("u_modelViewProjMatrix", modelViewProj);
shaderprogram->setUniform("u_modelMatrix", transform.transform);
shaderprogram->setUniform("u_viewPosition", camera_transform.position());
}
glBindVertexArray(mesh.vao);
glDrawElements(GL_TRIANGLES, mesh.indices_count, mesh.indices_type, nullptr);
glBindVertexArray(0);
ShaderProgram::unbind();
}
}
// Camera keyboard update
{
auto camera_view = m_registry.view<Camera const, Transform, GlobalTransform const>();
auto camera_entity = camera_view.front();
auto [camera, camera_transform, camera_global_transform] = camera_view.get(camera_entity);
glm::vec3 front_vec = Camera::front_vector(camera_global_transform);
glm::vec3 front_vec_without_y = glm::vec3(front_vec.x, 0., front_vec.z);
glm::vec3 deltaPos = glm::vec3(0., 0., 0.);
// float deltaFactor = SPEED * deltaTime * (m_accellerate ? 5.0 : 1.0);
float delta_factor = 0.5 * delta.count();
// m_accellerate = false;
for (auto const &[key, pressed] : key_input) {
if (key == GLFW_KEY_W && pressed) {
deltaPos += delta_factor * glm::normalize(front_vec_without_y);
}
if (key == GLFW_KEY_S && pressed) {
deltaPos -= delta_factor * glm::normalize(front_vec_without_y);
}
if (key == GLFW_KEY_A && pressed) {
deltaPos -= delta_factor * glm::normalize(glm::cross(front_vec, Camera::UP_VECTOR));
}
if (key == GLFW_KEY_D && pressed) {
deltaPos += delta_factor * glm::normalize(glm::cross(front_vec, Camera::UP_VECTOR));
}
if (key == GLFW_KEY_SPACE && pressed) {
deltaPos += delta_factor * Camera::UP_VECTOR;
}
if (key == GLFW_KEY_LEFT_SHIFT && pressed) {
deltaPos -= delta_factor * Camera::UP_VECTOR;
}
// if (key == GLFW_KEY_LEFT_ALT && pressed) {
// m_accellerate = true;
// }
}
camera_transform.translation += deltaPos;
}
// Camera mouse update
{
auto camera_view = m_registry.view<Camera, Transform>();
auto camera_entity = camera_view.front();
auto [camera, camera_transform] = camera_view.get(camera_entity);
auto [deltaX, deltaY] = mouse_cursor_input;
if (std::abs(deltaX) < std::numeric_limits<double>::epsilon() &&
std::abs(deltaY) < std::numeric_limits<double>::epsilon()) {
return;
}
glBindVertexArray(mesh.vao);
glDrawElements(GL_TRIANGLES, mesh.indices_count, mesh.indices_type, nullptr);
glBindVertexArray(0);
auto pitch = static_cast<float>(deltaY);
auto yaw = static_cast<float>(deltaX);
auto roll = 0.0F;
ShaderProgram::unbind();
// Orthographic projection currently unsupported
auto &camera_perspective = std::get<Camera::Perspective>(camera.projection);
camera_perspective.pitch += glm::radians(pitch);
camera_perspective.yaw += glm::radians(yaw);
static constexpr float PITCH_CLIP = glm::radians(89.);
camera_perspective.pitch =
std::clamp(static_cast<float>(camera_perspective.pitch), -PITCH_CLIP, PITCH_CLIP);
camera_transform.orientation =
glm::quat(glm::vec3(-camera_perspective.pitch, -camera_perspective.yaw, 0.0));
}
}
// Camera aspect ratio update
{
auto camera_view = m_registry.view<Camera>();
auto camera_entity = camera_view.front();
auto [camera] = camera_view.get(camera_entity);
// Orthographic projection currently unsupported
auto &camera_perspective = std::get<Camera::Perspective>(camera.projection);
camera_perspective.aspect_ratio = aspect_ratio;
}
}