aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2026-05-05 00:50:13 +0200
committerladevieq <ladevie.quentin@gmail.com>2026-05-05 00:50:49 +0200
commit37fdcb8a0f435c42f737252450626f2bd38bbd0f (patch)
tree7eeb45a2d2d08483409a04c74fbc74fb2bbcde9f
parent6818cbfe21beefc04e4a174d44a92159c34cead1 (diff)
Clean up around included files
-rw-r--r--include/aabb.hpp3
-rw-r--r--include/bvh.hpp5
-rw-r--r--include/camera.hpp2
-rw-r--r--include/gltf.hpp67
-rw-r--r--include/material.hpp15
-rw-r--r--include/mesh.hpp22
-rw-r--r--include/scene.hpp60
-rw-r--r--include/utils.hpp76
-rw-r--r--include/vec3.hpp2
-rw-r--r--include/vulkan-loader.hpp23
-rw-r--r--include/window.hpp89
-rw-r--r--src/bvh.cpp9
-rw-r--r--src/camera.cpp1
-rw-r--r--src/gltf.cpp542
-rw-r--r--src/mesh.cpp4
-rw-r--r--src/scene.cpp160
-rw-r--r--src/utils.cpp92
-rw-r--r--src/vec3.cpp19
-rw-r--r--src/vulkan-loader.cpp4
-rw-r--r--src/window.cpp113
20 files changed, 727 insertions, 581 deletions
diff --git a/include/aabb.hpp b/include/aabb.hpp
index adeb1fb..4e47a8f 100644
--- a/include/aabb.hpp
+++ b/include/aabb.hpp
@@ -1,8 +1,9 @@
#ifndef __AABB_HPP_
#define __AABB_HPP_
+#include <cstdint>
+
#include "vec3.hpp"
-#include "triangle.hpp"
class aabb {
public:
diff --git a/include/bvh.hpp b/include/bvh.hpp
index 2b66dcb..28a8554 100644
--- a/include/bvh.hpp
+++ b/include/bvh.hpp
@@ -1,10 +1,9 @@
#pragma once
-#include <vector>
+#include <cstdint>
-#include "aabb.hpp"
-// #include "sphere.hpp"
#include "triangle.hpp"
+#include "aabb.hpp"
struct bvh_node {
aabb bounding_box;
diff --git a/include/camera.hpp b/include/camera.hpp
index 5c1db61..ab81896 100644
--- a/include/camera.hpp
+++ b/include/camera.hpp
@@ -1,8 +1,6 @@
#ifndef __CAMERA_HPP_
#define __CAMERA_HPP_
-#include "vec3.hpp"
-
class camera {
public:
camera(
diff --git a/include/gltf.hpp b/include/gltf.hpp
index 1ccaf56..72d757c 100644
--- a/include/gltf.hpp
+++ b/include/gltf.hpp
@@ -3,59 +3,60 @@
#include <vector>
-#include <nlohmann/json.hpp>
-
-using json = nlohmann::json;
-
-#include "material.hpp"
+#include "utils.hpp"
+#include "handle.hpp"
#include "mesh.hpp"
+#include "material.hpp"
struct node {
- std::vector<node> children;
- Mesh* mesh = nullptr;
+ std::vector<uint32_t> children;
+ u32 mesh;
};
struct raw_image {
int32_t width;
int32_t height;
int32_t channels;
- uint8_t *data;
+ const uint8_t *data;
};
-namespace std::filesystem {
- class path;
-}
+struct buffer {
+ u8* bytes;
+ size_t size;
+};
class gltf {
public:
- gltf(const std::filesystem::path &filepath);
-
- node root_node;
-
-private:
-
- void load_node(uint32_t index, node &parent);
+ gltf(const char* filepath);
+ void deinit();
- void load_meshes();
+ std::vector<u32> root_nodes;
- Mesh::submesh load_primitive(const json &primitive);
-
- Mesh::attribute load_attribute(uint32_t accessor_index);
-
- void load_textures(const std::filesystem::path &path);
-
- void load_materials();
-
- json gltf_json;
+ std::vector<node> nodes;
std::vector<Mesh> meshes;
std::vector<material> materials;
-#ifdef API_TEST
std::vector<handle<device_texture>> textures;
// handle<device_sampler> samplers;
-#else
- std::vector<Texture*> textures;
-#endif // API_TEST
- std::vector<std::vector<uint8_t>> buffers;
+ std::vector<struct buffer> buffers;
+
+
+ // gbl only
+ struct glb_chunk {
+ u32 length;
+ u32 type;
+ u8 data[1];
+ };
+
+ struct glb_header {
+ u32 magic;
+ u32 version;
+ u32 length;
+ };
+ std::vector<struct glb_chunk*> chunks;
+ glb_header* header;
+
+ // TODO: remove
+ bool is_glb;
};
#endif
diff --git a/include/material.hpp b/include/material.hpp
index 35710d2..167e58e 100644
--- a/include/material.hpp
+++ b/include/material.hpp
@@ -1,24 +1,9 @@
#pragma once
-#include <cstdint>
-
-#include "vec3.hpp"
-
-#ifdef API_TEST
-#include "vk-device-types.hpp"
-#else
-class Texture;
-#endif
-
struct material {
color base_color;
-#ifdef API_TEST
handle<device_texture> base_color_texture;
handle<device_texture> metallic_roughness_texture;
-#else
- Texture* base_color_texture;
- Texture* metallic_roughness_texture;
-#endif // API_TEST
float metalness = 1.f;
float roughness = 1.f;
};
diff --git a/include/mesh.hpp b/include/mesh.hpp
index b88896d..c396814 100644
--- a/include/mesh.hpp
+++ b/include/mesh.hpp
@@ -1,15 +1,5 @@
#pragma once
-#include <cstdint>
-#include <vector>
-#include <array>
-
-#ifdef API_TEST
-#include "vk-device-types.hpp"
-#else
-#include "vk-renderer.hpp"
-#endif // API_TEST
-
enum ATTRIBUTE_TYPE {
POSITION,
NORMAL,
@@ -34,15 +24,15 @@ public:
};
struct attribute {
- uint8_t* data = nullptr;
+ const uint8_t* data = nullptr;
size_t length = 0;
};
struct submesh {
attribute indices;
std::array<attribute, ATTRIBUTE_TYPE::MAX_ATTRIBUTE> attributes;
- uint32_t vertex_count = 0;
- uint32_t index_count = 0;
+ u32 vertex_count = 0;
+ u32 index_count = 0;
// material& material;
};
@@ -93,15 +83,9 @@ private:
std::vector<submesh_info> submeshes;
struct gpu_mesh {
-#ifdef API_TEST
std::array<handle<device_buffer>, ATTRIBUTE_TYPE::MAX_ATTRIBUTE> attributes;
const device_buffer& indices;
const device_buffer& submeshes;
-#else
- std::array<Buffer*, ATTRIBUTE_TYPE::MAX_ATTRIBUTE> attributes;
- Buffer* indices;
- Buffer* submeshes;
-#endif // API_TEST
};
// allocate gpu mesh upon instanciation
diff --git a/include/scene.hpp b/include/scene.hpp
index 091e4fc..a1c76e2 100644
--- a/include/scene.hpp
+++ b/include/scene.hpp
@@ -1,44 +1,36 @@
#ifndef __SCENE_HPP_
#define __SCENE_HPP_
-#include <cstdint>
-
-#ifdef API_TEST
-#include "vk-device-types.hpp"
-#include "vk-device.hpp"
-#endif // API_TEST
-#include "camera.hpp"
-
class Buffer;
-class scene {
- struct metadata {
- camera cam;
+struct metadata {
+ camera cam;
- uint32_t max_bounce = 3;
- uint32_t min_bounce = 1;
+ uint32_t max_bounce = 3;
+ uint32_t min_bounce = 1;
- uint32_t width;
- uint32_t height;
+ uint32_t width;
+ uint32_t height;
- uint32_t sample_index = 0;
+ uint32_t sample_index = 1;
- uint32_t enable_dof = (uint32_t)false;
- uint32_t debug_bvh = (uint32_t)false;
- int32_t downscale_factor = 2;
+ uint32_t enable_dof = (uint32_t)false;
+ uint32_t debug_bvh = (uint32_t)false;
+ int32_t downscale_factor = 1;
- metadata(const camera &cam, uint32_t width, uint32_t height);
- };
+ metadata(const camera &cam, uint32_t width, uint32_t height);
+};
+class scene {
// void random_scene();
+ gltf model;
public:
scene(const camera& cam, uint32_t width, uint32_t height);
+ void deinit();
metadata meta;
-#ifdef API_TEST
- handle<device_buffer> scene_buffer_handle;
handle<device_buffer> indices_buffer_handle;
handle<device_buffer> positions_buffer_handle;
handle<device_buffer> normals_buffer_handle;
@@ -46,22 +38,12 @@ public:
handle<device_buffer> bvh_buffer_handle;
handle<device_buffer> materials_buffer_handle;
- uint64_t scene_buffer_address() { return vkdevice::get_render_device().get_buffer(scene_buffer_handle).device_address; };
- uint64_t indices_buffer_address() { return vkdevice::get_render_device().get_buffer(indices_buffer_handle).device_address; };
- uint64_t positions_buffer_address() { return vkdevice::get_render_device().get_buffer(positions_buffer_handle).device_address; };
- uint64_t normals_buffer_address() { return vkdevice::get_render_device().get_buffer(normals_buffer_handle).device_address; };
- uint64_t uvs_buffer_address() { return vkdevice::get_render_device().get_buffer(uvs_buffer_handle).device_address; };
- uint64_t bvh_buffer_address() { return vkdevice::get_render_device().get_buffer(bvh_buffer_handle).device_address; };
- uint64_t materials_buffer_address() { return vkdevice::get_render_device().get_buffer(materials_buffer_handle).device_address; };
-#else
- Buffer* scene_buffer;
- Buffer* indices_buffer;
- Buffer* positions_buffer;
- Buffer* normals_buffer;
- Buffer* uvs_buffer;
- Buffer* bvh_buffer;
- Buffer* materials_buffer;
-#endif // API_TEST
+ uint64_t indices_buffer_address() { return vkdevice::get().get_buffer(indices_buffer_handle).device_address; };
+ uint64_t positions_buffer_address() { return vkdevice::get().get_buffer(positions_buffer_handle).device_address; };
+ uint64_t normals_buffer_address() { return vkdevice::get().get_buffer(normals_buffer_handle).device_address; };
+ uint64_t uvs_buffer_address() { return vkdevice::get().get_buffer(uvs_buffer_handle).device_address; };
+ uint64_t bvh_buffer_address() { return vkdevice::get().get_buffer(bvh_buffer_handle).device_address; };
+ uint64_t materials_buffer_address() { return vkdevice::get().get_buffer(materials_buffer_handle).device_address; };
};
#endif // !__SCENE_HPP_
diff --git a/include/utils.hpp b/include/utils.hpp
index e49b218..19a5d9f 100644
--- a/include/utils.hpp
+++ b/include/utils.hpp
@@ -1,13 +1,56 @@
#pragma once
-#include <vector>
-#include <unordered_map>
+static constexpr size_t KB = 1024U;
+static constexpr size_t MB = 1024U * KB;
+static constexpr size_t GB = 1024U * MB;
+const char* DUMMY_NAME = "NO_NAME";
-std::vector<uint8_t> read_file(const char* path);
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+uint8_t* read_file(const char* path, size_t size);
+
+const uint32_t max_markers = 1024U;
+// hashmap ?
+uint32_t marker_count = 0U;
+const char* marker_names[max_markers] = { 0 };
+uint64_t marker_counter_start[max_markers] = { 0 };
+uint64_t marker_counter_end[max_markers] = { 0 };
+
+#define BEGIN_MARKER(name) \
+ static uint32_t marker_##name##_index = UINT32_MAX; \
+ do { \
+ if (marker_##name##_index == UINT32_MAX) { \
+ marker_##name##_index = marker_count++; \
+ marker_names[marker_##name##_index] = #name; \
+ } \
+ { \
+ LARGE_INTEGER start_qpc; \
+ QueryPerformanceCounter(&start_qpc); \
+ marker_counter_start[marker_##name##_index] = start_qpc.QuadPart; \
+ } \
+ } while(0);
+
+#define END_MARKER(name) \
+ do { \
+ LARGE_INTEGER end_qpc; \
+ QueryPerformanceCounter(&end_qpc); \
+ marker_counter_end[marker_##name##_index] = end_qpc.QuadPart; \
+ } while(0);
#define PI 3.14159265359
#define EPSILON 0.000001
+
+#define ALIGN(value, alignment) \
+ (((value) + ((alignment) - 1)) & ~((alignment) - 1))
+
inline float deg_to_rad(float deg) {
return static_cast<float>(deg * PI / 180.f);
}
@@ -31,31 +74,14 @@ inline float clamp(float x, float min, float max) {
}
-#if defined(WINDOWS)
-
-#include <windows.h>
+#if _WIN32
void log_last_error();
-class watcher {
-public:
- typedef void(*func)(void);
-
- static bool watch_file(const char* filepath, func callback);
-
- static bool watch_dir(const char* dir_path);
-
- static void pull_changes();
-
-private:
+typedef void(*func)(void);
+bool watch_file(const char* filepath, func callback);
- struct watch_data {
- HANDLE dir_handle;
- OVERLAPPED overlapped;
- DWORD buffer[512];
- };
+bool watch_dir(const char* dir_path);
- inline static std::unordered_map<const char*, func> callbacks;
- inline static std::unordered_map<const char*, watch_data> watched_dirs;
-};
+void pull_changes();
#endif
diff --git a/include/vec3.hpp b/include/vec3.hpp
index 42172e6..5fd143d 100644
--- a/include/vec3.hpp
+++ b/include/vec3.hpp
@@ -1,7 +1,6 @@
#ifndef __VEC3_HPP_
#define __VEC3_HPP_
-#include <xmmintrin.h>
#include <cstdint>
struct vec3u {
@@ -60,6 +59,7 @@ class vec3 {
vec3& normalize();
[[nodiscard]] bool near_zero() const;
+ [[nodiscard]] bool is_zero() const;
void print() const;
diff --git a/include/vulkan-loader.hpp b/include/vulkan-loader.hpp
index ec1464d..7a3a68e 100644
--- a/include/vulkan-loader.hpp
+++ b/include/vulkan-loader.hpp
@@ -3,8 +3,7 @@
#define VK_NO_PROTOTYPES
-#if defined(WINDOWS)
-#include <vulkan/vk_platform.h>
+#if _WIN32
#include <vulkan/vulkan_core.h>
typedef unsigned long DWORD;
typedef const wchar_t* LPCWSTR;
@@ -24,7 +23,6 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES;
X(vkGetInstanceProcAddr) \
X(vkGetDeviceProcAddr)
-
#define VULKAN_APPLICATION_FUNCTIONS \
X(vkCreateInstance) \
X(vkEnumerateInstanceVersion) \
@@ -154,32 +152,15 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES;
X(vkDestroyBuffer) \
X(vkDestroyRenderPass)
+
#define X(name) extern PFN_##name name;
- VULKAN_EXPORTED_FUNCTIONS
VULKAN_APPLICATION_FUNCTIONS
VULKAN_INSTANCE_FUNCTIONS
VULKAN_DEVICE_FUNCTIONS
#undef X
-
-#define X(name) void Load_##name();
- VULKAN_EXPORTED_FUNCTIONS
- VULKAN_APPLICATION_FUNCTIONS
-#undef X
-
-#define X(name) void Load_##name(VkInstance _instance);
- VULKAN_INSTANCE_FUNCTIONS
-#undef X
-
-#define X(name) void Load_##name(VkDevice _device);
- VULKAN_DEVICE_FUNCTIONS
-#undef X
-
-
void load_vulkan();
-
void load_instance_functions(VkInstance instance);
-
void load_device_functions(VkDevice device);
#endif // !__VULKAN_LOADER_HPP_
diff --git a/include/window.hpp b/include/window.hpp
index 2484742..9c79614 100644
--- a/include/window.hpp
+++ b/include/window.hpp
@@ -1,23 +1,10 @@
#ifndef __WINDOW_HPP_
#define __WINDOW_HPP_
-#include <vector>
-
-class vkrenderer;
-
#if defined(LINUX)
#include <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
-#elif defined(WINDOWS)
-// #include <Windows.h>
-typedef struct HWND__* HWND;
-typedef int64_t LRESULT;
-typedef int64_t LPARAM;
-typedef uint64_t WPARAM;
-typedef unsigned int UINT;
-typedef void* LPVOID;
-#define CALLBACK __stdcall
#endif
// enum MODIFIERS: uint32_t {
@@ -37,14 +24,22 @@ typedef void* LPVOID;
// };
// TODO improve this
-#if defined(WINDOWS)
-enum KEYS: uint32_t {
+#if _WIN32
+enum KEY: uint32_t {
LSHIFT = 0x10,
RSHIFT = 0x10,
LCTRL = 0x11,
RCTRL = 0x11,
ALT,
SPACE = 0x20,
+ PAGE_UP,
+ PAGE_DOWN,
+ END,
+ HOME,
+ LEFT_ARROW,
+ UP_ARROW,
+ RIGHT_ARROW,
+ DOWN_ARROW,
A = 0x41,
B,
C,
@@ -71,10 +66,22 @@ enum KEYS: uint32_t {
X,
Y,
Z,
- MAX_KEYS = 255
+ F1 = 0x70,
+ F2,
+ F3,
+ F4,
+ F5,
+ F6,
+ F7,
+ F8,
+ F9,
+ F10,
+ F11,
+ F12,
+ MAX_KEY = 0xff
};
#else
-enum KEYS: uint32_t {
+enum KEY: uint32_t {
SPACE = 32,
A = 0x61,
B,
@@ -108,25 +115,43 @@ enum KEYS: uint32_t {
RCTRL,
LALT = 65513,
RALT,
- MAX_KEYS = 0xffff
+ MAX_KEY = 0xffff
};
#endif
-enum BUTTONS: uint32_t {
+enum BUTTON: uint32_t {
LEFT,
RIGHT,
MIDDLE,
- MAX_BUTTONS = 255
+ MAX_BUTTON = 255
};
-enum EVENT_TYPES: int32_t {
+enum EVENT_TYPE: int32_t {
QUIT,
RESIZE,
KEY_PRESS,
+ KEY_DOWN,
KEY_RELEASE,
+ KEY_UP,
BUTTON_PRESS,
BUTTON_RELEASE,
- MOUSE_MOVE
+ MOUSE_MOVE,
+ MOUSE_WHEEL,
+};
+
+enum CURSOR_TYPE: int32_t {
+ ARROW,
+ TEXT_INPUT,
+ SIZE_ALL,
+ SIZE_NS,
+ SIZE_WE,
+ SIZE_NESW,
+ SIZE_NWSE,
+ HAND,
+ WAIT,
+ PROGRESS,
+ NOT_ALLOWED,
+ MAX_CURSOR,
};
// struct event {
@@ -148,10 +173,14 @@ struct event {
int32_t x;
int32_t y;
} position;
- KEYS key;
- BUTTONS button;
+ struct {
+ int32_t x;
+ int32_t y;
+ } delta;
+ KEY key;
+ BUTTON button;
} data;
- EVENT_TYPES type;
+ EVENT_TYPE type;
};
class window {
@@ -161,13 +190,15 @@ class window {
void poll_events();
-#if defined(WINDOWS)
+#if _WIN32
void message_loop();
LRESULT message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK window_procedure(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam);
+ static void set_cursor(enum CURSOR_TYPE type);
+
HWND handle {};
const char* window_class_name;
LPVOID main_fiber;
@@ -190,8 +221,10 @@ class window {
bool isOpen;
- bool keyboard[KEYS::MAX_KEYS] { false };
- bool mouse[BUTTONS::MAX_BUTTONS] { false };
+ bool keyboard[KEY::MAX_KEY] { false };
+ bool mouse[BUTTON::MAX_BUTTON] { false };
+
+ static HCURSOR cursors[CURSOR_TYPE::MAX_CURSOR];
};
#endif // !__WINDOW_HPP_
diff --git a/src/bvh.cpp b/src/bvh.cpp
index 8e62a93..9362504 100644
--- a/src/bvh.cpp
+++ b/src/bvh.cpp
@@ -1,11 +1,5 @@
#include "bvh.hpp"
-#include <cassert>
-
-#include <algorithm>
-#include <cstdint>
-#include <cstdio>
-
// bvh::bvh(std::vector<sphere>& spheres, std::vector<packed_bvh_node>& packed_nodes)
// :spheres(spheres) {
// packed_nodes.resize(2 * spheres.size() - 1);
@@ -48,6 +42,7 @@
bvh::bvh(std::vector<triangle>& triangles, std::vector<packed_bvh_node>& packed_nodes)
:triangles(triangles) {
+ BEGIN_MARKER(GENERATE_BVH);
assert(!triangles.empty());
packed_nodes.resize(2 * triangles.size() - 1);
@@ -84,6 +79,8 @@ bvh::bvh(std::vector<triangle>& triangles, std::vector<packed_bvh_node>& packed_
node.next_id = temp_nodes[old_node.next_id].df_id;
}
}
+
+ END_MARKER(GENERATE_BVH);
}
//-------------------------
diff --git a/src/camera.cpp b/src/camera.cpp
index 4c63630..8139c5b 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -1,5 +1,4 @@
#include "camera.hpp"
-#include "utils.hpp"
camera::camera(
point3 position,
diff --git a/src/gltf.cpp b/src/gltf.cpp
index 4cdfdce..2ddf16a 100644
--- a/src/gltf.cpp
+++ b/src/gltf.cpp
@@ -1,145 +1,177 @@
#include "gltf.hpp"
-#include <execution>
-#include <fstream>
+using namespace simdjson;
-#ifndef API_TEST
-#define STB_IMAGE_IMPLEMENTATION
-#endif
-#include <stb_image.h>
+ondemand::object root;
-#include "utils.hpp"
-#ifdef API_TEST
-#include "vk-device-types.hpp"
-#include "vk-device.hpp"
-#include "vk-command-buffer.hpp"
-#include <vk_mem_alloc.h>
-#else
-#include "vk-renderer.hpp"
-#endif
+struct accessor {
+ u32 view_index = 0U;
+ u32 count = 0U;
+ u32 component_type = 0U;
+ std::string_view type;
+};
-gltf::gltf(const std::filesystem::path& filepath) {
- auto parent_path = filepath.parent_path();
- std::fstream f{ filepath };
+struct buffer_view {
+ u32 buffer_index = 0U;
+ u32 length = 0U;
+ u32 offset = 0U;
+};
- if (!f.is_open()) {
- OutputDebugStringA("failed to open!");
- }
-
- f >> gltf_json;
+// component types
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
- auto& scene = gltf_json["scenes"][0];
+#define SCALAR 0x5343414C4152
+#define VEC2 0x56454332
+#define VEC3 0x56454333
+#define VEC4 0x56454334
- auto& gltf_buffers = gltf_json["buffers"];
- auto buffer_count = gltf_buffers.size();
- buffers.resize(gltf_buffers.size());
- for (auto buffer_index{ 0U }; buffer_index < buffer_count; buffer_index++) {
- auto buffer_path = parent_path / gltf_buffers[buffer_index]["uri"].get<std::string>();
- buffers[buffer_index] = read_file(buffer_path.string().c_str());
+static u32 accessor_type_to_component_count(std::string_view& type) {
+ if (strncmp("SCALAR", type.data(), type.size()) == 0) {
+ return 1U;
+ } else if (strncmp("VEC2", type.data(), type.size()) == 0) {
+ return 2U;
+ } else if (strncmp("VEC3", type.data(), type.size()) == 0) {
+ return 3U;
+ } else if (strncmp("VEC4", type.data(), type.size()) == 0) {
+ return 4U;
}
+ assert(false);
+ return 0U;
+}
- load_textures(parent_path);
- load_materials();
-
- load_meshes();
-
- auto& root_children = scene["nodes"];
- size_t root_children_count = scene["nodes"].size();
- root_node.children.resize(root_children_count);
-
- for (size_t child_index = 0; child_index < root_children_count; child_index++) {
- load_node(root_children[child_index].get<uint32_t>(), root_node.children[child_index]);
+static u32 component_type_size(u32 type) {
+ switch (type) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ return 1U;
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ return 2U;
+ case GL_FLOAT:
+ case GL_FIXED:
+ return 4U;
+ default: assert(false);
}
-
- f.close();
+ return 0U;
}
-void gltf::load_node(uint32_t index, node& parent) {
- const auto& gltf_node = gltf_json["nodes"][index];
+static Mesh::submesh load_primitive(ondemand::object& primitive, std::vector<struct buffer>& buffers, std::vector<struct accessor>& accessors, std::vector<struct buffer_view>& buffer_views) {
+ Mesh::submesh submesh;
+
+ // indices
+ {
+ u32 indices_id = primitive["indices"].get_uint32();
+ struct accessor& accessor = accessors[indices_id];
- if (gltf_node.contains("children")) {
- const auto& children = gltf_node["children"];
- uint32_t children_count = gltf_node["children"];
- parent.children.resize(children_count);
+ struct buffer_view& view = buffer_views[accessor.view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- for (size_t child_index = 0; child_index < children_count; child_index++) {
- load_node(children[child_index].get<uint32_t>(), parent.children[child_index]);
- }
- }
+ submesh.indices = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
- if (gltf_node.contains("mesh")) {
- parent.mesh = &meshes[gltf_node["mesh"].get<uint32_t>()];
+ submesh.index_count = accessor.count;
}
-}
-void gltf::load_meshes() {
- const auto& gltf_meshes = gltf_json["meshes"];
- auto meshes_count = gltf_meshes.size();
- meshes.resize(meshes_count);
+ // positions
+ {
+ u32 pos_id = primitive["attributes"]["POSITION"].get_uint32();
+ struct accessor& accessor = accessors[pos_id];
- for (size_t mesh_index = 0; mesh_index < meshes_count; mesh_index++) {
- auto& mesh = meshes[mesh_index];
- const auto& primitives = gltf_meshes[mesh_index]["primitives"];
+ struct buffer_view& view = buffer_views[accessor.view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- for (const auto& primitive : primitives) {
- auto& material = materials[primitive["material"].get<uint32_t>()];
- mesh.add_submesh(load_primitive(primitive), material);
- }
+ submesh.attributes[ATTRIBUTE_TYPE::POSITION] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
- Mesh::register_mesh(mesh);
+ submesh.vertex_count = accessor.count;
}
-}
-Mesh::submesh gltf::load_primitive(const json& primitive) {
- Mesh::submesh submesh;
+ u32 normal_index = 0U;
+ if (!primitive["attributes"]["NORMAL"].get(normal_index)) {
+ struct accessor& accessor = accessors[normal_index];
+ u32 view_index = accessor.view_index;
- submesh.indices = load_attribute(primitive["indices"]);
- submesh.attributes[ATTRIBUTE_TYPE::POSITION] = load_attribute(primitive["attributes"]["POSITION"]);
+ struct buffer_view& view = buffer_views[view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- if (primitive["attributes"].contains("NORMAL")) {
- submesh.attributes[ATTRIBUTE_TYPE::NORMAL] = load_attribute(primitive["attributes"]["NORMAL"]);
+ submesh.attributes[ATTRIBUTE_TYPE::NORMAL] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
}
- if (primitive["attributes"].contains("TEXCOORD_0")) {
- submesh.attributes[ATTRIBUTE_TYPE::UV_0] = load_attribute(primitive["attributes"]["TEXCOORD_0"]);
- }
+ u32 texcoord_index = 0U;
+ if (!primitive["attributes"]["TEXCOORD_0"].get(texcoord_index)) {
+ struct accessor& accessor = accessors[texcoord_index];
+ u32 view_index = accessor.view_index;
- submesh.index_count = gltf_json["accessors"][primitive["indices"].get<uint32_t>()]["count"].get<uint32_t>();
- submesh.vertex_count = gltf_json["accessors"][primitive["attributes"]["POSITION"].get<uint32_t>()]["count"].get<uint32_t>();
+ struct buffer_view& view = buffer_views[view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
+
+ submesh.attributes[ATTRIBUTE_TYPE::UV_0] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
+ }
return submesh;
}
-Mesh::attribute gltf::load_attribute(uint32_t accessor_index) {
- auto view_index = gltf_json["accessors"][accessor_index]["bufferView"].get<uint32_t>();
- const auto& view = gltf_json["bufferViews"][view_index];
- auto offset = view["byteOffset"].get<off_t>();
- auto& buffer = buffers[view["buffer"].get<uint32_t>()];
+static void load_textures(char* path, std::vector<handle<device_texture>>& textures, std::vector<struct buffer>& buffers, std::vector<struct buffer_view>& buffer_views, bool is_glb) {
+ ondemand::array gltf_images = root["images"];
+ std::vector<raw_image> images(gltf_images.count_elements());
+ size_t path_len = strlen(path);
+ char path_buffer[2048] = { 0U };
+ strncpy(path_buffer, path, path_len);
+ BEGIN_MARKER(LOAD_TEXTURES);
+ u32 image_index = 0U;
+ for (ondemand::object gltf_image : gltf_images) {
+ if (is_glb) {
+ // TODO: consider mimeType
+ struct buffer_view& view = buffer_views[gltf_image["bufferView"]];
+ struct buffer& buffer = buffers[view.buffer_index];
- return {
- &buffer[offset],
- view["byteLength"].get<size_t>()
- };
-}
+ raw_image& image = images[image_index++];
-void gltf::load_textures(const std::filesystem::path& path) {
- const auto& gltf_images = gltf_json["images"];
- auto images_count = gltf_images.size();
- std::vector<raw_image> images{ images_count };
+ image.data = stbi_load_from_memory(&buffer.bytes[view.offset], view.length, &image.width, &image.height, &image.channels, 4);
- std::vector<size_t> v(images_count);
- std::iota(v.begin(), v.end(), 0);
+ } else {
+ std::string_view uri_view = gltf_image["uri"];
+ strncpy(path_buffer + path_len, uri_view.data(), uri_view.length());
+ path_buffer[path_len + uri_view.length()] = '\0';
- const auto& gltf_textures = gltf_json["textures"];
- auto textures_count = gltf_textures.size();
- textures.resize(textures_count);
+ raw_image& image = images[image_index++];
+ image.data = stbi_load(path_buffer, &image.width, &image.height, &image.channels, 4);
+ }
+ }
+ END_MARKER(LOAD_TEXTURES);
-#ifdef API_TEST
- auto& device = vkdevice::get_render_device();
+ // ondemand::array gltf_samplers = root["samplers"];
+ // std::vector<handle<device_sampler>> samplers(gltf_samplers.count_elements());
+
+ // auto sampler = device.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
+ // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
+ // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
+ // }
+
+ vkdevice& device = vkdevice::get();
constexpr auto buffers_count = 2U;
- auto total_size = images_count * 4096U * 4096 * sizeof(uint32_t);
- auto buffer_size = total_size / 32U;
+ auto total_size = images.size() * 4096U * 4096 * sizeof(uint32_t);
+ // TODO: Fix nasty stuff going on
+ // Crash on buffer destruction
+ // Load wrong images
+ // auto buffer_size = total_size / 32U;
+ auto buffer_size = total_size / 2U;
handle<device_buffer> staging_buffers_handle[buffers_count] = {
device.create_buffer({
@@ -156,46 +188,28 @@ void gltf::load_textures(const std::filesystem::path& path) {
}),
};
+ // TODO: Create a proper upload heap
+ BEGIN_MARKER(UPLOAD_TEXTURES);
graphics_command_buffer command_buffers[buffers_count];
device.allocate_command_buffers(command_buffers, buffers_count, QueueType::GRAPHICS, "upload_buffer");
auto buffer_index = 0U;
auto command_buffer = command_buffers[buffer_index];
auto buffer_handle = staging_buffers_handle[buffer_index];
- auto buffer = device.get_buffer(buffer_handle);
+ device_buffer& buffer = device.get_buffer(buffer_handle);
command_buffer.start();
-#endif // API_TEST
-
- std::for_each(std::execution::par, v.begin(), v.end(), [&](const size_t image_index) {
- const auto& gltf_image = gltf_images[image_index];
- auto filepath = (path / gltf_image["uri"].get<std::string>()).string();
- auto& image = images[image_index];
- image.data = stbi_load(filepath.c_str(), &image.width, &image.height, &image.channels, 4);
- });
-
- // const auto &gltf_samplers = gltf_json["samplers"];
- // auto samplers_count = gltf_samplers.size();
- // std::vector<Sampler *> samplers{samplers_count};
-
-#ifdef API_TEST
- const auto &gltf_samplers = gltf_json["samplers"];
- auto samplers_count = gltf_samplers.size();
- std::vector<handle<device_sampler>> samplers{samplers_count};
-
- // auto sampler = device.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
- // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // }
- for (size_t texture_index = 0; texture_index < textures_count; texture_index++) {
- auto gltf_texture = gltf_textures[texture_index];
- auto& image = images[gltf_texture["source"].get<uint32_t>()];
+ ondemand::array gltf_textures = root["textures"];
+ textures.resize(gltf_textures.count_elements());
+ u32 texture_index = 0U;
+ for (ondemand::object gltf_texture: gltf_textures) {
+ raw_image& image = images[gltf_texture["source"]];
// if (gltf_texture.contains("sampler")) {
- // auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
+ // u32 sampler_index = gltf_texture["sampler"].get_uint32();
// sampler = samplers[sampler_index];
// }
- auto texture = device.create_texture({
+ handle<device_texture> texture = device.create_texture({
.width = static_cast<uint32_t>(image.width),
.height = static_cast<uint32_t>(image.height),
.usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
@@ -203,105 +217,247 @@ void gltf::load_textures(const std::filesystem::path& path) {
.type = VK_IMAGE_TYPE_2D,
});
- uint64_t size = image.width * image.height * sizeof(uint32_t);
- auto offset = buffer.offset;
- if (offset + size > buffer_size) {
+ u32 size = image.width * image.height * sizeof(uint32_t);
+ if (buffer.allocated_size + size > buffer.size) {
command_buffer.stop();
- device.submit(&command_buffer, 1 );
+ device.submit(&command_buffer, 1);
- buffer_index = (++buffer_index) % buffers_count;
+ buffer_index = (buffer_index + 1U) % buffers_count;
command_buffer = command_buffers[buffer_index];
buffer_handle = staging_buffers_handle[buffer_index];
buffer = device.get_buffer(buffer_handle);
buffer.reset();
- device.wait();
+ // TODO: Remove the wait
+ // device.wait();
command_buffer.start();
- offset = 0U;
}
- void* ptr = buffer.allocate(size);
- memcpy(ptr, image.data, size);
+ memcpy(buffer.allocate(size), image.data, size);
command_buffer.barrier(texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- command_buffer.copy(buffer_handle, texture, static_cast<VkDeviceSize>(offset));
+ command_buffer.copy(buffer_handle, texture, static_cast<VkDeviceSize>(buffer.offset));
command_buffer.barrier(texture, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
- textures[texture_index] = texture;
+ textures[texture_index++] = texture;
}
- command_buffer.stop();
- device.submit(&command_buffer, 1);
+ if (buffer.allocated_size > 0U) {
+ command_buffer.stop();
+ device.submit(&command_buffer, 1);
+ }
device.wait();
device.destroy_buffer(staging_buffers_handle[0]);
device.destroy_buffer(staging_buffers_handle[1]);
-#else
- Sampler* sampler = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
- // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // }
+ END_MARKER(UPLOAD_TEXTURES);
+}
- for (size_t texture_index = 0; texture_index < textures_count; texture_index++) {
- auto gltf_texture = gltf_textures[texture_index];
+static void load_materials(std::vector<material>& materials, std::vector<handle<device_texture>>& textures) {
+ ondemand::array gltf_materials = root["materials"];
+ materials.resize(gltf_materials.count_elements());
- auto& image = images[gltf_texture["source"].get<uint32_t>()];
- // if (gltf_texture.contains("sampler")) {
- // auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
- // sampler = samplers[sampler_index];
- // }
+ u32 material_index = 0U;
+ for (ondemand::object object: gltf_materials) {
+ material& material = materials[material_index++];
+ material.base_color = vec3(1.f);
+ material.metalness = 1.f;
+ material.roughness = 1.f;
- auto* texture = vkrenderer::create_2d_texture(static_cast<uint32_t>(image.width), static_cast<uint32_t>(image.height), VK_FORMAT_R8G8B8A8_UNORM, sampler);
+ ondemand::object pbr_params;
+ if (!object["pbrMetallicRoughness"].get(pbr_params)) {
+ ondemand::array base_color;
+ if (!pbr_params["baseColorFactor"].get(base_color)) {
+ u32 id = 0U;
+ for (double val : base_color) {
+ material.base_color.arr[id++] = static_cast<float>(val);
+ }
+ }
- texture->update(image.data);
+ ondemand::object base_color_texture;
+ if (!pbr_params["baseColorTexture"].get(base_color_texture)) {
+ material.base_color_texture = textures[base_color_texture["index"]];
+ }
- textures[texture_index] = texture;
+ pbr_params["metallicFactor"].get(material.metalness);
+ pbr_params["roughnessFactor"].get(material.roughness);
+
+ ondemand::object metallic_roughness_texture;
+ if (!pbr_params["metallicRoughnessTexture"].get(metallic_roughness_texture)) {
+ material.metallic_roughness_texture = textures[metallic_roughness_texture["index"]];
+ }
+ }
}
-#endif
}
-void gltf::load_materials() {
- const auto& gltf_materials = gltf_json["materials"];
- auto materials_count = gltf_materials.size();
- materials.resize(materials_count);
+gltf::gltf(const char* filepath) {
+ BEGIN_MARKER(LOAD_GLTF);
- for (size_t material_index = 0; material_index < materials_count; material_index++) {
- const auto& gltf_material = gltf_materials[material_index];
- auto& material = materials[material_index];
+ ondemand::parser parser;
+ padded_string json;
+ ondemand::document doc;
- if (gltf_material.contains("pbrMetallicRoughness")) {
- const auto& pbr_params = gltf_material["pbrMetallicRoughness"];
+ const char* ext = PathFindExtensionA(filepath);
- if (pbr_params.contains("baseColorFactor")) {
- const auto& base_color = pbr_params["baseColorFactor"];
- material.base_color.set<0>(base_color[0].get<float>());
- material.base_color.set<1>(base_color[1].get<float>());
- material.base_color.set<2>(base_color[2].get<float>());
- material.base_color.arr[3] = base_color[3].get<float>(); // Since we use a vec3 for colors we are not allowed toset fourth value with set<3>
- } else {
- material.base_color = vec3(1.f);
- }
+ char buffer_path[2048U] = { 0U };
+ char* filename = nullptr;
+ GetFullPathNameA( filepath, 2048U, buffer_path, &filename);
+ size_t parent_dir_len = filename - buffer_path;
- if (pbr_params.contains("baseColorTexture")) {
- auto base_color_index = pbr_params["baseColorTexture"]["index"].get<uint32_t>();
- material.base_color_texture = textures[base_color_index];
- }
+ // TODO: Remove
+ is_glb = strcmp(ext, ".glb") == 0;
+
+ if (is_glb) {
+ size_t filesize = 0U;
+ size_t read = 0U;
+ u8* glb_buffer = read_file(filepath, &filesize);
+ header = (struct glb_header*)glb_buffer;
+ assert(filesize == header->length);
+ // assert(header->magic == (u32)"glTF");
+
+ read += sizeof(*header);
+ chunks.push_back((struct glb_chunk*)(header + 1));
+ read += offsetof(struct glb_chunk, data) + chunks.back()->length;
+ while (read != header->length) {
+ chunks.push_back((struct glb_chunk*)(glb_buffer + read));
+ read += offsetof(struct glb_chunk, data) + chunks.back()->length;
+ }
+
+ doc = parser.iterate((const char*)&chunks[0]->data[0U], chunks[0]->length, filesize);
+ root = doc;
+
+ ondemand::array gltf_buffers = root["buffers"];
+ assert(gltf_buffers.count_elements() == chunks.size() - 1U);
+ buffers.resize(gltf_buffers.count_elements());
+ u32 buffer_index = 0U;
+ for (u32 chunk_index = 1U; chunk_index < chunks.size(); chunk_index++) {
+ buffers[buffer_index++] = buffer {
+ .bytes = chunks[chunk_index]->data,
+ .size = chunks[chunk_index]->length,
+ };
+ }
+ } else {
+ json = padded_string::load(filepath);
+ doc = parser.iterate(json);
+ root = doc;
- if (pbr_params.contains("metallicFactor")) {
- material.metalness = pbr_params["metallicFactor"].get<float>();
- } else {
- material.metalness = 1.0;
+ {
+ ondemand::array gltf_buffers = root["buffers"];
+ buffers.resize(gltf_buffers.count_elements());
+ u32 buffer_index = 0U;
+ for (ondemand::object value: gltf_buffers) {
+ std::string_view uri_view = value["uri"];
+ strncpy(buffer_path + parent_dir_len, uri_view.data(), uri_view.length());
+ buffer_path[parent_dir_len + uri_view.length()] = '\0';
+
+ size_t file_size = 0U;
+ uint8_t* bytes = read_file(buffer_path, &file_size);
+ buffers[buffer_index++] = {
+ .bytes = bytes,
+ .size = file_size,
+ };
}
+ }
+ }
+
+
+ std::vector<struct accessor> accessors;
+ {
+ ondemand::array gltf_accessors = root["accessors"];
+ accessors.resize(gltf_accessors.count_elements());
+ u32 accessor_index = 0U;
+ for (ondemand::object value: gltf_accessors) {
+ struct accessor& accessor = accessors[accessor_index++];
+ value["bufferView"].get(accessor.view_index);
+ value["count"].get(accessor.count);
+ value["type"].get(accessor.type);
+ value["componentType"].get(accessor.component_type);
+ }
+ }
+
+ std::vector<struct buffer_view> buffer_views;
+ {
+ ondemand::array gltf_views = root["bufferViews"];
+ buffer_views.resize(gltf_views.count_elements());
+ u32 view_index = 0U;
+ for (ondemand::object value: gltf_views) {
+ struct buffer_view& view = buffer_views[view_index++];
+ value["buffer"].get(view.buffer_index);
+ value["byteLength"].get(view.length);
+ value["byteOffset"].get(view.offset);
+ }
+ }
+
- if (pbr_params.contains("roughnessFactor")) {
- material.roughness = pbr_params["roughnessFactor"].get<float>();
- } else {
- material.roughness = 1.0;
+ {
+ ondemand::array gltf_nodes = root["nodes"];
+ nodes.resize(gltf_nodes.count_elements());
+
+ u32 node_index = 0U;
+ for (ondemand::object gltf_node: gltf_nodes) {
+ struct node& node = nodes[node_index++];
+
+ ondemand::array gltf_children;
+ if (!gltf_node["children"].get(gltf_children)) {
+ node.children.resize(gltf_children.count_elements());
+
+ u32 child_index = 0U;
+ for (auto child : gltf_children) {
+ node.children[child_index++] = child.get_uint32();
+ }
}
- if (pbr_params.contains("metallicRoughnessTexture")) {
- auto metallic_roughness_index = pbr_params["metallicRoughnessTexture"]["index"].get<uint32_t>();
- material.metallic_roughness_texture = textures[metallic_roughness_index];
+ node.mesh = UINT32_MAX;
+ gltf_node["mesh"].get(node.mesh);
+ }
+ }
+
+
+ // root nodes
+ {
+ u32 scene_index = root["scene"].get_uint32();
+ ondemand::array gltf_scene_nodes = root["scenes"].at(scene_index)["nodes"];
+ root_nodes.resize(gltf_scene_nodes.count_elements());
+
+ u32 index = 0U;
+ for (auto node_index: gltf_scene_nodes) {
+ root_nodes[index++] = node_index.get_uint32();
+ }
+ }
+
+ buffer_path[parent_dir_len] = '\0';
+ load_textures(buffer_path, textures, buffers, buffer_views, is_glb);
+ load_materials(materials, textures);
+
+ // meshes
+ {
+ ondemand::array gltf_meshes = root["meshes"];
+ meshes.resize(gltf_meshes.count_elements());
+
+ u32 mesh_index = 0U;
+ for (ondemand::object gltf_mesh: gltf_meshes) {
+ Mesh& mesh = meshes[mesh_index++];
+ ondemand::array gltf_primitives = gltf_mesh["primitives"];
+
+ for (ondemand::object primitive : gltf_primitives) {
+ material& material = materials[primitive["material"]];
+ mesh.add_submesh(load_primitive(primitive, buffers, accessors, buffer_views), material);
}
+
+ Mesh::register_mesh(mesh);
}
}
+
+ END_MARKER(LOAD_GLTF);
+}
+
+void gltf::deinit() {
+ for (handle<device_texture> handle: textures) {
+ vkdevice::get().destroy_texture(handle);
+ }
+
+ for (struct buffer& buffer: buffers) {
+ free(buffer.bytes);
+ }
+
+ free(header);
}
diff --git a/src/mesh.cpp b/src/mesh.cpp
index 3863ca8..cbfe392 100644
--- a/src/mesh.cpp
+++ b/src/mesh.cpp
@@ -1,6 +1,6 @@
#include "mesh.hpp"
-static std::vector<Mesh> meshes {};
+static std::vector<Mesh> registered_meshes {};
void Mesh::add_submesh(const submesh& submesh, material& material) {
submeshes.emplace_back(
@@ -42,5 +42,5 @@ void Mesh::add_submesh(const submesh& submesh, material& material) {
}
void Mesh::register_mesh(const Mesh& mesh) {
- meshes.push_back(mesh);
+ registered_meshes.push_back(mesh);
}
diff --git a/src/scene.cpp b/src/scene.cpp
index 9d6b981..9369eae 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -1,17 +1,5 @@
#include "scene.hpp"
-
-#include <cstdint>
-#include <queue>
-
-#ifdef API_TEST
-#include <vk_mem_alloc.h>
-#else
-#include "vk-renderer.hpp"
-#endif // API_TEST
-
-#include "gltf.hpp"
-#include "bvh.hpp"
-// #include "material.hpp"
+#include "mesh.hpp"
// void scene::random_scene() {
// material ground_material = { { 0.5, 0.5, 0.5 } };
@@ -63,15 +51,19 @@
// }
-scene::metadata::metadata(const camera &cam, uint32_t width, uint32_t height)
+metadata::metadata(const camera &cam, uint32_t width, uint32_t height)
: cam(cam), width(width), height(height) {}
scene::scene(const camera& cam, uint32_t width, uint32_t height)
- :meta(cam, width, height){
+ // :model("../models/sponza/Sponza.gltf"), meta(cam, width, height) {
+ // :model("../models/BistroInterior/BistroInterior.gltf"), meta(cam, width, height) {
+ // :model("../models/BistroExterior/BistroExterior.gltf"), meta(cam, width, height) {
+ // :model("../models/sponza-avif-hi.glb"), meta(cam, width, height) {
+ // :model("../models/main_sponza/NewSponza_Main_glTF_003.gltf"), meta(cam, width, height) {
+ // :model("../models/pkg_a_curtains/NewSponza_Curtains_glTF.gltf"), meta(cam, width, height) {
+ :model("../models/sponza.glb"), meta(cam, width, height) {
-#ifdef API_TEST
- auto& device = vkdevice::get_render_device();
-#endif
+ auto& device = vkdevice::get();
// Geometry & BVH
std::vector<uint32_t> indices;
@@ -81,51 +73,50 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
std::vector<gpu_material> materials;
std::vector<packed_bvh_node> packed_nodes;
- // auto root_node = gltf::load("../models/BistroInterior", "BistroInterior.gltf");
- auto gltf_model = gltf("../models/sponza/Sponza.gltf");
-
std::vector<triangle> triangles;
- size_t triangles_offset = 0;
- size_t vertices_offset = 0;
- std::queue<node> nodes_to_load {};
- nodes_to_load.push(gltf_model.root_node);
+ u32 triangles_offset = 0U;
+ u32 vertices_offset = 0U;
+ u32 positions_count = 0U;
+ u32 normals_count = 0U;
+ u32 uvs_count = 0U;
+ std::vector<u32> nodes_to_load = model.root_nodes;
- while(!nodes_to_load.empty()) {
- auto &node = nodes_to_load.front();
+ for (u32 cur_node_index = 0U; cur_node_index < nodes_to_load.size(); cur_node_index++) {
+ struct node &node = model.nodes[nodes_to_load[cur_node_index]];
- if (node.mesh != nullptr) {
- const auto* mesh = node.mesh;
- const auto& mesh_positions = mesh->get_attribute(ATTRIBUTE_TYPE::POSITION);
- const auto& mesh_normals = mesh->get_attribute(ATTRIBUTE_TYPE::NORMAL);
- const auto& mesh_uvs_0 = mesh->get_attribute(ATTRIBUTE_TYPE::UV_0);
- const auto& mesh_indices = mesh->get_indices();
+ if (node.mesh != UINT32_MAX) {
+ const Mesh& mesh = model.meshes[node.mesh];
+ const auto& mesh_positions = mesh.get_attribute(ATTRIBUTE_TYPE::POSITION);
+ const auto& mesh_normals = mesh.get_attribute(ATTRIBUTE_TYPE::NORMAL);
+ const auto& mesh_uvs_0 = mesh.get_attribute(ATTRIBUTE_TYPE::UV_0);
+ const auto& mesh_indices = mesh.get_indices();
- indices.resize(indices.size() + mesh_indices.size());
- positions.resize(vertices_offset + mesh_positions.size());
- normals.resize(vertices_offset + mesh_normals.size());
- uvs.resize(vertices_offset + mesh_uvs_0.size());
+ indices.resize(indices.size() + mesh_indices.size());
+ positions.resize(positions_count + mesh_positions.size());
+ normals.resize(normals_count + mesh_normals.size());
+ uvs.resize(uvs_count + mesh_uvs_0.size());
std::memcpy(
- positions.data() + vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::POSITION),
+ positions.data() + positions_count,
mesh_positions.data(),
- mesh_positions.size() * sizeof(float)
+ mesh_positions.size() * sizeof(mesh_positions[0U])
);
std::memcpy(
- normals.data() + vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::NORMAL),
+ normals.data() + normals_count,
mesh_normals.data(),
- mesh_normals.size() * sizeof(float)
+ mesh_normals.size() * sizeof(mesh_normals[0U])
);
std::memcpy(
- uvs.data() + vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::UV_0),
+ uvs.data() + uvs_count,
mesh_uvs_0.data(),
- mesh_uvs_0.size() * sizeof(float)
+ mesh_uvs_0.size() * sizeof(mesh_uvs_0[0U])
);
auto index_offset { 0U };
// Add offset to indices in order to have absolute indices
- for (const auto& submesh: mesh->get_submeshes()) {
+ for (const auto& submesh: mesh.get_submeshes()) {
auto vertex_offset = vertices_offset + submesh.vertex_offset;
const auto& material = submesh.material;
@@ -151,9 +142,6 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
indices[triangle_offset + 2] = static_cast<uint32_t>((submesh_level_index_3 + vertex_offset) | (0xff000000 & (materials.size() << 24)));
}
-// const auto& albedo_image = vkrenderer::api.get_image(material.base_color_texture->device_image);
-// const auto& albedo_sampler = vkrenderer::api.get_sampler(material.base_color_texture->sampler->device_sampler);
-
auto& mat = materials.emplace_back(gpu_material {
.base_color = material.base_color,
// .albedo_texture_id = albedo_image.bindless_sampled_index,
@@ -162,7 +150,6 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.roughness = material.roughness
});
-#ifdef API_TEST
if (material.base_color_texture.id != handle<device_texture>::invalid_id) {
mat.albedo_texture_id = device.get_texture(material.base_color_texture).get_sampled_index();
// mat.albedo_texture_sampler_id = device.get_sampler(0);
@@ -172,28 +159,18 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
mat.metallic_roughness_texture_id = device.get_texture(material.metallic_roughness_texture).get_sampled_index();
// mat.metallic_roughness_texture_sampler_id = device.get_sampler(0);
}
-#else
- if (material.metallic_roughness_texture != nullptr) {
- // auto& gpu_material = materials.back();
-// const auto& metallic_roughness_image = vkrenderer::api.get_image(material.metallic_roughness_texture->device_image);
-// const auto& metallic_roughness_sampler = vkrenderer::api.get_sampler(material.metallic_roughness_texture->sampler->device_sampler);
-
-// gpu_material.metallic_roughness_texture_id = metallic_roughness_image.bindless_sampled_index;
-// gpu_material.metallic_roughness_texture_sampler_id = metallic_roughness_sampler.bindless_index;
- }
-#endif
-
}
- triangles_offset += mesh->triangle_count();
- vertices_offset += mesh->vertices_count();
+ triangles_offset += mesh.triangle_count();
+ vertices_offset += mesh.vertices_count();
+ positions_count = vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::POSITION);
+ normals_count = vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::NORMAL);
+ uvs_count = vertices_offset * Mesh::attribute_components(ATTRIBUTE_TYPE::UV_0);
}
- for (auto &new_node: node.children) {
- nodes_to_load.push(new_node);
+ for (u32 child_index: node.children) {
+ nodes_to_load.push_back(child_index);
}
-
- nodes_to_load.pop();
}
// random_scene();
@@ -201,28 +178,13 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
bvh builder(triangles, packed_nodes);
// bvh builder(spheres, packed_nodes);
-#ifdef API_TEST
- {
- scene_buffer_handle = device.create_buffer({
- .size = sizeof(meta) * 3U,
- .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
- .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
- .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
- });
-
- const auto& scene_buffer = device.get_buffer(scene_buffer_handle);
- uint8_t* ptr = static_cast<uint8_t*>(scene_buffer.mapped_ptr);
- memcpy(static_cast<void*>(ptr), &meta, sizeof(meta));
- memcpy(static_cast<void*>(ptr + sizeof(meta)), &meta, sizeof(meta));
- memcpy(static_cast<void*>(ptr + sizeof(meta) * 2U), &meta, sizeof(meta));
- }
-
{
indices_buffer_handle = device.create_buffer({
.size = indices.size() * sizeof(indices[0]),
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "indices",
});
const auto& indices_buffer = device.get_buffer(indices_buffer_handle);
void* ptr = indices_buffer.mapped_ptr;
@@ -235,6 +197,7 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "positions",
});
const auto& positions_buffer = device.get_buffer(positions_buffer_handle);
void* ptr = positions_buffer.mapped_ptr;
@@ -247,6 +210,7 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "normals",
});
const auto& normals_buffer = device.get_buffer(normals_buffer_handle);
void* ptr = normals_buffer.mapped_ptr;
@@ -259,6 +223,7 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "uvs",
});
const auto& uvs_buffer = device.get_buffer(uvs_buffer_handle);
void* ptr = uvs_buffer.mapped_ptr;
@@ -271,6 +236,7 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "bvh",
});
const auto& bvh_buffer = device.get_buffer(bvh_buffer_handle);
void* ptr = bvh_buffer.mapped_ptr;
@@ -283,33 +249,21 @@ scene::scene(const camera& cam, uint32_t width, uint32_t height)
.usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
.memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
.memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
+ .name = "materials",
});
const auto& materials_buffer = device.get_buffer(materials_buffer_handle);
void* ptr = materials_buffer.mapped_ptr;
memcpy(ptr, materials.data(), materials.size() * sizeof(materials[0]));
}
-#else
- scene_buffer = vkrenderer::create_buffer(sizeof(meta) * vkrenderer::virtual_frames_count);
- scene_buffer->write(&meta, 0, sizeof(meta));
- scene_buffer->write(&meta, sizeof(meta), sizeof(meta));
- scene_buffer->write(&meta, sizeof(meta) * 2, sizeof(meta));
-
- indices_buffer = vkrenderer::create_buffer(indices.size() * sizeof(indices[0]));
- indices_buffer->write(indices.data(), 0, indices.size() * sizeof(indices[0]));
-
- positions_buffer = vkrenderer::create_buffer(positions.size() * sizeof(positions[0]));
- positions_buffer->write(positions.data(), 0, positions.size() * sizeof(positions[0]));
-
- normals_buffer = vkrenderer::create_buffer(normals.size() * sizeof(normals[0]));
- normals_buffer->write(normals.data(), 0, normals.size() * sizeof(normals[0]));
-
- uvs_buffer = vkrenderer::create_buffer(uvs.size() * sizeof(uvs[0]));
- uvs_buffer->write(uvs.data(), 0, uvs.size() * sizeof(uvs[0]));
+}
- bvh_buffer = vkrenderer::create_buffer(packed_nodes.size() * sizeof(packed_nodes[0]));
- bvh_buffer->write(packed_nodes.data(), 0, packed_nodes.size() * sizeof(packed_nodes[0]));
+void scene::deinit() {
+ vkdevice::get().destroy_buffer(indices_buffer_handle);
+ vkdevice::get().destroy_buffer(positions_buffer_handle);
+ vkdevice::get().destroy_buffer(normals_buffer_handle);
+ vkdevice::get().destroy_buffer(uvs_buffer_handle);
+ vkdevice::get().destroy_buffer(bvh_buffer_handle);
+ vkdevice::get().destroy_buffer(materials_buffer_handle);
- materials_buffer = vkrenderer::create_buffer(materials.size() * sizeof(materials[0]));
- materials_buffer->write(materials.data(), 0, materials.size() * sizeof(materials[0]));
-#endif // API_TEST
+ model.deinit();
}
diff --git a/src/utils.cpp b/src/utils.cpp
index ffe50b3..4c383db 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -1,54 +1,46 @@
#include "utils.hpp"
-#if defined(WINDOWS)
-#include <windows.h>
-#endif
-
-#include <filesystem>
-#include <iostream>
+#include <unordered_map>
-std::vector<uint8_t> read_file(const char* path) {
-#if defined(WINDOWS)
- FILE* f = nullptr;
- errno_t err = fopen_s(&f, path, "rb");
+uint8_t* read_file(const char* path, size_t* size) {
+#if _WIN32
+ HANDLE f = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (err != 0) {
- std::cerr << "Cannot open file !" << std::endl;
- return {};
+ if (f == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "Cannot open file !\n");
+ return nullptr;
}
-#elif defined(LINUX)
+#elif LINUX
FILE* f = fopen(path, "rb");
if (!f) {
- std::cerr << "Cannot open file !" << std::endl;
+ fprintf(stderr, "Cannot open file !\n");
return {};
}
#endif
- if (fseek(f, 0, SEEK_END) != 0) {
- return {};
+ LARGE_INTEGER file_size = { .QuadPart = 0ULL };
+ if (!GetFileSizeEx(f, &file_size)) {
+ return nullptr;
}
+ *size = file_size.LowPart;
- std::vector<uint8_t> file_content(ftell(f));
+ void* content = malloc(*size);
- if (fseek(f, 0, SEEK_SET) != 0) {
- return {};
- }
-
- if (fread(file_content.data(), sizeof(uint8_t), file_content.size(), f) != file_content.size()) {
- std::cerr << "Reading file content failed" << std::endl;
- return {};
+ DWORD bread = 0U;
+ if (!ReadFile(f, content, static_cast<DWORD>(*size), &bread, NULL) || bread != *size) {
+ fprintf(stderr, "Reading file content failed\n");
+ return nullptr;
}
- fclose(f);
+ CloseHandle(f);
- return file_content;
+ return (uint8_t*)content;
}
-
-#ifdef WINDOWS
+#if _WIN32
void log_last_error() {
- auto error_code = GetLastError();
+ DWORD error_code = GetLastError();
const char* error_message = nullptr;
FormatMessageA(
@@ -63,29 +55,49 @@ void log_last_error() {
nullptr
);
- std::cerr << error_message << std::endl;
+ fprintf(stderr, "%s\n", error_message);
}
-bool watcher::watch_file(const char* filepath, watcher::func callback) {
+struct watch_data {
+ HANDLE dir_handle;
+ OVERLAPPED overlapped;
+ DWORD buffer[512];
+};
+
+static std::unordered_map<const char*, func> callbacks;
+static std::unordered_map<const char*, watch_data> watched_dirs;
+
+bool watch_file(const char* filepath, func callback) {
DWORD attrib = GetFileAttributes(filepath);
if (attrib == INVALID_FILE_ATTRIBUTES)
return false;
- std::filesystem::path path(filepath);
- if (!watcher::watch_dir(path.parent_path().string().c_str()))
+ size_t buffer_size = 2048U;
+ char* fullpath = static_cast<char*>(malloc(buffer_size));
+ char* filename = nullptr;
+ GetFullPathNameA( filepath, 2028, fullpath, &filename);
+
+ size_t dir_len = filename - fullpath;
+ char* parent_dir = static_cast<char*>(malloc(dir_len));
+ strncpy(parent_dir, fullpath, dir_len);
+
+ free(fullpath);
+
+ if (!watch_dir(parent_dir)) {
return false;
+ }
- auto [_, is_inserted] = watcher::callbacks.emplace(filepath, callback);
+ auto [_, is_inserted] = callbacks.emplace(filepath, callback);
return is_inserted;
}
-bool watcher::watch_dir(const char* dir_path) {
+bool watch_dir(const char* dir_path) {
DWORD attrib = GetFileAttributes(dir_path);
if (attrib == INVALID_FILE_ATTRIBUTES || (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0U )
return false;
- if (watcher::watched_dirs.find(dir_path) != watcher::watched_dirs.end())
+ if (watched_dirs.find(dir_path) != watched_dirs.end())
return true;
HANDLE dir_handle = CreateFileA(
@@ -103,7 +115,7 @@ bool watcher::watch_dir(const char* dir_path) {
return false;
}
- auto [dir, _] = watcher::watched_dirs.emplace(dir_path, watch_data{ .dir_handle = dir_handle, .overlapped{}, .buffer{} });
+ auto [dir, _] = watched_dirs.emplace(dir_path, watch_data{ .dir_handle = dir_handle, .overlapped{}, .buffer{} });
if (FAILED(ReadDirectoryChangesW(dir_handle, dir->second.buffer, sizeof(watch_data::buffer), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, nullptr, &dir->second.overlapped, nullptr))) {
log_last_error();
@@ -113,8 +125,8 @@ bool watcher::watch_dir(const char* dir_path) {
return true;
}
-void watcher::pull_changes() {
- for (auto& dir : watcher::watched_dirs) {
+void pull_changes() {
+ for (auto& dir : watched_dirs) {
auto& watch_data = dir.second;
if (!HasOverlappedIoCompleted(&watch_data.overlapped))
continue;
diff --git a/src/vec3.cpp b/src/vec3.cpp
index 3167bc2..414ee73 100644
--- a/src/vec3.cpp
+++ b/src/vec3.cpp
@@ -1,10 +1,8 @@
-#include <cmath>
-#include <cassert.>
-#include <smmintrin.h>
-
-#include "utils.hpp"
#include "vec3.hpp"
+// #include <smmintrin.h>
+// #include <xmmintrin.h>
+
vec3::vec3() : v(_mm_setzero_ps()) {}
vec3::vec3(float x) : v(_mm_set1_ps(x)) {}
@@ -122,7 +120,16 @@ bool vec3::near_zero() const {
float v0 = fabs(static_cast<float>(_mm_extract_ps(v, 0)));
float v1 = fabs(static_cast<float>(_mm_extract_ps(v, 1)));
float v2 = fabs(static_cast<float>(_mm_extract_ps(v, 2)));
- return (v0 < EPSILON) && (v1 < EPSILON) && (v2 < EPSILON);
+ return (v0 < FLT_EPSILON) && (v1 < FLT_EPSILON) && (v2 < FLT_EPSILON);
+}
+
+bool vec3::is_zero() const {
+ // __m128 e = _mm_set1_ps(EPSILON);
+ // _mm_cmplt_ps(_mm_andnot_ps(_mm_set1_ps(-0.0f), v), e);
+ float v0 = fabs(static_cast<float>(_mm_extract_ps(v, 0)));
+ float v1 = fabs(static_cast<float>(_mm_extract_ps(v, 1)));
+ float v2 = fabs(static_cast<float>(_mm_extract_ps(v, 2)));
+ return (v0 == 0.f) && (v1 == 0.f) && (v2 == 0.f);
}
void vec3::print() const {
diff --git a/src/vulkan-loader.cpp b/src/vulkan-loader.cpp
index c799f17..399b566 100644
--- a/src/vulkan-loader.cpp
+++ b/src/vulkan-loader.cpp
@@ -1,8 +1,6 @@
#include "vulkan-loader.hpp"
-#include <cassert>
-
-#if defined(WINDOWS)
+#if defined(_WIN32)
// extern "C" void* GetProcAddress(HMODULE, const char*);
// extern "C" HMODULE LoadLibraryA(const char*);
HMODULE vulkanLibrary = LoadLibraryA("vulkan-1.dll");
diff --git a/src/window.cpp b/src/window.cpp
index 7ba3bc0..38c9765 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -1,6 +1,5 @@
#include "window.hpp"
-
#ifdef LINUX
#include <iostream>
@@ -169,10 +168,23 @@ void window::poll_events() {
}
}
-#elif defined(WINDOWS)
-#include <windowsx.h>
+#elif _WIN32
+#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
-#include "utils.hpp"
+HCURSOR window::cursors[CURSOR_TYPE::MAX_CURSOR] = {
+ LoadCursorA(NULL, IDC_ARROW),
+ LoadCursorA(NULL, IDC_IBEAM),
+ LoadCursorA(NULL, IDC_SIZEALL),
+ LoadCursorA(NULL, IDC_SIZENS),
+ LoadCursorA(NULL, IDC_SIZEWE),
+ LoadCursorA(NULL, IDC_SIZENESW),
+ LoadCursorA(NULL, IDC_SIZENWSE),
+ LoadCursorA(NULL, IDC_HAND),
+ LoadCursorA(NULL, IDC_WAIT),
+ LoadCursorA(NULL, IDC_APPSTARTING),
+ LoadCursorA(NULL, IDC_NO),
+};
LRESULT CALLBACK window::window_procedure(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) {
window* win = nullptr;
@@ -250,29 +262,27 @@ void window::message_loop() {
MSG msg {};
while(true) {
- // Generate keydown events pressed keys
- for (size_t virtual_key { KEYS::LSHIFT }; virtual_key < KEYS::MAX_KEYS; virtual_key++) {
- if (keyboard[virtual_key]) {
- events.push_back({
- .data {
- .key = (KEYS)virtual_key,
- },
- .type = EVENT_TYPES::KEY_PRESS,
- });
- }
- }
-
-
while (PeekMessageA(&msg, nullptr, 0, 0, PM_REMOVE) != 0) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
+ for (u32 key_index = 0U; key_index <= KEY::MAX_KEY; key_index++) {
+ events.push_back(event {
+ .data {
+ .key = (KEY)key_index,
+ },
+ .type = keyboard[key_index] ? EVENT_TYPE::KEY_DOWN : EVENT_TYPE::KEY_UP,
+ });
+ }
+
SwitchToFiber(main_fiber);
}
}
void window::poll_events() {
+ events.clear();
+
SwitchToFiber(message_loop_fiber);
}
@@ -281,7 +291,10 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
case WM_CLOSE:
case WM_DESTROY:
case WM_QUIT: {
- events.push_back({ .data {}, .type = EVENT_TYPES::QUIT });
+ events.push_back({
+ .data {},
+ .type = EVENT_TYPE::QUIT
+ });
isOpen = false;
break;
}
@@ -296,86 +309,90 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
.height = height,
},
},
- .type = EVENT_TYPES::RESIZE
+ .type = EVENT_TYPE::RESIZE
});
break;
}
case WM_KEYDOWN: {
- keyboard[wparam] = true;
-
events.push_back({
.data {
- .key = (KEYS)wparam,
+ .key = (KEY)wparam,
},
- .type = EVENT_TYPES::KEY_PRESS,
+ .type = EVENT_TYPE::KEY_PRESS,
});
+ keyboard[wparam] = true;
break;
}
case WM_KEYUP: {
- keyboard[wparam] = false;
-
events.push_back({
.data {
- .key = (KEYS)wparam,
+ .key = (KEY)wparam,
},
- .type = EVENT_TYPES::KEY_RELEASE,
+ .type = EVENT_TYPE::KEY_RELEASE,
});
+ keyboard[wparam] = false;
break;
}
case WM_LBUTTONDOWN: {
+ mouse[BUTTON::LEFT] = true;
events.push_back({
.data {
- .button = BUTTONS::LEFT,
+ .button = BUTTON::LEFT,
},
- .type = EVENT_TYPES::BUTTON_PRESS,
+ .type = EVENT_TYPE::BUTTON_PRESS,
});
break;
}
case WM_LBUTTONUP: {
+ mouse[BUTTON::LEFT] = false;
events.push_back({
.data {
- .button = BUTTONS::LEFT,
+ .button = BUTTON::LEFT,
},
- .type = EVENT_TYPES::BUTTON_RELEASE,
+ .type = EVENT_TYPE::BUTTON_RELEASE,
});
break;
}
case WM_RBUTTONDOWN: {
+ mouse[BUTTON::RIGHT] = true;
events.push_back({
.data {
- .button = BUTTONS::RIGHT,
+ .button = BUTTON::RIGHT,
},
- .type = EVENT_TYPES::BUTTON_PRESS,
+ .type = EVENT_TYPE::BUTTON_PRESS,
});
break;
}
case WM_RBUTTONUP: {
+ mouse[BUTTON::RIGHT] = false;
events.push_back({
.data {
- .button = BUTTONS::RIGHT,
+ .button = BUTTON::RIGHT,
},
- .type = EVENT_TYPES::BUTTON_RELEASE,
+ .type = EVENT_TYPE::BUTTON_RELEASE,
});
break;
}
case WM_MBUTTONDOWN: {
+ mouse[BUTTON::MIDDLE] = true;
events.push_back({
.data {
- .button = BUTTONS::MIDDLE,
+ .button = BUTTON::MIDDLE,
},
- .type = EVENT_TYPES::BUTTON_PRESS,
+ .type = EVENT_TYPE::BUTTON_PRESS,
});
break;
}
case WM_MBUTTONUP: {
+ mouse[BUTTON::MIDDLE] = false;
events.push_back({
.data {
- .button = BUTTONS::MIDDLE,
+ .button = BUTTON::MIDDLE,
},
- .type = EVENT_TYPES::BUTTON_RELEASE,
+ .type = EVENT_TYPE::BUTTON_RELEASE,
});
break;
}
@@ -387,7 +404,19 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
.y = GET_Y_LPARAM(lparam),
},
},
- .type = EVENT_TYPES::MOUSE_MOVE,
+ .type = EVENT_TYPE::MOUSE_MOVE,
+ });
+ break;
+ }
+ case WM_MOUSEWHEEL: {
+ events.push_back({
+ .data {
+ .delta {
+ .x = 0,
+ .y = GET_WHEEL_DELTA_WPARAM(wparam) / WHEEL_DELTA,
+ },
+ },
+ .type = EVENT_TYPE::MOUSE_WHEEL,
});
break;
}
@@ -400,6 +429,10 @@ LRESULT window::message_handler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lpar
return 0;
}
+
+void window::set_cursor(enum CURSOR_TYPE type) {
+ SetCursor(window::cursors[type]);
+}
#elif defined(MACOS)
window::window(uint32_t width, uint32_t height) {
}