aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvimene <vincent.menegaux@gmail.com>2023-11-26 06:49:51 +0100
committervimene <vincent.menegaux@gmail.com>2023-11-26 06:49:51 +0100
commitf63febed2a769d0c55192e192a20b8e39f162932 (patch)
treef12fef4643e03e93363f902e35d06ef92dd8350d
parent97f4e5c80483255912b177e6a2557344da499a3e (diff)
downloadengine-f63febed2a769d0c55192e192a20b8e39f162932.tar.gz
improved matrices, cube building and command parsing
-rw-r--r--src/engine.cpp217
-rw-r--r--src/math/mat4.cpp39
-rw-r--r--src/math/mat4.h6
-rw-r--r--src/o3d/obj3d.cpp23
-rw-r--r--src/o3d/obj3d.h2
5 files changed, 124 insertions, 163 deletions
diff --git a/src/engine.cpp b/src/engine.cpp
index 4740046..69b2f43 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -9,6 +9,7 @@
#include <vector>
#include <functional>
#include <utility>
+#include <iterator>
#include <SDL.h>
#ifdef ENABLE_NCURSES
@@ -49,158 +50,30 @@ template <class FB>
void scene_main(FB& fb, std::function<bool()> update_frame) {
MathVector3 a{0.f, 0.f, 0.f};
float dist = 4.f;
+ float rad = 5.f;
bool cont = true;
+ std::array<Object3D, 2> objs{{ Object3D::cube(), Object3D::cube() }};
+ auto scale_mat = Mat4::scale(rad);
while (cont) {
a.x += .0050f;
a.y += .0065f;
a.z += .0080f;
- float rad = 5.f;
- auto [e4_x, e4_y, e4_z, e4_w] = (Mat4::rot_x(a.x) * Mat4::rot_y(a.y) * Mat4::rot_z(a.z)).to_vecs();
- auto e_x = e4_x.xyz();
- auto e_y = e4_y.xyz();
- auto e_z = e4_z.xyz();
-
- std::array<Object3D, 2> objs{{
- {
- {
- {
- rad * (-e_x + -e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (+e_x + -e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (-e_x + +e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (+e_x + +e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (-e_x + -e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (+e_x + -e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (-e_x + +e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (+e_x + +e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- }
- },
- {
- // face 1
- { 0, 2, 3 },
- { 0, 3, 1 },
-
- // face 2
- { 0, 4, 6 },
- { 0, 6, 2 },
-
- // face 3
- { 0, 1, 5 },
- { 0, 5, 4 },
-
- // face 4
- { 7, 6, 4 },
- { 7, 4, 5 },
-
- // face 5
- { 7, 3, 2 },
- { 7, 2, 6 },
-
- // face 6
- { 7, 5, 1 },
- { 7, 1, 3 },
- }
- },
- {
- {
- {
- rad * (-e_x + -e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (+e_x + -e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (-e_x + +e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (+e_x + +e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (-e_x + -e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (+e_x + -e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (-e_x + +e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- },
- {
- rad * (+e_x + +e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f},
- {}
- }
- },
- {
- // face 1
- { 0, 2, 3 },
- { 0, 3, 1 },
-
- // face 2
- { 0, 4, 6 },
- { 0, 6, 2 },
-
- // face 3
- { 0, 1, 5 },
- { 0, 5, 4 },
-
- // face 4
- { 7, 6, 4 },
- { 7, 4, 5 },
-
- // face 5
- { 7, 3, 2 },
- { 7, 2, 6 },
-
- // face 6
- { 7, 5, 1 },
- { 7, 1, 3 },
- }
- }
- }};
fb.clear();
- float min_z = 2.f, max_z = 50.f;
- float fac_for_aspect_ratio = static_cast<float>(fb.height()) / static_cast<float>(fb.width());
- Mat4 mat{{
- fac_for_aspect_ratio, 0.f, 0.f, 0.f,
- 0.f, -1.f, 0.f, 0.f,
- 0.f, 0.f, -2.f / (max_z - min_z), -(max_z + min_z) / (max_z - min_z),
- 0.f, 0.f, -1.f, 0.f,
+ auto transform_mat = Mat4::translate(MathVector3{0.f, 0.f, -rad * dist}) * Mat4::rot_z(a.z) * Mat4::rot_y(a.y) * Mat4::rot_x(a.x);
+ std::array<Mat4, 2> mats{{
+ transform_mat * Mat4::translate(MathVector3{-.5f * rad, -.5f * rad, -.5f * rad}) * scale_mat,
+ transform_mat * Mat4::translate(MathVector3{+.5f * rad, +.5f * rad, +.5f * rad}) * scale_mat,
}};
- for (auto obj : objs) {
- for (auto triangle : obj) {
+ auto projection_mat = Mat4::projection(static_cast<float>(fb.height()) / static_cast<float>(fb.width()), 2.f, 50.f);
+ for (int i = 0; i < 2; i++) {
+ auto final_mat = projection_mat * mats[i];
+ for (auto triangle : objs[i]) {
TriangleVertex4 t{triangle};
- t.vertex1.point = mat * t.vertex1.point;
- t.vertex2.point = mat * t.vertex2.point;
- t.vertex3.point = mat * t.vertex3.point;
+ t.vertex1.point = final_mat * t.vertex1.point;
+ t.vertex2.point = final_mat * t.vertex2.point;
+ t.vertex3.point = final_mat * t.vertex3.point;
fb.draw_triangle(t);
}
@@ -285,13 +158,14 @@ int main_graphical() {
SDL_Renderer* renderer = NULL;
SDL_Texture* texture = NULL;
+ // init
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
- fprintf(stderr, "Error: SDL_Init error: %s\n", SDL_GetError());
+ std::cerr << "Error: SDL_Init error: " << SDL_GetError() << std::endl;
return EXIT_FAILURE;
}
window = SDL_CreateWindow("Engine", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL) {
- fprintf(stderr, "Error: SDL_CreateWindow error: %s\n", SDL_GetError());
+ std::cerr << "Error: SDL_CreateWindow error: " << SDL_GetError() << std::endl;
return EXIT_FAILURE;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
@@ -307,14 +181,17 @@ int main_graphical() {
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
bool cont = true;
- while (SDL_WaitEventTimeout(&e, 10)) {
- if (e.type == SDL_QUIT) {
- cont = false;
- }
+ if (SDL_WaitEventTimeout(&e, 10)) {
+ do {
+ if (e.type == SDL_QUIT) {
+ cont = false;
+ }
+ } while (SDL_PollEvent(&e));
}
return cont;
});
+ // terminate
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
@@ -323,29 +200,38 @@ int main_graphical() {
return EXIT_SUCCESS;
}
-int main(int argc, char *argv[]) {
- int mode = MODE_GRAPHICAL;
- for (int i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- if (argv[i][1] == '-') {
- if (strcmp(&argv[i][2], "help") == 0) {
+std::vector<std::string_view> convert_args(int argc, char *argv[]) {
+ std::vector<std::string_view> args(argc);
+ for (int i = 0; i < argc; i++)
+ args[i] = argv[i];
+ return args;
+}
+
+void parse_args(const std::vector<std::string_view>& args, int& mode) {
+ for (auto args_iter = std::next(args.begin()); args_iter != args.end(); args_iter++) {
+ const auto& arg = *args_iter;
+ if (arg.size() >= 1 && arg[0] == '-') {
+ if (arg.size() >= 2 && arg[1] == '-') {
+ auto long_opt = arg.substr(2);
+ if (long_opt == "help") {
mode = MODE_HELP;
- } else if (strcmp(&argv[i][2], "term") == 0) {
+ } else if (long_opt == "term") {
mode = MODE_TERM;
- } else if (strcmp(&argv[i][2], "graphical") == 0) {
+ } else if (long_opt == "graphical") {
mode = MODE_GRAPHICAL;
} else {
- std::cerr << "Error: Unexpected option `--" << &argv[i][2] << "'." << std::endl;
+ std::cerr << "Error: Unexpected option `--" << long_opt << "'." << std::endl;
usage_error_exit();
}
} else {
- if (!argv[i][1]) {
+ std::size_t arg_len = arg.size();
+ if (arg_len == 1) {
std::cerr << "Error: Unexpected argument `-'." << std::endl;
usage_error_exit();
}
- std::size_t arg_len = strlen(&argv[i][1]);
- for (int j = 0; j < arg_len; j++) {
- switch (argv[i][1 + j]) {
+ for (auto arg_iter = std::next(arg.begin()); arg_iter != arg.end(); arg_iter++) {
+ const auto& opt = *arg_iter;
+ switch (opt) {
case 'h':
mode = MODE_HELP;
break;
@@ -356,16 +242,21 @@ int main(int argc, char *argv[]) {
mode = MODE_GRAPHICAL;
break;
default:
- std::cerr << "Error: Unexpected option `-" << argv[i][1] << "'." << std::endl;
+ std::cerr << "Error: Unexpected option `-" << opt << "'." << std::endl;
usage_error_exit();
}
}
}
} else {
- std::cerr << "Error: Unexpected argument `" << argv[i] << "'." << std::endl;
+ std::cerr << "Error: Unexpected argument `" << arg << "'." << std::endl;
usage_error_exit();
}
}
+}
+
+int main(int argc, char *argv[]) {
+ int mode = MODE_GRAPHICAL;
+ parse_args(convert_args(argc, argv), mode);
switch (mode) {
case MODE_HELP:
print_usage(std::cout);
diff --git a/src/math/mat4.cpp b/src/math/mat4.cpp
index 0342fdf..ece42d8 100644
--- a/src/math/mat4.cpp
+++ b/src/math/mat4.cpp
@@ -12,6 +12,23 @@ Mat4 Mat4::idty() {
};
}
+Mat4 Mat4::translate(MathVector3 v) {
+ return {
+ 1.f, 0.f, 0.f, v.x,
+ 0.f, 1.f, 0.f, v.y,
+ 0.f, 0.f, 1.f, v.z,
+ 0.f, 0.f, 0.f, 1.f,
+ };
+}
+Mat4 Mat4::scale(float fac) {
+ return {
+ fac, 0.f, 0.f, 0.f,
+ 0.f, fac, 0.f, 0.f,
+ 0.f, 0.f, fac, 0.f,
+ 0.f, 0.f, 0.f, 1.f,
+ };
+}
+
Mat4 Mat4::rot_x(float a) {
float c = std::cos(a);
float s = std::sin(a);
@@ -45,6 +62,19 @@ Mat4 Mat4::rot_z(float a) {
};
}
+Mat4 Mat4::projection(float aspect_ratio, float min_z, float max_z) {
+ return {{
+ aspect_ratio, 0.f, 0.f, 0.f,
+ 0.f, -1.f, 0.f, 0.f,
+ 0.f, 0.f, -2.f / (max_z - min_z), -(max_z + min_z) / (max_z - min_z),
+ 0.f, 0.f, -1.f, 0.f,
+ }};
+}
+
+Mat4 Mat4::operator+() {
+ return *this;
+}
+
Mat4 Mat4::operator-() {
return {
-values[ 0], -values[ 1], -values[ 2], -values[ 3],
@@ -96,3 +126,12 @@ std::array<MathVector4, 4> Mat4::to_vecs() {
{ values[ 3], values[ 7], values[11], values[15] },
}};
}
+
+Mat4 operator*(float fac, Mat4 m) {
+ return {
+ fac * m.values[ 0], fac * m.values[ 1], fac * m.values[ 2], fac * m.values[ 3],
+ fac * m.values[ 4], fac * m.values[ 5], fac * m.values[ 6], fac * m.values[ 7],
+ fac * m.values[ 8], fac * m.values[ 9], fac * m.values[10], fac * m.values[11],
+ fac * m.values[12], fac * m.values[13], fac * m.values[14], fac * m.values[15],
+ };
+}
diff --git a/src/math/mat4.h b/src/math/mat4.h
index d81da63..6df9d49 100644
--- a/src/math/mat4.h
+++ b/src/math/mat4.h
@@ -7,12 +7,16 @@
class Mat4 {
public:
static Mat4 idty();
+ static Mat4 translate(MathVector3 v);
+ static Mat4 scale(float fac);
static Mat4 rot_x(float a);
static Mat4 rot_y(float a);
static Mat4 rot_z(float a);
+ static Mat4 projection(float aspect_ratio, float min_z, float max_z);
std::array<float, 16> values;
+ Mat4 operator+();
Mat4 operator-();
Mat4 operator+(Mat4 m);
Mat4 operator-(Mat4 m);
@@ -21,4 +25,6 @@ class Mat4 {
std::array<MathVector4, 4> to_vecs();
};
+Mat4 operator*(float fac, Mat4 m);
+
#endif // MATH_MAT4_H
diff --git a/src/o3d/obj3d.cpp b/src/o3d/obj3d.cpp
index 46f4db6..584e304 100644
--- a/src/o3d/obj3d.cpp
+++ b/src/o3d/obj3d.cpp
@@ -34,6 +34,29 @@ Object3D::TriangleVertex3Iterator::reference Object3D::TriangleVertex3Iterator::
};
}
+Object3D Object3D::cube() {
+ return {
+ {
+ { MathVector3(-1.f, -1.f, -1.f), {} },
+ { MathVector3(+1.f, -1.f, -1.f), {} },
+ { MathVector3(-1.f, +1.f, -1.f), {} },
+ { MathVector3(+1.f, +1.f, -1.f), {} },
+ { MathVector3(-1.f, -1.f, +1.f), {} },
+ { MathVector3(+1.f, -1.f, +1.f), {} },
+ { MathVector3(-1.f, +1.f, +1.f), {} },
+ { MathVector3(+1.f, +1.f, +1.f), {} },
+ },
+ {
+ { 0, 2, 3 }, { 0, 3, 1 }, // face 1
+ { 0, 4, 6 }, { 0, 6, 2 }, // face 2
+ { 0, 1, 5 }, { 0, 5, 4 }, // face 3
+ { 7, 6, 4 }, { 7, 4, 5 }, // face 4
+ { 7, 3, 2 }, { 7, 2, 6 }, // face 5
+ { 7, 5, 1 }, { 7, 1, 3 }, // face 6
+ }
+ };
+}
+
Object3D::Object3D(std::vector<Vertex3> pts, std::vector<std::array<int, 3>> faces) : pts{pts}, faces{faces} {
}
diff --git a/src/o3d/obj3d.h b/src/o3d/obj3d.h
index 559ed63..c65a06b 100644
--- a/src/o3d/obj3d.h
+++ b/src/o3d/obj3d.h
@@ -30,6 +30,8 @@ class Object3D {
};
+ static Object3D cube(); // this function should not be in this file
+
Object3D(std::vector<Vertex3> pts, std::vector<std::array<int, 3>> faces);
TriangleVertex3Iterator begin();
TriangleVertex3Iterator end();