mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -04:00
Allow branches to have a shell model that's always rendered and add leafy branches for all wood types.
This commit is contained in:
parent
8f0693f7b0
commit
42268c4b22
12
assets/cubyz/blocks/branch/leafy/_defaults.zig.zon
Normal file
12
assets/cubyz/blocks/branch/leafy/_defaults.zig.zon
Normal file
@ -0,0 +1,12 @@
|
||||
.{
|
||||
.tags = .{.leaf},
|
||||
.blockHealth = 0.5,
|
||||
.absorbedLight = 0x202830,
|
||||
.alwaysViewThrough = true,
|
||||
.rotation = .branch,
|
||||
.model = .{
|
||||
.radius = 4,
|
||||
.shellModel = "cubyz:cube",
|
||||
.textureSlotOffset = 6,
|
||||
},
|
||||
}
|
14
assets/cubyz/blocks/branch/leafy/baobab.zig.zon
Normal file
14
assets/cubyz/blocks/branch/leafy/baobab.zig.zon
Normal file
@ -0,0 +1,14 @@
|
||||
.{
|
||||
.drops = .{
|
||||
.{.items = .{"cubyz:baobab_leaves", "cubyz:baobab_branch"}},
|
||||
},
|
||||
.texture = "cubyz:baobab_leaves",
|
||||
.texture6 = "cubyz:branch/baobab/dot",
|
||||
.texture7 = "cubyz:branch/baobab/half_line",
|
||||
.texture8 = "cubyz:branch/baobab/line",
|
||||
.texture9 = "cubyz:branch/baobab/bend",
|
||||
.texture10 = "cubyz:branch/baobab/intersection",
|
||||
.texture11 = "cubyz:branch/baobab/cross",
|
||||
.lodReplacement = "cubyz:baobab_leaves_opaque",
|
||||
.opaqueVariant = "cubyz:baobab_leaves_opaque",
|
||||
}
|
14
assets/cubyz/blocks/branch/leafy/birch.zig.zon
Normal file
14
assets/cubyz/blocks/branch/leafy/birch.zig.zon
Normal file
@ -0,0 +1,14 @@
|
||||
.{
|
||||
.drops = .{
|
||||
.{.items = .{"cubyz:birch_leaves", "cubyz:birch_branch"}},
|
||||
},
|
||||
.texture = "cubyz:birch_leaves",
|
||||
.texture6 = "cubyz:branch/birch/dot",
|
||||
.texture7 = "cubyz:branch/birch/half_line",
|
||||
.texture8 = "cubyz:branch/birch/line",
|
||||
.texture9 = "cubyz:branch/birch/bend",
|
||||
.texture10 = "cubyz:branch/birch/intersection",
|
||||
.texture11 = "cubyz:branch/birch/cross",
|
||||
.lodReplacement = "cubyz:birch_leaves_opaque",
|
||||
.opaqueVariant = "cubyz:birch_leaves_opaque",
|
||||
}
|
14
assets/cubyz/blocks/branch/leafy/mahogany.zig.zon
Normal file
14
assets/cubyz/blocks/branch/leafy/mahogany.zig.zon
Normal file
@ -0,0 +1,14 @@
|
||||
.{
|
||||
.drops = .{
|
||||
.{.items = .{"cubyz:mahogany_leaves", "cubyz:mahogany_branch"}},
|
||||
},
|
||||
.texture = "cubyz:mahogany_leaves",
|
||||
.texture6 = "cubyz:branch/mahogany/dot",
|
||||
.texture7 = "cubyz:branch/mahogany/half_line",
|
||||
.texture8 = "cubyz:branch/mahogany/line",
|
||||
.texture9 = "cubyz:branch/mahogany/bend",
|
||||
.texture10 = "cubyz:branch/mahogany/intersection",
|
||||
.texture11 = "cubyz:branch/mahogany/cross",
|
||||
.lodReplacement = "cubyz:mahogany_leaves_opaque",
|
||||
.opaqueVariant = "cubyz:mahogany_leaves_opaque",
|
||||
}
|
14
assets/cubyz/blocks/branch/leafy/oak.zig.zon
Normal file
14
assets/cubyz/blocks/branch/leafy/oak.zig.zon
Normal file
@ -0,0 +1,14 @@
|
||||
.{
|
||||
.drops = .{
|
||||
.{.items = .{"cubyz:oak_leaves", "cubyz:oak_branch"}},
|
||||
},
|
||||
.texture = "cubyz:oak_leaves",
|
||||
.texture6 = "cubyz:branch/oak/dot",
|
||||
.texture7 = "cubyz:branch/oak/half_line",
|
||||
.texture8 = "cubyz:branch/oak/line",
|
||||
.texture9 = "cubyz:branch/oak/bend",
|
||||
.texture10 = "cubyz:branch/oak/intersection",
|
||||
.texture11 = "cubyz:branch/oak/cross",
|
||||
.lodReplacement = "cubyz:oak_leaves_opaque",
|
||||
.opaqueVariant = "cubyz:oak_leaves_opaque",
|
||||
}
|
14
assets/cubyz/blocks/branch/leafy/pine.zig.zon
Normal file
14
assets/cubyz/blocks/branch/leafy/pine.zig.zon
Normal file
@ -0,0 +1,14 @@
|
||||
.{
|
||||
.drops = .{
|
||||
.{.items = .{"cubyz:pine_needles", "cubyz:pine_branch"}},
|
||||
},
|
||||
.texture = "cubyz:pine_needles",
|
||||
.texture6 = "cubyz:branch/pine/dot",
|
||||
.texture7 = "cubyz:branch/pine/half_line",
|
||||
.texture8 = "cubyz:branch/pine/line",
|
||||
.texture9 = "cubyz:branch/pine/bend",
|
||||
.texture10 = "cubyz:branch/pine/intersection",
|
||||
.texture11 = "cubyz:branch/pine/cross",
|
||||
.lodReplacement = "cubyz:pine_needles_opaque",
|
||||
.opaqueVariant = "cubyz:pine_needles_opaque",
|
||||
}
|
14
assets/cubyz/blocks/branch/leafy/willow.zig.zon
Normal file
14
assets/cubyz/blocks/branch/leafy/willow.zig.zon
Normal file
@ -0,0 +1,14 @@
|
||||
.{
|
||||
.drops = .{
|
||||
.{.items = .{"cubyz:willow_leaves", "cubyz:willow_branch"}},
|
||||
},
|
||||
.texture = "cubyz:willow_leaves",
|
||||
.texture6 = "cubyz:branch/willow/dot",
|
||||
.texture7 = "cubyz:branch/willow/half_line",
|
||||
.texture8 = "cubyz:branch/willow/line",
|
||||
.texture9 = "cubyz:branch/willow/bend",
|
||||
.texture10 = "cubyz:branch/willow/intersection",
|
||||
.texture11 = "cubyz:branch/willow/cross",
|
||||
.lodReplacement = "cubyz:willow_leaves_opaque",
|
||||
.opaqueVariant = "cubyz:willow_leaves_opaque",
|
||||
}
|
@ -403,7 +403,23 @@ pub const RotationModes = struct {
|
||||
pub const Branch = struct { // MARK: Branch
|
||||
pub const id: []const u8 = "branch";
|
||||
pub const dependsOnNeighbors = true;
|
||||
var branchModels: std.AutoHashMap(u32, ModelIndex) = undefined;
|
||||
var branchModels: std.HashMap(HashMapKey, ModelIndex, HashMapKey, std.hash_map.default_max_load_percentage) = undefined;
|
||||
const HashMapKey = struct {
|
||||
radius: u16,
|
||||
shellModelId: []const u8,
|
||||
textureSlotOffset: u32,
|
||||
|
||||
pub fn hash(_: HashMapKey, val: HashMapKey) u64 {
|
||||
var hasher = std.hash.Wyhash.init(0);
|
||||
std.hash.autoHashStrat(&hasher, val, .DeepRecursive);
|
||||
return hasher.final();
|
||||
}
|
||||
pub fn eql(_: HashMapKey, val1: HashMapKey, val2: HashMapKey) bool {
|
||||
if(val1.radius != val2.radius) return false;
|
||||
if(val1.textureSlotOffset != val2.textureSlotOffset) return false;
|
||||
return std.mem.eql(u8, val1.shellModelId, val2.shellModelId);
|
||||
}
|
||||
};
|
||||
const BranchData = packed struct(u6) {
|
||||
enabledConnections: u6,
|
||||
|
||||
@ -425,7 +441,7 @@ pub const RotationModes = struct {
|
||||
};
|
||||
|
||||
fn init() void {
|
||||
branchModels = .init(main.globalAllocator.allocator);
|
||||
branchModels = .initContext(main.globalAllocator.allocator, undefined);
|
||||
}
|
||||
|
||||
fn deinit() void {
|
||||
@ -460,7 +476,7 @@ pub const RotationModes = struct {
|
||||
cross: void,
|
||||
};
|
||||
|
||||
fn rotateQuad(originalCorners: [4]Vec2f, pattern: Pattern, min: f32, max: f32, side: Neighbor) main.models.QuadInfo {
|
||||
fn rotateQuad(originalCorners: [4]Vec2f, pattern: Pattern, min: f32, max: f32, side: Neighbor, textureSlotOffset: u32) main.models.QuadInfo {
|
||||
var corners: [4]Vec2f = originalCorners;
|
||||
|
||||
switch(pattern) {
|
||||
@ -498,13 +514,13 @@ pub const RotationModes = struct {
|
||||
},
|
||||
.cornerUV = originalCorners,
|
||||
.normal = @floatFromInt(side.relPos()),
|
||||
.textureSlot = @intFromEnum(pattern),
|
||||
.textureSlot = textureSlotOffset + @intFromEnum(pattern),
|
||||
};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
fn addQuads(pattern: Pattern, side: Neighbor, radius: f32, out: *main.List(main.models.QuadInfo)) void {
|
||||
fn addQuads(pattern: Pattern, side: Neighbor, radius: f32, out: *main.List(main.models.QuadInfo), textureSlotOffset: u32) void {
|
||||
const min: f32 = (8.0 - radius)/16.0;
|
||||
const max: f32 = (8.0 + radius)/16.0;
|
||||
switch(pattern) {
|
||||
@ -514,7 +530,7 @@ pub const RotationModes = struct {
|
||||
.{min, max},
|
||||
.{max, min},
|
||||
.{max, max},
|
||||
}, pattern, min, max, side));
|
||||
}, pattern, min, max, side, textureSlotOffset));
|
||||
},
|
||||
.halfLine => {
|
||||
out.append(rotateQuad(.{
|
||||
@ -522,7 +538,7 @@ pub const RotationModes = struct {
|
||||
.{min, max},
|
||||
.{max, 0.0},
|
||||
.{max, max},
|
||||
}, pattern, min, max, side));
|
||||
}, pattern, min, max, side, textureSlotOffset));
|
||||
},
|
||||
.line => {
|
||||
out.append(rotateQuad(.{
|
||||
@ -530,7 +546,7 @@ pub const RotationModes = struct {
|
||||
.{min, 1.0},
|
||||
.{max, 0.0},
|
||||
.{max, 1.0},
|
||||
}, pattern, min, max, side));
|
||||
}, pattern, min, max, side, textureSlotOffset));
|
||||
},
|
||||
.bend => {
|
||||
out.append(rotateQuad(.{
|
||||
@ -538,7 +554,7 @@ pub const RotationModes = struct {
|
||||
.{0.0, max},
|
||||
.{max, 0.0},
|
||||
.{max, max},
|
||||
}, pattern, min, max, side));
|
||||
}, pattern, min, max, side, textureSlotOffset));
|
||||
},
|
||||
.intersection => {
|
||||
out.append(rotateQuad(.{
|
||||
@ -546,7 +562,7 @@ pub const RotationModes = struct {
|
||||
.{0.0, max},
|
||||
.{1.0, 0.0},
|
||||
.{1.0, max},
|
||||
}, pattern, min, max, side));
|
||||
}, pattern, min, max, side, textureSlotOffset));
|
||||
},
|
||||
.cross => {
|
||||
out.append(rotateQuad(.{
|
||||
@ -554,7 +570,7 @@ pub const RotationModes = struct {
|
||||
.{0.0, 1.0},
|
||||
.{1.0, 0.0},
|
||||
.{1.0, 1.0},
|
||||
}, pattern, min, max, side));
|
||||
}, pattern, min, max, side, textureSlotOffset));
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -638,20 +654,33 @@ pub const RotationModes = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn createBlockModel(_: Block, _: *u16, zon: ZonElement) ModelIndex {
|
||||
const radius = zon.get(f32, "radius", 4);
|
||||
if(branchModels.get(@bitCast(radius))) |modelIndex| return modelIndex;
|
||||
pub fn createBlockModel(_: Block, modeData: *u16, zon: ZonElement) ModelIndex {
|
||||
var radius = zon.get(f32, "radius", 4);
|
||||
const radiusForComparisons = std.math.lossyCast(u16, @round(radius*65536.0/16.0));
|
||||
radius = @as(f32, @floatFromInt(radiusForComparisons))*16.0/65536.0;
|
||||
modeData.* = radiusForComparisons;
|
||||
const shellModelId = zon.get([]const u8, "shellModel", "");
|
||||
const textureSlotOffset = zon.get(u32, "textureSlotOffset", 0);
|
||||
if(branchModels.get(.{.radius = radiusForComparisons, .shellModelId = shellModelId, .textureSlotOffset = textureSlotOffset})) |modelIndex| return modelIndex;
|
||||
|
||||
var shellQuads = main.List(main.models.QuadInfo).init(main.stackAllocator);
|
||||
defer shellQuads.deinit();
|
||||
if(shellModelId.len != 0) {
|
||||
const shellModel = main.models.getModelIndex(shellModelId).model();
|
||||
shellModel.getRawFaces(&shellQuads);
|
||||
}
|
||||
|
||||
var modelIndex: ModelIndex = undefined;
|
||||
for(0..64) |i| {
|
||||
var quads = main.List(main.models.QuadInfo).init(main.stackAllocator);
|
||||
defer quads.deinit();
|
||||
quads.appendSlice(shellQuads.items);
|
||||
|
||||
for(Neighbor.iterable) |neighbor| {
|
||||
const pattern = getPattern(BranchData.init(@intCast(i)), neighbor);
|
||||
|
||||
if(pattern) |pat| {
|
||||
addQuads(pat, neighbor, radius, &quads);
|
||||
addQuads(pat, neighbor, radius, &quads, textureSlotOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -661,7 +690,7 @@ pub const RotationModes = struct {
|
||||
}
|
||||
}
|
||||
|
||||
branchModels.put(@bitCast(radius), modelIndex) catch unreachable;
|
||||
branchModels.put(.{.radius = radiusForComparisons, .shellModelId = shellModelId, .textureSlotOffset = textureSlotOffset}, modelIndex) catch unreachable;
|
||||
|
||||
return modelIndex;
|
||||
}
|
||||
@ -707,16 +736,15 @@ pub const RotationModes = struct {
|
||||
neighborBlock: Block,
|
||||
blockPlacing: bool,
|
||||
) bool {
|
||||
const blockBaseModelIndex = blocks.meshes.modelIndexStart(currentBlock.*);
|
||||
const neighborBaseModelIndex = blocks.meshes.modelIndexStart(neighborBlock);
|
||||
const canConnectToNeighbor = currentBlock.mode() == neighborBlock.mode() and currentBlock.modeData() == neighborBlock.modeData();
|
||||
|
||||
if(blockPlacing or blockBaseModelIndex == neighborBaseModelIndex or neighborBlock.solid()) {
|
||||
if(blockPlacing or canConnectToNeighbor or neighborBlock.solid()) {
|
||||
const neighborModel = blocks.meshes.model(neighborBlock).model();
|
||||
|
||||
var currentData = BranchData.init(currentBlock.data);
|
||||
// Branch block upon placement should extend towards a block it was placed
|
||||
// on if the block is solid or also uses branch model.
|
||||
const targetVal = ((neighborBlock.solid() and !neighborBlock.viewThrough()) and (blockBaseModelIndex == neighborBaseModelIndex or neighborModel.isNeighborOccluded[neighbor.?.reverse().toInt()]));
|
||||
const targetVal = ((neighborBlock.solid() and (!neighborBlock.viewThrough() or canConnectToNeighbor)) and (canConnectToNeighbor or neighborModel.isNeighborOccluded[neighbor.?.reverse().toInt()]));
|
||||
currentData.setConnection(neighbor.?, targetVal);
|
||||
|
||||
const result: u16 = currentData.enabledConnections;
|
||||
@ -729,14 +757,13 @@ pub const RotationModes = struct {
|
||||
}
|
||||
|
||||
pub fn updateData(block: *Block, neighbor: Neighbor, neighborBlock: Block) bool {
|
||||
const blockBaseModel = blocks.meshes.modelIndexStart(block.*);
|
||||
const neighborBaseModel = blocks.meshes.modelIndexStart(neighborBlock);
|
||||
const canConnectToNeighbor = block.mode() == neighborBlock.mode() and block.modeData() == neighborBlock.modeData();
|
||||
var currentData = BranchData.init(block.data);
|
||||
|
||||
// Handle joining with other branches. While placed, branches extend in a
|
||||
// opposite direction than they were placed from, effectively connecting
|
||||
// to the block they were placed at.
|
||||
if(blockBaseModel == neighborBaseModel) {
|
||||
if(canConnectToNeighbor) {
|
||||
const neighborData = BranchData.init(neighborBlock.data);
|
||||
currentData.setConnection(neighbor, neighborData.isConnected(neighbor.reverse()));
|
||||
} else if(!neighborBlock.solid()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user