mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-15 23:39:25 -04:00
Add branch block type (#1118)
* Add branch block type * Fix tabs * Degenerate quads by setting them (.5,.5,.5) * Add directional branch connecting * Fix branches connecting to non-solid blocks * Simplify branchTransform * No automatic connections to solid blocks * Use Neighbor to express branch connections * Allow manual modification of branch connections * Update branch model to have solid ends * Tweak block connecting logic * Tweak comments * Tweak branch model UV * Update branch debug texture * Remove extra faces on connections * Apply review suggestions * Exclude viewThrough blocks from branch updateData * Revert "Exclude viewThrough blocks from branch updateData" This reverts commit 5942870253e841669c26db959e956fe416d77b9e. * Apply review suggestions * Snakes not allowed * Fix style issues * Apply review suggestions * Fix formatting issue
This commit is contained in:
parent
1f18486c67
commit
c4a4d29a07
11
assets/cubyz/blocks/oak_branch.zig.zon
Normal file
11
assets/cubyz/blocks/oak_branch.zig.zon
Normal file
@ -0,0 +1,11 @@
|
||||
.{
|
||||
.tags = .{.wood},
|
||||
.blockHealth = 5,
|
||||
.drops = .{
|
||||
.{ .items = .{.auto} },
|
||||
},
|
||||
.absorbedLight = 0x202830,
|
||||
.rotation = .branch,
|
||||
.model = "cubyz:branch",
|
||||
.texture = "cubyz:oak_branch",
|
||||
}
|
BIN
assets/cubyz/blocks/textures/oak_branch.png
Normal file
BIN
assets/cubyz/blocks/textures/oak_branch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
BIN
assets/cubyz/blocks/textures/oak_branch_debug.png
Normal file
BIN
assets/cubyz/blocks/textures/oak_branch_debug.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
108
assets/cubyz/models/branch.obj
Normal file
108
assets/cubyz/models/branch.obj
Normal file
@ -0,0 +1,108 @@
|
||||
# Blender 4.1.0
|
||||
# www.blender.org
|
||||
o branch
|
||||
v 0.250000 0.750000 0.750000
|
||||
v 0.250000 0.750000 0.250000
|
||||
v 0.250000 0.250000 0.250000
|
||||
v 0.250000 0.250000 0.750000
|
||||
v 0.750000 0.250000 0.750000
|
||||
v 0.750000 0.250000 0.250000
|
||||
v 0.750000 0.750000 0.250000
|
||||
v 0.750000 0.750000 0.750000
|
||||
v 0.750000 0.250000 0.750000
|
||||
v 0.750000 0.250000 0.250000
|
||||
v 1.000000 0.250000 0.250000
|
||||
v 1.000000 0.250000 0.750000
|
||||
v 1.000000 0.750000 0.750000
|
||||
v 1.000000 0.750000 0.250000
|
||||
v 0.750000 0.750000 0.250000
|
||||
v 0.750000 0.750000 0.750000
|
||||
v 0.750000 0.250000 0.750000
|
||||
v 0.750000 0.250000 0.250000
|
||||
v 0.750000 0.000000 0.250000
|
||||
v 0.750000 0.000000 0.750000
|
||||
v 0.250000 0.000000 0.750000
|
||||
v 0.250000 0.000000 0.250000
|
||||
v 0.250000 0.250000 0.250000
|
||||
v 0.250000 0.250000 0.750000
|
||||
v 0.750000 0.250000 0.250000
|
||||
v 0.250000 0.250000 0.250000
|
||||
v 0.250000 0.250000 -0.000000
|
||||
v 0.750000 0.250000 -0.000000
|
||||
v 0.750000 0.750000 -0.000000
|
||||
v 0.250000 0.750000 -0.000000
|
||||
v 0.250000 0.750000 0.250000
|
||||
v 0.750000 0.750000 0.250000
|
||||
v 0.750000 0.250000 1.000000
|
||||
v 0.250000 0.250000 1.000000
|
||||
v 0.250000 0.250000 0.750000
|
||||
v 0.750000 0.250000 0.750000
|
||||
v 0.750000 0.750000 0.750000
|
||||
v 0.250000 0.750000 0.750000
|
||||
v 0.250000 0.750000 1.000000
|
||||
v 0.750000 0.750000 1.000000
|
||||
v 0.250000 1.000000 0.750000
|
||||
v 0.250000 1.000000 0.250000
|
||||
v 0.250000 0.750000 0.250000
|
||||
v 0.250000 0.750000 0.750000
|
||||
v 0.750000 0.750000 0.750000
|
||||
v 0.750000 0.750000 0.250000
|
||||
v 0.750000 1.000000 0.250000
|
||||
v 0.750000 1.000000 0.750000
|
||||
v 0.000000 0.250000 0.750000
|
||||
v 0.000000 0.250000 0.250000
|
||||
v 0.250000 0.250000 0.250000
|
||||
v 0.250000 0.250000 0.750000
|
||||
v 0.250000 0.750000 0.750000
|
||||
v 0.250000 0.750000 0.250000
|
||||
v 0.000000 0.750000 0.250000
|
||||
v 0.000000 0.750000 0.750000
|
||||
vn -1.0000 -0.0000 -0.0000
|
||||
vn 1.0000 -0.0000 -0.0000
|
||||
vn -0.0000 -1.0000 -0.0000
|
||||
vn -0.0000 1.0000 -0.0000
|
||||
vn -0.0000 -0.0000 -1.0000
|
||||
vn -0.0000 -0.0000 1.0000
|
||||
vt 0.062500 0.187500
|
||||
vt 0.062500 0.062500
|
||||
vt 0.187500 0.062500
|
||||
vt 0.187500 0.187500
|
||||
vt 0.000000 0.062500
|
||||
vt 0.000000 0.187500
|
||||
vt 0.187500 0.250000
|
||||
vt 0.062500 0.250000
|
||||
vt 0.250000 0.062500
|
||||
vt 0.250000 0.187500
|
||||
vt 0.187500 0.000000
|
||||
vt 0.062500 0.000000
|
||||
s 0
|
||||
f 1/1/1 2/2/1 3/3/1 4/4/1
|
||||
f 5/1/2 6/2/2 7/3/2 8/4/2
|
||||
f 4/4/3 3/3/3 6/2/3 5/1/3
|
||||
f 8/4/4 7/1/4 2/2/4 1/3/4
|
||||
f 9/1/3 10/2/3 11/5/3 12/6/3
|
||||
f 13/7/4 14/8/4 15/1/4 16/4/4
|
||||
f 10/2/5 15/1/5 14/6/5 11/5/5
|
||||
f 12/6/6 13/5/6 16/2/6 9/1/6
|
||||
f 20/8/6 17/1/6 24/4/6 21/7/6
|
||||
f 20/6/2 19/5/2 18/2/2 17/1/2
|
||||
f 24/4/1 23/3/1 22/9/1 21/10/1
|
||||
f 22/11/5 23/3/5 18/2/5 19/12/5
|
||||
f 5/1/6 8/2/6 1/3/6 4/4/6
|
||||
f 3/3/5 2/4/5 7/1/5 6/2/5
|
||||
f 25/2/3 26/3/3 27/11/3 28/12/3
|
||||
f 29/6/4 30/5/4 31/2/4 32/1/4
|
||||
f 26/3/1 31/2/1 30/12/1 27/11/1
|
||||
f 28/12/2 29/11/2 32/3/2 25/2/2
|
||||
f 33/8/3 34/7/3 35/4/3 36/1/3
|
||||
f 37/4/4 38/3/4 39/9/4 40/10/4
|
||||
f 34/7/1 39/8/1 38/1/1 35/4/1
|
||||
f 36/1/2 37/4/2 40/7/2 33/8/2
|
||||
f 41/6/1 42/5/1 43/2/1 44/1/1
|
||||
f 45/4/2 46/3/2 47/9/2 48/10/2
|
||||
f 43/4/5 42/7/5 47/8/5 46/1/5
|
||||
f 45/2/6 48/12/6 41/11/6 44/3/6
|
||||
f 49/10/3 50/9/3 51/3/3 52/4/3
|
||||
f 53/3/4 54/2/4 55/12/4 56/11/4
|
||||
f 50/9/5 55/10/5 54/4/5 51/3/5
|
||||
f 52/4/6 53/3/6 56/9/6 49/10/6
|
160
src/rotation.zig
160
src/rotation.zig
@ -321,6 +321,166 @@ pub const RotationModes = struct {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
pub const Branch = struct { // MARK: Branch
|
||||
pub const id: []const u8 = "branch";
|
||||
pub const dependsOnNeighbors = true;
|
||||
var branchModels: std.StringHashMap(u16) = undefined;
|
||||
const BranchData = packed struct(u6) {
|
||||
enabledConnections: u6,
|
||||
|
||||
pub fn init(blockData: u16) BranchData {
|
||||
return .{.enabledConnections = @truncate(blockData)};
|
||||
}
|
||||
|
||||
pub fn isConnected(self: @This(), neighbor: Neighbor) bool {
|
||||
return (self.enabledConnections & Neighbor.bitMask(neighbor)) != 0;
|
||||
}
|
||||
|
||||
pub fn setConnection(self: *@This(), neighbor: Neighbor, value: bool) void {
|
||||
if(value) {
|
||||
self.enabledConnections |= Neighbor.bitMask(neighbor);
|
||||
} else {
|
||||
self.enabledConnections &= ~Neighbor.bitMask(neighbor);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn init() void {
|
||||
branchModels = .init(main.globalAllocator.allocator);
|
||||
}
|
||||
|
||||
fn deinit() void {
|
||||
branchModels.deinit();
|
||||
}
|
||||
|
||||
fn branchTransform(quad: *main.models.QuadInfo, data: BranchData) void {
|
||||
for(&quad.corners) |*corner| {
|
||||
if((!data.isConnected(Neighbor.dirNegX) and corner[0] == 0) or
|
||||
(!data.isConnected(Neighbor.dirPosX) and corner[0] == 1) or
|
||||
(!data.isConnected(Neighbor.dirNegY) and corner[1] == 0) or
|
||||
(!data.isConnected(Neighbor.dirPosY) and corner[1] == 1) or
|
||||
(!data.isConnected(Neighbor.dirDown) and corner[2] == 0) or
|
||||
(!data.isConnected(Neighbor.dirUp) and corner[2] == 1)) return degenerateQuad(quad);
|
||||
}
|
||||
}
|
||||
|
||||
fn degenerateQuad(quad: *main.models.QuadInfo) void {
|
||||
for(&quad.corners) |*corner| {
|
||||
corner.* = @splat(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn createBlockModel(modelId: []const u8) u16 {
|
||||
if(branchModels.get(modelId)) |modelIndex| return modelIndex;
|
||||
|
||||
const baseModelIndex = main.models.getModelIndex(modelId);
|
||||
const baseModel = main.models.models.items[baseModelIndex];
|
||||
|
||||
const modelIndex: u16 = baseModel.transformModel(branchTransform, .{BranchData.init(0)});
|
||||
for(1..64) |branchData| {
|
||||
_ = baseModel.transformModel(branchTransform, .{BranchData.init(@truncate(branchData))});
|
||||
}
|
||||
branchModels.put(modelId, modelIndex) catch unreachable;
|
||||
return modelIndex;
|
||||
}
|
||||
|
||||
pub fn model(block: Block) u16 {
|
||||
return blocks.meshes.modelIndexStart(block) + (block.data & 63);
|
||||
}
|
||||
|
||||
pub fn generateData(
|
||||
_: *main.game.World,
|
||||
_: Vec3i,
|
||||
_: Vec3f,
|
||||
_: Vec3f,
|
||||
_: Vec3i,
|
||||
neighbor: ?Neighbor,
|
||||
currentBlock: *Block,
|
||||
neighborBlock: Block,
|
||||
blockPlacing: bool,
|
||||
) bool {
|
||||
const blockBaseModel = blocks.meshes.modelIndexStart(currentBlock.*);
|
||||
const neighborBaseModel = blocks.meshes.modelIndexStart(neighborBlock);
|
||||
|
||||
if(blockPlacing or blockBaseModel == neighborBaseModel or neighborBlock.solid()) {
|
||||
const neighborModel = blocks.meshes.model(neighborBlock);
|
||||
|
||||
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 (blockBaseModel == neighborBaseModel or main.models.models.items[neighborModel].isNeighborOccluded[neighbor.?.reverse().toInt()]));
|
||||
currentData.setConnection(neighbor.?, targetVal);
|
||||
|
||||
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 blockBaseModel = blocks.meshes.modelIndexStart(block.*);
|
||||
const neighborBaseModel = blocks.meshes.modelIndexStart(neighborBlock);
|
||||
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) {
|
||||
const neighborData = BranchData.init(neighborBlock.data);
|
||||
currentData.setConnection(neighbor, neighborData.isConnected(neighbor.reverse()));
|
||||
} else if(!neighborBlock.solid()) {
|
||||
currentData.setConnection(neighbor, false);
|
||||
}
|
||||
|
||||
const result: u16 = currentData.enabledConnections;
|
||||
if(result == block.data) return false;
|
||||
|
||||
block.data = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
fn closestRay(block: Block, relativePlayerPos: Vec3f, playerDir: Vec3f) ?u16 {
|
||||
var closestIntersectionDistance: f64 = std.math.inf(f64);
|
||||
var resultBitMask: ?u16 = null;
|
||||
{
|
||||
const modelIndex = blocks.meshes.modelIndexStart(block);
|
||||
if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| {
|
||||
closestIntersectionDistance = intersection.distance;
|
||||
resultBitMask = 0;
|
||||
}
|
||||
}
|
||||
for(Neighbor.iterable) |direction| {
|
||||
const directionBitMask = Neighbor.bitMask(direction);
|
||||
|
||||
if((block.data & directionBitMask) != 0) {
|
||||
const modelIndex = blocks.meshes.modelIndexStart(block) + directionBitMask;
|
||||
if(RotationMode.DefaultFunctions.rayModelIntersection(modelIndex, relativePlayerPos, playerDir)) |intersection| {
|
||||
if(@abs(closestIntersectionDistance) > @abs(intersection.distance)) {
|
||||
closestIntersectionDistance = intersection.distance;
|
||||
resultBitMask = direction.bitMask();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultBitMask;
|
||||
}
|
||||
|
||||
pub fn onBlockBreaking(_: ?main.items.Item, relativePlayerPos: Vec3f, playerDir: Vec3f, currentData: *Block) void {
|
||||
if(closestRay(currentData.*, relativePlayerPos, playerDir)) |directionBitMask| {
|
||||
// If player destroys a central part of branch block, branch block is completely destroyed.
|
||||
if(directionBitMask == 0) {
|
||||
currentData.typ = 0;
|
||||
currentData.data = 0;
|
||||
return;
|
||||
}
|
||||
// Otherwise only the connection player aimed at is destroyed.
|
||||
currentData.data &= ~directionBitMask;
|
||||
}
|
||||
}
|
||||
};
|
||||
pub const Stairs = struct { // MARK: Stairs
|
||||
pub const id: []const u8 = "stairs";
|
||||
var modelIndex: u16 = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user