windows, monitors and provider

This commit is contained in:
L-Nafaryus 2022-10-27 22:27:50 +05:00
parent 7a264e5680
commit 38c644ffdf
36 changed files with 1490 additions and 337 deletions

View File

@ -28,7 +28,8 @@ public:
Context(DeviceAPI api);
virtual ~Context();
virtual
~Context();
// Member functions

View File

@ -8,16 +8,16 @@ namespace hpr::gpu
Device::Device() :
Context {DeviceAPI::Unknown},
p_currentVertexBuffer {nullptr},
p_currentIndexBuffer {nullptr},
p_currentShaderProgram {nullptr}
p_currentVertexBuffer {},
p_currentIndexBuffer {},
p_currentShaderProgram {}
{}
Device::Device(DeviceAPI api) :
Context {api},
p_currentVertexBuffer {nullptr},
p_currentIndexBuffer {nullptr},
p_currentShaderProgram {nullptr}
p_currentVertexBuffer {},
p_currentIndexBuffer {},
p_currentShaderProgram {}
{}
Device::~Device()
@ -28,16 +28,16 @@ Device::~Device()
void Device::create(Device** device, DeviceAPI api)
{
if (device == nullptr)
throw "Invalid parameter";
throw std::invalid_argument("Invalid parameter 'nullptr'");
if (api == DeviceAPI::Unknown)
throw "Invalid parameter";
throw std::invalid_argument("Cannot create device for 'Unknown'");
*device = nullptr;
if (api == DeviceAPI::OpenGL)
*device = new opengl::Device;
else
throw "Unsupported device";
throw std::invalid_argument("Unsupported device");
}
// Buffers

View File

@ -6,7 +6,7 @@
#include "shader_program.hpp"
#include "texture.hpp"
#include <vector>
#include "../hyplib/array/array.hpp"
namespace hpr::gpu
@ -27,10 +27,10 @@ public:
protected:
std::vector<Buffer> p_buffers;
std::vector<Shader> p_shaders;
std::vector<ShaderProgram> p_shaderPrograms;
std::vector<Texture> p_textures;
darray<Buffer> p_buffers;
darray<Shader> p_shaders;
darray<ShaderProgram> p_shaderPrograms;
darray<Texture> p_textures;
Buffer* p_currentVertexBuffer;
Buffer* p_currentIndexBuffer;

View File

@ -0,0 +1,5 @@
//
// Created by L-Nafaryus on 10/27/2022.
//
#include "monitor.hpp"

View File

@ -0,0 +1,14 @@
#pragma once
#include "../monitor.hpp"
namespace hpr::gpu::glfw
{
class Monitor : public gpu::Monitor
{
};
}

View File

@ -0,0 +1,5 @@
//
// Created by L-Nafaryus on 10/27/2022.
//
#include "window.hpp"

View File

@ -0,0 +1,8 @@
//
// Created by L-Nafaryus on 10/27/2022.
//
#ifndef HYPORO_WINDOW_HPP
#define HYPORO_WINDOW_HPP
#endif //HYPORO_WINDOW_HPP

View File

@ -0,0 +1,5 @@
//
// Created by L-Nafaryus on 10/27/2022.
//
#include "window_system.hpp"

View File

@ -0,0 +1,28 @@
#pragma once
#include "../window_system.hpp"
#include <GLFW/glfw3.h>
namespace hpr::gpu::glfw
{
class WindowSystem : public gpu::WindowSystem
{
protected:
GLFWwindow p_instance;
public:
WindowSystem();
~WindowSystem();
virtual
void newWindow(Window** window);
};
}

View File

@ -0,0 +1,44 @@
#include "monitor.hpp"
namespace hpr::gpu
{
Monitor::Monitor() :
WindowContext(Provider::Unknown),
p_deviceName {},
p_originX {0},
p_originY {0},
p_width {0},
p_height {0},
p_logicalWidth {0},
p_logicalHeight {0}
{}
Monitor::~Monitor() = default;
void Monitor::origin(int x, int y)
{
p_originX = x;
p_originY = y;
}
void Monitor::size(int width, int height)
{
p_width = width;
p_height = height;
}
void Monitor::logicalSize(int width, int height)
{
p_logicalWidth = width;
p_logicalHeight = height;
}
void Monitor::deviceName(const std::string &name)
{
p_deviceName = name;
}
}

View File

@ -0,0 +1,82 @@
#pragma once
#include "window_context.hpp"
#include <string>
namespace hpr::gpu
{
class Monitor : WindowContext
{
protected:
std::string p_deviceName;
int p_originX;
int p_originY;
int p_width;
int p_height;
int p_logicalWidth;
int p_logicalHeight;
public:
Monitor();
virtual
~Monitor();
// Member functions
void origin(int x, int y);
void size(int width, int height);
void logicalSize(int width, int height);
void deviceName(const std::string& name);
inline
int width() const
{
return p_width;
}
inline
int height() const
{
return p_height;
}
inline
int logicalWidth() const
{
return p_logicalWidth;
}
inline
int logicalHeight() const
{
return p_logicalHeight;
}
inline
int originX() const
{
return p_originX;
}
inline
int originY() const
{
return p_originY;
}
inline
std::string deviceName() const
{
return p_deviceName;
}
};
}

View File

@ -19,7 +19,7 @@ public:
Device();
~Device();
~Device() override;
// Member functions

View File

@ -3,7 +3,7 @@
#include "context.hpp"
#include "shader.hpp"
#include <array>
#include "../hyplib/array/array.hpp"
namespace hpr::gpu
@ -15,7 +15,7 @@ class ShaderProgram : public Context
protected:
std::array<Shader*, (size_t)Shader::ShaderType::ShaderTypeCount> p_slots;
sarray<Shader*, (size_t)Shader::ShaderType::ShaderTypeCount> p_slots;
bool p_isLinked;
public:

View File

