windows, monitors and provider
This commit is contained in:
parent
7a264e5680
commit
38c644ffdf
@ -28,7 +28,8 @@ public:
|
||||
|
||||
Context(DeviceAPI api);
|
||||
|
||||
virtual ~Context();
|
||||
virtual
|
||||
~Context();
|
||||
|
||||
// Member functions
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
5
source/hyporo/gpu/glfw/monitor.cpp
Normal file
5
source/hyporo/gpu/glfw/monitor.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by L-Nafaryus on 10/27/2022.
|
||||
//
|
||||
|
||||
#include "monitor.hpp"
|
14
source/hyporo/gpu/glfw/monitor.hpp
Normal file
14
source/hyporo/gpu/glfw/monitor.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "../monitor.hpp"
|
||||
|
||||
|
||||
namespace hpr::gpu::glfw
|
||||
{
|
||||
|
||||
class Monitor : public gpu::Monitor
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
}
|
5
source/hyporo/gpu/glfw/window.cpp
Normal file
5
source/hyporo/gpu/glfw/window.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by L-Nafaryus on 10/27/2022.
|
||||
//
|
||||
|
||||
#include "window.hpp"
|
8
source/hyporo/gpu/glfw/window.hpp
Normal file
8
source/hyporo/gpu/glfw/window.hpp
Normal 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
|
5
source/hyporo/gpu/glfw/window_system.cpp
Normal file
5
source/hyporo/gpu/glfw/window_system.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by L-Nafaryus on 10/27/2022.
|
||||
//
|
||||
|
||||
#include "window_system.hpp"
|
28
source/hyporo/gpu/glfw/window_system.hpp
Normal file
28
source/hyporo/gpu/glfw/window_system.hpp
Normal 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);
|
||||
};
|
||||
|
||||
}
|
44
source/hyporo/gpu/monitor.cpp
Normal file
44
source/hyporo/gpu/monitor.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
82
source/hyporo/gpu/monitor.hpp
Normal file
82
source/hyporo/gpu/monitor.hpp
Normal 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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -19,7 +19,7 @@ public:
|
||||
|
||||
Device();
|
||||
|
||||
~Device();
|
||||
~Device() override;
|
||||
|
||||
|
||||
// Member functions
|
||||
|
@ -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:
|
||||
|
103
source/hyporo/gpu/window.cpp
Normal file
103
source/hyporo/gpu/window.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
97
source/hyporo/gpu/window.hpp
Normal file
97
source/hyporo/gpu/window.hpp
Normal 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);
|
||||
|
||||
};
|
||||
|
||||
}
|
39
source/hyporo/gpu/window_context.hpp
Normal file
39
source/hyporo/gpu/window_context.hpp
Normal 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;
|
||||
|
||||
};
|
||||
|
||||
}
|
63
source/hyporo/gpu/window_system.cpp
Normal file
63
source/hyporo/gpu/window_system.cpp
Normal 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);
|
||||
}
|
||||
}
|
62
source/hyporo/gpu/window_system.hpp
Normal file
62
source/hyporo/gpu/window_system.hpp
Normal 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);
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
namespace hyporo
|
||||
{
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
using sizet = std::size_t;
|
||||
|
||||
} // end namespace hyporo
|
@ -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"
|
@ -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
|
54
source/hyporo/hyplib/matrix/clip_space.hpp
Normal file
54
source/hyporo/hyplib/matrix/clip_space.hpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
|
249
source/hyporo/hyplib/matrix/matrix_space.hpp
Normal file
249
source/hyporo/hyplib/matrix/matrix_space.hpp
Normal 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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
79
source/hyporo/hyplib/matrix/transform.hpp
Normal file
79
source/hyporo/hyplib/matrix/transform.hpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
#include "scalar.hpp"
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
*/
|
@ -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"
|
@ -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
|
@ -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
|
||||
}
|
||||
|
4
source/hyporo/hyplib/vector/vector_space.cpp
Normal file
4
source/hyporo/hyplib/vector/vector_space.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
//
|
||||
// Created by L-Nafaryus on 10/17/2022.
|
||||
//
|
||||
#include "vector_space.hpp"
|
332
source/hyporo/hyplib/vector/vector_space.hpp
Normal file
332
source/hyporo/hyplib/vector/vector_space.hpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user