mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-09-08 03:29:48 -04:00
Keep the faces to lod neighbors stored even if a neighbor of the same lod exists.
This is required for #130 to allow swapping between lod and non-lod connections on demand.
This commit is contained in:
parent
0c4f705082
commit
0b8c4b455b
126
src/chunk.zig
126
src/chunk.zig
@ -524,7 +524,8 @@ pub const meshing = struct {
|
|||||||
|
|
||||||
const PrimitiveMesh = struct {
|
const PrimitiveMesh = struct {
|
||||||
coreFaces: std.ArrayListUnmanaged(FaceData) = .{},
|
coreFaces: std.ArrayListUnmanaged(FaceData) = .{},
|
||||||
neighborFaces: [6]std.ArrayListUnmanaged(FaceData) = [_]std.ArrayListUnmanaged(FaceData){.{}} ** 6,
|
neighborFacesSameLod: [6]std.ArrayListUnmanaged(FaceData) = [_]std.ArrayListUnmanaged(FaceData){.{}} ** 6,
|
||||||
|
neighborFacesHigherLod: [6]std.ArrayListUnmanaged(FaceData) = [_]std.ArrayListUnmanaged(FaceData){.{}} ** 6,
|
||||||
completeList: []FaceData = &.{},
|
completeList: []FaceData = &.{},
|
||||||
bufferAllocation: graphics.SubAllocation = .{.start = 0, .len = 0},
|
bufferAllocation: graphics.SubAllocation = .{.start = 0, .len = 0},
|
||||||
vertexCount: u31 = 0,
|
vertexCount: u31 = 0,
|
||||||
@ -533,7 +534,10 @@ pub const meshing = struct {
|
|||||||
fn deinit(self: *PrimitiveMesh) void {
|
fn deinit(self: *PrimitiveMesh) void {
|
||||||
faceBuffer.free(self.bufferAllocation) catch unreachable;
|
faceBuffer.free(self.bufferAllocation) catch unreachable;
|
||||||
self.coreFaces.deinit(main.globalAllocator);
|
self.coreFaces.deinit(main.globalAllocator);
|
||||||
for(&self.neighborFaces) |*neighborFaces| {
|
for(&self.neighborFacesSameLod) |*neighborFaces| {
|
||||||
|
neighborFaces.deinit(main.globalAllocator);
|
||||||
|
}
|
||||||
|
for(&self.neighborFacesHigherLod) |*neighborFaces| {
|
||||||
neighborFaces.deinit(main.globalAllocator);
|
neighborFaces.deinit(main.globalAllocator);
|
||||||
}
|
}
|
||||||
main.globalAllocator.free(self.completeList);
|
main.globalAllocator.free(self.completeList);
|
||||||
@ -541,7 +545,10 @@ pub const meshing = struct {
|
|||||||
|
|
||||||
fn reset(self: *PrimitiveMesh) void {
|
fn reset(self: *PrimitiveMesh) void {
|
||||||
self.coreFaces.clearRetainingCapacity();
|
self.coreFaces.clearRetainingCapacity();
|
||||||
for(&self.neighborFaces) |*neighborFaces| {
|
for(&self.neighborFacesSameLod) |*neighborFaces| {
|
||||||
|
neighborFaces.clearRetainingCapacity();
|
||||||
|
}
|
||||||
|
for(&self.neighborFacesHigherLod) |*neighborFaces| {
|
||||||
neighborFaces.clearRetainingCapacity();
|
neighborFaces.clearRetainingCapacity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -550,18 +557,34 @@ pub const meshing = struct {
|
|||||||
try self.coreFaces.append(main.globalAllocator, face);
|
try self.coreFaces.append(main.globalAllocator, face);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn appendNeighbor(self: *PrimitiveMesh, face: FaceData, neighbor: u3) !void {
|
fn appendNeighbor(self: *PrimitiveMesh, face: FaceData, neighbor: u3, comptime isLod: bool) !void {
|
||||||
try self.neighborFaces[neighbor].append(main.globalAllocator, face);
|
if(isLod) {
|
||||||
|
try self.neighborFacesHigherLod[neighbor].append(main.globalAllocator, face);
|
||||||
|
} else {
|
||||||
|
try self.neighborFacesSameLod[neighbor].append(main.globalAllocator, face);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clearNeighbor(self: *PrimitiveMesh, neighbor: u3) void {
|
fn clearNeighbor(self: *PrimitiveMesh, neighbor: u3, comptime isLod: bool) void {
|
||||||
self.neighborFaces[neighbor].clearRetainingCapacity();
|
if(isLod) {
|
||||||
|
self.neighborFacesHigherLod[neighbor].clearRetainingCapacity();
|
||||||
|
} else {
|
||||||
|
self.neighborFacesSameLod[neighbor].clearRetainingCapacity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(self: *PrimitiveMesh, parent: *ChunkMesh) !void {
|
fn finish(self: *PrimitiveMesh, parent: *ChunkMesh) !void {
|
||||||
var len: usize = self.coreFaces.items.len;
|
var len: usize = self.coreFaces.items.len;
|
||||||
for(self.neighborFaces) |neighborFaces| {
|
var neighborFaceLists: [6][]FaceData = undefined;
|
||||||
len += neighborFaces.items.len;
|
for(0..6) |i| {
|
||||||
|
if(parent.lastNeighborsSameLod[i] == null) {
|
||||||
|
neighborFaceLists[i] = self.neighborFacesHigherLod[i].items;
|
||||||
|
} else {
|
||||||
|
neighborFaceLists[i] = self.neighborFacesSameLod[i].items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(neighborFaceLists) |neighborFaces| {
|
||||||
|
len += neighborFaces.len;
|
||||||
}
|
}
|
||||||
if(main.globalAllocator.resize(self.completeList, len)) {
|
if(main.globalAllocator.resize(self.completeList, len)) {
|
||||||
self.completeList.len = len;
|
self.completeList.len = len;
|
||||||
@ -572,9 +595,9 @@ pub const meshing = struct {
|
|||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
@memcpy(self.completeList[i..][0..self.coreFaces.items.len], self.coreFaces.items);
|
@memcpy(self.completeList[i..][0..self.coreFaces.items.len], self.coreFaces.items);
|
||||||
i += self.coreFaces.items.len;
|
i += self.coreFaces.items.len;
|
||||||
for(self.neighborFaces) |neighborFaces| {
|
for(neighborFaceLists) |neighborFaces| {
|
||||||
@memcpy(self.completeList[i..][0..neighborFaces.items.len], neighborFaces.items);
|
@memcpy(self.completeList[i..][0..neighborFaces.len], neighborFaces);
|
||||||
i += neighborFaces.items.len;
|
i += neighborFaces.len;
|
||||||
}
|
}
|
||||||
for(self.completeList) |*face| {
|
for(self.completeList) |*face| {
|
||||||
face.light = getLight(parent, face.position.x, face.position.y, face.position.z, face.position.normal);
|
face.light = getLight(parent, face.position.x, face.position.y, face.position.z, face.position.normal);
|
||||||
@ -657,7 +680,7 @@ pub const meshing = struct {
|
|||||||
|
|
||||||
fn addFace(self: *PrimitiveMesh, faceData: FaceData, fromNeighborChunk: ?u3) !void {
|
fn addFace(self: *PrimitiveMesh, faceData: FaceData, fromNeighborChunk: ?u3) !void {
|
||||||
if(fromNeighborChunk) |neighbor| {
|
if(fromNeighborChunk) |neighbor| {
|
||||||
try self.neighborFaces[neighbor].append(main.globalAllocator, faceData);
|
try self.neighborFacesSameLod[neighbor].append(main.globalAllocator, faceData);
|
||||||
} else {
|
} else {
|
||||||
try self.coreFaces.append(main.globalAllocator, faceData);
|
try self.coreFaces.append(main.globalAllocator, faceData);
|
||||||
}
|
}
|
||||||
@ -666,13 +689,13 @@ pub const meshing = struct {
|
|||||||
fn removeFace(self: *PrimitiveMesh, faceData: FaceData, fromNeighborChunk: ?u3) void {
|
fn removeFace(self: *PrimitiveMesh, faceData: FaceData, fromNeighborChunk: ?u3) void {
|
||||||
if(fromNeighborChunk) |neighbor| {
|
if(fromNeighborChunk) |neighbor| {
|
||||||
var pos: usize = std.math.maxInt(usize);
|
var pos: usize = std.math.maxInt(usize);
|
||||||
for(self.neighborFaces[neighbor].items, 0..) |item, i| {
|
for(self.neighborFacesSameLod[neighbor].items, 0..) |item, i| {
|
||||||
if(std.meta.eql(faceData, item)) {
|
if(std.meta.eql(faceData, item)) {
|
||||||
pos = i;
|
pos = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = self.neighborFaces[neighbor].swapRemove(pos);
|
_ = self.neighborFacesSameLod[neighbor].swapRemove(pos);
|
||||||
} else {
|
} else {
|
||||||
var pos: usize = std.math.maxInt(usize);
|
var pos: usize = std.math.maxInt(usize);
|
||||||
for(self.coreFaces.items, 0..) |item, i| {
|
for(self.coreFaces.items, 0..) |item, i| {
|
||||||
@ -746,7 +769,8 @@ pub const meshing = struct {
|
|||||||
opaqueMesh: PrimitiveMesh,
|
opaqueMesh: PrimitiveMesh,
|
||||||
voxelMesh: PrimitiveMesh,
|
voxelMesh: PrimitiveMesh,
|
||||||
transparentMesh: PrimitiveMesh,
|
transparentMesh: PrimitiveMesh,
|
||||||
lastNeighbors: [6]?*const ChunkMesh = [_]?*const ChunkMesh{null} ** 6,
|
lastNeighborsSameLod: [6]?*const ChunkMesh = [_]?*const ChunkMesh{null} ** 6,
|
||||||
|
lastNeighborsHigherLod: [6]?*const ChunkMesh = [_]?*const ChunkMesh{null} ** 6,
|
||||||
visibilityMask: u8 = 0xff,
|
visibilityMask: u8 = 0xff,
|
||||||
currentSorting: []SortingData = &.{},
|
currentSorting: []SortingData = &.{},
|
||||||
sortingOutputBuffer: []FaceData = &.{},
|
sortingOutputBuffer: []FaceData = &.{},
|
||||||
@ -1015,15 +1039,15 @@ pub const meshing = struct {
|
|||||||
const nullNeighborMesh = renderer.RenderStructure.getNeighborFromRenderThread(self.pos, self.pos.voxelSize, neighbor);
|
const nullNeighborMesh = renderer.RenderStructure.getNeighborFromRenderThread(self.pos, self.pos.voxelSize, neighbor);
|
||||||
if(nullNeighborMesh) |neighborMesh| {
|
if(nullNeighborMesh) |neighborMesh| {
|
||||||
std.debug.assert(neighborMesh != self);
|
std.debug.assert(neighborMesh != self);
|
||||||
if(self.lastNeighbors[neighbor] == neighborMesh) continue;
|
if(self.lastNeighborsSameLod[neighbor] == neighborMesh) continue;
|
||||||
self.lastNeighbors[neighbor] = neighborMesh;
|
self.lastNeighborsSameLod[neighbor] = neighborMesh;
|
||||||
neighborMesh.lastNeighbors[neighbor ^ 1] = self;
|
neighborMesh.lastNeighborsSameLod[neighbor ^ 1] = self;
|
||||||
self.opaqueMesh.clearNeighbor(neighbor);
|
self.opaqueMesh.clearNeighbor(neighbor, false);
|
||||||
self.voxelMesh.clearNeighbor(neighbor);
|
self.voxelMesh.clearNeighbor(neighbor, false);
|
||||||
self.transparentMesh.clearNeighbor(neighbor);
|
self.transparentMesh.clearNeighbor(neighbor, false);
|
||||||
neighborMesh.opaqueMesh.clearNeighbor(neighbor ^ 1);
|
neighborMesh.opaqueMesh.clearNeighbor(neighbor ^ 1, false);
|
||||||
neighborMesh.voxelMesh.clearNeighbor(neighbor ^ 1);
|
neighborMesh.voxelMesh.clearNeighbor(neighbor ^ 1, false);
|
||||||
neighborMesh.transparentMesh.clearNeighbor(neighbor ^ 1);
|
neighborMesh.transparentMesh.clearNeighbor(neighbor ^ 1, false);
|
||||||
const x3: i32 = if(neighbor & 1 == 0) chunkMask else 0;
|
const x3: i32 = if(neighbor & 1 == 0) chunkMask else 0;
|
||||||
var x1: i32 = 0;
|
var x1: i32 = 0;
|
||||||
while(x1 < chunkSize): (x1 += 1) {
|
while(x1 < chunkSize): (x1 += 1) {
|
||||||
@ -1053,28 +1077,28 @@ pub const meshing = struct {
|
|||||||
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
|
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
|
||||||
if(block.transparent()) {
|
if(block.transparent()) {
|
||||||
if(block.hasBackFace()) {
|
if(block.hasBackFace()) {
|
||||||
try self.transparentMesh.appendNeighbor(constructFaceData(block, neighbor ^ 1, x, y, z, true), neighbor);
|
try self.transparentMesh.appendNeighbor(constructFaceData(block, neighbor ^ 1, x, y, z, true), neighbor, false);
|
||||||
}
|
}
|
||||||
try neighborMesh.transparentMesh.appendNeighbor(constructFaceData(block, neighbor, otherX, otherY, otherZ, false), neighbor ^ 1);
|
try neighborMesh.transparentMesh.appendNeighbor(constructFaceData(block, neighbor, otherX, otherY, otherZ, false), neighbor ^ 1, false);
|
||||||
} else {
|
} else {
|
||||||
if(blocks.meshes.model(block).modelIndex == 0) {
|
if(blocks.meshes.model(block).modelIndex == 0) {
|
||||||
try neighborMesh.opaqueMesh.appendNeighbor(constructFaceData(block, neighbor, otherX, otherY, otherZ, false), neighbor ^ 1);
|
try neighborMesh.opaqueMesh.appendNeighbor(constructFaceData(block, neighbor, otherX, otherY, otherZ, false), neighbor ^ 1, false);
|
||||||
} else {
|
} else {
|
||||||
try neighborMesh.voxelMesh.appendNeighbor(constructFaceData(block, neighbor, otherX, otherY, otherZ, false), neighbor ^ 1);
|
try neighborMesh.voxelMesh.appendNeighbor(constructFaceData(block, neighbor, otherX, otherY, otherZ, false), neighbor ^ 1, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
|
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
|
||||||
if(otherBlock.transparent()) {
|
if(otherBlock.transparent()) {
|
||||||
if(otherBlock.hasBackFace()) {
|
if(otherBlock.hasBackFace()) {
|
||||||
try neighborMesh.transparentMesh.appendNeighbor(constructFaceData(otherBlock, neighbor, otherX, otherY, otherZ, true), neighbor ^ 1);
|
try neighborMesh.transparentMesh.appendNeighbor(constructFaceData(otherBlock, neighbor, otherX, otherY, otherZ, true), neighbor ^ 1, false);
|
||||||
}
|
}
|
||||||
try self.transparentMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor);
|
try self.transparentMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor, false);
|
||||||
} else {
|
} else {
|
||||||
if(blocks.meshes.model(otherBlock).modelIndex == 0) {
|
if(blocks.meshes.model(otherBlock).modelIndex == 0) {
|
||||||
try self.opaqueMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor);
|
try self.opaqueMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor, false);
|
||||||
} else {
|
} else {
|
||||||
try self.voxelMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor);
|
try self.voxelMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1083,24 +1107,30 @@ pub const meshing = struct {
|
|||||||
try neighborMesh.opaqueMesh.finish(neighborMesh);
|
try neighborMesh.opaqueMesh.finish(neighborMesh);
|
||||||
try neighborMesh.voxelMesh.finish(neighborMesh);
|
try neighborMesh.voxelMesh.finish(neighborMesh);
|
||||||
try neighborMesh.transparentMesh.finish(neighborMesh);
|
try neighborMesh.transparentMesh.finish(neighborMesh);
|
||||||
continue;
|
} else {
|
||||||
|
if(self.lastNeighborsSameLod[neighbor] != null) {
|
||||||
|
self.opaqueMesh.clearNeighbor(neighbor, false);
|
||||||
|
self.voxelMesh.clearNeighbor(neighbor, false);
|
||||||
|
self.transparentMesh.clearNeighbor(neighbor, false);
|
||||||
|
}
|
||||||
|
self.lastNeighborsSameLod[neighbor] = null;
|
||||||
}
|
}
|
||||||
// lod border:
|
// lod border:
|
||||||
if(self.pos.voxelSize == 1 << settings.highestLOD) continue;
|
if(self.pos.voxelSize == 1 << settings.highestLOD) continue;
|
||||||
const neighborMesh = renderer.RenderStructure.getNeighborFromRenderThread(self.pos, 2*self.pos.voxelSize, neighbor) orelse {
|
const neighborMesh = renderer.RenderStructure.getNeighborFromRenderThread(self.pos, 2*self.pos.voxelSize, neighbor) orelse {
|
||||||
if(self.lastNeighbors[neighbor] != null) {
|
if(self.lastNeighborsHigherLod[neighbor] != null) {
|
||||||
self.opaqueMesh.clearNeighbor(neighbor);
|
self.opaqueMesh.clearNeighbor(neighbor, true);
|
||||||
self.voxelMesh.clearNeighbor(neighbor);
|
self.voxelMesh.clearNeighbor(neighbor, true);
|
||||||
self.transparentMesh.clearNeighbor(neighbor);
|
self.transparentMesh.clearNeighbor(neighbor, true);
|
||||||
}
|
}
|
||||||
self.lastNeighbors[neighbor] = null;
|
self.lastNeighborsHigherLod[neighbor] = null;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if(self.lastNeighbors[neighbor] == neighborMesh) continue;
|
if(self.lastNeighborsHigherLod[neighbor] == neighborMesh) continue;
|
||||||
self.lastNeighbors[neighbor] = neighborMesh;
|
self.lastNeighborsHigherLod[neighbor] = neighborMesh;
|
||||||
self.opaqueMesh.clearNeighbor(neighbor);
|
self.opaqueMesh.clearNeighbor(neighbor, true);
|
||||||
self.voxelMesh.clearNeighbor(neighbor);
|
self.voxelMesh.clearNeighbor(neighbor, true);
|
||||||
self.transparentMesh.clearNeighbor(neighbor);
|
self.transparentMesh.clearNeighbor(neighbor, true);
|
||||||
const x3: i32 = if(neighbor & 1 == 0) chunkMask else 0;
|
const x3: i32 = if(neighbor & 1 == 0) chunkMask else 0;
|
||||||
const offsetX = @divExact(self.pos.wx, self.pos.voxelSize) & chunkSize;
|
const offsetX = @divExact(self.pos.wx, self.pos.voxelSize) & chunkSize;
|
||||||
const offsetY = @divExact(self.pos.wy, self.pos.voxelSize) & chunkSize;
|
const offsetY = @divExact(self.pos.wy, self.pos.voxelSize) & chunkSize;
|
||||||
@ -1132,18 +1162,18 @@ pub const meshing = struct {
|
|||||||
const otherBlock = (&neighborMesh.chunk.blocks)[getIndex(otherX, otherY, otherZ)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
const otherBlock = (&neighborMesh.chunk.blocks)[getIndex(otherX, otherY, otherZ)]; // ← a temporary fix to a compiler performance bug. TODO: check if this was fixed.
|
||||||
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
|
if(canBeSeenThroughOtherBlock(otherBlock, block, neighbor ^ 1)) {
|
||||||
if(otherBlock.transparent()) {
|
if(otherBlock.transparent()) {
|
||||||
try self.transparentMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor);
|
try self.transparentMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor, true);
|
||||||
} else {
|
} else {
|
||||||
if(blocks.meshes.model(otherBlock).modelIndex == 0) {
|
if(blocks.meshes.model(otherBlock).modelIndex == 0) {
|
||||||
try self.opaqueMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor);
|
try self.opaqueMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor, true);
|
||||||
} else {
|
} else {
|
||||||
try self.voxelMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor);
|
try self.voxelMesh.appendNeighbor(constructFaceData(otherBlock, neighbor ^ 1, x, y, z, false), neighbor, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(block.hasBackFace()) {
|
if(block.hasBackFace()) {
|
||||||
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
|
if(canBeSeenThroughOtherBlock(block, otherBlock, neighbor)) {
|
||||||
try self.transparentMesh.appendNeighbor(constructFaceData(block, neighbor ^ 1, x, y, z, true), neighbor);
|
try self.transparentMesh.appendNeighbor(constructFaceData(block, neighbor ^ 1, x, y, z, true), neighbor, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user