Change log rotation to be more similar to branches, and also remove log_top (#1496)

Fixes #357 

Stuff left to do

- [x] Make them more like branches
- [x] ~Make them rotate~ Fixed automatically by making them like
branches
- [x] ~Let them be chiseled like stairs?~ This will be a future pr
- [x] Automatic migration between old and new logs

---------

Co-authored-by: Carrie <carriecapp9@gmail.com>
This commit is contained in:
OneAvargeCoder193 2025-06-01 11:17:33 -04:00 committed by GitHub
parent 0c1ee186b2
commit a59ac2b011
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
95 changed files with 457 additions and 132 deletions

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/baobab"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:baobab_log",
.texture_top = "cubyz:baobab_log_top",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/baobab"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:baobab_log",
.texture_top = "cubyz:baobab_log",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/birch"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:birch_log",
.texture_top = "cubyz:birch_log_top",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/birch"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:birch_log",
.texture_top = "cubyz:birch_log",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 4,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/bolete"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:bolete_stem",
}

View File

@ -1,10 +1,11 @@
.{
.tags = .{.leaf},
.blockHealth = 5,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/cactus"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:cactus",
.texture_top = "cubyz:cactus_top",

View File

@ -9,7 +9,7 @@
.alwaysViewThrough = true,
.absorbedLight = 0x121012,
.model = "cubyz:cactus_flower",
.rotation = .log,
.rotation = .direction,
.texture = "cubyz:cactus_flower",
.texture_top = "cubyz:cactus_flower_top",
.texture_bottom = "cubyz:cactus_flower_top",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 4,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/glimmergill"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:glimmergill_stem",
}

View File

@ -0,0 +1,9 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.drops = .{
.{.items = .{.auto}},
},
.rotation = .log,
.model = "cubyz:cube",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/baobab/dot",
.texture1 = "cubyz:log/baobab/line",
.texture2 = "cubyz:log/baobab/bend",
.texture3 = "cubyz:log/baobab/intersection",
.texture4 = "cubyz:log/baobab/cross",
.texture5 = "cubyz:log/baobab/top",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/birch/dot",
.texture1 = "cubyz:log/birch/line",
.texture2 = "cubyz:log/birch/bend",
.texture3 = "cubyz:log/birch/intersection",
.texture4 = "cubyz:log/birch/cross",
.texture5 = "cubyz:log/birch/top",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/bolete/dot",
.texture1 = "cubyz:log/bolete/line",
.texture2 = "cubyz:log/bolete/bend",
.texture3 = "cubyz:log/bolete/intersection",
.texture4 = "cubyz:log/bolete/cross",
.texture5 = "cubyz:log/bolete/top",
}

View File

@ -0,0 +1,9 @@
.{
.tags = .{.leaf},
.texture0 = "cubyz:log/cactus/dot",
.texture1 = "cubyz:log/cactus/line",
.texture2 = "cubyz:log/cactus/bend",
.texture3 = "cubyz:log/cactus/intersection",
.texture4 = "cubyz:log/cactus/cross",
.texture5 = "cubyz:log/cactus/top",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/glimmergill/dot",
.texture1 = "cubyz:log/glimmergill/line",
.texture2 = "cubyz:log/glimmergill/bend",
.texture3 = "cubyz:log/glimmergill/intersection",
.texture4 = "cubyz:log/glimmergill/cross",
.texture5 = "cubyz:log/glimmergill/top",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/mahogany/dot",
.texture1 = "cubyz:log/mahogany/line",
.texture2 = "cubyz:log/mahogany/bend",
.texture3 = "cubyz:log/mahogany/intersection",
.texture4 = "cubyz:log/mahogany/cross",
.texture5 = "cubyz:log/mahogany/top",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/oak/dot",
.texture1 = "cubyz:log/oak/line",
.texture2 = "cubyz:log/oak/bend",
.texture3 = "cubyz:log/oak/intersection",
.texture4 = "cubyz:log/oak/cross",
.texture5 = "cubyz:log/oak/top",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/pine/dot",
.texture1 = "cubyz:log/pine/line",
.texture2 = "cubyz:log/pine/bend",
.texture3 = "cubyz:log/pine/intersection",
.texture4 = "cubyz:log/pine/cross",
.texture5 = "cubyz:log/pine/top",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/toadstool/dot",
.texture1 = "cubyz:log/toadstool/line",
.texture2 = "cubyz:log/toadstool/bend",
.texture3 = "cubyz:log/toadstool/intersection",
.texture4 = "cubyz:log/toadstool/cross",
.texture5 = "cubyz:log/toadstool/top",
}

