start to refactor for C++23

This commit is contained in:
Hartmut Seichter 2024-06-06 23:45:53 +02:00
parent 42c7221318
commit cd19543627
19 changed files with 489 additions and 434 deletions

12
.clang-format Normal file
View file

@ -0,0 +1,12 @@
# We'll use defaults from the LLVM style, but with 4 columns indentation.
BasedOnStyle: LLVM
IndentWidth: 4
Language: Cpp
# Force pointers to the type for C++.
DerivePointerAlignment: false
PointerAlignment: Left
AlignConsecutiveAssignments: true
LambdaBodyIndentation: OuterScope

36
.vscode/settings.json vendored
View file

@ -16,7 +16,41 @@
"stdexcept": "cpp",
"streambuf": "cpp",
"type_traits": "cpp",
"tuple": "cpp"
"tuple": "cpp",
"cmath": "cpp",
"span": "cpp",
"*.tcc": "cpp",
"*.inc": "cpp",
"*.ipp": "cpp",
"bit": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"format": "cpp",
"future": "cpp",
"optional": "cpp",
"ranges": "cpp",
"shared_mutex": "cpp",
"stop_token": "cpp",
"regex": "cpp",
"valarray": "cpp",
"*.def": "cpp",
"boundingsphere": "cpp",
"callback": "cpp",
"geometry": "cpp",
"node": "cpp",
"nodevisitor": "cpp",
"object": "cpp",
"plane": "cpp",
"program": "cpp",
"shape": "cpp",
"stateattribute": "cpp",
"observer_ptr": "cpp",
"thread": "cpp",
"concepts": "cpp",
"typeinfo": "cpp",
"drawable": "cpp",
"userdatacontainer": "cpp",
"*.txx": "cpp"
},
"mesonbuild.configureOnOpen": false
}

View file

@ -1,15 +1,15 @@
#
# CMake build system for pixwerx
#
cmake_minimum_required(VERSION 3.8)
cmake_minimum_required(VERSION 3.28)
project(pixwerx)
#
# pixwerx ist C++20
# pixwerx ist C++23
#
set (CMAKE_CXX_STANDARD 20)
set (CMAKE_CXX_STANDARD 23)
# internal cmake modules
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/etc/cmake ${CMAKE_MODULE_PATH})
@ -28,3 +28,4 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
#
add_subdirectory(src)
add_subdirectory(share)
add_subdirectory(tests)

View file

@ -1,22 +1,19 @@
# pixwerx
pixwerx is an opinionated, academic approach to a 3D engine. It tries to mix
modern andproven methods to build a fast and portable engine beyond pure 3D.
pixwerx is an opinionated, academic approach to a 3D graphics engine. It mixes
modern and proven methods to build a fast and portable graphics system.
## Design Principles
Dogdooding: pixwerx is built on the principle of dogfooding. The engine is a
Dogfooding: pixwerx is built on the principle of dogfooding. The engine is a
full-stack system that tries to implement all necessary functions. The engine
editor is just a UI build with the engine.
Reasonable dependencies: like many engines pixwerx tries to include as much 3rd-
party code as possible and implements some of the core systems itself.
Reasonable dependencies: like many engines pixwerx tries to include as much 3rd-party code as possible and implements some of the core systems itself.
No premature optimization: pixwerx implements only very few systems with machine
code. It tries to utilize the power of the compiler as much as possible.
No premature optimization: pixwerx implements only very few systems with machine code. It tries to utilize the power of the compiler as much as possible.
Computer graphics 101: pixwerx does implement graphics components and systems in
a way that makes code portable and not over-parameterized. Usability is
Computer graphics 101: pixwerx does implement graphics components and systems in a way that makes code portable and not over-parameterized. Usability is
achieved through layers on top of the core components.
@ -28,7 +25,3 @@ LICENSE file.
## Authors
© 1999-2020 Hartmut Seichter

View file

@ -1,4 +1,4 @@
find_package(mkdocs 1.0)
# find_package(mkdocs 1.0)
# if(MKDOCS_FOUND)
# configure_file(mkdocs.yml "${CMAKE_CURRENT_BINARY_DIR}/mkdocs.yml" COPYONLY)

View file

@ -1,15 +1,15 @@
# first build dependencies
add_subdirectory(deps)
# add_subdirectory(deps)
# build internal core
add_subdirectory(core)
add_subdirectory(scene)
add_subdirectory(system)
add_subdirectory(io)
# add_subdirectory(scene)
# add_subdirectory(system)
# add_subdirectory(io)
#add_subdirectory(ui)
add_subdirectory(binding)
add_subdirectory(visual)
add_subdirectory(geometry)
# add_subdirectory(binding)
# add_subdirectory(visual)
# add_subdirectory(geometry)
add_subdirectory(runtime)
# add_subdirectory(runtime)

View file

