mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-09 12:16:24 -04:00
Start working on rotation modes.
This commit is contained in:
parent
56f83aedbc
commit
cbd3abea49
@ -8,6 +8,8 @@ const Color = @import("graphics.zig").Color;
|
||||
const TextureArray = @import("graphics.zig").TextureArray;
|
||||
const items = @import("items.zig");
|
||||
const models = @import("models.zig");
|
||||
const rotation = @import("rotation.zig");
|
||||
const RotationMode = rotation.RotationMode;
|
||||
|
||||
pub const BlockClass = enum(u8) {
|
||||
wood,
|
||||
@ -29,8 +31,6 @@ pub const BlockDrop = struct {
|
||||
amount: f32,
|
||||
};
|
||||
|
||||
pub const RotationMode = u0; // TODO!
|
||||
|
||||
var _lightingTransparent: [MaxBLockCount]bool = undefined;
|
||||
var _transparent: [MaxBLockCount]bool = undefined;
|
||||
var _id: [MaxBLockCount][]u8 = undefined;
|
||||
@ -50,7 +50,7 @@ var _light: [MaxBLockCount]u32 = undefined;
|
||||
var _absorption: [MaxBLockCount]u32 = undefined;
|
||||
/// GUI that is opened on click.
|
||||
var _gui: [MaxBLockCount][]u8 = undefined;
|
||||
var _mode: [MaxBLockCount]RotationMode = undefined;
|
||||
var _mode: [MaxBLockCount]*RotationMode = undefined;
|
||||
|
||||
var reverseIndices = std.StringHashMap(u16).init(arena.allocator());
|
||||
|
||||
@ -62,9 +62,8 @@ pub fn register(_: []const u8, id: []const u8, json: JsonElement) !u16 {
|
||||
}
|
||||
_id[size] = try allocator.dupe(u8, id);
|
||||
try reverseIndices.put(_id[size], @intCast(u16, size));
|
||||
// TODO:
|
||||
// _mode[size] = CubyzRegistries.ROTATION_MODE_REGISTRY.getByID(json.getString("rotation", "cubyz:no_rotation"));
|
||||
// _blockDrops[size] = new BlockDrop[0];
|
||||
|
||||
_mode[size] = rotation.getByID(json.get([]const u8, "rotation", "cubyz:no_rotation"));
|
||||
_breakingPower[size] = json.get(f32, "breakingPower", 0);
|
||||
_hardness[size] = json.get(f32, "hardness", 1);
|
||||
|
||||
@ -217,7 +216,7 @@ pub const Block = packed struct {
|
||||
return _gui[self.typ];
|
||||
}
|
||||
|
||||
pub fn mode(self: Block) RotationMode {
|
||||
pub fn mode(self: Block) *RotationMode {
|
||||
return _mode[self.typ];
|
||||
}
|
||||
|
||||
@ -240,7 +239,7 @@ pub const Block = packed struct {
|
||||
|
||||
pub const meshes = struct {
|
||||
var size: u32 = 0;
|
||||
var _modelIndices: [MaxBLockCount]u16 = undefined;
|
||||
var _modelIndex: [MaxBLockCount]u16 = undefined;
|
||||
var _textureIndices: [MaxBLockCount][6]u32 = undefined;
|
||||
/// Stores the number of textures after each block was added. Used to clean additional textures when the world is switched.
|
||||
var maxTextureCount: [MaxBLockCount]u32 = undefined;
|
||||
@ -317,8 +316,12 @@ pub const meshes = struct {
|
||||
arenaForWorld = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
}
|
||||
|
||||
pub fn modelIndices(block: Block) u16 {
|
||||
return (&_modelIndices[block.typ]).*;
|
||||
pub fn modelIndex(block: Block) u16 {
|
||||
return block.mode().modelIndex(block);
|
||||
}
|
||||
|
||||
pub fn modelIndexStart(block: Block) u16 {
|
||||
return _modelIndex[block.typ];
|
||||
}
|
||||
|
||||
pub fn textureIndices(block: Block) *const [6] u32 {
|
||||
@ -421,7 +424,7 @@ pub const meshes = struct {
|
||||
}
|
||||
|
||||
pub fn register(assetFolder: []const u8, _: []const u8, json: JsonElement) !void {
|
||||
_modelIndices[meshes.size] = models.getModelIndex(json.get([]const u8, "model", "cube"));
|
||||
_modelIndex[meshes.size] = models.getModelIndex(json.get([]const u8, "model", "cube"));
|
||||
|
||||
// The actual model is loaded later, in the rendering thread.
|
||||
// But textures can be loaded here:
|
||||
|
@ -482,7 +482,7 @@ pub const meshing = struct {
|
||||
}
|
||||
|
||||
fn canBeSeenThroughOtherBlock(block: Block, other: Block, neighbor: u3) bool {
|
||||
const model = &models.voxelModels.items[blocks.meshes.modelIndices(block)];
|
||||
const model = &models.voxelModels.items[blocks.meshes.modelIndex(block)];
|
||||
const freestandingModel = blk:{
|
||||
switch(neighbor) {
|
||||
Neighbors.dirNegX => {
|
||||
@ -509,9 +509,8 @@ pub const meshing = struct {
|
||||
return block.typ != 0 and (
|
||||
freestandingModel
|
||||
or other.typ == 0
|
||||
or false // TODO: Blocks.mode(other).checkTransparency(other, neighbor) // TODO: make blocks.meshes.modelIndices(other) != 0 more strict to avoid overdraw.
|
||||
or (!std.meta.eql(block, other) and other.viewThrough())
|
||||
or blocks.meshes.modelIndices(other) != 0
|
||||
or blocks.meshes.modelIndex(other) != 0 // TODO: make this more strict to avoid overdraw.
|
||||
);
|
||||
}
|
||||
|
||||
@ -538,7 +537,7 @@ pub const meshing = struct {
|
||||
if(canBeSeenThroughOtherBlock(block, neighborBlock, i)) {
|
||||
const normal: u32 = i;
|
||||
const positionNormal: u32 = @intCast(u32, x2) | @intCast(u32, y2)<<5 | @intCast(u32, z2)<<10 | normal<<24;
|
||||
const textureModel = blocks.meshes.textureIndices(block)[i] | @as(u32, blocks.meshes.modelIndices(block))<<16;
|
||||
const textureModel = blocks.meshes.textureIndices(block)[i] | @as(u32, blocks.meshes.modelIndex(block))<<16;
|
||||
try self.faces.append(positionNormal);
|
||||
try self.faces.append(textureModel);
|
||||
}
|
||||
@ -649,8 +648,8 @@ pub const meshing = struct {
|
||||
const newVisibility = canBeSeenThroughOtherBlock(newBlock, neighborBlock, neighbor);
|
||||
const normal: u32 = neighbor;
|
||||
const position: u32 = @intCast(u32, nx) | @intCast(u32, ny)<<5 | @intCast(u32, nz)<<10 | normal<<24;
|
||||
const newTextureNormal = blocks.meshes.textureIndices(newBlock)[neighbor] | @as(u32, blocks.meshes.modelIndices(newBlock))<<16;
|
||||
const oldTextureNormal = blocks.meshes.textureIndices(oldBlock)[neighbor] | @as(u32, blocks.meshes.modelIndices(oldBlock))<<16;
|
||||
const newTextureNormal = blocks.meshes.textureIndices(newBlock)[neighbor] | @as(u32, blocks.meshes.modelIndex(newBlock))<<16;
|
||||
const oldTextureNormal = blocks.meshes.textureIndices(oldBlock)[neighbor] | @as(u32, blocks.meshes.modelIndex(oldBlock))<<16;
|
||||
if(canBeSeenThroughOtherBlock(oldBlock, neighborBlock, neighbor) != newVisibility) {
|
||||
if(newVisibility) { // Adding the face
|
||||
if(neighborMesh == self) {
|
||||
@ -677,8 +676,8 @@ pub const meshing = struct {
|
||||
const newVisibility = canBeSeenThroughOtherBlock(neighborBlock, newBlock, neighbor ^ 1);
|
||||
const normal: u32 = neighbor ^ 1;
|
||||
const position: u32 = @intCast(u32, x) | @intCast(u32, y)<<5 | @intCast(u32, z)<<10 | normal<<24;
|
||||
const newTextureNormal = blocks.meshes.textureIndices(neighborBlock)[neighbor] | @as(u32, blocks.meshes.modelIndices(neighborBlock))<<16;
|
||||
const oldTextureNormal = blocks.meshes.textureIndices(neighborBlock)[neighbor] | @as(u32, blocks.meshes.modelIndices(neighborBlock))<<16;
|
||||
const newTextureNormal = blocks.meshes.textureIndices(neighborBlock)[neighbor] | @as(u32, blocks.meshes.modelIndex(neighborBlock))<<16;
|
||||
const oldTextureNormal = blocks.meshes.textureIndices(neighborBlock)[neighbor] | @as(u32, blocks.meshes.modelIndex(neighborBlock))<<16;
|
||||
if(canBeSeenThroughOtherBlock(neighborBlock, oldBlock, neighbor ^ 1) != newVisibility) {
|
||||
if(newVisibility) { // Adding the face
|
||||
if(neighborMesh == self) {
|
||||
@ -757,14 +756,14 @@ pub const meshing = struct {
|
||||
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
|
||||
const normal: u32 = neighbor;
|
||||
const position: u32 = @as(u32, otherX) | @as(u32, otherY)<<5 | @as(u32, otherZ)<<10 | normal<<24;
|
||||
const textureNormal = blocks.meshes.textureIndices(block)[neighbor] | @as(u32, blocks.meshes.modelIndices(block))<<16;
|
||||
const textureNormal = blocks.meshes.textureIndices(block)[neighbor] | @as(u32, blocks.meshes.modelIndex(block))<<16;
|
||||
try additionalNeighborFaces.append(position);
|
||||
try additionalNeighborFaces.append(textureNormal);
|
||||
}
|
||||
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
|
||||
const normal: u32 = neighbor ^ 1;
|
||||
const position: u32 = @as(u32, x) | @as(u32, y)<<5 | @as(u32, z)<<10 | normal<<24;
|
||||
const textureNormal = blocks.meshes.textureIndices(otherBlock)[neighbor ^ 1] | @as(u32, blocks.meshes.modelIndices(otherBlock))<<16;
|
||||
const textureNormal = blocks.meshes.textureIndices(otherBlock)[neighbor ^ 1] | @as(u32, blocks.meshes.modelIndex(otherBlock))<<16;
|
||||
try self.faces.append(position);
|
||||
try self.faces.append(textureNormal);
|
||||
}
|
||||
@ -818,7 +817,7 @@ pub const meshing = struct {
|
||||
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
|
||||
const normal: u32 = neighbor ^ 1;
|
||||
const position: u32 = @as(u32, x) | @as(u32, y)<<5 | @as(u32, z)<<10 | normal<<24;
|
||||
const textureNormal = blocks.meshes.textureIndices(otherBlock)[neighbor ^ 1] | @as(u32, blocks.meshes.modelIndices(otherBlock))<<16;
|
||||
const textureNormal = blocks.meshes.textureIndices(otherBlock)[neighbor ^ 1] | @as(u32, blocks.meshes.modelIndex(otherBlock))<<16;
|
||||
try self.faces.append(position);
|
||||
try self.faces.append(textureNormal);
|
||||
}
|
||||
|
@ -8,8 +8,9 @@ const game = @import("game.zig");
|
||||
const graphics = @import("graphics.zig");
|
||||
const items = @import("items.zig");
|
||||
const models = @import("models.zig");
|
||||
const renderer = @import("renderer.zig");
|
||||
const network = @import("network.zig");
|
||||
const renderer = @import("renderer.zig");
|
||||
const rotation = @import("rotation.zig");
|
||||
const settings = @import("settings.zig");
|
||||
const utils = @import("utils.zig");
|
||||
|
||||
@ -249,6 +250,9 @@ pub fn main() !void {
|
||||
graphics.init();
|
||||
defer graphics.deinit();
|
||||
|
||||
try rotation.init();
|
||||
defer rotation.deinit();
|
||||
|
||||
try models.init();
|
||||
defer models.deinit();
|
||||
|
||||
|
@ -637,7 +637,7 @@ pub const MeshSelection = struct {
|
||||
const block = RenderStructure.getBlock(x, y, z) orelse break;
|
||||
if(block.typ != 0) {
|
||||
// Check the true bounding box (using this algorithm here: https://tavianator.com/2011/ray_box.html):
|
||||
const voxelModel = &models.voxelModels.items[blocks.meshes.modelIndices(block)];
|
||||
const voxelModel = &models.voxelModels.items[blocks.meshes.modelIndex(block)];
|
||||
const tx1 = (@intToFloat(f64, x) + @intToFloat(f64, voxelModel.minX)/16.0 - pos[0])*invDirX;
|
||||
const tx2 = (@intToFloat(f64, x) + @intToFloat(f64, voxelModel.maxX)/16.0 - pos[0])*invDirX;
|
||||
const ty1 = (@intToFloat(f64, y) + @intToFloat(f64, voxelModel.minY)/16.0 - pos[1])*invDirY;
|
||||
@ -774,7 +774,7 @@ pub const MeshSelection = struct {
|
||||
pub fn render(projectionMatrix: Mat4f, viewMatrix: Mat4f, playerPos: Vec3d) void {
|
||||
if(selectedBlockPos) |_selectedBlockPos| {
|
||||
var block = RenderStructure.getBlock(_selectedBlockPos[0], _selectedBlockPos[1], _selectedBlockPos[2]) orelse return;
|
||||
var voxelModel = &models.voxelModels.items[blocks.meshes.modelIndices(block)];
|
||||
var voxelModel = &models.voxelModels.items[blocks.meshes.modelIndex(block)];
|
||||
shader.bind();
|
||||
|
||||
c.glUniformMatrix4fv(uniforms.projectionMatrix, 1, c.GL_FALSE, @ptrCast([*c]const f32, &projectionMatrix));
|
||||
|
129
src/rotation.zig
Normal file
129
src/rotation.zig
Normal file
@ -0,0 +1,129 @@
|
||||
const std = @import("std");
|
||||
|
||||
const blocks = @import("blocks.zig");
|
||||
const Block = blocks.Block;
|
||||
const main = @import("main.zig");
|
||||
|
||||
|
||||
/// 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 modelIndex(block: Block) u16 {
|
||||
return blocks.meshes.modelIndexStart(block);
|
||||
}
|
||||
};
|
||||
|
||||
id: []const u8,
|
||||
/// if the block should be destroyed or changed when a certain neighbor is removed.
|
||||
dependsOnNeighbors: bool = false,
|
||||
|
||||
modelIndex: *const fn(block: Block) u16 = &DefaultFunctions.modelIndex,
|
||||
};
|
||||
|
||||
//public interface RotationMode extends RegistryElement {
|
||||
// /**
|
||||
// * Called when generating the chunk mesh.
|
||||
// * @param bi
|
||||
// * @param vertices
|
||||
// * @param faces
|
||||
// * @return incremented renderIndex
|
||||
// */
|
||||
// void generateChunkMesh(BlockInstance bi, VertexAttribList vertices, IntSimpleList faces);
|
||||
//
|
||||
// /**
|
||||
// * 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
|
||||
// * @param removedDir given as neighbor index (See NormalChunk.)
|
||||
// * @return new data
|
||||
// */
|
||||
// int updateData(int oldBlock, int removedDir, int newNeighbor);
|
||||
//
|
||||
// /**
|
||||
// * A RotationMode may even alter the blocks transparency. Here is where it's done.
|
||||
// * @param block The blocks data
|
||||
// * @param neighbor the inverted(!) neighbor index(see Neighbors.java).
|
||||
// */
|
||||
// boolean checkTransparency(int block, int neighbor);
|
||||
//
|
||||
// /**
|
||||
// * @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.
|
||||
// * @return Whether the entity and block hitboxes overlap.
|
||||
// */
|
||||
// boolean checkEntity(Vector3d pos, double width, double height, int x, int y, int z, int block);
|
||||
//
|
||||
// /**
|
||||
// * Check if the entity would collide with the block, if its position was changed by `vel`.
|
||||
// * If a collision occurs, adjust the velocity in way such that the entity does not move inside the block.
|
||||
// * @param vel Velocity of the entity. The 4th element is reserved for stepping: a y-movement that is done exactly once.
|
||||
// * @return Returns true if the block behaves like a normal block and therefor needs to be handled like a normal block in the specified direction. Returns false if everything has been handled already in here.
|
||||
// */
|
||||
// boolean checkEntityAndDoCollision(Entity ent, Vector4d vel, int x, int y, int z, int block);
|
||||
//}
|
||||
|
||||
var rotationModes: std.StringHashMap(RotationMode) = undefined;
|
||||
|
||||
const RotationModes = struct {
|
||||
const NoRotation = struct {
|
||||
const id: []const u8 = "cubyz:no_rotation";
|
||||
};
|
||||
};
|
||||
|
||||
pub fn init() !void {
|
||||
rotationModes = std.StringHashMap(RotationMode).init(main.globalAllocator);
|
||||
inline for(@typeInfo(RotationModes).Struct.decls) |declaration| {
|
||||
try register(@field(RotationModes, declaration.name));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
rotationModes.deinit();
|
||||
}
|
||||
|
||||
pub fn getByID(id: []const u8) *RotationMode {
|
||||
if(rotationModes.getPtr(id)) |mode| return mode;
|
||||
std.log.warn("Could not find rotation mode {s}. Using cubyz:no_rotation instead.", .{id});
|
||||
return rotationModes.getPtr("cubyz:no_rotation").?;
|
||||
}
|
||||
|
||||
pub fn register(comptime Mode: type) !void {
|
||||
var result: RotationMode = RotationMode{.id = Mode.id};
|
||||
inline for(@typeInfo(RotationMode).Struct.fields) |field| {
|
||||
if(@hasDecl(Mode, field.name)) {
|
||||
if(field.field_type == @TypeOf(@field(Mode, field.name))) {
|
||||
@field(result, field.name) = @field(Mode, field.name);
|
||||
} else {
|
||||
@field(result, field.name) = &@field(Mode, field.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
try rotationModes.putNoClobber(result.id, result);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user