@ -0,0 +1,103 @@
#include "window.hpp"
namespace hpr::gpu
{
Window::Window() :
WindowContext(Provider::Unknown),
p_width {0},
p_height {0},
p_posX {0},
p_posY {0},
p_title {},
p_state {State::Hidden},
p_style {Style::Unknown},
p_parent {nullptr},
p_monitor {nullptr},
p_isActive {true},
p_isResizing {false}
{}
Window::~Window() = default;
void Window::init(const std::string& title, Style style, int x, int y, int width, int height, Window* parent, Monitor* monitor)
{
p_width = width;
p_height = height;
p_posX = x;
p_posY = y;
p_title = title;
p_state = State::Hidden;
p_style = style;
p_parent = parent;
p_monitor = monitor;
}
void Window::init(const std::string& title, Style style, Window* parent, Monitor* monitor)
{
init(title, style, monitor->originX(), monitor->originY(), monitor->width(), monitor->height(), parent, monitor);
}
void Window::state(State state)
{
p_state = state;
}
void Window::close()
{
state(State::Closed);
}
void Window::restore()
{
State prevState {p_state};
init(p_title, p_style, p_posX, p_posY, p_width, p_height, p_parent, p_monitor);
state(prevState);
}
bool Window::isOpen() const
{
return p_state != State::Closed;
}
bool Window::isActive() const
{
return p_isActive;
}
void Window::size(int width, int height)
{
resizeCallback(width, height);
}
void Window::position(int x, int y)
{
moveCallback(x, y);
}
void Window::title(const std::string& title)
{
p_title = title;
}
void Window::style(Style style)
{
p_style = style;
}
void Window::resizeCallback(int width, int height)
{
p_width = width;
p_height = height;
}
void Window::moveCallback(int x, int y)
{
p_posX = x;
p_posY = y;
}
}

View File

@ -0,0 +1,97 @@
#pragma once
#include "window_context.hpp"
#include "monitor.hpp"
namespace hpr::gpu
{
class Window : public WindowContext
{
public:
enum class State
{
Unknown,
Visible,
Hidden,
Maximized,
Minimized,
Closed,
};
enum class Style
{
Unknown,
Windowed,
Fullscreen,
Popup
};
protected:
int p_width;
int p_height;
int p_posX;
int p_posY;
std::string p_title;
State p_state;
Style p_style;
Window* p_parent;
Monitor* p_monitor;
bool p_isActive;
bool p_isResizing;
public:
Window();
virtual
~Window();
// Member functions
virtual
void init(const std::string& title, Style style, int x, int y, int width, int height, Window* parent, Monitor* monitor);
virtual
void init(const std::string& title, Style style, Window* parent, Monitor* monitor);
virtual
void state(State state = State::Visible);
virtual
void close();
virtual
void restore();
virtual
bool isOpen() const;
virtual
bool isActive() const;
virtual
void size(int width, int height);
virtual
void position(int x, int y);
virtual
void title(const std::string& title);
virtual
void style(Style style);
void resizeCallback(int width, int height);
void moveCallback(int x, int y);
};
}

View File

@ -0,0 +1,39 @@
#pragma once
namespace hpr::gpu
{
class WindowContext
{
public:
enum class Provider
{
Unknown,
GLFW
};
private:
Provider p_provider;
public:
inline
WindowContext() :
p_provider {Provider::Unknown}
{}
inline
WindowContext(Provider provider) :
p_provider {provider}
{}
virtual
~WindowContext() = default;
};
}

View File

@ -0,0 +1,63 @@
#include "window_system.hpp"
#include "glfw/window_system.hpp"
namespace hpr::gpu
{
WindowSystem::WindowSystem() :
WindowContext {Provider::Unknown}
{}
WindowSystem::WindowSystem(Provider provider) :
WindowContext {provider}
{}
WindowSystem::~WindowSystem() = default;
void WindowSystem::create(WindowSystem** ws, Provider provider)
{
if (ws == nullptr)
throw std::invalid_argument("Invalid parameter 'nullptr'");
if (provider == Provider::Unknown)
throw std::invalid_argument("Cannot create window system from 'Unknown' provider");
*ws = nullptr;
if (provider == Provider::GLFW)
*ws = new glfw::WindowSystem;
else
throw std::invalid_argument("Unsupported window system");
}
void WindowSystem::destroy(WindowSystem*& ws)
{
delete ws;
ws = nullptr;
}
Window& WindowSystem::window(int index)
{
return p_windows[index];
}
void WindowSystem::closeWindow(Window* window)
{
window->close();
}
void WindowSystem::destroyWindow(Window* window)
{
p_windows.remove(*window);
}
Monitor& WindowSystem::monitor(int index)
{
return p_monitors[index];
}
void WindowSystem::destroyMonitor(Monitor* monitor)
{
p_monitors.remove(*monitor);
}
}

View File

@ -0,0 +1,62 @@
#pragma once
#include "window.hpp"
#include "monitor.hpp"
#include "../hyplib/array/array.hpp"
#include <string>
namespace hpr::gpu
{
class WindowSystem : WindowContext
{
protected:
darray<Window> p_windows;
darray<Monitor> p_monitors;
protected:
WindowSystem();
WindowSystem(Provider provider);
virtual
~WindowSystem();
public:
// Global functions
static
void create(WindowSystem** ws, Provider provider);
static
void destroy(WindowSystem*& ws);
// Window interface
virtual
void newWindow(Window** window) = 0;
Window& window(int index);
void closeWindow(Window* window);
void destroyWindow(Window* window);
// Monitor interface
virtual
void newMonitor(Monitor** monitor) = 0;
Monitor& monitor(int index);
void destroyMonitor(Monitor* monitor);
};
}

View File