@ -33,14 +33,14 @@ set(misc
set(srcs
# src/buffer.cpp
src/core.cpp
src/image.cpp
src/debug.cpp
src/geometry.cpp
src/material.cpp
src/resource.cpp
src/serialize.cpp
src/time.cpp
src/image.cpp
# src/image.cpp
# src/debug.cpp
# src/geometry.cpp
# src/material.cpp
# src/resource.cpp
# src/serialize.cpp
# src/time.cpp
# src/image.cpp
)
add_library(pwcore
@ -58,5 +58,5 @@ target_include_directories(
target_link_libraries(pwcore)
add_subdirectory(tests)
# add_subdirectory(tests)

View file

@ -8,8 +8,8 @@
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -29,24 +29,12 @@ namespace pw {
struct aabb {
vector3 min;
vector3 max;
aabb(const vector3 min_vec,const vector3 max_vec)
: min(min_vec)
, max(max_vec)
{}
aabb() {
min.zero(); max.zero();
}
vector3 dimension() const {
return max - min;
}
vector3 min{};
vector3 max{};
constexpr vector3 dimension() const noexcept { return max - min; }
};
}
} // namespace pw
#endif

View file

@ -31,23 +31,12 @@ template <typename T>
struct axisangle_ {
using value_type = T;
using axis_type = vector3_<T>;
using axis_type = vector3_<T>; // todo - should default to UP
axis_type axis;
T angle;
axis_type axis{};
T angle{};
axisangle_()
: axis(vector3_<T>::up()),
angle(0)
{}
axisangle_(vector3_<T> axis,T angle)
: axis(std::move(axis))
, angle(std::move(angle))
{
}
static const axisangle_ from_matrix(const matrix_<4,4,T>& m)
static axisangle_ from_matrix(const matrix_<4,4,T>& m)
{
using std::acos;
using std::sqrt;

View file

@ -58,13 +58,10 @@ public:
using texture_t = std::tuple<texture_type,std::string,uint32_t>;
protected:
vector4 _color = {{}, {1.0, 0.0, 1.0, 1.0}};
vector4 _color = vector4 { 1.0, 0.0, 1.0, 1.0 };
std::vector<texture_t> _textures;
std::vector<texture_t> _textures;
};

View file

@ -8,8 +8,8 @@
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -27,253 +27,213 @@
#include <pw/core/math.hpp>
#include <pw/core/matrixbase.hpp>
// #include <array>
#include <numeric>
#include <array>
namespace pw
{
namespace pw {
template <std::size_t R, std::size_t C, typename T, bool RowMajor = false>
struct matrix_ : matrixbase_<T, matrix_<R, C, T>>
{
T data[R * C];
template <std::size_t R, std::size_t C, typename T, bool RowMajor = false>
struct matrix_ : matrixbase_<T, matrix_<R, C, T>> {
using matrixbase_<T, matrix_<R, C, T>>::matrixbase_;
using base_type = matrixbase_<T, matrix_<R, C, T>>;
using typename base_type::value_type;
using typename base_type::derived_type;
static constexpr std::size_t rows{R};
static constexpr std::size_t cols{C};
static constexpr std::size_t rows{R};
static constexpr std::size_t cols{C};
static constexpr std::size_t coefficients{R * C};
static constexpr std::size_t diagonal_size{std::min(R,C)};
static constexpr std::size_t coefficients{R * C};
using col_type = matrix_<R, 1, T>;
using row_type = matrix_<1, C, T>;
using diag_type = matrix_<diagonal_size, 1, T>;
using transpose_type = matrix_<C, R, T>;
using col_type = matrix_<R, 1, T>;
using row_type = matrix_<1, C, T>;
using transpose_type = matrix_<C, R, T>;
matrix_<R, C, T> &operator=(const matrix_<R, C, T> &other)
{
for (size_t i = 0; i < other.size(); i++)
(*this)[i] = other[i];
return *this;
}
value_type data[R * C]{};
matrix_(std::initializer_list<T> args)
{
typename std::initializer_list<T>::iterator it = args.begin();
for (; it != args.end(); it++)
data[it - args.begin()] = *it;
}
template <typename... Arguments>
matrix_ &set(Arguments... values)
{
static_assert(sizeof...(Arguments) == R * C, "Incorrect number of arguments");
data = {values...};
return *this;
}
template <typename... Arguments>
static constexpr auto make(Arguments&&... values) -> matrix_ {
static_assert(sizeof...(Arguments) == coefficients,
"Incorrect number of arguments");
return {.data = { T(values)... } };
}
inline size_t offset(size_t r, size_t c) const
{
return (RowMajor) ? r * C + c : c * R + r;
}
constexpr size_t offset(size_t r, size_t c) const noexcept {
return (RowMajor) ? r * C + c : c * R + r;
}
inline T &operator()(std::size_t r, std::size_t c)
{
return data[offset(r, c)];
}
constexpr T& operator()(std::size_t r, std::size_t c) noexcept {
return data[offset(r, c)];
}
inline const T &operator()(std::size_t r, std::size_t c) const
{
return data[offset(r, c)];
}
constexpr const T& operator()(std::size_t r, std::size_t c) const noexcept {
return data[offset(r, c)];
}
inline const T *ptr() const { return &data[0]; }
constexpr const T* ptr() const noexcept { return &data[0]; }
//! set identity
inline matrix_ &set_identity()
{
for (std::size_t r = 0; r < rows; r++)
for (std::size_t c = 0; c < cols; c++)
(*this)(r, c) = (c == r) ? T(1) : T(0);
return *this;
}
//! set identity
constexpr matrix_& set_identity() {
for (std::size_t r = 0; r < rows; r++)
for (std::size_t c = 0; c < cols; c++)
(*this)(r, c) = (c == r) ? T(1) : T(0);
return *this;
}
inline matrix_ &set_uniform(const T& v)
{
std::fill(std::begin(data),std::end(data),v);
return *this;
}
constexpr matrix_& set_uniform(const T& v) {
std::fill(std::begin(data), std::end(data), v);
return *this;
}
template <std::size_t Rs, std::size_t Cs, bool RowMajorSlice = RowMajor>
auto slice(std::size_t r, std::size_t c) const
{
matrix_<Rs, Cs, T, RowMajorSlice> s;
for (std::size_t ri = 0; ri < Rs; ri++)
for (std::size_t ci = 0; ci < Cs; ci++)
s(ri, ci) = (*this)(ri + r, ci + c);
return s;
}
template <std::size_t Rs, std::size_t Cs, bool RowMajorSlice = RowMajor>
auto slice(std::size_t r, std::size_t c) const {
matrix_<Rs, Cs, T, RowMajorSlice> s;
for (std::size_t ri = 0; ri < Rs; ri++)
for (std::size_t ci = 0; ci < Cs; ci++)
s(ri, ci) = (*this)(ri + r, ci + c);
return s;
}
template <std::size_t Rs, std::size_t Cs, bool RowMajorSlice = RowMajor>
matrix_ &set_slice(const matrix_<Rs, Cs, T, RowMajorSlice> &s,
std::size_t r, std::size_t c)
{
for (std::size_t ri = 0; ri < Rs; ri++)
for (std::size_t ci = 0; ci < Cs; ci++)
(*this)(ri + r, ci + c) = s(ri, ci);
return *this;
}
template <std::size_t Rs, std::size_t Cs, bool RowMajorSlice = RowMajor>
matrix_& set_slice(const matrix_<Rs, Cs, T, RowMajorSlice>& s,
std::size_t r, std::size_t c) {
for (std::size_t ri = 0; ri < Rs; ri++)
for (std::size_t ci = 0; ci < Cs; ci++)
(*this)(ri + r, ci + c) = s(ri, ci);
return *this;
}
template <std::size_t Rs, std::size_t Cs, bool RowMajorSlice = RowMajor>
auto minor(std::size_t r0, std::size_t c0) const
{
matrix_<Rs, Cs, T, RowMajorSlice> m;
size_t r = 0;
for (size_t ri = 0; ri < R; ri++)
{
size_t c = 0;
if (ri == r0)
continue;
for (size_t ci = 0; ci < C; ci++)
{
if (ci == c0)
continue;
m(r, c) = (*this)(ri, ci);
c++;
}
r++;
}
return m;
}
template <std::size_t Rs, std::size_t Cs, bool RowMajorSlice = RowMajor>
auto minor(std::size_t r0, std::size_t c0) const {
matrix_<Rs, Cs, T, RowMajorSlice> m;
size_t r = 0;
for (size_t ri = 0; ri < R; ri++) {
size_t c = 0;
if (ri == r0)
continue;
for (size_t ci = 0; ci < C; ci++) {
if (ci == c0)
continue;
m(r, c) = (*this)(ri, ci);
c++;
}
r++;
}
return m;
}
T determinant() const
{
T det(0);
for (size_t c = 0; c < C; c++)
det += ((c % 2 == 0) ? (*this)(0, c) : -(*this)(0, c)) * this->minor<R - 1, C - 1, RowMajor>(0, c).determinant();
return det;
}
constexpr T determinant() const {
T det(0);
for (size_t c = 0; c < C; c++)
det += ((c % 2 == 0) ? (*this)(0, c) : -(*this)(0, c)) *
this->minor<R - 1, C - 1, RowMajor>(0, c).determinant();
return det;
}
auto transposed() const
{
transpose_type res;
for (size_t r = rows; r-- > 0;)
for (size_t c = cols; c-- > 0;)
res(c, r) = (*this)(r, c);
return res;
}
auto transposed() const {
transpose_type res;
for (size_t r = rows; r-- > 0;)
for (size_t c = cols; c-- > 0;)
res(c, r) = (*this)(r, c);
return res;
}
auto inverse() const
{
T invDet = T(1) / this->determinant();
matrix_<R, C, T, RowMajor> inv;
for (int j = 0; j < C; j++)
for (int i = 0; i < R; i++)
{
const T minorDet = this->minor<R - 1, C - 1, RowMajor>(j, i).determinant();
const T coFactor = ((i + j) % 2 == 1) ? -minorDet : minorDet;
inv(i, j) = invDet * coFactor;
}
return inv;
}
auto inverse() const {
T invDet = T(1) / this->determinant();
matrix_<R, C, T, RowMajor> inv;
for (int j = 0; j < C; j++)
for (int i = 0; i < R; i++) {
const T minorDet =
this->minor<R - 1, C - 1, RowMajor>(j, i).determinant();
const T coFactor = ((i + j) % 2 == 1) ? -minorDet : minorDet;
inv(i, j) = invDet * coFactor;
}
return inv;
}
inline bool row_major() const
{
return RowMajor;
}
constexpr bool row_major() const { return RowMajor; }
inline bool square() const { return R == C; }
constexpr bool square() const { return R == C; }
inline const matrix_ operator+(const matrix_ &other) const
{
matrix_ res(*this);
for (size_t r = 0; r < R; r++)
for (size_t c = 0; c < C; c++)
res(r, c) += other(r, c);
return res;
}
constexpr const matrix_ operator+(const matrix_& other) const {
matrix_ res(*this);
for (size_t r = 0; r < R; r++)
for (size_t c = 0; c < C; c++)
res(r, c) += other(r, c);
return res;
}
inline const matrix_ operator-(const matrix_ &other) const
{
matrix_ res(*this);
for (size_t r = 0; r < R; r++)
for (size_t c = 0; c < C; c++)
res(r, c) -= other(r, c);
return res;
}
constexpr const matrix_ operator-(const matrix_& other) const {
matrix_ res(*this);
for (size_t r = 0; r < R; r++)
for (size_t c = 0; c < C; c++)
res(r, c) -= other(r, c);
return res;
}
auto row(size_t row_) const
{
row_type r;
for (size_t i = 0; i < cols; i++)
r[i] = (*this)(row_, i);
return r;
}
auto row(size_t row_) const {
row_type r;
for (size_t i = 0; i < cols; i++)
r[i] = (*this)(row_, i);
return r;
}
auto column(size_t col_) const
{
col_type c;
for (size_t i = 0; i < rows; i++)
c[i] = (*this)(i, col_);
return c;
}
auto column(size_t col_) const {
col_type c;
for (size_t i = 0; i < rows; i++)
c[i] = (*this)(i, col_);
return c;
}
static constexpr auto identity()
{
matrix_ res;
for (std::size_t r = 0; r < rows; r++)
for (std::size_t c = 0; c < cols; c++)
res(r, c) = (c == r) ? T(1) : T(0);
return res;
}
};
static constexpr auto identity() {
matrix_ res;
for (std::size_t r = 0; r < rows; r++)
for (std::size_t c = 0; c < cols; c++)
res(r, c) = (c == r) ? T(1) : T(0);
return res;
}
};
template <>
inline float matrix_<1, 1, float>::determinant() const
{
return (*this)(0, 0);
}
template <>
inline double matrix_<1, 1, double>::determinant() const
{
return (*this)(0, 0);
}
template <typename T, std::size_t R, std::size_t Ca, std::size_t Cb>
auto operator*(const matrix_<R, Ca, T> &A,
const matrix_<R, Cb, T> &B)
{
matrix_<R, Cb, T> result;
result.zero(); // zero the output
for (size_t r = 0; r < R; r++)
for (size_t c = 0; c < Cb; c++)
for (size_t iI = 0; iI < R; iI++)
result(r, c) += A(r, iI) * B(iI, c); // inner product
return result;
}
//
// common matrix types
//
template <typename T>
using matrix2x2_ = matrix_<2, 2, T>;
template <typename T>
using matrix3x3_ = matrix_<3, 3, T>;
template <typename T>
using matrix4x4_ = matrix_<4, 4, T>;
using matrix2x2f = matrix2x2_<float>;
using matrix2x2d = matrix2x2_<double>;
using matrix2x2 = matrix2x2_<real_t>;
using matrix3x3f = matrix3x3_<float>;
using matrix3x3d = matrix3x3_<double>;
using matrix3x3 = matrix3x3_<real_t>;
using matrix4x4f = matrix4x4_<float>;
using matrix4x4d = matrix4x4_<double>;
using matrix4x4 = matrix4x4_<real_t>;
template <> constexpr float matrix_<1, 1, float>::determinant() const {
return (*this)(0, 0);
}
template <> constexpr double matrix_<1, 1, double>::determinant() const {
return (*this)(0, 0);
}
template <typename T, std::size_t R, std::size_t Ca, std::size_t Cb>
auto operator*(const matrix_<R, Ca, T>& A, const matrix_<R, Cb, T>& B) {
matrix_<R, Cb, T> result;
result.zero(); // zero the output
for (size_t r = 0; r < R; r++)
for (size_t c = 0; c < Cb; c++)
for (size_t iI = 0; iI < R; iI++)
result(r, c) += A(r, iI) * B(iI, c); // inner product
return result;
}
//
// common matrix types
//
template <typename T> using matrix2x2_ = matrix_<2, 2, T>;
template <typename T> using matrix3x3_ = matrix_<3, 3, T>;
template <typename T> using matrix4x4_ = matrix_<4, 4, T>;
using matrix2x2f = matrix2x2_<float>;
using matrix2x2d = matrix2x2_<double>;
using matrix2x2 = matrix2x2_<real_t>;
using matrix3x3f = matrix3x3_<float>;
using matrix3x3d = matrix3x3_<double>;
using matrix3x3 = matrix3x3_<real_t>;
using matrix4x4f = matrix4x4_<float>;
using matrix4x4d = matrix4x4_<double>;
using matrix4x4 = matrix4x4_<real_t>;
} // namespace pw
#endif

View file

@ -30,8 +30,7 @@ namespace pw {
template <typename T>
struct matrix_transform {
inline static
matrix_<4,4,T> scale_matrix(const vector3_<T>& s)
constexpr static matrix_<4,4,T> scale_matrix(const vector3_<T>& s) noexcept
{
matrix_<4,4,T> scale; scale.zero();
scale(0,0) = s[0]; scale(1,1) = s[1]; scale(2,2) = s[2]; scale(3,3) = T(1);

View file

@ -24,93 +24,97 @@
#define PW_CORE_MATRIXBASE_HPP
#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <type_traits>
#include <utility>
#include <initializer_list>
#include <cmath>
#include <iostream>
namespace pw {
template <typename T, typename Derived>
struct matrixbase_ {
using value_type = T;
using derived_type = Derived;
using iterator = value_type*;
using const_iterator = const value_type*;
Derived& derived() { return static_cast<Derived&>(*this); }
const Derived& derived() const { return static_cast<const Derived&>(*this); }
constexpr Derived& derived() noexcept { return static_cast<Derived&>(*this); }
constexpr const Derived& derived() const noexcept { return static_cast<const Derived&>(*this); }
std::size_t size() const {
constexpr std::size_t size() const noexcept {
return std::extent<decltype(Derived::data)>::value;
}
Derived& fill(const T& v) {
constexpr Derived& fill(const T& v) noexcept {
std::fill(std::begin(derived().data), std::end(derived().data), T(v));
return derived();
}
Derived& zero() {
constexpr Derived& zero() {
return derived().fill(0);
}
inline T squared_norm() const {
constexpr T squared_norm() const noexcept {
return std::accumulate(std::begin(derived().data),std::end(derived().data), T(0),
[&](const T& a,const T& b){
return a + b * b;
});
}
inline T norm() const {
static constexpr Derived
all(const std::convertible_to<T> auto& v) noexcept {
Derived d;
d.fill(v);
return d;
}
constexpr T norm() const noexcept {
return std::sqrt(squared_norm());
}
inline constexpr Derived normalized() const {
constexpr Derived normalized() const noexcept {
return *this / this->norm() ;
}
inline void normalize() {
constexpr void normalize() {
*this /= this->norm();
}
using iterator = T*;
using const_iterator = const T*;
iterator begin() { return &derived().data[0]; }
iterator end() { return &derived().data[0] + size(); }
const_iterator begin() const { return &derived().data[0]; }
const_iterator end() const { return &derived().data[0] + size(); }
T& operator [] (std::size_t i) {
constexpr iterator begin() { return &derived().data[0]; }
constexpr iterator end() { return &derived().data[0] + size(); }
constexpr const_iterator begin() const { return &derived().data[0]; }
constexpr const_iterator end() const { return &derived().data[0] + size(); }
constexpr T& operator [] (std::size_t i) {
return derived().data[i];
}
const T& operator [] (std::size_t i) const {
constexpr const T& operator [] (std::size_t i) const {
return derived().data[i];
}
static constexpr T dot(const Derived &a,const Derived &b)
static constexpr T dot(const Derived &a,const Derived &b) noexcept
{
return std::inner_product(std::begin(a),std::end(a),std::begin(b),T(0));
}
static constexpr Derived lerp(const Derived &a,const Derived &b,const T& t)
static constexpr Derived lerp(const Derived &a,const Derived &b,const T& t) noexcept
{
return a + (b - a) * t;
}
inline void operator *= (const T& b) { for (auto & e : *this) e *= b; }
inline void operator /= (const T& b) { for (auto & e : *this) e /= b; }
inline void operator += (const T& b) { for (auto & e : *this) e += b; }
inline void operator -= (const T& b) { for (auto & e : *this) e -= b; }
constexpr void operator *= (const T& b) { for (auto & e : *this) e *= b; }
constexpr void operator /= (const T& b) { for (auto & e : *this) e /= b; }
constexpr void operator += (const T& b) { for (auto & e : *this) e += b; }
constexpr void operator -= (const T& b) { for (auto & e : *this) e -= b; }
inline const Derived operator * (const T& b) const { Derived r(derived()); for (auto & e : r) e *= b; return r; }
inline const Derived operator / (const T& b) const { Derived r(derived()); for (auto & e : r) e /= b; return r; }
inline const Derived operator + (const T& b) const { Derived r(derived()); for (auto & e : r) e += b; return r; }
inline const Derived operator - (const T& b) const { Derived r(derived()); for (auto & e : r) e -= b; return r; }
constexpr const Derived operator * (const T& b) const { Derived r(derived()); for (auto & e : r) e *= b; return r; }
constexpr const Derived operator / (const T& b) const { Derived r(derived()); for (auto & e : r) e /= b; return r; }
constexpr const Derived operator + (const T& b) const { Derived r(derived()); for (auto & e : r) e += b; return r; }
constexpr const Derived operator - (const T& b) const { Derived r(derived()); for (auto & e : r) e -= b; return r; }
};

View file

@ -8,8 +8,8 @@
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -31,138 +31,130 @@ namespace pw {
* Basic vector types used in pixwerx.
*/
template <typename T>
struct vector2_ : matrix_<2,1,T> {
template <typename T> struct vector2_ : matrix_<2, 1, T> {
typedef matrix_<2,1,T> base_type;
using base_type = matrix_<2, 1, T>;
using base_type::base_type;
using base_type::operator = ;
using base_type::operator=;
vector2_(const base_type& m) : base_type(m) {}
vector2_(T x_,T y_) : base_type({x_,y_}) {}
vector2_(T x_, T y_) : base_type({x_, y_}) {}
inline const T& x() const { return (*this)[0]; }
inline T& x() { return (*this)[0]; }
constexpr const T& x() const { return (*this)[0]; }
constexpr T& x() { return (*this)[0]; }
inline const T& y() const { return (*this)[1]; }
inline T& y() { return (*this)[1]; }
constexpr const T& y() const { return (*this)[1]; }
constexpr T& y() { return (*this)[1]; }
inline auto homogenous(T w = 1) const { return matrix_<3,1,T>( { x(),y(),w } ); }
static T angle_between(const vector2_ &a,const vector2_ &b) {
return std::acos( dot( a.normalized(), b.normalized() ) );
constexpr auto homogenous(T w = 1) const {
return matrix_<3, 1, T>({x(), y(), w});
}
static constexpr auto zero() { return vector2_<T>(0,0); }
};
template <typename T>
struct vector3_ : matrix_<3,1,T> {
typedef matrix_<3,1,T> base_type;
using base_type::base_type;
using base_type::operator = ;
vector3_() : base_type() {}
vector3_(const base_type& m) : base_type(m) {}
vector3_(T x_,T y_,T z_) : base_type({x_,y_,z_}) {}
vector3_(const vector2_<T> &m, T w) : base_type({m(0),m(1),w}) {}
inline const T& x() const { return (*this)[0]; }
inline T& x() { return (*this)[0]; }
inline vector3_& set_x(T val) { (*this)[0] = val; return *this;}
inline const T& y() const { return (*this)[1]; }
inline T& y() { return (*this)[1]; }
inline vector3_& set_y(T val) { (*this)[1] = val; return *this;}
inline const T& z() const { return (*this)[2]; }
inline T& z() { return (*this)[2]; }
inline vector3_& set_z(T val) { (*this)[2] = val; return *this;}
inline auto xy() const { return vector2_( { x(),y() } ); }
inline auto homogenous(T w = 1) const { return matrix_<4,1,T>( { x(),y(),z(),w } ); }
inline static constexpr vector3_ cross(const vector3_& lhs,
const vector3_& rhs)
{
return vector3_( {
lhs[1] * rhs[2] - rhs[1] * lhs[2],
lhs[2] * rhs[0] - rhs[2] * lhs[0],
lhs[0] * rhs[1] - rhs[0] * lhs[1]
}
);
static T angle_between(const vector2_& a, const vector2_& b) {
return std::acos(dot(a.normalized(), b.normalized()));
}
inline static constexpr vector3_<T> forward() { return vector3_<T> ( { T(0), T(0),-T(1) } ); }
inline static constexpr vector3_<T> backward() { return vector3_<T>( { T(0), T(0), T(1) } ); }
inline static constexpr vector3_<T> right() { return vector3_<T> ( { T(1), T(0), T(0) } ); }
inline static constexpr vector3_<T> left() { return vector3_<T> ( {-T(1), T(0), T(0) } ); }
inline static constexpr vector3_<T> up() { return vector3_<T> ( { T(0), T(1), T(0) } ); }
inline static constexpr vector3_<T> down() { return vector3_<T> ( { T(0),-T(1), T(0) } ); }
inline static vector3_<T> x_axis() { return vector3_<T> ( { T(1), T(0), T(0) } ); }
inline static vector3_<T> y_axis() { return vector3_<T> ( { T(0), T(1), T(0) } ); }
inline static vector3_<T> z_axis() { return vector3_<T> ( { T(0), T(0), T(1) } ); }
static constexpr auto zero() { return vector3_(0,0,0); }
static constexpr auto zero() { return vector2_<T>(0, 0); }
};
template <typename T>
struct vector4_ : matrix_<4,1,T> {
template <typename T> struct vector3_ : matrix_<3, 1, T> {
typedef matrix_<4,1,T> base_type;
typedef matrix_<3, 1, T> base_type;
using base_type::base_type;
using base_type::operator = ;
// using base_type::base_type;
// using base_type::operator=;
vector4_(T x_,T y_,T z_,T w_) : base_type( {x_,y_,z_,w_} ) {}
vector4_(const base_type& m) : base_type(m) {}
vector4_(const vector3_<T> &m, T w) : base_type({m(0),m(1),m(2),w}) {}
constexpr const T& x() const { return (*this)[0]; }
constexpr T& x() { return (*this)[0]; }
constexpr vector3_& set_x(T val) {
(*this)[0] = val;
return *this;
}
inline const T& x() const { return (*this)[0]; }
inline T& x() { return (*this)[0]; }
constexpr const T& y() const { return (*this)[1]; }
constexpr T& y() { return (*this)[1]; }
constexpr vector3_& set_y(T val) {
(*this)[1] = val;
return *this;
}
inline const T& y() const { return (*this)[1]; }
inline T& y() { return (*this)[1]; }
constexpr const T& z() const { return (*this)[2]; }
constexpr T& z() { return (*this)[2]; }
constexpr vector3_& set_z(T val) {
(*this)[2] = val;
return *this;
}
inline const T& z() const { return (*this)[2]; }
inline T& z() { return (*this)[2]; }
constexpr auto xy() const { return vector2_({x(), y()}); }
constexpr auto homogenous(T w = 1) const {
return matrix_<4, 1, T>::make(x(), y(), z(), w);
}
inline const T& w() const { return (*this)[3]; }
inline T& w() { return (*this)[3]; }
constexpr static vector3_ cross(const vector3_& lhs, const vector3_& rhs) {
return vector3_::make(lhs[1] * rhs[2] - rhs[1] * lhs[2],
lhs[2] * rhs[0] - rhs[2] * lhs[0],
lhs[0] * rhs[1] - rhs[0] * lhs[1]);
}
inline auto xyz() const { return vector3_<T>({ x(),y(),z() } ); }
constexpr static auto forward() { return vector3_<T>::make(0, 0, -1); }
constexpr static auto backward() { return vector3_<T>::make(0, 0, +1); }
constexpr static auto up() { return vector3_<T>::make(0, +1, 0); }
constexpr static auto down() { return vector3_<T>::make(0, -1, 0); }
constexpr static auto right() { return vector3_<T>::make(+1, 0, 0); }
constexpr static auto left() { return vector3_<T>::make(-1, 0, 0); }
constexpr static auto x_axis() { return vector3_<T>::make(0, 0, +1); }
constexpr static auto y_axis() { return vector3_<T>::make(0, 0, +1); }
constexpr static auto z_axis() { return vector3_<T>::make(0, 0, +1); }
inline auto project() const { return vector3_<T>({ x()/w(),y()/w(),z()/w() } ); }
static constexpr auto zero() { return vector3_(0, 0, 0); }
};
static constexpr auto zero() { return vector2_<T>(0,0,0,0); }
template <typename T> struct vector4_ : matrix_<4, 1, T> {
using base_type = matrix_<4, 1, T>;
// using base_type::operator=;
constexpr const T& x() const { return (*this)[0]; }
constexpr T& x() { return (*this)[0]; }
constexpr const T& y() const { return (*this)[1]; }
constexpr T& y() { return (*this)[1]; }
constexpr const T& z() const { return (*this)[2]; }
constexpr T& z() { return (*this)[2]; }
constexpr const T& w() const { return (*this)[3]; }
constexpr T& w() { return (*this)[3]; }
constexpr auto xyz() const { return vector3_<T>::make(x(), y(), z()); }
constexpr auto project() const {
return vector3_<T>::make(x() / w(), y() / w(), z() / w());
}
static constexpr auto zero() { return vector2_<T>(0, 0, 0, 0); }
};
//
//
//
using vector2f = vector2_<float>;
using vector2d = vector2_<double>;
using vector2i = vector2_<int>;
using vector2 = vector2_<real_t>;
using vector2f = vector2_<float>;
using vector2d = vector2_<double>;
using vector2i = vector2_<int>;
using vector2 = vector2_<real_t>;
using vector2_array = std::vector<vector2>;
using vector3f = vector3_<float>;
using vector3d = vector3_<double>;
using vector3 = vector3_<real_t>;
using vector3f = vector3_<float>;
using vector3d = vector3_<double>;
using vector3 = vector3_<real_t>;
using vector3_array = std::vector<vector3>;
using vector4f = vector4_<float>;
using vector4d = vector4_<double>;
using vector4 = vector4_<real_t>;
}
} // namespace pw
#endif

View file

@ -3,6 +3,7 @@
#include <limits>
#include <random>
#include <algorithm>
namespace pw {

View file

@ -7,9 +7,9 @@ macro(make_test arg1)
endmacro()
make_test(pwcore_test_matrix)
make_test(pwcore_test_vector)
make_test(pwcore_test_axisangle)
make_test(pwcore_test_quaternion)
make_test(pwcore_test_transform_tools)
make_test(pwcore_test_mesh)
# make_test(pwcore_test_matrix)
# make_test(pwcore_test_vector)
# make_test(pwcore_test_axisangle)
# make_test(pwcore_test_quaternion)
# make_test(pwcore_test_transform_tools)
# make_test(pwcore_test_mesh)

View file

@ -28,8 +28,6 @@ scene::scene()
// size_t scene::count_all_enties() const
// {
// return _registry->storage().
// size_t scene::count_alive_enties() const
// {
// return _registry->storage().alive();

21
tests/CMakeLists.txt Normal file
View file

@ -0,0 +1,21 @@
include(FetchContent)
FetchContent_Declare(snitch
GIT_REPOSITORY https://github.com/snitch-org/snitch.git
GIT_TAG v1.2.5) # update version number as needed
FetchContent_MakeAvailable(snitch)
set(pixwerx_test_files
pw_test_core.cpp
)
add_executable(pixwerx_tests ${pixwerx_test_files})
target_link_libraries(pixwerx_tests PRIVATE
snitch::snitch
pwcore
)

66
tests/pw_test_core.cpp Normal file
View file

@ -0,0 +1,66 @@
#include <snitch/snitch.hpp>
#include <pw/core/matrix.hpp>
#include <pw/core/vector.hpp>
TEST_CASE("core", "[matrix]") {
auto m44 = pw::matrix_<2, 2, float>{};
REQUIRE(m44(0, 0) == 0);
REQUIRE(m44(0, 1) == 0);
REQUIRE(m44(1, 0) == 0);
REQUIRE(m44(1, 1) == 0);
m44 = pw::matrix2x2_<float>::all(42.42f);
REQUIRE(m44(0, 0) == 42.42f);
REQUIRE(m44(0, 1) == 42.42f);
REQUIRE(m44(1, 0) == 42.42f);
REQUIRE(m44(1, 1) == 42.42f);
m44 *= 2;
REQUIRE(m44(0, 0) == 84.84f);
REQUIRE(m44(0, 1) == 84.84f);
REQUIRE(m44(1, 0) == 84.84f);
REQUIRE(m44(1, 1) == 84.84f);
m44.set_identity();
REQUIRE(m44(0, 0) == 1.0f);
REQUIRE(m44(0, 1) == 0.0f);
REQUIRE(m44(1, 0) == 0.0f);
REQUIRE(m44(1, 1) == 1.0f);
auto m44_2 = pw::matrix2x2::make(0, 1, 2, 3);
REQUIRE(m44_2(0, 0) == 0.0f);
REQUIRE(m44_2(1, 0) == 1.0f);
REQUIRE(m44_2(0, 1) == 2.0f);
REQUIRE(m44_2(1, 1) == 3.0f);
pw::matrix2x2 m44_3 = {{},{1, 2, 3, 4}};
REQUIRE(m44_3(0, 0) == 1.0f);
REQUIRE(m44_3(1, 0) == 2.0f);
REQUIRE(m44_3(0, 1) == 3.0f);
REQUIRE(m44_3(1, 1) == 4.0f);
}
TEST_CASE("core", "[vector]") {
auto vec4_1 = pw::vector4_<float>{};
auto vec4_2 = pw::vector4::make(1, 2, 3, 4);
auto vec4_3 = vec4_1 + vec4_2;
REQUIRE(vec4_3[0] == 1.0f);
REQUIRE(vec4_3[1] == 2.0f);
REQUIRE(vec4_3[2] == 3.0f);
REQUIRE(vec4_3[3] == 4.0f);
}