Compare commits

...

10 Commits

Author SHA1 Message Date
1ee0407d16 Add vcpkg baseline 2025-03-11 22:34:00 +01:00
94434d373c Minor CMake refactor 2024-12-07 19:32:55 +01:00
997e45d8af Switch from CPM to VCPKG 2024-12-07 19:30:17 +01:00
e4378dcddc Restructure project 2024-12-07 15:46:02 +01:00
991093d352 Move flycam to binary 2024-10-20 15:53:57 +02:00
5331c3d002 Clean up CMakeLists 2024-10-19 18:13:33 +02:00
45a1c77e90 Switch to CPM package manager 2024-10-19 18:10:11 +02:00
2a43299a15 Update project structure 2024-10-19 10:20:37 +02:00
aa3dd28fb3 Add controls to readme 2023-07-02 22:16:28 +02:00
125e19e0be Restore compatibility with Windows 2023-07-02 21:17:03 +02:00
27 changed files with 382 additions and 409 deletions

View File

@@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.20)
cmake_policy(SET CMP0135 NEW)
cmake_minimum_required(VERSION 3.24)
project(
Fall-Fever
@@ -12,43 +11,48 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(FetchContent)
# EnTT
FetchContent_Declare(
entt
URL https://github.com/skypjack/entt/archive/refs/tags/v3.12.0.tar.gz
)
FetchContent_MakeAvailable(entt)
# GLFW
FetchContent_Declare(
glfw
URL https://github.com/glfw/glfw/releases/download/3.3.8/glfw-3.3.8.zip
)
option(GLFW_BUILD_DOCS "" OFF)
option(GLFW_BUILD_EXAMPLES "" OFF)
option(GLFW_BUILD_TESTS "" OFF)
option(GLFW_INSTALL "" OFF)
FetchContent_MakeAvailable(glfw)
# fx-gltf
FetchContent_Declare(
fx-gltf
URL https://github.com/jessey-git/fx-gltf/archive/refs/tags/v2.0.0.tar.gz
)
option(FX_GLTF_BUILD_TESTS "" OFF)
option(FX_GLTF_INSTALL "" OFF)
FetchContent_MakeAvailable(fx-gltf)
find_package(glm REQUIRED)
find_package(EnTT CONFIG REQUIRED)
find_package(glm CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(glfw3 REQUIRED)
find_package(spdlog REQUIRED)
find_package(fx-gltf REQUIRED)
add_subdirectory(${PROJECT_SOURCE_DIR}/lib)
add_subdirectory(${PROJECT_SOURCE_DIR}/src)
add_library(fever_core
src/components/transform.cpp
src/core/application.cpp
src/core/camera.cpp
src/core/glad.cpp
src/core/graphics/framebuffer.cpp
src/core/graphics/image.cpp
src/core/graphics/material.cpp
src/core/graphics/mesh.cpp
src/core/light.cpp
src/core/render.cpp
src/core/shader.cpp
src/core/time.cpp
src/input/input.cpp
src/scene/gltf.cpp
src/scene/gltf_loader.cpp
src/util/log.cpp
src/window/window.cpp
)
target_compile_features(fever_core PUBLIC cxx_std_20)
target_include_directories(fever_core PUBLIC ${CMAKE_SOURCE_DIR}/src)
target_link_libraries(
fever_core PUBLIC
glad
stb
glfw
EnTT::EnTT
spdlog::spdlog
glm::glm
fx-gltf::fx-gltf
nlohmann_json::nlohmann_json
)
add_subdirectory(${PROJECT_SOURCE_DIR}/apps)

View File

@@ -1,8 +1,8 @@
{
"version": 2,
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 14,
"minor": 24,
"patch": 0
},
"configurePresets": [
@@ -26,17 +26,26 @@
"CMAKE_CXX_STANDARD_REQUIRED": "ON"
}
},
{
"name": "vcpkg",
"hidden": true,
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALL_OPTIONS": "--no-print-usage"
}
},
{
"name": "dev",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"inherits": [
"std"
"std",
"vcpkg"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic"
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -fdiagnostics-color=always"
}
}
]
}
}