View File

@ -0,0 +1,8 @@
.{
.texture0 = "cubyz:log/willow/dot",
.texture1 = "cubyz:log/willow/line",
.texture2 = "cubyz:log/willow/bend",
.texture3 = "cubyz:log/willow/intersection",
.texture4 = "cubyz:log/willow/cross",
.texture5 = "cubyz:log/willow/top",
}

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/mahogany"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:mahogany_log",
.texture_top = "cubyz:mahogany_log_top",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/mahogany"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:mahogany_log",
.texture_top = "cubyz:mahogany_log",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/oak"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:oak_log",
.texture_top = "cubyz:oak_log_top",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/oak"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:oak_log",
.texture_top = "cubyz:oak_log",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/pine"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:pine_log",
.texture_top = "cubyz:pine_log_top",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/pine"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:pine_log",
.texture_top = "cubyz:pine_log",

View File

@ -1,5 +1,5 @@
.{
.tags = .{.sbbChild},
.model = "cubyz:cube",
.rotation = .log,
.rotation = .direction,
}

View File

@ -1,7 +1,7 @@
.{
.tags = .{.sbbOrigin},
.model = "cubyz:cube",
.rotation = .log,
.rotation = .direction,
.texture = "cubyz:sbb/origin_side",
.texture_top = "cubyz:sbb/origin_top",
.texture_bottom = "cubyz:sbb/origin_bottom",

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 551 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 4,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/toadstool"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:toadstool_stem",
}

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/willow"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:willow_log",
.texture_top = "cubyz:willow_log_top",

View File

@ -1,10 +1,11 @@
.{
.tags = .{.wood},
.blockHealth = 8,
.hasItem = false,
.drops = .{
.{.items = .{.auto}},
.{.items = .{"cubyz:log/willow"}},
},
.rotation = .log,
.rotation = .direction,
.model = "cubyz:cube",
.texture = "cubyz:willow_log",
.texture_top = "cubyz:willow_log",

View File

@ -24,15 +24,11 @@
.output = "cubyz:workbench",
},
.{
.inputs = .{"cubyz:birch_log"},
.inputs = .{"cubyz:log/birch"},
.output = "4 cubyz:birch_planks",
},
.{
.inputs = .{"cubyz:birch_top"},
.output = "3 cubyz:birch_planks",
},
.{
.inputs = .{"cubyz:birch_log"},
.inputs = .{"cubyz:log/birch"},
.output = "2 cubyz:birch_branch",
},
.{
@ -40,15 +36,11 @@
.output = "2 cubyz:birch_planks",
},
.{
.inputs = .{"cubyz:baobab_log"},
.inputs = .{"cubyz:log/baobab"},
.output = "4 cubyz:baobab_planks",
},
.{
.inputs = .{"cubyz:baobab_top"},
.output = "3 cubyz:baobab_planks",
},
.{
.inputs = .{"cubyz:baobab_log"},
.inputs = .{"cubyz:log/baobab"},
.output = "2 cubyz:baobab_branch",
},
.{
@ -56,15 +48,11 @@
.output = "2 cubyz:baobab_planks",
},
.{
.inputs = .{"cubyz:oak_log"},
.inputs = .{"cubyz:log/oak"},
.output = "4 cubyz:oak_planks",
},
.{
.inputs = .{"cubyz:oak_top"},
.output = "3 cubyz:oak_planks",
},
.{
.inputs = .{"cubyz:oak_log"},
.inputs = .{"cubyz:log/oak"},
.output = "2 cubyz:oak_branch",
},
.{
@ -72,15 +60,11 @@
.output = "2 cubyz:oak_planks",
},
.{
.inputs = .{"cubyz:mahogany_log"},
.inputs = .{"cubyz:log/mahogany"},
.output = "4 cubyz:mahogany_planks",
},
.{
.inputs = .{"cubyz:mahogany_top"},
.output = "3 cubyz:mahogany_planks",
},
.{
.inputs = .{"cubyz:mahogany_log"},
.inputs = .{"cubyz:log/mahogany"},
.output = "2 cubyz:mahogany_branch",
},
.{
@ -88,15 +72,11 @@
.output = "2 cubyz:mahogany_planks",
},
.{
.inputs = .{"cubyz:pine_log"},
.inputs = .{"cubyz:log/pine"},
.output = "4 cubyz:pine_planks",
},
.{
.inputs = .{"cubyz:pine_top"},
.output = "3 cubyz:pine_planks",
},
.{
.inputs = .{"cubyz:pine_log"},
.inputs = .{"cubyz:log/pine"},
.output = "2 cubyz:pine_branch",
},
.{
@ -104,15 +84,11 @@
.output = "2 cubyz:pine_planks",
},
.{
.inputs = .{"cubyz:willow_log"},
.inputs = .{"cubyz:log/willow"},
.output = "4 cubyz:willow_planks",
},
.{
.inputs = .{"cubyz:willow_top"},
.output = "3 cubyz:willow_planks",
},
.{
.inputs = .{"cubyz:willow_log"},
.inputs = .{"cubyz:log/willow"},
.output = "2 cubyz:willow_branch",
},
.{
@ -172,15 +148,15 @@
.output = "2 cubyz:cactus_arm",
},
.{
.inputs = .{"cubyz:bolete_stem"},
.inputs = .{"cubyz:log/bolete"},
.output = "2 cubyz:bolete_branch",
},
.{
.inputs = .{"cubyz:toadstool_stem"},
.inputs = .{"cubyz:log/toadstool"},
.output = "2 cubyz:toadstool_branch",
},
.{
.inputs = .{"cubyz:glimmergill_stem"},
.inputs = .{"cubyz:log/glimmergill"},
.output = "2 cubyz:glimmergill_branch",
},

