aboutsummaryrefslogtreecommitdiff
path: root/src/engine.cpp
diff options
context:
space:
mode:
authorvimene <vincent.menegaux@gmail.com>2024-12-31 03:40:14 +0100
committervimene <vincent.menegaux@gmail.com>2024-12-31 03:40:14 +0100
commitcc6fb8c33637566a7b116d46440e6063f016deea (patch)
tree5cc83f84525507994add57df7dd974e6611d675a /src/engine.cpp
parent6b765a85cf81bf4b7162e4c9280dd4054581c611 (diff)
downloadengine-cc6fb8c33637566a7b116d46440e6063f016deea.tar.gz
various improvements
- added quaternions and rewrote all rotations to use them - added transforms to put all object transforms in a single place - added Wavefront .obj file parser - removed frame buffer's abstract class - improved vectors, matrices, triangles, vertices and vertices data by putting all code in header file - added vector's operations - changed from NULL to nullptr - miscellaneous improvements
Diffstat (limited to 'src/engine.cpp')
-rw-r--r--src/engine.cpp115
1 files changed, 65 insertions, 50 deletions
diff --git a/src/engine.cpp b/src/engine.cpp
index e8cde92..c484b0d 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -13,6 +13,7 @@
#include <memory>
#include <utility>
#include <SDL.h>
+#include <numbers>
#ifdef ENABLE_NCURSES
#include <ncurses.h>
@@ -28,7 +29,22 @@
#include "o3d/camera.h"
#include "math/vector.h"
#include "math/mat4.h"
+#include "math/quat.h"
+#include "math/tform.h"
#include "renderer.h"
+#include "obj_parser.h"
+
+using
+ engine::Renderer,
+ engine::fb::CharacterFrameBuffer,
+ engine::fb::PixelFrameBuffer,
+ engine::o3d::Scene,
+ engine::o3d::Mesh,
+ engine::o3d::Triangle,
+ engine::math::Vector3,
+ engine::math::Vector4,
+ engine::math::Matrix4,
+ engine::math::Quaternion;
#define FPS 60
@@ -52,49 +68,55 @@ static void usage_error_exit() {
std::exit(EXIT_FAILURE);
}
-static void scene_main(engine::Renderer& renderer, engine::math::Matrix4 final_transform_mat, std::function<bool()> update_frame) {
+extern Quaternion camera_quat;
+Quaternion camera_quat = Quaternion::one();
+
+template<typename FrameBuffer, typename UpdateFrameFn>
+static void scene_main(Renderer<FrameBuffer>& renderer, const Matrix4& final_transform_mat, UpdateFrameFn update_frame) {
float dist = 1.5f;
float rad = 5.f;
bool cont = true;
- engine::o3d::Scene scene{
- {{0.f, 0.f, rad * dist}, 0.f, 0.f, 0.f}, // camera
- { // objects
- engine::o3d::Object3D{
- engine::o3d::Mesh::plane(),
- -rad * engine::math::Vector3(.5f, .5f, .5f),
- rad, 0.f, 0.f, 0.f
+ Scene scene{
+ {{{0.f, 0.f, rad * dist}, {1.f, 0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}}},
+ {
+ // {
+ // Mesh::plane(),
+ // {
+ // Vector3(0.f, 0.f, 0.f),
+ // {1.f, 0.f, 0.f, 0.f},
+ // Vector3(rad, rad, rad),
+ // }
+ // },
+ {
+ engine::parse_object("../assets/suzanne.obj"),
+ {
+ Vector3(0.f, 0.f, 0.f),
+ {1.f, 0.f, 0.f, 0.f},
+ Vector3(rad, rad, rad),
+ }
},
}
};
- auto scale_mat = engine::math::Matrix4::scale(rad);
+ float mul_angle = 0.f;
while (cont) {
- scene.camera.rot_x += .0050f;
- scene.camera.rot_y += .0065f;
- scene.camera.rot_z += .0080f;
+ camera_quat = Quaternion::euler_zyx(mul_angle * .0050f, mul_angle * .0065f, mul_angle * .0080f);
+ mul_angle += 1.f;
+ scene.camera.transform.rot = camera_quat;
renderer.clear();
- auto transform_mat =
- engine::math::Matrix4::translate(-scene.camera.loc)
- * engine::math::Matrix4::rot_x(-scene.camera.rot_x)
- * engine::math::Matrix4::rot_y(-scene.camera.rot_y)
- * engine::math::Matrix4::rot_z(-scene.camera.rot_z);
- std::array<engine::math::Matrix4, 1> mats{{
- transform_mat * scale_mat,
- }};
auto pre_final_mat = final_transform_mat
- * engine::math::Matrix4::projection(static_cast<float>(renderer.height()) / static_cast<float>(renderer.width()), 2.f, 50.f);
- for (int i = 0; i < 1; i++) {
- auto final_mat = pre_final_mat * mats[i];
- const auto& mesh = scene.objs[i].mesh;
- std::vector<engine::math::Vector4> vertices;
+ * Matrix4::projection(static_cast<float>(renderer.height()) / static_cast<float>(renderer.width()), 2.f, 50.f)
+ * scene.camera.transform.opposite().to_mat4();
+ for (const auto& obj : scene.objs) {
+ auto final_mat = pre_final_mat * obj.transform.to_mat4();
+ const auto& mesh = obj.mesh;
+ std::vector<Vector4> vertices;
for (const auto& vertex : mesh.vertices)
vertices.push_back(final_mat * vertex);
- for (auto triangle_indices : mesh.indices) {
- renderer.draw_triangle({
- {vertices[triangle_indices[0][0]], mesh.normals[triangle_indices[0][1]], mesh.vertices_data[triangle_indices[0][2]]},
- {vertices[triangle_indices[1][0]], mesh.normals[triangle_indices[1][1]], mesh.vertices_data[triangle_indices[1][2]]},
- {vertices[triangle_indices[2][0]], mesh.normals[triangle_indices[2][1]], mesh.vertices_data[triangle_indices[2][2]]},
- });
+ for (const auto& triangle_indices : mesh.indices) {
+ [&]<std::size_t... j>(std::integer_sequence<std::size_t, j...>) {
+ renderer.draw_triangle({{vertices[triangle_indices[j][0]], mesh.normals[triangle_indices[j][1]], mesh.vertices_data[triangle_indices[j][2]]}...});
+ }(std::make_integer_sequence<std::size_t, 3>());
}
}
cont = update_frame();
@@ -122,13 +144,10 @@ static int main_term() {
int w, h;
getmaxyx(stdscr, h, w);
- engine::Renderer renderer{
- std::make_unique<engine::fb::CharacterFrameBuffer>(static_cast<unsigned int>(w), static_cast<unsigned int>(h))};
+ Renderer<CharacterFrameBuffer> renderer{CharacterFrameBuffer{static_cast<unsigned int>(w), static_cast<unsigned int>(h)}};
- scene_main(renderer, engine::math::Matrix4::scale(engine::math::Vector3(2.f, 1.f, 1.f)), [&]() {
- mvaddnstr(0, 0,
- static_cast<engine::fb::CharacterFrameBuffer*>(renderer.fb.get())->chars(),
- renderer.width() * renderer.height());
+ scene_main(renderer, Matrix4::scale(Vector3(2.f, 1.f, 1.f)), [&]() {
+ mvaddnstr(0, 0, renderer.fb.chars(), renderer.width() * renderer.height());
bool cont = true;
//timeout(1000 / FPS);
@@ -176,9 +195,9 @@ static int main_term() {
#define SCREEN_HEIGHT 480
static int main_graphical() {
- SDL_Window* window = NULL;
- SDL_Renderer* renderer = NULL;
- SDL_Texture* texture = NULL;
+ SDL_Window* window = nullptr;
+ SDL_Renderer* renderer = nullptr;
+ SDL_Texture* texture = nullptr;
// init
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
@@ -186,24 +205,21 @@ static int main_graphical() {
return EXIT_FAILURE;
}
window = SDL_CreateWindow("Engine", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
- if (window == NULL) {
+ if (window == nullptr) {
SDL_Quit();
std::cerr << "Error: SDL_CreateWindow error: " << SDL_GetError() << std::endl;
return EXIT_FAILURE;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT);
- engine::Renderer engine_renderer{
- std::make_unique<engine::fb::PixelFrameBuffer>(SCREEN_WIDTH, SCREEN_HEIGHT)};
+ Renderer<PixelFrameBuffer> engine_renderer{PixelFrameBuffer{SCREEN_WIDTH, SCREEN_HEIGHT}};
SDL_Event e;
- scene_main(engine_renderer, engine::math::Matrix4::idty(), [&]() {
- SDL_UpdateTexture(texture, NULL,
- static_cast<engine::fb::PixelFrameBuffer*>(engine_renderer.fb.get())->pixels(),
- SCREEN_WIDTH * 4);
+ scene_main(engine_renderer, Matrix4::idty(), [&]() {
+ SDL_UpdateTexture(texture, nullptr, engine_renderer.fb.pixels(), SCREEN_WIDTH * 4);
SDL_RenderClear(renderer);
- SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderCopy(renderer, texture, nullptr, nullptr);
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
bool cont = true;
@@ -297,7 +313,6 @@ int main(int argc, char *argv[]) {
case MODE_GRAPHICAL:
return main_graphical();
default:
- ; // unreachable
+ std::unreachable();
}
- return EXIT_SUCCESS; // unreachable
}