View File

@@ -1,3 +1,13 @@
A work in progress game engine written in C++ using OpenGL and [entt](https://github.com/skypjack/entt).
![A screenshot](screenshot.png)
## Controls
| Button | Action |
| ------------ | -------------------------- |
| W, A, S, D | Horizontal Camera Movement |
| Left Shift | Camera Down |
| Space | Camera Up |
| Left Alt | Accelerate |
| Left Control | Catch Mouse |
| Escape | Quit |

1
apps/CMakeLists.txt Normal file
View File

@@ -0,0 +1 @@
add_subdirectory(fall-fever)

View File

@@ -0,0 +1,9 @@
find_package(cxxopts CONFIG)
add_executable(Fall-Fever
main.cpp
controller.cpp
flycam.cpp
)
target_link_libraries(Fall-Fever PRIVATE fever_core cxxopts::cxxopts)

View File

@@ -1,40 +1,27 @@
#include "controller.h"
#include "flycam.h"
#include "components/name.h"
#include "components/transform.h"
#include "core/camera.h"
#include "core/light.h"
#include "window/window.h"
#include <spdlog/spdlog.h>
using namespace entt::literals;
Controller::Controller()
Controller::Controller(std::string_view path)
{
std::filesystem::path document_path("WaterBottle/glTF-Binary/WaterBottle.glb");
entt::hashed_string document_hash(document_path.c_str());
spdlog::info("Open {}", path);
std::filesystem::path document_path(path);
entt::hashed_string document_hash(document_path.string().c_str());
entt::resource<Gltf> gltf_document =
gltf_cache.load(document_hash, document_path).first->second;
gltf_document->spawn_default_scene(registry(), gltf_node_cache);
// Convert meshes
auto mesh_view = registry().view<entt::resource<Mesh>>();
for (auto [entity, mesh] : mesh_view.each()) {
registry().emplace<GpuMesh>(entity, GpuMesh(mesh));
// Remove Mesh resource as it is no longer needed.
registry().erase<entt::resource<Mesh>>(entity);
}
// Convert materials
auto material_view = registry().view<entt::resource<Material>>();
for (auto [entity, material] : material_view.each()) {
registry().emplace<GpuMaterial>(entity, GpuMaterial(material));
// Remove Material resource as it is no longer needed.
registry().erase<entt::resource<Material>>(entity);
}
// Spawn default lights
auto directional_light = registry().create();
registry().emplace<Name>(directional_light, "Directional Light");
@@ -53,13 +40,24 @@ Controller::Controller()
registry().emplace<GlobalTransform>(point_light, GlobalTransform{});
registry().emplace<PointLight>(point_light,
PointLight{.intensity = PointLight::DEFAULT_INTENSITY});
// Spawn default camera
auto camera_view = registry().view<Camera const>();
if (camera_view.empty()) {
auto entity = registry().create();
registry().emplace<Name>(entity, "Camera");
registry().emplace<Transform>(entity, Transform{.translation = glm::vec3(0.0, 0.25, -1.0)});
registry().emplace<GlobalTransform>(entity, GlobalTransform{});
registry().emplace<Camera>(entity, Camera{.projection = Camera::Perspective{}});
registry().emplace<Flycam>(entity);
}
}
void Controller::update()
{
Camera::keyboard_movement(registry());
Flycam::keyboard_movement(registry());
if (registry().ctx().get<Window::MouseCatched>().catched) {
Camera::mouse_orientation(registry());
Flycam::mouse_orientation(registry());
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "core/application.h"
#include <entt/entt.hpp>
#include <glm/glm.hpp>
class Controller : public FeverCore::Application
{
public:
Controller(std::string_view path);
void update() override;
};

View File

@@ -0,0 +1,98 @@
#include "flycam.h"
#include "core/camera.h"
#include "core/time.h"
#include "input/input.h"
#include <GLFW/glfw3.h>
#include <algorithm>
#include <chrono>
#include <spdlog/spdlog.h>
void Flycam::keyboard_movement(entt::registry& registry)
{
struct KeyboardMovementContext
{
bool accelerate{};
};
auto& movement_context = registry.ctx().emplace<KeyboardMovementContext>();
auto const& key_state = registry.ctx().get<Input::State<Input::KeyCode>>();
auto const& delta_time = registry.ctx().get<Time::Delta>();
auto camera_view =
registry.view<Flycam const, Camera const, Transform, GlobalTransform const>();
auto camera_entity = camera_view.front();
if (camera_entity == entt::null) {
spdlog::debug("No camera entity found");
return;
}
auto [camera, camera_transform, camera_global_transform] = camera_view.get(camera_entity);
glm::vec3 front_vec = Camera::front_vector(camera_global_transform);
front_vec.y = 0;
glm::vec3 delta_pos = glm::vec3(0., 0., 0.);
float acceleration = movement_context.accelerate ? ACCELERATION : 1.0F;
float delta_factor = static_cast<float>(delta_time.delta.count()) * SPEED * acceleration;
movement_context.accelerate = false;
if (key_state.pressed(Input::KeyCode{GLFW_KEY_W})) {
delta_pos += delta_factor * glm::normalize(front_vec);
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_S})) {
delta_pos -= delta_factor * glm::normalize(front_vec);
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_A})) {
delta_pos -= delta_factor * glm::normalize(glm::cross(front_vec, Camera::UP_VECTOR));
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_D})) {
delta_pos += delta_factor * glm::normalize(glm::cross(front_vec, Camera::UP_VECTOR));
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_SPACE})) {
delta_pos += delta_factor * Camera::UP_VECTOR;
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_LEFT_SHIFT})) {
delta_pos -= delta_factor * Camera::UP_VECTOR;
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_LEFT_ALT})) {
movement_context.accelerate = true;
}
camera_transform.translation += delta_pos;
}
void Flycam::mouse_orientation(entt::registry& registry)
{
auto camera_view = registry.view<Flycam const, Camera, Transform>();
auto camera_entity = camera_view.front();
if (camera_entity == entt::null) {
spdlog::debug("No camera entity found");
return;
}
auto [camera, camera_transform] = camera_view.get(camera_entity);
auto const& mouse_cursor_input = registry.ctx().get<Input::MouseMotion>();
auto delta_x = mouse_cursor_input.delta.x;
auto delta_y = mouse_cursor_input.delta.y;
auto pitch = static_cast<float>(-delta_y);
auto yaw = static_cast<float>(delta_x);
// 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));
}

