Compare commits

...

3 Commits

Author SHA1 Message Date
a13a9c5489 feat: animation in main 2025-12-27 23:51:55 +01:00
51989119ba feat: modelmatrix 2025-12-27 23:51:34 +01:00
e13458d793 feat: added matrix to mathlib 2025-12-27 23:50:41 +01:00
4 changed files with 228 additions and 128 deletions

View File

@@ -113,7 +113,7 @@ template <int n, class Dev> struct vec {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
newV.v[i] = v1.v[i] - v2.v[i]; newV.v[i] = v1.v[i] - v2.v[i];
} }
return static_cast<Dev>(newV); return newV;
} }
friend std::ostream &operator<<(std::ostream &os, const vec<n, Dev> &v) { friend std::ostream &operator<<(std::ostream &os, const vec<n, Dev> &v) {
@@ -192,6 +192,14 @@ template <int n, class Dev> struct vec {
decimal f = decimal(1.0) / this->len(); decimal f = decimal(1.0) / this->len();
return (*this * f); return (*this * f);
} }
constexpr static Dev zero() {
Dev newV = {};
for (int i = 0; i < n; i++) {
newV[i] = decimal(0);
}
return newV;
}
}; };
struct vec2 : public vec<2, vec2> { struct vec2 : public vec<2, vec2> {
@@ -233,6 +241,8 @@ struct vec3 : public vec<3, vec3> {
}; };
struct vec4 : public vec<4, vec4> { struct vec4 : public vec<4, vec4> {
constexpr vec4() : vec<4, vec4>() {}
vec4(float x, float y, float z, float w) vec4(float x, float y, float z, float w)
: vec<4, vec4>(decimal(x), decimal(y), decimal(z), decimal(w)) {} : vec<4, vec4>(decimal(x), decimal(y), decimal(z), decimal(w)) {}
@@ -242,6 +252,7 @@ struct vec4 : public vec<4, vec4> {
vec4(int32_t x, int32_t y, int32_t z, int32_t w) vec4(int32_t x, int32_t y, int32_t z, int32_t w)
: vec<4, vec4>(decimal(x), decimal(y), decimal(z), decimal(w)) {} : vec<4, vec4>(decimal(x), decimal(y), decimal(z), decimal(w)) {}
vec4(vec3 v, decimal w) : vec<4, vec4>(v.x(), v.y(), v.z(), w) {}
decimal &x() { return v[0]; } decimal &x() { return v[0]; }
decimal &y() { return v[1]; } decimal &y() { return v[1]; }
@@ -249,107 +260,152 @@ struct vec4 : public vec<4, vec4> {
decimal &w() { return v[3]; } decimal &w() { return v[3]; }
}; };
// template <int n, class Dev> struct mat { template <int n, class Dev> struct mat {
// decimal m[n * n];
// mat(decimal newM[n * n]) {
// for (int i = 0; i < n * n; i++) { static const int size = n;
// m[i] = newM[i]; friend Dev operator+(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
// } Dev newM = {};
// }
// for (int i = 0; i < n * n; i++) {
// mat(std::vector<decimal> newM) { newM.v[i] = m1.m[i] + m2.m[i];
// for (int i = 0; i < n * n; i++) { }
// m[i] = newM[i]; return newM;
// } }
// } friend Dev operator+=(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
// Dev newM = {};
// mat() : m{} {}
// for (int i = 0; i < n * n; i++) {
// friend Dev operator+(const mat<n, Dev> &m1, const mat<n, Dev> &m2) { newM.m[i] = m1.m[i] + m2.m[i];
// Dev newM = {}; }
// return newM;
// for (int i = 0; i < n * n; i++) { }
// newM.v[i] = m1.m[i] + m2.m[i];
// } friend Dev operator-(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
// return newM; Dev newM = {};
// }
// friend Dev operator+=(const mat<n, Dev> &m1, const mat<n, Dev> &m2) { for (int i = 0; i < n * n; i++) {
// Dev newM = {}; newM.m[i] = m1.m[i] - m2.m[i];
// }
// for (int i = 0; i < n * n; i++) { return newM;
// newM.m[i] = m1.m[i] + m2.m[i]; }
// }
// return newM; friend std::ostream &operator<<(std::ostream &os, const mat<n, Dev> &m) {
// } for (int i = 0; i < n; i++) {
// os << "|" << m.m[i * n];
// friend Dev operator-(const mat<n, Dev> &m1, const mat<n, Dev> &m2) { for (int j = 1; j < n; j++) {
// Dev newM = {}; os << ", " << m.m[i * n + j];
// }
// for (int i = 0; i < n * n; i++) { os << "|" << "\n";
// newM.m[i] = m1.m[i] - m2.m[i]; }
// } return (os << std::endl);
// return static_cast<Dev>(newM); }
// }
// template <class Dev1>
// friend std::ostream &operator<<(std::ostream &os, const mat<n, Dev> &m) { friend Dev1 operator*(const mat<n, Dev> &mat, const vec<n, Dev1> &v) {
// os << "(" << m.m[0]; Dev1 newV = vec<n, Dev1>::zero();
// for (int i = 1; i < n * n; i++) { for (int i = 0; i < n; i++) {
// os << ", " << m.m[i]; for (int j = 0; j < n; j++) {
// } newV[i] += mat.m[i * n + j] * v.v[j];
// return (os << ")" << std::endl); }
// } }
// return newV;
// friend Dev operator*(const mat<n, Dev> &m, const decimal &d) { }
// int32_t f = d.i >> HALF_SHIFT;
// decimal &operator[](const int &i) { return m[i]; }
// Dev newM = {};
// for (int i = 0; i < n * n; i++) { friend Dev operator*(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
// newM.m[i] = (m.m[i].i >> HALF_SHIFT) * f; Dev newM = mat<n, Dev>::zero();
// } for (int i = 0; i < n; i++) {
// return newM; for (int j = 0; j < n; j++) {
// } for (int k = 0; k < n; k++) {
// newM[i * n + j] += m1.m[i * n + k] * m2.m[k * n + j];
// friend Dev operator*(const decimal &d, const mat<n, Dev> &v) { }
// return v * d; }
// } }
// return newM;
// Dev operator*(const mat<n, Dev> &mat) { }
// Dev newM = {};
// for (int i = 0; i < n; i++) { constexpr static Dev identity() {
// for (int j = 0; j < n; j++) { Dev newM = {};
// newM.m += mat.v[i * n] * m[i]; for (int i = 0; i < n; i++) {
// } for (int j = 0; j < n; j++) {
// } if (i == j)
// return res; newM.m[i * n + i] = decimal(1.0f);
// } else
// newM.m[i * n + j] = decimal(0.0f);
// friend bool operator==(const mat<n, Dev> &v1, const mat<n, Dev> &m2) { }
// bool res = true; }
// for (int i = 0; i < n; i++) { return newM;
// res &= v1.v[i] == m2.v[i]; }
// } constexpr static Dev zero() {
// return res; Dev newM = {};
// } for (int i = 0; i < n * n; i++) {
// bool isSmall() { newM[i] = decimal(0);
// for (int i = 0; i < n; i++) { }
// if (!v[i].isSmall()) return newM;
// return false; }
// }
// return true; inline void set(int x, int y, decimal v) { m[y * n + x] = v; }
// } inline decimal get(int x, int y) { return m[y * n + x]; }
// decimal &operator[](const int &i) { return v[i]; }
// friend bool operator==(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
// decimal len_sq() { return *this * *this; } bool res = true;
// for (int i = 0; i < n * n; i++) {
// decimal len() { return this->len_sq().sqrt(); } res &= m1.m[i] == m2.m[i];
// }
// Dev normalize() { return res;
// decimal f = decimal(1.0) / this->len(); }
// return (*this * f); bool isSmall() {
// } for (int i = 0; i < n; i++) {
// if (!m[i].isSmall())
// protected: return false;
// decimal m[n * n]; }
// }; return true;
}
template <class Dev1> Dev1 cutTo() const {
static_assert(Dev1::size < n, "Can only convert to smaller matrix");
Dev1 newM = mat<Dev1::size, Dev1>::zero();
for (int i = 0; i < Dev1::size; i++) {
for (int j = 0; j < Dev1::size; j++) {
newM.m[Dev1::size * i + j] = m[n * i + j];
}
}
return newM;
}
};
template <int n> struct matN : public mat<n, matN<n>> {};
struct mat3 : public mat<3, mat3> {};
struct mat4 : public mat<4, mat4> {
static mat4 translation(const vec3 &v) {
mat4 newM = mat4::identity();
for (int i = 0; i < 3; i++) {
newM[4 * i + 3] = v.v[i];
}
return newM;
}
static mat4 rotateOnX(float a) {
mat4 newM = mat4::identity();
newM.m[1 * 4 + 1] = cos(a), newM.m[2 * 4 + 2] = cos(a);
newM.m[1 * 4 + 2] = -sin(a), newM.m[2 * 4 + 1] = sin(a);
return newM;
}
static mat4 rotateOnY(float a) {
mat4 newM = mat4::identity();
newM.m[0 * 4 + 0] = cos(a), newM.m[2 * 4 + 2] = cos(a);
newM.m[0 * 4 + 2] = sin(a), newM.m[2 * 4 + 0] = -sin(a);
return newM;
}
static mat4 rotateOnZ(float a) {
mat4 newM = mat4::identity();
newM.m[0 * 4 + 0] = cos(a), newM.m[1 * 4 + 1] = cos(a);
newM.m[1 * 4 + 0] = sin(a), newM.m[0 * 4 + 1] = -sin(a);
return newM;
}
};
#endif #endif

View File

@@ -6,7 +6,9 @@
#include <QApplication> #include <QApplication>
#include <QImage> #include <QImage>
#include <QLabel> #include <QLabel>
#include <QObject>
#include <QPixmap> #include <QPixmap>
#include <QTimer>
#include <chrono> #include <chrono>
#include <functional> #include <functional>
#include <math.h> #include <math.h>
@@ -80,7 +82,8 @@ int main(int argc, char *argv[]) {
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::time_point begin =
std::chrono::steady_clock::now(); std::chrono::steady_clock::now();
renderer.render(&testModel); renderer.render(&testModel, mat4::translation(vec3(0.0f, -1.0f, 5.0f)) *
mat4::rotateOnY(-1.5707963267948966f));
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::time_point end =
std::chrono::steady_clock::now(); std::chrono::steady_clock::now();
@@ -101,26 +104,53 @@ int main(int argc, char *argv[]) {
} }
}; };
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 64; y++) {
uint32_t result[3] = {};
addTo((target.width * y * 2 + x * 2) * 3, result);
addTo((target.width * (y * 2 + 1) + x * 2) * 3, result);
addTo((target.width * y * 2 + (x * 2 + 1)) * 3, result);
addTo((target.width * (y * 2 + 1) + (x * 2 + 1)) * 3, result);
for (int c = 0; c < 3; c++) {
pixel[(WIDTH * (WIDTH - y - 1) + WIDTH - x - 1) * 3 + c] =
result[c] >> 2;
}
}
}
QApplication a(argc, argv); QApplication a(argc, argv);
QWidget widget; QWidget widget;
widget.setAutoFillBackground(true); widget.setAutoFillBackground(true);
widget.setGeometry(0, 0, 500, 500); widget.setGeometry(0, 0, 500, 500);
QLabel display(&widget); QLabel display(&widget);
QImage img((unsigned char *)pixel, 64, 64, QImage::Format_RGB888); QImage img((unsigned char *)pixel, 64, 64, QImage::Format_RGB888);
display.setPixmap(QPixmap::fromImage(img).scaled(widget.size()));
// display.setPixmap(QPixmap::fromImage(img).scaled(widget.size()));
float rot = 0.f;
std::function<void()> renderLoop = [&addTo, &target, &pixel, &renderer,
&display, &widget, &img, &rot]() {
std::chrono::steady_clock::time_point begin =
std::chrono::steady_clock::now();
renderer.render(&testModel, mat4::translation(vec3(0.0f, -1.0f, 5.0f)) *
mat4::rotateOnY(rot));
std::chrono::steady_clock::time_point end =
std::chrono::steady_clock::now();
std::cout << "Time difference = "
<< std::chrono::duration_cast<std::chrono::milliseconds>(
end - begin)
.count()
<< "[ms]" << std::endl;
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 64; y++) {
uint32_t result[3] = {};
addTo((target.width * y * 2 + x * 2) * 3, result);
addTo((target.width * (y * 2 + 1) + x * 2) * 3, result);
addTo((target.width * y * 2 + (x * 2 + 1)) * 3, result);
addTo((target.width * (y * 2 + 1) + (x * 2 + 1)) * 3, result);
for (int c = 0; c < 3; c++) {
pixel[(WIDTH * (WIDTH - y - 1) + WIDTH - x - 1) * 3 + c] =
result[c] >> 2;
}
}
}
// QImage img((unsigned char *)pixel, 64, 64, QImage::Format_RGB888);
display.setPixmap(QPixmap::fromImage(img).scaled(widget.size() * 1));
rot += 0.1f;
};
renderLoop();
widget.show(); widget.show();
QTimer timer;
timer.setInterval(20);
timer.start();
QObject::connect(&timer, &QTimer::timeout, &widget, renderLoop);
return a.exec(); return a.exec();
} }

