Blocks and chunks
This commit is contained in:
262
src/assets/Blocks.zig
Normal file
262
src/assets/Blocks.zig
Normal file
@@ -0,0 +1,262 @@
|
||||
const Blocks = @This();
|
||||
const std = @import("std");
|
||||
|
||||
const atoms = @import("../engine/atoms.zig");
|
||||
const Engine = @import("../engine/Engine.zig");
|
||||
const Materials = @import("Materials.zig");
|
||||
const Textures = @import("Textures.zig");
|
||||
|
||||
pub const Block = struct {
|
||||
positive_x: Materials.Id,
|
||||
negative_x: Materials.Id,
|
||||
positive_y: Materials.Id,
|
||||
negative_y: Materials.Id,
|
||||
positive_z: Materials.Id,
|
||||
negative_z: Materials.Id,
|
||||
|
||||
pub fn initUniform(material: Materials.Id) Block {
|
||||
return .{
|
||||
.positive_x = material,
|
||||
.negative_x = material,
|
||||
.positive_y = material,
|
||||
.negative_y = material,
|
||||
.positive_z = material,
|
||||
.negative_z = material,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initSeparate(
|
||||
positive_x: Materials.Id,
|
||||
negative_x: Materials.Id,
|
||||
positive_y: Materials.Id,
|
||||
negative_y: Materials.Id,
|
||||
positive_z: Materials.Id,
|
||||
negative_z: Materials.Id,
|
||||
) Block {
|
||||
return .{
|
||||
.positive_x = positive_x,
|
||||
.negative_x = negative_x,
|
||||
.positive_y = positive_y,
|
||||
.negative_y = negative_y,
|
||||
.positive_z = positive_z,
|
||||
.negative_z = negative_z,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initArray(materials: [6]Materials.Id) Block {
|
||||
return .{
|
||||
.positive_x = materials[0],
|
||||
.negative_x = materials[1],
|
||||
.positive_y = materials[2],
|
||||
.negative_y = materials[3],
|
||||
.positive_z = materials[4],
|
||||
.negative_z = materials[5],
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
map: Map,
|
||||
blocks: Array,
|
||||
|
||||
pub const capacity = std.math.maxInt(std.meta.Tag(Id));
|
||||
|
||||
pub const Key = struct { atom: atoms.Atom };
|
||||
pub const Id = enum(u12) {
|
||||
air = 0,
|
||||
_,
|
||||
|
||||
pub fn next(self: Id) Id {
|
||||
return @enumFromInt(@intFromEnum(self) + 1);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Map = std.AutoHashMapUnmanaged(Key, Id);
|
||||
pub const Array = std.ArrayList(Block);
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) !Blocks {
|
||||
var map: Map = .empty;
|
||||
errdefer map.deinit(allocator);
|
||||
try map.ensureTotalCapacity(allocator, capacity);
|
||||
|
||||
var blocks: Array = try .initCapacity(allocator, capacity);
|
||||
errdefer blocks.deinit(allocator);
|
||||
|
||||
const air = Block.initUniform(.empty);
|
||||
blocks.appendAssumeCapacity(air);
|
||||
|
||||
return .{
|
||||
.map = map,
|
||||
.blocks = blocks,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Blocks, allocator: std.mem.Allocator) void {
|
||||
std.log.debug("Deinitializing {*} with Allocator{{{*},{*}}}", .{ self, allocator.ptr, allocator.vtable });
|
||||
|
||||
self.blocks.deinit(allocator);
|
||||
self.map.deinit(allocator);
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn getAtom(self: *const Blocks, atom: atoms.Atom) ?Id {
|
||||
const key: Key = .{ .atom = atom };
|
||||
return self.map.get(key);
|
||||
}
|
||||
|
||||
pub fn getFilename(self: *const Blocks, filename: []const u8) ?Id {
|
||||
const atom = atoms.getAtom(filename) orelse return null;
|
||||
const key: Key = .{ .atom = atom };
|
||||
return self.map.get(key);
|
||||
}
|
||||
|
||||
pub fn getBlock(self: *const Blocks, id: Id) ?*Block {
|
||||
const index: usize = @intFromEnum(id);
|
||||
return if (index < self.blocks.items.len) &self.blocks.items[index] else null;
|
||||
}
|
||||
|
||||
pub fn getOrLoadAtom(
|
||||
self: *Blocks,
|
||||
engine: *Engine,
|
||||
materials: *Materials,
|
||||
textures: *Textures,
|
||||
atom: atoms.Atom,
|
||||
temp_allocator: std.mem.Allocator,
|
||||
) !Id {
|
||||
const key: Key = .{ .atom = atom };
|
||||
const entry = self.map.getOrPutAssumeCapacity(key);
|
||||
|
||||
if (entry.found_existing) {
|
||||
return entry.value_ptr.*;
|
||||
} else {
|
||||
errdefer _ = self.map.remove(key);
|
||||
const block = try loadBlock(engine, materials, textures, atoms.getString(atom), temp_allocator);
|
||||
const id = self.nextId();
|
||||
entry.value_ptr.* = id;
|
||||
self.blocks.appendAssumeCapacity(block);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getOrLoadFilename(
|
||||
self: *Blocks,
|
||||
engine: *Engine,
|
||||
materials: *Materials,
|
||||
textures: *Textures,
|
||||
filename: []const u8,
|
||||
temp_allocator: std.mem.Allocator,
|
||||
) !Id {
|
||||
const atom = try atoms.getOrPutAtom(filename);
|
||||
const key: Key = .{ .atom = atom };
|
||||
const entry = self.map.getOrPutAssumeCapacity(key);
|
||||
|
||||
if (entry.found_existing) {
|
||||
return entry.value_ptr.*;
|
||||
} else {
|
||||
errdefer _ = self.map.remove(key);
|
||||
const texture = try loadBlock(engine, materials, textures, filename, temp_allocator);
|
||||
const id = self.nextId();
|
||||
entry.value_ptr.* = id;
|
||||
self.blocks.appendAssumeCapacity(texture);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn loadAll(
|
||||
self: *Blocks,
|
||||
engine: *Engine,
|
||||
materials: *Materials,
|
||||
textures: *Textures,
|
||||
temp_allocator: std.mem.Allocator,
|
||||
) void {
|
||||
const cwd = std.fs.cwd();
|
||||
|
||||
var dir = cwd.openDir("assets/blocks", .{ .iterate = true }) catch |err| {
|
||||
std.log.err("Error while opening blocks directory: {s}", .{@errorName(err)});
|
||||
return;
|
||||
};
|
||||
defer dir.close();
|
||||
|
||||
var it = dir.iterate();
|
||||
while (it.next() catch |err| {
|
||||
std.log.err("Error while iterating over blocks directory: {s}", .{@errorName(err)});
|
||||
return;
|
||||
}) |entry| {
|
||||
if (entry.kind != .file) {
|
||||
std.log.warn("Skipping block entry {s}, which is not a file", .{entry.name});
|
||||
continue;
|
||||
}
|
||||
|
||||
_ = self.getOrLoadFilename(engine, materials, textures, entry.name, temp_allocator) catch |err| {
|
||||
std.log.err("Error while loading block entry {s}: {s}", .{ entry.name, @errorName(err) });
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn loadBlock(
|
||||
engine: *Engine,
|
||||
materials: *Materials,
|
||||
textures: *Textures,
|
||||
filename: []const u8,
|
||||
temp_allocator: std.mem.Allocator,
|
||||
) !Block {
|
||||
const BlockJson = struct {
|
||||
material: ?[]const u8 = null,
|
||||
materials: ?[6][]const u8 = null,
|
||||
};
|
||||
|
||||
std.log.debug("Loading block \"{s}\"...", .{filename});
|
||||
|
||||
const cwd = std.fs.cwd();
|
||||
|
||||
var dir = try cwd.openDir("assets/blocks", .{});
|
||||
defer dir.close();
|
||||
|
||||
// NOTE Buffer size approximated based on expected JSON structure.
|
||||
var buffer: [256]u8 = undefined;
|
||||
|
||||
const file = try dir.openFile(filename, .{});
|
||||
defer file.close();
|
||||
|
||||
var file_reader = file.reader(&buffer);
|
||||
var json_reader: std.json.Reader = .init(temp_allocator, &file_reader.interface);
|
||||
defer json_reader.deinit();
|
||||
|
||||
const parsed: std.json.Parsed(BlockJson) = try std.json.parseFromTokenSource(BlockJson, temp_allocator, &json_reader, .{
|
||||
.duplicate_field_behavior = .@"error",
|
||||
.ignore_unknown_fields = false,
|
||||
.allocate = .alloc_if_needed,
|
||||
});
|
||||
defer parsed.deinit();
|
||||
|
||||
const block_json = parsed.value;
|
||||
|
||||
const block: Block = blk: {
|
||||
if (block_json.material) |name| {
|
||||
if (block_json.materials != null) {
|
||||
std.log.err("Block entry {s} has both properties \"material\" and \"materials\" defined, but exactly one of them must be defined", .{filename});
|
||||
return error.ParseError;
|
||||
}
|
||||
|
||||
const material = try materials.getOrLoadFilename(engine, textures, name, temp_allocator);
|
||||
break :blk .initUniform(material);
|
||||
}
|
||||
|
||||
if (block_json.materials) |names| {
|
||||
var ids: [6]Materials.Id = undefined;
|
||||
for (names, &ids) |name, *id| {
|
||||
id.* = try materials.getOrLoadFilename(engine, textures, name, temp_allocator);
|
||||
}
|
||||
break :blk .initArray(ids);
|
||||
}
|
||||
|
||||
std.log.err("Block entry {s} has neither \"material\" or \"materials\" properties defined, but exactly one of them must be defined", .{filename});
|
||||
return error.ParseError;
|
||||
};
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
fn nextId(self: *const Blocks) Id {
|
||||
const index = self.blocks.items.len;
|
||||
return @enumFromInt(index);
|
||||
}
|
||||
238
src/assets/Chunk.zig
Normal file
238
src/assets/Chunk.zig
Normal file
@@ -0,0 +1,238 @@
|
||||
const Chunk = @This();
|
||||
const std = @import("std");
|
||||
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const math = @import("../math.zig");
|
||||
|
||||
const Blocks = @import("Blocks.zig");
|
||||
const CommandBuffer = @import("../engine/CommandBuffer.zig").CommandBuffer;
|
||||
const Engine = @import("../engine/Engine.zig");
|
||||
const Game = @import("../Game.zig");
|
||||
const GenericBuffer = @import("../engine/GenericBuffer.zig").GenericBuffer;
|
||||
|
||||
const Matrix4x4 = math.Matrix4x4;
|
||||
const ObjectUniformsBuffer = GenericBuffer(void, Game.ObjectUniforms);
|
||||
const Vector3 = math.Vector3;
|
||||
|
||||
pub const chunk_size = 16;
|
||||
|
||||
const initial_capacity = 256;
|
||||
|
||||
blocks: [chunk_size][chunk_size][chunk_size]Blocks.Id,
|
||||
origin: Vector3,
|
||||
descriptor_set: vk.DescriptorSet,
|
||||
object_buffer: ObjectUniformsBuffer,
|
||||
object_count: u32,
|
||||
|
||||
pub const InitInfo = struct {
|
||||
origin: Vector3,
|
||||
descriptor_pool: vk.DescriptorPool,
|
||||
per_batch_descriptor_set_layout: vk.DescriptorSetLayout,
|
||||
};
|
||||
|
||||
pub fn init(engine: *Engine, init_info: InitInfo) !Chunk {
|
||||
const descriptor_set = try engine.allocateDescriptorSet(.{
|
||||
.descriptor_pool = init_info.descriptor_pool,
|
||||
.set_layout = init_info.per_batch_descriptor_set_layout,
|
||||
});
|
||||
errdefer engine.freeDescriptorSet(init_info.descriptor_pool, descriptor_set);
|
||||
|
||||
var object_buffer: ObjectUniformsBuffer = try .init(engine, .{
|
||||
.usage = .storage,
|
||||
.target_queue = .graphics,
|
||||
.array_capacity = initial_capacity,
|
||||
});
|
||||
errdefer object_buffer.deinit(engine);
|
||||
|
||||
try engine.updateDescriptorSets(.{
|
||||
.writes = &.{
|
||||
.{
|
||||
.dst_set = descriptor_set,
|
||||
.dst_binding = 0,
|
||||
.dst_array_element = 0,
|
||||
.descriptor_type = .storage_buffer,
|
||||
.descriptor_infos = .{
|
||||
.buffer = &.{
|
||||
.{
|
||||
.buffer = object_buffer.buffer,
|
||||
.offset = 0,
|
||||
.range = vk.WHOLE_SIZE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return .{
|
||||
.blocks = .{.{[_]Blocks.Id{.air} ** chunk_size} ** chunk_size} ** chunk_size,
|
||||
.origin = init_info.origin,
|
||||
.descriptor_set = descriptor_set,
|
||||
.object_buffer = object_buffer,
|
||||
.object_count = 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Chunk, engine: *Engine, descriptor_pool: vk.DescriptorPool) void {
|
||||
self.object_buffer.deinit(engine);
|
||||
engine.freeDescriptorSet(descriptor_pool, self.descriptor_set);
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
pub fn refresh(self: *Chunk, engine: *Engine, blocks: *const Blocks, temp_allocator: std.mem.Allocator) !void {
|
||||
var object_count: u32 = 0;
|
||||
|
||||
for (self.blocks) |plane| {
|
||||
for (plane) |row| {
|
||||
for (row) |id| {
|
||||
const block = blocks.getBlock(id).?;
|
||||
object_count += @intFromBool(block.positive_x != .empty);
|
||||
object_count += @intFromBool(block.negative_x != .empty);
|
||||
object_count += @intFromBool(block.positive_y != .empty);
|
||||
object_count += @intFromBool(block.negative_y != .empty);
|
||||
object_count += @intFromBool(block.positive_z != .empty);
|
||||
object_count += @intFromBool(block.negative_z != .empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.object_buffer.array_capacity < object_count) {
|
||||
const desired_capacity = std.math.ceilPowerOfTwoAssert(u32, object_count);
|
||||
const new_object_buffer: ObjectUniformsBuffer = try .init(engine, .{
|
||||
.usage = .storage,
|
||||
.target_queue = .graphics,
|
||||
.array_capacity = desired_capacity,
|
||||
});
|
||||
|
||||
try engine.updateDescriptorSets(.{
|
||||
.writes = &.{
|
||||
.{
|
||||
.dst_set = self.descriptor_set,
|
||||
.dst_binding = 0,
|
||||
.dst_array_element = 0,
|
||||
.descriptor_type = .storage_buffer,
|
||||
.descriptor_infos = .{
|
||||
.buffer = &.{
|
||||
.{
|
||||
.buffer = new_object_buffer.buffer,
|
||||
.offset = 0,
|
||||
.range = vk.WHOLE_SIZE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
self.object_buffer.deinit(engine);
|
||||
self.object_buffer = new_object_buffer;
|
||||
}
|
||||
|
||||
const uniforms = try temp_allocator.alloc(Game.ObjectUniforms, object_count);
|
||||
var object_i: usize = 0;
|
||||
defer temp_allocator.free(uniforms);
|
||||
|
||||
for (self.blocks, 0..) |plane, iz| {
|
||||
const fz: f32 = @floatFromInt(iz);
|
||||
for (plane, 0..) |row, iy| {
|
||||
const fy: f32 = @floatFromInt(iy);
|
||||
for (row, 0..) |id, ix| {
|
||||
const fx: f32 = @floatFromInt(ix);
|
||||
const block = blocks.getBlock(id).?;
|
||||
|
||||
const center = Vector3.add(self.origin, .init(fx, fy, fz));
|
||||
const cx, const cy, const cz = center.asArray();
|
||||
|
||||
if (block.positive_x != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
1, 0, 0, 0,
|
||||
cx + 0.5, cy, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.positive_x);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.negative_x != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
0, -1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
-1, 0, 0, 0,
|
||||
cx - 0.5, cy, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.negative_x);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.positive_y != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
-1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 1, 0, 0,
|
||||
cx, cy + 0.5, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.positive_y);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.negative_y != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, -1, 0, 0,
|
||||
cx, cy - 0.5, cz, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.negative_y);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.positive_z != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
cx, cy, cz + 0.5, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.positive_z);
|
||||
object_i += 1;
|
||||
}
|
||||
|
||||
if (block.negative_z != .empty) {
|
||||
// zig fmt: off
|
||||
const matrix: Matrix4x4 = .init(
|
||||
1, 0, 0, 0,
|
||||
0, -1, 0, 0,
|
||||
0, 0, -1, 0,
|
||||
cx, cy, cz - 0.5, 1,
|
||||
);
|
||||
// zig fmt: on
|
||||
uniforms[object_i] = .init(matrix, matrix, block.negative_z);
|
||||
object_i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std.debug.assert(object_i == uniforms.len);
|
||||
|
||||
try self.object_buffer.write(engine, .{ .elements = uniforms });
|
||||
self.object_count = object_count;
|
||||
}
|
||||
|
||||
pub fn draw(self: *const Chunk, layout: vk.PipelineLayout, command_buffer: CommandBuffer(.graphics, .transient)) void {
|
||||
command_buffer.bindDescriptorSets(.graphics, layout, 1, &.{self.descriptor_set}, &.{});
|
||||
command_buffer.drawIndexed(.{ .index_count = 6, .instance_count = self.object_count });
|
||||
}
|
||||
@@ -19,6 +19,7 @@ pub const capacity = std.math.maxInt(std.meta.Tag(Id));
|
||||
|
||||
pub const Key = struct { atom: atoms.Atom };
|
||||
pub const Id = enum(u16) {
|
||||
empty,
|
||||
_,
|
||||
|
||||
pub fn next(self: Id) Id {
|
||||
@@ -55,10 +56,12 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Materials {
|
||||
});
|
||||
errdefer material_buffer.deinit(engine);
|
||||
|
||||
// TODO Add "error" material to represent the empty value (it shouldn't be rendered, so it's good to know when it is).
|
||||
|
||||
return .{
|
||||
.map = map,
|
||||
.material_buffer = material_buffer,
|
||||
.next_id = @enumFromInt(0),
|
||||
.next_id = @enumFromInt(1),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -37,12 +37,12 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
errdefer map.deinit(allocator);
|
||||
try map.ensureTotalCapacity(allocator, capacity);
|
||||
|
||||
var array: Array = try .initCapacity(allocator, capacity);
|
||||
var textures: Array = try .initCapacity(allocator, capacity);
|
||||
errdefer {
|
||||
for (array.items) |*texture| {
|
||||
for (textures.items) |*texture| {
|
||||
texture.deinit(engine);
|
||||
}
|
||||
array.deinit(allocator);
|
||||
textures.deinit(allocator);
|
||||
}
|
||||
|
||||
const empty_base_color_texture = try Texture.init(engine, .{
|
||||
@@ -51,6 +51,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
.usage = .base_color,
|
||||
.target_queue = .graphics,
|
||||
});
|
||||
textures.appendAssumeCapacity(empty_base_color_texture);
|
||||
|
||||
const empty_emissive_texture = try Texture.init(engine, .{
|
||||
.width = 1,
|
||||
@@ -58,6 +59,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
.usage = .emissive,
|
||||
.target_queue = .graphics,
|
||||
});
|
||||
textures.appendAssumeCapacity(empty_emissive_texture);
|
||||
|
||||
const empty_normal_texture = try Texture.init(engine, .{
|
||||
.width = 1,
|
||||
@@ -65,6 +67,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
.usage = .normal,
|
||||
.target_queue = .graphics,
|
||||
});
|
||||
textures.appendAssumeCapacity(empty_normal_texture);
|
||||
|
||||
const empty_occlusuion_roughness_metallic_texture = try Texture.init(engine, .{
|
||||
.width = 1,
|
||||
@@ -72,13 +75,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
.usage = .occlusion_roughness_metallic,
|
||||
.target_queue = .graphics,
|
||||
});
|
||||
|
||||
array.appendSliceAssumeCapacity(&.{
|
||||
empty_base_color_texture,
|
||||
empty_emissive_texture,
|
||||
empty_normal_texture,
|
||||
empty_occlusuion_roughness_metallic_texture,
|
||||
});
|
||||
textures.appendAssumeCapacity(empty_occlusuion_roughness_metallic_texture);
|
||||
|
||||
try empty_base_color_texture.writeSamples(u8, engine, &.{ 255, 255, 255, 255 });
|
||||
try empty_emissive_texture.writeSamples(f16, engine, &.{ 1.0, 1.0, 1.0, 1.0 });
|
||||
@@ -87,7 +84,7 @@ pub fn init(engine: *Engine, allocator: std.mem.Allocator) !Textures {
|
||||
|
||||
return .{
|
||||
.map = map,
|
||||
.textures = array,
|
||||
.textures = textures,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -114,14 +111,10 @@ pub fn getFilename(self: *const Textures, filename: []const u8, usage: Texture.U
|
||||
}
|
||||
|
||||
pub fn getTexture(self: *const Textures, id: Id) ?*Texture {
|
||||
const index: usize = id.id;
|
||||
const index: usize = @intFromEnum(id);
|
||||
return if (index < self.textures.items.len) &self.textures.items[index] else null;
|
||||
}
|
||||
|
||||
pub fn getId(self: *const Textures, key: Key) ?Id {
|
||||
return self.map.get(key);
|
||||
}
|
||||
|
||||
pub fn getOrLoadAtom(self: *Textures, engine: *Engine, atom: atoms.Atom, usage: Texture.Usage, temp_allocator: std.mem.Allocator) !Id {
|
||||
const key: Key = .{ .atom = atom, .usage = usage };
|
||||
const entry = self.map.getOrPutAssumeCapacity(key);
|
||||
@@ -130,7 +123,7 @@ pub fn getOrLoadAtom(self: *Textures, engine: *Engine, atom: atoms.Atom, usage:
|
||||
return entry.value_ptr.*;
|
||||
} else {
|
||||
errdefer _ = self.map.remove(key);
|
||||
const texture = try self.loadTexture(engine, atoms.getString(atom), usage, temp_allocator);
|
||||
const texture = try loadTexture(engine, atoms.getString(atom), usage, temp_allocator);
|
||||
const id = self.nextId();
|
||||
entry.value_ptr.* = id;
|
||||
self.textures.appendAssumeCapacity(texture);
|
||||
|
||||
Reference in New Issue
Block a user