diff --git a/src/rotation/stairs.zig b/src/rotation/stairs.zig index 5799cb45..8a5de223 100644 --- a/src/rotation/stairs.zig +++ b/src/rotation/stairs.zig @@ -254,42 +254,22 @@ pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i, return false; } -fn intersectHalfUnitBox(start: Vec3f, invDir: Vec3f) ?f32 { - const t0 = start*invDir; - const t1 = (start + Vec3f{0.5, 0.5, 0.5})*invDir; - const entry = @reduce(.Max, @min(t0, t1)); - const exit = @reduce(.Min, @max(t0, t1)); - if(entry > exit or exit < 0) { - return null; - } else return entry; -} - -fn intersectionPos(block: Block, relativePlayerPos: Vec3f, playerDir: Vec3f) ?struct {minT: f32, minPos: @Vector(3, u1)} { - const invDir = @as(Vec3f, @splat(1))/playerDir; - const relPos: Vec3f = @floatCast(-relativePlayerPos); - const data: u8 = @truncate(block.data); - var minT: f32 = std.math.floatMax(f32); - var minPos: @Vector(3, u1) = undefined; - for(0..8) |i| { - const subPos: @Vector(3, u1) = .{ - @truncate(i >> 2), - @truncate(i >> 1), - @truncate(i), - }; - if(hasSubBlock(data, subPos[0], subPos[1], subPos[2])) { - const relSubPos = relPos + @as(Vec3f, @floatFromInt(subPos))*@as(Vec3f, @splat(0.5)); - if(intersectHalfUnitBox(relSubPos, invDir)) |t| { - if(t < minT) { - minT = t; - minPos = subPos; +fn closestRay(comptime typ: enum {bit, intersection}, block: Block, relativePlayerPos: Vec3f, playerDir: Vec3f) if(typ == .intersection) ?RayIntersectionResult else u16 { + var result: ?RayIntersectionResult = null; + var resultBit: u16 = 0; + for([_]u16{1, 2, 4, 8, 16, 32, 64, 128}) |bit| { + if(block.data & bit == 0) { + const cornerModelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + (255 ^ bit)}; + if(RotationMode.DefaultFunctions.rayModelIntersection(cornerModelIndex, relativePlayerPos, playerDir)) |intersection| { + if(result == null or intersection.distance < result.?.distance) { + result = intersection; + resultBit = bit; } } } } - if(minT != std.math.floatMax(f32)) { - return .{.minT = minT, .minPos = minPos}; - } - return null; + if(typ == .bit) return resultBit; + return result; } pub fn rayIntersection(block: Block, item: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult { @@ -297,13 +277,7 @@ pub fn rayIntersection(block: Block, item: ?main.items.Item, relativePlayerPos: switch(_item) { .baseItem => |baseItem| { if(std.mem.eql(u8, baseItem.id, "cubyz:chisel")) { // Select only one eighth of a block - if(intersectionPos(block, relativePlayerPos, playerDir)) |intersection| { - const offset: Vec3f = @floatFromInt(intersection.minPos); - const half: Vec3f = @splat(0.5); - const fullIntersection = RotationMode.DefaultFunctions.rayIntersection(block, item, relativePlayerPos, playerDir) orelse unreachable; - return .{.distance = intersection.minT, .min = half*offset, .max = half + half*offset, .face = fullIntersection.face}; - } - return null; + return closestRay(.intersection, block, relativePlayerPos, playerDir); } }, else => {}, @@ -317,11 +291,9 @@ pub fn onBlockBreaking(item: ?main.items.Item, relativePlayerPos: Vec3f, playerD switch(_item) { .baseItem => |baseItem| { if(std.mem.eql(u8, baseItem.id, "cubyz:chisel")) { // Break only one eigth of a block - if(intersectionPos(currentData.*, relativePlayerPos, playerDir)) |intersection| { - currentData.data = currentData.data | subBlockMask(intersection.minPos[0], intersection.minPos[1], intersection.minPos[2]); - if(currentData.data == 255) currentData.* = .{.typ = 0, .data = 0}; - return; - } + currentData.data |= closestRay(.bit, currentData.*, relativePlayerPos, playerDir); + if(currentData.data == 255) currentData.* = .{.typ = 0, .data = 0}; + return; } }, else => {}, diff --git a/src/rotation/torch.zig b/src/rotation/torch.zig index d00359a9..33aa2581 100644 --- a/src/rotation/torch.zig +++ b/src/rotation/torch.zig @@ -174,7 +174,7 @@ fn closestRay(comptime typ: enum {bit, intersection}, block: Block, _: ?main.ite if(block.data & bit != 0) { const modelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + bit - 1}; if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| { - if(result == null or result.?.distance > intersection.distance) { + if(result == null or intersection.distance < result.?.distance) { result = intersection; resultBit = bit; }