@ -10,7 +10,6 @@ include_directories(
add_library(hyporo-hyplib STATIC
# Header files
integer/integer.hpp
scalar/scalar.hpp
array/iterator.hpp
@ -20,26 +19,31 @@ add_library(hyporo-hyplib STATIC
vector/vector_space.hpp
vector/VectorSpace.hpp
vector/vector.hpp
matrix/MatrixSpace.hpp
matrix/matrix_space.hpp
matrix/matrix.hpp
io/file.hpp
io/io.hpp
# Source files
scalar/scalar.cpp
io/file.cpp
matrix/matrix_space.cpp
)
if(WITH_GTESTS)
add_executable(hyporo-hyplib-test
tests/hyplib-test.cpp
matrix/matrix_space.hpp
)
target_link_libraries(hyporo-hyplib-test
hyporo-hyplib
GTest::gtest_main
)

View File

@ -255,6 +255,35 @@ public:
++p_end;
}
virtual
int findByAddress(const value_type& value)
{
for (int n = 0; n < p_size; ++n)
if (std::addressof(*(p_start + n)) == std::addressof(value))
return n;
return -1;
}
virtual
void remove(size_type position)
{
for (size_type n = position; n < p_size - 1; ++n)
*(p_start + n) = std::move(*(p_start + n + 1));
std::destroy_at(p_end);
--p_end;
--p_size;
}
virtual
void remove(const value_type& value)
{
size_type index = findByAddress(value);
if (index != -1)
remove(index);
else
throw std::runtime_error("Value is not found to remove it");
}
// Friend functions
friend

View File

@ -2,6 +2,8 @@
#include "iterator.hpp"
#include <limits>
#include <functional>
namespace hpr
{
@ -20,7 +22,7 @@ public:
using iterator = Iterator<Type>;
using const_pointer = Type const*;
using const_reference = Type const&;
using const_iterator = Iterator<Type> const;
using const_iterator = Iterator<const Type>;
protected:
@ -64,12 +66,50 @@ public:
}
inline
StaticArray(std::initializer_list<value_type> list) :
p_size {Size},
p_start {new value_type[p_size]},
p_end {p_start + p_size}
StaticArray(const_iterator start, const_iterator end) :
p_size {Size},
p_start {new value_type[p_size]},
p_end {p_start + p_size}
{
std::copy(list.begin(), list.end(), p_start);
std::copy(start, end, p_start);
}
inline
StaticArray(iterator start, iterator end) :
p_size {Size},
p_start {new value_type[p_size]},
p_end {p_start + p_size}
{
std::copy(start, end, p_start);
}
inline
StaticArray(std::initializer_list<value_type> list) :
StaticArray {list.begin(), list.end()}
{}
template <std::convertible_to<value_type>... Args>
inline
StaticArray(value_type&& v, Args&& ...args) :
StaticArray {std::initializer_list<value_type>({v, static_cast<value_type>(args)...})}
{
static_assert(1 + sizeof...(args) == Size, "Number of arguments must be equal to size of array");
}
template <size_type SubSize, std::convertible_to<value_type>... Args>
inline
StaticArray(const StaticArray<value_type, SubSize>& subarr, const value_type& v, const Args& ...args) :
p_size {Size},
p_start {new value_type[p_size]},
p_end {p_start + p_size}
{
static_assert(SubSize + 1 + sizeof...(args) == Size,
"Number of arguments and sub-array elements must be equal to size of main array");
std::initializer_list<value_type> list {v, static_cast<value_type>(args)...};
std::copy(subarr.begin(), subarr.end(), begin());
size_type pos {subarr.size()};
for (auto& val : list)
(*this)[pos++] = val;
}
inline
@ -165,10 +205,18 @@ public:
friend
void swap(StaticArray& lhs, StaticArray& rhs)
{
lhs.p_size = rhs.p_size;
std::swap(lhs.p_start, rhs.p_start);
std::swap(lhs.p_end, rhs.p_end);
}
friend
bool operator==(const StaticArray& lhs, const StaticArray& rhs)
{
for (auto n = 0; n < Size; ++n)
if (lhs[n] != rhs[n])
return false;
return true;
}
};
}

View File

@ -1,12 +0,0 @@
#include <cstddef>
namespace hyporo
{
using uint = unsigned int;
using sizet = std::size_t;
} // end namespace hyporo

View File

@ -1,33 +0,0 @@
#include "VectorSpace.hpp"
namespace hyporo
{
template <class C, sizet Mrows, sizet Ncols>
class MatrixSpace : public VectorSpace<C, Mrows * Ncols>
{
public:
// Member constants
static const sizet mRows = Mrows;
static const sizet nColumns = Ncols;
// Constructors
inline MatrixSpace();
template <class... Args>
inline MatrixSpace(const Args... components);
// Member operators
inline const C& operator()(const sizet& n, const sizet& m);
};
} // end namespace hyporo
#include "MatrixSpace.hxx"

View File

@ -1,27 +0,0 @@
namespace hyporo
{
// Constructors
template <class C, sizet Mrows, sizet Ncols>
inline MatrixSpace<C, Mrows, Ncols>::MatrixSpace()
{}
template <class C, sizet Mrows, sizet Ncols>
template <class... Args>
inline MatrixSpace<C, Mrows, Ncols>::MatrixSpace(const Args... components)
//: row { static_cast<C>(components)... }
{
this->row = { static_cast<C>(components)... };
}
// Member operators
template <class C, sizet Mrows, sizet Ncols>
inline const C& MatrixSpace<C, Mrows, Ncols>::operator()(const sizet& n, const sizet& m)
{
return this->row[n * Ncols + m];
}
} // end namespace hyporo

View File

