Skip to content

Commit

Permalink
Use palette compression for chunks and increase the maximum render di…
Browse files Browse the repository at this point in the history
…stance.

fixes #156
fixes #136
  • Loading branch information
IntegratedQuantum committed Apr 17, 2024
1 parent 64e37dc commit 775dcc8
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 49 deletions.
23 changes: 13 additions & 10 deletions src/chunk.zig
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ pub const ChunkPosition = struct {

pub const Chunk = struct {
pos: ChunkPosition,
blocks: [chunkVolume]Block = undefined,
data: main.utils.PaletteCompressedRegion(Block, chunkVolume) = undefined,

wasChanged: bool = false,
/// When a chunk is cleaned, it won't be saved by the ChunkManager anymore, so following changes need to be saved directly.
Expand Down Expand Up @@ -199,10 +199,12 @@ pub const Chunk = struct {
.widthShift = voxelSizeShift + chunkShift,
.mutex = std.Thread.Mutex{},
};
self.data.init();
return self;
}

pub fn deinit(self: *Chunk) void {
self.data.deinit();
memoryPoolMutex.lock();
memoryPool.destroy(@alignCast(self));
memoryPoolMutex.unlock();
Expand Down Expand Up @@ -260,8 +262,9 @@ pub const Chunk = struct {
const y = _y >> self.voxelSizeShift;
const z = _z >> self.voxelSizeShift;
const index = getIndex(x, y, z);
if (self.blocks[index].typ == 0 or self.blocks[index].degradable()) {
self.blocks[index] = newBlock;
const oldBlock = self.data.getValue(index);
if(oldBlock.typ == 0 or oldBlock.degradable()) {
self.data.setValue(index, newBlock);
}
}

Expand All @@ -272,7 +275,7 @@ pub const Chunk = struct {
const y = _y >> self.voxelSizeShift;
const z = _z >> self.voxelSizeShift;
const index = getIndex(x, y, z);
self.blocks[index] = newBlock;
self.data.setValue(index, newBlock);
}

/// Updates a block if it is inside this chunk. Should be used in generation to prevent accidently storing these as changes.
Expand All @@ -282,7 +285,7 @@ pub const Chunk = struct {
const y = _y >> self.voxelSizeShift;
const z = _z >> self.voxelSizeShift;
const index = getIndex(x, y, z);
self.blocks[index] = newBlock;
self.data.setValue(index, newBlock);
}

/// Gets a block if it is inside this chunk.
Expand All @@ -292,7 +295,7 @@ pub const Chunk = struct {
const y = _y >> self.voxelSizeShift;
const z = _z >> self.voxelSizeShift;
const index = getIndex(x, y, z);
return self.blocks[index];
return self.data.getValue(index);
}

pub fn getNeighbors(self: *const Chunk, x: i32, y: i32, z: i32, neighborsArray: *[6]Block) void {
Expand Down Expand Up @@ -340,7 +343,7 @@ pub const Chunk = struct {
while(dz <= 1): (dz += 1) {
const index = getIndex(x*2 + dx, y*2 + dy, z*2 + dz);
const i = dx*4 + dz*2 + dy;
octantBlocks[i] = other.blocks[index];
octantBlocks[i] = other.data.getValue(index);
if(octantBlocks[i] == 0) continue; // I don't care about air blocks.

var count: u32 = 0;
Expand All @@ -350,7 +353,7 @@ pub const Chunk = struct {
const nz = z*2 + dz + Neighbors.relZ[n];
if((nx & chunkMask) == nx and (ny & chunkMask) == ny and (nz & chunkMask) == nz) { // If it's inside the chunk.
const neighborIndex = getIndex(nx, ny, nz);
if(other.blocks[neighborIndex].transparent()) {
if(other.data.getValue(neighborIndex).transparent()) {
count += 5;
}
} else {
Expand All @@ -368,12 +371,12 @@ pub const Chunk = struct {
for(0..8) |i| {
const appliedPermutation = permutationStart ^ i;
if(neighborCount[appliedPermutation] >= maxCount - 1) { // Avoid pattern breaks at chunk borders.
block = blocks[appliedPermutation];
block = octantBlocks[appliedPermutation];
}
}
// Update the block:
const thisIndex = getIndex(x + xOffset, y + yOffset, z + zOffset);
self.blocks[thisIndex] = block;
self.data.setValue(thisIndex, block);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/gui/windows/graphics.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ pub var window = GuiWindow {
};

const padding: f32 = 8;
const renderDistances = [_]u16{3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};

fn renderDistanceCallback(newValue: u16) void {
settings.renderDistance = newValue + 1;
settings.renderDistance = newValue + renderDistances[0];
}

fn LODFactorCallback(newValue: u16) void {
Expand All @@ -42,8 +43,7 @@ fn anisotropicFilteringCallback(newValue: bool) void {

pub fn onOpen() void {
const list = VerticalList.init(.{padding, 16 + padding}, 300, 16);
const renderDistances = [_]u32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
list.add(DiscreteSlider.init(.{0, 0}, 128, "#ffffffRender Distance: ", "{}", &renderDistances, settings.renderDistance - 1, &renderDistanceCallback));
list.add(DiscreteSlider.init(.{0, 0}, 128, "#ffffffRender Distance: ", "{}", &renderDistances, settings.renderDistance - renderDistances[0], &renderDistanceCallback));
list.add(CheckBox.init(.{0, 0}, 128, "Bloom", settings.bloom, &bloomCallback));
list.add(CheckBox.init(.{0, 0}, 128, "Vertical Synchronization", settings.vsync, &vsyncCallback));
list.add(CheckBox.init(.{0, 0}, 128, "Anisotropic Filtering", settings.anisotropicFiltering, &anisotropicFilteringCallback));
Expand Down
13 changes: 7 additions & 6 deletions src/network.zig
Original file line number Diff line number Diff line change
Expand Up @@ -744,16 +744,16 @@ pub const Protocols = struct {
}
data = _inflatedData;
const ch = chunk.Chunk.init(pos);
for(&ch.blocks) |*block| {
block.* = Block.fromInt(std.mem.readInt(u32, data[0..4], .big));
for(0..chunk.chunkVolume) |i| {
ch.data.setValue(i, Block.fromInt(std.mem.readInt(u32, data[0..4], .big)));
data = data[4..];
}
renderer.mesh_storage.updateChunkMesh(ch);
}
fn sendChunkOverTheNetwork(conn: *Connection, ch: *chunk.Chunk) void {
var uncompressedData: [@sizeOf(@TypeOf(ch.blocks))]u8 = undefined; // TODO: #15280
for(&ch.blocks, 0..) |*block, i| {
std.mem.writeInt(u32, uncompressedData[4*i..][0..4], block.toInt(), .big);
var uncompressedData: [chunk.chunkVolume*@sizeOf(u32)]u8 = undefined;
for(0..chunk.chunkVolume) |i| {
std.mem.writeInt(u32, uncompressedData[4*i..][0..4], ch.data.getValue(i).toInt(), .big);
}
const compressedData = utils.Compression.deflate(main.stackAllocator, &uncompressedData);
defer main.stackAllocator.free(compressedData);
Expand All @@ -768,7 +768,8 @@ pub const Protocols = struct {
}
fn sendChunkLocally(ch: *chunk.Chunk) void {
const chunkCopy = chunk.Chunk.init(ch.pos);
@memcpy(&chunkCopy.blocks, &ch.blocks);
chunkCopy.data.deinit();
chunkCopy.data.initCopy(&ch.data);
renderer.mesh_storage.updateChunkMesh(chunkCopy);
}
pub fn sendChunk(conn: *Connection, ch: *chunk.Chunk) void {
Expand Down
36 changes: 18 additions & 18 deletions src/renderer/chunk_meshing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ pub const ChunkMesh = struct {
while(y < chunk.chunkSize): (y += 1) {
var z: u8 = 0;
while(z < chunk.chunkSize): (z += 1) {
const block = (&self.chunk.blocks)[chunk.getIndex(x, y, z)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
const block = self.chunk.data.getValue(chunk.getIndex(x, y, z));
if(block.light() != 0) lightEmittingBlocks.append(.{x, y, z});
}
}
Expand Down Expand Up @@ -666,7 +666,7 @@ pub const ChunkMesh = struct {
while(y < chunk.chunkSize): (y += 1) {
var z: u8 = 0;
while(z < chunk.chunkSize): (z += 1) {
const block = (&self.chunk.blocks)[chunk.getIndex(x, y, z)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
const block = self.chunk.data.getValue(chunk.getIndex(x, y, z));
if(block.typ == 0) continue;
// Check all neighbors:
for(chunk.Neighbors.iterable) |i| {
Expand All @@ -675,7 +675,7 @@ pub const ChunkMesh = struct {
const y2 = y + chunk.Neighbors.relY[i];
const z2 = z + chunk.Neighbors.relZ[i];
if(x2&chunk.chunkMask != x2 or y2&chunk.chunkMask != y2 or z2&chunk.chunkMask != z2) continue; // Neighbor is outside the chunk.
const neighborBlock = (&self.chunk.blocks)[chunk.getIndex(x2, y2, z2)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
const neighborBlock = self.chunk.data.getValue(chunk.getIndex(x2, y2, z2));
if(canBeSeenThroughOtherBlock(block, neighborBlock, i)) {
if(block.transparent()) {
if(block.hasBackFace()) {
Expand All @@ -700,12 +700,12 @@ pub const ChunkMesh = struct {
while(x < chunk.chunkSize): (x += 1) {
var y: u8 = 0;
while(y < chunk.chunkSize): (y += 1) {
self.chunkBorders[chunk.Neighbors.dirNegX].adjustToBlock((&self.chunk.blocks)[chunk.getIndex(0, x, y)], .{0, x, y}, chunk.Neighbors.dirNegX); // TODO: Wait for the compiler bug to get fixed.
self.chunkBorders[chunk.Neighbors.dirPosX].adjustToBlock((&self.chunk.blocks)[chunk.getIndex(chunk.chunkSize-1, x, y)], .{chunk.chunkSize, x, y}, chunk.Neighbors.dirPosX); // TODO: Wait for the compiler bug to get fixed.
self.chunkBorders[chunk.Neighbors.dirNegY].adjustToBlock((&self.chunk.blocks)[chunk.getIndex(x, 0, y)], .{x, 0, y}, chunk.Neighbors.dirNegY); // TODO: Wait for the compiler bug to get fixed.
self.chunkBorders[chunk.Neighbors.dirPosY].adjustToBlock((&self.chunk.blocks)[chunk.getIndex(x, chunk.chunkSize-1, y)], .{x, chunk.chunkSize, y}, chunk.Neighbors.dirPosY); // TODO: Wait for the compiler bug to get fixed.
self.chunkBorders[chunk.Neighbors.dirDown].adjustToBlock((&self.chunk.blocks)[chunk.getIndex(x, y, 0)], .{x, y, 0}, chunk.Neighbors.dirDown); // TODO: Wait for the compiler bug to get fixed.
self.chunkBorders[chunk.Neighbors.dirUp].adjustToBlock((&self.chunk.blocks)[chunk.getIndex(x, y, chunk.chunkSize-1)], .{x, y, chunk.chunkSize}, chunk.Neighbors.dirUp); // TODO: Wait for the compiler bug to get fixed.
self.chunkBorders[chunk.Neighbors.dirNegX].adjustToBlock(self.chunk.data.getValue(chunk.getIndex(0, x, y)), .{0, x, y}, chunk.Neighbors.dirNegX);
self.chunkBorders[chunk.Neighbors.dirPosX].adjustToBlock(self.chunk.data.getValue(chunk.getIndex(chunk.chunkSize-1, x, y)), .{chunk.chunkSize, x, y}, chunk.Neighbors.dirPosX);
self.chunkBorders[chunk.Neighbors.dirNegY].adjustToBlock(self.chunk.data.getValue(chunk.getIndex(x, 0, y)), .{x, 0, y}, chunk.Neighbors.dirNegY);
self.chunkBorders[chunk.Neighbors.dirPosY].adjustToBlock(self.chunk.data.getValue(chunk.getIndex(x, chunk.chunkSize-1, y)), .{x, chunk.chunkSize, y}, chunk.Neighbors.dirPosY);
self.chunkBorders[chunk.Neighbors.dirDown].adjustToBlock(self.chunk.data.getValue(chunk.getIndex(x, y, 0)), .{x, y, 0}, chunk.Neighbors.dirDown);
self.chunkBorders[chunk.Neighbors.dirUp].adjustToBlock(self.chunk.data.getValue(chunk.getIndex(x, y, chunk.chunkSize-1)), .{x, y, chunk.chunkSize}, chunk.Neighbors.dirUp);
}
}
self.mutex.unlock();
Expand All @@ -729,10 +729,10 @@ pub const ChunkMesh = struct {
defer neighborChunkMesh.decreaseRefCount();
const index = chunk.getIndex(nx & chunk.chunkMask, ny & chunk.chunkMask, nz & chunk.chunkMask);
neighborChunkMesh.mutex.lock();
var neighborBlock = neighborChunkMesh.chunk.blocks[index];
var neighborBlock = neighborChunkMesh.chunk.data.getValue(index);
if(neighborBlock.mode().dependsOnNeighbors) {
if(neighborBlock.mode().updateData(&neighborBlock, neighbor ^ 1, newBlock)) {
neighborChunkMesh.chunk.blocks[index] = neighborBlock;
neighborChunkMesh.chunk.data.setValue(index, neighborBlock);
neighborChunkMesh.opaqueMesh.coreFaces.clearRetainingCapacity();
neighborChunkMesh.transparentMesh.coreFaces.clearRetainingCapacity();
neighborChunkMesh.mutex.unlock();
Expand All @@ -745,10 +745,10 @@ pub const ChunkMesh = struct {
} else {
const index = chunk.getIndex(nx, ny, nz);
self.mutex.lock();
var neighborBlock = self.chunk.blocks[index];
var neighborBlock = self.chunk.data.getValue(index);
if(neighborBlock.mode().dependsOnNeighbors) {
if(neighborBlock.mode().updateData(&neighborBlock, neighbor ^ 1, newBlock)) {
self.chunk.blocks[index] = neighborBlock;
self.chunk.data.setValue(index, neighborBlock);
}
}
self.mutex.unlock();
Expand All @@ -761,7 +761,7 @@ pub const ChunkMesh = struct {
}
}
self.mutex.lock();
self.chunk.blocks[chunk.getIndex(x, y, z)] = newBlock;
self.chunk.data.setValue(chunk.getIndex(x, y, z), newBlock);
self.mutex.unlock();
for(self.lightingData[0..]) |lightingData| {
lightingData.propagateLightsDestructive(&.{.{@intCast(x), @intCast(y), @intCast(z)}});
Expand Down Expand Up @@ -872,8 +872,8 @@ pub const ChunkMesh = struct {
const otherX = x+%chunk.Neighbors.relX[neighbor] & chunk.chunkMask;
const otherY = y+%chunk.Neighbors.relY[neighbor] & chunk.chunkMask;
const otherZ = z+%chunk.Neighbors.relZ[neighbor] & chunk.chunkMask;
const block = (&self.chunk.blocks)[chunk.getIndex(x, y, z)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
const otherBlock = (&neighborMesh.chunk.blocks)[chunk.getIndex(otherX, otherY, otherZ)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
const block = self.chunk.data.getValue(chunk.getIndex(x, y, z));
const otherBlock = neighborMesh.chunk.data.getValue(chunk.getIndex(otherX, otherY, otherZ));
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
if(block.transparent()) {
if(block.hasBackFace()) {
Expand Down Expand Up @@ -953,8 +953,8 @@ pub const ChunkMesh = struct {
const otherX = (x+%chunk.Neighbors.relX[neighbor]+%offsetX >> 1) & chunk.chunkMask;
const otherY = (y+%chunk.Neighbors.relY[neighbor]+%offsetY >> 1) & chunk.chunkMask;
const otherZ = (z+%chunk.Neighbors.relZ[neighbor]+%offsetZ >> 1) & chunk.chunkMask;
const block = (&self.chunk.blocks)[chunk.getIndex(x, y, z)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
const otherBlock = (&neighborMesh.chunk.blocks)[chunk.getIndex(otherX, otherY, otherZ)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
const block = self.chunk.data.getValue(chunk.getIndex(x, y, z));
const otherBlock = neighborMesh.chunk.data.getValue(chunk.getIndex(otherX, otherY, otherZ));
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
if(otherBlock.transparent()) {
self.transparentMesh.appendNeighborFacingQuadsToNeighbor(otherBlock, neighbor ^ 1, x, y, z, false, true);
Expand Down
18 changes: 9 additions & 9 deletions src/renderer/lighting.zig
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,14 @@ pub const ChannelChunk = struct {
result.value[1] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
result.value[2] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
}
calculateOutgoingOcclusion(&result.value, self.ch.blocks[index], self.ch.pos.voxelSize, neighbor);
calculateOutgoingOcclusion(&result.value, self.ch.data.getValue(index), self.ch.pos.voxelSize, neighbor);
if(result.value[0] == 0 and result.value[1] == 0 and result.value[2] == 0) continue;
if(nx < 0 or nx >= chunk.chunkSize or ny < 0 or ny >= chunk.chunkSize or nz < 0 or nz >= chunk.chunkSize) {
neighborLists[neighbor].append(main.stackAllocator, result);
continue;
}
const neighborIndex = chunk.getIndex(nx, ny, nz);
calculateIncomingOcclusion(&result.value, self.ch.blocks[neighborIndex], self.ch.pos.voxelSize, neighbor ^ 1);
calculateIncomingOcclusion(&result.value, self.ch.data.getValue(neighborIndex), self.ch.pos.voxelSize, neighbor ^ 1);
if(result.value[0] != 0 or result.value[1] != 0 or result.value[2] != 0) lightQueue.enqueue(result);
}
}
Expand Down Expand Up @@ -213,13 +213,13 @@ pub const ChannelChunk = struct {
result.value[1] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
result.value[2] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
}
calculateOutgoingOcclusion(&result.value, self.ch.blocks[index], self.ch.pos.voxelSize, neighbor);
calculateOutgoingOcclusion(&result.value, self.ch.data.getValue(index), self.ch.pos.voxelSize, neighbor);
if(nx < 0 or nx >= chunk.chunkSize or ny < 0 or ny >= chunk.chunkSize or nz < 0 or nz >= chunk.chunkSize) {
neighborLists[neighbor].append(main.stackAllocator, result);
continue;
}
const neighborIndex = chunk.getIndex(nx, ny, nz);
calculateIncomingOcclusion(&result.value, self.ch.blocks[neighborIndex], self.ch.pos.voxelSize, neighbor ^ 1);
calculateIncomingOcclusion(&result.value, self.ch.data.getValue(neighborIndex), self.ch.pos.voxelSize, neighbor ^ 1);
lightQueue.enqueue(result);
}
}
Expand All @@ -245,7 +245,7 @@ pub const ChannelChunk = struct {
for(lights) |entry| {
const index = chunk.getIndex(entry.x, entry.y, entry.z);
var result = entry;
calculateIncomingOcclusion(&result.value, self.ch.blocks[index], self.ch.pos.voxelSize, entry.sourceDir);
calculateIncomingOcclusion(&result.value, self.ch.data.getValue(index), self.ch.pos.voxelSize, entry.sourceDir);
if(result.value[0] != 0 or result.value[1] != 0 or result.value[2] != 0) lightQueue.enqueue(result);
}
self.propagateDirect(lightQueue);
Expand All @@ -256,7 +256,7 @@ pub const ChannelChunk = struct {
for(lights) |entry| {
const index = chunk.getIndex(entry.x, entry.y, entry.z);
var result = entry;
calculateIncomingOcclusion(&result.value, self.ch.blocks[index], self.ch.pos.voxelSize, entry.sourceDir);
calculateIncomingOcclusion(&result.value, self.ch.data.getValue(index), self.ch.pos.voxelSize, entry.sourceDir);
lightQueue.enqueue(result);
}
return self.propagateDestructive(lightQueue, constructiveEntries, false);
Expand All @@ -270,7 +270,7 @@ pub const ChannelChunk = struct {
if(self.isSun) {
lightQueue.enqueue(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = .{255, 255, 255}, .sourceDir = 6, .activeValue = 0b111});
} else {
lightQueue.enqueue(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = extractColor(self.ch.blocks[index].light()), .sourceDir = 6, .activeValue = 0b111});
lightQueue.enqueue(.{.x = @intCast(pos[0]), .y = @intCast(pos[1]), .z = @intCast(pos[2]), .value = extractColor(self.ch.data.getValue(index).light()), .sourceDir = 6, .activeValue = 0b111});
}
}
if(checkNeighbors) {
Expand Down Expand Up @@ -312,9 +312,9 @@ pub const ChannelChunk = struct {
value[1] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
value[2] -|= 8*|@as(u8, @intCast(self.ch.pos.voxelSize));
}
calculateOutgoingOcclusion(&value, self.ch.blocks[neighborIndex], self.ch.pos.voxelSize, neighbor);
calculateOutgoingOcclusion(&value, self.ch.data.getValue(neighborIndex), self.ch.pos.voxelSize, neighbor);
if(value[0] == 0 and value[1] == 0 and value[2] == 0) continue;
calculateIncomingOcclusion(&value, self.ch.blocks[index], self.ch.pos.voxelSize, neighbor ^ 1);
calculateIncomingOcclusion(&value, self.ch.data.getValue(index), self.ch.pos.voxelSize, neighbor ^ 1);
if(value[0] != 0 or value[1] != 0 or value[2] != 0) lightQueue.enqueue(.{.x = @intCast(x), .y = @intCast(y), .z = @intCast(z), .value = value, .sourceDir = @intCast(neighbor), .activeValue = 0b111});
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/mesh_storage.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const ChunkMeshNode = struct {
active: bool,
rendered: bool,
};
const storageSize = 32;
const storageSize = 64;
const storageMask = storageSize - 1;
var storageLists: [settings.highestLOD + 1]*[storageSize*storageSize*storageSize]ChunkMeshNode = undefined;
var mapStorageLists: [settings.highestLOD + 1]*[storageSize*storageSize]Atomic(?*LightMap.LightMapFragment) = undefined;
Expand Down
17 changes: 15 additions & 2 deletions src/utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,7 @@ pub fn PaletteCompressedRegion(T: type, size: comptime_int) type {

pub fn init(self: *Self) void {
self.* = .{
.palette = main.globalAllocator.alloc([3]u8, 1),
.palette = main.globalAllocator.alloc(T, 1),
.paletteOccupancy = main.globalAllocator.alloc(u32, 1),
.paletteLength = 1,
.activePaletteEntries = 1,
Expand All @@ -1224,13 +1224,26 @@ pub fn PaletteCompressedRegion(T: type, size: comptime_int) type {
self.paletteOccupancy[0] = size;
}

pub fn initCopy(self: *Self, template: *const Self) void {
self.* = .{
.data = .{
.data = main.globalAllocator.dupe(u8, template.data.data),
.bitSize = template.data.bitSize,
},
.palette = main.globalAllocator.dupe(T, template.palette),
.paletteOccupancy = main.globalAllocator.dupe(u32, template.paletteOccupancy),
.paletteLength = template.paletteLength,
.activePaletteEntries = template.activePaletteEntries,
};
}

pub fn deinit(self: *Self) void {
self.data.deinit(main.globalAllocator);
main.globalAllocator.free(self.palette);
main.globalAllocator.free(self.paletteOccupancy);
}

pub fn getValue(self: *Self, i: usize) T {
pub fn getValue(self: *const Self, i: usize) T {
return self.palette[self.data.getValue(i)];
}

Expand Down

0 comments on commit 775dcc8

Please sign in to comment.