View File

@ -1,5 +1,6 @@
pub const branch = @import("branch.zig");
pub const carpet = @import("carpet.zig");
pub const direction = @import("direction.zig");
pub const fence = @import("fence.zig");
pub const log = @import("log.zig");
pub const no_rotation = @import("no_rotation.zig");

View File

@ -33,7 +33,7 @@ const HashMapKey = struct {
return std.mem.eql(u8, val1.shellModelId, val2.shellModelId);
}
};
const BranchData = packed struct(u6) {
pub const BranchData = packed struct(u6) {
enabledConnections: u6,
pub inline fn init(blockData: u16) BranchData {
@ -65,7 +65,7 @@ pub fn reset() void {
branchModels.clearRetainingCapacity();
}
const Direction = enum(u2) {
pub const Direction = enum(u2) {
negYDir = 0,
posXDir = 1,
posYDir = 2,
@ -74,18 +74,10 @@ const Direction = enum(u2) {
const Pattern = union(enum) {
dot: void,
halfLine: struct {
dir: Direction,
},
line: struct {
dir: Direction,
},
bend: struct {
dir: Direction,
},
intersection: struct {
dir: Direction,
},
halfLine: Direction,
line: Direction,
bend: Direction,
intersection: Direction,
cross: void,
};
@ -95,7 +87,7 @@ fn rotateQuad(originalCorners: [4]Vec2f, pattern: Pattern, min: f32, max: f32, s
switch(pattern) {
.dot, .cross => {},
inline else => |typ| {
const angle: f32 = @as(f32, @floatFromInt(@intFromEnum(typ.dir)))*std.math.pi/2.0;
const angle: f32 = @as(f32, @floatFromInt(@intFromEnum(typ)))*std.math.pi/2.0;
corners = .{
vec.rotate2d(originalCorners[0], angle, @splat(0.5)),
vec.rotate2d(originalCorners[1], angle, @splat(0.5)),
@ -188,7 +180,7 @@ fn addQuads(pattern: Pattern, side: Neighbor, radius: f32, out: *main.List(main.
}
}
fn getPattern(data: BranchData, side: Neighbor) ?Pattern {
pub fn getPattern(data: BranchData, side: Neighbor) ?Pattern {
const posX = Neighbor.fromRelPos(side.textureX()).?;
const negX = Neighbor.fromRelPos(side.textureX()).?.reverse();
const posY = Neighbor.fromRelPos(side.textureY()).?;
@ -218,7 +210,7 @@ fn getPattern(data: BranchData, side: Neighbor) ?Pattern {
} else if(connectedPosY) {
dir = .posYDir;
}
return .{.halfLine = .{.dir = dir}};
return .{.halfLine = dir};
},
2 => {
if((connectedPosX and connectedNegX) or (connectedPosY and connectedNegY)) {
@ -227,7 +219,7 @@ fn getPattern(data: BranchData, side: Neighbor) ?Pattern {
dir = .posXDir;
}
return .{.line = .{.dir = dir}};
return .{.line = dir};
}
var dir: Direction = .negXDir;
@ -249,7 +241,7 @@ fn getPattern(data: BranchData, side: Neighbor) ?Pattern {
}
}
return .{.bend = .{.dir = dir}};
return .{.bend = dir};
},
3 => {
var dir: Direction = undefined;
@ -258,7 +250,7 @@ fn getPattern(data: BranchData, side: Neighbor) ?Pattern {
if(!connectedNegY) dir = .posYDir;
if(!connectedPosX) dir = .negXDir;
return .{.intersection = .{.dir = dir}};
return .{.intersection = dir};
},
4 => {
return .cross;

View File

@ -0,0 +1,71 @@
const std = @import("std");
const main = @import("main");
const blocks = main.blocks;
const Block = blocks.Block;
const Neighbor = main.chunk.Neighbor;
const ModelIndex = main.models.ModelIndex;
const rotation = main.rotation;
const Degrees = rotation.Degrees;
const vec = main.vec;
const Mat4f = vec.Mat4f;
const Vec3f = vec.Vec3f;
const Vec3i = vec.Vec3i;
const ZonElement = main.ZonElement;
var rotatedModels: std.StringHashMap(ModelIndex) = undefined;
pub fn init() void {
rotatedModels = .init(main.globalAllocator.allocator);
}
pub fn deinit() void {
rotatedModels.deinit();
}
pub fn reset() void {
rotatedModels.clearRetainingCapacity();
}
pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
const modelId = zon.as([]const u8, "cubyz:cube");
if(rotatedModels.get(modelId)) |modelIndex| return modelIndex;
const baseModel = main.models.getModelIndex(modelId).model();
// Rotate the model:
const modelIndex = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.identity()});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationY(std.math.pi)});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationZ(-std.math.pi/2.0).mul(Mat4f.rotationX(-std.math.pi/2.0))});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationZ(std.math.pi/2.0).mul(Mat4f.rotationX(-std.math.pi/2.0))});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationX(-std.math.pi/2.0)});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationZ(std.math.pi).mul(Mat4f.rotationX(-std.math.pi/2.0))});
rotatedModels.put(modelId, modelIndex) catch unreachable;
return modelIndex;
}
pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + @min(block.data, 5)};
}
pub fn rotateZ(data: u16, angle: Degrees) u16 {
comptime var rotationTable: [4][6]u8 = undefined;
comptime for(0..6) |i| {
rotationTable[0][i] = i;
};
comptime for(1..4) |a| {
for(0..6) |i| {
const neighbor: Neighbor = @enumFromInt(rotationTable[a - 1][i]);
rotationTable[a][i] = neighbor.rotateZ().toInt();
}
};
if(data >= 6) return 0;
return rotationTable[@intFromEnum(angle)][data];
}
pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i, neighbor: ?Neighbor, currentData: *Block, _: Block, blockPlacing: bool) bool {
if(blockPlacing) {
currentData.data = neighbor.?.reverse().toInt();
return true;
}
return false;
}