12
apps/fall-fever/flycam.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <entt/entt.hpp>
struct Flycam
{
static constexpr float SPEED = 0.5;
static constexpr float ACCELERATION = 5.0;
static void keyboard_movement(entt::registry& registry);
static void mouse_orientation(entt::registry& registry);
};

49
apps/fall-fever/main.cpp Normal file
View File

@@ -0,0 +1,49 @@
#include "controller.h"
#include "util/log.h"
#include <GLFW/glfw3.h>
#include <cxxopts.hpp>
#include <iostream>
#include <spdlog/spdlog.h>
auto main(int argc, char* argv[]) -> int
{
Log::initialize();
cxxopts::Options options("Fall-Fever", "A brief description");
// clang-format off
options.add_options()
("model", "Model file to load", cxxopts::value<std::string>())
("h,help", "Print usage")
;
// clang-format on
options.parse_positional({"model"});
auto result = options.parse(argc, argv);
if (result.count("help")) {
std::cout << options.help() << std::endl;
exit(0);
}
std::string model;
if (result.count("model"))
model = result["model"].as<std::string>();
// Initialize GLFW
if (glfwInit() == 0) {
spdlog::critical("Could not initialize GLFW");
return -1;
}
{
// Create controller
Controller controller(model);
controller.run();
}
glfwTerminate();
return 0;
}