@ -0,0 +1,54 @@
#pragma once
#include "matrix.hpp"
namespace hpr
{
template <typename Type>
inline
MatrixSpace<Type, 4, 4> ortho(Type left, Type right, Type bottom, Type top)
{
MatrixSpace<Type, 4, 4> ms;
ms.fill(1);
ms(0, 0) = 2 / (right - left);
ms(1, 1) = 2 / (top - bottom);
ms(2, 2) = -1;
ms(3, 0) = -(right + left) / (right - left);
ms(3, 1) = -(top + bottom) / (top - bottom);
return ms;
}
template <typename Type>
inline
MatrixSpace<Type, 4, 4> ortho(Type left, Type right, Type bottom, Type top, Type zNear, Type zFar)
{
MatrixSpace<Type, 4, 4> ms;
ms.fill(1);
ms(0, 0) = 2 / (right - left);
ms(1, 1) = 2 / (top - bottom);
ms(2, 2) = 2 / (zFar - zNear);
ms(3, 0) = -(right + left) / (right - left);
ms(3, 1) = -(top + bottom) / (top - bottom);
ms(3, 2) = -(zFar + zNear) / (zFar - zNear);
return ms;
}
template <typename Type>
inline
MatrixSpace<Type, 4, 4> perspective(Type fovy, Type aspect, Type zNear, Type zFar)
{
assert(abs(aspect - std::numeric_limits<Type>::epsilon()) > 0);
MatrixSpace<Type, 4, 4> ms;
const Type halfFovyTan = tan(fovy / 2);
ms(0, 0) = 1 / (aspect * halfFovyTan);
ms(1, 1) = 1 / halfFovyTan;
ms(2, 2) = (zFar + zNear) / (zFar - zNear);
ms(2, 3) = 1;
ms(3, 2) = -(2 * zFar * zNear) / (zFar - zNear);
return ms;
}
}

View File

@ -1,11 +1,15 @@
#include "MatrixSpace.hpp"
#include "../scalar/scalar.hpp"
#include "matrix_space.hpp"
namespace hyporo
namespace hpr
{
using mat3 = MatrixSpace<scalar, 3, 3>;
template <typename Type, size_t Row, size_t Col>
using mat = MatrixSpace<Type, Row, Col>;
using mat2 = MatrixSpace<scalar, 2, 2>;
using mat3 = MatrixSpace<scalar, 3, 3>;
using mat4 = MatrixSpace<scalar, 4, 4>;
} // end namespace hyporo
}

View File

@ -0,0 +1,249 @@
#pragma once
#include "../vector/vector.hpp"
namespace hpr
{
template <typename Type, size_t Rows, size_t Cols>
class MatrixSpace : public VectorSpace<Type, Rows * Cols>
{
static_assert(Rows >= 1);
static_assert(Cols >= 1);
using base = VectorSpace<Type, Rows * Cols>;
using Minor = typename std::conditional<(Rows >= 2 && Cols >= 2), MatrixSpace<Type, Rows - 1, Cols - 1>, MatrixSpace<Type, 1, 1>>::type;
public:
using value_type = Type;
using size_type = size_t;
using pointer = Type*;
using reference = Type&;
using iterator = Iterator<Type>;
using const_iterator = Iterator<const Type>;
protected:
static
const size_type p_mrows = Rows - 1;
static
const size_type p_mcols = Cols - 1;
size_type p_rows;
size_type p_cols;
public:
inline
MatrixSpace() :
base {},
p_rows {Rows},
p_cols {Cols}
{}
inline
MatrixSpace(const MatrixSpace& ms) :
base {static_cast<base>(ms)},
p_rows {Rows},
p_cols {Cols}
{}
inline
MatrixSpace(const base& ms) :
base {ms},
p_rows {Rows},
p_cols {Cols}
{}
inline
MatrixSpace(MatrixSpace&& ms) noexcept :
base {std::move(static_cast<base>(ms))},
p_rows {Rows},
p_cols {Cols}
{}
inline
MatrixSpace(typename base::iterator start, typename base::iterator end) :
base {start, end},
p_rows {Rows},
p_cols {Cols}
{}
inline
MatrixSpace(typename base::const_iterator start, typename base::const_iterator end) :
base {start, end},
p_rows {Rows},
p_cols {Cols}
{}
inline
MatrixSpace(std::initializer_list<value_type> list) :
base {list},
p_rows {Rows},
p_cols {Cols}
{}
template <std::convertible_to<value_type>... Args>
inline
MatrixSpace(value_type&& v, Args&& ...args) :
base {v, static_cast<value_type>(std::forward<Args>(args))...},
p_rows {Rows},
p_cols {Cols}
{
static_assert(1 + sizeof...(args) == Rows * Cols, "Number of arguments must be equal to rows * cols of matrix");
}
// Member functions
inline
reference operator()(size_type row, size_type col)
{
if (row >= p_rows || std::numeric_limits<size_type>::max() - p_rows < row)
throw std::out_of_range("Row index is out of range");
if (col >= p_cols || std::numeric_limits<size_type>::max() - p_cols < col)
throw std::out_of_range("Column index is out of range");
return (*this)[col + p_rows * row];
}
VectorSpace<value_type, Cols> row(size_type row)
{
VectorSpace<value_type, Cols> vs;
for (auto n = 0; n < Cols; ++n)
vs[n] = (*this)(row, n);
return vs;
}
void row(size_type row, const VectorSpace<value_type, Cols>& vs)
{
for (auto n = 0; n < Cols; ++n)
(*this)(n, row) = vs[n];
}
VectorSpace<value_type, Rows> col(size_type col)
{
VectorSpace<value_type, Rows> vs;
for (auto n = 0; n < Rows; ++n)
vs[n] = (*this)(n, col);
return vs;
}
void col(size_type col, const VectorSpace<value_type, Rows>& vs)
{
for (auto n = 0; n < Rows; ++n)
(*this)(n, col) = vs[n];
}
size_type rows() const { return p_rows; }
size_type cols() const { return p_cols; }
[[nodiscard]]
inline
bool is_square() const
{
return p_rows == p_cols;
}
inline
Minor minor(size_type row, size_type col)
{
if (this->size() < 4)
throw std::runtime_error("Impossible to find minor for matrix with size less than 2x2");
Minor minor;
auto minor_iter = minor.begin();
for (auto n = 0; n < Rows; ++n)
for (auto k = 0; k < Cols; ++k)
if (k != col && n != row)
*(minor_iter++) = (*this)[k + p_rows * n];
return minor;
}
inline
value_type det()
{
if (!is_square())
throw std::runtime_error("Matrix must be square");
if (this->size() == 1)
return (*this)[0];
else if (this->size() == 4)
return (*this)(0, 0) * (*this)(1, 1) - (*this)(0, 1) * (*this)(1, 0);
else {
auto res = 0;
for (auto m = 0; m < Cols; ++m)
res += pow(-1, m) * (*this)(0, m) * minor(0, m).det();
return res;
}
}
inline
MatrixSpace transpose()
{
MatrixSpace ms;
for (auto n = 0; n < Rows; ++n)
for (auto k = 0; k < Cols; ++k)
ms(k, n) = (*this)(n, k);
return ms;
}
inline
MatrixSpace adj()
{
MatrixSpace ms;
for (auto n = 0; n < Rows; ++n)
for (auto k = 0; k < Cols; ++k)
{
ms(n, k) = pow(-1, n + k) * minor(n, k).det();
}
return ms.transpose();
}
inline
MatrixSpace inv()
{
return adj() / det();
}
// Friend functions
friend inline
bool operator==(const MatrixSpace& lhs, const MatrixSpace& rhs)
{
for (auto n = 0; n < lhs.size(); ++n)
if (lhs[n] != rhs[n])
return false;
return true;
}
friend inline
bool operator!=(const MatrixSpace& lhs, const MatrixSpace& rhs)
{
return !(lhs == rhs);
}
template <typename T, size_type S>
friend inline
bool operator==(const MatrixSpace& lhs, const VectorSpace<T, S>& rhs)
{
return false;
}
MatrixSpace& fill(value_type value)
{
for (auto n = 0; n < this->size(); ++n)
(*this)[n] = value;
return *this;
}
// Global functions
static inline
MatrixSpace identity()
{
MatrixSpace ms;
for (auto n = 0; n < Rows; ++n)
for (auto k = 0; k < Cols; ++k)
ms(n, k) = 1;
return ms;
}
};
}

