use of io.xol.chunkstories.renderer.terrain.FarTerrainBaker.RegionMesh in project chunkstories by Hugobros3.
the class FarTerrainMeshRenderer method drawTerrainBits.
private int drawTerrainBits(RenderingInterface renderingContext, ReadyVoxelMeshesMask mask, Shader terrainShader) {
// Starts asynch regeneration
if (farTerrainUpdatesToTakeIntoAccount.get() > 0 && (System.currentTimeMillis() - this.lastTerrainUpdateTiming) > this.timeToWaitBetweenTerrainUpdates) {
if (this.isTerrainUpdateRunning.compareAndSet(false, true))
this.startAsynchSummaryRegeneration(renderingContext.getCamera());
}
// Setups stuff
renderingContext.setCullingMode(CullingMode.COUNTERCLOCKWISE);
renderingContext.setDepthTestMode(DepthTestMode.LESS_OR_EQUAL);
// Camera is of position
CameraInterface camera = renderingContext.getCamera();
int camRX = (int) (camera.getCameraPosition().x() / 256);
int camRZ = (int) (camera.getCameraPosition().z() / 256);
int wrapRegionsDistance = world.getSizeInChunks() / 2;
int worldSizeInRegions = world.getSizeInChunks() / 8;
int cameraChunkX = (int) (camera.getCameraPosition().x() / 32);
int cameraChunkZ = (int) (camera.getCameraPosition().z() / 32);
// Update their displayed position to reflect where the camera is
for (RegionMesh mesh : renderedRegions) {
mesh.regionDisplayedX = mesh.regionSummary.getRegionX();
mesh.regionDisplayedZ = mesh.regionSummary.getRegionZ();
// We wrap the chunks if they are too far
if (mesh.regionSummary.getRegionX() * 8 - cameraChunkX > wrapRegionsDistance)
mesh.regionDisplayedX += -worldSizeInRegions;
if (mesh.regionSummary.getRegionX() * 8 - cameraChunkX < -wrapRegionsDistance)
mesh.regionDisplayedX += worldSizeInRegions;
if (mesh.regionSummary.getRegionZ() * 8 - cameraChunkZ > wrapRegionsDistance)
mesh.regionDisplayedZ += -worldSizeInRegions;
if (mesh.regionSummary.getRegionZ() * 8 - cameraChunkZ < -wrapRegionsDistance)
mesh.regionDisplayedZ += worldSizeInRegions;
// System.out.println(mesh.regionDisplayedX + " : " + cameraChunkX);
}
// Sort to draw near first
// µ-opt
// List<FarTerrainBaker.RegionMesh> regionsMeshesToRenderSorted = new ArrayList<FarTerrainBaker.RegionMesh>(renderedRegions);
regionsMeshesToRenderSorted.clear();
regionsMeshesToRenderSorted.addAll(renderedRegions);
regionsMeshesToRenderSorted.sort(new Comparator<FarTerrainBaker.RegionMesh>() {
@Override
public int compare(FarTerrainBaker.RegionMesh a, FarTerrainBaker.RegionMesh b) {
int distanceA = Math.abs(a.regionDisplayedX - camRX) + Math.abs(a.regionDisplayedZ - camRZ);
int distanceB = Math.abs(b.regionDisplayedX - camRX) + Math.abs(b.regionDisplayedZ - camRZ);
return distanceA - distanceB;
}
});
// µ-opt
/*List<Integer> temp = new ArrayList<Integer>();
List<Integer> temp2 = new ArrayList<Integer>();*/
temp.clear();
temp2.clear();
int bitsDrew = 0;
CollisionBox collisionBoxCheck = new CollisionBox(0, 0, 0, 0, 0, 0);
for (FarTerrainBaker.RegionMesh regionMesh : regionsMeshesToRenderSorted) {
// Frustrum checks (assuming maxHeight of 1024 blocks)
// TODO do a simple max() and improve accuracy
float height = 1024f;
// Early-out
if (!renderingContext.getCamera().isBoxInFrustrum(new CollisionBox(regionMesh.regionDisplayedX * 256, 0, regionMesh.regionDisplayedZ * 256, 256, height, 256)))
continue;
for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) {
int delta = regionMesh.regionSummary.max[i][j] - regionMesh.regionSummary.min[i][j];
collisionBoxCheck.xpos = (regionMesh.regionDisplayedX * 8 + i) * 32;
collisionBoxCheck.ypos = regionMesh.regionSummary.min[i][j];
collisionBoxCheck.zpos = (regionMesh.regionDisplayedZ * 8 + j) * 32;
collisionBoxCheck.xw = 32;
collisionBoxCheck.h = delta + 1;
collisionBoxCheck.zw = 32;
if (renderingContext.getCamera().isBoxInFrustrum(collisionBoxCheck)) // if (renderingContext.getCamera().isBoxInFrustrum(new CollisionBox((regionMesh.regionDisplayedX * 8 + i) * 32, regionMesh.regionSummary.min[i][j], (regionMesh.regionDisplayedZ * 8 + j) * 32, 32, delta + 1, 32)))
{
if (mask != null) {
if (mask.shouldMaskSlab(regionMesh.regionDisplayedX * 8 + i, regionMesh.regionDisplayedZ * 8 + j, regionMesh.regionSummary.min[i][j], regionMesh.regionSummary.max[i][j]))
continue;
}
temp.add(regionMesh.vertexSectionsOffsets[i][j]);
temp2.add(regionMesh.vertexSectionsSizes[i][j]);
}
}
if (temp.size() == 0)
continue;
HeightmapImplementation regionSummaryData = regionMesh.regionSummary;
// Skip unloaded regions immediately
if (regionSummaryData.isUnloaded())
continue;
renderingContext.bindArrayTexture("heights", worldRenderer.getSummariesTexturesHolder().getHeightsArrayTexture());
renderingContext.bindArrayTexture("topVoxels", worldRenderer.getSummariesTexturesHolder().getTopVoxelsArrayTexture());
renderingContext.bindTexture1D("blocksTexturesSummary", getBlocksTexturesSummary());
int index = worldRenderer.getSummariesTexturesHolder().getSummaryIndex(regionSummaryData.getRegionX(), regionSummaryData.getRegionZ());
if (index == -1) {
// System.out.println("index == -1");
continue;
}
// System.out.println("index:"+index);
terrainShader.setUniform1i("arrayIndex", index);
/*renderingContext.bindTexture2D("groundTexture", regionSummaryData.voxelTypesTexture);
regionSummaryData.voxelTypesTexture.setTextureWrapping(false);
regionSummaryData.voxelTypesTexture.setLinearFiltering(false);
renderingContext.bindTexture2D("heightMap", regionSummaryData.heightsTexture);
regionSummaryData.heightsTexture.setTextureWrapping(false);
regionSummaryData.heightsTexture.setLinearFiltering(false);*/
// Actual region position
terrainShader.setUniform2f("regionPosition", regionSummaryData.getRegionX(), regionSummaryData.getRegionZ());
// Displayed position
terrainShader.setUniform2f("visualOffset", regionMesh.regionDisplayedX * 256, regionMesh.regionDisplayedZ * 256);
// Checks this regionMesh instance has it's stuff uploaded already
if (!regionMesh.verticesObject.isDataPresent())
continue;
// else
// System.out.println("warning");
int stride = 4 * 2 + 4 + 0 * 4;
int vertices2draw = (int) (regionMesh.verticesObject.getVramUsage() / stride);
renderingContext.bindAttribute("vertexIn", regionMesh.verticesObject.asAttributeSource(VertexFormat.SHORT, 3, stride, 0L));
renderingContext.bindAttribute("normalIn", regionMesh.verticesObject.asAttributeSource(VertexFormat.UBYTE, 4, stride, 8L));
bitsDrew += vertices2draw;
int[] theStuff = new int[temp.size() * 2];
for (int i = 0; i < temp.size(); i++) {
theStuff[i * 2] = temp.get(i);
theStuff[i * 2 + 1] = temp2.get(i);
}
temp.clear();
temp2.clear();
renderingContext.drawMany(Primitive.TRIANGLE, theStuff);
}
return bitsDrew;
}
use of io.xol.chunkstories.renderer.terrain.FarTerrainBaker.RegionMesh in project chunkstories by Hugobros3.
the class FarTerrainMeshRenderer method startAsynchSummaryRegeneration.
private void startAsynchSummaryRegeneration(CameraInterface camera) {
cameraChunkX = (int) (camera.getCameraPosition().x() / 32);
cameraChunkZ = (int) (camera.getCameraPosition().z() / 32);
Thread asynchGenerateThread = new Thread() {
@Override
public void run() {
int tookIntoAccount = farTerrainUpdatesToTakeIntoAccount.get();
Thread.currentThread().setName("Far terrain rebuilder thread");
Thread.currentThread().setPriority(Constants.TERRAIN_RENDERER_THREAD_PRIORITY);
FarTerrainBaker baker = new FarTerrainBaker(regionMeshBuffer, world, cameraChunkX, cameraChunkZ);
List<RegionMesh> previousMeshes = renderedRegions;
renderedRegions = baker.generateArround();
if (previousMeshes != null) {
for (RegionMesh rm : previousMeshes) {
rm.delete();
}
}
farTerrainUpdatesToTakeIntoAccount.addAndGet(-tookIntoAccount);
lastTerrainUpdateTiming = System.currentTimeMillis();
isTerrainUpdateRunning.set(false);
}
};
asynchGenerateThread.start();
}
Aggregations