aboutsummaryrefslogtreecommitdiff
path: root/src/engine.cpp
diff options
context:
space:
mode:
authorvimene <vincent.menegaux@gmail.com>2025-01-02 13:25:14 +0100
committervimene <vincent.menegaux@gmail.com>2025-01-02 13:25:14 +0100
commit26b4b82a7be2c029491f3009b66b3cbf8db5d93c (patch)
treeddc247a0600b5933185677212f158ebea5a87530 /src/engine.cpp
parent9fdb5881d46f5d80626f961f9c9f133cc25dab70 (diff)
downloadengine-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.cpp142
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;
});