use of io.xol.chunkstories.world.summary.HeightmapImplementation in project chunkstories by Hugobros3.
the class FarTerrainBaker method generateArround.
public List<RegionMesh> generateArround() {
List<FarTerrainBaker.RegionMesh> regionsToRender_NewList = new ArrayList<FarTerrainBaker.RegionMesh>();
int summaryDistance = 32;
int currentChunkX = cameraChunkX - summaryDistance;
while (currentChunkX < cameraChunkX + summaryDistance) {
// Computes where are we
int currentRegionX = (int) Math.floor(currentChunkX / 8f);
// if(currentChunkX < 0)
// currentRegionX--;
// System.out.println(currentChunkX + " : " + currentRegionX);
int nextRegionX = currentRegionX + 1;
int nextChunkX = nextRegionX * 8;
// Iterate over Z chunks but skip whole regions
int currentChunkZ = cameraChunkZ - summaryDistance;
while (currentChunkZ < cameraChunkZ + summaryDistance) {
// Computes where are we
int currentRegionZ = (int) Math.floor(currentChunkZ / 8f);
int nextRegionZ = currentRegionZ + 1;
int nextChunkZ = nextRegionZ * 8;
// Clear shit
regionMeshBuffer.clear();
/*int rx = currentChunkX / 8;
int rz = currentChunkZ / 8;
if (currentChunkZ < 0 && currentChunkZ % 8 != 0)
rz--;
if (currentChunkX < 0 && currentChunkX % 8 != 0)
rx--;*/
HeightmapImplementation summary = world.getRegionsSummariesHolder().getHeightmapWorldCoordinates(currentChunkX * 32, currentChunkZ * 32);
if (summary == null || !summary.isLoaded()) {
currentChunkZ = nextChunkZ;
continue;
}
int rcx = currentChunkX % world.getSizeInChunks();
if (rcx < 0)
rcx += world.getSizeInChunks();
int rcz = currentChunkZ % world.getSizeInChunks();
if (rcz < 0)
rcz += world.getSizeInChunks();
int[] heightMap = summary.getHeightData();
int[] ids = summary.getVoxelData();
@SuppressWarnings("unused") int vertexCount = 0;
// Compute the LODs for every subchunk of the region, plus borders
int[] lodsArray = new int[100];
for (int scx = -1; scx < 9; scx++) for (int scz = -1; scz < 9; scz++) {
int regionMiddleX = currentRegionX * 8 + scx;
int regionMiddleZ = currentRegionZ * 8 + scz;
int detail = (int) (Math.sqrt(Math.abs(regionMiddleX - cameraChunkX) * Math.abs(regionMiddleX - cameraChunkX) + Math.abs(regionMiddleZ - cameraChunkZ) * Math.abs(regionMiddleZ - cameraChunkZ)) / (world.getClient().getConfiguration().getBooleanOption("client.rendering.hqTerrain") ? 6f : 4f));
if (detail > 5)
detail = 5;
if (!world.getClient().getConfiguration().getBooleanOption("client.rendering.hqTerrain") && detail < 2)
detail = 2;
lodsArray[(scx + 1) * 10 + (scz + 1)] = detail;
}
int[][] vertexSectionsOffsets = new int[8][8];
int[][] vertexSectionsSizes = new int[8][8];
int currentOffset = 0;
int currentSize = 0;
for (int scx = 0; scx < 8; scx++) for (int scz = 0; scz < 8; scz++) {
currentOffset += currentSize;
vertexSectionsOffsets[scx][scz] = currentOffset;
currentSize = 0;
int chunkLod = lodsArray[(scx + 1) * 10 + (scz + 1)];
int cellSize = (int) Math.pow(2, chunkLod);
int x0 = (scx * 32) / cellSize;
int y0 = (scz * 32) / cellSize;
HeightmapMesher mesher = new HeightmapMesher(heightMap, ids, offsets[chunkLod], 32 / cellSize, x0, y0, 256 / cellSize);
int test = 0;
Surface surf = mesher.nextSurface();
while (surf != null) {
// Top
addVertexBytes(regionMeshBuffer, scx * 32 + (surf.getX()) * cellSize, surf.getLevel(), scz * 32 + (surf.getY()) * cellSize, 0, 1, 0, surf.getId());
addVertexBytes(regionMeshBuffer, scx * 32 + (surf.getX() + surf.getW()) * cellSize, surf.getLevel(), scz * 32 + (surf.getY() + surf.getH()) * cellSize, 0, 1, 0, surf.getId());
addVertexBytes(regionMeshBuffer, scx * 32 + (surf.getX() + surf.getW()) * cellSize, surf.getLevel(), scz * 32 + (surf.getY()) * cellSize, 0, 1, 0, surf.getId());
addVertexBytes(regionMeshBuffer, scx * 32 + (surf.getX()) * cellSize, surf.getLevel(), scz * 32 + (surf.getY()) * cellSize, 0, 1, 0, surf.getId());
addVertexBytes(regionMeshBuffer, scx * 32 + (surf.getX()) * cellSize, surf.getLevel(), scz * 32 + (surf.getY() + surf.getH()) * cellSize, 0, 1, 0, surf.getId());
addVertexBytes(regionMeshBuffer, scx * 32 + (surf.getX() + surf.getW()) * cellSize, surf.getLevel(), scz * 32 + (surf.getY() + surf.getH()) * cellSize, 0, 1, 0, surf.getId());
vertexCount += 6;
currentSize += 6;
// Left side
int vx = scx * 32 + (surf.getX()) * cellSize;
int vz = scz * 32 + (surf.getY()) * cellSize;
int heightCurrent = getHeight(heightMap, world, vx - cellSize, vz, currentRegionX, currentRegionZ, lodsArray[((int) Math.floor((vx - cellSize) / 32f) + 1) * 10 + (scz + 1)]);
int d = 0;
for (int i = 1; i < surf.getH() + 1; i++) {
int newHeight = (i < surf.getH()) ? getHeight(heightMap, world, vx - cellSize, vz + i * cellSize, currentRegionX, currentRegionZ, lodsArray[((int) Math.floor((vx - cellSize) / 32f) + 1) * 10 + ((int) Math.floor((vz + (i) * cellSize) / 32f) + 1)]) : -1;
if (newHeight != heightCurrent) {
if (heightCurrent != surf.getLevel()) {
int side = heightCurrent > surf.getLevel() ? 1 : -1;
addVertexBytes(regionMeshBuffer, vx, surf.getLevel(), vz + d * cellSize, side, 0, 0, surf.getId());
addVertexBytes(regionMeshBuffer, vx, heightCurrent, vz + d * cellSize, side, 0, 0, surf.getId());
addVertexBytes(regionMeshBuffer, vx, heightCurrent, vz + (i) * cellSize, side, 0, 0, surf.getId());
addVertexBytes(regionMeshBuffer, vx, surf.getLevel(), vz + d * cellSize, side, 0, 0, surf.getId());
addVertexBytes(regionMeshBuffer, vx, heightCurrent, vz + (i) * cellSize, side, 0, 0, surf.getId());
addVertexBytes(regionMeshBuffer, vx, surf.getLevel(), vz + (i) * cellSize, side, 0, 0, surf.getId());
vertexCount += 6;
currentSize += 6;
}
heightCurrent = newHeight;
d = i;
}
}
// Bot side
heightCurrent = getHeight(heightMap, world, vx, vz - cellSize, currentRegionX, currentRegionZ, lodsArray[((int) Math.floor((vx) / 32f) + 1) * 10 + ((int) Math.floor((vz - cellSize) / 32f) + 1)]);
d = 0;
for (int i = 1; i < surf.getW() + 1; i++) {
int newHeight = (i < surf.getW()) ? getHeight(heightMap, world, vx + i * cellSize, vz - cellSize, currentRegionX, currentRegionZ, lodsArray[((int) Math.floor((vx + i * cellSize) / 32f) + 1) * 10 + ((int) Math.floor((vz - cellSize) / 32f) + 1)]) : -1;
if (newHeight != heightCurrent) {
if (heightCurrent != surf.getLevel()) {
int side = heightCurrent > surf.getLevel() ? 1 : -1;
addVertexBytes(regionMeshBuffer, vx + d * cellSize, surf.getLevel(), vz, 0, 0, side, surf.getId());
addVertexBytes(regionMeshBuffer, vx + (i) * cellSize, heightCurrent, vz, 0, 0, side, surf.getId());
addVertexBytes(regionMeshBuffer, vx + d * cellSize, heightCurrent, vz, 0, 0, side, surf.getId());
addVertexBytes(regionMeshBuffer, vx + (i) * cellSize, heightCurrent, vz, 0, 0, side, surf.getId());
addVertexBytes(regionMeshBuffer, vx + d * cellSize, surf.getLevel(), vz, 0, 0, side, surf.getId());
addVertexBytes(regionMeshBuffer, vx + (i) * cellSize, surf.getLevel(), vz, 0, 0, side, surf.getId());
vertexCount += 6;
currentSize += 6;
}
heightCurrent = newHeight;
d = i;
}
}
// Next
surf = mesher.nextSurface();
test++;
}
if (test > 32 * 32 / (cellSize * cellSize)) {
System.out.println("Meshing made more than reasonnable vertices");
}
// If the next side has a coarser resolution we want to fill in the gaps
// We go alongside the two other sides of the mesh and we add another skirt to match the coarser mesh on the side
int nextMeshDetailsX = lodsArray[(scx + 2) * 10 + (scz + 1)];
if (nextMeshDetailsX > chunkLod) {
int vx = scx * 32 + 32;
for (int vz = scz * 32; vz < scz * 32 + 32; vz += cellSize) {
int height = getHeight(heightMap, world, vx - 1, vz, currentRegionX, currentRegionZ, chunkLod);
int heightNext = getHeight(heightMap, world, vx + 1, vz, currentRegionX, currentRegionZ, nextMeshDetailsX);
if (heightNext > height) {
int gapData = getIds(ids, world, vx - 1, vz, currentRegionX, currentRegionZ, chunkLod);
addVertexBytes(regionMeshBuffer, vx, height, vz, 1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, heightNext, vz + cellSize, 1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, heightNext, vz, 1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, height, vz, 1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, height, vz + cellSize, 1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, heightNext, vz + cellSize, 1, 0, 0, gapData);
vertexCount += 6;
currentSize += 6;
} else if (heightNext < height) {
int gapData = getIds(ids, world, vx + 1, vz, currentRegionX, currentRegionZ, chunkLod);
addVertexBytes(regionMeshBuffer, vx, height, vz, -1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, heightNext, vz, -1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, heightNext, vz + cellSize, -1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, height, vz, -1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, heightNext, vz + cellSize, -1, 0, 0, gapData);
addVertexBytes(regionMeshBuffer, vx, height, vz + cellSize, -1, 0, 0, gapData);
vertexCount += 6;
currentSize += 6;
}
}
}
int nextMeshDetailsZ = lodsArray[(scx + 1) * 10 + (scz + 2)];
if (nextMeshDetailsZ > chunkLod) {
int vz = scz * 32 + 32;
for (int vx = scx * 32; vx < scx * 32 + 32; vx += cellSize) {
int height = getHeight(heightMap, world, vx, vz - 1, currentRegionX, currentRegionZ, chunkLod);
int heightNext = getHeight(heightMap, world, vx, vz + 1, currentRegionX, currentRegionZ, nextMeshDetailsZ);
if (heightNext > height) {
int gapData = getIds(heightMap, world, vx, vz - 1, currentRegionX, currentRegionZ, nextMeshDetailsZ);
addVertexBytes(regionMeshBuffer, vx, height, vz, 0, 0, 1, gapData);
addVertexBytes(regionMeshBuffer, vx, heightNext, vz, 0, 0, 1, gapData);
addVertexBytes(regionMeshBuffer, vx + cellSize, heightNext, vz, 0, 0, 1, gapData);
addVertexBytes(regionMeshBuffer, vx, height, vz, 0, 0, 1, gapData);
addVertexBytes(regionMeshBuffer, vx + cellSize, heightNext, vz, 0, 0, 1, gapData);
addVertexBytes(regionMeshBuffer, vx + cellSize, height, vz, 0, 0, 1, gapData);
vertexCount += 6;
currentSize += 6;
} else if (heightNext < height) {
int gapData = getIds(heightMap, world, vx, vz + 1, currentRegionX, currentRegionZ, nextMeshDetailsZ);
addVertexBytes(regionMeshBuffer, vx, height, vz, 0, 0, -1, gapData);
addVertexBytes(regionMeshBuffer, vx + cellSize, heightNext, vz, 0, 0, -1, gapData);
addVertexBytes(regionMeshBuffer, vx, heightNext, vz, 0, 0, -1, gapData);
addVertexBytes(regionMeshBuffer, vx, height, vz, 0, 0, -1, gapData);
addVertexBytes(regionMeshBuffer, vx + cellSize, height, vz, 0, 0, -1, gapData);
addVertexBytes(regionMeshBuffer, vx + cellSize, heightNext, vz, 0, 0, -1, gapData);
vertexCount += 6;
currentSize += 6;
}
}
}
// Computes those sizes
vertexSectionsSizes[scx][scz] = currentSize;
}
byte[] vboContent = new byte[regionMeshBuffer.position()];
regionMeshBuffer.flip();
regionMeshBuffer.get(vboContent);
FarTerrainBaker.RegionMesh regionMesh = new FarTerrainBaker.RegionMesh(summary, vboContent, vertexSectionsOffsets, vertexSectionsSizes);
regionsToRender_NewList.add(regionMesh);
currentChunkZ = nextChunkZ;
}
currentChunkX = nextChunkX;
}
return regionsToRender_NewList;
}
use of io.xol.chunkstories.world.summary.HeightmapImplementation 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.world.summary.HeightmapImplementation in project chunkstories by Hugobros3.
the class HeightmapArrayTexture method update.
public void update() {
Player player = client.getPlayer();
Location playerPosition = player.getLocation();
if (playerPosition == null)
// We won't do shit with that going on
return;
World world = playerPosition.getWorld();
int chunkX = (int) Math.floor(playerPosition.x / 32.0);
int chunkZ = (int) Math.floor(playerPosition.z / 32.0);
int regionX = chunkX / 8;
int regionZ = chunkZ / 8;
// Remap the array
if (lastRegionX != regionX || lastRegionZ != regionZ || redo.compareAndSet(true, false)) {
WriteLock writeLock = lock.writeLock();
writeLock.lock();
// We may need this
ByteBuffer bb = MemoryUtil.memAlloc(4 * 256 * 256);
bb.order(ByteOrder.LITTLE_ENDIAN);
// Clear unused slots
for (int i = 0; i < 81; i++) {
ArrayTextureSlot slot = arrayTextureContents[i];
if (slot == null)
continue;
// Frees slots immediately once out of the area we care about
if (Math.abs(slot.regionX - regionX) >= 5 || Math.abs(slot.regionZ - regionZ) >= 5)
arrayTextureContents[i] = null;
}
for (int i = -4; i <= 4; i++) for (int j = -4; j <= 4; j++) {
int regionI = regionX + i;
int regionJ = regionZ + j;
// Wrap arround the world!
if (regionI < 0)
regionI += world.getSizeInChunks() / 256;
if (regionJ < 0)
regionJ += world.getSizeInChunks() / 256;
// Look for a slot already containing our wanted textures
int free = -1;
int good = -1;
for (int k = 0; k < 81; k++) {
ArrayTextureSlot slot = arrayTextureContents[k];
if (slot == null) {
if (free == -1)
free = k;
} else {
if (slot.regionX == regionI && slot.regionZ == regionJ) {
good = k;
break;
}
}
}
int slot;
// If no good slot was found :(
if (good == -1) {
arrayTextureContents[free] = new ArrayTextureSlot();
arrayTextureContents[free].regionX = regionI;
arrayTextureContents[free].regionZ = regionJ;
slot = free;
} else {
slot = good;
}
// If data is not yet in the slot, check if the world has data for it
if (!arrayTextureContents[slot].hasData) {
Heightmap sum = world.getRegionsSummariesHolder().getHeightmap(arrayTextureContents[slot].regionX, arrayTextureContents[slot].regionZ);
if (sum != null && sum.isLoaded()) {
loadHeights((HeightmapImplementation) sum, bb, 0);
heights.uploadTextureData(slot, 0, bb);
for (int lod = 1; lod <= 8; lod++) {
loadHeights((HeightmapImplementation) sum, bb, lod);
heights.uploadTextureData(slot, lod, bb);
}
heights.setMipMapping(true);
heights.setMipmapLevelsRange(0, 8);
loadTopVoxels((HeightmapImplementation) sum, bb, 0);
topVoxels.uploadTextureData(slot, 0, bb);
for (int lod = 1; lod <= 8; lod++) {
loadTopVoxels((HeightmapImplementation) sum, bb, lod);
topVoxels.uploadTextureData(slot, lod, bb);
}
topVoxels.setMipMapping(true);
topVoxels.setMipmapLevelsRange(0, 8);
arrayTextureContents[slot].hasData = true;
}
}
arrayTextureReference[i + 4][j + 4] = slot;
}
MemoryUtil.memFree(bb);
lastRegionX = regionX;
lastRegionZ = regionZ;
writeLock.unlock();
}
}
use of io.xol.chunkstories.world.summary.HeightmapImplementation in project chunkstories by Hugobros3.
the class TaskBuildHeightmap method task.
@Override
protected boolean task(TaskExecutor taskExecutor) {
ConverterWorkerThread cwt = (ConverterWorkerThread) taskExecutor;
// We wait on a bunch of stuff to load everytime
CompoundFence loadRelevantData = new CompoundFence();
HeightmapImplementation summary = csWorld.getRegionsSummariesHolder().aquireHeightmap(cwt, regionX, regionZ);
loadRelevantData.add(summary.waitForLoading());
// Aquires the chunks we want to make the summaries of.
for (int innerCX = 0; innerCX < 8; innerCX++) for (int innerCZ = 0; innerCZ < 8; innerCZ++) for (int chunkY = 0; chunkY < OfflineWorldConverter.mcWorldHeight / 32; chunkY++) {
ChunkHolder holder = csWorld.aquireChunkHolder(cwt, regionX * 8 + innerCX, chunkY, regionZ * 8 + innerCZ);
if (holder != null) {
loadRelevantData.add(holder.waitForLoading());
if (cwt.registeredCS_Holders.add(holder))
cwt.chunksAquired++;
}
}
// Wait until all of that crap loads
loadRelevantData.traverse();
// Descend from top
for (int i = 0; i < 256; i++) for (int j = 0; j < 256; j++) {
for (int h = OfflineWorldConverter.mcWorldHeight; h > 0; h--) {
CellData data = csWorld.peekSafely(regionX * 256 + i, h, regionZ * 256 + j);
if (!data.getVoxel().isAir()) {
Voxel vox = data.getVoxel();
if (vox.getDefinition().isSolid() || vox.getDefinition().isLiquid()) {
summary.setTopCell(data);
break;
}
}
}
}
Fence waitForSummarySave = summary.saveSummary();
// cwt.converter().verbose("Waiting for summary saving...");
waitForSummarySave.traverse();
// cwt.converter().verbose("Done.");
// We don't need the summary anymore
summary.unregisterUser(cwt);
return true;
}
use of io.xol.chunkstories.world.summary.HeightmapImplementation in project chunkstories by Hugobros3.
the class FarTerrainGSMeshRenderer method renderTerrain.
@Override
public void renderTerrain(RenderingInterface renderer, ReadyVoxelMeshesMask mask) {
Shader terrainShader = renderer.useShader("terrain_blocky");
renderer.setBlendMode(BlendMode.DISABLED);
renderer.getCamera().setupShader(terrainShader);
worldRenderer.getSkyRenderer().setupShader(terrainShader);
terrainShader.setUniform1f("viewDistance", world.getClient().getConfiguration().getIntOption("client.rendering.viewDistance"));
Texture2D waterTexture = renderer.textures().getTexture("./textures/water/shallow.png");
waterTexture.setLinearFiltering(true);
waterTexture.setMipMapping(true);
Texture2D waterTexture2 = renderer.textures().getTexture("./textures/water/deep.png");
waterTexture2.setLinearFiltering(true);
waterTexture2.setMipMapping(true);
// renderer.bindCubemap("environmentCubemap", worldRenderer.renderBuffers.rbEnvironmentMap);
renderer.bindTexture2D("blockLightmap", TexturesHandler.getTexture("./textures/environement/light.png"));
Texture2D lightColors = TexturesHandler.getTexture("./textures/environement/lightcolors.png");
renderer.bindTexture2D("lightColors", lightColors);
renderer.bindTexture2D("waterNormalShallow", waterTexture);
renderer.bindTexture2D("waterNormalDeep", waterTexture2);
world.getGenerator().getEnvironment().setupShadowColors(renderer, terrainShader);
renderer.bindTexture2D("vegetationColorTexture", world.getGenerator().getEnvironment().getGrassTexture(renderer));
terrainShader.setUniform1f("mapSize", worldRenderer.getWorld().getSizeInChunks() * 32);
terrainShader.setUniform1f("animationTimer", worldRenderer.getAnimationTimer());
renderer.bindArrayTexture("heights", worldRenderer.getSummariesTexturesHolder().getHeightsArrayTexture());
renderer.bindArrayTexture("topVoxels", worldRenderer.getSummariesTexturesHolder().getTopVoxelsArrayTexture());
renderer.bindTexture1D("blocksTexturesSummary", colours.get());
if (renderer.getClient().getInputsManager().getInputByName("wireframeFarTerrain").isPressed() && ClientLimitations.isDebugAllowed)
renderer.setPolygonFillMode(PolygonFillMode.WIREFRAME);
if (!renderer.getClient().getInputsManager().getInputByName("hideFarTerrain").isPressed() && ClientLimitations.isDebugAllowed) {
renderer.setCullingMode(CullingMode.DISABLED);
// renderer.setCullingMode(CullingMode.COUNTERCLOCKWISE);
renderer.setDepthTestMode(DepthTestMode.LESS_OR_EQUAL);
Player player = Client.getInstance().getPlayer();
Location playerPosition = player.getLocation();
if (playerPosition == null)
// We won't do shit with that going on
return;
Vector2d playerCenter = new Vector2d(playerPosition.x, playerPosition.z);
int chunkX = (int) Math.floor(playerPosition.x / 32.0);
int chunkZ = (int) Math.floor(playerPosition.z / 32.0);
int regionX = chunkX / 8;
int regionZ = chunkZ / 8;
int[] lodInstanceCount = new int[detailLevels.length];
ByteBuffer[] lodByteBuffer = new ByteBuffer[detailLevels.length];
// ByteBuffer summariesAttributes = MemoryUtil.memAlloc(9 * 9 * (4 + 2 * 4));
// MemFreeByteBuffer auto_free_summariesAttributes = new MemFreeByteBuffer(summariesAttributes);
// int count = 0;
double lodBias = -0.2;
double lodExponent = 0.35;
if (!world.getClient().getConfiguration().getBooleanOption("client.rendering.hqTerrain")) {
lodBias = 0.3;
lodExponent = 0.35;
} else {
lodBias = 0.0;
lodExponent = 0.45;
}
if (mask == null) {
lodExponent = 1.0;
lodBias = 0.6;
}
Vector2d center = new Vector2d();
for (int i = -4; i <= 4; i++) for (int j = -4; j <= 4; j++) {
int regionI = regionX + i;
int regionJ = regionZ + j;
int index = worldRenderer.getSummariesTexturesHolder().getSummaryIndex(regionI, regionJ);
if (index == -1)
continue;
// For the extra row of triangles to mask the seams
int index10 = worldRenderer.getSummariesTexturesHolder().getSummaryIndex(regionI + 1, regionJ);
int index01 = worldRenderer.getSummariesTexturesHolder().getSummaryIndex(regionI, regionJ + 1);
int index11 = worldRenderer.getSummariesTexturesHolder().getSummaryIndex(regionI + 1, regionJ + 1);
if (index10 == -1 || index01 == -1 || index11 == -1)
continue;
HeightmapImplementation sum = (HeightmapImplementation) world.getRegionsSummariesHolder().getHeightmap(regionI, regionJ);
// Early out
if (sum == null || !sum.isLoaded())
continue;
if (!renderer.getCamera().isBoxInFrustrum(new CollisionBox(regionI * 256, 0, regionJ * 256, 256, 1024, /*+ sum.getHeightMipmapped(0, 0, 9)*/
256)))
continue;
for (int l = 0; l < 8; l++) for (int m = 0; m < 8; m++) {
if (mask != null) {
if (mask.shouldMaskSlab(regionI * 8 + l, regionJ * 8 + m, sum.min[l][m], sum.max[l][m]))
continue;
}
center.set(regionI * 256 + l * 32 + 16, regionJ * 256 + m * 32 + 16);
int lod = detailLevels.length - (int) ((lodBias + Math.pow(Math.min(1024, center.distance(playerCenter)) / 1024, lodExponent)) * detailLevels.length);
// System.out.println(center.distance(playerCenter));
if (lod <= 0)
lod = 0;
if (lod >= detailLevels.length)
lod = detailLevels.length - 1;
// lod = 2;
// lod = 2;
// System.out.println("lod:"+lod);
// lod = Math.random() > 0.5 ? 1 : 2;
ByteBuffer summariesAttributes = lodByteBuffer[lod];
if (summariesAttributes == null) {
summariesAttributes = MemoryUtil.memAlloc(9 * 9 * 8 * 8 * (4 + 2 * 4));
lodByteBuffer[lod] = summariesAttributes;
}
summariesAttributes.putFloat(regionI * 256 + l * 32);
summariesAttributes.putFloat(regionJ * 256 + m * 32);
summariesAttributes.put((byte) index);
summariesAttributes.put((byte) index10);
summariesAttributes.put((byte) index01);
summariesAttributes.put((byte) index11);
lodInstanceCount[lod]++;
// Always add both so lod 1 is drew under
/*if(lod != 0) {
lod = 0;
summariesAttributes = lodByteBuffer[lod];
if(summariesAttributes == null) {
summariesAttributes = MemoryUtil.memAlloc(9 * 9 * 8 * 8 * (4 + 2 * 4));
lodByteBuffer[lod] = summariesAttributes;
}
summariesAttributes.putFloat(regionI * 256 + l * 32);
summariesAttributes.putFloat(regionJ * 256 + m * 32);
summariesAttributes.put((byte)index);
summariesAttributes.put((byte)index10);
summariesAttributes.put((byte)index01);
summariesAttributes.put((byte)index11);
lodInstanceCount[lod]++;
}*/
}
}
// for(int lod = 0; lod < detailLevels.length; lod++) {
for (int lod = detailLevels.length - 1; lod >= 0; lod--) {
// Check if anything was supposed to be drew at this lod
ByteBuffer summariesAttributes = lodByteBuffer[lod];
if (summariesAttributes == null)
continue;
if (lod < 0) {
MemoryUtil.memFree(summariesAttributes);
continue;
}
// Flip buffer, box it for autodeletion, upload it
summariesAttributes.flip();
MemFreeByteBuffer auto_free_summariesAttributes = new MemFreeByteBuffer(summariesAttributes);
gridAttributes.uploadData(auto_free_summariesAttributes);
terrainShader.setUniform1i("lodLevel", lod);
terrainShader.setUniform1f("textureLodLevel", lod - 5);
terrainShader.setUniform1i("maskPresence", mask == null ? 0 : 1);
renderer.bindAttribute("vertexIn", grids[lod].asAttributeSource(VertexFormat.FLOAT, 3, 0, 0L));
renderer.bindAttribute("displacementIn", gridAttributes.asAttributeSource(VertexFormat.FLOAT, 2, (4 + 2 * 4), 0L, 1));
renderer.bindAttribute("indexIn", gridAttributes.asIntegerAttributeSource(VertexFormat.BYTE, 4, (4 + 2 * 4), 8L, 1));
renderer.draw(Primitive.POINT, 0, (detailLevels[lod] + 1) * (detailLevels[lod] + 1) * 1, lodInstanceCount[lod]);
}
}
renderer.setPolygonFillMode(PolygonFillMode.FILL);
}
Aggregations