diff --git a/src/debug_scene.zig b/src/debug_scene.zig index 374a903..70eba32 100644 --- a/src/debug_scene.zig +++ b/src/debug_scene.zig @@ -69,15 +69,33 @@ pub fn init(controller: *Controller, graphics: *Graphics) !void { pub fn deinit() void {} -pub fn update(cube: *Cube, mouse: *Game.Mouse, graphics: *Graphics) void { +pub fn update( + mouse: *Game.Mouse, + keyboard: *Game.Keyboard, + graphics: *Graphics, + time: *Game.Time, +) void { + if (keyboard.is_pressed(sdl.SCANCODE_W)) { + graphics.camera.transform.translateLocal(.{ 0.0, 0.0, 5.0 * time.delta }); + } + if (keyboard.is_pressed(sdl.SCANCODE_S)) { + graphics.camera.transform.translateLocal(.{ 0.0, 0.0, -5.0 * time.delta }); + } + if (keyboard.is_pressed(sdl.SCANCODE_D)) { + graphics.camera.transform.translateLocal(.{ 5.0 * time.delta, 0.0, 0.0 }); + } + if (keyboard.is_pressed(sdl.SCANCODE_A)) { + graphics.camera.transform.translateLocal(.{ -5.0 * time.delta, 0.0, 0.0 }); + } + if (@abs(mouse.dx) < 0.01 and @abs(mouse.dy) < 0.01) return; - const delta, const length = Graphics.Transform.extractNormal(.{ -mouse.dy, -mouse.dx, 0.0 }); + const delta, const length = Graphics.Transform.extractNormal(.{ mouse.dy, mouse.dx, 0.0 }); const rot = Graphics.Transform.rotationByAxis( delta, length * std.math.pi / @as(f32, @floatFromInt(graphics.window_size[1])) * 2.0, ); - cube.transform.rotate(rot); + graphics.camera.transform.rotateLocal(rot); } pub fn draw(cube: *Cube, graphics: *Graphics) !void { diff --git a/src/game.zig b/src/game.zig index ccb5999..83ad00b 100644 --- a/src/game.zig +++ b/src/game.zig @@ -9,8 +9,10 @@ const Graphics = @import("graphics.zig"); // TODO: // - Do something about deallocating `Resource`s when `Graph` fails -const RunInfo = struct { running: bool }; -pub const Mouse = struct { x: f32, y: f32, dx: f32, dy: f32 }; +pub const RunInfo = struct { running: bool }; +pub const Mouse = @import("mouse.zig"); +pub const Keyboard = @import("keyboard.zig"); +pub const Time = @import("time.zig"); alloc: std.mem.Allocator, graph: Graph, @@ -30,6 +32,11 @@ pub fn init(alloc: std.mem.Allocator) GameError!Self { .dx = 0.0, .dy = 0.0, }); + controller.addResource(Keyboard{}); + controller.addResource(Time{ + .delta = 0.0, + .now = 0, + }); controller.queue(debug_scene.init); try graph.freeController(controller); @@ -54,6 +61,13 @@ pub fn run(self: *Self) GameError!void { break; } + var current_time: sdl.Time = undefined; + if (sdl.GetCurrentTime(¤t_time)) { + const time = self.graph.getResource(Time).?; + time.delta = @as(f32, @floatFromInt(current_time - time.now)) * 0.000000001; + time.now = current_time; + } + var controller = try self.graph.getController(); controller.queue(.{ .events = processEvents, @@ -84,9 +98,15 @@ fn clean(graphics: *Graphics) !void { // TODO: Also remove the resource } -fn processEvents(graphics: *Graphics, run_info: *RunInfo, mouse: *Mouse) GameError!void { +fn processEvents( + graphics: *Graphics, + run_info: *RunInfo, + mouse: *Mouse, + keyboard: *Keyboard, +) GameError!void { mouse.dx = 0.0; mouse.dy = 0.0; + keyboard.reset(); sdl.PumpEvents(); while (true) { @@ -109,6 +129,14 @@ fn processEvents(graphics: *Graphics, run_info: *RunInfo, mouse: *Mouse) GameErr mouse.dx += event.motion.xrel; mouse.dy += event.motion.yrel; }, + sdl.EVENT_KEY_DOWN => { + if (event.key.windowID != sdl.GetWindowID(graphics.window)) continue; + keyboard.press(event.key.scancode); + }, + sdl.EVENT_KEY_UP => { + if (event.key.windowID != sdl.GetWindowID(graphics.window)) continue; + keyboard.release(event.key.scancode); + }, else => {}, } } diff --git a/src/graphics/transform.zig b/src/graphics/transform.zig index 3d925a4..d972173 100644 --- a/src/graphics/transform.zig +++ b/src/graphics/transform.zig @@ -13,6 +13,7 @@ scale: Scale = @splat(1.0), pub fn matrix(transform: Transform) TMatrix { @setFloatMode(.optimized); + const r = rotationMatrix(transform.rotation); const sx, const sy, const sz = transform.scale; return .{ @@ -25,6 +26,7 @@ pub fn matrix(transform: Transform) TMatrix { pub fn inverseMatrix(transform: Transform) TMatrix { @setFloatMode(.optimized); + const r = rotationMatrix(flipRotation(transform.rotation)); const tx, const ty, const tz = transform.position; const sx = 1.0 / transform.scale[0]; @@ -47,11 +49,49 @@ pub fn inverseMatrix(transform: Transform) TMatrix { }; } +pub fn translate(transform: *Transform, translation: Position) void { + @setFloatMode(.optimized); + + transform.position += translation; +} + +pub fn translateLocal(transform: *Transform, translation: Position) void { + @setFloatMode(.optimized); + + const a = transform.rotation[0]; + const b = transform.rotation[1]; + const c = transform.rotation[2]; + const d = transform.rotation[3]; + + const s = 2.0 / (a * a + b * b + c * c + d * d); + const bs = b * s; + const cs = c * s; + const ds = d * s; + + const ab = a * bs; + const ac = a * cs; + const ad = a * ds; + const bb = b * bs; + const bc = b * cs; + const bd = b * ds; + const cc = c * cs; + const cd = c * ds; + const dd = d * ds; + + transform.position[0] += translation[0] * (1 - cc - dd) + translation[1] * (bc - ad) + translation[2] * (bd + ac); + transform.position[1] += translation[0] * (bc + ad) + translation[1] * (1 - bb - dd) + translation[2] * (cd - ab); + transform.position[2] += translation[0] * (bd - ac) + translation[1] * (cd + ab) + translation[2] * (1 - bb - cc); +} + pub fn rotate(transform: *Transform, rotation: Rotation) void { + @setFloatMode(.optimized); + transform.rotation = normalizeRotation(combineRotations(transform.rotation, rotation)); } pub fn rotateLocal(transform: *Transform, rotation: Rotation) void { + @setFloatMode(.optimized); + transform.rotation = normalizeRotation(combineRotations(rotation, transform.rotation)); } diff --git a/src/keyboard.zig b/src/keyboard.zig new file mode 100644 index 0000000..a35eb96 --- /dev/null +++ b/src/keyboard.zig @@ -0,0 +1,69 @@ +const sdl = @import("sdl"); + +const BUFFER_SIZE = 16; +const ZERO = sdl.SCANCODE_UNKNOWN; + +just_pressed: [BUFFER_SIZE]sdl.Scancode = .{ZERO} ** BUFFER_SIZE, +pressed: [BUFFER_SIZE]sdl.Scancode = .{ZERO} ** BUFFER_SIZE, +just_released: [BUFFER_SIZE]sdl.Scancode = .{ZERO} ** BUFFER_SIZE, + +const Self = @This(); +pub fn reset(self: *Self) void { + self.just_pressed = .{ZERO} ** BUFFER_SIZE; + self.just_released = .{ZERO} ** BUFFER_SIZE; +} +pub fn press(self: *Self, code: sdl.Scancode) void { + for (self.pressed) |pressed| { + if (pressed == code) return; + } + for (&self.pressed) |*pressed| { + if (pressed.* == ZERO) { + pressed.* = code; + break; + } + } + for (self.just_pressed) |just_pressed| { + if (just_pressed == code) return; + } + for (&self.just_pressed) |*just_pressed| { + if (just_pressed.* == ZERO) { + just_pressed.* = code; + break; + } + } +} +pub fn release(self: *Self, code: sdl.Scancode) void { + for (&self.pressed) |*pressed| { + if (pressed.* == code) { + pressed.* = ZERO; + break; + } + } + for (self.just_released) |just_released| { + if (just_released == code) return; + } + for (&self.just_released) |*just_released| { + if (just_released.* == ZERO) { + just_released.* = code; + break; + } + } +} +pub fn is_just_pressed(self: *Self, code: sdl.Scancode) bool { + for (self.just_pressed) |just_pressed| { + if (just_pressed == code) return true; + } + return false; +} +pub fn is_pressed(self: *Self, code: sdl.Scancode) bool { + for (self.pressed) |pressed| { + if (pressed == code) return true; + } + return false; +} +pub fn is_just_released(self: *Self, code: sdl.Scancode) bool { + for (self.just_released) |just_released| { + if (just_released == code) return true; + } + return false; +} diff --git a/src/mouse.zig b/src/mouse.zig new file mode 100644 index 0000000..32e7a8a --- /dev/null +++ b/src/mouse.zig @@ -0,0 +1,4 @@ +x: f32, +y: f32, +dx: f32, +dy: f32, diff --git a/src/time.zig b/src/time.zig new file mode 100644 index 0000000..b040cac --- /dev/null +++ b/src/time.zig @@ -0,0 +1,4 @@ +const sdl = @import("sdl"); + +delta: f32, +now: sdl.Time,