Only display the selection box of the currently selected submodel of torch and carpet rotation modes.

fixes #784
This commit is contained in:
IntegratedQuantum 2024-11-25 17:00:55 +01:00
parent 72f5a6b0fd
commit 1fffecb870
2 changed files with 39 additions and 6 deletions

View File

@ -709,7 +709,7 @@ pub const MeshSelection = struct { // MARK: MeshSelection
if(block.typ != 0) { if(block.typ != 0) {
if(block.blockClass() != .fluid and block.blockClass() != .air) { // TODO: Buckets could select fluids if(block.blockClass() != .fluid and block.blockClass() != .air) { // TODO: Buckets could select fluids
const relativePlayerPos: Vec3f = @floatCast(pos - @as(Vec3d, @floatFromInt(voxelPos))); const relativePlayerPos: Vec3f = @floatCast(pos - @as(Vec3d, @floatFromInt(voxelPos)));
if(block.mode().rayIntersection(block, item, voxelPos, relativePlayerPos, _dir)) |intersection| { if(block.mode().rayIntersection(block, item, relativePlayerPos, _dir)) |intersection| {
if(intersection.distance <= closestDistance) { if(intersection.distance <= closestDistance) {
selectedBlockPos = voxelPos; selectedBlockPos = voxelPos;
selectionMin = intersection.min; selectionMin = intersection.min;

View File

@ -35,10 +35,13 @@ pub const RotationMode = struct { // MARK: RotationMode
fn updateData(_: *Block, _: Neighbor, _: Block) bool { fn updateData(_: *Block, _: Neighbor, _: Block) bool {
return false; return false;
} }
fn rayIntersection(block: Block, _: ?main.items.Item, _: Vec3i, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult { fn rayIntersection(block: Block, _: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult {
return rayModelIntersection(blocks.meshes.model(block), relativePlayerPos, playerDir);
}
fn rayModelIntersection(modelIndex: u32, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult {
// Check the true bounding box (using this algorithm here: https://tavianator.com/2011/ray_box.html): // Check the true bounding box (using this algorithm here: https://tavianator.com/2011/ray_box.html):
const invDir = @as(Vec3f, @splat(1))/playerDir; const invDir = @as(Vec3f, @splat(1))/playerDir;
const modelData = &main.models.models.items[blocks.meshes.model(block)]; const modelData = &main.models.models.items[modelIndex];
const min: Vec3f = modelData.min; const min: Vec3f = modelData.min;
const max: Vec3f = modelData.max; const max: Vec3f = modelData.max;
const t1 = (min - relativePlayerPos)*invDir; const t1 = (min - relativePlayerPos)*invDir;
@ -70,7 +73,7 @@ pub const RotationMode = struct { // MARK: RotationMode
/// Updates data of a placed block if the RotationMode dependsOnNeighbors. /// Updates data of a placed block if the RotationMode dependsOnNeighbors.
updateData: *const fn(block: *Block, neighbor: Neighbor, neighborBlock: Block) bool = &DefaultFunctions.updateData, updateData: *const fn(block: *Block, neighbor: Neighbor, neighborBlock: Block) bool = &DefaultFunctions.updateData,
rayIntersection: *const fn(block: Block, item: ?main.items.Item, voxelPos: Vec3i, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult = &DefaultFunctions.rayIntersection, rayIntersection: *const fn(block: Block, item: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult = &DefaultFunctions.rayIntersection,
}; };
var rotationModes: std.StringHashMap(RotationMode) = undefined; var rotationModes: std.StringHashMap(RotationMode) = undefined;
@ -512,7 +515,7 @@ pub const RotationModes = struct {
return null; return null;
} }
pub fn rayIntersection(block: Block, item: ?main.items.Item, blockPos: Vec3i, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult { pub fn rayIntersection(block: Block, item: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult {
if(item) |_item| { if(item) |_item| {
switch(_item) { switch(_item) {
.baseItem => |baseItem| { .baseItem => |baseItem| {
@ -532,7 +535,7 @@ pub const RotationModes = struct {
else => {}, else => {},
} }
} }
return RotationMode.DefaultFunctions.rayIntersection(block, item, blockPos, relativePlayerPos, playerDir); return RotationMode.DefaultFunctions.rayIntersection(block, item, relativePlayerPos, playerDir);
} }
pub fn chisel(_: *main.game.World, _: Vec3i, relativePlayerPos: Vec3f, playerDir: Vec3f, currentData: *Block) bool { pub fn chisel(_: *main.game.World, _: Vec3i, relativePlayerPos: Vec3f, playerDir: Vec3f, currentData: *Block) bool {
@ -662,6 +665,21 @@ pub const RotationModes = struct {
else block.data = result; else block.data = result;
return true; return true;
} }
pub fn rayIntersection(block: Block, _: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult {
var result: ?RayIntersectionResult = null;
for([_]u16{1, 2, 4, 8, 16}) |bit| {
if(block.data & bit != 0) {
const modelIndex = blocks.meshes.modelIndexStart(block) + bit - 1;
if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| {
if(result == null or result.?.distance > intersection.distance) {
result = intersection;
}
}
}
}
return result;
}
}; };
pub const Carpet = struct { // MARK: Carpet pub const Carpet = struct { // MARK: Carpet
pub const id: []const u8 = "carpet"; pub const id: []const u8 = "carpet";
@ -790,6 +808,21 @@ pub const RotationModes = struct {
else block.data = result; else block.data = result;
return true; return true;
} }
pub fn rayIntersection(block: Block, _: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f) ?RayIntersectionResult {
var result: ?RayIntersectionResult = null;
for([_]u16{1, 2, 4, 8, 16, 32}) |bit| {
if(block.data & bit != 0) {
const modelIndex = blocks.meshes.modelIndexStart(block) + bit - 1;
if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| {
if(result == null or result.?.distance > intersection.distance) {
result = intersection;
}
}
}
}
return result;
}
}; };
}; };