View File

@@ -1,42 +0,0 @@
add_library(fever_engine
components/transform.cpp
core/graphics/framebuffer.cpp
core/graphics/image.cpp
core/graphics/material.cpp
core/graphics/mesh.cpp
core/camera.cpp
core/game_loop.cpp
core/glad.cpp
core/light.cpp
core/render.cpp
core/shader.cpp
core/time.cpp
input/input.cpp
scene/gltf.cpp
scene/gltf_loader.cpp
util/log.cpp
window/window.cpp
)
target_compile_features(fever_engine PUBLIC cxx_std_20)
target_include_directories(fever_engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(fever_engine PRIVATE SPDLOG_FMT_EXTERNAL)
target_link_libraries(
fever_engine PUBLIC
glad
glfw
EnTT::EnTT
fmt
pthread
spdlog
fx-gltf::fx-gltf
stb
)
add_executable(Fall-Fever
bin/main.cpp
bin/controller.cpp
)
target_link_libraries(Fall-Fever PRIVATE fever_engine)

View File

@@ -1,16 +0,0 @@
#pragma once
#include "core/game_loop.h"
#include <entt/entt.hpp>
#include <glm/glm.hpp>
#include <memory>
#include <unordered_map>
#include <vector>
class Controller : public GameLoop
{
public:
Controller();
void update() override;
};

View File

@@ -1,26 +0,0 @@
#include "controller.h"
#include "util/log.h"
#include <GLFW/glfw3.h>
#include <iostream>
#include <spdlog/spdlog.h>
auto main() -> int
{
Log::initialize();
// Initialize GLFW
if (glfwInit() == 0) {
spdlog::critical("Could not initialize GLFW");
return -1;
}
{
// Create controller
Controller controller;
controller.run();
}
glfwTerminate();
return 0;
}

View File

@@ -2,6 +2,8 @@
#include <entt/entt.hpp>
#include <glm/glm.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/quaternion.hpp>
struct Transform

View File

@@ -1,29 +1,25 @@
#include "game_loop.h"
#include "application.h"
#include "core/camera.h"
#include "core/light.h"
#include "core/render.h"
#include "core/shader.h"
#include "core/time.h"
#include "input/input.h"
#include "scene/scene.h"
#include "window/window.h"
#include <GLFW/glfw3.h>
#include <array>
#include <chrono>
#include <filesystem>
#include <fx/gltf.h>
#include <glad/gl.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include <spdlog/spdlog.h>
#include <thread>
#include <utility>
GameLoop::~GameLoop() = default;
namespace FeverCore {
GameLoop::GameLoop() :
Application::~Application() = default;
Application::Application() :
game_window(std::make_shared<Window>(event_dispatcher)),
post_processing_framebuffer(game_window->physical_dimensions()),
key_listener{.registry = entt_registry},
@@ -38,13 +34,13 @@ GameLoop::GameLoop() :
{
register_context_variables();
event_dispatcher.sink<Window::ResizeEvent>().connect<&GameLoop::recreate_framebuffer>(this);
event_dispatcher.sink<Window::ResizeEvent>().connect<&Application::recreate_framebuffer>(this);
event_dispatcher.sink<Input::KeyInput>().connect<&Input::KeyListener::key_event>(key_listener);
event_dispatcher.sink<Input::MouseMotion>().connect<&Input::CursorListener::cursor_event>(
cursor_listener);
}
void GameLoop::run()
void Application::run()
{
entt::hashed_string shader_hash(Material::SHADER_NAME.data());
auto standard_material_shader =
@@ -70,7 +66,7 @@ void GameLoop::run()
GlobalTransform::update(entt_registry);
Camera::aspect_ratio_update(entt_registry);
update();
this->update();
Input::State<Input::KeyCode>::update_state(entt_registry);
Input::reset_mouse_motion(entt_registry);
@@ -91,14 +87,16 @@ void GameLoop::run()
}
}
void GameLoop::register_context_variables()
void Application::register_context_variables()
{
entt_registry.ctx().emplace<Input::State<Input::KeyCode>>();
entt_registry.ctx().emplace<Input::MouseMotion>();
}
void GameLoop::recreate_framebuffer()
void Application::recreate_framebuffer()
{
auto dimensions = game_window->physical_dimensions();
post_processing_framebuffer = Framebuffer(dimensions);
}
} // namespace FeverCore