View File

@ -0,0 +1,79 @@
#pragma once
#include "matrix.hpp"
namespace hpr
{
template <typename Type>
inline
mat<Type, 4, 4> translate(const mat<Type, 4, 4>& ms, const vec<Type, 3>& vs)
{
mat<Type, 4, 4> res {ms};
res.row(3, ms.row(0) * vs[0] + ms.row(1) * vs[1] + ms.row(2) * vs[2] + ms.row(3));
return res;
}
template <typename Type>
inline
mat<Type, 4, 4> rotate(const mat<Type, 4, 4>& ms, const vec<Type, 3>& vs, Type angle)
{
const Type cos {cos(angle)};
const Type sin {sin(angle)};
vec<Type, 3> axis {normalize(vs)};
vec<Type, 3> temp {(1. - cos) * axis};
mat<Type, 4, 4> rot;
rot(0, 0) = cos + temp[0] * axis[0];
rot(0, 1) = temp[0] * axis[1] + sin * axis[2];
rot(0, 2) = temp[0] * axis[2] - sin * axis[1];
rot(1, 0) = temp[1] * axis[0] - sin * axis[2];
rot(1, 1) = cos + temp[1] * axis[1];
rot(1, 2) = temp[1] * axis[2] + sin * axis[0];
rot(2, 0) = temp[2] * axis[0] + sin * axis[1];
rot(2, 1) = temp[2] * axis[1] - sin * axis[0];
rot(2, 2) = cos + temp[2] * axis[2];
mat<Type, 4, 4> res {ms};
res.row(0, ms.row(0) * rot(0, 0) + ms.row(1) * rot(0, 1) + ms.row(2) * rot(0, 2));
res.row(0, ms.row(0) * rot(1, 0) + ms.row(1) * rot(1, 1) + ms.row(2) * rot(1, 2));
res.row(0, ms.row(0) * rot(2, 0) + ms.row(1) * rot(2, 1) + ms.row(2) * rot(2, 2));
res.row(3, ms.row(3));
return res;
}
template <typename Type>
inline
mat<Type, 4, 4> scale(const mat<Type, 4, 4>& ms, const vec<Type, 3>& vs)
{
mat<Type, 4, 4> res;
res.row(0, ms.row(0) * vs[0]);
res.row(1, ms.row(1) * vs[1]);
res.row(2, ms.row(2) * vs[2]);
res.row(3, ms.row(3));
return res;
}
template <typename Type>
inline
mat<Type, 4, 4> lookAt(const mat<Type, 4, 4>& ms, const vec<Type, 3>& eye, const vec<Type, 3>& center, const vec<Type, 3>& up)
{
const vec<Type, 3> forward {normalize(center - eye)};
const vec<Type, 3> left {normalize(cross(up, forward))};
const vec<Type, 3> nup {cross(forward, left)};
mat<Type, 4, 4> res;
res.col(0, vec<Type, 4>(left, 0));
res.col(1, vec<Type, 4>(nup, 0));
res.col(2, vec<Type, 4>(forward, 0));
res.row(3, -vec<Type, 4>(dot(left, eye), dot(nup, eye), dot(forward, eye), -1.));
return res;
}
}

View File

@ -1,3 +0,0 @@
#include "scalar.hpp"

View File

