macro data blocks terrain and block gen
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-20 12:50:51 -04:00
parent 3685eb1c92
commit 27330797e9
10 changed files with 67 additions and 11 deletions

View File

@ -1916,6 +1916,7 @@ Place roads using line segments instead of splines
Town layout tries to connect intersection nodes with roads
Macro area objects don't store start/end bounds separate from aabb anymore
Unify functions to fetch/generate chunks on server
Macro data blocks terrain and block generation until it is ready

View File

@ -10,6 +10,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import org.joml.Vector3d;
@ -816,6 +817,14 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
try {
BlockChunkData blockChunkData = realm.getServerWorldData().getServerBlockManager().getChunk(worldPos.x, worldPos.y, worldPos.z);
ServerTerrainChunk terrainChunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldPos.x, worldPos.y, worldPos.z, ServerChunkCache.STRIDE_FULL_RES);
while(terrainChunk == null){
TimeUnit.MILLISECONDS.sleep(1);
terrainChunk = realm.getServerWorldData().getServerTerrainManager().getChunk(worldPos.x, worldPos.y, worldPos.z, ServerChunkCache.STRIDE_FULL_RES);
}
while(blockChunkData == null){
TimeUnit.MILLISECONDS.sleep(1);
blockChunkData = realm.getServerWorldData().getServerBlockManager().getChunk(worldPos.x, worldPos.y, worldPos.z);
}
targetCell.setTerrainChunk(terrainChunk);
targetCell.setBlockChunk(blockChunkData);

View File

@ -85,16 +85,22 @@ public class PhysicsDataCell {
//
this.fillInData();
//grab local reference to this cell's entities
Entity localPhysicsEnt = this.physicsEntity;
Entity localBlockPhysicsEntity = this.blockPhysicsEntity;
//check if cell has already been retired
if(localBlockPhysicsEntity == null || localPhysicsEnt == null){
return;
}
//generate
this.terrainChunkData = TerrainChunk.serverGenerateTerrainChunkData(weights, types);
TerrainChunk.serverCreateTerrainChunkEntity(this.physicsEntity, this.terrainChunkData);
this.physicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
TerrainChunk.serverCreateTerrainChunkEntity(localPhysicsEnt, this.terrainChunkData);
localPhysicsEnt.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
this.blockData = BlockMeshgen.rasterize(this.blockChunk);
BlockChunkEntity.serverCreateBlockChunkEntity(this.blockPhysicsEntity, this.blockData);
this.blockPhysicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
// //then actually perform the attach
// physicsObject = PhysicsUtils.attachTerrainRigidBody(physicsEntity,heightmap,true);
// Realm realm = Globals.serverState.realmManager.getEntityRealm(physicsEntity);
// realm.getCollisionEngine().registerPhysicsEntity(physicsEntity);
BlockChunkEntity.serverCreateBlockChunkEntity(localBlockPhysicsEntity, this.blockData);
localBlockPhysicsEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
}
/**

View File

@ -298,6 +298,7 @@ public class MacroData {
public List<MacroObject> getNearbyObjects(Vector3d position){
List<MacroObject> rVal = new LinkedList<MacroObject>();
rVal.addAll(this.roads);
rVal.addAll(this.towns);
return rVal;
}

View File

@ -0,0 +1,14 @@
package electrosphere.server.macro.spatial;
/**
* A macro object that can be simulated at different resolutions
*/
public interface MacroLODObject {
/**
* Checks if this macro object is full resolution or not
* @return true if it is full resolution, false otherwise
*/
public boolean isFullRes();
}

View File

