Compare commits

..

2 Commits

Author SHA1 Message Date
3d42dea9eb - Started interface for renderers
- Renamed fproc -> langproc (I'll probably never settle on a naming convention for this)
 - Refactored set to use median psl
2025-08-02 13:17:20 -04:00
3d4ea4398a - Setup Contexts to pull more info from the GPU
- Started outlining OpenGL implementation
2025-07-28 21:06:52 -04:00
41 changed files with 1170 additions and 201 deletions

View File

@@ -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 =============================================================================================================
@@ -189,6 +189,11 @@ add_library(fennec STATIC
# EXTRA SOURCES ========================================================================================================
${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)

View File

@@ -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
@@ -162,22 +162,31 @@ management would be used.
Platform support will be implemented in the following order:
- Linux/BSD
- Wayland
- OpenGL (EGL)
- OpenGL (EGL)
- XKB
- PulseAudio
- Vulkan
- X11
- OpenGL (EGL)
- ALSA
- Vulkan
- Microsoft Windows
- XInput
- OpenGL
- DirectSound
- OpenGL (WGL)
- WASAPI
- Vulkan
- Android
- OpenGL ES
- macOS
- iOS
- AAudio
- openslES
- macOS/iOS
- cocoa
- OpenGL
- Core Audio
- Vulkan
- Metal
Linux Wayland will be implemented first. Once setup, the core engine will be implemented and tested on top of Wayland.
Once the engine is in a stable state, then support for other platforms will be resumed.
Most consoles will never get official platform support due to NDAs which conflict with the principles of this engine.
fennec will avoid using proprietary libraries except when strictly necessary, such as support for Windows and MacOS.
@@ -238,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
@@ -247,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
@@ -285,8 +294,67 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi
- SVG
- TTF
- 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
@@ -294,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
@@ -328,8 +396,8 @@ in their operation order:
- AI
- **Physics**
- Newtonian Commit
- Apply Forces (Updates Acceleration and Torque)
- Apply Torque & Acceleration (Updates Velocities)
- Apply Forces (Updates Accelerations)
- Acceleration (Updates Velocities)
- Apply Velocities (Updates Position and Rotation)
- Constraint Resolution
- Collision Detection
@@ -453,6 +521,15 @@ This allows the GPU to draw every single deferred rendered mesh in a single draw
Specifications for debugging views via early breaks are included in the stages.
There will be three profiles for OpenGL implementation:
- modern
- fallback
- legacy
All profiles will have the same feature set, however their implementations will differ.
The modern context will use up-to-date features to get as much performance out of the pipeline as
possible.
### Structures (`gfx3d`)
@@ -464,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 RGBA Texture `4096, 2048, 1024, 512` (8)
- 8-Bit R Cubemap `1024, 512, 256, 128` (4)
- 8-Bit RGB Cubemap `1024, 512, 256, 128` (4)
* 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 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
@@ -501,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
@@ -567,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

View File

@@ -23,18 +23,9 @@ else()
find_package(OpenGL)
endif()
if(TARGET OpenGL::GL) # Core OpenGL Desktop Profile
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::OpenGL)
if(TARGET OpenGL::GL)
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GL)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_OPENGL=1)
elseif(TARGET OpenGL::GLES3) # OpenGL for Embedded Systems 3
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GLES3)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_GLES3=1)
elseif (TARGET OpenGL::GLES2) # OpenGL for Embedded Systems 2
list(APPEND FENNEC_LINK_LIBRARIES OpenGL::GLES2)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_GLES2=1)
else()
message(FATAL_ERROR "No Suitable OpenGL implementation found.")
endif()
@@ -48,5 +39,8 @@ if(FENNEC_GRAPHICS_WANT_EGL)
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_GRAPHICS_EGL=1)
list(APPEND FENNEC_EXTRA_SOURCES
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp
include/fennec/renderers/opengl/modern.h
include/fennec/renderers/opengl/fallback.h
)
endif()

View File