@ -4,7 +4,7 @@
#include <limits>
namespace hyporo
namespace hpr
{
#if defined(PRECISION_FLOAT)
@ -26,7 +26,7 @@ using scalar = float;
#endif
static const scalar small = std::numeric_limits<scalar>::epsilon();
static const scalar great = 1.0 / small;
static const scalar great = static_cast<scalar>(1.0) / small;
static const scalar valueSmall = std::numeric_limits<scalar>::min();
static const scalar valueGreat = std::numeric_limits<scalar>::max() * 0.1;
static const scalar NaN = std::numeric_limits<scalar>::signaling_NaN();
@ -43,5 +43,23 @@ inline scalar mag(const scalar s)
return std::fabs(s);
}
// trigonometric
} // end namespace hyporo
static const scalar PI = static_cast<scalar>(M_PIl);
template <typename Type>
constexpr
Type radians(Type degrees)
{
static_assert(std::numeric_limits<Type>::is_iec559);
return degrees * PI / static_cast<Type>(180);
}
template <typename Type>
constexpr
Type degrees(Type radians)
{
static_assert(std::numeric_limits<Type>::is_iec559);
return radians * static_cast<Type>(180) / PI;
}
}

View File

@ -1,20 +1,79 @@
#include <gtest/gtest.h>
#include "array.hpp"
#include "vector.hpp"
#include "matrix.hpp"
TEST(hyplibTest, VectorCreation)
TEST(hyplib, Array)
{
hyporo::vec3 v {1, 3, 2};
EXPECT_EQ(v[0], 1);
EXPECT_EQ(v[1], 3);
EXPECT_EQ(v[2], 2);
hpr::StaticArray<float, 3> arr {1, 3, 2};
hpr::StaticArray<float, 4> sarr {arr, 5};
hpr::StaticArray<float, 4> sarr2 {1, 3, 2, 5};
EXPECT_EQ(sarr, sarr2);
}
TEST(hyplibTest, VectorOperations)
TEST(hyplib, Vector)
{
using hyporo::vec3;
vec3 v1 {1, 3, 2};
vec3 v2 {5, 7, -1};
EXPECT_EQ(-v1, vec3(-1, -3, -2));
EXPECT_EQ(v1 + v2, vec3(6, 10, 1));
EXPECT_EQ(v1 - v2, vec3(-4, -4, 3));
hpr::vec3 v1 {1, 3, 2};
hpr::vec3 v2 {5, 7, -1};
hpr::vec2 v31 {13, -2};
hpr::vec3 v32 {v31, 9};
EXPECT_EQ((hpr::vec3(v2.begin(), v2.end())), v2);
EXPECT_EQ(v32, hpr::vec3(13, -2, 9));
EXPECT_EQ(-v1, hpr::vec3(-1, -3, -2));
EXPECT_EQ(v1 + v2, hpr::vec3(6, 10, 1));
EXPECT_EQ(v1 - v2, hpr::vec3(-4, -4, 3));
EXPECT_EQ((hpr::dot(v1, v2) ), 24);
}
TEST(hyplib, Matrix)
{
hpr::mat2 m1;
hpr::vec4 v1;
EXPECT_FALSE(v1 == m1);
hpr::mat2 m2 {3, 2, 7, 4};
hpr::vec2 v2 {2, 4};
EXPECT_EQ(m2.col(1), v2);
hpr::vec2 v3 {13, 51};
m2.col(1, v3);
EXPECT_EQ(m2.col(1), v3);
hpr::mat3 m4 {1, 2, 3, 4, 5, 6, 7, 8, 9};
hpr::mat2 m41 {5, 6, 8, 9};
EXPECT_EQ(m41.minor(0, 0), 9);
hpr::mat2 m5 {1, 2, 3, 4};
EXPECT_EQ((m4.det()), 0);
EXPECT_EQ(hpr::mat3(-9, 23, 3, 5, 5, 6, 7, -3, 9).det(), -786);
hpr::mat2 m6 {2, 1, 7, 4};
EXPECT_EQ(m6.inv(), hpr::mat2(4, -1, -7, 2));
//EXPECT_EQ(m4.det(), 0);
}
/*using Minor = typename std::conditional<(Rows > 2 && Cols > 2),
MatrixSpace<Type, Rows - 1, Cols - 1>, MatrixSpace<Type, 1, 1>>::type;
value_type det()
{
if (!is_square())
throw std::runtime_error("Matrix must be square");
if (this->size() == 1)
return (*this)[0];
else if (this->size() == 4)
return (*this)(0, 0) * (*this)(1, 1) - (*this)(0, 1) * (*this)(1, 0);
else {
auto res = 0;
for (auto m = 0; m < Cols; ++m) {
Minor minor;
auto minor_iter = minor.begin();
for (auto n = 0; n < Rows; ++n)
for (auto k = 0; k < Cols; ++k)
if (k != 0 && n != m)
*(minor_iter++) = (*this)[k + p_rows * n];
res += pow(-1, m) * (*this)(0, m) * minor.det();
}
return res;
}
}
*/

View File

@ -1,66 +0,0 @@
#pragma once
/** \file
* \ingroup hyplib
**/
#include "integer.hpp"
#include "scalar.hpp"
#include <array>
#include <ostream>
namespace hyporo
{
// Forward declaration of friend functions and operators
template <class C, sizet NC> class VectorSpace;
template <class C, sizet NC>
std::ostream& operator<<(std::ostream&, const VectorSpace<C, NC>&);
// Class declaration
template <class C, sizet NC>
class VectorSpace
{
public:
//- The components of this vector space
std::array<C, NC> row;
// Static constants
static const sizet nComponents = NC;
// Constructors
inline VectorSpace();
//inline VectorSpace(const VectorSpace<C, NC>&);
template <class... Args>
inline VectorSpace(const Args... components);
// Member functions
inline static sizet size();
// Member operators
inline C& operator[](const sizet);
inline VectorSpace<C, NC>& operator*=(const scalar);
inline VectorSpace<C, NC>& operator/=(const scalar);
// Friend operators
friend std::ostream& operator<< <C, NC>(std::ostream&, const VectorSpace<C, NC>&);
};
} // end namespace hyporo
#include "VectorSpace.hxx"

View File