@ -5,6 +5,7 @@ import electrosphere.server.macro.MacroData;
import electrosphere.server.macro.character.Character;
import electrosphere.server.macro.civilization.Civilization;
import electrosphere.server.macro.spatial.MacroAreaObject;
import electrosphere.server.macro.spatial.MacroLODObject;
import electrosphere.server.macro.structure.VirtualStructure;
import java.util.LinkedList;
@ -17,7 +18,7 @@ import org.joml.Vector3d;
/**
* Server representation of a town
*/
public class Town implements MacroAreaObject {
public class Town implements MacroAreaObject, MacroLODObject {
/**
* Minimum data resolution town (ie hasn't generated structures or residents)
@ -209,5 +210,10 @@ public class Town implements MacroAreaObject {
public Civilization getParent(MacroData macroData){
return macroData.getCivilization(this.parentCivId);
}
@Override
public boolean isFullRes() {
return this.resolution == TOWN_RES_MAX;
}
}

View File

@ -15,6 +15,8 @@ import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.datacell.ServerWorldData;
import electrosphere.server.macro.MacroData;
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;
@ -146,6 +148,17 @@ public class ServerBlockChunkGenerationThread implements Runnable {
ServerBlockChunkDiskMap chunkDiskMap,
BlockChunkCache chunkCache
){
//get the macro data that affects this chunk
List<MacroObject> objects = null;
if(macroData != null){
objects = macroData.getNearbyObjects(ServerWorldData.convertChunkToRealSpace(worldX, worldY, worldZ));
}
//if any of this macro data isn't ready, return a null chunk
long notFullResCount = objects.stream().filter((MacroObject macroObj) -> macroObj instanceof MacroLODObject).map((MacroObject oldView) -> (MacroLODObject)oldView).filter((MacroLODObject lodObj) -> !lodObj.isFullRes()).count();
if(notFullResCount > 0){
return null;
}
BlockChunkData chunk = null;
if(chunkCache.containsChunk(worldX, worldY, worldZ, stride)){
chunk = chunkCache.get(worldX, worldY, worldZ, stride);

View File

@ -14,6 +14,7 @@ import electrosphere.engine.Globals;
import electrosphere.server.datacell.ServerWorldData;
import electrosphere.server.macro.civilization.road.Road;
import electrosphere.server.macro.spatial.MacroObject;
import electrosphere.server.macro.town.Town;
import electrosphere.server.physics.terrain.generation.heightmap.EmptySkyGen;
import electrosphere.server.physics.terrain.generation.heightmap.HeightmapGenerator;
import electrosphere.server.physics.terrain.generation.heightmap.HeightmapNoiseGen;
@ -281,6 +282,7 @@ public class ProceduralChunkGenerator implements ChunkGenerator {
}
}
}
} else if(object instanceof Town){
} else {
throw new Error("Unsupported object type " + object);
}

View File

@ -8,6 +8,7 @@ import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.datacell.ServerWorldData;
import electrosphere.server.macro.MacroData;
import electrosphere.server.macro.spatial.MacroLODObject;
import electrosphere.server.macro.spatial.MacroObject;
import electrosphere.server.physics.terrain.diskmap.ChunkDiskMap;
import electrosphere.server.physics.terrain.generation.interfaces.ChunkGenerator;
@ -158,7 +159,10 @@ public class ChunkGenerationThread implements Runnable {
objects = macroData.getNearbyObjects(ServerWorldData.convertChunkToRealSpace(worldX, worldY, worldZ));
}
//if any of this macro data isn't ready, return a null chunk
long notFullResCount = objects.stream().filter((MacroObject macroObj) -> macroObj instanceof MacroLODObject).map((MacroObject oldView) -> (MacroLODObject)oldView).filter((MacroLODObject lodObj) -> !lodObj.isFullRes()).count();
if(notFullResCount > 0){
return null;
}
if(chunkCache.containsChunk(worldX, worldY, worldZ, stride)){
rVal = chunkCache.get(worldX, worldY, worldZ, stride);

View File

@ -291,7 +291,7 @@ public class ServerTerrainManager {
//THIS FIRES IF THERE IS A MAIN GAME WORLD RUNNING
ServerTerrainChunk returnedChunk = ChunkGenerationThread.getChunk(macroData, worldX, worldY, worldZ, stride, chunkDiskMap, chunkCache, chunkGenerator);
if(returnedChunk == null){
LoggerInterface.loggerEngine.WARNING("Failed to generate chunk at " + worldX + " " + worldY + " " + worldZ + " asynchronously");
LoggerInterface.loggerEngine.WARNING("Failed to generate chunk at " + worldX + " " + worldY + " " + worldZ + " synchronously");
}
Globals.profiler.endCpuSample();
return returnedChunk;