View File

@@ -20,15 +20,16 @@ class Renderer {
bool clearTarget = true; bool clearTarget = true;
vec3 sunDir = vec3(1.0, -1.0, 1.0).normalize(); vec3 sunDir = vec3(1.0, -1.0, 1.0).normalize();
void toScreenSpace(vec3 *p) { void toScreenSpace(vec3 *np, mat4 matrix) {
p->x() = p->x() / p->z() * decimal(2.0) * decimal(SCREEN_SPACE_SIZE) + vec4 tp = (matrix * vec4(*np, decimal(1.0f)));
tp.x() = tp.x() / tp.z() * decimal(2.0) * decimal(SCREEN_SPACE_SIZE) +
decimal(SCREEN_SPACE_SIZE); decimal(SCREEN_SPACE_SIZE);
p->y() = p->y() / p->z() * decimal(2.0) * decimal(SCREEN_SPACE_SIZE) + tp.y() = tp.y() / tp.z() * decimal(2.0) * decimal(SCREEN_SPACE_SIZE) +
decimal(SCREEN_SPACE_SIZE); decimal(SCREEN_SPACE_SIZE);
p->z() = p->z(); *np = vec3(tp.x(), tp.y(), tp.z());
} }
void render(const model *model) { void render(const model *model, const mat4 matrix) {
decimal widthScale = decimal widthScale =
decimal(SCREEN_SPACE_SIZE * 2) / decimal((float)target->width); decimal(SCREEN_SPACE_SIZE * 2) / decimal((float)target->width);
decimal heightScale = decimal heightScale =
@@ -44,6 +45,7 @@ class Renderer {
// memset((wchar_t *)target->pixels, 0, // memset((wchar_t *)target->pixels, 0,
// target->height * target->width * sizeof(target[0])); // target->height * target->width * sizeof(target[0]));
target->clearDepth(); target->clearDepth();
target->clearTarget();
} }
vec3 verts[model->verts.size()] = {}; vec3 verts[model->verts.size()] = {};
@@ -51,7 +53,13 @@ class Renderer {
std::copy(model->verts.begin(), model->verts.end(), verts); std::copy(model->verts.begin(), model->verts.end(), verts);
for (int i = 0; i < model->verts.size(); i++) { for (int i = 0; i < model->verts.size(); i++) {
toScreenSpace(verts + i); toScreenSpace(verts + i, matrix);
}
vec3 normals[model->normals.size()] = {};
mat3 normalMatrix = matrix.cutTo<mat3>();
for (int i = 0; i < model->normals.size(); i++) {
normals[i] = normalMatrix * model->normals[i];
} }
polygon testP; polygon testP;
@@ -62,8 +70,7 @@ class Renderer {
testP.points[p] = verts[std::get<0>(model->faces[f + p])]; testP.points[p] = verts[std::get<0>(model->faces[f + p])];
testP.colors[p] = testP.colors[p] =
model->colors[std::get<0>(model->faces[f + p])]; model->colors[std::get<0>(model->faces[f + p])];
testP.normals[p] = testP.normals[p] = normals[std::get<1>(model->faces[f + p])];
model->normals[std::get<1>(model->faces[f + p])];
} }
if ((testP.avgNormal() * vec3(0.0, 0.0, 1.0)) > decimal(0.)) if ((testP.avgNormal() * vec3(0.0, 0.0, 1.0)) > decimal(0.))
continue; continue;
@@ -86,8 +93,6 @@ class Renderer {
for (int y = startY; y < endY; y++) { for (int y = startY; y < endY; y++) {
if (testP.depContains(pos)) { if (testP.depContains(pos)) {
if (testP.small)
continue;
testP.calcBarycentric(pos); testP.calcBarycentric(pos);
decimal depth = testP.calcDepth(); decimal depth = testP.calcDepth();
@@ -108,6 +113,10 @@ class Renderer {
// target->set(x, y, // target->set(x, y,
// (normal + vec3(1.0, 1.0, 1.0)) * // (normal + vec3(1.0, 1.0, 1.0)) *
// decimal(120.0)); // decimal(120.0));
// target->set(
// x, y,
// (testP.avgNormal() + vec3(1.0, 1.0, 1.0)) *
// decimal(120.0));
// target->set(x, y, // target->set(x, y,
// testP.barycentrics * decimal(200.0)); // testP.barycentrics * decimal(200.0));
// if (!factors.isSmall()) // if (!factors.isSmall())

View File

@@ -32,6 +32,11 @@ class Rendertarget {
depth[i].i = std::numeric_limits<int32_t>::max(); depth[i].i = std::numeric_limits<int32_t>::max();
} }
} }
void clearTarget() {
for (int i = 0; i < width * height * 3; i++) {
pixels[i] = 0;
}
}
uint8_t *pixels; uint8_t *pixels;
decimal *depth; decimal *depth;