Simplify stair chisel selection code, using the same technique as torches.

fixes #1360
This commit is contained in:
IntegratedQuantum 2025-05-09 21:45:12 +02:00
parent 74bf4b62c9
commit ffab4407e9
2 changed files with 17 additions and 45 deletions

View File

@ -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 => {},

View File

@ -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;
}