Compare commits
5 Commits
f4ba9b3df3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| a13a9c5489 | |||
| 51989119ba | |||
| e13458d793 | |||
| f01d539489 | |||
| 8fffe4d8e3 |
@@ -12,3 +12,4 @@ set (CMAKE_CXX_STANDARD 20)
|
||||
add_executable(one main.cpp)
|
||||
|
||||
target_link_libraries(one m Qt6::Widgets Qt6::Gui)
|
||||
# target_link_libraries(one m)
|
||||
|
||||
262
fastmath.hpp
262
fastmath.hpp
@@ -113,7 +113,7 @@ template <int n, class Dev> struct vec {
|
||||
for (int i = 0; i < n; 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) {
|
||||
@@ -192,6 +192,14 @@ template <int n, class Dev> struct vec {
|
||||
decimal f = decimal(1.0) / this->len();
|
||||
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> {
|
||||
|
||||
@@ -233,6 +241,8 @@ struct vec3 : public vec<3, vec3> {
|
||||
};
|
||||
struct vec4 : public vec<4, vec4> {
|
||||
|
||||
constexpr vec4() : vec<4, vec4>() {}
|
||||
|
||||
vec4(float x, float y, float z, float 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)
|
||||
: 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 &y() { return v[1]; }
|
||||
@@ -249,107 +260,152 @@ struct vec4 : public vec<4, vec4> {
|
||||
decimal &w() { return v[3]; }
|
||||
};
|
||||
|
||||
// template <int n, class Dev> struct mat {
|
||||
//
|
||||
// mat(decimal newM[n * n]) {
|
||||
// for (int i = 0; i < n * n; i++) {
|
||||
// m[i] = newM[i];
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// mat(std::vector<decimal> newM) {
|
||||
// for (int i = 0; i < n * n; i++) {
|
||||
// m[i] = newM[i];
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// mat() : m{} {}
|
||||
//
|
||||
// friend Dev operator+(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
|
||||
// Dev newM = {};
|
||||
//
|
||||
// for (int i = 0; i < n * n; i++) {
|
||||
// newM.v[i] = m1.m[i] + m2.m[i];
|
||||
// }
|
||||
// return newM;
|
||||
// }
|
||||
// friend Dev operator+=(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
|
||||
// Dev newM = {};
|
||||
//
|
||||
// for (int i = 0; i < n * n; i++) {
|
||||
// newM.m[i] = m1.m[i] + m2.m[i];
|
||||
// }
|
||||
// return newM;
|
||||
// }
|
||||
//
|
||||
// friend Dev operator-(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
|
||||
// Dev newM = {};
|
||||
//
|
||||
// for (int i = 0; i < n * n; i++) {
|
||||
// newM.m[i] = m1.m[i] - m2.m[i];
|
||||
// }
|
||||
// return static_cast<Dev>(newM);
|
||||
// }
|
||||
//
|
||||
// friend std::ostream &operator<<(std::ostream &os, const mat<n, Dev> &m) {
|
||||
// os << "(" << m.m[0];
|
||||
// for (int i = 1; i < n * n; i++) {
|
||||
// os << ", " << m.m[i];
|
||||
// }
|
||||
// return (os << ")" << std::endl);
|
||||
// }
|
||||
//
|
||||
// friend Dev operator*(const mat<n, Dev> &m, const decimal &d) {
|
||||
// int32_t f = d.i >> HALF_SHIFT;
|
||||
//
|
||||
// Dev newM = {};
|
||||
// for (int i = 0; i < n * n; i++) {
|
||||
// newM.m[i] = (m.m[i].i >> HALF_SHIFT) * f;
|
||||
// }
|
||||
// return newM;
|
||||
// }
|
||||
//
|
||||
// friend Dev operator*(const decimal &d, const mat<n, Dev> &v) {
|
||||
// return v * d;
|
||||
// }
|
||||
//
|
||||
// Dev operator*(const mat<n, Dev> &mat) {
|
||||
// Dev newM = {};
|
||||
// for (int i = 0; i < n; i++) {
|
||||
// for (int j = 0; j < n; j++) {
|
||||
// newM.m += mat.v[i * n] * m[i];
|
||||
// }
|
||||
// }
|
||||
// return res;
|
||||
// }
|
||||
//
|
||||
// friend bool operator==(const mat<n, Dev> &v1, const mat<n, Dev> &m2) {
|
||||
// bool res = true;
|
||||
// for (int i = 0; i < n; i++) {
|
||||
// res &= v1.v[i] == m2.v[i];
|
||||
// }
|
||||
// return res;
|
||||
// }
|
||||
// bool isSmall() {
|
||||
// for (int i = 0; i < n; i++) {
|
||||
// if (!v[i].isSmall())
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// decimal &operator[](const int &i) { return v[i]; }
|
||||
//
|
||||
// decimal len_sq() { return *this * *this; }
|
||||
//
|
||||
// decimal len() { return this->len_sq().sqrt(); }
|
||||
//
|
||||
// Dev normalize() {
|
||||
// decimal f = decimal(1.0) / this->len();
|
||||
// return (*this * f);
|
||||
// }
|
||||
//
|
||||
// protected:
|
||||
// decimal m[n * n];
|
||||
// };
|
||||
template <int n, class Dev> struct mat {
|
||||
decimal m[n * n];
|
||||
|
||||
static const int size = n;
|
||||
friend Dev operator+(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
|
||||
Dev newM = {};
|
||||
|
||||
for (int i = 0; i < n * n; i++) {
|
||||
newM.v[i] = m1.m[i] + m2.m[i];
|
||||
}
|
||||
return newM;
|
||||
}
|
||||
friend Dev operator+=(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
|
||||
Dev newM = {};
|
||||
|
||||
for (int i = 0; i < n * n; i++) {
|
||||
newM.m[i] = m1.m[i] + m2.m[i];
|
||||
}
|
||||
return newM;
|
||||
}
|
||||
|
||||
friend Dev operator-(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
|
||||
Dev newM = {};
|
||||
|
||||
for (int i = 0; i < n * n; i++) {
|
||||
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];
|
||||
for (int j = 1; j < n; j++) {
|
||||
os << ", " << m.m[i * n + j];
|
||||
}
|
||||
os << "|" << "\n";
|
||||
}
|
||||
return (os << std::endl);
|
||||
}
|
||||
|
||||
template <class Dev1>
|
||||
friend Dev1 operator*(const mat<n, Dev> &mat, const vec<n, Dev1> &v) {
|
||||
Dev1 newV = vec<n, Dev1>::zero();
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
newV[i] += mat.m[i * n + j] * v.v[j];
|
||||
}
|
||||
}
|
||||
return newV;
|
||||
}
|
||||
|
||||
decimal &operator[](const int &i) { return m[i]; }
|
||||
|
||||
friend Dev operator*(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
|
||||
Dev newM = mat<n, Dev>::zero();
|
||||
for (int i = 0; i < n; i++) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
return newM;
|
||||
}
|
||||
|
||||
constexpr static Dev identity() {
|
||||
Dev newM = {};
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
if (i == j)
|
||||
newM.m[i * n + i] = decimal(1.0f);
|
||||
else
|
||||
newM.m[i * n + j] = decimal(0.0f);
|
||||
}
|
||||
}
|
||||
return newM;
|
||||
}
|
||||
constexpr static Dev zero() {
|
||||
Dev newM = {};
|
||||
for (int i = 0; i < n * n; i++) {
|
||||
newM[i] = decimal(0);
|
||||
}
|
||||
return newM;
|
||||
}
|
||||
|
||||
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]; }
|
||||
|
||||
friend bool operator==(const mat<n, Dev> &m1, const mat<n, Dev> &m2) {
|
||||
bool res = true;
|
||||
for (int i = 0; i < n * n; i++) {
|
||||
res &= m1.m[i] == m2.m[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
bool isSmall() {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (!m[i].isSmall())
|
||||
return false;
|
||||
}
|
||||
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
|
||||
|
||||
62
main.cpp
62
main.cpp
@@ -6,7 +6,9 @@
|
||||
#include <QApplication>
|
||||
#include <QImage>
|
||||
#include <QLabel>
|
||||
#include <QObject>
|
||||
#include <QPixmap>
|
||||
#include <QTimer>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <math.h>
|
||||
@@ -80,7 +82,8 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
std::chrono::steady_clock::time_point begin =
|
||||
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::now();
|
||||
|
||||
@@ -89,7 +92,6 @@ int main(int argc, char *argv[]) {
|
||||
begin)
|
||||
.count()
|
||||
<< "[ms]" << std::endl;
|
||||
QApplication a(argc, argv);
|
||||
|
||||
uint8_t *pixel = new uint8_t[64 * 64 * 3];
|
||||
/*for (int i = 0; i < 64 * 64 * 3; i++) {
|
||||
@@ -102,25 +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);
|
||||
QWidget widget;
|
||||
widget.setAutoFillBackground(true);
|
||||
widget.setGeometry(0, 0, 500, 500);
|
||||
QLabel display(&widget);
|
||||
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();
|
||||
QTimer timer;
|
||||
timer.setInterval(20);
|
||||
timer.start();
|
||||
QObject::connect(&timer, &QTimer::timeout, &widget, renderLoop);
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
34
renderer.hpp
34
renderer.hpp
@@ -20,15 +20,16 @@ class Renderer {
|
||||
bool clearTarget = true;
|
||||
vec3 sunDir = vec3(1.0, -1.0, 1.0).normalize();
|
||||
|
||||
void toScreenSpace(vec3 *p) {
|
||||
p->x() = p->x() / p->z() * decimal(2.0) * decimal(SCREEN_SPACE_SIZE) +
|
||||
void toScreenSpace(vec3 *np, mat4 matrix) {
|
||||
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);
|
||||
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);
|
||||
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(SCREEN_SPACE_SIZE * 2) / decimal((float)target->width);
|
||||
decimal heightScale =
|
||||
@@ -44,6 +45,7 @@ class Renderer {
|
||||
// memset((wchar_t *)target->pixels, 0,
|
||||
// target->height * target->width * sizeof(target[0]));
|
||||
target->clearDepth();
|
||||
target->clearTarget();
|
||||
}
|
||||
|
||||
vec3 verts[model->verts.size()] = {};
|
||||
@@ -51,7 +53,13 @@ class Renderer {
|
||||
std::copy(model->verts.begin(), model->verts.end(), verts);
|
||||
|
||||
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;
|
||||
@@ -62,8 +70,7 @@ class Renderer {
|
||||
testP.points[p] = verts[std::get<0>(model->faces[f + p])];
|
||||
testP.colors[p] =
|
||||
model->colors[std::get<0>(model->faces[f + p])];
|
||||
testP.normals[p] =
|
||||
model->normals[std::get<1>(model->faces[f + p])];
|
||||
testP.normals[p] = normals[std::get<1>(model->faces[f + p])];
|
||||
}
|
||||
if ((testP.avgNormal() * vec3(0.0, 0.0, 1.0)) > decimal(0.))
|
||||
continue;
|
||||
@@ -85,12 +92,9 @@ class Renderer {
|
||||
for (int x = startX; x < endX; x++) {
|
||||
for (int y = startY; y < endY; y++) {
|
||||
|
||||
testP.calcBarycentric(pos);
|
||||
|
||||
if (testP.contains(pos)) {
|
||||
if (testP.small)
|
||||
continue;
|
||||
if (testP.depContains(pos)) {
|
||||
|
||||
testP.calcBarycentric(pos);
|
||||
decimal depth = testP.calcDepth();
|
||||
if (depth < target->getDepth(x, y)) {
|
||||
// std::cout << factors << std::endl;
|
||||
@@ -109,6 +113,10 @@ class Renderer {
|
||||
// target->set(x, y,
|
||||
// (normal + vec3(1.0, 1.0, 1.0)) *
|
||||
// decimal(120.0));
|
||||
// target->set(
|
||||
// x, y,
|
||||
// (testP.avgNormal() + vec3(1.0, 1.0, 1.0)) *
|
||||
// decimal(120.0));
|
||||
// target->set(x, y,
|
||||
// testP.barycentrics * decimal(200.0));
|
||||
// if (!factors.isSmall())
|
||||
|
||||
@@ -32,6 +32,11 @@ class Rendertarget {
|
||||
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;
|
||||
decimal *depth;
|
||||
|
||||
Reference in New Issue
Block a user