@ -1,143 +0,0 @@
#include <algorithm>
namespace hyporo
{
// Constructors
template <class C, sizet NC>
inline VectorSpace<C, NC>::VectorSpace()
{}
template <class C, sizet NC>
template <class... Args>
inline VectorSpace<C, NC>::VectorSpace(const Args... components)
: row { static_cast<C>(components)... }
{}
// Member functions
template <class C, sizet NC>
inline sizet VectorSpace<C, NC>::size()
{
return NC;
}
// Member operators
template <class C, sizet NC>
inline C& VectorSpace<C, NC>::operator[](const sizet n)
{
return row[n];
}
template <class C, sizet NC>
inline VectorSpace<C, NC>& VectorSpace<C, NC>::operator*=(const scalar s)
{
for (C& v : row)
v *= s;
return *this;
}
template <class C, sizet NC>
inline VectorSpace<C, NC>& VectorSpace<C, NC>::operator/=(const scalar s)
{
for (C& v : row)
v /= s;
return *this;
}
// Friend operators
template <class C, sizet NC>
std::ostream& operator<<(std::ostream& os, const VectorSpace<C, NC>& vs)
{
os << "(";
for (sizet n = 0; n < NC; n++)
{
os << vs.row[n];
if (n != NC - 1)
os << ", ";
}
os << ")";
return os;
}
// Global operators
template <class C, sizet NC>
inline VectorSpace<C, NC> operator-(const VectorSpace<C, NC>& vs)
{
VectorSpace<C, NC> nvs;
for (sizet n = 0; n < NC; n++)
nvs.row[n] = -vs.row[n];
return nvs;
}
template <class C, sizet NC>
inline VectorSpace<C, NC> operator+(const VectorSpace<C, NC>& vs1, const VectorSpace<C, NC>& vs2)
{
VectorSpace<C, NC> nvs;
for (sizet n = 0; n < NC; n++)
nvs.row[n] = vs1.row[n] + vs2.row[n];
return nvs;
}
template <class C, sizet NC>
inline VectorSpace<C, NC> operator-(const VectorSpace<C, NC>& vs1, const VectorSpace<C, NC>& vs2)
{
VectorSpace<C, NC> nvs;
for (sizet n = 0; n < NC; n++)
nvs.row[n] = vs1.row[n] - vs2.row[n];
return nvs;
}
template <class C, sizet NC>
inline VectorSpace<C, NC> operator*(const scalar& s, const VectorSpace<C, NC>& vs)
{
VectorSpace<C, NC> nvs;
for (sizet n = 0; n < NC; n++)
nvs.row[n] = s * vs.row[n];
return nvs;
}
template <class C, sizet NC>
inline VectorSpace<C, NC> operator*(const VectorSpace<C, NC>& vs, const scalar& s)
{
VectorSpace<C, NC> nvs;
for (sizet n = 0; n < NC; n++)
nvs.row[n] = vs.row[n] * s;
return nvs;
}
template <class C, sizet NC>
inline VectorSpace<C, NC> operator/(const VectorSpace<C, NC>& vs, const scalar& s)
{
VectorSpace<C, NC> nvs;
for (sizet n = 0; n < NC; n++)
nvs.row[n] = vs.row[n] / s;
return nvs;
}
template <class C, sizet NC>
inline bool operator==(const VectorSpace<C, NC>& vs1, const VectorSpace<C, NC>& vs2)
{
bool eq = true;
for (sizet n = 0; n < NC; n++)
if (!(eq &= (vs1.row[n] == vs2.row[n])))
break;
return eq;
}
template <class C, sizet NC>
inline bool operator!=(const VectorSpace<C, NC>& vs1, const VectorSpace<C, NC>& vs2)
{
return !(vs1 == vs2);
}
} // end namespace hyporo

View File

@ -1,16 +1,17 @@
#pragma once
#include "scalar.hpp"
#include "VectorSpace.hpp"
#include "vector_space.hpp"
namespace hyporo
namespace hpr
{
template <typename Type, size_t Size>
using vec = VectorSpace<Type, Size>;
using vec2 = VectorSpace<scalar, 2>;
using vec3 = VectorSpace<scalar, 3>;
using vec4 = VectorSpace<scalar, 4>;
} // end namespace hyporo
}

View File

@ -0,0 +1,4 @@
//
// Created by L-Nafaryus on 10/17/2022.
//
#include "vector_space.hpp"

View File

