mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 19:28:49 -04:00
Remove the Permutation and generate all variants of the fence model.
Progess towards #68
This commit is contained in:
parent
e248d85e1c
commit
0159b65e51
@ -414,7 +414,7 @@ pub const meshes = struct {
|
||||
_ = arenaForWorld.reset(.free_all);
|
||||
}
|
||||
|
||||
pub inline fn model(block: Block) rotation.RotatedModel {
|
||||
pub inline fn model(block: Block) u16 {
|
||||
return block.mode().model(block);
|
||||
}
|
||||
|
||||
|
@ -1880,7 +1880,7 @@ pub fn generateBlockTexture(blockType: u16) Texture {
|
||||
|
||||
var faceData: main.ListUnmanaged(main.renderer.chunk_meshing.FaceData) = .{};
|
||||
defer faceData.deinit(main.stackAllocator);
|
||||
const model = &main.models.models.items[main.blocks.meshes.model(block).modelIndex];
|
||||
const model = &main.models.models.items[main.blocks.meshes.model(block)];
|
||||
model.appendInternalQuadsToList(&faceData, main.stackAllocator, block, 1, 1, 1, false);
|
||||
for(main.chunk.Neighbors.iterable) |neighbor| {
|
||||
model.appendNeighborFacingQuadsToList(&faceData, main.stackAllocator, block, neighbor, 1 + main.chunk.Neighbors.relX[neighbor], 1 + main.chunk.Neighbors.relY[neighbor], 1 + main.chunk.Neighbors.relZ[neighbor], false);
|
||||
|
@ -761,7 +761,7 @@ pub const ItemDropRenderer = struct {
|
||||
if(item == .baseItem and item.baseItem.block != null) {
|
||||
const blockType = item.baseItem.block.?;
|
||||
const block = blocks.Block{.typ = blockType, .data = 0};
|
||||
c.glUniform1i(itemUniforms.modelIndex, block.mode().model(block).modelIndex);
|
||||
c.glUniform1i(itemUniforms.modelIndex, block.mode().model(block));
|
||||
c.glUniform1i(itemUniforms.block, blockType);
|
||||
} else {
|
||||
const index = getModelIndex(item);
|
||||
|
@ -14,7 +14,7 @@ const NeverFailingAllocator = main.utils.NeverFailingAllocator;
|
||||
|
||||
var quadSSBO: graphics.SSBO = undefined;
|
||||
|
||||
const QuadInfo = extern struct {
|
||||
pub const QuadInfo = extern struct {
|
||||
normal: Vec3f,
|
||||
corners: [4]Vec3f,
|
||||
cornerUV: [4]Vec2f,
|
||||
@ -98,7 +98,7 @@ const Model = struct {
|
||||
allocator.free(self.internalQuads);
|
||||
}
|
||||
|
||||
pub fn transformModel(model: Model, transformMatrix: Mat4f) u16 {
|
||||
pub fn transformModel(model: Model, transformFunction: anytype, transformFunctionParameters: anytype) u16 {
|
||||
var quadList = main.List(QuadInfo).init(main.stackAllocator);
|
||||
defer quadList.deinit();
|
||||
for(model.internalQuads) |quadIndex| {
|
||||
@ -114,10 +114,7 @@ const Model = struct {
|
||||
}
|
||||
}
|
||||
for(quadList.items) |*quad| {
|
||||
quad.normal = vec.xyz(Mat4f.mulVec(transformMatrix, vec.combine(quad.normal, 0)));
|
||||
for(&quad.corners) |*corner| {
|
||||
corner.* = vec.xyz(Mat4f.mulVec(transformMatrix, vec.combine(corner.* - Vec3f{0.5, 0.5, 0.5}, 1))) + Vec3f{0.5, 0.5, 0.5};
|
||||
}
|
||||
@call(.auto, transformFunction, .{quad} ++ transformFunctionParameters);
|
||||
}
|
||||
return Model.init(main.globalAllocator, quadList.items);
|
||||
}
|
||||
|
@ -731,7 +731,7 @@ pub const MeshSelection = struct {
|
||||
if(block.typ != 0) {
|
||||
// Check the true bounding box (using this algorithm here: https://tavianator.com/2011/ray_box.html):
|
||||
const model = blocks.meshes.model(block);
|
||||
const modelData = &models.models.items[model.modelIndex];
|
||||
const modelData = &models.models.items[model];
|
||||
const min: Vec3d = @floatCast(modelData.min);
|
||||
const max: Vec3d = @floatCast(modelData.max);
|
||||
const voxelPosFloat: Vec3d = @floatFromInt(voxelPos);
|
||||
@ -864,7 +864,7 @@ pub const MeshSelection = struct {
|
||||
c.glPolygonOffset(-2, 0);
|
||||
const block = mesh_storage.getBlockFromRenderThread(_selectedBlockPos[0], _selectedBlockPos[1], _selectedBlockPos[2]) orelse return;
|
||||
const model = blocks.meshes.model(block);
|
||||
const modelData = &models.models.items[model.modelIndex];
|
||||
const modelData = &models.models.items[model];
|
||||
const min: Vec3f = @floatCast(modelData.min);
|
||||
const max: Vec3f = @floatCast(modelData.max);
|
||||
drawCube(projectionMatrix, viewMatrix, @as(Vec3d, @floatFromInt(_selectedBlockPos)) - playerPos, min, max);
|
||||
|
@ -188,20 +188,20 @@ const PrimitiveMesh = struct {
|
||||
|
||||
fn appendInternalQuadsToCore(self: *PrimitiveMesh, block: Block, x: i32, y: i32, z: i32, comptime backFace: bool) void {
|
||||
const model = blocks.meshes.model(block);
|
||||
models.models.items[model.modelIndex].appendInternalQuadsToList(&self.coreFaces, main.globalAllocator, block, x, y, z, backFace);
|
||||
models.models.items[model].appendInternalQuadsToList(&self.coreFaces, main.globalAllocator, block, x, y, z, backFace);
|
||||
}
|
||||
|
||||
fn appendNeighborFacingQuadsToCore(self: *PrimitiveMesh, block: Block, neighbor: u3, x: i32, y: i32, z: i32, comptime backFace: bool) void {
|
||||
const model = blocks.meshes.model(block);
|
||||
models.models.items[model.modelIndex].appendNeighborFacingQuadsToList(&self.coreFaces, main.globalAllocator, block, neighbor, x, y, z, backFace);
|
||||
models.models.items[model].appendNeighborFacingQuadsToList(&self.coreFaces, main.globalAllocator, block, neighbor, x, y, z, backFace);
|
||||
}
|
||||
|
||||
fn appendNeighborFacingQuadsToNeighbor(self: *PrimitiveMesh, block: Block, neighbor: u3, x: i32, y: i32, z: i32, comptime backFace: bool, comptime isLod: bool) void {
|
||||
const model = blocks.meshes.model(block);
|
||||
if(isLod) {
|
||||
models.models.items[model.modelIndex].appendNeighborFacingQuadsToList(&self.neighborFacesHigherLod[neighbor ^ 1], main.globalAllocator, block, neighbor, x, y, z, backFace);
|
||||
models.models.items[model].appendNeighborFacingQuadsToList(&self.neighborFacesHigherLod[neighbor ^ 1], main.globalAllocator, block, neighbor, x, y, z, backFace);
|
||||
} else {
|
||||
models.models.items[model.modelIndex].appendNeighborFacingQuadsToList(&self.neighborFacesSameLod[neighbor ^ 1], main.globalAllocator, block, neighbor, x, y, z, backFace);
|
||||
models.models.items[model].appendNeighborFacingQuadsToList(&self.neighborFacesSameLod[neighbor ^ 1], main.globalAllocator, block, neighbor, x, y, z, backFace);
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,13 +526,13 @@ pub const ChunkMesh = struct {
|
||||
|
||||
fn canBeSeenThroughOtherBlock(block: Block, other: Block, neighbor: u3) bool {
|
||||
const rotatedModel = blocks.meshes.model(block);
|
||||
const model = &models.models.items[rotatedModel.modelIndex];
|
||||
const model = &models.models.items[rotatedModel];
|
||||
_ = neighbor;
|
||||
_ = model; // TODO: Check if the neighbor model occludes this one. (maybe not that relevant)
|
||||
return block.typ != 0 and (
|
||||
other.typ == 0
|
||||
or (!std.meta.eql(block, other) and other.viewThrough())
|
||||
or blocks.meshes.model(other).modelIndex != 0
|
||||
or blocks.meshes.model(other) != 0
|
||||
);
|
||||
}
|
||||
|
||||
|
269
src/rotation.zig
269
src/rotation.zig
@ -12,124 +12,14 @@ const Vec3d = vec.Vec3d;
|
||||
const Mat4f = vec.Mat4f;
|
||||
|
||||
|
||||
pub const Permutation = packed struct(u6) {
|
||||
/// 0 if x is x, 1 if x and y are swapped, 2 if x and z are swapped
|
||||
permutationX: u2 = 0,
|
||||
/// whether y and z are swapped (applied after permutationX)
|
||||
permutationYZ: bool = false,
|
||||
/// whether the x coordinate of the original model(applied before permutations) is flipped
|
||||
mirrorX: bool = false,
|
||||
/// whether the y coordinate of the original model(applied before permutations) is flipped
|
||||
mirrorY: bool = false,
|
||||
/// whether the z coordinate of the original model(applied before permutations) is flipped
|
||||
mirrorZ: bool = false,
|
||||
|
||||
pub fn toInt(self: Permutation) u6 {
|
||||
return @bitCast(self);
|
||||
}
|
||||
|
||||
pub fn transform(self: Permutation, _x: anytype) @TypeOf(_x) {
|
||||
var x = _x;
|
||||
if(@typeInfo(@TypeOf(x)) != .Vector) @compileError("Can only transform vector types.");
|
||||
if(@typeInfo(@TypeOf(x)).Vector.len != 3) @compileError("Vector needs to have length 3.");
|
||||
if(self.mirrorX) x[0] = -x[0];
|
||||
if(self.mirrorY) x[1] = -x[1];
|
||||
if(self.mirrorZ) x[2] = -x[2];
|
||||
switch(self.permutationX) {
|
||||
0 => {},
|
||||
1 => {
|
||||
const swap = x[0];
|
||||
x[0] = x[1];
|
||||
x[1] = swap;
|
||||
},
|
||||
2 => {
|
||||
const swap = x[0];
|
||||
x[0] = x[2];
|
||||
x[2] = swap;
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
if(self.permutationYZ) {
|
||||
const swap = x[1];
|
||||
x[1] = x[2];
|
||||
x[2] = swap;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
pub fn permuteNeighborIndex(self: Permutation, neighbor: u3) u3 {
|
||||
// TODO: Make this more readable. Not sure how though.
|
||||
const mirrored: u3 = switch(neighbor) {
|
||||
Neighbors.dirNegX,
|
||||
Neighbors.dirPosX => (
|
||||
if(self.mirrorX) neighbor ^ 1
|
||||
else neighbor
|
||||
),
|
||||
Neighbors.dirNegY,
|
||||
Neighbors.dirPosY => (
|
||||
if(self.mirrorY) neighbor ^ 1
|
||||
else neighbor
|
||||
),
|
||||
Neighbors.dirDown,
|
||||
Neighbors.dirUp => (
|
||||
if(self.mirrorZ) neighbor ^ 1
|
||||
else neighbor
|
||||
),
|
||||
else => unreachable,
|
||||
};
|
||||
const afterXPermutation: u3 = switch(mirrored) {
|
||||
Neighbors.dirNegX,
|
||||
Neighbors.dirPosX => (
|
||||
if(self.permutationX == 1) mirrored +% (Neighbors.dirNegY -% Neighbors.dirNegX)
|
||||
else if(self.permutationX == 2) mirrored +% (Neighbors.dirDown -% Neighbors.dirNegX)
|
||||
else mirrored
|
||||
),
|
||||
Neighbors.dirNegY,
|
||||
Neighbors.dirPosY => (
|
||||
if(self.permutationX == 1) mirrored +% (Neighbors.dirNegX -% Neighbors.dirNegY)
|
||||
else mirrored
|
||||
),
|
||||
Neighbors.dirDown,
|
||||
Neighbors.dirUp => (
|
||||
if(self.permutationX == 2) mirrored +% (Neighbors.dirNegX -% Neighbors.dirDown)
|
||||
else mirrored
|
||||
),
|
||||
else => unreachable,
|
||||
};
|
||||
const afterYZPermutation: u3 = switch(afterXPermutation) {
|
||||
Neighbors.dirNegX,
|
||||
Neighbors.dirPosX => afterXPermutation,
|
||||
Neighbors.dirNegY,
|
||||
Neighbors.dirPosY => (
|
||||
if(self.permutationYZ) afterXPermutation +% (Neighbors.dirDown -% Neighbors.dirNegY)
|
||||
else afterXPermutation
|
||||
),
|
||||
Neighbors.dirDown,
|
||||
Neighbors.dirUp => (
|
||||
if(self.permutationYZ) afterXPermutation +% (Neighbors.dirNegY -% Neighbors.dirDown)
|
||||
else afterXPermutation
|
||||
),
|
||||
else => unreachable,
|
||||
};
|
||||
return afterYZPermutation;
|
||||
}
|
||||
};
|
||||
|
||||
pub const RotatedModel = struct {
|
||||
modelIndex: u16,
|
||||
permutation: Permutation = Permutation{},
|
||||
};
|
||||
|
||||
// TODO: Why not just use a tagged union?
|
||||
/// Each block gets 16 bit of additional storage(apart from the reference to the block type).
|
||||
/// These 16 bits are accessed and interpreted by the `RotationMode`.
|
||||
/// With the `RotationMode` interface there is almost no limit to what can be done with those 16 bit.
|
||||
pub const RotationMode = struct {
|
||||
const DefaultFunctions = struct {
|
||||
fn model(block: Block) RotatedModel {
|
||||
return RotatedModel{
|
||||
.modelIndex = blocks.meshes.modelIndexStart(block),
|
||||
};
|
||||
fn model(block: Block) u16 {
|
||||
return blocks.meshes.modelIndexStart(block);
|
||||
}
|
||||
fn generateData(_: *main.game.World, _: Vec3i, _: Vec3d, _: Vec3f, _: Vec3i, _: *Block, blockPlacing: bool) bool {
|
||||
return blockPlacing;
|
||||
@ -142,32 +32,17 @@ pub const RotationMode = struct {
|
||||
/// if the block should be destroyed or changed when a certain neighbor is removed.
|
||||
dependsOnNeighbors: bool = false,
|
||||
|
||||
model: *const fn(block: Block) RotatedModel = &DefaultFunctions.model,
|
||||
model: *const fn(block: Block) u16 = &DefaultFunctions.model,
|
||||
|
||||
createBlockModel: *const fn(modelId: []const u8) u16 = &DefaultFunctions.createBlockModel,
|
||||
|
||||
/// Updates the block data of a block in the world or places a block in the world.
|
||||
/// return true if the placing was successful, false otherwise.
|
||||
generateData: *const fn(world: *main.game.World, pos: Vec3i, relativePlayerPos: Vec3d, playerDir: Vec3f, relativeDir: Vec3i, currentData: *Block, blockPlacing: bool) bool = DefaultFunctions.generateData,
|
||||
|
||||
createBlockModel: *const fn(modelId: []const u8) u16 = &DefaultFunctions.createBlockModel,
|
||||
};
|
||||
|
||||
//public interface RotationMode extends RegistryElement {
|
||||
// /**
|
||||
// * Update or place a block.
|
||||
// * @param world
|
||||
// * @param x
|
||||
// * @param y
|
||||
// * @param z
|
||||
// * @param relativePlayerPosition Position of the player head relative to the (0, 0, 0) corner of the block.
|
||||
// * @param playerDirection
|
||||
// * @param relativeDir the direction in which the selected neighbor is.
|
||||
// * @param currentData 0 if no block was there before.
|
||||
// * @param blockPlacing true if the position of the block was previously empty/nonsolid.
|
||||
// * @return true if the placing was successful, false otherwise.
|
||||
// */
|
||||
// boolean generateData(World world, int x, int y, int z, Vector3d relativePlayerPosition, Vector3f playerDirection, Vector3i relativeDir, IntWrapper currentData, boolean blockPlacing);
|
||||
//
|
||||
// /**
|
||||
// * Updates data of a placed block if the RotationMode dependsOnNeighbors().
|
||||
// * If the returned value is null, then the block will be removed instead of only updating the data.
|
||||
// * @param oldBlock
|
||||
@ -187,12 +62,6 @@ pub const RotationMode = struct {
|
||||
// * @return standard data for natural generation.
|
||||
// */
|
||||
// int getNaturalStandard(int block);
|
||||
//
|
||||
// /**
|
||||
// * @param min minimal point of the surrounding block. May be overwritten.
|
||||
// * @param max maximal point of the surrounding block. May be overwritten.
|
||||
// */
|
||||
// float getRayIntersection(RayAabIntersection intersection, int block, Vector3f min, Vector3f max, Vector3f transformedPosition);
|
||||
//
|
||||
// /**
|
||||
// * Check if the entity would collide with the block.
|
||||
@ -211,6 +80,13 @@ pub const RotationMode = struct {
|
||||
|
||||
var rotationModes: std.StringHashMap(RotationMode) = undefined;
|
||||
|
||||
fn rotationMatrixTransform(quad: *main.models.QuadInfo, transformMatrix: Mat4f) void {
|
||||
quad.normal = vec.xyz(Mat4f.mulVec(transformMatrix, vec.combine(quad.normal, 0)));
|
||||
for(&quad.corners) |*corner| {
|
||||
corner.* = vec.xyz(Mat4f.mulVec(transformMatrix, vec.combine(corner.* - Vec3f{0.5, 0.5, 0.5}, 1))) + Vec3f{0.5, 0.5, 0.5};
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Instead of using a permutation, rotation modes should directly return a rotated version of the model.
|
||||
|
||||
const RotationModes = struct {
|
||||
@ -231,29 +107,26 @@ const RotationModes = struct {
|
||||
rotatedModels.deinit();
|
||||
}
|
||||
|
||||
pub fn model(block: Block) RotatedModel {
|
||||
return RotatedModel{
|
||||
.modelIndex = blocks.meshes.modelIndexStart(block) + @min(block.data, 5),
|
||||
.permutation = undefined,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn createBlockModel(modelId: []const u8) u16 {
|
||||
if(rotatedModels.get(modelId)) |modelIndex| return modelIndex;
|
||||
|
||||
const baseModelIndex = main.models.getModelIndex(modelId);
|
||||
const baseModel = main.models.models.items[baseModelIndex];
|
||||
// Rotate the model:
|
||||
const modelIndex: u16 = baseModel.transformModel(Mat4f.identity());
|
||||
_ = baseModel.transformModel(Mat4f.rotationY(std.math.pi));
|
||||
_ = baseModel.transformModel(Mat4f.rotationY(std.math.pi/2.0));
|
||||
_ = baseModel.transformModel(Mat4f.rotationY(-std.math.pi/2.0));
|
||||
_ = baseModel.transformModel(Mat4f.rotationX(-std.math.pi/2.0));
|
||||
_ = baseModel.transformModel(Mat4f.rotationX(std.math.pi/2.0));
|
||||
const modelIndex: u16 = baseModel.transformModel(rotationMatrixTransform, .{Mat4f.identity()});
|
||||
_ = baseModel.transformModel(rotationMatrixTransform, .{Mat4f.rotationY(std.math.pi)});
|
||||
_ = baseModel.transformModel(rotationMatrixTransform, .{Mat4f.rotationY(std.math.pi/2.0)});
|
||||
_ = baseModel.transformModel(rotationMatrixTransform, .{Mat4f.rotationY(-std.math.pi/2.0)});
|
||||
_ = baseModel.transformModel(rotationMatrixTransform, .{Mat4f.rotationX(-std.math.pi/2.0)});
|
||||
_ = baseModel.transformModel(rotationMatrixTransform, .{Mat4f.rotationX(std.math.pi/2.0)});
|
||||
rotatedModels.put(modelId, modelIndex) catch unreachable;
|
||||
return modelIndex;
|
||||
}
|
||||
|
||||
pub fn model(block: Block) u16 {
|
||||
return blocks.meshes.modelIndexStart(block) + @min(block.data, 5);
|
||||
}
|
||||
|
||||
pub fn generateData(_: *main.game.World, _: Vec3i, _: Vec3d, _: Vec3f, relativeDir: Vec3i, currentData: *Block, blockPlacing: bool) bool {
|
||||
if(blockPlacing) {
|
||||
if(relativeDir[0] == 1) currentData.data = chunk.Neighbors.dirNegX;
|
||||
@ -269,52 +142,60 @@ const RotationModes = struct {
|
||||
};
|
||||
pub const Fence = struct {
|
||||
pub const id: []const u8 = "fence";
|
||||
// TODO:
|
||||
fn init() void {}
|
||||
fn deinit() void {}
|
||||
pub const dependsOnNeighbors = true;
|
||||
var fenceModels: std.StringHashMap(u16) = undefined;
|
||||
const FenceData = packed struct(u4) {
|
||||
isConnectedNegX: bool,
|
||||
isConnectedPosX: bool,
|
||||
isConnectedNegY: bool,
|
||||
isConnectedPosY: bool,
|
||||
};
|
||||
|
||||
pub fn model(block: Block) RotatedModel {
|
||||
const data = block.data>>2 & 15; // TODO: This is just for compatibility with the java version. Remove it.
|
||||
const modelIndexOffsets = [16]u16 {
|
||||
0, // 0b0000
|
||||
1, // 0b0001
|
||||
1, // 0b0010
|
||||
3, // 0b0011
|
||||
1, // 0b0100
|
||||
2, // 0b0101
|
||||
2, // 0b0110
|
||||
4, // 0b0111
|
||||
1, // 0b1000
|
||||
2, // 0b1001
|
||||
2, // 0b1010
|
||||
4, // 0b1011
|
||||
3, // 0b1100
|
||||
4, // 0b1101
|
||||
4, // 0b1110
|
||||
5, // 0b1111
|
||||
};
|
||||
const permutations = [16]Permutation {
|
||||
Permutation{}, // 0b0000
|
||||
Permutation{.mirrorX = true, .mirrorZ = true}, // 0b0001
|
||||
Permutation{}, // 0b0010
|
||||
Permutation{}, // 0b0011
|
||||
Permutation{.permutationX = 2, .mirrorZ = true}, // 0b0100
|
||||
Permutation{.mirrorX = true, .mirrorZ = true}, // 0b0101
|
||||
Permutation{.permutationX = 2, .mirrorZ = true}, // 0b0110
|
||||
Permutation{.permutationX = 2, .mirrorX = true}, // 0b0111
|
||||
Permutation{.permutationX = 2, .mirrorX = true}, // 0b1000
|
||||
Permutation{.permutationX = 2, .mirrorX = true}, // 0b1001
|
||||
Permutation{}, // 0b1010
|
||||
Permutation{.permutationX = 2, .mirrorZ = true}, // 0b1011
|
||||
Permutation{.permutationX = 2, .mirrorX = true}, // 0b1100
|
||||
Permutation{}, // 0b1101
|
||||
Permutation{.mirrorX = true, .mirrorZ = true}, // 0b1110
|
||||
Permutation{}, // 0b1111
|
||||
};
|
||||
return RotatedModel{
|
||||
.modelIndex = blocks.meshes.modelIndexStart(block) + modelIndexOffsets[data],
|
||||
.permutation = permutations[data],
|
||||
};
|
||||
fn init() void {
|
||||
fenceModels = std.StringHashMap(u16).init(main.globalAllocator.allocator);
|
||||
}
|
||||
|
||||
fn deinit() void {
|
||||
fenceModels.deinit();
|
||||
}
|
||||
|
||||
fn fenceTransform(quad: *main.models.QuadInfo, data: FenceData) void {
|
||||
for(&quad.corners, &quad.cornerUV) |*corner, *cornerUV| {
|
||||
if(!data.isConnectedNegX and corner[0] == 0) {
|
||||
corner[0] = 0.5;
|
||||
cornerUV[0] = 0.5;
|
||||
}
|
||||
if(!data.isConnectedPosX and corner[0] == 1) {
|
||||
corner[0] = 0.5;
|
||||
cornerUV[0] = 0.5;
|
||||
}
|
||||
if(!data.isConnectedNegY and corner[1] == 0) {
|
||||
corner[1] = 0.5;
|
||||
cornerUV[0] = 0.5;
|
||||
}
|
||||
if(!data.isConnectedPosY and corner[1] == 1) {
|
||||
corner[1] = 0.5;
|
||||
cornerUV[0] = 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn createBlockModel(modelId: []const u8) u16 {
|
||||
if(fenceModels.get(modelId)) |modelIndex| return modelIndex;
|
||||
|
||||
const baseModelIndex = main.models.getModelIndex(modelId);
|
||||
const baseModel = main.models.models.items[baseModelIndex];
|
||||
// Rotate the model:
|
||||
const modelIndex: u16 = baseModel.transformModel(fenceTransform, .{@as(FenceData, @bitCast(@as(u4, 0)))});
|
||||
for(1..16) |fenceData| {
|
||||
_ = baseModel.transformModel(fenceTransform, .{@as(FenceData, @bitCast(@as(u4, @intCast(fenceData))))});
|
||||
}
|
||||
fenceModels.put(modelId, modelIndex) catch unreachable;
|
||||
return modelIndex;
|
||||
}
|
||||
|
||||
pub fn model(block: Block) u16 {
|
||||
return blocks.meshes.modelIndexStart(block) + @min(block.data, 15);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user