diff --git a/CMakeLists.txt b/CMakeLists.txt index 849e100..13f3b2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,8 @@ add_library(fennec STATIC include/fennec/lang/detail/__type_traits.h include/fennec/lang/detail/__type_sequences.h + include/fennec/lang/assert.h source/lang/assert.cpp + # MEMORY =============================================================================================================== include/fennec/memory/new.h source/memory/new.cpp @@ -98,8 +100,8 @@ add_library(fennec STATIC include/fennec/math/detail/__fwd.h include/fennec/math/detail/__types.h include/fennec/math/detail/__vector_traits.h - include/fennec/lang/assert.h - source/lang/assert.cpp + + source/debug/assert_impl.cpp ) # add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled diff --git a/PLANNING.md b/PLANNING.md index e786f98..f56764b 100644 --- a/PLANNING.md +++ b/PLANNING.md @@ -9,7 +9,7 @@ 3. [C++ Language](#c-language-library-lang) 4. [Math Library](#math-library-math) 5. [Memory Library](#memory-library-memory) - 6. [Containers Library](#containers-containers) + 6. [Containers Library](#containers-library-containers) 7. [Format Processing](#format-processing-fproc) 8. [Core](#core-core) 1. [Tick](#tick) @@ -33,9 +33,11 @@ This file serves as a general planning document for engine structure, systems, p 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. +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 in debug mode any bugprone or erroneous behaviour should throw +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 @@ -48,7 +50,7 @@ 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 and should be given configurability and programmability within those systems and their stages. -This however can be acheived using events at different stages of those engines that are on-demand. +This however can be achieved using events at different stages of those engines that are on-demand. @@ -81,8 +83,8 @@ Implement math functions according to the [OpenGL 4.6 Shading Language Specifica the Specification. Additional extensions should be implemented to provide standard definitions for functions predominantly related -to Linear Algebra, Mathematical Analysis, and Discrete Analysis. Additional extensions will be implemented on a -as-needed basis. +to Linear Algebra, Mathematical Analysis, and more specifically Discrete Analysis. Additional extensions will be +implemented on an as-needed basis. @@ -219,9 +221,9 @@ in their operation order: ## Application Layer (`app`) -This is the core windowing system of fennec. The implementation will initially be an SDL3 wrapper. -Custom implementation may be further down the roadmap, however this is extremely complicated and there are better -implementations than I could write. +This is the core windowing system of fennec. The implementation will initially be an SDL3 wrapper. +Custom implementation may be further down the roadmap, however this is extremely complicated and there are better +implementations than I could write alone. @@ -249,8 +251,8 @@ Object Structure. The mesh is implicit data. ### 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++ @@ -285,8 +287,8 @@ 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. @@ -304,14 +306,14 @@ Links: - https://pixelandpoly.com/ior.html - https://developer.download.nvidia.com/SDK/10/opengl/screenshots/samples/dual_depth_peeling.html -**DirectX will never have official support.** +**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. diff --git a/README.md b/README.md index 56006bf..28a5b3f 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ 3. [Running the Test Suite](#running-the-test-suite) 4. [Usage](#usage) 5. [Contribution](#contribution) - 6. [Documentation](./fennec_documentation.html) + 6. [Documentation](./documentation.html)

@@ -27,16 +27,16 @@ ## Introduction -fennec is designed to be a general purpose, educational game engine. -fennec may be used through the provided editor application, or as a standalone -library to link against your application. +  fennec is designed to be a general purpose, educational game engine. fennec +may be used through the provided editor application, or as a standalone library to +link against your application.
### Coding Standards -Interfacing with the API in C++ follows the [GNU Coding Standards](https://www.gnu.org/prep/standards/html_node/index.html). +Interfacing with the API in C++ follows the [GNU Coding Standards](https://www.gnu.org/prep/standards/html_node/index.html). Some main areas where the engine strays from the GNU standard includes the following: * [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html). @@ -44,25 +44,44 @@ Some main areas where the engine strays from the GNU standard includes the follo - [Section 6.1, GNU Manuals](https://www.gnu.org/prep/standards/html_node/GNU-Manuals.html) fennec does not use Texinfo and instead uses Doxygen. Otherwise, it follows the other standards of this section. * [Section 7, The Release Process](https://www.gnu.org/prep/standards/html_node/Managing-Releases.html) - fennec follows most of the conventions in this section, however the build system used is CMake and not + fennec follows most of the conventions in this section, however the build system used is CMake and not Makefile. CMake, although overwhelming at first, is much more friendly to those who are learning build systems for the first time.
fennec Standards: - * As per the GNU standard, macros should be `SCREAMING_SNAKE_CASE`. Additionally, Macros should be preceded by `_`. + * As per the GNU standard, macros should be `SCREAMING_SNAKE_CASE`. Additionally, Macros should be preceded by `_`. Macros that wrap C-Style functions may use normal `snake_case`. - - Header Guards should be implemented using `#ifndef`, `#define`, and `#endif` for portability. - The naming convention for Header Guards is as follows: `___H`. - I.E. the engine file `fennec/lang/utility.h` has the Header Guard `FENNEC_LANG_UTILITY_H`. + - Header Guards should be implemented using `#ifndef`, `#define`, and `#endif` for portability. + The naming convention for Header Guards is as follows: `___H`. + I.E. the engine file `fennec/lang/utility.h` has the Header Guard `FENNEC_LANG_UTILITY_H`. - * Helper Functions, in the case of classes, should be private. - In the case of global functions, helpers should be placed in a similarly named file in a subdirectory and namespace called `detail`. - Helper functions should be documented with C-Style comments, however it is not necessary to provide Doxygen documentation. + * Helper Functions, in the case of classes, should be private. + In the case of global functions, helpers should be placed in a similarly named file in a subdirectory and namespace + called `detail`. Helper functions should be documented with C-Style comments, however it is not necessary to provide + Doxygen documentation. - - **DO NOT USE C++ EXCEPTIONS** they will not be supported because they are shit. No, I won't elaborate. + - **DO NOT USE C++ EXCEPTIONS** they will not be supported because they are shit. No, I won't elaborate.[[1]](#f1) + + * Most behaviours should be type independent. Specifically interactions with the core systems of the engine. + +

+ + +[1] Okay, I will elaborate. If we were to use the exception paradigm for all erroneous behaviour, we couldn't + guarantee that the state will not be corrupted when an exception is thrown. The behaviour afterward is + undefined because of this, and we also don't really know when, how, or where that exception will be handled. + The assertion paradigm is better at handling this because you are defining erroneous behaviour in the code and how + it is handled. In a debug build we can immediately halt the program, we don't care about the state afterward, only + beforehand. Now for a release build, this is first and foremost a game engine, so we want to crash as gracefully as + possible, prevent data loss, and get some debug information for it. fennec defines its own `assert` macro to + be used, defining a hook in the private version of the function. This hook is used to clean up any state information + within the engine and may be used to send immediate events to listeners so that outside functionality may decide + how to handle the impending crash. There is nothing that can be done to stop the crash, as soon as the branch + finishes, `abort()` will be called. +
@@ -82,11 +101,11 @@ There are a few reasons for this: ## Building from Source -fennec uses the CMake build manager. The CMake build script provides several +  fennec uses the CMake build manager. The CMake build script provides several targets for building parts of the engine. -Using an IDE will streamline the build process for you and add additional configuration -options. Eclipse, Visual Studio, and CLion provide built-in support for CMake. VSCode +  Using an IDE will streamline the build process for you and add additional configuration +options. Eclipse, Visual Studio, and CLion provide built-in support for CMake. VSCode is also a viable IDE but involves some extra setup. | Target | Description | @@ -116,18 +135,17 @@ is also a viable IDE but involves some extra setup. `build.sh` provides profiles for building the main engine. Run `./build.sh --help` for more info. -By default, the CMake generator -used is Ninja, which requires Ninja to be installed. -You can modify the build scripts to use another build manager, see the [CMake documentation for available generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). +  By default, the CMake generator used is Ninja, which requires Ninja to be installed. You can modify the +build scripts to use another build manager, see the [CMake documentation for available generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
### Building on Windows -The bash script can be run natively on Windows when WSL is enabled. -You do not need to run the script in WSL, simply use the "bash" command in Command Prompt or PowerShell. -The script will require the build [dependencies](#dependencies) installed and configured to be available on the `PATH` environment variable. +  The bash script can be run natively on Windows when WSL is enabled. You do not need to run the +script in WSL, simply use the "bash" command in Command Prompt or PowerShell. The script will require +the build [dependencies](#dependencies) installed and configured to be available on the `PATH` environment variable. Fore more details, [see this blog post](https://blogs.windows.com/windows-insider/2016/04/06/announcing-windows-10-insider-preview-build-14316/) for Windows Build 14316. @@ -152,10 +170,9 @@ The value of `` may be one of the following:
-If you would like to use Visual Studio without CMake, you can use the build -script to generate a Visual Studio project for the source. For a list of available -Visual Studio generators, [see this section](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). -Running the following command will generate the Visual Studio project. +  If you would like to use Visual Studio without CMake, you can use the build script to generate +a Visual Studio project for the source. For a list of available Visual Studio generators, [see this section](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) +of the CMake docs. Running the following command will generate the Visual Studio project. ```commandline cmake -G "Visual Studio 17 2022" -A x64 @@ -169,10 +186,10 @@ cmake -G "Visual Studio 17 2022" -A x64 `test.sh` provides profiles for building the test suite and executes them. -By default, it runs in debug mode and the first failed test will throw an assertion. -Any tests that involve running as an application will spawn a subprocess with a window, -and give a short description of the behaviour in the terminal. It will then have you confirm -whether the information displayed is correct. +  By default, the program runs in debug mode and the first failed test will throw an assertion. +Any tests that involve running as an application will spawn a subprocess with a window, and give +a short description of the behaviour in the terminal. It will then have you confirm whether the +information displayed is correct.

diff --git a/include/fennec/lang/assert.h b/include/fennec/lang/assert.h index d38c5fc..f74300a 100644 --- a/include/fennec/lang/assert.h +++ b/include/fennec/lang/assert.h @@ -21,8 +21,6 @@ using assert_handler = void (*)(const char *, const char *, int , const char *); -extern void set_assert_handler(assert_handler handler); - extern void __assert_impl(const char* expression, const char* file, int line, const char* function); #define assert(expression) if(not(expression)) { __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__); } diff --git a/include/fennec/lang/type_transforms.h b/include/fennec/lang/type_transforms.h index b9af62e..a140ddb 100644 --- a/include/fennec/lang/type_transforms.h +++ b/include/fennec/lang/type_transforms.h @@ -131,7 +131,6 @@ namespace fennec // fennec::type_transform ============================================================================================== /// -/// \struct fennec::type_transform /// \brief Base Class for Type Transformations /// /// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type @@ -139,7 +138,6 @@ namespace fennec template struct type_transform { /// - /// \typedef type_transform::type /// \brief the type to transform into using type = T; }; diff --git a/include/fennec/math/exponential.h b/include/fennec/math/exponential.h index 1e2d882..43f31f8 100644 --- a/include/fennec/math/exponential.h +++ b/include/fennec/math/exponential.h @@ -32,7 +32,10 @@ #ifndef FENNEC_MATH_EXPONENTIAL_H #define FENNEC_MATH_EXPONENTIAL_H -#include +#pragma push_macro("__cplusplus") +#undef __cplusplus +#include +#pragma pop_macro("__cplusplus") /// /// @@ -106,7 +109,7 @@ namespace fennec /// \param y the exponent template constexpr genType pow(genType x, genType y) - { return std::pow(x, y); } + { return ::pow(x, y); } template constexpr vector pow(const vector & x, const vector & y) @@ -123,7 +126,7 @@ constexpr vector pow(const vector & x, const vecto /// \param x the exponent template constexpr genType exp(genType x) - { return std::exp(x); } + { return ::exp(x); } template constexpr vector exp(const vector& x) { return vector(fennec::exp(x[i]) ...); } @@ -138,7 +141,7 @@ template constexpr vector exp(const /// /// \param x the exponent template constexpr genType exp2(genType x) - { return std::exp2(x); } + { return ::exp2(x); } template constexpr vector exp2(const vector& x) { return vector(fennec::exp2(x[i]) ...); } @@ -154,7 +157,7 @@ template constexpr vector exp2(cons /// /// \param x the input value template constexpr genType log(genType x) - { return std::log(x); } + { return ::log(x); } template constexpr genType log(const vector& x) { return vector(log(x[i]) ...); } @@ -171,7 +174,7 @@ template constexpr genType log(const vector constexpr genType log2(genType x) - { return std::log2(x); } + { return ::log2(x); } template constexpr genType log2(const vector& x) { return vector(log2(x[i]) ...); } @@ -187,7 +190,7 @@ template constexpr genType log2(const vector constexpr genType sqrt(genType x) - { return std::sqrt(x); } + { return ::sqrt(x); } template constexpr genType sqrt(const vector& x) { return vector(fennec::sqrt(x[i]) ...); } diff --git a/include/fennec/math/matrix.h b/include/fennec/math/matrix.h index 40173cd..f2c9db1 100644 --- a/include/fennec/math/matrix.h +++ b/include/fennec/math/matrix.h @@ -46,8 +46,8 @@ #include #include + #include -#include #include namespace fennec @@ -80,38 +80,43 @@ constexpr vec row(const matrix& { return vec(m[cols][i]...); } +template using tmat2x2 = mat; ///< helper for creating 2x2 matrices of the specified type. +template using tmat2x3 = mat; ///< helper for creating 2x3 matrices of the specified type. +template using tmat2x4 = mat; ///< helper for creating 2x4 matrices of the specified type. +template using tmat3x2 = mat; ///< helper for creating 3x2 matrices of the specified type. +template using tmat3x3 = mat; ///< helper for creating 3x3 matrices of the specified type. +template using tmat3x4 = mat; ///< helper for creating 3x4 matrices of the specified type. +template using tmat4x2 = mat; ///< helper for creating 4x2 matrices of the specified type. +template using tmat4x3 = mat; ///< helper for creating 4x3 matrices of the specified type. +template using tmat4x4 = mat; ///< helper for creating 4x4 matrices of the specified type. -template using tmat = mat; +using mat2 = tmat2x2; ///< Specification for glsl float matrices +using mat3 = tmat3x3; ///< Specification for glsl float matrices +using mat4 = tmat3x3; ///< Specification for glsl float matrices -using mat2 = tmat<2, 2>; -using mat3 = tmat<3, 3>; -using mat4 = tmat<4, 4>; +using mat2x2 = tmat2x2; ///< Specification for sized glsl float matrices +using mat2x3 = tmat2x3; ///< Specification for sized glsl float matrices +using mat2x4 = tmat2x4; ///< Specification for sized glsl float matrices +using mat3x2 = tmat3x2; ///< Specification for sized glsl float matrices +using mat3x3 = tmat3x3; ///< Specification for sized glsl float matrices +using mat3x4 = tmat3x4; ///< Specification for sized glsl float matrices +using mat4x2 = tmat4x2; ///< Specification for sized glsl float matrices +using mat4x3 = tmat4x3; ///< Specification for sized glsl float matrices +using mat4x4 = tmat4x4; ///< Specification for sized glsl float matrices -using mat2x2 = tmat<2, 2>; -using mat2x3 = tmat<2, 3>; -using mat2x4 = tmat<2, 4>; -using mat3x2 = tmat<3, 2>; -using mat3x3 = tmat<3, 3>; -using mat3x4 = tmat<3, 4>; -using mat4x2 = tmat<4, 2>; -using mat4x3 = tmat<4, 3>; -using mat4x4 = tmat<4, 4>; +using dmat2 = tmat2x2; ///< Specification for glsl double matrices +using dmat3 = tmat3x3; ///< Specification for glsl double matrices +using dmat4 = tmat3x3; ///< Specification for glsl double matrices -template using tdmat = mat; - -using dmat2 = tdmat<2, 2>; -using dmat3 = tdmat<3, 3>; -using dmat4 = tdmat<4, 4>; - -using dmat2x2 = tdmat<2, 2>; -using dmat2x3 = tdmat<2, 3>; -using dmat2x4 = tdmat<2, 4>; -using dmat3x2 = tdmat<3, 2>; -using dmat3x3 = tdmat<3, 3>; -using dmat3x4 = tdmat<3, 4>; -using dmat4x2 = tdmat<4, 2>; -using dmat4x3 = tdmat<4, 3>; -using dmat4x4 = tdmat<4, 4>; +using dmat2x2 = tmat2x2; ///< Specification for size glsl double matrices +using dmat2x3 = tmat2x3; ///< Specification for size glsl double matrices +using dmat2x4 = tmat2x4; ///< Specification for size glsl double matrices +using dmat3x2 = tmat3x2; ///< Specification for size glsl double matrices +using dmat3x3 = tmat3x3; ///< Specification for size glsl double matrices +using dmat3x4 = tmat3x4; ///< Specification for size glsl double matrices +using dmat4x2 = tmat4x2; ///< Specification for size glsl double matrices +using dmat4x3 = tmat4x3; ///< Specification for size glsl double matrices +using dmat4x4 = tmat4x4; ///< Specification for size glsl double matrices /// @@ -197,7 +202,7 @@ struct matrix /// /// \details /// \param mat matrix to move - constexpr matrix(matrix_t&& mat) + constexpr matrix(matrix_t&& mat) noexcept : data{ mat.data } {} @@ -215,7 +220,6 @@ struct matrix ///

/// /// \param s scalar value - /// constexpr matrix(scalar_t s) { (((ColIndicesV < rows) ? data[ColIndicesV][ColIndicesV] = s : 0), ...); } @@ -278,7 +282,6 @@ struct matrix { assert(i < rows); return data[i]; } /// - /// \fn matrix::operator()(size_t, size_t) /// \copydetails matrix::operator()(size_t, size_t) const constexpr scalar_t& operator()(size_t i, size_t j) { assert(i < rows && j < columns); return data[i][j]; } @@ -298,13 +301,245 @@ struct matrix /// \name Scalar Operators /// @{ + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar addition operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns a copy of the matrix with each component having been added by the scalar + constexpr friend matrix_t operator+(const matrix_t& lhs, scalar_t rhs) + { + matrix_t retval = lhs; + ((retval[ColIndicesV] += rhs), ...); + return retval; + } + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" addition operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns a copy of the matrix with each component having been added by the scalar + constexpr friend matrix_t operator+(scalar_t lhs, const matrix_t& rhs) + { + matrix_t retval = rhs; + ((retval[ColIndicesV] += lhs), ...); + return retval; + } + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar subtraction operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns a copy of the matrix with each component having been subtracted by the scalar + constexpr friend matrix_t operator-(const matrix_t& lhs, scalar_t rhs) + { + matrix_t retval = lhs; + ((retval[ColIndicesV] -= rhs), ...); + return retval; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" subtraction operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns a copy of the matrix with each component having been subtracted by the scalar + constexpr friend matrix_t operator-(scalar_t lhs, const matrix_t& rhs) + { + matrix_t retval = rhs; + ((retval[ColIndicesV] -= lhs), ...); + return retval; + } + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar multiplication operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns a copy of the matrix with each component having been multiplied by the scalar + constexpr friend matrix_t operator*(const matrix_t& lhs, scalar_t rhs) + { + matrix_t retval = lhs; + ((retval[ColIndicesV] *= rhs), ...); + return retval; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" multiplication operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns a copy of the matrix with each component having been multiplied by the scalar + constexpr friend matrix_t operator*(scalar_t lhs, const matrix_t& rhs) + { + matrix_t retval = rhs; + ((retval[ColIndicesV] *= lhs), ...); + return retval; + } + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar division operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns a copy of the matrix with each component having been divided by the scalar + constexpr friend matrix_t operator/(const matrix_t& lhs, scalar_t rhs) + { + matrix_t retval = lhs; + ((retval[ColIndicesV] /= rhs), ...); + return retval; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" division operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns a copy of the matrix with each component having been divided by the scalar + constexpr friend matrix_t operator/(scalar_t lhs, const matrix_t& rhs) + { + matrix_t retval = rhs; + ((retval[ColIndicesV] /= lhs), ...); + return retval; + } + + + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar addition assignment operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns the matrix after having each component added by the scalar + constexpr friend matrix_t& operator+=(matrix_t& lhs, scalar_t rhs) + { + ((lhs[ColIndicesV] += rhs), ...); + return lhs; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" addition assignment operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns the matrix after having each component added by the scalar + constexpr friend matrix_t& operator+=(scalar_t lhs, matrix_t& rhs) + { + ((rhs[ColIndicesV] += lhs), ...); + return rhs; + } + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar subtraction assignment operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns the matrix after having each component subtracted by the scalar + constexpr friend matrix_t& operator-=(matrix_t& lhs, scalar_t rhs) + { + ((lhs[ColIndicesV] -= rhs), ...); + return lhs; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" addition assignment operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns the matrix after having each component added by the scalar + constexpr friend matrix_t& operator-=(scalar_t lhs, matrix_t& rhs) + { + ((rhs[ColIndicesV] -= lhs), ...); + return rhs; + } + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar multiplication assignment operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns the matrix after having each component multiplied by the scalar + constexpr friend matrix_t& operator*=(matrix_t& lhs, scalar_t rhs) + { + ((lhs[ColIndicesV] *= rhs), ...); + return lhs; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" multiplication assignment operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns the matrix after having each component multiplied by the scalar + constexpr friend matrix_t& operator*=(scalar_t lhs, matrix_t& rhs) + { + ((rhs[ColIndicesV] *= lhs), ...); + return rhs; + } + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar division assignment operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns the matrix after having each component divided by the scalar + constexpr friend matrix_t& operator/=(matrix_t& lhs, scalar_t rhs) + { + ((lhs[ColIndicesV] /= rhs), ...); + return lhs; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" division assignment operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns the matrix after having each component divided by the scalar + constexpr friend matrix_t& operator/=(scalar_t lhs, matrix_t& rhs) + { + ((rhs[ColIndicesV] /= lhs), ...); + return rhs; + } + + + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar modulo operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns a copy of the matrix with each component having been reduced modulo by the scalar + constexpr friend matrix_t operator%(const matrix_t& lhs, scalar_t rhs) requires is_integral_v + { + matrix_t retval = lhs; + ((retval[ColIndicesV] %= rhs), ...); + return retval; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" modulo operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns a copy of the matrix with each component having been reduced modulo by the scalar + constexpr friend matrix_t operator%(scalar_t lhs, const matrix_t& rhs) requires is_integral_v + { + matrix_t retval = rhs; + ((retval[ColIndicesV] %= lhs), ...); + return retval; + } + + /// + /// \brief \ref fennec::matrix "matrix" - \ref scalar modulo assignment operator. + /// \param lhs the matrix + /// \param rhs the scalar + /// \returns the matrix after having each component reduced modulo by the scalar + constexpr friend matrix_t& operator%=(matrix_t& lhs, scalar_t rhs) requires is_integral_v + { + ((lhs[ColIndicesV] %= rhs), ...); + return lhs; + } + + /// + /// \brief \ref scalar - \ref fennec::matrix "matrix" modulo assignment operator. + /// \param lhs the scalar + /// \param rhs the matrix + /// \returns the matrix after having each component reduced modulo by the scalar + constexpr friend matrix_t& operator%=(scalar_t lhs, matrix_t& rhs) requires is_integral_v + { + ((rhs[ColIndicesV] %= lhs), ...); + return rhs; + } /// @} // Vector Operators ==================================================================================================== - /// \name \ref matrix_t "matrix" \ref fennec::vector "vector" Operators + /// \name \ref fennec::matrix "matrix" - \ref fennec::vector "vector" Operators /// @{ /// @@ -330,9 +565,25 @@ struct matrix // Matrix Operators ==================================================================================================== - /// \name \ref matrix_t "matrix" \ref matrix_t "matrix" Operators + /// \name \ref fennec::matrix "matrix" - \ref fennec::matrix "matrix" Operators /// @{ + /// + /// \brief matrix comparison operator + /// \param lhs the first matrix + /// \param rhs the second matrix + /// \returns a boolean value that contains \f$true\f$ when all components of `lhs` and `rhs` are equal and \f$false\f$ otherwise + constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs) + { return lhs.data == rhs.data; } + + /// + /// \brief matrix comparison operator + /// \param lhs the first matrix + /// \param rhs the second matrix + /// \returns a boolean value that contains \f$true\f$ when all components of `lhs` and `rhs` are not equal and \f$false\f$ otherwise + constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs) + { return lhs.data != rhs.data; } + /// /// \brief performs a linear algebraic matrix multiplication /// \param lhs the rows to multiply with @@ -341,12 +592,6 @@ struct matrix { return [lhs, rhs](index_sequence) -> matrix_t { return matrix_t(rhs * fennec::row(lhs, i)...); }(make_index_sequence{}); } - constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs) - { return lhs.data == rhs.data; } - - constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs) - { return lhs.data != rhs.data; } - /// @} diff --git a/include/fennec/math/vector.h b/include/fennec/math/vector.h index 04f1fd5..e1d8c95 100644 --- a/include/fennec/math/vector.h +++ b/include/fennec/math/vector.h @@ -163,8 +163,7 @@ using ivec2 = tvec2; /// \brief A three-component signed integer \ref fennec_math_vector "vector" using ivec3 = tvec3; -/// \typedef ivec4 -/// \anchor ivec4 +/// /// \brief A four-component signed integer \ref fennec_math_vector "vector" using ivec4 = tvec4; @@ -214,7 +213,6 @@ using dvec4 = tvec4; /// -/// \struct fennec::vector /// \brief Math Vector Type /// \tparam ScalarT base \ref scalar type of each Component /// \tparam IndicesV index of each Component @@ -233,7 +231,6 @@ struct vector : detail::vector_base_type /// @{ /// - /// \typedef vector::base_type /// \brief vector base type using base_type = detail::vector_base_type; @@ -242,12 +239,10 @@ struct vector : detail::vector_base_type using base_type::data; /// - /// \typedef scalar_t /// \brief alias for ScalarT using scalar_t = ScalarT; /// - /// \typedef vector::vector_t /// \brief alias for this type using vector_t = vector; @@ -667,7 +662,6 @@ struct vector : detail::vector_base_type { return vector((lhs[IndicesV] * rhs[IndicesV]) ...); } /// - /// \fn vector::operator/(const vector_t&, const vector_t&) /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression @@ -899,7 +893,7 @@ struct vector : detail::vector_base_type /// - /// \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise or operator + /// \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise xor operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ @@ -907,8 +901,7 @@ struct vector : detail::vector_base_type { return vector_t((lhs ^ rhs[IndicesV]) ...); } /// - /// \fn vector::operator^=(vector_t&, scalar_t) - /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or assignment operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ @@ -916,8 +909,7 @@ struct vector : detail::vector_base_type { return ((lhs[IndicesV] ^= rhs), ..., lhs); } /// - /// \fn vector::operator^(const vector_t&, scalar_t) - /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ @@ -925,8 +917,7 @@ struct vector : detail::vector_base_type { return vector_t((lhs[IndicesV] ^ rhs) ...); } /// - /// \fn vector::operator^=(vector_t&, const vector_t&) - /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ @@ -934,8 +925,7 @@ struct vector : detail::vector_base_type { return ((lhs[IndicesV] ^= rhs), ..., lhs); } /// - /// \fn vector::operator^(const vector_t&, const vector_t&) - /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator + /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ @@ -945,7 +935,6 @@ struct vector : detail::vector_base_type /// - /// \fn vector::operator<<=(vector_t&, scalar_t) /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression @@ -954,7 +943,6 @@ struct vector : detail::vector_base_type { return ((lhs[IndicesV] <<= rhs), ..., lhs); } /// - /// \fn vector::operator<<(const vector_t&, scalar_t) /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression @@ -963,7 +951,6 @@ struct vector : detail::vector_base_type { return vector_t((lhs[IndicesV] << rhs) ...); } /// - /// \fn vector::operator<<=(vector_t&, const vector_t&) /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression @@ -972,7 +959,6 @@ struct vector : detail::vector_base_type { return ((lhs[IndicesV] <<= rhs), ..., lhs); } /// - /// \fn vector::operator<<(const vector_t&, const vector_t&) /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression @@ -983,7 +969,6 @@ struct vector : detail::vector_base_type /// - /// \fn vector::operator>>=(vector_t&, scalar_t) /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression @@ -992,7 +977,6 @@ struct vector : detail::vector_base_type { return ((lhs[IndicesV] >>= rhs), ..., lhs); } /// - /// \fn vector::operator>>(const vector_t&, scalar_t) /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression @@ -1001,7 +985,6 @@ struct vector : detail::vector_base_type { return vector_t((lhs[IndicesV] >> rhs) ...); } /// - /// \fn vector::operator>>=(vector_t&, const vector_t&) /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression @@ -1010,7 +993,6 @@ struct vector : detail::vector_base_type { return ((lhs[IndicesV] >>= rhs), ..., lhs); } /// - /// \fn vector::operator>>(const vector_t&, const vector_t&) /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator /// \param lhs Left Hand Side of the Expression /// \param rhs Right Hand Side of the Expression diff --git a/include/fennec/math/vector_base.h b/include/fennec/math/vector_base.h index 3e51877..6286009 100644 --- a/include/fennec/math/vector_base.h +++ b/include/fennec/math/vector_base.h @@ -34,7 +34,6 @@ namespace detail { /// -/// \struct vector_base_type_helper /// \brief helper class for generating vectors /// \tparam scalar base scalar type /// \tparam size size of the vector type @@ -48,22 +47,18 @@ struct vector_base_type_helper /// - /// \typedef ScalarT /// \brief Base scalar type using ScalarT = scalar; /// - /// \typedef VectorT /// \brief Base vector type using VectorT = vec; /// - /// \typedef DataT /// \brief Backing array holding the elements using DataT = array; /// - /// \struct SwizzleGen /// \brief Helper for generating a swizzle from a set of indices /// \tparam IndicesV Indices of the vector to pull from template struct SwizzleGen @@ -72,10 +67,7 @@ struct vector_base_type_helper using type = swizzle; }; - /// - /// \struct SwizzleGen - /// \brief Partial Specialization for single component swizzles to decay into a scalar - /// \tparam IndexV + // Specialization for single component swizzles to decay into a scalar template struct SwizzleGen { /// \brief decayed scalar type @@ -83,11 +75,12 @@ struct vector_base_type_helper }; /// - /// \typedef StorageT /// \brief backing storage type using StorageT = vector_storage; }; +/// +/// \brief helper for getting the storage type of the vector constructed with the provided size and scalar type template using vector_base_type = typename vector_base_type_helper::StorageT; diff --git a/include/fennec/math/vector_storage.h b/include/fennec/math/vector_storage.h index fd97034..ab1c8b4 100644 --- a/include/fennec/math/vector_storage.h +++ b/include/fennec/math/vector_storage.h @@ -30,7 +30,6 @@ namespace detail { /// -/// \struct vector_storage /// \brief backing storage type for vectors /// \tparam SizeV size of the vector /// \tparam SwizzleGenT generator for swizzles @@ -38,17 +37,10 @@ namespace detail template class SwizzleGenT, typename DataT> struct vector_storage; -/// -/// \struct vector_storage<1, SwizzleGenT, DataT> -/// \brief specialization for single component vectors -/// \tparam SwizzleGenT generator for swizzles -/// \tparam DataT backing data type +// specialization for single component vectors template