From c985569b30b80dc61c1556c44e5563f6ab0f1eed Mon Sep 17 00:00:00 2001 From: SnekProgrammer Date: Tue, 7 Oct 2025 19:05:37 -0600 Subject: [PATCH 1/2] Added item swing animation --- src/game.zig | 2 +- src/itemdrop.zig | 48 ++++++++++++++++++++++++++++++++++++------------ src/renderer.zig | 15 ++++++++++----- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/game.zig b/src/game.zig index 71ba4b369..3b517de9e 100644 --- a/src/game.zig +++ b/src/game.zig @@ -752,7 +752,7 @@ var biomeFog = Fog{.skyColor = .{0.8, 0.8, 1}, .fogColor = .{0.8, 0.8, 1}, .dens pub var fog = Fog{.skyColor = .{0.8, 0.8, 1}, .fogColor = .{0.8, 0.8, 1}, .density = 1.0/15.0/128.0, .fogLower = 100, .fogHigher = 1000}; var nextBlockPlaceTime: ?i64 = null; -var nextBlockBreakTime: ?i64 = null; +pub var nextBlockBreakTime: ?i64 = null; pub fn pressPlace() void { const time = std.time.milliTimestamp(); diff --git a/src/itemdrop.zig b/src/itemdrop.zig index 1f770cef7..9b6580dc7 100644 --- a/src/itemdrop.zig +++ b/src/itemdrop.zig @@ -791,7 +791,7 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer return result; } - pub fn renderDisplayItems(ambientLight: Vec3f, playerPos: Vec3d) void { + pub fn renderDisplayItems(ambientLight: Vec3f, playerPos: Vec3d, swingProgress: f32, swingTime: f32) void { if(!ItemDisplayManager.showItem) return; const projMatrix: Mat4f = Mat4f.perspective(std.math.degreesToRadians(65), @as(f32, @floatFromInt(main.renderer.lastWidth))/@as(f32, @floatFromInt(main.renderer.lastHeight)), 0.01, 3); @@ -800,7 +800,7 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer const selectedItem = game.Player.inventory.getItem(game.Player.selectedSlot); if(selectedItem) |item| { - var pos: Vec3d = Vec3d{0, 0, 0}; + var pos: Vec3f = Vec3f{0, 0, 0}; const rot: Vec3f = ItemDisplayManager.cameraFollow; const lightPos = @as(Vec3d, @floatCast(playerPos)) - @as(Vec3f, @splat(0.5)); @@ -852,26 +852,50 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer blockType = item.baseItem.block().?; vertices = model.len/2*6; scale = 0.3; - pos = Vec3d{0.4, 0.55, -0.32}; + pos = Vec3f{0.4, 0.40, -0.32}; } else { scale = 0.57; - pos = Vec3d{0.4, 0.65, -0.3}; + pos = Vec3f{0.4, 0.50, -0.3}; } bindModelUniforms(model.index, blockType); - var modelMatrix = Mat4f.rotationZ(-rot[2]); - modelMatrix = modelMatrix.mul(Mat4f.rotationY(-rot[1])); - modelMatrix = modelMatrix.mul(Mat4f.rotationX(-rot[0])); - modelMatrix = modelMatrix.mul(Mat4f.translation(@floatCast(pos))); + // Swing animation: swingProgress goes from 0 to swingTime + // Define start and end offsets for position and rotation + const startPos: Vec3f = pos; + const swingPosOffset: Vec3f = Vec3f{-0.1, 0.0, 0.2}; // Offset: -X (left), +Z (forward) in player hand coordinates + const startRot: Vec3f = Vec3f{0.0, 0.0, 0.0}; + const swingRotOffset: Vec3f = Vec3f{-0.2, -0.1, 0.0}; // swing rotation offset: negative X (down), negative Y (side), Z unchanged + var swingPhase: f32 = 0.0; + if(swingTime <= 0) { + swingPhase = 0.0; + } else { + swingPhase = std.math.sin((swingProgress / swingTime) * std.math.pi); + } + const lerpedPos: Vec3f = startPos + swingPosOffset * Vec3f{ swingPhase, swingPhase, swingPhase }; + const lerpedRot: Vec3f = Vec3f{ + startRot[0] + (swingRotOffset[0] * swingPhase), + startRot[1] + (swingRotOffset[1] * swingPhase), + startRot[2] + (swingRotOffset[2] * swingPhase), + }; + // Rotation and translation for swing + var modelMatrix = Mat4f.rotationX(-rot[0] + lerpedRot[0]); + modelMatrix = modelMatrix.mul(Mat4f.rotationY(-rot[1] + lerpedRot[1])); + modelMatrix = modelMatrix.mul(Mat4f.rotationZ(-rot[2] + lerpedRot[2])); + modelMatrix = modelMatrix.mul(Mat4f.translation(lerpedPos)); + const TOOL_ROT_Z: f32 = -std.math.pi * 0.47; + const TOOL_ROT_Y: f32 = std.math.pi * 0.25; + const ITEM_ROT_Z: f32 = -std.math.pi * 0.45; + const BLOCK_ROT_Z: f32 = -std.math.pi * 0.2; + if(!isBlock) { if(item == .tool) { - modelMatrix = modelMatrix.mul(Mat4f.rotationZ(-std.math.pi*0.47)); - modelMatrix = modelMatrix.mul(Mat4f.rotationY(std.math.pi*0.25)); + modelMatrix = modelMatrix.mul(Mat4f.rotationZ(TOOL_ROT_Z)); + modelMatrix = modelMatrix.mul(Mat4f.rotationY(TOOL_ROT_Y)); } else { - modelMatrix = modelMatrix.mul(Mat4f.rotationZ(-std.math.pi*0.45)); + modelMatrix = modelMatrix.mul(Mat4f.rotationZ(ITEM_ROT_Z)); } } else { - modelMatrix = modelMatrix.mul(Mat4f.rotationZ(-std.math.pi*0.2)); + modelMatrix = modelMatrix.mul(Mat4f.rotationZ(BLOCK_ROT_Z)); } modelMatrix = modelMatrix.mul(Mat4f.scale(@splat(scale))); modelMatrix = modelMatrix.mul(Mat4f.translation(@splat(-0.5))); diff --git a/src/renderer.zig b/src/renderer.zig index e0fdaf617..31d872601 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -147,10 +147,14 @@ pub fn render(playerPosition: Vec3d, deltaTime: f64) void { ambient[1] = @max(0.1, world.ambientLight); ambient[2] = @max(0.1, world.ambientLight); - itemdrop.ItemDisplayManager.update(deltaTime); - renderWorld(world, ambient, game.fog.skyColor, playerPosition); - const startTime = std.time.milliTimestamp(); - mesh_storage.updateMeshes(startTime + maximumMeshTime); + // Reset swing animation if not mining (input released) + if (game.nextBlockBreakTime == null) { + MeshSelection.currentSwingProgress = 0; + } + itemdrop.ItemDisplayManager.update(deltaTime); + renderWorld(world, ambient, game.fog.skyColor, playerPosition); + const startTime = std.time.milliTimestamp(); + mesh_storage.updateMeshes(startTime + maximumMeshTime); } else { c.glViewport(0, 0, main.Window.width, main.Window.height); MenuBackGround.render(); @@ -277,7 +281,8 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo } c.glDepthRange(0, 0.001); - itemdrop.ItemDropRenderer.renderDisplayItems(ambientLight, playerPos); + // Pass swing progress to display item renderer for animation + itemdrop.ItemDropRenderer.renderDisplayItems(ambientLight, playerPos, MeshSelection.currentSwingProgress, MeshSelection.currentSwingTime); c.glDepthRange(0.001, 1); chunk_meshing.endRender(); From ab196fbcc049086c463212485cd421944343de9f Mon Sep 17 00:00:00 2001 From: SnekProgrammer Date: Tue, 7 Oct 2025 20:11:36 -0600 Subject: [PATCH 2/2] fix formatting & useless comments --- src/itemdrop.zig | 44 ++++++++++++++++++++------------------------ src/renderer.zig | 17 ++++++++--------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/src/itemdrop.zig b/src/itemdrop.zig index 9b6580dc7..9e90242be 100644 --- a/src/itemdrop.zig +++ b/src/itemdrop.zig @@ -859,33 +859,29 @@ pub const ItemDropRenderer = struct { // MARK: ItemDropRenderer } bindModelUniforms(model.index, blockType); - // Swing animation: swingProgress goes from 0 to swingTime - // Define start and end offsets for position and rotation + // Item swing animation const startPos: Vec3f = pos; - const swingPosOffset: Vec3f = Vec3f{-0.1, 0.0, 0.2}; // Offset: -X (left), +Z (forward) in player hand coordinates + const swingPosOffset: Vec3f = Vec3f{-0.1, 0.0, 0.2}; const startRot: Vec3f = Vec3f{0.0, 0.0, 0.0}; - const swingRotOffset: Vec3f = Vec3f{-0.2, -0.1, 0.0}; // swing rotation offset: negative X (down), negative Y (side), Z unchanged + const swingRotOffset: Vec3f = Vec3f{-0.2, -0.1, 0.0}; var swingPhase: f32 = 0.0; - if(swingTime <= 0) { - swingPhase = 0.0; - } else { - swingPhase = std.math.sin((swingProgress / swingTime) * std.math.pi); - } - const lerpedPos: Vec3f = startPos + swingPosOffset * Vec3f{ swingPhase, swingPhase, swingPhase }; - const lerpedRot: Vec3f = Vec3f{ - startRot[0] + (swingRotOffset[0] * swingPhase), - startRot[1] + (swingRotOffset[1] * swingPhase), - startRot[2] + (swingRotOffset[2] * swingPhase), - }; - // Rotation and translation for swing - var modelMatrix = Mat4f.rotationX(-rot[0] + lerpedRot[0]); - modelMatrix = modelMatrix.mul(Mat4f.rotationY(-rot[1] + lerpedRot[1])); - modelMatrix = modelMatrix.mul(Mat4f.rotationZ(-rot[2] + lerpedRot[2])); - modelMatrix = modelMatrix.mul(Mat4f.translation(lerpedPos)); - const TOOL_ROT_Z: f32 = -std.math.pi * 0.47; - const TOOL_ROT_Y: f32 = std.math.pi * 0.25; - const ITEM_ROT_Z: f32 = -std.math.pi * 0.45; - const BLOCK_ROT_Z: f32 = -std.math.pi * 0.2; + if(swingTime <= 0) { + swingPhase = 0.0; + } else { + swingPhase = std.math.sin((swingProgress/swingTime)*std.math.pi); + } + const lerpedPos: Vec3f = startPos + swingPosOffset*@as(Vec3f, @splat(swingPhase)); + const lerpedRot: Vec3f = startRot + swingRotOffset*@as(Vec3f, @splat(swingPhase)); + + var modelMatrix = Mat4f.rotationX(-rot[0] + lerpedRot[0]); + modelMatrix = modelMatrix.mul(Mat4f.rotationY(-rot[1] + lerpedRot[1])); + modelMatrix = modelMatrix.mul(Mat4f.rotationZ(-rot[2] + lerpedRot[2])); + modelMatrix = modelMatrix.mul(Mat4f.translation(lerpedPos)); + + const TOOL_ROT_Z: f32 = -std.math.pi*0.47; + const TOOL_ROT_Y: f32 = std.math.pi*0.25; + const ITEM_ROT_Z: f32 = -std.math.pi*0.45; + const BLOCK_ROT_Z: f32 = -std.math.pi*0.2; if(!isBlock) { if(item == .tool) { diff --git a/src/renderer.zig b/src/renderer.zig index 31d872601..cfd87c3e6 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -147,14 +147,14 @@ pub fn render(playerPosition: Vec3d, deltaTime: f64) void { ambient[1] = @max(0.1, world.ambientLight); ambient[2] = @max(0.1, world.ambientLight); - // Reset swing animation if not mining (input released) - if (game.nextBlockBreakTime == null) { - MeshSelection.currentSwingProgress = 0; - } - itemdrop.ItemDisplayManager.update(deltaTime); - renderWorld(world, ambient, game.fog.skyColor, playerPosition); - const startTime = std.time.milliTimestamp(); - mesh_storage.updateMeshes(startTime + maximumMeshTime); + // Reset swing animation if not mining (input released) + if(game.nextBlockBreakTime == null) { + MeshSelection.currentSwingProgress = 0; + } + itemdrop.ItemDisplayManager.update(deltaTime); + renderWorld(world, ambient, game.fog.skyColor, playerPosition); + const startTime = std.time.milliTimestamp(); + mesh_storage.updateMeshes(startTime + maximumMeshTime); } else { c.glViewport(0, 0, main.Window.width, main.Window.height); MenuBackGround.render(); @@ -281,7 +281,6 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo } c.glDepthRange(0, 0.001); - // Pass swing progress to display item renderer for animation itemdrop.ItemDropRenderer.renderDisplayItems(ambientLight, playerPos, MeshSelection.currentSwingProgress, MeshSelection.currentSwingTime); c.glDepthRange(0.001, 1);