const std = @import("std"); const matrix = @import("matrix.zig"); const sdl = @import("sdl.zig"); const Cube = struct { points: [8]Point, }; pub const Point = struct { x: f32, y: f32, z: f32, }; pub fn draw_cube(instance: sdl.instance, cube: Cube) void { sdl.draw_color(instance, 255, 255, 255, 0); sdl.draw_line(instance, cube.points[0], cube.points[1]); sdl.draw_line(instance, cube.points[0], cube.points[2]); sdl.draw_line(instance, cube.points[0], cube.points[4]); sdl.draw_line(instance, cube.points[7], cube.points[6]); sdl.draw_line(instance, cube.points[7], cube.points[5]); sdl.draw_line(instance, cube.points[7], cube.points[3]); sdl.draw_line(instance, cube.points[2], cube.points[3]); sdl.draw_line(instance, cube.points[4], cube.points[5]); sdl.draw_line(instance, cube.points[1], cube.points[5]); sdl.draw_line(instance, cube.points[6], cube.points[2]); sdl.draw_line(instance, cube.points[3], cube.points[1]); sdl.draw_line(instance, cube.points[4], cube.points[6]); } pub fn shift_cube(cube: Cube, x: f32, y: f32, z: f32) Cube { var shifted_cube = Cube{ .points = undefined }; for (cube.points) |point, i| { shifted_cube.points[i].x = point.x + x; shifted_cube.points[i].y = point.y + y; shifted_cube.points[i].z = point.z + z; } return shifted_cube; } pub fn center_cube(cube: Cube, offset: f32) Cube { var centered_cube = Cube{ .points = undefined }; for (cube.points) |point, i| { centered_cube.points[i] = center_point(point, offset); } return centered_cube; } pub fn center_point(point: Point, offset: f32) Point { return Point{ .x = point.x + offset, .y = point.y + offset, .z = 0, }; } pub fn rotate_cube(cube: Cube, alpha: f32, beta: f32) Cube { var rotated_cube = Cube{ .points = undefined }; var a = matrix.new( 3, 3, &[_]f32{ 1, 0, 0, 0, @cos(alpha), @sin(alpha), 0, -@sin(alpha), @cos(alpha), }, ); var b = matrix.new( 3, 3, &[_]f32{ @cos(beta), 0, -@sin(beta), 0, 1, 0, @sin(beta), 0, @cos(beta), }, ); for (cube.points) |point, i| { var m = matrix.multiply( matrix.multiply(a, b), matrix.new(3, 1, &[3]f32{ point.x, point.y, point.z }), ).x.items; rotated_cube.points[i].x = m[0]; rotated_cube.points[i].y = m[1]; rotated_cube.points[i].z = m[2]; } return rotated_cube; } pub fn project_cube(cube: Cube) Cube { var projected_cube = Cube{ .points = undefined }; for (cube.points) |point, i| { projected_cube.points[i] = project_point(point); } return projected_cube; } pub fn project_point(p: Point) Point { var cx = [_]f32{ 1, 0, 0, 0, 1, 0, 0, 0, 0, }; var c = matrix.new(3, 3, &cx); var m = matrix.multiply(c, matrix.new(3, 1, &[3]f32{ p.x, p.y, p.z })).x.items; var projected_point = Point{ .x = m[0], .y = m[1], .z = m[2], }; return projected_point; } pub fn scale_cube(cube: Cube, scale: f32) Cube { var scaled_cube = Cube{ .points = undefined }; for (cube.points) |point, i| { scaled_cube.points[i].x = point.x * scale; scaled_cube.points[i].y = point.y * scale; scaled_cube.points[i].z = point.z * scale; } return scaled_cube; } pub fn draw_axis(instance: sdl.instance) void { var o = center_point( project_point(Point{ .x = 00, .y = 00, .z = 00 }), 250, ); var x = center_point( project_point(Point{ .x = 50, .y = 00, .z = 00 }), 250, ); var y = center_point( project_point(Point{ .x = 00, .y = 50, .z = 00 }), 250, ); var z = center_point( project_point(Point{ .x = 00, .y = 00, .z = 50 }), 250, ); sdl.draw_color(instance, 255, 0, 0, 0); sdl.draw_line(instance, o, x); sdl.draw_color(instance, 0, 255, 0, 0); sdl.draw_line(instance, o, y); sdl.draw_color(instance, 0, 0, 255, 0); sdl.draw_line(instance, o, z); } pub fn main() anyerror!void { var instance = sdl.init(); const unit_cube = Cube{ .points = [8]Point{ Point{ .x = 01, .y = 01, .z = 01 }, Point{ .x = 01, .y = 01, .z = -1 }, Point{ .x = 01, .y = -1, .z = 01 }, Point{ .x = 01, .y = -1, .z = -1 }, Point{ .x = -1, .y = 01, .z = 01 }, Point{ .x = -1, .y = 01, .z = -1 }, Point{ .x = -1, .y = -1, .z = 01 }, Point{ .x = -1, .y = -1, .z = -1 }, }, }; var beta: f32 = 0; var alpha: f32 = 0; while (true) { var event = sdl.get_event(); if (event.mode == sdl.modes.quit) { break; } else if (event.mode == sdl.modes.key) { switch (event.key) { sdl.keys.q => break, else => continue, } } sdl.draw_color(instance, 0, 0, 0, 0); sdl.clear(instance); var cube = rotate_cube(unit_cube, alpha, beta); cube = scale_cube(cube, 50); cube = project_cube(cube); cube = center_cube(cube, 250); draw_cube(instance, cube); cube = rotate_cube(unit_cube, alpha + 90, beta + 90); cube = scale_cube(cube, 25); cube = project_cube(cube); cube = center_cube(cube, 250); draw_cube(instance, cube); cube = shift_cube(unit_cube, 5, 0, 0); cube = rotate_cube(cube, 2 * alpha, 2 * beta); cube = scale_cube(cube, 25); cube = project_cube(cube); cube = center_cube(cube, 250); draw_cube(instance, cube); cube = shift_cube(unit_cube, -5, 0, 0); cube = rotate_cube(cube, 2 * alpha, 2 * beta); cube = scale_cube(cube, 25); cube = project_cube(cube); cube = center_cube(cube, 250); draw_cube(instance, cube); draw_axis(instance); beta += 0.01; alpha += 0.01; sdl.present(instance); sdl.delay(10); } sdl.quit(instance); }