diff options
author | vimene <vincent.menegaux@gmail.com> | 2025-01-02 13:25:14 +0100 |
---|---|---|
committer | vimene <vincent.menegaux@gmail.com> | 2025-01-02 13:25:14 +0100 |
commit | 26b4b82a7be2c029491f3009b66b3cbf8db5d93c (patch) | |
tree | ddc247a0600b5933185677212f158ebea5a87530 /src/engine.cpp | |
parent | 9fdb5881d46f5d80626f961f9c9f133cc25dab70 (diff) | |
download | engine-26b4b82a7be2c029491f3009b66b3cbf8db5d93c.tar.gz |
various improvements
- cleaned up the computation of the camera's matrix
- changed VertexData to being a struct which transmit data between the "vertex shader" and the "fragment shader"
- started working on keyboard and mouse controls
- added fov (field of view)
- changed quaternion to euler angles conversion, from zyx to zxy
- fixed computations of z coordinates in triangle rendering
- improved naming in the triangle rasterizer
Diffstat (limited to 'src/engine.cpp')
-rw-r--r-- | src/engine.cpp | 142 |
1 files changed, 116 insertions, 26 deletions
diff --git a/src/engine.cpp b/src/engine.cpp index 9b2f673..0d99578 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -41,6 +41,8 @@ using engine::o3d::Scene, engine::o3d::Mesh, engine::o3d::Triangle, + engine::o3d::Camera, + engine::o3d::VertexData, engine::math::Vector3, engine::math::Vector4, engine::math::Matrix4, @@ -54,6 +56,12 @@ using #define MODE_TERM 1 #define MODE_GRAPHICAL 2 +#define GAME_PLANE 0 +#define GAME_SUZANNE 1 +#define GAME_PHYSICS 2 + +#define GAME GAME_PHYSICS + static void print_usage(std::ostream& output_stream) { output_stream << "Usage: ./engine [-htg] [--help] [--term] [--graphical]\n" << " -h, --help show usage (this)\n" @@ -68,61 +76,77 @@ static void usage_error_exit() { std::exit(EXIT_FAILURE); } -extern Quaternion camera_quat; -Quaternion camera_quat = Quaternion::one(); +extern Camera* camera; +Camera* camera; 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; Scene scene{ - {{{0.f, 0.f, rad * dist}, {1.f, 0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}}}, + {90.f * PI / 180.f, {{0.f, 1.8f, 7.f}, Quaternion::one(), {1.f, 1.f, 1.f}}}, { -#if 0 +#if GAME == GAME_PLANE { - Mesh::plane(), + Mesh::plane(2.f, 2.f), { Vector3(0.f, 0.f, 0.f), - {1.f, 0.f, 0.f, 0.f}, - Vector3(rad, rad, rad), + Quaternion::one(), + Vector3(1.f, 1.f, 1.f), } }, -#else +#elif GAME == GAME_SUZANNE { 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), + Quaternion::one(), + Vector3(1.f, 1.f, 1.f), + } + }, +#elif GAME == GAME_PHYSICS + { + Mesh::plane(10.f, 10.f), + { + Vector3(0.f, 0.f, 0.f), + Quaternion::one(), + Vector3(1.f, 1.f, 1.f), + } + }, + { + engine::parse_object("../assets/suzanne.obj"), + { + Vector3(0.f, 1.f, 0.f), + Quaternion::one(), + Vector3(1.f, 1.f, 1.f), } }, #endif } }; - float mul_angle = 0.f; - while (cont) { - camera_quat = Quaternion::euler_zyx(mul_angle * .0050f, mul_angle * .0065f, mul_angle * .0080f); - mul_angle += 1.f; - scene.camera.transform.rot = camera_quat; + camera = &scene.camera; + + while (cont) { renderer.clear(); auto pre_final_mat = final_transform_mat - * Matrix4::projection(static_cast<float>(renderer.height()) / static_cast<float>(renderer.width()), 2.f, 50.f) - * scene.camera.transform.opposite().to_mat4(); + * scene.camera.to_mat4(static_cast<float>(renderer.height()) / static_cast<float>(renderer.width()), .5f, 12.f); for (const auto& obj : scene.objs) { - auto final_mat = pre_final_mat * obj.transform.to_mat4(); + auto obj_mat = obj.transform.to_mat4(); + auto final_mat = pre_final_mat * obj_mat; const auto& mesh = obj.mesh; std::vector<Vector4> vertices; - for (const auto& vertex : mesh.vertices) + std::vector<VertexData> vertices_data; + for (const auto& vertex : mesh.vertices) { vertices.push_back(final_mat * vertex); + vertices_data.push_back(VertexData((obj_mat * vertex).xyz())); + } 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]]}...}); + renderer.draw_triangle({{vertices[triangle_indices[j][0]], mesh.normals[triangle_indices[j][1]], vertices_data[triangle_indices[j][0]]}...}); }(std::make_integer_sequence<std::size_t, 3>()); } } - cont = update_frame(); + cont = update_frame(scene); } } @@ -149,7 +173,8 @@ static int main_term() { getmaxyx(stdscr, h, w); Renderer<CharacterFrameBuffer> renderer{CharacterFrameBuffer{static_cast<unsigned int>(w), static_cast<unsigned int>(h)}}; - scene_main(renderer, Matrix4::scale(Vector3(2.f, 1.f, 1.f)), [&]() { + scene_main(renderer, Matrix4::scale(Vector3(2.f, 1.f, 1.f)), [&](Scene& scene) { + (void) scene; mvaddnstr(0, 0, renderer.fb.chars(), renderer.width() * renderer.height()); bool cont = true; @@ -219,20 +244,85 @@ static int main_graphical() { SDL_Event e; - scene_main(engine_renderer, Matrix4::idty(), [&]() { + float rx = 0.f, ry = 0.f; + bool fw_down = false, left_down = false, bw_down = false, right_down = false, zoom_down = false; + + scene_main(engine_renderer, Matrix4::idty(), [&](Scene& scene) { + (void) scene; SDL_UpdateTexture(texture, nullptr, engine_renderer.fb.pixels(), SCREEN_WIDTH * 4); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_RenderPresent(renderer); SDL_UpdateWindowSurface(window); + SDL_SetRelativeMouseMode(SDL_TRUE); bool cont = true; if (SDL_WaitEventTimeout(&e, 10)) { do { - if (e.type == SDL_QUIT) { + switch (e.type) { + case SDL_QUIT: cont = false; + break; + case SDL_KEYDOWN: + switch (e.key.keysym.sym) { + case SDLK_z: + fw_down = true; + break; + case SDLK_q: + left_down = true; + break; + case SDLK_s: + bw_down = true; + break; + case SDLK_d: + right_down = true; + break; + case SDLK_LCTRL: + zoom_down = true; + break; + } + break; + case SDL_KEYUP: + switch (e.key.keysym.sym) { + case SDLK_z: + fw_down = false; + break; + case SDLK_q: + left_down = false; + break; + case SDLK_s: + bw_down = false; + break; + case SDLK_d: + right_down = false; + break; + case SDLK_LCTRL: + zoom_down = false; + break; + case SDLK_ESCAPE: + cont = false; + break; + } + break; + case SDL_MOUSEMOTION: + rx += -static_cast<float>(e.motion.yrel) * .01f; + ry += -static_cast<float>(e.motion.xrel) * .01f; + if (rx < -PI / 2.f) rx = -PI / 2.f; + if (rx > PI / 2.f) rx = PI / 2.f; + scene.camera.transform.rot = Quaternion::euler_zxy(rx, ry, 0.f); + break; } } while (SDL_PollEvent(&e)); } + + Vector3 movement(0.f, 0.f, 0.f); + if (fw_down) movement.z += -1.f; + if (left_down) movement.x += -1.f; + if (bw_down) movement.z += +1.f; + if (right_down) movement.x += +1.f; + if (fw_down || left_down || bw_down || right_down) movement.normalize(); + scene.camera.transform.loc += movement.rot(Quaternion::rot_y(ry)) * .05f; + scene.camera.fov = (zoom_down ? 40.f : 80.f) * PI / 180.f; + return cont; }); |