mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-05 12:17:53 -04:00
Simplify stair chisel selection code, using the same technique as torches.
fixes #1360
This commit is contained in:
parent
74bf4b62c9
commit
ffab4407e9
@ -254,42 +254,22 @@ pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersectHalfUnitBox(start: Vec3f, invDir: Vec3f) ?f32 {
|
fn closestRay(comptime typ: enum {bit, intersection}, block: Block, relativePlayerPos: Vec3f, playerDir: Vec3f) if(typ == .intersection) ?RayIntersectionResult else u16 {
|
||||||
const t0 = start*invDir;
|
var result: ?RayIntersectionResult = null;
|
||||||
const t1 = (start + Vec3f{0.5, 0.5, 0.5})*invDir;
|
var resultBit: u16 = 0;
|
||||||
const entry = @reduce(.Max, @min(t0, t1));
|
for([_]u16{1, 2, 4, 8, 16, 32, 64, 128}) |bit| {
|
||||||
const exit = @reduce(.Min, @max(t0, t1));
|
if(block.data & bit == 0) {
|
||||||
if(entry > exit or exit < 0) {
|
const cornerModelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + (255 ^ bit)};
|
||||||
return null;
|
if(RotationMode.DefaultFunctions.rayModelIntersection(cornerModelIndex, relativePlayerPos, playerDir)) |intersection| {
|
||||||
} else return entry;
|
if(result == null or intersection.distance < result.?.distance) {
|
||||||
}
|
result = intersection;
|
||||||
|
resultBit = bit;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(minT != std.math.floatMax(f32)) {
|
if(typ == .bit) return resultBit;
|
||||||
return .{.minT = minT, .minPos = minPos};
|
return result;
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rayIntersection(block: Block, item: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult {
|
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) {
|
switch(_item) {
|
||||||
.baseItem => |baseItem| {
|
.baseItem => |baseItem| {
|
||||||
if(std.mem.eql(u8, baseItem.id, "cubyz:chisel")) { // Select only one eighth of a block
|
if(std.mem.eql(u8, baseItem.id, "cubyz:chisel")) { // Select only one eighth of a block
|
||||||
if(intersectionPos(block, relativePlayerPos, playerDir)) |intersection| {
|
return closestRay(.intersection, block, relativePlayerPos, playerDir);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
@ -317,11 +291,9 @@ pub fn onBlockBreaking(item: ?main.items.Item, relativePlayerPos: Vec3f, playerD
|
|||||||
switch(_item) {
|
switch(_item) {
|
||||||
.baseItem => |baseItem| {
|
.baseItem => |baseItem| {
|
||||||
if(std.mem.eql(u8, baseItem.id, "cubyz:chisel")) { // Break only one eigth of a block
|
if(std.mem.eql(u8, baseItem.id, "cubyz:chisel")) { // Break only one eigth of a block
|
||||||
if(intersectionPos(currentData.*, relativePlayerPos, playerDir)) |intersection| {
|
currentData.data |= closestRay(.bit, currentData.*, relativePlayerPos, playerDir);
|
||||||
currentData.data = currentData.data | subBlockMask(intersection.minPos[0], intersection.minPos[1], intersection.minPos[2]);
|
if(currentData.data == 255) currentData.* = .{.typ = 0, .data = 0};
|
||||||
if(currentData.data == 255) currentData.* = .{.typ = 0, .data = 0};
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
|
@ -174,7 +174,7 @@ fn closestRay(comptime typ: enum {bit, intersection}, block: Block, _: ?main.ite
|
|||||||
if(block.data & bit != 0) {
|
if(block.data & bit != 0) {
|
||||||
const modelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + bit - 1};
|
const modelIndex = ModelIndex{.index = blocks.meshes.modelIndexStart(block).index + bit - 1};
|
||||||
if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| {
|
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;
|
result = intersection;
|
||||||
resultBit = bit;
|
resultBit = bit;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user