@ -0,0 +1,332 @@
#pragma once
#include "../array/array.hpp"
namespace hpr
{
template <typename Type, size_t Size>
class VectorSpace : public StaticArray<Type, Size>
{
static_assert(std::is_arithmetic<Type>::value, "Type must be numeric");
using base = StaticArray<Type, Size>;
using SubVector = typename std::conditional<Size >= 2, VectorSpace<Type, Size - 1>, VectorSpace<Type, 1>>::type;
public:
using value_type = Type;
using size_type = size_t;
using pointer = Type*;
using reference = Type&;
using iterator = Iterator<Type>;
using const_iterator = Iterator<const Type>;
public:
inline
VectorSpace() :
base {}
{}
inline
VectorSpace(const VectorSpace& vs) :
base {static_cast<base>(vs)}
{}
inline
VectorSpace(VectorSpace&& vs) noexcept :
base {std::move(static_cast<base>(vs))}
{}
inline
VectorSpace(typename base::iterator start, typename base::iterator end) :
base {start, end}
{}
inline
VectorSpace(typename base::const_iterator start, typename base::const_iterator end) :
base {start, end}
{}
inline
VectorSpace(std::initializer_list<value_type> list) :
base {list}
{}
template <std::convertible_to<value_type>... Args>
inline
VectorSpace(value_type&& v, Args&& ...args) :
base {v, static_cast<value_type>(std::forward<Args>(args))...}
{
static_assert(1 + sizeof...(args) == Size, "Number of arguments must be equal to size of vector");
}
/*template <size_type SubSize, std::convertible_to<value_type>... Args>
inline
VectorSpace(const VectorSpace<value_type, SubSize>& subvec, const value_type& v, const Args& ...args) :
base {static_cast<StaticArray<value_type, SubSize>>(subvec), v,
static_cast<value_type>(std::forward<Args>(args))...}
{}*/
inline
VectorSpace(const SubVector& subvs, const value_type& v) :
base {}
{
for (auto n = 0; n < subvs.size(); ++n)
(*this)[n] = subvs[n];
(*this)[subvs.size() - 1] = v;
}
// Member functions
// vector versus scalar (per element operations)
friend inline
VectorSpace operator-(const VectorSpace& rhs)
{
VectorSpace vs {rhs};
for (value_type& v : vs)
v = -v;
return vs;
}
inline
void operator*=(const value_type& val)
{
//for (value_type& v : *this)
// v *= val;
for (auto n = 0; n < Size; ++n)
(*this)[n] *= val;
}
inline
void operator+=(const value_type& val)
{
for (auto n = 0; n < Size; ++n)
(*this)[n] += val;
}
inline
void operator-=(const value_type& val)
{
//for (value_type& v : *this)
// v -= val;
for (auto n = 0; n < Size; ++n)
(*this)[n] -= val;
}
inline
void operator/=(const value_type& val)
{
for (value_type& v : *this)
v /= val;
}
using type = VectorSpace<Type, Size>;
friend inline
type operator+(const VectorSpace& lhs, const value_type& rhs)
{
VectorSpace vs {lhs};
vs += rhs;
return vs;
}
friend inline
VectorSpace operator+(const value_type& lhs, const VectorSpace& rhs)
{
return operator+(rhs, lhs);
}
friend inline
VectorSpace operator*(const VectorSpace& lhs, const value_type& rhs)
{
VectorSpace vs {lhs};
vs *= rhs;
return vs;
}
friend inline
VectorSpace operator*(const value_type& lhs, const VectorSpace& rhs)
{
return operator*(rhs, lhs);
}
friend inline
VectorSpace operator/(const VectorSpace& lhs, const value_type& rhs)
{
VectorSpace vs {lhs};
vs /= rhs;
return vs;
}
friend inline
VectorSpace operator/(const value_type& lhs, const VectorSpace& rhs)
{
VectorSpace vs;
for (auto n = 0; n < vs.size(); ++n)
vs[n] = lhs / rhs[n];
return vs;
}
// vector versus vector (per element operations)
inline
void operator*=(const VectorSpace& vs)
{
for (auto n = 0; n < Size; ++n)
(*this)[n] *= vs[n];
}
inline
void operator+=(const VectorSpace& vs)
{
for (auto n = 0; n < Size; ++n)
(*this)[n] += vs[n];
}
inline
void operator-=(const VectorSpace& vs)
{
for (auto n = 0; n < Size; ++n)
(*this)[n] -= vs[n];
}
inline
void operator/=(const VectorSpace& vs)
{
for (auto n = 0; n < Size; ++n)
(*this)[n] /= vs[n];
}
friend inline
VectorSpace operator+(const VectorSpace& lhs, const VectorSpace& rhs)
{
VectorSpace vs {lhs};
vs += rhs;
return vs;
}
friend inline
VectorSpace operator-(const VectorSpace& lhs, const VectorSpace& rhs)
{
VectorSpace vs {lhs};
vs -= rhs;
return vs;
}
friend inline
VectorSpace operator*(const VectorSpace& lhs, const VectorSpace& rhs)
{
VectorSpace vs {lhs};
vs *= rhs;
return vs;
}
friend inline
VectorSpace operator/(const VectorSpace& lhs, const VectorSpace& rhs)
{
VectorSpace vs {lhs};
vs /= rhs;
return vs;
}
friend inline
bool operator==(const VectorSpace& lhs, const VectorSpace& rhs)
{
for (auto n = 0; n < Size; ++n)
if (lhs[n] != rhs[n])
return false;
return true;
}
friend inline
bool operator!=(const VectorSpace& lhs, const VectorSpace& rhs)
{
return !(lhs == rhs);
}
};
template <typename Type, size_t Size>
inline
Type sum(const VectorSpace<Type, Size>& vs)
{
Type sum {0};
for (const Type& v : vs)
sum += v;
return sum;
}
template <typename Type, size_t Size>
constexpr
Type dot(const VectorSpace<Type, Size>& lhs, const VectorSpace<Type, Size>& rhs)
{
return sum(lhs * rhs);
}
template <typename Type, size_t Size>
inline
Type length(const VectorSpace<Type, Size>& vs)
{
return sqrt(dot(vs, vs));
}
template <typename Type, size_t Size>
inline
Type distance(const VectorSpace<Type, Size>& point1, const VectorSpace<Type, Size>& point2)
{
return length(point1 - point2);
}
template <typename Type>
constexpr
VectorSpace<Type, 3> cross(const VectorSpace<Type, 3>& lhs, const VectorSpace<Type, 3>& rhs)
{
return VectorSpace<Type, 3>(
lhs[2] * rhs[3] - lhs[3] * rhs[2],
lhs[3] * rhs[1] - lhs[1] * rhs[3],
lhs[1] * rhs[2] - lhs[2] * rhs[1]
);
}
template <typename Type, size_t Size>
inline
VectorSpace<Type, Size> normalize(const VectorSpace<Type, Size>& vs)
{
return vs * inversesqrt(dot(vs, vs));
}
template <typename Type, size_t Size>
constexpr
VectorSpace<bool, Size> equal(const VectorSpace<Type, Size>& lhs, const VectorSpace<Type, Size>& rhs)
{
VectorSpace<bool, Size> vs;
for (auto n = 0; n < Size; ++n)
vs[n] = lhs[n] == rhs[n];
return vs;
}
template <size_t Size>
constexpr
bool any(const VectorSpace<bool, Size>& vs)
{
bool res = false;
for (auto e : vs)
res = res || e;
return res;
}
template <size_t Size>
constexpr
bool all(const VectorSpace<bool, Size>& vs)
{
bool res = true;
for (auto e : vs)
res = res && e;
return res;
}
}