Rendering with matricies
Started to use matricies to handle transformations and the camera Added Vector3 and Matrix3x3 classes and improved Vector2
This commit is contained in:
parent
30e4f41138
commit
0913c7b05e
6 changed files with 379 additions and 10 deletions
|
@ -5,6 +5,8 @@
|
|||
#include "tiles/dirt.h"
|
||||
#include "tiles/grass.h"
|
||||
#include "util/vector2.h"
|
||||
#include "util/vector3.h"
|
||||
#include "util/matrix3x3.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
|
147
src/util/matrix3x3.h
Normal file
147
src/util/matrix3x3.h
Normal file
|
@ -0,0 +1,147 @@
|
|||
#pragma once
|
||||
|
||||
#include "vector3.h"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
template <typename T>
|
||||
class Matrix3x3 {
|
||||
public:
|
||||
Matrix3x3() = default;
|
||||
Matrix3x3(T s) : m_rows{
|
||||
{s, static_cast<T>(0), static_cast<T>(0)},
|
||||
{static_cast<T>(0), s, static_cast<T>(0)},
|
||||
{static_cast<T>(0), static_cast<T>(0), s}
|
||||
} {}
|
||||
Matrix3x3(Vector3<T> r1, Vector3<T> r2, Vector3<T> r3) : m_rows{r1, r2, r3} {}
|
||||
Matrix3x3(const Matrix3x3<T> &other) = default;
|
||||
|
||||
Matrix3x3<T> operator-() const { return Matrix3x3<T>(-m_rows[0], -m_rows[1], -m_rows[2]); }
|
||||
|
||||
Matrix3x3<T> &operator=(const Matrix3x3<T> &other) {
|
||||
m_rows[0] = other.m_rows[0];
|
||||
m_rows[1] = other.m_rows[1];
|
||||
m_rows[2] = other.m_rows[2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix3x3<T> operator+(const Matrix3x3<T> &other) const {
|
||||
return Matrix3x3(
|
||||
m_rows[0] + other.m_rows[0],
|
||||
m_rows[1] + other.m_rows[1],
|
||||
m_rows[2] + other.m_rows[2]
|
||||
);
|
||||
}
|
||||
Matrix3x3<T> &operator+=(const Matrix3x3<T> &other) {
|
||||
m_rows[0] += other.m_rows[0];
|
||||
m_rows[1] += other.m_rows[1];
|
||||
m_rows[2] += other.m_rows[2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix3x3<T> operator-(const Matrix3x3<T> &other) const {
|
||||
return Matrix3x3(
|
||||
m_rows[0] - other.m_rows[0],
|
||||
m_rows[1] - other.m_rows[1],
|
||||
m_rows[2] - other.m_rows[2]
|
||||
);
|
||||
}
|
||||
Matrix3x3<T> &operator-=(const Matrix3x3<T> &other) {
|
||||
m_rows[0] -= other.m_rows[0];
|
||||
m_rows[1] -= other.m_rows[1];
|
||||
m_rows[2] -= other.m_rows[2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix3x3<T> &operator*=(const Matrix3x3<T> &other) {
|
||||
return (*this = *this * other);
|
||||
}
|
||||
Matrix3x3<T> operator*(const T &s) const {
|
||||
return Matrix3x3(
|
||||
m_rows[0] * s,
|
||||
m_rows[1] * s,
|
||||
m_rows[2] * s
|
||||
);
|
||||
}
|
||||
Matrix3x3<T> &operator*=(const T &s) {
|
||||
return (*this = *this * s);
|
||||
}
|
||||
|
||||
/*
|
||||
Matrix3x3<T> operator/(const Matrix3x3<T> &other) const { return Matrix3x3(m_x / other.m_x, m_y / other.m_y, m_z / other.m_z); }
|
||||
Matrix3x3<T> &operator/=(const Matrix3x3<T> &other) { m_x /= other.m_x; m_y /= other.m_y; m_z /= other.m_z; return *this; }
|
||||
Matrix3x3<T> operator/(const T &s) const { return Matrix3x3(m_x / s, m_y / s, m_z / s); }
|
||||
Matrix3x3<T> &operator/=(const T &s) { m_x /= s; m_y /= s; m_z /= s; return *this; }
|
||||
*/
|
||||
|
||||
Vector3<T> &operator[](const int idx) { return m_rows[idx]; }
|
||||
const Vector3<T> &operator[](const int idx) const { return m_rows[idx]; }
|
||||
|
||||
T &operator()(const int x, const int y) { return m_rows[y][x]; }
|
||||
const T &operator()(const int x, const int y) const { return m_rows[y][x]; }
|
||||
|
||||
bool operator==(const Matrix3x3<T> &other) const {
|
||||
return m_rows[0] == other.m_rows[0] &&
|
||||
m_rows[1] == other.m_rows[1] &&
|
||||
m_rows[2] == other.m_rows[2];
|
||||
}
|
||||
bool operator!=(const Matrix3x3<T> &other) const {
|
||||
return m_rows[0] == other.m_rows[0] ||
|
||||
m_rows[1] != other.m_rows[1] ||
|
||||
m_rows[2] != other.m_rows[2];
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Matrix3x3<T> &m) {
|
||||
os << "Matrix3x3(\n\t" << m[0] << "\n\t" << m[1] << "\n\t" << m[2] << "\n)";
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
Vector3<T> m_rows[3];
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Matrix3x3<T> operator*(const Matrix3x3<T> &m1, const Matrix3x3<T> &m2) {
|
||||
Matrix3x3<T> result(
|
||||
{
|
||||
m1(0, 0) * m2(0, 0) + m1(1, 0) * m2(0, 1) + m1(2, 0) * m2(0, 2),
|
||||
m1(0, 0) * m2(1, 0) + m1(1, 0) * m2(1, 1) + m1(2, 0) * m2(1, 2),
|
||||
m1(0, 0) * m2(2, 0) + m1(1, 0) * m2(2, 1) + m1(2, 0) * m2(2, 2)
|
||||
|
||||
},
|
||||
{
|
||||
m1(0, 1) * m2(0, 0) + m1(1, 1) * m2(0, 1) + m1(2, 1) * m2(0, 2),
|
||||
m1(0, 1) * m2(1, 0) + m1(1, 1) * m2(1, 1) + m1(2, 1) * m2(1, 2),
|
||||
m1(0, 1) * m2(2, 0) + m1(1, 1) * m2(2, 1) + m1(2, 1) * m2(2, 2)
|
||||
},
|
||||
{
|
||||
m1(0, 2) * m2(0, 0) + m1(1, 2) * m2(0, 1) + m1(2, 2) * m2(0, 2),
|
||||
m1(0, 2) * m2(1, 0) + m1(1, 2) * m2(1, 1) + m1(2, 2) * m2(1, 2),
|
||||
m1(0, 2) * m2(2, 0) + m1(1, 2) * m2(2, 1) + m1(2, 2) * m2(2, 2)
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Vector3<T> operator*(const Matrix3x3<T> &m, const Vector3<T> &v) {
|
||||
Vector3<T> result({
|
||||
m(0, 0) * v[0] + m(1, 0) * v[1] + m(2, 0) * v[2],
|
||||
m(0, 1) * v[0] + m(1, 1) * v[1] + m(2, 1) * v[2],
|
||||
m(0, 2) * v[0] + m(1, 2) * v[1] + m(2, 2) * v[2]
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Vector3<T> operator*(const Vector3<T> &v, const Matrix3x3<T> &m) {
|
||||
Vector3<T> result({
|
||||
m(0, 0) * v[0] + m(0, 1) * v[1] + m(0, 2) * v[2],
|
||||
m(1, 0) * v[0] + m(1, 1) * v[1] + m(1, 2) * v[2],
|
||||
m(2, 0) * v[0] + m(2, 1) * v[1] + m(2, 2) * v[2]
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1,22 +1,93 @@
|
|||
#include "util/render.h"
|
||||
|
||||
void Render::rectangle(Vector2<int> start, Vector2<int> end, Color color) {
|
||||
auto origin = start + m_camera_pos;
|
||||
m_pge->DrawRect(origin.x(), origin.y(), end.x() - start.x(), end.y() - start.y(), olc::Pixel(color.r(), color.g(), color.b()));
|
||||
auto screen_start = m_matrix * m_view_matrix * Vector3<float>(start, 1);
|
||||
auto screen_end = m_matrix * m_view_matrix * Vector3<float>(end, 1);
|
||||
m_pge->DrawRect(
|
||||
screen_start.x(),
|
||||
screen_start.y(),
|
||||
screen_end.x() - screen_start.x(),
|
||||
screen_end.y() - screen_start.y(),
|
||||
olc::Pixel(color.r(), color.g(), color.b())
|
||||
);
|
||||
}
|
||||
|
||||
void Render::rectangle_sz(Vector2<int> start, Vector2<int> size, Color color) {
|
||||
auto origin = start + m_camera_pos;
|
||||
m_pge->DrawRect(origin.x(), origin.y(), size.x(), size.y(), olc::Pixel(color.r(), color.g(), color.b()));
|
||||
auto screen_start = m_matrix * m_view_matrix * Vector3<float>(start, 1);
|
||||
m_pge->DrawRect(
|
||||
screen_start.x(),
|
||||
screen_start.y(),
|
||||
size.x(),
|
||||
size.y(),
|
||||
olc::Pixel(color.r(), color.g(), color.b())
|
||||
);
|
||||
}
|
||||
|
||||
void Render::fill_rectangle(Vector2<int> start, Vector2<int> end, Color color) {
|
||||
auto origin = start + m_camera_pos;
|
||||
m_pge->FillRect(origin.x(), origin.y(), end.x() - start.x() + 1, end.y() - start.y() + 1, olc::Pixel(color.r(), color.g(), color.b()));
|
||||
auto screen_start = m_matrix * m_view_matrix * Vector3<float>(start, 1);
|
||||
auto screen_end = m_matrix * m_view_matrix * Vector3<float>(end, 1);
|
||||
m_pge->FillRect(
|
||||
screen_start.x(),
|
||||
screen_start.y(),
|
||||
screen_end.x() - screen_start.x() + 1,
|
||||
screen_end.y() - screen_start.y() + 1,
|
||||
olc::Pixel(color.r(), color.g(), color.b())
|
||||
);
|
||||
}
|
||||
|
||||
void Render::fill_rectangle_sz(Vector2<int> start, Vector2<int> size, Color color) {
|
||||
auto origin = start + m_camera_pos;
|
||||
m_pge->FillRect(origin.x(), origin.y(), size.x() + 1, size.y() + 1, olc::Pixel(color.r(), color.g(), color.b()));
|
||||
auto screen_start = m_view_matrix * Vector3<float>(start, 1);
|
||||
m_pge->FillRect(
|
||||
screen_start.x(),
|
||||
screen_start.y(),
|
||||
size.x() + 1,
|
||||
size.y() + 1,
|
||||
olc::Pixel(color.r(), color.g(), color.b())
|
||||
);
|
||||
}
|
||||
|
||||
void Render::set_camera_pos(Vector2<int> camera_pos) {
|
||||
m_camera_pos = camera_pos;
|
||||
m_view_matrix = translation_matrix(camera_pos);
|
||||
}
|
||||
|
||||
Vector2<int> Render::camera_pos() {
|
||||
return m_camera_pos;
|
||||
}
|
||||
|
||||
void Render::translate(Vector2<float> trans) {
|
||||
m_matrix *= translation_matrix(trans);
|
||||
}
|
||||
|
||||
void Render::rotate(float theta) {
|
||||
m_matrix *= rotation_matrix(theta);
|
||||
}
|
||||
|
||||
void Render::scale(Vector2<float> scale) {
|
||||
m_matrix *= scale_matrix(scale);
|
||||
}
|
||||
|
||||
Matrix3x3<float> Render::translation_matrix(Vector2<float> trans) {
|
||||
return Matrix3x3<float>(
|
||||
{1., 0., trans[0]},
|
||||
{0., 1., trans[1]},
|
||||
{0., 0., 1.}
|
||||
);
|
||||
}
|
||||
|
||||
Matrix3x3<float> Render::rotation_matrix(float theta) {
|
||||
return Matrix3x3<float>(
|
||||
{cos(theta), -sin(theta), 0},
|
||||
{sin(theta), cos(theta), 0},
|
||||
{0., 0., 1.}
|
||||
);
|
||||
}
|
||||
|
||||
Matrix3x3<float> Render::scale_matrix(Vector2<float> scale) {
|
||||
return Matrix3x3<float>(
|
||||
{scale[0], 0., 0.},
|
||||
{0., scale[1], 0.},
|
||||
{0., 0., 1.}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "olcPixelGameEngine.h"
|
||||
#include "util/color.h"
|
||||
#include "util/vector2.h"
|
||||
#include "util/vector3.h"
|
||||
#include "util/matrix3x3.h"
|
||||
|
||||
|
||||
class Render {
|
||||
public:
|
||||
|
@ -14,11 +19,23 @@ class Render {
|
|||
void fill_rectangle(Vector2<int> start, Vector2<int> end, Color color = {0, 0, 0});
|
||||
void fill_rectangle_sz(Vector2<int> start, Vector2<int> size, Color color = {0, 0, 0});
|
||||
|
||||
void set_camera_pos(Vector2<int> camera_pos) { m_camera_pos = camera_pos; }
|
||||
Vector2<int> camera_pos() { return m_camera_pos; }
|
||||
void set_camera_pos(Vector2<int> camera_pos);
|
||||
Vector2<int> camera_pos();
|
||||
|
||||
void translate(Vector2<float> trans);
|
||||
void rotate(float theta);
|
||||
void scale(Vector2<float> scale);
|
||||
|
||||
private:
|
||||
Matrix3x3<float> translation_matrix(Vector2<float> trans);
|
||||
Matrix3x3<float> rotation_matrix(float theta);
|
||||
Matrix3x3<float> scale_matrix(Vector2<float> scale);
|
||||
|
||||
private:
|
||||
olc::PixelGameEngine *m_pge;
|
||||
|
||||
Vector2<int> m_camera_pos;
|
||||
Matrix3x3<float> m_view_matrix{1};
|
||||
Matrix3x3<float> m_matrix{1};
|
||||
std::stack<Matrix3x3<float>> m_matrix_stack;
|
||||
};
|
||||
|
|
|
@ -6,8 +6,18 @@ template <typename T>
|
|||
class Vector2 {
|
||||
public:
|
||||
Vector2() = default;
|
||||
|
||||
Vector2(T x, T y) : m_x(x), m_y(y) {}
|
||||
template <typename X, typename Y>
|
||||
Vector2(X x, Y y) :
|
||||
m_x(static_cast<T>(x)),
|
||||
m_y(static_cast<T>(y)) {}
|
||||
|
||||
Vector2(const Vector2<T> &other) = default;
|
||||
template <typename A>
|
||||
Vector2(const Vector2<A> &other) :
|
||||
m_x(static_cast<T>(other[0])),
|
||||
m_y(static_cast<T>(other[1])) {};
|
||||
|
||||
T x() { return m_x; }
|
||||
T y() { return m_y; }
|
||||
|
@ -46,6 +56,25 @@ class Vector2 {
|
|||
bool operator<=(const Vector2<T> &other) const { return m_x <= other.m_x || (m_x == other.m_x && m_y <= other.m_y); }
|
||||
bool operator>=(const Vector2<T> &other) const { return m_x >= other.m_x || (m_x == other.m_x && m_y >= other.m_y); }
|
||||
|
||||
T &operator[](const int idx) {
|
||||
switch(idx) {
|
||||
default:
|
||||
case 0:
|
||||
return m_x;
|
||||
case 1:
|
||||
return m_y;
|
||||
}
|
||||
}
|
||||
const T &operator[](const int idx) const {
|
||||
switch(idx) {
|
||||
default:
|
||||
case 0:
|
||||
return m_x;
|
||||
case 1:
|
||||
return m_y;
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Vector2<T> &vec) {
|
||||
os << "Vector2(" << vec.m_x << ", " << vec.m_y << ")";
|
||||
return os;
|
||||
|
|
103
src/util/vector3.h
Normal file
103
src/util/vector3.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
#pragma once
|
||||
|
||||
#include "vector2.h"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
template <typename T>
|
||||
class Vector3 {
|
||||
public:
|
||||
Vector3() = default;
|
||||
|
||||
Vector3(T x, T y, T z) : m_x(x), m_y(y), m_z(z) {}
|
||||
template <typename X, typename Y, typename Z>
|
||||
Vector3(X x, Y y, Z z) :
|
||||
m_x(static_cast<T>(x)),
|
||||
m_y(static_cast<T>(y)),
|
||||
m_z(static_cast<T>(z)) {}
|
||||
|
||||
template <typename A, typename B>
|
||||
Vector3(Vector2<A> xy, B z) :
|
||||
m_x(static_cast<T>(xy[0])),
|
||||
m_y(static_cast<T>(xy[1])),
|
||||
m_z(static_cast<T>(z)) {}
|
||||
template <typename A, typename B>
|
||||
Vector3(A x, Vector2<B> yz) :
|
||||
m_x(static_cast<T>(x)),
|
||||
m_y(static_cast<T>(yz[0])),
|
||||
m_z(static_cast<T>(yz[1])) {}
|
||||
|
||||
Vector3(const Vector3<T> &other) = default;
|
||||
template <typename A>
|
||||
Vector3(const Vector3<A> &other) :
|
||||
m_x(static_cast<T>(other[0])),
|
||||
m_y(static_cast<T>(other[1])),
|
||||
m_z(static_cast<T>(other[2])) {}
|
||||
|
||||
T x() { return m_x; }
|
||||
T y() { return m_y; }
|
||||
T z() { return m_z; }
|
||||
|
||||
void set_x(T x) { m_x = x; }
|
||||
void set_y(T y) { m_y = y; }
|
||||
void set_z(T z) { m_z = z; }
|
||||
|
||||
void set(T x, T y, T z) { m_x = x; m_y = y; m_z = z; }
|
||||
|
||||
Vector3<T> operator-() const { return Vector3<T>(-m_x, -m_y, -m_z); }
|
||||
|
||||
Vector3<T> &operator=(const Vector3<T> &other) { m_x = other.m_x; m_y = other.m_y; m_z = other.m_z; return *this; }
|
||||
|
||||
Vector3<T> operator+(const Vector3<T> &other) const { return Vector3(m_x + other.m_x, m_y + other.m_y, m_z + other.m_z); }
|
||||
Vector3<T> &operator+=(const Vector3<T> &other) { m_x += other.m_x; m_y += other.m_y; m_z += other.m_z; return *this; }
|
||||
|
||||
Vector3<T> operator-(const Vector3<T> &other) const { return Vector3(m_x - other.m_x, m_y - other.m_y, m_z - other.m_z); }
|
||||
Vector3<T> &operator-=(const Vector3<T> &other) { m_x -= other.m_x; m_y -= other.m_y; m_z -= other.m_z; return *this; }
|
||||
|
||||
Vector3<T> operator*(const Vector3<T> &other) const { return Vector3(m_x * other.m_x, m_y * other.m_y, m_z * other.m_z); }
|
||||
Vector3<T> &operator*=(const Vector3<T> &other) { m_x *= other.m_x; m_y *= other.m_y; m_z *= other.m_z; return *this; }
|
||||
Vector3<T> operator*(const T &s) const { return Vector3(m_x * s, m_y * s, m_z * s); }
|
||||
Vector3<T> &operator*=(const T &s) { m_x *= s; m_y *= s; m_z *= s; return *this; }
|
||||
|
||||
Vector3<T> operator/(const Vector3<T> &other) const { return Vector3(m_x / other.m_x, m_y / other.m_y, m_z / other.m_z); }
|
||||
Vector3<T> &operator/=(const Vector3<T> &other) { m_x /= other.m_x; m_y /= other.m_y; m_z /= other.m_z; return *this; }
|
||||
Vector3<T> operator/(const T &s) const { return Vector3(m_x / s, m_y / s, m_z / s); }
|
||||
Vector3<T> &operator/=(const T &s) { m_x /= s; m_y /= s; m_z /= s; return *this; }
|
||||
|
||||
bool operator==(const Vector3<T> &other) const { return m_x == other.m_x && m_y == other.m_y && m_z == other.m_z; }
|
||||
bool operator!=(const Vector3<T> &other) const { return m_x == other.m_x || m_y != other.m_y || m_z != other.m_z; }
|
||||
|
||||
T &operator[](const int idx) {
|
||||
switch(idx) {
|
||||
default:
|
||||
case 0:
|
||||
return m_x;
|
||||
case 1:
|
||||
return m_y;
|
||||
case 2:
|
||||
return m_z;
|
||||
}
|
||||
}
|
||||
const T &operator[](const int idx) const {
|
||||
switch(idx) {
|
||||
default:
|
||||
case 0:
|
||||
return m_x;
|
||||
case 1:
|
||||
return m_y;
|
||||
case 2:
|
||||
return m_z;
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const Vector3<T> &vec) {
|
||||
os << "Vector3(" << vec.m_x << ", " << vec.m_y << ", " << vec.m_z << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_x = 0;
|
||||
T m_y = 0;
|
||||
T m_z = 0;
|
||||
};
|
||||
|
Loading…
Reference in a new issue