block chunks properly stride
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-23 18:58:42 -04:00
parent 456036c0d2
commit 086c6da72e
8 changed files with 80 additions and 37 deletions

View File

@ -1948,6 +1948,7 @@ Small fixes
(05/23/2025)
Town layout work
Macro broadphase filters prior to per-voxel macro data intersection checks
Block chunks properly stride

View File

@ -30,64 +30,68 @@ public class BlockDrawCell {
/**
* Number of child cells per parent cell
*/
static final int CHILD_CELLS_PER_PARENT = 8;
private static final int CHILD_CELLS_PER_PARENT = 8;
//the position of the draw cell in world coordinates
Vector3i worldPos;
/**
* the position of the draw cell in world coordinates
*/
private Vector3i worldPos;
/**
* The LOD of the draw cell
*/
int lod;
protected int lod;
//the main entity for the cell
List<Entity> modelEntities = new LinkedList<Entity>();
/**
* the main entity for the cell
*/
private List<Entity> modelEntities = new LinkedList<Entity>();
/**
* The data for generating the visuals
*/
BlockChunkData chunkData;
private BlockChunkData chunkData;
/**
* Tracks whether the draw cell has requested its chunk data or not
*/
boolean hasRequested = false;
private boolean hasRequested = false;
/**
* Tracks whether the draw cell has generated its entity or not
*/
boolean hasGenerated = false;
private boolean hasGenerated = false;
/**
* Tracks whether this draw cell is flagged as homogenous from the server or not
*/
boolean homogenous = false;
private boolean homogenous = false;
/**
* Number of failed generation attempts
*/
int failedGenerationAttempts = 0;
private int failedGenerationAttempts = 0;
/**
* Labels an invalid distance cache
*/
static final int INVALID_DIST_CACHE = -1;
private static final int INVALID_DIST_CACHE = -1;
/**
* The cached minimum distance
*/
long cachedMinDistance = -1;
private long cachedMinDistance = -1;
/**
* Target to notify on generation completion
*/
BlockDrawCell notifyTarget = null;
private BlockDrawCell notifyTarget = null;
/**
* The number of cells that have alerted this one
*/
int generationAlertCount = 0;
private int generationAlertCount = 0;
/**

View File

@ -480,7 +480,7 @@ public class CursorState {
public void setSelectedFab(BlockFab fab){
Map<Integer,Boolean> solidsMap = Globals.gameConfigCurrent.getBlockData().getSolidsMap();
QueuedModel queuedModel = new QueuedModel(() -> {
return BlockMeshgen.generateBlockModel(BlockMeshgen.rasterize(fab,false,solidsMap));
return BlockMeshgen.generateBlockModel(BlockMeshgen.rasterize(fab,false,solidsMap,BlockMeshgen.DEFAULT_SCALING_FACTOR));
});
Globals.assetManager.queuedAsset(queuedModel);
EntityCreationUtils.makeEntityDrawablePreexistingModel(playerFabCursor, queuedModel.getPromisedPath());

View File

@ -71,7 +71,7 @@ public class BlockChunkEntity {
generationService.submit(() -> {
BlockMeshData data;
try {
data = BlockMeshgen.rasterize(chunkData, true, solidsMap);
data = BlockMeshgen.rasterize(chunkData, true, solidsMap,(int)Math.pow(2,levelOfDetail));
if(Globals.clientState.clientScene.containsEntity(solidsEnt) && data.getFaceElements().length > 0){
String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> {
return BlockMeshgen.generateBlockModel(data);
@ -122,7 +122,7 @@ public class BlockChunkEntity {
generationService.submit(() -> {
BlockMeshData data;
try {
data = BlockMeshgen.rasterize(chunkData, false, solidsMap);
data = BlockMeshgen.rasterize(chunkData, false, solidsMap, (int)Math.pow(2,levelOfDetail));
if(Globals.clientState.clientScene.containsEntity(transparentEnt) && data.getFaceElements().length > 0){
String modelPath = Globals.assetManager.queuedAsset(new QueuedModel(() -> {
return BlockMeshgen.generateBlockModel(data);

View File

@ -334,7 +334,7 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
* @param worldZ the world z
* @param stride The stride of the data
*/
static void sendBlocksAsyncStrided(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ, int stride){
private static void sendBlocksAsyncStrided(ServerConnectionHandler connectionHandler, int worldX, int worldY, int worldZ, int stride){
Globals.profiler.beginAggregateCpuSample("TerrainProtocol(server).sendWorldSubChunk");
// System.out.println("Received request for chunk " + message.getworldX() + " " + message.getworldY());

View File

@ -66,6 +66,11 @@ public class BlockMeshgen {
*/
static final int SAMPLER_DATA_SIZE = 1;
/**
* Default scaling factor
*/
public static final int DEFAULT_SCALING_FACTOR = 1;
/**
* Checks whether this block should be rasterized or not
@ -394,9 +399,10 @@ public class BlockMeshgen {
* @param chunkData The block chunk data
* @param solids true to rasterize solid blocks, false to rasterize transparent blocks
* @param solidsMap The solids map
* @param scalingFactor Scaling applied to the verts
* @return The mesh data
*/
public static BlockMeshData rasterize(BlockMeshgenData chunkData, boolean solids, Map<Integer,Boolean> solidsMap){
public static BlockMeshData rasterize(BlockMeshgenData chunkData, boolean solids, Map<Integer,Boolean> solidsMap, int scalingFactor){
BlockMeshData rVal = new BlockMeshData();
//calculate quad meshes
@ -456,9 +462,9 @@ public class BlockMeshgen {
rVal.vertices = new float[verts.size() * 3];
for(int i = 0; i < verts.size(); i++){
Vector3f currentVert = verts.get(i);
rVal.vertices[3 * i + 0] = currentVert.x;
rVal.vertices[3 * i + 1] = currentVert.y;
rVal.vertices[3 * i + 2] = currentVert.z;
rVal.vertices[3 * i + 0] = currentVert.x * scalingFactor;
rVal.vertices[3 * i + 1] = currentVert.y * scalingFactor;
rVal.vertices[3 * i + 2] = currentVert.z * scalingFactor;
}
rVal.vertBuffer = BufferUtils.createFloatBuffer(rVal.vertices.length);
rVal.vertBuffer.put(rVal.vertices);
@ -486,8 +492,8 @@ public class BlockMeshgen {
rVal.uvs = new float[uvs.size() * 2];
for(int i = 0; i < uvs.size(); i++){
Vector2f currentUV = uvs.get(i);
rVal.uvs[2 * i + 0] = currentUV.x;
rVal.uvs[2 * i + 1] = currentUV.y;
rVal.uvs[2 * i + 0] = currentUV.x * scalingFactor;
rVal.uvs[2 * i + 1] = currentUV.y * scalingFactor;
}
rVal.uvBuffer = BufferUtils.createFloatBuffer(rVal.uvs.length);
rVal.uvBuffer.put(rVal.uvs);
@ -509,7 +515,7 @@ public class BlockMeshgen {
* @return The mesh data
*/
public static BlockMeshData rasterize(BlockMeshgenData chunkData){
return BlockMeshgen.rasterize(chunkData, true, null);
return BlockMeshgen.rasterize(chunkData, true, null, BlockMeshgen.DEFAULT_SCALING_FACTOR);
}
/**

View File

@ -326,6 +326,15 @@ public class ServerWorldData {
);
}
public static void convertRealToChunkSpace(Vector3d position, Vector3i destVec){
destVec.set(
ServerWorldData.convertRealToChunkSpace(position.x),
ServerWorldData.convertRealToChunkSpace(position.y),
ServerWorldData.convertRealToChunkSpace(position.z)
);
}
/**
* Converts a world space vector to a real space vector
* @param position The world space vector
@ -387,6 +396,19 @@ public class ServerWorldData {
);
}
/**
* Converts a real coordinate to a local block grid space coordinate
* @param position The real coordinate
* @param destVec The vector to store the result in
*/
public static void convertRealToLocalBlockSpace(Vector3d position, Vector3i destVec){
destVec.set(
ServerWorldData.convertRealToLocalBlockSpace(position.x),
ServerWorldData.convertRealToLocalBlockSpace(position.y),
ServerWorldData.convertRealToLocalBlockSpace(position.z)
);
}
/**
* Converts a world coordinate to a macro scale coordinate
* @param worldPos The world position

View File

@ -21,6 +21,7 @@ import electrosphere.server.macro.spatial.MacroLODObject;
import electrosphere.server.macro.spatial.MacroObject;
import electrosphere.server.macro.structure.VirtualStructure;
import electrosphere.server.physics.block.diskmap.ServerBlockChunkDiskMap;
import electrosphere.server.physics.terrain.manager.ServerChunkCache;
/**
* A job that fetches a chunk, either by generating it or by reading it from disk
@ -177,7 +178,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
chunk = chunkCache.get(worldX, worldY, worldZ, stride);
} else {
//pull from disk if it exists
if(chunkDiskMap != null){
if(chunkDiskMap != null && stride == ServerChunkCache.STRIDE_FULL_RES){
if(chunkDiskMap.containsBlocksAtPosition(worldX, worldY, worldZ)){
chunk = chunkDiskMap.getBlockChunk(worldX, worldY, worldZ);
}
@ -188,7 +189,7 @@ public class ServerBlockChunkGenerationThread implements Runnable {
chunk.setWorldX(worldX);
chunk.setWorldY(worldY);
chunk.setWorldZ(worldZ);
ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ);
ServerBlockChunkGenerationThread.generate(chunk, macroData, worldX, worldY, worldZ, stride);
}
if(chunk != null){
chunkCache.add(worldX, worldY, worldZ, stride, chunk);
@ -204,36 +205,45 @@ public class ServerBlockChunkGenerationThread implements Runnable {
* @param worldX THe world x coordinate
* @param worldY The world y coordinate
* @param worldZ The world z coordinate
* @param stride The stride of the data to generate
*/
protected static void generate(BlockChunkData chunk, MacroData macroData, int worldX, int worldY, int worldZ){
protected static void generate(BlockChunkData chunk, MacroData macroData, int worldX, int worldY, int worldZ, int stride){
if(macroData == null){
chunk.setHomogenousValue(0);
return;
}
//check if this chunk intersects any macro data
AABBd localAABB = new AABBd(ServerWorldData.convertChunkToRealSpace(worldX,worldY,worldZ),ServerWorldData.convertChunkToRealSpace(worldX+1,worldY+1,worldZ+1));
int strideMultiplier = (int)Math.pow(2,stride);
if(strideMultiplier > 16){
throw new Error("Invalid stride size!");
}
AABBd localAABB = new AABBd(ServerWorldData.convertChunkToRealSpace(worldX,worldY,worldZ),ServerWorldData.convertChunkToRealSpace(worldX+strideMultiplier,worldY+strideMultiplier,worldZ+strideMultiplier));
List<VirtualStructure> filtered = macroData.getStructures().stream().filter((VirtualStructure struct) -> {return !struct.isRepairable() && struct.getAABB().testAABB(localAABB);}).collect(Collectors.toList());
if(filtered.size() > 0){
Vector3i chunkPos = new Vector3i(worldX, worldY, worldZ);
Vector3i blockPos = new Vector3i(0,0,0);
Vector3d chunkRealPos = ServerWorldData.convertChunkToRealSpace(chunkPos);
Vector3i localBlockPos = new Vector3i();
Vector3d currRealPos = new Vector3d(chunkRealPos);
//contains at least one structure
for(int x = 0; x < BlockChunkData.CHUNK_DATA_WIDTH; x++){
for(int y = 0; y < BlockChunkData.CHUNK_DATA_WIDTH; y++){
for(int z = 0; z < BlockChunkData.CHUNK_DATA_WIDTH; z++){
boolean placedBlock = false;
currRealPos.set(chunkRealPos).add(x * strideMultiplier * BlockChunkData.BLOCK_SIZE_MULTIPLIER,y * strideMultiplier * BlockChunkData.BLOCK_SIZE_MULTIPLIER,z * strideMultiplier * BlockChunkData.BLOCK_SIZE_MULTIPLIER);
ServerWorldData.convertRealToLocalBlockSpace(currRealPos,blockPos);
ServerWorldData.convertRealToChunkSpace(currRealPos,chunkPos);
//try placing a structure block
blockPos.set(x,y,z);
Vector3d currRealPoint = ServerWorldData.convertLocalBlockToRealSpace(chunkPos, blockPos);
blockPos.set(x*strideMultiplier,y*strideMultiplier,z*strideMultiplier);
for(VirtualStructure struct : filtered){
if(struct.getAABB().testPoint(currRealPoint.x, currRealPoint.y, currRealPoint.z)){
if(struct.getAABB().testPoint(currRealPos.x, currRealPos.y, currRealPos.z)){
AABBd aabb = struct.getAABB();
localBlockPos.set(
(int)((chunkRealPos.x + (x * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - aabb.minX) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
(int)((chunkRealPos.y + (y * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - aabb.minY) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
(int)((chunkRealPos.z + (z * BlockChunkData.BLOCK_SIZE_MULTIPLIER) - aabb.minZ) / BlockChunkData.BLOCK_SIZE_MULTIPLIER)
(int)((currRealPos.x - aabb.minX) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
(int)((currRealPos.y - aabb.minY) / BlockChunkData.BLOCK_SIZE_MULTIPLIER),
(int)((currRealPos.z - aabb.minZ) / BlockChunkData.BLOCK_SIZE_MULTIPLIER)
);
//structure file might have dimensions larger than fab, so need to make sure we're inbounds on fab file to draw data from fab file
if(localBlockPos.x < struct.getFab().getDimensions().x && localBlockPos.y < struct.getFab().getDimensions().y && localBlockPos.z < struct.getFab().getDimensions().z){