diff --git a/src/base/base_inc.c b/src/base/base_inc.c index 71f2db1..36fd6b4 100644 --- a/src/base/base_inc.c +++ b/src/base/base_inc.c @@ -1,3 +1,5 @@ // clang-format off +#include "base_math.c" + // clang-format on diff --git a/src/base/base_math.c b/src/base/base_math.c new file mode 100644 index 0000000..f5c56d4 --- /dev/null +++ b/src/base/base_math.c @@ -0,0 +1,20 @@ +Vec3F32 vec3f32_rotate_x(Vec3F32 vector, float new_angle) { + Vec3F32 rotated_vector = {.x = vector.x, + .y = vector.y * cos(new_angle) - vector.z * sin(new_angle), + .z = vector.y * sin(new_angle) + vector.z * cos(new_angle)}; + return rotated_vector; +} + +Vec3F32 vec3f32_rotate_y(Vec3F32 vector, float new_angle) { + Vec3F32 rotated_vector = {.x = vector.x * cos(new_angle) - vector.z * sin(new_angle), + .y = vector.y, + .z = vector.x * sin(new_angle) + vector.z * cos(new_angle)}; + return rotated_vector; +} + +Vec3F32 vec3f32_rotate_z(Vec3F32 vector, float new_angle) { + Vec3F32 rotated_vector = {.x = vector.x * cos(new_angle) - vector.y * sin(new_angle), + .y = vector.x * sin(new_angle) + vector.y * cos(new_angle), + .z = vector.z}; + return rotated_vector; +} diff --git a/src/base/base_math.h b/src/base/base_math.h index 056d36c..e34adcc 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -20,4 +20,8 @@ union Vec3F32 { f32 v[2]; }; +Vec3F32 vec3f32_rotate_x(Vec3F32 vector, float angle); +Vec3F32 vec3f32_rotate_y(Vec3F32 vector, float angle); +Vec3F32 vec3f32_rotate_z(Vec3F32 vector, float angle); + #endif // BASE_MATH_H diff --git a/src/ragar/ragar_main.c b/src/ragar/ragar_main.c index 75fb1a5..59a6af7 100644 --- a/src/ragar/ragar_main.c +++ b/src/ragar/ragar_main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,20 +6,21 @@ #include "base/base_inc.h" #include "renderer/display.h" +#include "base/base_inc.c" #include "renderer/display.c" #define POINTS (9 * 9 * 9) Vec3F32 cube_points[POINTS]; Vec2F32 g_projected_points[POINTS]; Vec3F32 camera_position = {.x = 0, .y = 0, .z = -5}; +Vec3F32 cube_rotation = {.x = 0, .y = 0, .z = 0}; int is_running; -// Perspective Projection -// Perspective divide formula -// P'x = Px/Pz -// -// P'y = Py/Pz +// Perspective Projection (perspective divide) +// Formula +// P'x = Px/Pz +// P'y = Py/Pz Vec2F32 perspective_projection(Vec3F32 points) { Vec2F32 projected_point = {.x = (field_of_view_factor * points.x) / points.z, .y = (field_of_view_factor * points.y) / points.z}; @@ -67,14 +69,23 @@ void process_input(void) { } void update(void) { + cube_rotation.x += 0.01; + cube_rotation.y += 0.01; + cube_rotation.z += 0.01; + for (s32 i = 0; i < POINTS; i++) { Vec3F32 point = cube_points[i]; - // Move things away from the camera - point.z -= camera_position.z; + // Transform points + Vec3F32 transformed_points = vec3f32_rotate_x(point, cube_rotation.x); + transformed_points = vec3f32_rotate_y(transformed_points, cube_rotation.y); + transformed_points = vec3f32_rotate_z(transformed_points, cube_rotation.z); - // Project the current point - Vec2F32 projected_point = perspective_projection(point); + // Translate points away from the camera + transformed_points.z -= camera_position.z; + + // Project the transformed point + Vec2F32 projected_point = perspective_projection(transformed_points); // Save the projected 2D vector in the global array of projected points g_projected_points[i] = projected_point; @@ -87,7 +98,7 @@ void render(void) { // Loop through all projected points and render them for (u32 i = 0; i < POINTS; i++) { Vec2F32 projected_point = g_projected_points[i]; - draw_rect(projected_point.x + (window_width / 2), projected_point.y + (window_height / 2), 4, 4, 0xFFFFFF00); + draw_rect(projected_point.x + (window_width / 2), projected_point.y + (window_height / 2), 4, 4, 0xFF659F00); } render_colour_buffer(); diff --git a/src/renderer/display.c b/src/renderer/display.c index 03d5f82..1f6da68 100644 --- a/src/renderer/display.c +++ b/src/renderer/display.c @@ -4,14 +4,15 @@ int initialize_window(void) { return false; } - // NOTE(tijani): Query screen size for fullscreen - // SDL_DisplayMode display_mode; - // SDL_GetCurrentDisplayMode(0, &display_mode); // NOTE(tijani): second screen instead of main one - // window_width = display_mode.w; - // window_height = display_mode.h; + // NOTE(tijani): Query screen size for fullscreen, this is important as not doing so + // will make everything compressed and not scale properly. + SDL_DisplayMode display_mode; + SDL_GetCurrentDisplayMode(0, &display_mode); // NOTE(tijani): second screen instead of main one + window_width = display_mode.w; + window_height = display_mode.h; window = SDL_CreateWindow("Ragar: 3D Software Renderer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, - window_height, 0); + window_height, SDL_WINDOW_FULLSCREEN_DESKTOP); if (!window) { fprintf(stderr, "SDL could not create a window.\n"); return false; diff --git a/src/renderer/display.h b/src/renderer/display.h index 0e53977..bef3d8b 100644 --- a/src/renderer/display.h +++ b/src/renderer/display.h @@ -7,8 +7,8 @@ SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; SDL_Texture *colour_buffer_texture = NULL; -global s32 window_width = 800; -global s32 window_height = 600; +global s32 window_width = 1080; +global s32 window_height = 1920; global f32 field_of_view_factor = 940; global u32 *colour_buffer;