From 3d42dea9ebe881bcf9df1a93eb239e029f9dc693 Mon Sep 17 00:00:00 2001 From: Medusa Slockbower Date: Sat, 2 Aug 2025 13:17:20 -0400 Subject: [PATCH] - Started interface for renderers - Renamed fproc -> langproc (I'll probably never settle on a naming convention for this) - Refactored set to use median psl --- CMakeLists.txt | 18 +- PLANNING.md | 134 +++++++++-- cmake/opengl.cmake | 1 - include/fennec/containers/list.h | 133 +++++++++-- include/fennec/containers/rdtree.h | 220 ++++++++++++++++++ include/fennec/containers/set.h | 73 ++++-- .../opengl/legacy.h => core/system.h} | 34 ++- .../filesystem/detail/_stdio.h | 6 +- .../{fproc => langproc}/filesystem/file.h | 16 +- .../{fproc => langproc}/filesystem/path.h | 8 +- .../{fproc => langproc}/strings/cstring.h | 8 +- .../strings/detail/_ctype.h | 6 +- .../strings/detail/_locale.h | 6 +- .../{fproc => langproc}/strings/locale.h | 8 +- .../{fproc => langproc}/strings/string.h | 10 +- .../{fproc => langproc}/strings/wcstring.h | 8 +- .../{fproc => langproc}/strings/wstring.h | 10 +- include/fennec/memory/allocator.h | 42 +++- include/fennec/platform/interface/display.h | 2 +- .../fennec/platform/interface/gfxcontext.h | 2 +- include/fennec/platform/interface/platform.h | 4 +- include/fennec/platform/interface/window.h | 2 +- include/fennec/renderers/interface/renderer.h | 166 +++++++++++++ include/fennec/renderers/opengl/fallback.h | 2 + include/fennec/renderers/opengl/modern.h | 2 + include/fennec/scene/component.h | 69 ++++++ include/fennec/scene/scene.h | 60 +++++ .../{fproc => langproc}/filesystem/file.cpp | 4 +- .../{fproc => langproc}/filesystem/path.cpp | 2 +- source/platform/linux/platform.cpp | 2 +- source/platform/opengl/egl/context.cpp | 2 +- test/CMakeLists.txt | 8 +- test/main.cpp | 4 +- test/printing.h | 4 +- test/tests/containers/test_map.h | 2 +- .../strings/test_cstring.h | 10 +- test/tests/{fproc => langproc}/test_io.h | 12 +- test/tests/{fproc => langproc}/test_strings.h | 10 +- test/tests/{test_fproc.h => test_langproc.h} | 16 +- 39 files changed, 962 insertions(+), 164 deletions(-) create mode 100644 include/fennec/containers/rdtree.h rename include/fennec/{renderers/opengl/legacy.h => core/system.h} (65%) rename include/fennec/{fproc => langproc}/filesystem/detail/_stdio.h (87%) rename include/fennec/{fproc => langproc}/filesystem/file.h (96%) rename include/fennec/{fproc => langproc}/filesystem/path.h (97%) rename include/fennec/{fproc => langproc}/strings/cstring.h (98%) rename include/fennec/{fproc => langproc}/strings/detail/_ctype.h (87%) rename include/fennec/{fproc => langproc}/strings/detail/_locale.h (87%) rename include/fennec/{fproc => langproc}/strings/locale.h (87%) rename include/fennec/{fproc => langproc}/strings/string.h (98%) rename include/fennec/{fproc => langproc}/strings/wcstring.h (98%) rename include/fennec/{fproc => langproc}/strings/wstring.h (98%) create mode 100644 include/fennec/scene/component.h create mode 100644 include/fennec/scene/scene.h rename source/{fproc => langproc}/filesystem/file.cpp (99%) rename source/{fproc => langproc}/filesystem/path.cpp (97%) rename test/tests/{fproc => langproc}/strings/test_cstring.h (87%) rename test/tests/{fproc => langproc}/test_io.h (92%) rename test/tests/{fproc => langproc}/test_strings.h (85%) rename test/tests/{test_fproc.h => test_langproc.h} (82%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e565a35..84e08ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,18 +164,18 @@ add_library(fennec STATIC include/fennec/math/detail/_vector_traits.h -# FPROC ================================================================================================================ +# langproc ================================================================================================================ # Strings - include/fennec/fproc/strings/cstring.h - include/fennec/fproc/strings/locale.h - include/fennec/fproc/strings/string.h + include/fennec/langproc/strings/cstring.h + include/fennec/langproc/strings/locale.h + include/fennec/langproc/strings/string.h - include/fennec/fproc/strings/detail/_ctype.h + include/fennec/langproc/strings/detail/_ctype.h # Filesystem - include/fennec/fproc/filesystem/file.h source/fproc/filesystem/file.cpp - include/fennec/fproc/filesystem/path.h source/fproc/filesystem/path.cpp + include/fennec/langproc/filesystem/file.h source/langproc/filesystem/file.cpp + include/fennec/langproc/filesystem/path.h source/langproc/filesystem/path.cpp # PLATFORM ============================================================================================================= @@ -190,6 +190,10 @@ add_library(fennec STATIC ${FENNEC_EXTRA_SOURCES} include/fennec/renderers/interface/renderer.h + include/fennec/containers/rdtree.h + include/fennec/scene/scene.h + include/fennec/scene/component.h + include/fennec/core/system.h ) add_dependencies(fennec metaprogramming) diff --git a/PLANNING.md b/PLANNING.md index a48c533..8c75112 100644 --- a/PLANNING.md +++ b/PLANNING.md @@ -12,7 +12,7 @@ 4. [Math Library](#math-library-math) 5. [Memory Library](#memory-library-memory) 6. [Containers Library](#containers-library-containers) - 7. [Format Processing](#format-processing-fproc) + 7. [Format Processing](#format-processing-langproc) 8. [Core](#core-core) 1. [Tick](#tick) 2. [Frame](#frame) @@ -143,7 +143,7 @@ trivially cracked locally, you can scrape most assets from the GPU and Audio Car I have managed to solve the specific case provided at the top of this section, which was done by wrapping C I/O calls into a file wrapper. This wrapper can handle a few different mode flags and has specific conditions for the flags. See -the documentation for `fennec/fproc/io/file.h` for more info. +the documentation for `fennec/langproc/io/file.h` for more info. One question remains unanswered on this front; should a read/write file open as `r+` or `a+`. `rewind` is slightly faster than `fseek(SEEK_END)`, however for the case of save files and editor assets, `r+` makes more sense from a usage perspective @@ -247,7 +247,7 @@ Here are essential data-structures not specified in the C++ stdlib: -## Format Processing (`fproc`) +## Language Processing (`langproc`) This library contains information for any data that is formatted. This includes basic string formats, file formats, and eventually programming languages @@ -256,13 +256,13 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi ### Notes - * String Analysis (`fproc/strings`) + * String Analysis (`langproc/strings`) * Search * Manipulation * Delimiting * Regex - - File Formats (`fproc/formats`) + - File Formats (`langproc/formats`) - Serialization - JSON - HTML @@ -293,9 +293,68 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi - OTF - SVG - TTF - - Models + - Models + unfortunately, most formats are esoteric due to copyright/trademark/etc. I will be using assimp for the + time being, below is a list of formats supported by assimp. + - 3D + - 3DS + - 3MF + - AC + - AC3D + - ACC + - AMJ + - ASE + - ASK + - B3D + - BVH + - CSM + - COB + - DAE/Collada + - DXF + - ENFF - FBX - - Wavefront OBJ + - glTF 1.0 + GLB + - glTF 2.0 + - HMB + - IFC-STEP + - IQM + - IRR / IRRMESH + - LWO + - LWS + - LXO + - M3D + - MD2 + - MD3 + - MD5 + - MDC + - MDL + - MESH / MESH.XML + - MOT + - MS3D + - NDO + - NFF + - OBJ + - OFF + - OGEX + - PLY + - PMX + - PRJ + - Q3O + - Q3S + - RAW + - SCN + - SIB + - SMD + - STP + - STL + - TER + - UC + - USD + - VTA + - X + - X3D + - XGL + - ZGL - Video Formats - MP4 - AVI @@ -303,7 +362,7 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi - MOV **TODO LATER** - * Compilation (`fproc/code`) + * Compilation (`langproc/code`) * Lexical Analysis * Syntax Analysis * Semantic Analysis @@ -482,33 +541,41 @@ struct Object { vec3 location, scale; // A matrix would be 64 bytes, this is instead 28 bytes quat rotation; - int material; + uint32 material, lighting; } ``` Textures for 3D rendering are stored in various buffers with sizes of powers of 2. Ratios of `1:1` and `2:1` are allowed. The `2:1` ratio is specifically for spherical and cylindrical projection. UVs may be transformed to use a `2:1` as if it were `1:2`. -Cubemaps may only be `1:1`, I would be concerned if you are using any other ratio. +Cubemaps and 3D textures may only be `1:1`, I would be concerned if you are using any other ratio. - - 8-Bit R Texture `4096, 2048, 1024, 512` (8) - - 8-Bit RG Texture `4096, 2048, 1024, 512` (8) - - 8-Bit RGB Texture `4096, 2048, 1024, 512` (8) + - 8-Bit R Texture `4096, 2048, 1024, 512` (8) + - 8-Bit RG Texture `4096, 2048, 1024, 512` (8) + - 8-Bit RGB Texture `4096, 2048, 1024, 512` (8) - 8-Bit RGBA Texture `4096, 2048, 1024, 512` (8) - - 8-Bit RGB Cubemap `1024, 512, 256, 128` (4) + - 8-Bit R Cubemap `1024, 512, 256, 128` (4) + - 8-Bit RGB Cubemap `1024, 512, 256, 128` (4) - * 16-Bit HDR RGB Texture `4096, 2048, 1024, 512` (8) + * 16-Bit HDR R Texture `4096, 2048, 1024, 512` (8) + * 16-Bit HDR RGB Texture `4096, 2048, 1024, 512` (8) * 16-Bit HDR RGBA Texture `4096, 2048, 1024, 512` (8) - * 16-Bit HDR RGB Cubemap `1024, 512, 256, 128` (4) + * 16-Bit HDR R Cubemap `1024, 512, 256, 128` (4) + * 16-Bit HDR RGB Cubemap `1024, 512, 256, 128` (4) - 16-Bit Shadow Texture `4096, 2048, 1024, 512` (8) - 16-Bit Shadow Cubemap `2048, 1024, 512, 256` (4) + * 8-Bit 3D R Texture `256, 128, 64, 32` (4) + * 8-Bit 3D RGB Texture `256, 128, 64, 32` (4) + * 16-Bit 3D HDR R Texture `256, 128, 64, 32` (4) + * 16-Bit 3D HDR RGB Texture `256, 128, 64, 32` (4) + Documentation should provide guidelines on categories of Art Assets and the resolution of textures to use. -Textures are identified by an 8-bit integer and 16-bit integer. - - `int8` → the texture buffer - - `int16` → the layer in the buffer +Textures are identified by a 32-bit integer. + - `8 bits` → the texture buffer + - `24 bits` → the layer in the buffer Artists should be informed on the texture structure of the engine and its limitations. However, these principles should be followed in other game engines as these are @@ -519,6 +586,14 @@ Materials are, for the most part, user-defined. Documentation should make the us Material buffers will be a sequence of the Material Struct instances. They will at the very least contain the id of their shader. +Types of materials: + - Surface (Vertex & Fragment) + - Opaque / Masked + - Translucent (Forward) + - Volume (Path Traced Volumetrics / Forward) + - Light (Lighting Model) + - Post-Process + @@ -585,17 +660,28 @@ Debug View: Visibility Buffer Debug View: Depth, Stencil, Diffuse, Emission, Normal, Specularity +- Generate Dynamic Shadows +- Generate Dynamic Reflections (Optional) +- SSAO (Optional) - Deferred Lighting Pass `(10 Bpp, 80 bpp) [1920x1080] ≈ 2 x 16.3MB + 8.3MB ≈ 24.6MB` - Depth Buffer → `D24` - - Lighting Buffer → `RGB16` (w/ Mipmapping when Bloom or DoF are enabled) + - Lighting Buffer → `RGB16` w/ Mipmapping - Stencil Buffer $rarr; `S8` - - Generate Dynamic Shadows - - Generate Dynamic Reflections (Optional) - - SSAO (Optional) - Apply Lighting Model - + Debug View: Shadows, Reflections, SSAO, Deferred Lighting +We can combine all of these into one framebuffer: + + - Depth - Stencil → `D24_S8` + - Visibility Info → `RGB32I` + - Diffuse → `RGBA8` + - Emission → `RGB8` + - Normal → `RGB8` + - Specular → `RGB8` + - Lighting Buffer → `RGB16` w/ Mipmapping + - One more slot left open for another + * Forward Pass * BVH, Same as Above * LOD Selection, Same as Above diff --git a/cmake/opengl.cmake b/cmake/opengl.cmake index 83f45d9..3d595e4 100644 --- a/cmake/opengl.cmake +++ b/cmake/opengl.cmake @@ -42,6 +42,5 @@ if(FENNEC_GRAPHICS_WANT_EGL) include/fennec/renderers/opengl/modern.h include/fennec/renderers/opengl/fallback.h - include/fennec/renderers/opengl/legacy.h ) endif() \ No newline at end of file diff --git a/include/fennec/containers/list.h b/include/fennec/containers/list.h index 38fd1c0..65df561 100644 --- a/include/fennec/containers/list.h +++ b/include/fennec/containers/list.h @@ -94,6 +94,32 @@ public: return *_table[n].data; } + void insert(const iterator& it, const value_t& x) { + if (size() == capacity()) { + _expand(); + } + + size_t n = it._n; + size_t p = _next_free(); + fennec::construct(&_table[p].data, x); + if (n == npos) { + if (empty()) { + _root = p; + _table[p].next = npos; + _table[p].prev = npos; + } else { + _table[p].prev = n; + _table[p].next = npos; + _last = n; + } + return; + } + _table[p].next = n; + _table[p].prev = _prev(n); + _table[n].prev = p; + ++_size; + } + void insert(const iterator& it, value_t&& x) { if (size() == capacity()) { _expand(); @@ -120,35 +146,86 @@ public: ++_size; } + void insert(size_t i, const value_t& x) { + assert(i <= size(), "Index out of Bounds"); + if (size() == capacity()) { + _expand(); + } + + size_t n = _walk(min(i, size_t(size() - 1))); + size_t p = _next_free(); + fennec::construct(&_table[p].data, x); + if (n == npos) { + if (empty()) { + _root = p; + _table[p].next = npos; + _table[p].prev = npos; + } else { + _table[p].prev = n; + _table[p].next = npos; + _last = n; + } + return; + } + _table[p].next = n; + _table[p].prev = _prev(n); + _table[n].prev = p; + ++_size; + } + void insert(size_t i, value_t&& x) { assert(i <= size(), "Index out of Bounds"); if (size() == capacity()) { _expand(); } + size_t n = _walk(min(i, size_t(size() - 1))); size_t p = _next_free(); + fennec::construct(&_table[p].data, fennec::forward(x)); if (n == npos) { - _root = p; - _table[p].data = fennec::forward(x); - _table[p].next = npos; - _table[p].prev = npos; + if (empty()) { + _root = p; + _table[p].next = npos; + _table[p].prev = npos; + } else { + _table[p].prev = n; + _table[p].next = npos; + _last = n; + } return; } - _table[p].data = fennec::forward(x); - if (i == size()) { - _table[p].prev = n; - _last = n; - } - else { - _table[p].next = n; - _table[p].prev = _prev(n); - _table[n].prev = p; - } + _table[p].next = n; + _table[p].prev = _prev(n); + _table[n].prev = p; ++_size; } - void insert(size_t i, const value_t& x) { - this->insert(i, elem_t(x)); + template + void emplace(size_t i, ArgsT&&...args) { + assert(i <= size(), "Index out of Bounds"); + if (size() == capacity()) { + _expand(); + } + + size_t n = _walk(min(i, size_t(size() - 1))); + size_t p = _next_free(); + fennec::construct(&_table[p].data, fennec::forward(args)...); + if (n == npos) { + if (empty()) { + _root = p; + _table[p].next = npos; + _table[p].prev = npos; + } else { + _table[p].prev = n; + _table[p].next = npos; + _last = n; + } + return; + } + _table[p].next = n; + _table[p].prev = _prev(n); + _table[n].prev = p; + ++_size; } void push_front(const value_t& x) { @@ -159,6 +236,11 @@ public: this->insert(0, fennec::forward(x)); } + template + void emplace_front(ArgsT...args) { + this->emplace(0, fennec::forward(args)...); + } + void push_back(const value_t& x) { this->insert(_size, x); } @@ -167,6 +249,11 @@ public: this->insert(_size, fennec::forward(x)); } + template + void emplace_back(ArgsT...args) { + this->emplace(_size, fennec::forward(args)...); + } + void erase(size_t i) { size_t j = _walk(i); if (j == npos) return; @@ -199,12 +286,20 @@ public: erase(_size - 1); } + constexpr value_t& front() { + return *_table[_root].data; + } + + constexpr const value_t& front() const { + return *_table[_root].data; + } + constexpr value_t& back() { - return this->operator[](size() - 1); + return *_table[_last].data; } constexpr const value_t& back() const { - return this->operator[](size() - 1); + return *_table[_last].data; } // ITERATOR ============================================================================================================ @@ -329,7 +424,7 @@ private: friend class iterator; constexpr void _expand() { - _table.reallocate(fennec::max(_table.capacity(), size_t(1)) * 2); + _table.creallocate(fennec::max(_table.capacity(), size_t(1)) * 2); } struct node { diff --git a/include/fennec/containers/rdtree.h b/include/fennec/containers/rdtree.h new file mode 100644 index 0000000..ddc3997 --- /dev/null +++ b/include/fennec/containers/rdtree.h @@ -0,0 +1,220 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_CONTAINERS_RDTREE_H +#define FENNEC_CONTAINERS_RDTREE_H + +#include +#include +#include + +namespace fennec +{ + +template> +struct rdtree { +private: + struct node; + +public: + using value_t = TypeT; + using alloc_t = typename allocator_traits::template rebind; + static constexpr size_t root = 0; + static constexpr size_t npos = -1; + +protected: + struct node { + optional value; + size_t parent, child, prev, next; + + template + constexpr node(size_t p, size_t c, size_t v, size_t n, ArgsT&&...args) + : value(fennec::forward(args)...) + , parent(p), child(c), prev(v), next(n) { + } + + constexpr ~node() { + parent = npos; + child = npos; + prev = npos; + next = npos; + } + }; + +public: + +// Constructors ======================================================================================================== + + template + explicit constexpr rdtree(ArgsT&&...args) + : _data(), _freed(), _size(1) { + _data.callocate(10); + fennec::construct(&_data[0], npos, npos, npos, npos, fennec::forward(args)...); + } + + constexpr rdtree(const rdtree& tree) + : _data(tree._data), _freed(tree._freed), _size(tree._size) { + } + + constexpr rdtree(rdtree&& tree) noexcept + : _data(fennec::move(tree._data)), _freed(fennec::move(tree._freed)), _size(tree._size) { + } + + +// Assignment ========================================================================================================== + + friend constexpr rdtree& operator=(rdtree& lhs, const rdtree& rhs) { + for (value_t* it : lhs._data) { + fennec::destruct(it); + } + lhs._data = rhs._data; + lhs._freed = rhs._freed; + lhs._size = rhs._size; + return lhs; + } + + friend constexpr rdtree& operator=(rdtree& lhs, rdtree&& rhs) noexcept { + for (value_t* it : lhs._data) { + fennec::destruct(it); + } + lhs._data = fennec::move(rhs._data); + lhs._freed = fennec::move(rhs._freed); + lhs._size = rhs._size; + return lhs; + } + + +// Access ============================================================================================================== + + constexpr size_t parent(size_t i) const { + return _data[i].parent; + } + + constexpr size_t child(size_t i) const { + return _data[i].child; + } + + constexpr size_t next(size_t i) const { + return _data[i].next; + } + + constexpr size_t prev(size_t i) const { + return _data[i].prev; + } + + constexpr optional& operator[](size_t i) { + return *_data[i].value; + } + + constexpr const optional& operator[](size_t i) const { + return *_data[i].value; + } + + +// Insertion & Deletion ================================================================================================ + + /// + /// \brief Insertion, creates a node in the tree with parent `parent` + /// \param parent the parent node, if `npos` sets the value of the root node + /// \param val the value to insert + /// \returns the index of the created node + constexpr size_t insert(size_t parent, const value_t& val) { + if (parent == npos || _size == 0) { + if (_size == 0) { + fennec::construct(&_data[root], npos, npos, npos, npos, val); + _size = 1; + } else { + _data[root].value = val; + } + return root; + } + + size_t i = _next_free(); + size_t n = child(parent); + _data[parent].child = i; + fennec::construct(&_data[i], parent, npos, n, npos); + return i; + } + + /// + /// \brief Insertion, creates a node in the tree with parent `parent` + /// \param parent the parent node, if `npos` sets the value of the root node + /// \param val the value to insert + /// \returns the index of the created node + constexpr size_t insert(size_t parent, value_t&& val) { + if (parent == npos || _size == 0) { + if (_size == 0) { + fennec::construct(&_data[root], npos, npos, npos, npos, fennec::forward(val)); + _size = 1; + } else { + _data[root].value = fennec::forward(val); + } + return root; + } + + size_t i = _next_free(); + size_t n = child(parent); + _data[parent].child = i; + fennec::construct(&_data[i], parent, npos, n, npos); + return i; + } + + /// + /// \brief Erase a node in the tree and all of it's children + /// \param i the index of the node + constexpr void erase(size_t i) { + list queue; + if (child(i) != npos) { + queue.push_back(i); + } + + while (not queue.empty()) { + size_t n = queue.front(); queue.pop_front(); + if (next(n) != npos) queue.push_back(next(n)); + if (child(n) != npos) queue.push_back(child(n)); + fennec::destruct(&_data[n]); + _freed.push_back(n); + } + + fennec::destruct(&_data[i]); + _freed.push_back(i); + } + + +protected: + allocation _data; + list _freed; + size_t _size; + + void _expand() { + _data.creallocate(_data.capacity() * 2); + } + + size_t _next_free() { + size_t next = _size + 1; + if (not _freed.empty()) { + next = _freed.back(); + _freed.pop_back(); + } + return next; + } +}; + +} + +#endif // FENNEC_CONTAINERS_RDTREE_H diff --git a/include/fennec/containers/set.h b/include/fennec/containers/set.h index 57a2c38..ca252e4 100644 --- a/include/fennec/containers/set.h +++ b/include/fennec/containers/set.h @@ -22,6 +22,7 @@ // https://programming.guide/robin-hood-hashing.html #include +#include #include #include #include @@ -58,6 +59,7 @@ public: : _alloc() , _hash() , _size(0) + , _sumpsl(0) , _load(default_load) { }; @@ -65,6 +67,7 @@ public: : _alloc() , _hash(hash) , _size(0) + , _sumpsl(0) , _load(default_load) { } @@ -72,6 +75,7 @@ public: : _alloc() , _hash(hash) , _size(0) + , _sumpsl(0) , _load(default_load) { } @@ -79,6 +83,7 @@ public: : _alloc(alloc) , _hash() , _size(0) + , _sumpsl(0) , _load(default_load) { } @@ -86,6 +91,7 @@ public: : _alloc(alloc) , _hash() , _size(0) + , _sumpsl(0) , _load(default_load) { } @@ -93,6 +99,7 @@ public: : _alloc(alloc) , _hash(hash) , _size(0) + , _sumpsl(0) , _load(default_load) { } @@ -100,6 +107,7 @@ public: : _alloc(alloc) , _hash(hash) , _size(0) + , _sumpsl(0) , _load(default_load) { } @@ -107,6 +115,7 @@ public: : _alloc(alloc) , _hash(hash) , _size(0) + , _sumpsl(0) , _load(default_load) { } @@ -114,6 +123,7 @@ public: : _alloc(alloc) , _hash(hash) , _size(0) + , _sumpsl(0) , _load(default_load) { } @@ -121,13 +131,16 @@ public: : _alloc(set._alloc) , _hash(set._hash) , _size(set._size) - , _load(default_load) { + , _sumpsl(set._sumpsl) + , _load(set._load) { } constexpr set(set&& set) noexcept : _alloc(fennec::move(set._alloc)) , _hash(fennec::move(set._hash)) - , _size(fennec::move(set._size)) { + , _size(fennec::move(set._size)) + , _sumpsl(set._sumpsl) + , _load(set._load) { } constexpr ~set() = default; @@ -153,13 +166,14 @@ public: return; } if (psl > _alloc[i].psl) { // When psl is higher, swap - fennec::swap(*_alloc[i].value, value); + _sumpsl += psl - _alloc[i].psl; fennec::swap(_alloc[i].psl, psl); + fennec::swap(*_alloc[i].value, value); } i = (i + 1) % capacity(); ++psl; } _alloc[i].value = fennec::move(value); - _alloc[i].psl = psl; + _sumpsl += (_alloc[i].psl = psl); ++_size; } @@ -175,15 +189,41 @@ public: } constexpr iterator find(const elem_t& val) const { - size_t i = _hash(val) % capacity(); // Initial search index - int psl = 0; + size_t s = _hash(val) % capacity(); // Initial search index + int psl = (_size != 0) ? _sumpsl / _size : 0; // Initial psl + size_t i = (s + psl) % capacity(); // Median search + size_t n = 0; - // Loop while there is a value and its psl is greater than our probe - while (_alloc[i].value && _alloc[i].psl <= psl) { - if (_equal(*_alloc[i].value, val)) { + // Check the first element; + if (_alloc[i].psl >= psl && _alloc[i].value) { + if (*_alloc[i].value == val) { return iterator(this, i); } - i = (i + 1) % capacity(); ++psl; + } + + // Loop while there is a value and its psl is greater than our probe + while (true) { + ++n; + size_t i0 = (i + capacity() - n) % capacity(); // Prevent index underflow + size_t i1 = (i + n) % capacity(); + int p0 = psl - n, p1 = psl + n; + bool c0 = false, c1 = false; + + if ((c0 = (p0 > 0 && _alloc[i0].psl >= p0)) && _alloc[i0].value) { + if (*_alloc[i0].value == val) { + return iterator(this, i); + } + } + + if ((c1 = (_alloc[i1].psl >= p1)) && _alloc[i1].value) { + if (*_alloc[i1].value == val) { + return iterator(this, i); + } + } + + if (not(c0 or c1)) { + break; + } } return iterator(this, npos); @@ -217,14 +257,14 @@ public: } _alloc[i].value = nullopt; + _sumpsl -= _alloc[i].psl; --_size; size_t p = i; while (_alloc[i = (i + 1) % capacity()].value) { - size_t psl = _alloc[i].psl; - if (psl == 0) break; + if (_alloc[i].psl == 0) break; fennec::swap(_alloc[i - 1].value, _alloc[i].value); - _alloc[p].psl = psl - 1; + --_alloc[p].psl, --_sumpsl; p = i; } } @@ -316,10 +356,11 @@ private: } allocation _alloc; - hash_t _hash; + hash_t _hash; equal_t _equal; - size_t _size; - double _load; + size_t _size; + size_t _sumpsl; + double _load; }; } diff --git a/include/fennec/renderers/opengl/legacy.h b/include/fennec/core/system.h similarity index 65% rename from include/fennec/renderers/opengl/legacy.h rename to include/fennec/core/system.h index e610e0f..d8a35dc 100644 --- a/include/fennec/renderers/opengl/legacy.h +++ b/include/fennec/core/system.h @@ -16,12 +16,32 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_RENDERERS_OPENGL_LEGACY_H -#define FENNEC_RENDERERS_OPENGL_LEGACY_H +#ifndef FENNEC_CORE_SYSTEM_H +#define FENNEC_CORE_SYSTEM_H +#include -/* - * This should be implemented using the OpenGL ES 2.0 profile - * https://registry.khronos.org/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf - */ +namespace fennec +{ -#endif // FENNEC_RENDERERS_OPENGL_LEGACY_H +class system { +public: + using tick_f = void (*)(system*, double); + using frame_f = void (*)(system*, size_t); + + const string name; + const tick_f tick; + const frame_f frame; + + system(const cstring& name, tick_f tick, frame_f frame) + : name(name), tick(tick), frame(frame) { + } + + virtual ~system() = default; + + virtual void init() = 0; + virtual void shutdown() = 0; +}; + +} + +#endif // FENNEC_CORE_SYSTEM_H diff --git a/include/fennec/fproc/filesystem/detail/_stdio.h b/include/fennec/langproc/filesystem/detail/_stdio.h similarity index 87% rename from include/fennec/fproc/filesystem/detail/_stdio.h rename to include/fennec/langproc/filesystem/detail/_stdio.h index 59180c5..f34b5d5 100644 --- a/include/fennec/fproc/filesystem/detail/_stdio.h +++ b/include/fennec/langproc/filesystem/detail/_stdio.h @@ -16,9 +16,9 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H -#define FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H +#ifndef FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H +#define FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H #include -#endif // FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H +#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H diff --git a/include/fennec/fproc/filesystem/file.h b/include/fennec/langproc/filesystem/file.h similarity index 96% rename from include/fennec/fproc/filesystem/file.h rename to include/fennec/langproc/filesystem/file.h index a8625f1..87fe5bf 100644 --- a/include/fennec/fproc/filesystem/file.h +++ b/include/fennec/langproc/filesystem/file.h @@ -16,14 +16,14 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_IO_FILE_H -#define FENNEC_FPROC_IO_FILE_H +#ifndef FENNEC_LANGPROC_IO_FILE_H +#define FENNEC_LANGPROC_IO_FILE_H -#include +#include -#include -#include -#include +#include +#include +#include namespace fennec { @@ -34,7 +34,7 @@ namespace fennec /// fmode_binary and fmode_wide are independent of the other modes /// /// \details Valid Flag Combinations -/// +///
///
Flags /// Description /// @@ -301,4 +301,4 @@ private: } -#endif // FENNEC_FPROC_IO_FILE_H +#endif // FENNEC_LANGPROC_IO_FILE_H diff --git a/include/fennec/fproc/filesystem/path.h b/include/fennec/langproc/filesystem/path.h similarity index 97% rename from include/fennec/fproc/filesystem/path.h rename to include/fennec/langproc/filesystem/path.h index 2b4675a..35b29c8 100644 --- a/include/fennec/fproc/filesystem/path.h +++ b/include/fennec/langproc/filesystem/path.h @@ -16,10 +16,10 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_IO_PATH_H -#define FENNEC_FPROC_IO_PATH_H +#ifndef FENNEC_LANGPROC_IO_PATH_H +#define FENNEC_LANGPROC_IO_PATH_H -#include +#include namespace fennec { @@ -233,4 +233,4 @@ private: } -#endif // FENNEC_FPROC_IO_PATH_H +#endif // FENNEC_LANGPROC_IO_PATH_H diff --git a/include/fennec/fproc/strings/cstring.h b/include/fennec/langproc/strings/cstring.h similarity index 98% rename from include/fennec/fproc/strings/cstring.h rename to include/fennec/langproc/strings/cstring.h index 63e2eb8..1167b4c 100644 --- a/include/fennec/fproc/strings/cstring.h +++ b/include/fennec/langproc/strings/cstring.h @@ -16,10 +16,10 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_STRINGS_CSTRING_H -#define FENNEC_FPROC_STRINGS_CSTRING_H +#ifndef FENNEC_LANGPROC_STRINGS_CSTRING_H +#define FENNEC_LANGPROC_STRINGS_CSTRING_H -#include +#include #include #include @@ -337,4 +337,4 @@ struct hash : hash { } -#endif // FENNEC_FPROC_STRINGS_CSTRING_H +#endif // FENNEC_LANGPROC_STRINGS_CSTRING_H diff --git a/include/fennec/fproc/strings/detail/_ctype.h b/include/fennec/langproc/strings/detail/_ctype.h similarity index 87% rename from include/fennec/fproc/strings/detail/_ctype.h rename to include/fennec/langproc/strings/detail/_ctype.h index e5ee76e..32df664 100644 --- a/include/fennec/fproc/strings/detail/_ctype.h +++ b/include/fennec/langproc/strings/detail/_ctype.h @@ -16,10 +16,10 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H -#define FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H +#ifndef FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H +#define FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H #include #include -#endif // FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H +#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H diff --git a/include/fennec/fproc/strings/detail/_locale.h b/include/fennec/langproc/strings/detail/_locale.h similarity index 87% rename from include/fennec/fproc/strings/detail/_locale.h rename to include/fennec/langproc/strings/detail/_locale.h index e13dcb7..2e53936 100644 --- a/include/fennec/fproc/strings/detail/_locale.h +++ b/include/fennec/langproc/strings/detail/_locale.h @@ -16,9 +16,9 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H -#define FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H +#ifndef FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H +#define FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H #include -#endif // FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H +#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H diff --git a/include/fennec/fproc/strings/locale.h b/include/fennec/langproc/strings/locale.h similarity index 87% rename from include/fennec/fproc/strings/locale.h rename to include/fennec/langproc/strings/locale.h index 87b2600..93b5b32 100644 --- a/include/fennec/fproc/strings/locale.h +++ b/include/fennec/langproc/strings/locale.h @@ -16,10 +16,10 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_STRINGS_LOCALE_H -#define FENNEC_FPROC_STRINGS_LOCALE_H +#ifndef FENNEC_LANGPROC_STRINGS_LOCALE_H +#define FENNEC_LANGPROC_STRINGS_LOCALE_H -#include +#include namespace fennec { @@ -41,4 +41,4 @@ using ::localeconv; } -#endif // FENNEC_FPROC_STRINGS_LOCALE_H +#endif // FENNEC_LANGPROC_STRINGS_LOCALE_H diff --git a/include/fennec/fproc/strings/string.h b/include/fennec/langproc/strings/string.h similarity index 98% rename from include/fennec/fproc/strings/string.h rename to include/fennec/langproc/strings/string.h index 77276cb..378279c 100644 --- a/include/fennec/fproc/strings/string.h +++ b/include/fennec/langproc/strings/string.h @@ -16,11 +16,11 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_STRINGS_STRING_H -#define FENNEC_FPROC_STRINGS_STRING_H +#ifndef FENNEC_LANGPROC_STRINGS_STRING_H +#define FENNEC_LANGPROC_STRINGS_STRING_H -#include -#include +#include +#include #include @@ -433,4 +433,4 @@ struct hash : hash { } -#endif // FENNEC_FPROC_STRINGS_STRING_H +#endif // FENNEC_LANGPROC_STRINGS_STRING_H diff --git a/include/fennec/fproc/strings/wcstring.h b/include/fennec/langproc/strings/wcstring.h similarity index 98% rename from include/fennec/fproc/strings/wcstring.h rename to include/fennec/langproc/strings/wcstring.h index 637d7a9..42a4ead 100644 --- a/include/fennec/fproc/strings/wcstring.h +++ b/include/fennec/langproc/strings/wcstring.h @@ -16,10 +16,10 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_STRINGS_wcstring_H -#define FENNEC_FPROC_STRINGS_wcstring_H +#ifndef FENNEC_LANGPROC_STRINGS_wcstring_H +#define FENNEC_LANGPROC_STRINGS_wcstring_H -#include +#include #include #include @@ -323,4 +323,4 @@ private: } -#endif // FENNEC_FPROC_STRINGS_wcstring_H +#endif // FENNEC_LANGPROC_STRINGS_wcstring_H diff --git a/include/fennec/fproc/strings/wstring.h b/include/fennec/langproc/strings/wstring.h similarity index 98% rename from include/fennec/fproc/strings/wstring.h rename to include/fennec/langproc/strings/wstring.h index e6d4a50..e2af73f 100644 --- a/include/fennec/fproc/strings/wstring.h +++ b/include/fennec/langproc/strings/wstring.h @@ -16,11 +16,11 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_FPROC_wstringS_wstring_H -#define FENNEC_FPROC_wstringS_wstring_H +#ifndef FENNEC_LANGPROC_wstringS_wstring_H +#define FENNEC_LANGPROC_wstringS_wstring_H -#include -#include +#include +#include #include @@ -415,4 +415,4 @@ private: } -#endif // FENNEC_FPROC_wstringS_wstring_H +#endif // FENNEC_LANGPROC_wstringS_wstring_H diff --git a/include/fennec/memory/allocator.h b/include/fennec/memory/allocator.h index 662985c..92fac59 100644 --- a/include/fennec/memory/allocator.h +++ b/include/fennec/memory/allocator.h @@ -532,24 +532,58 @@ public: _capacity = n; } + /// + /// \brief Reallocate the block with a new size. + /// Contents are copied to the new allocation. + constexpr void creallocate(size_t n, align_t align = zero()) noexcept { + if (_data == nullptr) { + callocate(n, align); + } - // Access ============================================================================================================== + value_t* old = _data; + _data = _alloc.allocate(n); + fennec::memcpy(static_cast(_data), old, min(_capacity, n) * sizeof(T)); + if (n > _capacity) { + fennec::memset(static_cast(_data + _capacity), 0, n - _capacity); + } + _alloc.deallocate(old); + _capacity = n; + } + + +// Access ============================================================================================================== constexpr value_t& operator[](size_t i) { - assertd(i < size(), "Array Out of Bounds"); + assertd(i < capacity(), "Array Out of Bounds"); return _data[i]; } constexpr value_t operator[](size_t i) const requires is_fundamental_v { - assertd(i < size(), "Array Out of Bounds"); + assertd(i < capacity(), "Array Out of Bounds"); return _data[i]; } constexpr const value_t& operator[](size_t i) const { - assertd(i < size(), "Array Out of Bounds"); + assertd(i < capacity(), "Array Out of Bounds"); return _data[i]; } + value_t* begin() { + return _data; + } + + value_t* end() { + return _data + capacity(); + } + + const value_t* begin() const { + return _data; + } + + const value_t* end() const { + return _data + capacity(); + } + // Modification ======================================================================================================== diff --git a/include/fennec/platform/interface/display.h b/include/fennec/platform/interface/display.h index d650b6b..c0e8713 100644 --- a/include/fennec/platform/interface/display.h +++ b/include/fennec/platform/interface/display.h @@ -19,7 +19,7 @@ #ifndef FENNEC_PLATFORM_INTERFACE_DISPLAY_H #define FENNEC_PLATFORM_INTERFACE_DISPLAY_H -#include +#include #include #include #include diff --git a/include/fennec/platform/interface/gfxcontext.h b/include/fennec/platform/interface/gfxcontext.h index 7b2ff94..c94b088 100644 --- a/include/fennec/platform/interface/gfxcontext.h +++ b/include/fennec/platform/interface/gfxcontext.h @@ -19,7 +19,7 @@ #ifndef FENNEC_PLATFORM_INTERFACE_GFXCONTEXT_H #define FENNEC_PLATFORM_INTERFACE_GFXCONTEXT_H -#include +#include #include #include diff --git a/include/fennec/platform/interface/platform.h b/include/fennec/platform/interface/platform.h index 9a7ce12..df7b157 100644 --- a/include/fennec/platform/interface/platform.h +++ b/include/fennec/platform/interface/platform.h @@ -20,8 +20,8 @@ #define FENNEC_PLATFORM_INTERFACE_PLATFORM_H #include -#include -#include +#include +#include #include #include diff --git a/include/fennec/platform/interface/window.h b/include/fennec/platform/interface/window.h index 3ad2f50..7614af6 100644 --- a/include/fennec/platform/interface/window.h +++ b/include/fennec/platform/interface/window.h @@ -20,7 +20,7 @@ #define FENNEC_PLATFORM_INTERFACE_WINDOW_H #include -#include +#include #include namespace fennec diff --git a/include/fennec/renderers/interface/renderer.h b/include/fennec/renderers/interface/renderer.h index 0732b5e..20ff169 100644 --- a/include/fennec/renderers/interface/renderer.h +++ b/include/fennec/renderers/interface/renderer.h @@ -19,4 +19,170 @@ #ifndef FENNEC_RENDERERS_INTERFACE_RENDERER_H #define FENNEC_RENDERERS_INTERFACE_RENDERER_H +#include +#include +#include +#include +#include +#include + +/* + * Some ramblings on deciding what objects are needed to support the features in PLANNING.md + * + * + * Definitions: + * Static Mesh -> A mesh whose number of vertices and attributes does not change after creation + * Object -> A static mesh instance + * Skeletal Mesh -> A static mesh with support for skinned rigs + * Animation -> A set of keys for a skeletal mesh + * Puppet -> A skeletal mesh instance + * Static Object -> An object whose transform does not change after scene start + * Dynamic Object -> An object whose transform can change after scene start, all puppets must be dynamic objects + * Static Light -> A light whose transform does not change after scene start. Other attributes may change, which will + * be specified per light + * Dynamic Light -> A light whose transform can change after scene start, including all attributes + * + * Static mesh rendering + * Skeletal mesh rendering + * Lights with or without shadows (PCSS for soft shadowing) + * - Sun Light + * - Skybox + * - Point Light + * - Spotlight + * - Area light + * Post-Processing + * + * Materials + */ + +namespace fennec +{ + +class renderer3d { +public: + // These refer to assets + // texture -> 8-bit type, 24-bit id (256, 16,777,216) + // mesh -> 32-bit id (4,294,967,296) + // skeleton -> 32-bit id (4,294,967,296) + // animation -> 32-bit id (4,294,967,296) + // shader -> 32-bit id (4,294,967,296) + + // model -> 8-bit flag, 24-bit id (8, 16,777,216) + // puppet -> 32-bit id (4,294,967,296) + // light -> 8-bit type, 24-bit id (256, 16,777,216) + // material -> 32-bit id (4,294,967,296) + +// TYPEDEFS & CONSTANTS ================================================================================================ + + using uid_t = uint32_t; + + static constexpr uid_t null = -1; + static constexpr uint_t max_bone_weights = 8; + + +// ENUMS =============================================================================================================== + + enum format_ : uint8_t { + format_r = 0, + format_rg, + format_rgb, + format_rgba, + format_shadow, // TODO: decide whether end-users may create shadow buffers + + format_count, + format_last = format_count - 1, + }; + + enum texture_ : uint8_t { + texture_2d = 0, + texture_3d, + texture_cubemap, + }; + + enum light_ : uint8_t { + light_sun = 0, + light_sky, + light_point, + light_spot, + light_area, + }; + + enum iterp_ : uint8_t { + iterp_step = 0, + iterp_linear, + iterp_spherical, + iterp_cubic, + }; + + +// STRUCTURES ========================================================================================================== + + struct mesh_vertex { + vec3 location; + vec3 normal; + vec3 tangent; + vec2 uv; + }; + + struct skin_vertex { + vec3 location; + vec3 normal; + vec3 tangent; + vec2 uv; + + uint32_t bones[max_bone_weights]; + uint32_t weights[max_bone_weights]; + }; + + struct bone { + mat4 localSpace; // I was going to use quaternions, but Assimp, glTF, FBX, Unity, Unreal, and Godot all use matrices + }; + + struct skeleton { + mat4 root; + uint boneStart, boneEnd; // APIs job to figure out how to store bones, should be in a SSBO regardless of API + }; + + // Wrapper for animation keys + template + struct key { + double time; + ValueT val; + uint8_t mode; + }; + + // Wrapper for a track, essentially the keyframes for a single bone + struct track { + uint posStart, posEnd; // APIs job to figure out how to store keys, should be in a SSBO regardless of API + uint rotStart, rotEnd; + uint sclStart, sclEnd; + }; + + struct animation { + uint trkStart, trkEnd; // APIs job to figure out how to store tracks, should be in a SSBO regardless of API + }; + + +// FUNCTIONS =========================================================================================================== + + virtual uid_t create_mesh(const dynarray& indices, const dynarray& vertices) = 0; + virtual void release_mesh(uid_t id); + + // TODO: virtual uid_t create_skeleton() + // TODO: virtual uid_t create_shader() + + virtual uid_t create_texture(uint8_t type, uint8_t format, bool hdr) = 0; + virtual void release_texture(uid_t); + + + + // TODO: virtual uid_t create_light() + + virtual ~renderer3d() = default; +private: +}; + + +} + #endif // FENNEC_RENDERERS_INTERFACE_RENDERER_H diff --git a/include/fennec/renderers/opengl/fallback.h b/include/fennec/renderers/opengl/fallback.h index d23ab59..f872e64 100644 --- a/include/fennec/renderers/opengl/fallback.h +++ b/include/fennec/renderers/opengl/fallback.h @@ -29,6 +29,8 @@ * - ARB_compute_shader * - ARB_shader_image_load_store * - ARB_texture_cube_map_array + * + * This will support all mobile devices since 2012 */ #endif // FENNEC_RENDERERS_OPENGL_FALLBACK_H diff --git a/include/fennec/renderers/opengl/modern.h b/include/fennec/renderers/opengl/modern.h index 58c1427..e183c35 100644 --- a/include/fennec/renderers/opengl/modern.h +++ b/include/fennec/renderers/opengl/modern.h @@ -29,6 +29,8 @@ * - ARB_compute_shader * - ARB_shader_image_load_store * - ARB_texture_cube_map_array + * + * This will support >91.31% of devices on Steam, including all Desktop GPUs and iGPUs since 2012 */ #endif // FENNEC_RENDERERS_OPENGL_MODERN_H diff --git a/include/fennec/scene/component.h b/include/fennec/scene/component.h new file mode 100644 index 0000000..4a9376b --- /dev/null +++ b/include/fennec/scene/component.h @@ -0,0 +1,69 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_SCENE_COMPONENT_H +#define FENNEC_SCENE_COMPONENT_H + +#include +#include +#include + +namespace fennec +{ + +class component { +public: + using component_create = component (*)(size_t); + using component_find = component* (*)(size_t); + using component_erase = void (*)(size_t); + + struct type { + string name; + component_create create; + component_find find; + component_erase erase; + }; + +private: + static dynarray& _type_list() { + static dynarray type_list; + return type_list; + } + + static void _register_type(uint64_t id, const cstring& name, component_create create, component_find find, component_erase erase) { + dynarray& type_list = _type_list(); + if (id > type_list.size()) { + type_list.resize(id + 1); + } + type_list[id] = { name, create, find, erase }; + } + +public: + template + static void register_type(const cstring& name, component_create create, component_find find, component_erase erase) { + component::_register_type(typeuuid(), name, create, find, erase); + } + + static const dynarray& type_list() { + return _type_list(); + } +}; + +} + +#endif // FENNEC_SCENE_COMPONENT_H diff --git a/include/fennec/scene/scene.h b/include/fennec/scene/scene.h new file mode 100644 index 0000000..64a1fee --- /dev/null +++ b/include/fennec/scene/scene.h @@ -0,0 +1,60 @@ +// ===================================================================================================================== +// fennec, a free and open source game engine +// Copyright © 2025 Medusa Slockbower +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// ===================================================================================================================== + +#ifndef FENNEC_CORE_SCENE_H +#define FENNEC_CORE_SCENE_H +#include +#include + +namespace fennec +{ + +class scene : public rdtree { +public: + size_t operator[](const cstring& name) const { + list parse; + parse.push_back(root); + while (not parse.empty()) { + if (*_data[parse.front()].value == name) { + return parse.front(); + } + parse.push_back(child(parse.front())); + parse.push_back(next(parse.front())); + parse.pop_front(); + } + return npos; + } + + size_t operator[](const string& name) const { + list parse; + parse.push_back(root); + while (not parse.empty()) { + if (*_data[parse.front()].value == name) { + return parse.front(); + } + parse.push_back(child(parse.front())); + parse.push_back(next(parse.front())); + parse.pop_front(); + } + return npos; + } +}; + +} + +#endif // FENNEC_CORE_SCENE_H diff --git a/source/fproc/filesystem/file.cpp b/source/langproc/filesystem/file.cpp similarity index 99% rename from source/fproc/filesystem/file.cpp rename to source/langproc/filesystem/file.cpp index d65b605..0ab3801 100644 --- a/source/fproc/filesystem/file.cpp +++ b/source/langproc/filesystem/file.cpp @@ -20,8 +20,8 @@ #include #include -#include -#include +#include +#include #ifdef FENNEC_COMPILER_MSVC diff --git a/source/fproc/filesystem/path.cpp b/source/langproc/filesystem/path.cpp similarity index 97% rename from source/fproc/filesystem/path.cpp rename to source/langproc/filesystem/path.cpp index b1f61c0..a4515f4 100644 --- a/source/fproc/filesystem/path.cpp +++ b/source/langproc/filesystem/path.cpp @@ -17,7 +17,7 @@ // ===================================================================================================================== -#include +#include namespace fennec { diff --git a/source/platform/linux/platform.cpp b/source/platform/linux/platform.cpp index f8772aa..7b0029f 100644 --- a/source/platform/linux/platform.cpp +++ b/source/platform/linux/platform.cpp @@ -16,7 +16,7 @@ // along with this program. If not, see . // ===================================================================================================================== -#include +#include #include #include diff --git a/source/platform/opengl/egl/context.cpp b/source/platform/opengl/egl/context.cpp index d6ffd2e..1cd035c 100644 --- a/source/platform/opengl/egl/context.cpp +++ b/source/platform/opengl/egl/context.cpp @@ -16,7 +16,7 @@ // along with this program. If not, see . // ===================================================================================================================== -#include +#include #include #include #include diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bd6cb84..e92764e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,10 +20,10 @@ add_executable(fennec-test main.cpp tests/math/test_exponential.h tests/math/test_relational.h tests/math/test_trigonometric.h - tests/fproc/test_strings.h - tests/fproc/strings/test_cstring.h - tests/test_fproc.h - tests/fproc/test_io.h + tests/langproc/test_strings.h + tests/langproc/strings/test_cstring.h + tests/test_langproc.h + tests/langproc/test_io.h printing.h tests/math/test_ext.h tests/math/ext/test_quaternion.h diff --git a/test/main.cpp b/test/main.cpp index e661d7f..a92ba2c 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -24,7 +24,7 @@ #include "test.h" #include "tests/test_containers.h" -#include "tests/test_fproc.h" +#include "tests/test_langproc.h" #include "tests/test_platform.h" @@ -51,7 +51,7 @@ int main(int, char **) fennec_test_header("format processing library"); fennec_test_spacer(2); - fennec::test::fennec_test_fproc(); + fennec::test::fennec_test_langproc(); fennec_test_spacer(3); fennec_test_header("platform library"); diff --git a/test/printing.h b/test/printing.h index 6147f32..5f7cde4 100644 --- a/test/printing.h +++ b/test/printing.h @@ -20,8 +20,8 @@ #define FENNEC_TEST_PRINTING_H #include -#include -#include +#include +#include #include #include diff --git a/test/tests/containers/test_map.h b/test/tests/containers/test_map.h index 904fb24..a0afb8d 100644 --- a/test/tests/containers/test_map.h +++ b/test/tests/containers/test_map.h @@ -20,7 +20,7 @@ #define FENNEC_TEST_CONTAINERS_MAP_H #include -#include +#include namespace fennec::test { diff --git a/test/tests/fproc/strings/test_cstring.h b/test/tests/langproc/strings/test_cstring.h similarity index 87% rename from test/tests/fproc/strings/test_cstring.h rename to test/tests/langproc/strings/test_cstring.h index b20deeb..6cacea9 100644 --- a/test/tests/fproc/strings/test_cstring.h +++ b/test/tests/langproc/strings/test_cstring.h @@ -16,15 +16,15 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_TEST_FPROC_STRINGS_CSTRING_H -#define FENNEC_TEST_FPROC_STRINGS_CSTRING_H +#ifndef FENNEC_TEST_LANGPROC_STRINGS_CSTRING_H +#define FENNEC_TEST_LANGPROC_STRINGS_CSTRING_H -#include +#include namespace fennec::test { - inline void fennec_test_fproc_strings_cstring() + inline void fennec_test_langproc_strings_cstring() { static char test_string[] = "Hello World!"; static const char test_string_const[] = "Hello World!"; @@ -48,4 +48,4 @@ namespace fennec::test } -#endif // FENNEC_TEST_FPROC_STRINGS_CSTRING_H +#endif // FENNEC_TEST_LANGPROC_STRINGS_CSTRING_H diff --git a/test/tests/fproc/test_io.h b/test/tests/langproc/test_io.h similarity index 92% rename from test/tests/fproc/test_io.h rename to test/tests/langproc/test_io.h index 0001eec..63e1408 100644 --- a/test/tests/fproc/test_io.h +++ b/test/tests/langproc/test_io.h @@ -16,18 +16,18 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_TEST_FPROC_IO_H -#define FENNEC_TEST_FPROC_IO_H +#ifndef FENNEC_TEST_LANGPROC_IO_H +#define FENNEC_TEST_LANGPROC_IO_H #include "../../test.h" -#include -#include +#include +#include namespace fennec::test { - inline void fennec_test_fproc_io() { + inline void fennec_test_langproc_io() { fennec_test_section("utilities"); @@ -89,4 +89,4 @@ namespace fennec::test } -#endif // FENNEC_TEST_FPROC_IO_H +#endif // FENNEC_TEST_LANGPROC_IO_H diff --git a/test/tests/fproc/test_strings.h b/test/tests/langproc/test_strings.h similarity index 85% rename from test/tests/fproc/test_strings.h rename to test/tests/langproc/test_strings.h index b3fba97..b4a14f3 100644 --- a/test/tests/fproc/test_strings.h +++ b/test/tests/langproc/test_strings.h @@ -16,8 +16,8 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_TEST_FPROC_STRINGS_H -#define FENNEC_TEST_FPROC_STRINGS_H +#ifndef FENNEC_TEST_LANGPROC_STRINGS_H +#define FENNEC_TEST_LANGPROC_STRINGS_H #include "../../test.h" #include "./strings/test_cstring.h" @@ -25,11 +25,11 @@ namespace fennec::test { - inline void fennec_test_fproc_strings() + inline void fennec_test_langproc_strings() { fennec_test_subheader("cstring"); fennec_test_spacer(2); - fennec_test_fproc_strings_cstring(); + fennec_test_langproc_strings_cstring(); fennec_test_spacer(3); // TODO @@ -37,4 +37,4 @@ namespace fennec::test } -#endif // FENNEC_TEST_FPROC_STRINGS_H +#endif // FENNEC_TEST_LANGPROC_STRINGS_H diff --git a/test/tests/test_fproc.h b/test/tests/test_langproc.h similarity index 82% rename from test/tests/test_fproc.h rename to test/tests/test_langproc.h index 88e103d..912b36d 100644 --- a/test/tests/test_fproc.h +++ b/test/tests/test_langproc.h @@ -16,26 +16,26 @@ // along with this program. If not, see . // ===================================================================================================================== -#ifndef FENNEC_TEST_FPROC_H -#define FENNEC_TEST_FPROC_H +#ifndef FENNEC_TEST_LANGPROC_H +#define FENNEC_TEST_LANGPROC_H #include "../test.h" -#include "./fproc/test_strings.h" -#include "./fproc/test_io.h" +#include "./langproc/test_strings.h" +#include "./langproc/test_io.h" namespace fennec::test { - inline void fennec_test_fproc() { + inline void fennec_test_langproc() { fennec_test_header("strings"); fennec_test_spacer(2); - fennec_test_fproc_strings(); + fennec_test_langproc_strings(); fennec_test_spacer(3); fennec_test_header("io"); fennec_test_spacer(2); - fennec_test_fproc_io(); + fennec_test_langproc_io(); fennec_test_spacer(3); // TODO @@ -43,4 +43,4 @@ namespace fennec::test } -#endif // FENNEC_TEST_FPROC_H +#endif // FENNEC_TEST_LANGPROC_H