View File

@ -7,65 +7,244 @@ const Neighbor = main.chunk.Neighbor;
const ModelIndex = main.models.ModelIndex;
const rotation = main.rotation;
const Degrees = rotation.Degrees;
const RotationMode = rotation.RotationMode;
const vec = main.vec;
const Mat4f = vec.Mat4f;
const Vec2f = vec.Vec2f;
const Vec3f = vec.Vec3f;
const Vec3i = vec.Vec3i;
const ZonElement = main.ZonElement;
const branch = @import("branch.zig");
var rotatedModels: std.StringHashMap(ModelIndex) = undefined;
pub const dependsOnNeighbors = true;
pub fn init() void {
rotatedModels = .init(main.globalAllocator.allocator);
}
var modelIndex: ?ModelIndex = null;
pub fn deinit() void {
rotatedModels.deinit();
}
const LogData = branch.BranchData;
pub fn init() void {}
pub fn deinit() void {}
pub fn reset() void {
rotatedModels.clearRetainingCapacity();
modelIndex = null;
}
pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
const modelId = zon.as([]const u8, "cubyz:cube");
if(rotatedModels.get(modelId)) |modelIndex| return modelIndex;
const DirectionWithSign = branch.Direction;
const baseModel = main.models.getModelIndex(modelId).model();
// Rotate the model:
const modelIndex = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.identity()});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationY(std.math.pi)});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationZ(-std.math.pi/2.0).mul(Mat4f.rotationX(-std.math.pi/2.0))});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationZ(std.math.pi/2.0).mul(Mat4f.rotationX(-std.math.pi/2.0))});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationX(-std.math.pi/2.0)});
_ = baseModel.transformModel(rotation.rotationMatrixTransform, .{Mat4f.rotationZ(std.math.pi).mul(Mat4f.rotationX(-std.math.pi/2.0))});
rotatedModels.put(modelId, modelIndex) catch unreachable;
return modelIndex;
const DirectionWithoutSign = enum(u1) {
y = 0,
x = 1,
fn fromBranchDirection(dir: DirectionWithSign) DirectionWithoutSign {
return switch(dir) {
.negYDir => .y,
.posXDir => .x,
.posYDir => .y,
.negXDir => .x,
};
}
};
const Pattern = union(enum) {
dot: void,
line: DirectionWithoutSign,
bend: DirectionWithSign,
intersection: DirectionWithSign,
cross: void,
cut: void,
};
fn rotateQuad(pattern: Pattern, side: Neighbor) main.models.QuadInfo {
const originalCorners: [4]Vec2f = .{
.{0, 0},
.{0, 1},
.{1, 0},
.{1, 1},
};
var corners: [4]Vec2f = originalCorners;
switch(pattern) {
.dot, .cross, .cut => {},
.line => |dir| {
var angle: f32 = @as(f32, @floatFromInt(@intFromEnum(dir)))*std.math.pi/2.0;
if(side.relZ() != 0) {
angle *= -1;
}
if(side.isPositive()) {
angle *= -1;
}
if(side.relY() != 0) {
angle *= -1;
}
corners = .{
vec.rotate2d(originalCorners[0], angle, @splat(0.5)),
vec.rotate2d(originalCorners[1], angle, @splat(0.5)),
vec.rotate2d(originalCorners[2], angle, @splat(0.5)),
vec.rotate2d(originalCorners[3], angle, @splat(0.5)),
};
},
.bend, .intersection => |dir| {
corners = originalCorners;
const angle: f32 = -@as(f32, @floatFromInt(@intFromEnum(dir)))*std.math.pi/2.0;
corners = .{
vec.rotate2d(originalCorners[0], angle, @splat(0.5)),
vec.rotate2d(originalCorners[1], angle, @splat(0.5)),
vec.rotate2d(originalCorners[2], angle, @splat(0.5)),
vec.rotate2d(originalCorners[3], angle, @splat(0.5)),
};
},
}
const offX: f32 = @floatFromInt(@intFromBool(@reduce(.Add, side.textureX()) < 0));
const offY: f32 = @floatFromInt(@intFromBool(@reduce(.Add, side.textureY()) < 0));
const corners3d = .{
@as(Vec3f, @floatFromInt(side.textureX()))*@as(Vec3f, @splat(originalCorners[0][0] - offX)) + @as(Vec3f, @floatFromInt(side.textureY()))*@as(Vec3f, @splat(originalCorners[0][1] - offY)),
@as(Vec3f, @floatFromInt(side.textureX()))*@as(Vec3f, @splat(originalCorners[1][0] - offX)) + @as(Vec3f, @floatFromInt(side.textureY()))*@as(Vec3f, @splat(originalCorners[1][1] - offY)),
@as(Vec3f, @floatFromInt(side.textureX()))*@as(Vec3f, @splat(originalCorners[2][0] - offX)) + @as(Vec3f, @floatFromInt(side.textureY()))*@as(Vec3f, @splat(originalCorners[2][1] - offY)),
@as(Vec3f, @floatFromInt(side.textureX()))*@as(Vec3f, @splat(originalCorners[3][0] - offX)) + @as(Vec3f, @floatFromInt(side.textureY()))*@as(Vec3f, @splat(originalCorners[3][1] - offY)),
};
var offset: Vec3f = .{0.0, 0.0, 0.0};
offset[@intFromEnum(side.vectorComponent())] = @floatFromInt(@intFromBool(side.isPositive()));
const res: main.models.QuadInfo = .{
.corners = .{
corners3d[0] + offset,
corners3d[1] + offset,
corners3d[2] + offset,
corners3d[3] + offset,
},
.cornerUV = corners,
.normal = @floatFromInt(side.relPos()),
.textureSlot = @intFromEnum(pattern),
};
return res;
}
fn getPattern(data: LogData, side: Neighbor) Pattern {
if(data.isConnected(side)) {
return .cut;
}
const pattern = branch.getPattern(data, side).?;
switch(pattern) {
.dot => {
return .dot;
},
.halfLine => |dir| {
return .{.line = .fromBranchDirection(dir)};
},
.line => |dir| {
return .{.line = .fromBranchDirection(dir)};
},
.bend => |dir| {
return .{.bend = dir};
},
.intersection => |dir| {
return .{.intersection = dir};
},
.cross => {
return .cross;
},
}
}
pub fn createBlockModel(_: Block, _: *u16, _: ZonElement) ModelIndex {
if(modelIndex) |idx| return idx;
for(0..64) |i| {
var quads = main.List(main.models.QuadInfo).init(main.stackAllocator);
defer quads.deinit();
const data = LogData.init(@intCast(i));
for(Neighbor.iterable) |neighbor| {
const pattern = getPattern(data, neighbor);
quads.append(rotateQuad(pattern, neighbor));
}
const index = main.models.Model.init(quads.items);
if(i == 0) {
modelIndex = index;
}
}
return modelIndex.?;
}
pub fn model(block: Block) ModelIndex {
return .{.index = blocks.meshes.modelIndexStart(block).index + @min(block.data, 5)};
return .{.index = blocks.meshes.modelIndexStart(block).index + (block.data & 63)};
}
pub fn rotateZ(data: u16, angle: Degrees) u16 {
comptime var rotationTable: [4][6]u8 = undefined;
comptime for(0..6) |i| {
rotationTable[0][i] = i;
};
comptime for(1..4) |a| {
for(0..6) |i| {
const neighbor: Neighbor = @enumFromInt(rotationTable[a - 1][i]);
rotationTable[a][i] = neighbor.rotateZ().toInt();
pub const rotateZ = branch.rotateZ;
pub fn generateData(
_: *main.game.World,
pos: Vec3i,
_: Vec3f,
_: Vec3f,
_: Vec3i,
neighbor: ?Neighbor,
currentBlock: *Block,
neighborBlock: Block,
blockPlacing: bool,
) bool {
const canConnectToNeighbor = currentBlock.mode() == neighborBlock.mode();
if(blockPlacing or canConnectToNeighbor or !neighborBlock.replacable()) {
const neighborModel = blocks.meshes.model(neighborBlock).model();
var currentData = LogData.init(currentBlock.data);
// Log block upon placement should extend towards a block it was placed
// on if the block is solid or also uses log model.
const targetVal = ((!neighborBlock.replacable() and (!neighborBlock.viewThrough() or canConnectToNeighbor)) and (canConnectToNeighbor or neighborModel.isNeighborOccluded[neighbor.?.reverse().toInt()]));
currentData.setConnection(neighbor.?, targetVal);
for(Neighbor.iterable) |side| {
if(side == neighbor.?) {
continue;
}
const sidePos = pos + side.relPos();
const sideBlock = main.renderer.mesh_storage.getBlock(sidePos[0], sidePos[1], sidePos[2]) orelse continue;
const canConnectToSide = currentBlock.mode() == sideBlock.mode() and currentBlock.modeData() == sideBlock.modeData();
if(canConnectToSide) {
const sideData = LogData.init(sideBlock.data);
currentData.setConnection(side, sideData.isConnected(side.reverse()));
}
}
};
if(data >= 6) return 0;
return rotationTable[@intFromEnum(angle)][data];
}
pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3f, _: Vec3f, _: Vec3i, neighbor: ?Neighbor, currentData: *Block, _: Block, blockPlacing: bool) bool {
if(blockPlacing) {
currentData.data = neighbor.?.reverse().toInt();
const result: u16 = currentData.enabledConnections;
if(result == currentBlock.data) return false;
currentBlock.data = result;
return true;
}
return false;
}
pub fn updateData(block: *Block, neighbor: Neighbor, neighborBlock: Block) bool {
const canConnectToNeighbor = block.mode() == neighborBlock.mode();
var currentData = LogData.init(block.data);
// Handle joining with other logs. While placed, logs extend in a
// opposite direction than they were placed from, effectively connecting
// to the block they were placed at.
if(canConnectToNeighbor) {
const neighborData = LogData.init(neighborBlock.data);
currentData.setConnection(neighbor, neighborData.isConnected(neighbor.reverse()));
}
const result: u16 = currentData.enabledConnections;
if(result == block.data) return false;
block.data = result;
return true;
}