@@ -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<value_t>(x));
if (n == npos) {
if (empty()) {
_root = p;
_table[p].data = fennec::forward<value_t>(x);
_table[p].next = npos;
_table[p].prev = npos;
return;
}
_table[p].data = fennec::forward<value_t>(x);
if (i == size()) {
} else {
_table[p].prev = n;
_table[p].next = npos;
_last = n;
}
else {
return;
}
_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<typename...ArgsT>
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<ArgsT>(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<value_t>(x));
}
template<typename...ArgsT>
void emplace_front(ArgsT...args) {
this->emplace(0, fennec::forward<ArgsT>(args)...);
}
void push_back(const value_t& x) {
this->insert(_size, x);
}
@@ -167,6 +249,11 @@ public:
this->insert(_size, fennec::forward<value_t>(x));
}
template<typename...ArgsT>
void emplace_back(ArgsT...args) {
this->emplace(_size, fennec::forward<ArgsT>(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 {

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_CONTAINERS_RDTREE_H
#define FENNEC_CONTAINERS_RDTREE_H
#include <fennec/containers/list.h>
#include <fennec/containers/optional.h>
#include <fennec/memory/allocator.h>
namespace fennec
{
template<typename TypeT, typename AllocT = allocator<TypeT>>
struct rdtree {
private:
struct node;
public:
using value_t = TypeT;
using alloc_t = typename allocator_traits<AllocT>::template rebind<node>;
static constexpr size_t root = 0;
static constexpr size_t npos = -1;
protected:
struct node {
optional<TypeT> value;
size_t parent, child, prev, next;
template<typename...ArgsT>
constexpr node(size_t p, size_t c, size_t v, size_t n, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, parent(p), child(c), prev(v), next(n) {
}
constexpr ~node() {
parent = npos;
child = npos;
prev = npos;
next = npos;
}
};
public:
// Constructors ========================================================================================================
template<typename...ArgsT>
explicit constexpr rdtree(ArgsT&&...args)
: _data(), _freed(), _size(1) {
_data.callocate(10);
fennec::construct(&_data[0], npos, npos, npos, npos, fennec::forward<ArgsT>(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<value_t>& operator[](size_t i) {
return *_data[i].value;
}
constexpr const optional<value_t>& 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<value_t>(val));
_size = 1;
} else {
_data[root].value = fennec::forward<value_t>(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<size_t> 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<node, alloc_t> _data;
list<size_t> _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

View File

@@ -22,6 +22,7 @@
// https://programming.guide/robin-hood-hashing.html
#include <fennec/containers/optional.h>
#include <fennec/containers/set.h>
#include <fennec/lang/compare.h>
#include <fennec/math/ext/primes.h>
#include <fennec/memory/allocator.h>
@@ -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;
}
}
@@ -319,6 +359,7 @@ private:
hash_t _hash;
equal_t _equal;
size_t _size;
size_t _sumpsl;
double _load;
};

View File

@@ -0,0 +1,47 @@
// =====================================================================================================================
// 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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_CORE_SYSTEM_H
#define FENNEC_CORE_SYSTEM_H
#include <fennec/langproc/strings/string.h>
namespace fennec
{
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

View File

@@ -16,9 +16,9 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <stdio.h>
#endif // FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H
#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H

View File

@@ -16,14 +16,14 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/filesystem/path.h>
#include <fennec/langproc/filesystem/path.h>
#include <fennec/fproc/strings/cstring.h>
#include <fennec/fproc/strings/string.h>
#include <fennec/fproc/strings/wstring.h>
#include <fennec/langproc/strings/cstring.h>
#include <fennec/langproc/strings/string.h>
#include <fennec/langproc/strings/wstring.h>
namespace fennec
{
@@ -34,7 +34,7 @@ namespace fennec
/// fmode_binary and fmode_wide are independent of the other modes
///
/// \details Valid Flag Combinations
/// <table width="100%" class="fieldtable" id="table_fennec_fproc_io_fmode">
/// <table width="100%" class="fieldtable" id="table_fennec_LANGPROC_io_fmode">
/// <tr><th style="vertical-align: top">Flags
/// <th style="vertical-align: top">Description
///
@@ -301,4 +301,4 @@ private:
}
#endif // FENNEC_FPROC_IO_FILE_H
#endif // FENNEC_LANGPROC_IO_FILE_H

View File

@@ -16,10 +16,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/strings/string.h>
#include <fennec/langproc/strings/string.h>
namespace fennec
{
@@ -233,4 +233,4 @@ private:
}
#endif // FENNEC_FPROC_IO_PATH_H
#endif // FENNEC_LANGPROC_IO_PATH_H

View File

@@ -16,10 +16,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/strings/detail/_ctype.h>
#include <fennec/langproc/strings/detail/_ctype.h>
#include <fennec/memory/detail/_string.h>
#include <fennec/lang/assert.h>
@@ -337,4 +337,4 @@ struct hash<cstring> : hash<byte_array> {
}
#endif // FENNEC_FPROC_STRINGS_CSTRING_H
#endif // FENNEC_LANGPROC_STRINGS_CSTRING_H

View File

@@ -16,10 +16,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <ctype.h>
#include <wctype.h>
#endif // FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H
#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H

View File

@@ -16,9 +16,9 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <locale.h>
#endif // FENNEC_FPROC_STRINGS_DETAIL_CTYPE_H
#endif // FENNEC_LANGPROC_STRINGS_DETAIL_CTYPE_H

View File

@@ -16,10 +16,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/strings/detail/_locale.h>
#include <fennec/langproc/strings/detail/_locale.h>
namespace fennec
{
@@ -41,4 +41,4 @@ using ::localeconv;
}
#endif // FENNEC_FPROC_STRINGS_LOCALE_H
#endif // FENNEC_LANGPROC_STRINGS_LOCALE_H

View File

@@ -16,11 +16,11 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/strings/detail/_ctype.h>
#include <fennec/fproc/strings/cstring.h>
#include <fennec/langproc/strings/detail/_ctype.h>
#include <fennec/langproc/strings/cstring.h>
#include <fennec/lang/assert.h>
@@ -433,4 +433,4 @@ struct hash<string> : hash<byte_array> {
}
#endif // FENNEC_FPROC_STRINGS_STRING_H
#endif // FENNEC_LANGPROC_STRINGS_STRING_H

View File

@@ -16,10 +16,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/strings/detail/_ctype.h>
#include <fennec/langproc/strings/detail/_ctype.h>
#include <fennec/memory/detail/_string.h>
#include <fennec/lang/assert.h>
@@ -323,4 +323,4 @@ private:
}
#endif // FENNEC_FPROC_STRINGS_wcstring_H
#endif // FENNEC_LANGPROC_STRINGS_wcstring_H

View File

@@ -16,11 +16,11 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/strings/detail/_ctype.h>
#include <fennec/fproc/strings/wcstring.h>
#include <fennec/langproc/strings/detail/_ctype.h>
#include <fennec/langproc/strings/wcstring.h>
#include <fennec/lang/assert.h>
@@ -415,4 +415,4 @@ private:
}
#endif // FENNEC_FPROC_wstringS_wstring_H
#endif // FENNEC_LANGPROC_wstringS_wstring_H

View File

@@ -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<align_t>()) noexcept {
if (_data == nullptr) {
callocate(n, align);
}
// Access ==============================================================================================================
value_t* old = _data;
_data = _alloc.allocate(n);
fennec::memcpy(static_cast<void*>(_data), old, min(_capacity, n) * sizeof(T));
if (n > _capacity) {
fennec::memset(static_cast<void*>(_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<value_t> {
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 ========================================================================================================

View File

@@ -19,7 +19,7 @@
#ifndef FENNEC_PLATFORM_INTERFACE_DISPLAY_H
#define FENNEC_PLATFORM_INTERFACE_DISPLAY_H
#include <fennec/fproc/strings/string.h>
#include <fennec/langproc/strings/string.h>
#include <fennec/lang/types.h>
#include <fennec/lang/typeuuid.h>
#include <fennec/platform/interface/fwd.h>

View File

@@ -19,7 +19,7 @@
#ifndef FENNEC_PLATFORM_INTERFACE_GFXCONTEXT_H
#define FENNEC_PLATFORM_INTERFACE_GFXCONTEXT_H
#include <fennec/fproc/strings/string.h>
#include <fennec/langproc/strings/string.h>
#include <fennec/lang/typeuuid.h>
#include <fennec/platform/interface/fwd.h>
@@ -32,6 +32,12 @@ public:
const uint64_t uuid;
virtual bool connected() = 0;
virtual int32_t get_version_major() = 0;
virtual int32_t get_version_minor() = 0;
virtual int32_t get_context_version() = 0;
virtual const cstring& get_context_name() = 0;
virtual bool check_extension(const cstring& ext) = 0;
virtual void make_current(gfxsurface* surface) = 0;
virtual ~gfxcontext() = default;

View File

@@ -20,8 +20,8 @@
#define FENNEC_PLATFORM_INTERFACE_PLATFORM_H
#include <fennec/containers/list.h>
#include <fennec/fproc/strings/cstring.h>
#include <fennec/fproc/strings/string.h>
#include <fennec/langproc/strings/cstring.h>
#include <fennec/langproc/strings/string.h>
#include <fennec/lang/typeuuid.h>
#include <fennec/platform/interface/fwd.h>

View File

@@ -20,7 +20,7 @@
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
#include <fennec/containers/optional.h>
#include <fennec/fproc/strings/string.h>
#include <fennec/langproc/strings/string.h>
#include <fennec/platform/interface/fwd.h>
namespace fennec

View File

@@ -32,6 +32,11 @@ public:
~eglcontext() override;
bool connected() override;
int32_t get_version_major() override { return _eglvmajor; }
int32_t get_version_minor() override { return _eglvminor; }
int32_t get_context_version() override { return _eglctype; }
const cstring& get_context_name() override;
bool check_extension(const cstring& ext) override;
void make_current(gfxsurface* surface) override;
@@ -39,7 +44,8 @@ private:
EGLDisplay _egldisplay;
EGLContext _eglcontext;
EGLConfig _eglconfig;
EGLint _eglvmajor, _eglvminor;
EGLint _eglvmajor, _eglvminor, _eglctype;
cstring _extensions;
void cleanup();
};

View File

@@ -0,0 +1,188 @@
// =====================================================================================================================
// 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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_RENDERERS_INTERFACE_RENDERER_H
#define FENNEC_RENDERERS_INTERFACE_RENDERER_H
#include <fennec/containers/dynarray.h>
#include <fennec/lang/types.h>
#include <fennec/langproc/strings/cstring.h>
#include <fennec/math/matrix.h>
#include <fennec/math/scalar.h>
#include <fennec/math/ext/quaternion.h>
/*
* 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<typename ValueT>
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<uint32_t>& indices, const dynarray<mesh_vertex>& 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

View File

@@ -0,0 +1,36 @@
// =====================================================================================================================
// 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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_RENDERERS_OPENGL_FALLBACK_H
#define FENNEC_RENDERERS_OPENGL_FALLBACK_H
/*
* This should be implemented using the OpenGL ES 3.2 profile
* https://registry.khronos.org/OpenGL/specs/es/3.2/es_spec_3.2.pdf
*
* Requires the following:
* OpenGL ES 3.2 / OpenGL 4.3 OR
* - EXT_texture_array
* - 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

View File

@@ -0,0 +1,36 @@
// =====================================================================================================================
// 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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_RENDERERS_OPENGL_MODERN_H
#define FENNEC_RENDERERS_OPENGL_MODERN_H
/*
*
* Requires the following:
* OpenGL 4.6 OR
* - ARB_shader_draw_parameters
* - ARB_multi_draw_indirect
* - EXT_texture_array
* - 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

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_SCENE_COMPONENT_H
#define FENNEC_SCENE_COMPONENT_H
#include <fennec/containers/dynarray.h>
#include <fennec/langproc/strings/string.h>
#include <fennec/lang/typeuuid.h>
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>& _type_list() {
static dynarray<type> 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>& type_list = _type_list();
if (id > type_list.size()) {
type_list.resize(id + 1);
}
type_list[id] = { name, create, find, erase };
}
public:
template<typename ComponentT>
static void register_type(const cstring& name, component_create create, component_find find, component_erase erase) {
component::_register_type(typeuuid<ComponentT>(), name, create, find, erase);
}
static const dynarray<type>& type_list() {
return _type_list();
}
};
}
#endif // FENNEC_SCENE_COMPONENT_H

View File

@@ -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 <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_CORE_SCENE_H
#define FENNEC_CORE_SCENE_H
#include <fennec/containers/rdtree.h>
#include <fennec/langproc/strings/string.h>
namespace fennec
{
class scene : public rdtree<string> {
public:
size_t operator[](const cstring& name) const {
list<size_t> 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<size_t> 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

View File

@@ -20,8 +20,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <fennec/fproc/filesystem/file.h>
#include <fennec/fproc/filesystem/path.h>
#include <fennec/langproc/filesystem/file.h>
#include <fennec/langproc/filesystem/path.h>
#ifdef FENNEC_COMPILER_MSVC

View File

@@ -17,7 +17,7 @@
// =====================================================================================================================
#include <fennec/fproc/filesystem/path.h>
#include <fennec/langproc/filesystem/path.h>
namespace fennec
{

View File

@@ -16,7 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#include <fennec/fproc/filesystem/file.h>
#include <fennec/langproc/filesystem/file.h>
#include <fennec/platform/linux/platform.h>
#include <fennec/lang/startup.h>

View File

@@ -16,11 +16,14 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#include <fennec/langproc/filesystem/file.h>
#include <fennec/lang/startup.h>
#include <fennec/platform/interface/display.h>
#include <fennec/platform/interface/platform.h>
#include <fennec/platform/opengl/egl/context.h>
#include <GL/gl.h>
namespace fennec
{
@@ -39,22 +42,15 @@ STATIC_CONSTRUCTOR(_egl_init) {
eglcontext::eglcontext(display* display)
: gfxcontext(display, "EGL", this) {
// Get the display format
const display::pixel_format& fmt = _display->get_color_format();
// Currently empty
EGLint context_attrs[] = {
#if FENNEC_GRAPHICS_OPENGL
EGL_CONTEXT_MAJOR_VERSION, 4,
EGL_CONTEXT_MINOR_VERSION, 3,
#elif FENNEC_GRAPHICS_GLES3
EGL_CONTEXT_MAJOR_VERSION, 3,
EGL_CONTEXT_MINOR_VERSION, 2,
#elif FENNEC_GRAPHICS_GLES2
EGL_CONTEXT_MAJOR_VERSION, 2,
EGL_CONTEXT_MINOR_VERSION, 0,
#endif
EGL_NONE
};
// Configure the depth and rgb bit-depth
EGLint config_attrs[] = {
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
@@ -62,50 +58,59 @@ eglcontext::eglcontext(display* display)
EGL_RED_SIZE, fmt.r,
EGL_RED_SIZE, fmt.g,
EGL_RED_SIZE, fmt.b,
EGL_RENDERABLE_TYPE,
#if FENNEC_GRAPHICS_OPENGL
EGL_OPENGL_BIT,
#elif FENNEC_GRAPHICS_GLES3
EGL_OPENGL_ES3_BIT,
#elif FENNEC_GRAPHICS_GLES2
EGL_OPENGL_ES2_BIT,
#endif
EGL_RENDERABLE_TYPE,
EGL_OPENGL_BIT, // 7
EGL_NONE
};
// Attempt to retrieve an egl display from the native display
_egldisplay = eglGetDisplay(_display->get_native_handle());
if (_egldisplay == nullptr) {
cleanup();
return;
}
if (not eglInitialize(_egldisplay, &_eglvmajor, &_eglvminor)) {
// Attempt to initialize egl
if (not eglInitialize(_egldisplay, nullptr, nullptr)) {
cleanup();
return;
}
#if FENNEC_GRAPHICS_OPENGL
// Attempt to bind to Core OpenGL, otherwise OpenGL ES
if (not eglBindAPI(EGL_OPENGL_API)) {
#elif FENNEC_GRAPHICS_GLES3 or FENNEC_GRAPHICS_GLES2
if (not eglBindAPI(EGL_OPENGL_ES_API)) {
#endif
cleanup();
return;
}
config_attrs[7] = EGL_OPENGL_ES_BIT; // Change the support bit to OpenGL ES
}
// Select a configuration
EGLint n;
if (not eglChooseConfig(_egldisplay, config_attrs, &_eglconfig, 1, &n)) {
cleanup();
return;
}
// Create the context
_eglcontext = eglCreateContext(_egldisplay, _eglconfig, EGL_NO_CONTEXT, context_attrs);
if (_eglcontext == nullptr) {
cleanup();
return;
}
// make this the current context so we can retrieve the information below
eglMakeCurrent(_egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, _eglcontext);
// Query available extensions
const char* ptr = eglQueryString(_egldisplay, EGL_EXTENSIONS);
_extensions = { ptr, strlen(ptr) + 1 };
// Query the context and version
eglQueryContext(_egldisplay, _eglcontext, EGL_CONTEXT_CLIENT_TYPE, &_eglctype);
glGetIntegerv(GL_MAJOR_VERSION, &_eglvmajor);
glGetIntegerv(GL_MINOR_VERSION, &_eglvminor);
}
eglcontext::~eglcontext() {
@@ -116,6 +121,22 @@ bool eglcontext::connected() {
return _eglcontext != nullptr;
}
const cstring& eglcontext::get_context_name() {
static constexpr cstring opengl = "OpenGL";
static constexpr cstring gles = "GLES";
static constexpr cstring openvg = "OpenVG"; // this should never be used
switch (_eglctype) {
default:
case EGL_OPENGL_API: return opengl;
case EGL_OPENGL_ES_API: return gles;
case EGL_OPENVG_API: return openvg;
}
}
bool eglcontext::check_extension(const cstring& ext) {
return _extensions.find(ext) != _extensions.size();
}
void eglcontext::make_current(gfxsurface*) {
}

View File

@@ -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

View File

@@ -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");

View File

@@ -20,8 +20,8 @@
#define FENNEC_TEST_PRINTING_H
#include <iostream>
#include <fennec/fproc/filesystem/path.h>
#include <fennec/fproc/strings/string.h>
#include <fennec/langproc/filesystem/path.h>
#include <fennec/langproc/strings/string.h>
#include <fennec/math/common.h>
#include <fennec/math/matrix.h>

View File

@@ -20,7 +20,7 @@
#define FENNEC_TEST_CONTAINERS_MAP_H
#include <fennec/containers/map.h>
#include <fennec/fproc/strings/string.h>
#include <fennec/langproc/strings/string.h>
namespace fennec::test {

View File

@@ -16,15 +16,15 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/strings/cstring.h>
#include <fennec/langproc/strings/cstring.h>
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

View File

@@ -16,18 +16,18 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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 <fennec/fproc/filesystem/file.h>
#include <fennec/fproc/filesystem/path.h>
#include <fennec/langproc/filesystem/file.h>
#include <fennec/langproc/filesystem/path.h>
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

View File

@@ -16,8 +16,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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

View File

@@ -16,26 +16,26 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#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

View File

@@ -19,7 +19,10 @@
#ifndef FENNEC_TEST_PLATFORM_H
#define FENNEC_TEST_PLATFORM_H
#include "../test.h"
#include <fennec/platform/interface/display.h>
#include <fennec/platform/interface/gfxcontext.h>
#include <fennec/platform/interface/platform.h>
@@ -34,6 +37,10 @@ inline void fennec_test_platform() {
fennec_test_run(instance->get_display() != nullptr, true);
fennec_test_run(instance->get_display()->get_context() != nullptr, true);
std::cout << instance->get_display()->get_context()->get_context_name() << " ";
std::cout << instance->get_display()->get_context()->get_version_major() << ".";
std::cout << instance->get_display()->get_context()->get_version_minor() << std::endl;
instance->shutdown();
}