diff --git a/.gitmodules b/.gitmodules index 0a15db9..0350e7a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "external/cpptrace"] path = external/cpptrace url = https://github.com/jeremy-rifkin/cpptrace.git +[submodule "external/boost-atomic"] + path = external/boost-atomic + url = https://github.com/boostorg/atomic +[submodule "external/boost-thread"] + path = external/boost-thread + url = https://github.com/boostorg/thread diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a95b34..3b1836c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,9 +20,9 @@ cmake_minimum_required(VERSION 3.30) project(fennec) # External dependencies should be loaded here - -# CppTrace is a dependency of the project, added as a git submodule add_subdirectory(external/cpptrace) +add_subdirectory(external/boost-atomic) +add_subdirectory(external/boost-thread) set(CMAKE_CXX_STANDARD 23) set(CMAKE_C_STANDARD 23) @@ -138,11 +138,6 @@ add_library(fennec STATIC include/fennec/memory/detail/_ptr_traits.h -# CONCURRENCY ========================================================================================================== - include/fennec/concurrency/thread.h - include/fennec/concurrency/mutex.h - include/fennec/concurrency/atomic.h - # DEBUG ================================================================================================================ source/debug/assert_impl.cpp @@ -223,8 +218,11 @@ target_link_options(fennec PRIVATE ${FENNEC_PRIVATE_LINK_OPTIONS}) # Do not comp # This implementation is designed to be as readable as possible, and expose information that would otherwise be obfuscated target_link_libraries(fennec PRIVATE - cpptrace::cpptrace ${FENNEC_LINK_LIBRARIES} + + cpptrace::cpptrace + Boost::atomic + Boost::thread ) diff --git a/READINGS.md b/READINGS.md index 6d6696f..6a8f60f 100644 --- a/READINGS.md +++ b/READINGS.md @@ -3,7 +3,7 @@ # Readings -Here is a list of relevant books and articles on various concepts related to +Here is a list of relevant books and articles on various concepts related to developing a game engine and its subsystems. - Game Engine Architecture, Ed. 3 – Jason Gregory diff --git a/README.md b/README.md index ed9ee38..22cffb3 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ fennec Standards: immediate events to listeners so that outside functionality may decide how to handle the impending crash. In Debug Mode there is nothing that can be done to stop the crash, as soon as the branch finishes, `abort()` will be called. - +
diff --git a/external/boost-atomic b/external/boost-atomic new file mode 160000 index 0000000..8a6de6d --- /dev/null +++ b/external/boost-atomic @@ -0,0 +1 @@ +Subproject commit 8a6de6d93dbe123134deff264851a18d96063764 diff --git a/external/boost-thread b/external/boost-thread new file mode 160000 index 0000000..a1f89c9 --- /dev/null +++ b/external/boost-thread @@ -0,0 +1 @@ +Subproject commit a1f89c951879b6677772606d0549e7368c9c99bc diff --git a/gdb/fennec/containers.py b/gdb/fennec/containers.py index cd1fcfa..d716940 100644 --- a/gdb/fennec/containers.py +++ b/gdb/fennec/containers.py @@ -396,10 +396,10 @@ class GraphPrinter: class Iterator: def __init__(self, val): - self.node_pool = val['_node_pool']['_table']['_alloc']['_data'] - self.max_nodes = val['_node_pool']['_table']['_alloc']['_capacity'] - self.conn_map = val['_conn_map']['_alloc']['_data'] - self.max_conn = val['_conn_map']['_size'] + self.node_pool = val['_vertex_pool']['_table']['_alloc']['_data'] + self.max_nodes = val['_vertex_pool']['_table']['_alloc']['_capacity'] + self.conn_map = val['_edge_map']['_alloc']['_data'] + self.max_conn = val['_edge_map']['_size'] self.index = 0 def __iter__(self): @@ -447,7 +447,7 @@ class GraphPrinter: def __init__(self, val): self.val = val - self.size = val['_node_pool']['_size'] + self.size = val['_vertex_pool']['_size'] def to_string(self): if self.size == 0: diff --git a/include/fennec/concurrency/atomic.h b/include/fennec/concurrency/atomic.h deleted file mode 100644 index 33b528b..0000000 --- a/include/fennec/concurrency/atomic.h +++ /dev/null @@ -1,22 +0,0 @@ -// ===================================================================================================================== -// 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_CONCURRENCY_ATOMIC_H -#define FENNEC_CONCURRENCY_ATOMIC_H - -#endif // FENNEC_CONCURRENCY_ATOMIC_H diff --git a/include/fennec/concurrency/mutex.h b/include/fennec/concurrency/mutex.h deleted file mode 100644 index 94682da..0000000 --- a/include/fennec/concurrency/mutex.h +++ /dev/null @@ -1,22 +0,0 @@ -// ===================================================================================================================== -// 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_CONCURRENCY_MUTEX_H -#define FENNEC_CONCURRENCY_MUTEX_H - -#endif // FENNEC_CONCURRENCY_MUTEX_H diff --git a/include/fennec/concurrency/thread.h b/include/fennec/concurrency/thread.h deleted file mode 100644 index 26814d2..0000000 --- a/include/fennec/concurrency/thread.h +++ /dev/null @@ -1,22 +0,0 @@ -// ===================================================================================================================== -// 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_CONCURRENCY_THREAD_H -#define FENNEC_CONCURRENCY_THREAD_H - -#endif // FENNEC_CONCURRENCY_THREAD_H diff --git a/include/fennec/containers/graph.h b/include/fennec/containers/graph.h index 8b111a0..744ec65 100644 --- a/include/fennec/containers/graph.h +++ b/include/fennec/containers/graph.h @@ -149,7 +149,7 @@ public: /// /// \returns The number of edges in the graph constexpr size_t num_edges() const { - return _conn_pool.size(); + return _edge_pool.size(); } /// @@ -170,7 +170,7 @@ public: /// \param b The second vertex /// \returns `true` if the edge exists, `false` otherwise constexpr bool exists(size_t a, size_t b) const { - return _conn_map[a][b] != nullptr; + return _edge_map[a][b] != nullptr; } /// @@ -189,8 +189,8 @@ public: /// \param b The second vertex /// \returns `true` if both edges exist, `false` otherwise constexpr bool is_undirected(size_t a, size_t b) const { - const auto* e0 = _conn_map[a][b]; - const auto* e1 = _conn_map[b][a]; + const auto* e0 = _edge_map[a][b]; + const auto* e1 = _edge_map[b][a]; if (not (e0 != nullptr && e1 != nullptr)) { return false; } @@ -232,9 +232,9 @@ public: if (empty()) { return nullptr; } - edge_t* it = _conn_map[a][b]; + edge_t* it = _edge_map[a][b]; if (it) { - return _conn_pool[*it]; + return _edge_pool[*it]; } return nullptr; } @@ -248,9 +248,9 @@ public: if (empty()) { return nullptr; } - const edge_t* it = _conn_map[a][b]; + const edge_t* it = _edge_map[a][b]; if (it) { - return _conn_pool[*it]; + return _edge_pool[*it]; } return nullptr; } @@ -261,10 +261,10 @@ public: /// \returns A list containing all vertices `x` with edges from `vertex` to `x...` list outgoing(size_t vertex) { list res; - if (empty() || vertex >= _conn_map.size()) { + if (empty() || vertex >= _edge_map.size()) { return res; } - for (const auto& it : _conn_map[vertex]) { + for (const auto& it : _edge_map[vertex]) { res.push_back(it.first); } return res; @@ -276,11 +276,11 @@ public: /// \returns A list containing all vertices `x` with edges from `x...` to `vertex` list incoming(size_t vertex) { list res; - if (empty() || vertex >= _conn_map.size()) { + if (empty() || vertex >= _edge_map.size()) { return res; } - for (size_t n = 0; n < _conn_map.size(); ++n) { - if (_conn_map[n][vertex]) { + for (size_t n = 0; n < _edge_map.size(); ++n) { + if (_edge_map[n][vertex]) { res.push_back(n); } } @@ -293,11 +293,11 @@ public: /// \returns A list containing all vertices `x` that have symmetric edges with `vertex` list symmetric(size_t vertex) { list res; - if (empty() || vertex >= _conn_map.size()) { + if (empty() || vertex >= _edge_map.size()) { return res; } - for (const auto& it : _conn_map[vertex]) { - if (_conn_map[it.first][vertex]) { + for (const auto& it : _edge_map[vertex]) { + if (_edge_map[it.first][vertex]) { res.push_back(it.first); } } @@ -314,11 +314,11 @@ public: /// \returns A list containing all vertices `x` that have symmetric edges with `vertex` list undirected(size_t vertex) { list res; - if (empty() || vertex >= _conn_map.size()) { + if (empty() || vertex >= _edge_map.size()) { return res; } - for (const auto& it : _conn_map[vertex]) { - const auto* at = _conn_map[it.first][vertex]; + for (const auto& it : _edge_map[vertex]) { + const auto* at = _edge_map[it.first][vertex]; if (at != nullptr && *at == it.second) { res.push_back(it.first); } @@ -332,10 +332,10 @@ public: /// \param vertex The id of the vertex /// \returns A pointer to a map containing edges mapped from this vertex const auto* edges(size_t vertex) { - if (empty() || vertex >= _conn_map.size()) { + if (empty() || vertex >= _edge_map.size()) { return nullptr; } - return &_conn_map[vertex]; + return &_edge_map[vertex]; } /// @} @@ -392,19 +392,19 @@ public: return; } - if (_conn_map.size() < _vertex_pool.capacity()) { - _conn_map.resize(_vertex_pool.capacity()); + if (_edge_map.size() < _vertex_pool.capacity()) { + _edge_map.resize(_vertex_pool.capacity()); } - auto it = _conn_map[a][b]; + auto it = _edge_map[a][b]; size_t conn; if (it != nullptr) { conn = *it; - _conn_pool[conn] = vertex_t(fennec::forward(args)...); + _edge_pool[conn] = vertex_t(fennec::forward(args)...); } else { - conn = _conn_pool.emplace(fennec::forward(args)...); + conn = _edge_pool.emplace(fennec::forward(args)...); } - _conn_map[a].emplace(b, conn); + _edge_map[a].emplace(b, conn); } /// @@ -419,21 +419,21 @@ public: return; } - if (_conn_map.size() < _vertex_pool.capacity()) { - _conn_map.resize(_vertex_pool.capacity()); + if (_edge_map.size() < _vertex_pool.capacity()) { + _edge_map.resize(_vertex_pool.capacity()); } - auto it = _conn_map[a][b]; + auto it = _edge_map[a][b]; size_t conn; if (it != nullptr) { conn = *it; - _conn_pool[conn] = vertex_t(fennec::forward(args)...); + _edge_pool[conn] = vertex_t(fennec::forward(args)...); } else { - conn = _conn_pool.emplace(fennec::forward(args)...); + conn = _edge_pool.emplace(fennec::forward(args)...); } - _conn_map[a].emplace(b, conn); - _conn_map[b].emplace(a, conn); + _edge_map[a].emplace(b, conn); + _edge_map[b].emplace(a, conn); } /// @@ -443,20 +443,20 @@ public: constexpr void cut_edge(size_t a, size_t b) { // Find the edge object - const auto* it = _conn_map[a][b]; + const auto* it = _edge_map[a][b]; if (not it) { return; } size_t c = *it; // Check if undirected - const auto* at = _conn_map[b][a]; + const auto* at = _edge_map[b][a]; if (not at || *at != c) { - _conn_pool.erase(c); + _edge_pool.erase(c); } // Erase the edge mapping - _conn_map[a].erase(b); + _edge_map[a].erase(b); } /// @@ -464,15 +464,15 @@ public: /// \param a The first vertex id /// \param b The second vertex id constexpr void cut_edge2(size_t a, size_t b) { - const auto* ita = _conn_map[a][b]; - const auto* itb = _conn_map[a][b]; + const auto* ita = _edge_map[a][b]; + const auto* itb = _edge_map[a][b]; if (not (ita || itb)) { return; } - if (ita) _conn_pool.erase(*ita); - if (itb) _conn_pool.erase(*itb); - _conn_map[a].erase(b); - _conn_map[b].erase(a); + if (ita) _edge_pool.erase(*ita); + if (itb) _edge_pool.erase(*itb); + _edge_map[a].erase(b); + _edge_map[b].erase(a); } /// @@ -491,8 +491,8 @@ public: /// \brief Clear the graph, destructing all vertices and edges. void clear() { _vertex_pool.clear(); - _conn_pool.clear(); - _conn_map.clear(); + _edge_pool.clear(); + _edge_map.clear(); } /// @} @@ -503,8 +503,8 @@ public: private: vertex_pool_t _vertex_pool; - edge_pool_t _conn_pool; - edge_map_t _conn_map; + edge_pool_t _edge_pool; + edge_map_t _edge_map; template size_t _insert(ArgsT&&...args) { diff --git a/planning/2D_GRAPHICS.md b/planning/2D_GRAPHICS.md index f8aee36..4886923 100644 --- a/planning/2D_GRAPHICS.md +++ b/planning/2D_GRAPHICS.md @@ -23,8 +23,8 @@ Links: ### Structures (`gfx2d`) -For the 2d rendering framework, Materials need to be rendered independently because we have -no size constraints for images. This disallows us from using a meta-shader like in +For the 2d rendering framework, Materials need to be rendered independently because we have +no size constraints for images. This disallows us from using a meta-shader like in the 3d rendering framework. ```c++ @@ -59,6 +59,6 @@ struct Object - Adjust Buffer Size using the counts - Insert using another atomic buffer -- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate. - This will allow us to sort objects as they are created. We can still bulk render each z-index, +- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate. + This will allow us to sort objects as they are created. We can still bulk render each z-index, with meshes and objects being grouped by material. \ No newline at end of file diff --git a/planning/3D_GRAPHICS.md b/planning/3D_GRAPHICS.md index ebc3181..1fdafb5 100644 --- a/planning/3D_GRAPHICS.md +++ b/planning/3D_GRAPHICS.md @@ -15,16 +15,16 @@ ## Introduction -  This system handles the rendering of 3D meshes, materials, lights, and post-processing +  This system handles the rendering of 3D meshes, materials, lights, and post-processing effects. **DirectX will never have official support.** If you would like to make a fork, have at it, but know that I will hold a deep disdain for you. -The graphics pipeline will have a buffer with a list of objects and their rendering data. +The graphics pipeline will have a buffer with a list of objects and their rendering data. This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes. -The buffers will be optimized by scene prediction. -This involves tracking the meshes and textures directly and indirectly used by a scene. +The buffers will be optimized by scene prediction. +This involves tracking the meshes and textures directly and indirectly used by a scene. A callback function in the graphics system for scene loading can do this. @@ -66,8 +66,8 @@ Objects are identified with a manually provided type and ID. Object types includ A user should never have to specify these and should be automatically generated by the respective components. -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 +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 and 3D textures may only be `1:1`. diff --git a/planning/3D_PHYSICS.md b/planning/3D_PHYSICS.md index 79e28f1..1661d36 100644 --- a/planning/3D_PHYSICS.md +++ b/planning/3D_PHYSICS.md @@ -14,10 +14,10 @@ ## Introduction -  This system will handle newtonian physics for 3D rigid and soft-bodies. This should include -articulated skeletal systems, particle physics, and soft-body physics. The following soft-body systems -will be supported with the associated implementation; elastics with finite element simulation, cloth -physics with position-based dynamics, oceans with iWave, 3D fluid dynamics with smoothed-particle +  This system will handle newtonian physics for 3D rigid and soft-bodies. This should include +articulated skeletal systems, particle physics, and soft-body physics. The following soft-body systems +will be supported with the associated implementation; elastics with finite element simulation, cloth +physics with position-based dynamics, oceans with iWave, 3D fluid dynamics with smoothed-particle hydrodynamics, 2D surface fluid dynamics with force-based dynamics. diff --git a/planning/ARTIFICIAL_INTELLIGENCE.md b/planning/ARTIFICIAL_INTELLIGENCE.md index da90348..5e2181e 100644 --- a/planning/ARTIFICIAL_INTELLIGENCE.md +++ b/planning/ARTIFICIAL_INTELLIGENCE.md @@ -8,10 +8,10 @@ ## Introduction -  This system implements pathing and decision systems for general-purpose traditional -artifical intelligence algorithms. This library will not support Machine-Learning Artificial -Intelligence (ML/AI). This artificial intelligence method only differs in static generation -between 2D and 3D. The solvers are dimension independent since they work on a graph. +  This system implements pathing and decision systems for general-purpose traditional +artifical intelligence algorithms. This library will not support Machine-Learning Artificial +Intelligence (ML/AI). This artificial intelligence method only differs in static generation +between 2D and 3D. The solvers are dimension independent since they work on a graph. ## General Process @@ -25,5 +25,5 @@ between 2D and 3D. The solvers are dimension independent since they work on a gr * update paths using dijkstra's algorithm * apply rigid-body forces with constraints -The update loop for artificial intelligence should only update every `n` ticks. Where +The update loop for artificial intelligence should only update every `n` ticks. Where `n <= k`, with `k` being the tick rate of the physics engine. diff --git a/planning/CONTAINERS.md b/planning/CONTAINERS.md index 42bd7a6..91d1ed4 100644 --- a/planning/CONTAINERS.md +++ b/planning/CONTAINERS.md @@ -16,8 +16,8 @@ ## Introduction -  This library contains headers and classes that implement common data -structures. The contents include the Containers Library of the C++ Standard +  This library contains headers and classes that implement common data +structures. The contents include the Containers Library of the C++ Standard Library and Template Library. @@ -29,29 +29,29 @@ Library and Template Library. | Symbol | Implemented | Passed | |:-------------------------------------|:-----------:|:------:| | map (`std::unordered_map`) | ✅ | ✅ | -| map_sequence (`std::map`) | ⛔ | ⛔ | -| multiset (`std::unordered_multiset`) | ⛔ | ⛔ | -| multisequence (`std::multiset`) | ⛔ | ⛔ | -| multimap (`std::unordered_multimap`) | ⛔ | ⛔ | -| multimap_sequence (`std::multimap`) | ⛔ | ⛔ | +| map_sequence (`std::map`) | ⛔ | ⛔ | +| multiset (`std::unordered_multiset`) | ⛔ | ⛔ | +| multisequence (`std::multiset`) | ⛔ | ⛔ | +| multimap (`std::unordered_multimap`) | ⛔ | ⛔ | +| multimap_sequence (`std::multimap`) | ⛔ | ⛔ | | pair | ✅ | ✅ | | tuple | 🚧 | 🚧 | | optional | ✅ | ✅ | -| variant | ⛔ | ⛔ | -| any | ⛔ | ⛔ | -| bitset | ⛔ | ⛔ | +| variant | ⛔ | ⛔ | +| any | ⛔ | ⛔ | +| bitset | ⛔ | ⛔ | | array | ✅ | ✅ | | dynarray (`std::vector`) | 🚧 | 🚧 | -| deque | ⛔ | ⛔ | +| deque | ⛔ | ⛔ | | list | ✅ | ✅ | | set (`std::unordered_set`) | ✅ | ✅ | -| sequence (`std::set`) | ⛔ | ⛔ | +| sequence (`std::set`) | ⛔ | ⛔ | ### fennec | Symbol | Implemented | Passed | |:------------|:-----------:|:------:| -| graph | 🚧 | 🚧 | -| object_pool | 🚧 | 🚧 | +| graph | 🚧 | 🚧 | +| object_pool | 🚧 | 🚧 | | rd_tree | ✅ | ✅ | diff --git a/planning/CONTENTS.md b/planning/CONTENTS.md index 6695cf1..cf50208 100644 --- a/planning/CONTENTS.md +++ b/planning/CONTENTS.md @@ -15,41 +15,58 @@ ## Introduction -  These files serve as general planning documentation for engine structure, systems, +  These files serve as general planning documentation for engine structure, systems, pipelines, and implementation. -  Implementations of core engine systems should strive to be `O(1)` in -implementations, both in terms of runtime and memory performance. This is obviously -not a realistic goal, so rather than the goal requiring the entire engine to be `O(1)`, -we should more specifically look at achieving `O(1)` performance on hot paths. -I distinctly use 'strive' and 'goal' as different concepts, where designs should -*strive* to accommodate function implementations for `O(1)`, however the specifics -of the implementation might not always be able to achieve that, so the end *goal* is +  Implementations of core engine systems should strive to be `O(1)` in +implementations, both in terms of runtime and memory performance. This is obviously +not a realistic goal, so rather than the goal requiring the entire engine to be `O(1)`, +we should more specifically look at achieving `O(1)` performance on hot paths. +I distinctly use 'strive' and 'goal' as different concepts, where designs should +*strive* to accommodate function implementations for `O(1)`, however the specifics +of the implementation might not always be able to achieve that, so the end *goal* is that hot paths should be `O(1)`. -  Functions should be highly verbose and any bugprone or erroneous behaviour should +  Functions should be highly verbose and any bugprone or erroneous behaviour should throw assertions. **DO NOT USE EXCEPTIONS**. -  System implementations should be independent of architecture or platforms. i.e. -the code of the graphics system should not care if OpenGL or Vulkan is used and should +  System implementations should be independent of architecture or platforms. i.e. +the code of the graphics system should not care if OpenGL or Vulkan is used and should not use any direct calls to OpenGL or Vulkan. -  The engine should not care about the types of objects loaded from a so/dll. In -fact, most of the code should be type independent. Any shared information among a -collection of objects should be held either implicitly or explicitly in the super-class. -It will be the responsibility of the linked code to initialize and cleanup the objects +  The engine should not care about the types of objects loaded from a so/dll. In +fact, most of the code should be type independent. Any shared information among a +collection of objects should be held either implicitly or explicitly in the super-class. +It will be the responsibility of the linked code to initialize and cleanup the objects related to it. This principle should extend to the submodules of the engine. -  It is also best to avoid objects having behaviour that is not defined by the system -they are in. There are some exceptions in extensions or mods, which should be given -configurability and programmability within those systems and their stages. This can +  It is also best to avoid objects having behaviour that is not defined by the system +they are in. There are some exceptions in extensions or mods, which should be given +configurability and programmability within those systems and their stages. This can be achieved using events at different stages of those engines that are on-demand. +## External Libraries + + * `cpptrace` + * Walking the stack and retrieving information about the code is *very* platform + dependent, and it makes little sense spending days writing a library that will + be less effective. + * `boost-atomic` `boost-thread` + * Concurrency support is *extremely* platform dependent. Each OS has its own + implementations with its own idiosyncrasies. We are not writing an operating system, + we do not want to spend days writing a library that will be less performant and + much more bugprone. Comparing this with the containers library, the containers + library is worth reimplementing since it is not platform dependent and we can + make an implementation with consistent behavior. Boost is slightly better for our + purposes since its implementation is more consistent across implementations than + the C++ stdlib. + + ## Definitions -  Many subpages of these documents will contain tables that use symbols to +  Many subpages of these documents will contain tables that use symbols to denote implementation and testing progress. The symbols are defined below. | Symbol | Meaning | Notes | @@ -62,4 +79,7 @@ denote implementation and testing progress. The symbols are defined below. ## Libraries - [C++ Language Library](./CPP_LANGUAGE.md#c-language-library-lang) - - [Platform Support Library](./PLATFORM_SUPPORT.md#platform--api-support) \ No newline at end of file + - [Platform Support Library](./PLATFORM_SUPPORT.md#platform-support-library-platform) + - [Memory Library](./MEMORY.md#memory-library-memory) + - [Containers Library](./CONTAINERS.md#containers-library-containers) + - [Language Processing Library](./LANGUAGE_PROCESSING.md#language-processing-library-langproc) \ No newline at end of file diff --git a/planning/CPP_LANGUAGE.md b/planning/CPP_LANGUAGE.md index 159aa07..eee50a9 100644 --- a/planning/CPP_LANGUAGE.md +++ b/planning/CPP_LANGUAGE.md @@ -26,8 +26,8 @@ ## Introduction -  This library contains headers and classes related to the C++ language. The -contents of this library include the Language Support, Diagnostics, and +  This library contains headers and classes related to the C++ language. The +contents of this library include the Language Support, Diagnostics, and Metaprogramming libraries of the C++ Standard Library and Template Library. See: @@ -59,22 +59,22 @@ See: | is_null_pointer | ✅ | ✅ | | is_integral | ✅ | ✅ | | is_floating_point | ✅ | ✅ | -| is_array | ✅ | ❓ | +| is_array | ✅ | 🚧 | | is_enum | ⛔ | ⛔ | | is_union | ⛔ | ⛔ | | is_class | ✅ | ✅ | | is_function | ⛔ | ⛔ | | is_pointer | ✅ | ✅ | | is_lvalue_reference | ✅ | ✅ | -| is_rvalue_reference | ✔ | ✔ | +| is_rvalue_reference | ✅ | ✅ | | is_member_object_pointer | ⛔ | ⛔ | | is_member_function_pointer | ⛔ | ⛔ | ### Composite Types | Symbol | Implemented | Passed | |:------------------|:-----------:|:------:| -| is_fundamental | ✔ | ✔ | -| is_arithmetic | ✔ | ✔ | +| is_fundamental | ✅ | ✅ | +| is_arithmetic | ✅ | ✅ | | is_scalar | ⛔ | ⛔ | | is_object | ⛔ | ⛔ | | is_compound | ⛔ | ⛔ | @@ -84,9 +84,9 @@ See: ### Type Properties | Symbol | Implemented | Passed | |:----------------------------------|:-----------:|:------:| -| is_const | ✔ | ✔ | -| is_volatile | ✔ | ✔ | -| is_trivially_copyable | ✔ | ✔ | +| is_const | ✅ | ✅ | +| is_volatile | ✅ | ✅ | +| is_trivially_copyable | ✅ | ✅ | | is_standard_layout | ⛔ | ⛔ | | has_unique_object_representations | ⛔ | ⛔ | | is_empty | ⛔ | ⛔ | @@ -95,8 +95,8 @@ See: | is_final | ⛔ | ⛔ | | is_aggregate | ⛔ | ⛔ | | is_implicit_lifetime | ⛔ | ⛔ | -| is_signed | ✔ | ✔ | -| is_unsigned | ✔ | ✔ | +| is_signed | ✅ | ✅ | +| is_unsigned | ✅ | ✅ | | is_bounded_array | ⛔ | ⛔ | | is_unbounded_array | ⛔ | ⛔ | | is_scoped_enum | ⛔ | ⛔ | @@ -104,16 +104,16 @@ See: ### Supported Operations | Symbol | Implemented | Passed | |:------------------------------------|:-----------:|:------:| -| is_constructible | ✔ | ✔ | -| is_trivially_constructible | ✔ | ✔ | +| is_constructible | ✅ | ✅ | +| is_trivially_constructible | ✅ | ✅ | | is_nothrow_constructible | ⛔ | ⛔ | -| is_default_constructible | ✔ | ✔ | +| is_default_constructible | ✅ | ✅ | | is_trivially_default_constructible | ⛔ | ⛔ | | is_nothrow_default_constructible | ⛔ | ⛔ | -| is_copy_constructible | ✔ | ✔ | +| is_copy_constructible | ✅ | ✅ | | is_trivially_copy_constructible | ⛔ | ⛔ | | is_nothrow_copy_constructible | ⛔ | ⛔ | -| is_move_constructible | ✔ | ✔ | +| is_move_constructible | ✅ | ✅ | | is_trivially_move_constructible | ⛔ | ⛔ | | is_nothrow_move_constructible | ⛔ | ⛔ | | is_destructible | ⛔ | ⛔ | @@ -137,10 +137,10 @@ See: ### Type Relationships | Symbol | Implemented | Passed | |:------------------------------------|:-----------:|:------:| -| is_same | ✔ | ✔ | +| is_same | ✅ | ✅ | | is_base_of | ❌ | ❌ | | is_virtual_base_of | ❌ | ❌ | -| is_convertible | ✔ | ✔ | +| is_convertible | ✅ | ✅ | | is_nothrow_convertible | ❌ | ❌ | | is_layout_compatible | ❌ | ❌ | | is_pointer_interconvertible_base_of | ❌ | ❌ | @@ -152,19 +152,19 @@ See: ### Type Transformations | Symbol | Implemented | Passed | |:---------------------|:-----------:|:------:| -| add_const | ✔ | ✔ | -| add_volatile | ✔ | ✔ | -| add_cv | ✔ | ✔ | -| remove_const | ✔ | ✔ | -| remove_volatile | ✔ | ✔ | -| remove_cv | ✔ | ✔ | -| add_lvalue_reference | ✔ | ✔ | -| add_rvalue_reference | ✔ | ✔ | -| remove_reference | ✔ | ✔ | -| add_pointer | ✔ | ✔ | -| remove_pointer | ✔ | ✔ | -| make_signed | ✔ | ✔ | -| make_unsigned | ✔ | ✔ | +| add_const | ✅ | ✅ | +| add_volatile | ✅ | ✅ | +| add_cv | ✅ | ✅ | +| remove_const | ✅ | ✅ | +| remove_volatile | ✅ | ✅ | +| remove_cv | ✅ | ✅ | +| add_lvalue_reference | ✅ | ✅ | +| add_rvalue_reference | ✅ | ✅ | +| remove_reference | ✅ | ✅ | +| add_pointer | ✅ | ✅ | +| remove_pointer | ✅ | ✅ | +| make_signed | ✅ | ✅ | +| make_unsigned | ✅ | ✅ | | remove_extent | ❌ | ❌ | | remove_all_extents | ❌ | ❌ | @@ -174,17 +174,17 @@ See: | aligned_storage | ❌ | ❌ | | aligned_union | ❌ | ❌ | | aligned_union | ❌ | ❌ | -| decay | 🚧 | 🚧 | -| remove_cvref | ✔ | ✔ | -| enable_if | ✔ | ✔ | -| conditional | ✔ | ✔ | +| decay | 🚧 | 🚧 | +| remove_cvref | ✅ | ✅ | +| enable_if | ✅ | ✅ | +| conditional | ✅ | ✅ | | common_type | ❌ | ❌ | | common_reference | ❌ | ❌ | | basic_common_reference | ❌ | ❌ | | underlying_type | ❌ | ❌ | | result_of | ❌ | ❌ | | invoke_result | ❌ | ❌ | -| void_t | ✔ | ✔ | +| void_t | ✅ | ✅ | ### Logical Operations | Symbol | Implemented | Passed | @@ -196,9 +196,9 @@ See: ### Sequences | Symbol | Implemented | Passed | |:-------------------------------------------------|:-----------:|:------:| -| const_sequence | ✔ | ✔ | -| const_integer_sequence (`std::integer_sequence`) | ✔ | ✔ | -| make_integer_sequence | ✔ | ✔ | -| const_index_sequence (`std::index_sequence`) | ✔ | ✔ | -| make_index_sequence | ✔ | ✔ | -| concat_sequence | ✔ | ✔ | +| const_sequence | ✅ | ✅ | +| const_integer_sequence (`std::integer_sequence`) | ✅ | ✅ | +| make_integer_sequence | ✅ | ✅ | +| const_index_sequence (`std::index_sequence`) | ✅ | ✅ | +| make_index_sequence | ✅ | ✅ | +| concat_sequence | ✅ | ✅ | diff --git a/planning/ENGINE.md b/planning/ENGINE.md index 0eb808c..28ec621 100644 --- a/planning/ENGINE.md +++ b/planning/ENGINE.md @@ -24,7 +24,7 @@ ## Introduction -  This file outlines the core engine structure and all necessary systems for +  This file outlines the core engine structure and all necessary systems for the engine to run. @@ -35,70 +35,70 @@ This section outlines core systems to the engine and brief overviews. ### Events -  fennec will be largely event based, the system should be able to handle multiple -event types without having any type-specific code. There will be a few categories of events, -predominantly on-demand and delayed events. On-demand events are fired immediately, which is -useful for events related to graphics and audio. Delayed events are fired at the next tick or -after a certain period of time, this is useful for physics events which can't be handled -immediately without potentially harming the state of the physics engine. Events should be +  fennec will be largely event based, the system should be able to handle multiple +event types without having any type-specific code. There will be a few categories of events, +predominantly on-demand and delayed events. On-demand events are fired immediately, which is +useful for events related to graphics and audio. Delayed events are fired at the next tick or +after a certain period of time, this is useful for physics events which can't be handled +immediately without potentially harming the state of the physics engine. Events should be optionally able to be handled with multithreading. ### Scene -  The core structure of the engine and its levels will be a scene hierarchy. The hierarchy -will be implemented using a rooted-directed tree (rdtree, not to be confused with rbtree). -Each element in the tree will be a node with a name and some very basic flags. Component -dependent behaviour *must* be handled in systems to avoid the overhead of an object-oriented -scene hierarchy. This is predominantly caused by the recursive nature of parsing an object- +  The core structure of the engine and its levels will be a scene hierarchy. The hierarchy +will be implemented using a rooted-directed tree (rdtree, not to be confused with rbtree). +Each element in the tree will be a node with a name and some very basic flags. Component +dependent behaviour *must* be handled in systems to avoid the overhead of an object-oriented +scene hierarchy. This is predominantly caused by the recursive nature of parsing an object- oriented scene hierarchy where each node records its children and updates them accordingly. ### Scripts -  Scripts won't be handled the same way scripts are in other engines, they will be translated -as a system which will be data-oriented. This is to reduce the overhead of the object-oriented +  Scripts won't be handled the same way scripts are in other engines, they will be translated +as a system which will be data-oriented. This is to reduce the overhead of the object-oriented approach in C++ while maintaining the appearance of being object-oriented. ### AI -  AI will be a fairly multi-parted system as we need to handle different use-cases. -The first use case is characters that can "walk" and "jump" on surfaces. The second use-case -is characters that "fly" in some manner. The static path generation will be the only difference +  AI will be a fairly multi-parted system as we need to handle different use-cases. +The first use case is characters that can "walk" and "jump" on surfaces. The second use-case +is characters that "fly" in some manner. The static path generation will be the only difference between 2D and 3D. ### Physics -  Physics, like other systems, will be separated into 2D and 3D specific implementations. -This system should be able to handle both Newtonian Rigid-Bodies and Soft-Bodies. The 2D -and 3D systems should be able to co-exist but not interact. This is for such cases where one +  Physics, like other systems, will be separated into 2D and 3D specific implementations. +This system should be able to handle both Newtonian Rigid-Bodies and Soft-Bodies. The 2D +and 3D systems should be able to co-exist but not interact. This is for such cases where one might decide to have a minigame with physics enabled in a 2D environment. ### Graphics -  Graphics, like other systems, will be separated into 2D and 3D specific implementations. -Graphics will exist on a separate thread that handles "frames" vs "ticks," see definitions below -for more information. From an abstract, the graphics system should be able to handle static models, +  Graphics, like other systems, will be separated into 2D and 3D specific implementations. +Graphics will exist on a separate thread that handles "frames" vs "ticks," see definitions below +for more information. From an abstract, the graphics system should be able to handle static models, dynamic models, skeletons, materials, lights, lighting models, and post-processing effects. ### Audio -  Audio may actually be implemented generically since the principles of spatial audio apply -identically in both 2D and 3D. The only thing that may change for 2D is which axis is "up" and which -axis is "forwards," for example side-scrollers vs top-down. However, this does not mandate specific -implementations and rather just aliases which axis is "up." The X-axis can always be "left" and "right" -while the Y axis may be interpreted as "up" or "forwards." Audio also won't be handled in the same +  Audio may actually be implemented generically since the principles of spatial audio apply +identically in both 2D and 3D. The only thing that may change for 2D is which axis is "up" and which +axis is "forwards," for example side-scrollers vs top-down. However, this does not mandate specific +implementations and rather just aliases which axis is "up." The X-axis can always be "left" and "right" +while the Y axis may be interpreted as "up" or "forwards." Audio also won't be handled in the same manner as other systems which have explicit ticks and frames. ## Core Game Loop -  The core game loop is divided into Ticks and Frames. Ticks represent updates in the engine +  The core game loop is divided into Ticks and Frames. Ticks represent updates in the engine state while Frames represent the generation of the visual output of the engine. ### Tick diff --git a/planning/LANGUAGE_PROCESSING.md b/planning/LANGUAGE_PROCESSING.md index c0287d9..8ba8bc4 100644 --- a/planning/LANGUAGE_PROCESSING.md +++ b/planning/LANGUAGE_PROCESSING.md @@ -17,20 +17,20 @@ ## Introduction -  This library contains implementations of headers and classes related to processing -languages. This includes; ascii/utf8/utf16 string processing, file formats, machine language, +  This library contains implementations of headers and classes related to processing +languages. This includes; ascii/utf8/utf16 string processing, file formats, machine language, and programming languages. -  fennec should be able to process documentation in files, the main ways it will support +  fennec should be able to process documentation in files, the main ways it will support this is through Doxygen and LaTeX. Consider including binaries with releases. ## String Analysis (`langproc/strings`) -  fennec reimplements the C++ Strings Library as a submodule of this library. This -is because C++ `std::string` has a lot of overhead. I would say that `std::string` -is a Jeep, while `fennec::string` is an F2 Car, if that analogy makes any sense. i.e. -`std::string` offers a lot of use cases, but is slower, while an F2 Car is barebones and +  fennec reimplements the C++ Strings Library as a submodule of this library. This +is because C++ `std::string` has a lot of overhead. I would say that `std::string` +is a Jeep, while `fennec::string` is an F2 Car, if that analogy makes any sense. i.e. +`std::string` offers a lot of use cases, but is slower, while an F2 Car is barebones and highly performant on the right surface. ### Implementation @@ -46,7 +46,7 @@ highly performant on the right surface. ## File System (`filesystem`) -  fennec *does not* reimplement the C++ I/O Library. What it does do +  fennec *does not* reimplement the C++ I/O Library. What it does do is create C++ classes that handle file streams, directory streams, and file paths. ### Implementation @@ -86,7 +86,7 @@ certain specification. Here are some concepts that will need to be implemented a ### Writing -  The writers will be responsible for writing data as a specific format. I.E. converting +  The writers will be responsible for writing data as a specific format. I.E. converting data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/utf16). - Writer @@ -96,7 +96,7 @@ data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/ut ## Formats (`langproc/formats`) -  This submodule will contain classes for processing a variety of file formats. +  This submodule will contain classes for processing a variety of file formats. ### Serialization @@ -166,8 +166,8 @@ data values (e.g. floats, ints, etc.) to a readable language (e.g. ascii/utf8/ut #### 3D Model Formats -  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 +  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. | Symbol | Implemented | Passed | diff --git a/planning/MEMORY.md b/planning/MEMORY.md index 237ba99..729cdfe 100644 --- a/planning/MEMORY.md +++ b/planning/MEMORY.md @@ -14,9 +14,9 @@ ## Introduction -  This library contains headers and classes related to memory allocation and -management in C++. The contents include the Memory Management Library of -the C++ Standard Library and Template Library. This pulls some functions from the +  This library contains headers and classes related to memory allocation and +management in C++. The contents include the Memory Management Library of +the C++ Standard Library and Template Library. This pulls some functions from the C stdlib and either wraps them or aliases them. diff --git a/planning/PLATFORM_SUPPORT.md b/planning/PLATFORM_SUPPORT.md index 3795e67..c870632 100644 --- a/planning/PLATFORM_SUPPORT.md +++ b/planning/PLATFORM_SUPPORT.md @@ -15,8 +15,8 @@ ## Introduction -  The platform support library will include headers, functions, and classes related -to supporting various platforms. Platforms may be defined as any Hardware, OS, or +  The platform support library will include headers, functions, and classes related +to supporting various platforms. Platforms may be defined as any Hardware, OS, or Drivers that must be initialized for the engine context. @@ -48,14 +48,14 @@ Platform Support will be implemented in the following order: - 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, +  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. ## Consoles -  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. fennec will interact +  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. fennec will interact with any drivers required for the listed operating systems above, even if proprietary.