View File

@@ -10,22 +10,22 @@
#include <entt/entt.hpp>
#include <glm/glm.hpp>
#include <memory>
#include <unordered_map>
#include <vector>
class Camera;
class Window;
class GameLoop
namespace FeverCore {
class Application
{
public:
GameLoop();
Application();
virtual ~GameLoop();
GameLoop(GameLoop const&) = delete;
GameLoop(GameLoop&&) = delete;
auto operator=(GameLoop const&) -> GameLoop& = delete;
auto operator=(GameLoop&&) -> GameLoop& = delete;
virtual ~Application();
Application(Application const&) = delete;
Application(Application&&) = delete;
auto operator=(Application const&) -> Application& = delete;
auto operator=(Application&&) -> Application& = delete;
auto registry() -> entt::registry& { return entt_registry; }
auto registry() const -> entt::registry const& { return entt_registry; }
@@ -62,4 +62,6 @@ protected:
GltfLoader gltf_loader;
entt::resource_cache<Gltf, GltfLoader> gltf_cache;
};
};
} // namespace FeverCore

View File

@@ -1,10 +1,7 @@
#include "camera.h"
#include "core/time.h"
#include "input/input.h"
#include "window/window.h"
#include <GLFW/glfw3.h>
#include <algorithm>
#include <glm/gtc/matrix_transform.hpp>
#include <spdlog/spdlog.h>
@@ -33,108 +30,15 @@ auto Camera::front_vector(GlobalTransform const& transform) -> glm::vec3
return glm::normalize(transform.transform * glm::vec4(0.0, 0.0, 1.0, 0.0));
}
void Camera::keyboard_movement(entt::registry& registry)
{
struct KeyboardMovementContext
{
bool accelerate{};
};
auto& movement_context = registry.ctx().emplace<KeyboardMovementContext>();
auto const& key_state = registry.ctx().get<Input::State<Input::KeyCode>>();
auto const& delta_time = registry.ctx().get<Time::Delta>();
auto camera_view = registry.view<Camera const, Transform, GlobalTransform const>();
auto camera_entity = camera_view.front();
if (camera_entity == entt::null) {
spdlog::debug("No camera entity found");
return;
}
auto [camera, camera_transform, camera_global_transform] = camera_view.get(camera_entity);
glm::vec3 front_vec = front_vector(camera_global_transform);
front_vec.y = 0;
glm::vec3 delta_pos = glm::vec3(0., 0., 0.);
float acceleration = movement_context.accelerate ? ACCELERATION : 1.0F;
float delta_factor = static_cast<float>(delta_time.delta.count()) * SPEED * acceleration;
movement_context.accelerate = false;
if (key_state.pressed(Input::KeyCode{GLFW_KEY_W})) {
delta_pos += delta_factor * glm::normalize(front_vec);
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_S})) {
delta_pos -= delta_factor * glm::normalize(front_vec);
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_A})) {
delta_pos -= delta_factor * glm::normalize(glm::cross(front_vec, Camera::UP_VECTOR));
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_D})) {
delta_pos += delta_factor * glm::normalize(glm::cross(front_vec, Camera::UP_VECTOR));
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_SPACE})) {
delta_pos += delta_factor * UP_VECTOR;
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_LEFT_SHIFT})) {
delta_pos -= delta_factor * UP_VECTOR;
}
if (key_state.pressed(Input::KeyCode{GLFW_KEY_LEFT_ALT})) {
movement_context.accelerate = true;
}
camera_transform.translation += delta_pos;
}
void Camera::mouse_orientation(entt::registry& registry)
{
auto camera_view = registry.view<Camera, Transform>();
auto camera_entity = camera_view.front();
if (camera_entity == entt::null) {
spdlog::debug("No camera entity found");
return;
}
auto [camera, camera_transform] = camera_view.get(camera_entity);
auto const& mouse_cursor_input = registry.ctx().get<Input::MouseMotion>();
auto delta_x = mouse_cursor_input.delta.x;
auto delta_y = mouse_cursor_input.delta.y;
auto pitch = static_cast<float>(-delta_y);
auto yaw = static_cast<float>(delta_x);
// Orthographic projection currently unsupported
auto& camera_perspective = std::get<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));
}
void Camera::aspect_ratio_update(entt::registry& registry)
{
float aspect_ratio = registry.ctx().get<Window::Descriptor>().aspect_ratio;
auto camera_view = registry.view<Camera>();
auto camera_entity = camera_view.front();
if (camera_entity == entt::null) {
spdlog::debug("No camera entity found");
return;
for (auto [entity, camera] : camera_view.each()) {
// Orthographic projection currently unsupported
auto& camera_perspective = std::get<Perspective>(camera.projection);
camera_perspective.aspect_ratio = aspect_ratio;
}
auto [camera] = camera_view.get(camera_entity);
// Orthographic projection currently unsupported
auto& camera_perspective = std::get<Perspective>(camera.projection);
camera_perspective.aspect_ratio = aspect_ratio;
}

View File

@@ -2,7 +2,6 @@
#include "components/transform.h"
#include <chrono>
#include <entt/entt.hpp>
#include <glm/glm.hpp>
#include <variant>
@@ -15,11 +14,6 @@ struct Camera
static constexpr glm::vec3 UP_VECTOR = glm::vec3(0.0, 1.0, 0.0);
static constexpr float SPEED = 0.5;
static constexpr float ACCELERATION = 5.0;
static constexpr glm::vec3 DEFAULT_POSITION = glm::vec3(0.0, 0.25, -1.0);
struct Perspective
{
float fov = DEFAULT_FOV;

View File

@@ -128,7 +128,7 @@ void init_glad()
// Initialize GLAD
if (gladLoadGL(glfwGetProcAddress) == 0) {
spdlog::critical("Failed to initialize GLAD");
std::quick_exit(-1);
std::abort();
}
#ifndef NDEBUG

View File

@@ -1,6 +1,5 @@
#include "shader.h"
#include <fmt/format.h>
#include <fstream>
#include <glm/gtc/type_ptr.hpp>
#include <spdlog/spdlog.h>

View File

@@ -84,16 +84,6 @@ auto Gltf::spawn_scene(std::size_t index,
registry.get<Children>(scene_entity).children.push_back(node_entity);
}
auto camera_view = registry.view<Camera const>();
if (camera_view.empty()) {
// Spawn default camera
auto entity = registry.create();
registry.emplace<Name>(entity, "Camera");
registry.emplace<Transform>(entity, Transform{.translation = Camera::DEFAULT_POSITION});
registry.emplace<GlobalTransform>(entity, GlobalTransform{});
registry.emplace<Camera>(entity, Camera{.projection = Camera::Perspective{}});
}
return scene_entity;
}
@@ -113,12 +103,32 @@ auto Gltf::spawn_scene(std::string_view name,
return entt::null;
}
auto Gltf::spawn_default_scene(entt::registry& registry, entt::resource_cache<GltfNode>& node_cache)
-> entt::entity
auto Gltf::spawn_default_scene(entt::registry& registry,
entt::resource_cache<GltfNode>& node_cache) -> entt::entity
{
if (document.scene != -1) {
return spawn_scene(document.scene, registry, node_cache);
if (document.scene == -1) {
return entt::null;
}
return entt::null;
auto scene = spawn_scene(document.scene, registry, node_cache);
// Convert meshes
auto mesh_view = registry.view<entt::resource<Mesh>>();
for (auto [entity, mesh] : mesh_view.each()) {
registry.emplace<GpuMesh>(entity, GpuMesh(mesh));
// Remove Mesh resource as it is no longer needed.
registry.erase<entt::resource<Mesh>>(entity);
}
// Convert materials
auto material_view = registry.view<entt::resource<Material>>();
for (auto [entity, material] : material_view.each()) {
registry.emplace<GpuMaterial>(entity, GpuMaterial(material));
// Remove Material resource as it is no longer needed.
registry.erase<entt::resource<Material>>(entity);
}
return scene;
}

View File

@@ -78,7 +78,7 @@ static auto load_texture(fx::gltf::Texture const& texture,
std::istreambuf_iterator<char>(),
std::back_inserter(image_data));
entt::hashed_string const image_hash(image_path.c_str());
entt::hashed_string const image_hash(image_path.string().c_str());
return image_cache.load(image_hash, image_data, colorFormat).first->second;
}
@@ -389,103 +389,6 @@ auto GltfLoader::operator()(std::filesystem::path const& document_path) -> resul
nodes.push_back(node.second);
}
// // Load scenes
// std::vector<entt::resource<Scene>> scenes;
// for (auto const& gltf_scene : gltf.scenes) {
// // Get nodes by hash
// std::vector<entt::resource<GltfNode>> nodes;
// nodes.reserve(gltf_scene.nodes.size());
// for (auto node_id : gltf_scene.nodes) {
// auto const& node = gltf.nodes.at(node_id);
// entt::hashed_string node_hash(node.name.c_str());
// nodes.push_back(gltf_node_cache[node_hash]);
// }
// if (gltf_scene.name.empty()) {
// spdlog::warn("glTF scene has no name.");
// }
// // Spawn an entity for every node in scene
// for (auto const& node : nodes) {
// std::function<entt::entity(GltfNode const&, std::optional<entt::entity>)> spawn_node =
// [this, &spawn_node](GltfNode const& node, std::optional<entt::entity> parent) {
// auto entity = registry.create();
// registry.emplace<Name>(entity, node.name);
// registry.emplace<Transform>(entity, node.transform);
// registry.emplace<GlobalTransform>(entity, GlobalTransform{});
// if (parent.has_value()) {
// registry.emplace<Parent>(entity, Parent{.parent = parent.value()});
// }
// std::vector<entt::entity> child_entities;
// auto mesh = node.mesh;
// if (mesh.has_value()) {
// for (auto const& primitive : mesh.value()->primitives) {
// auto mesh_entity = registry.create();
// registry.emplace<Parent>(mesh_entity, Parent{.parent = entity});
// registry.emplace<Transform>(mesh_entity, Transform{});
// registry.emplace<GlobalTransform>(mesh_entity, GlobalTransform{});
// registry.emplace<entt::resource<Mesh>>(mesh_entity, primitive.mesh);
// registry.emplace<entt::resource<Material>>(mesh_entity,
// primitive.material);
// child_entities.push_back(mesh_entity);
// }
// }
// auto camera = node.camera;
// if (camera.has_value()) {
// auto perspective =
// std::get<fx::gltf::Camera::Perspective>(camera.value().projection);
// Camera::Perspective camera_perspective{.fov = perspective.yfov,
// .aspect_ratio =
// perspective.aspectRatio,
// .near = perspective.znear,
// .far = perspective.zfar};
// registry.emplace<Camera>(entity, Camera{.projection = camera_perspective});
// }
// // Spawn child nodes
// for (auto const& child : node.children) {
// auto child_entity = spawn_node(child, entity);
// child_entities.push_back(child_entity);
// }
// registry.emplace<Children>(entity, Children{.children = child_entities});
// return entity;
// };
// spawn_node(node, {});
// }
// auto camera_view = registry.view<Camera const>();
// if (camera_view.empty()) {
// // Spawn default camera
// auto entity = registry.create();
// registry.emplace<Name>(entity, "Camera");
// registry.emplace<Transform>(entity, Transform{.translation = Camera::DEFAULT_POSITION});
// registry.emplace<GlobalTransform>(entity, GlobalTransform{});
// registry.emplace<Camera>(entity, Camera{.projection = Camera::Perspective{}});
// }
// entt::hashed_string scene_hash(gltf_scene.name.c_str());
// entt::resource<Scene> scene_resource =
// scene_cache.load(scene_hash, Scene{}).first->second;
// scenes.push_back(scene_resource);
// }
// // Default scene
// auto default_scene = [&gltf, &scenes]() -> std::optional<entt::resource<Scene>> {
// if (gltf.scene != -1) {
// return scenes.at(gltf.scene);
// }
// return {};
// }();
return std::make_shared<Gltf>(Gltf{.materials = std::move(materials),
.meshes = std::move(gltf_meshes),
.nodes = std::move(nodes),

View File

@@ -42,6 +42,12 @@ Window::Window(entt::dispatcher& event_dispatcher) : event_dispatcher(event_disp
glfwSetFramebufferSizeCallback(glfw_window.get(), framebuffer_size_callback);
init_glad();
{
int width, height;
glfwGetFramebufferSize(glfw_window.get(), &width, &height);
glViewport(0, 0, width, height);
}
}
void Window::glfw_error_callback(int error, char const* description)
@@ -107,17 +113,7 @@ auto Window::physical_dimensions() const -> glm::u32vec2
void Window::mouse_catching(entt::registry& registry) const
{
if (!registry.ctx().contains<MouseCatched>()) {
bool catched = true;
#ifndef NDEBUG
catched = false;
#endif
registry.ctx().emplace<MouseCatched>(MouseCatched{.catched = catched});
}
auto& mouse_catched = registry.ctx().get<MouseCatched>();
auto& mouse_catched = registry.ctx().emplace<MouseCatched>(MouseCatched{.catched = false});
auto const& key_state = registry.ctx().get<Input::State<Input::KeyCode>>();
if (key_state.just_pressed(Input::KeyCode{GLFW_KEY_LEFT_CONTROL})) {

23
vcpkg.json Normal file
View File

@@ -0,0 +1,23 @@
{
"vcpkg-configuration": {
"overlay-ports": [
"./vcpkg"
]
},
"dependencies": [
"cxxopts",
"entt",
"fmt",
{
"name": "glfw3",
"features": [
"wayland"
]
},
"glm",
"nlohmann-json",
"spdlog",
"fx-gltf"
],
"builtin-baseline": "c14d62387153eaa2d720113542dbde2e9754ee71"
}

View File

@@ -0,0 +1,16 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO jessey-git/fx-gltf
REF v2.0.0
SHA512 0731732b5919a55045df2fe06bda6ea2a4d4d889556d738d0ade5acf39341a0748deb13bb130cbd6226146c70c2566ebfa67e6ac398157be00fefcf1f071a9bd
HEAD_REF main
)
vcpkg_configure_cmake(
SOURCE_PATH ${SOURCE_PATH}
PREFER_NINJA
OPTIONS
-DFX_GLTF_BUILD_TESTS=OFF
)
vcpkg_install_cmake()

7
vcpkg/fx-gltf/vcpkg.json Normal file
View File

@@ -0,0 +1,7 @@
{
"name": "fx-gltf",
"version": "2.0.0",
"description": "A C++ library for loading and saving glTF 2.0 files.",
"homepage": "https://github.com/jessey-git/fx-gltf",
"dependencies": []
}