Have RenderSourceFileHandler update all detail levels
This commit is contained in:
+32
-65
@@ -4,6 +4,8 @@ import com.seibel.lod.core.dataObjects.fullData.FullDataPointIdMap;
|
||||
import com.seibel.lod.core.dataObjects.fullData.accessor.SingleColumnFullDataAccessor;
|
||||
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
|
||||
import com.seibel.lod.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.pos.DhChunkPos;
|
||||
import com.seibel.lod.core.util.RenderDataPointUtil;
|
||||
import com.seibel.lod.core.dataObjects.render.ColumnRenderSource;
|
||||
import com.seibel.lod.core.dataObjects.render.columnViews.ColumnArrayView;
|
||||
@@ -19,6 +21,8 @@ import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.lod.coreapi.util.BitShiftUtil;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class FullToColumnTransformer
|
||||
{
|
||||
@@ -87,19 +91,6 @@ public class FullToColumnTransformer
|
||||
|
||||
columnSource.fillDebugFlag(0, 0, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.DebugSourceFlag.FULL);
|
||||
|
||||
// } else if (dataDetail == 0 && columnSource.getDataDetail() > dataDetail) {
|
||||
// byte deltaDetail = (byte) (columnSource.getDataDetail() - dataDetail);
|
||||
// int perColumnWidth = 1 << deltaDetail;
|
||||
// int columnCount = pos.getWidth(dataDetail).value / perColumnWidth;
|
||||
//
|
||||
//
|
||||
// for (int x = 0; x < pos.getWidth(dataDetail).value; x++) {
|
||||
// for (int z = 0; z < pos.getWidth(dataDetail).value; z++) {
|
||||
// ColumnArrayView columnArrayView = columnSource.getVerticalDataView(x, z);
|
||||
// SingleColumnFullDataAccessor fullArrayView = data.get(x, z);
|
||||
// convertColumnData(level, columnArrayView, fullArrayView);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -144,6 +135,7 @@ public class FullToColumnTransformer
|
||||
|
||||
ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z);
|
||||
convertColumnData(level, baseX + x, baseZ + z, columnArrayView, fullArrayView, 1);
|
||||
|
||||
columnSource.fillDebugFlag(x, z, 1, 1, ColumnRenderSource.DebugSourceFlag.SPARSE);
|
||||
if (fullArrayView.doesColumnExist())
|
||||
LodUtil.assertTrue(columnSource.doesDataPointExist(x, z));
|
||||
@@ -162,20 +154,28 @@ public class FullToColumnTransformer
|
||||
* @throws InterruptedException Can be caused by interrupting the thread upstream.
|
||||
* Generally thrown if the method is running after the client leaves the current world.
|
||||
*/
|
||||
public static void writeFullDataChunkToColumnData(ColumnRenderSource render, IDhClientLevel level, ChunkSizedFullDataAccessor chunkDataView) throws InterruptedException
|
||||
public static void writeFullDataChunkToColumnData(ColumnRenderSource renderSource, IDhClientLevel level, ChunkSizedFullDataAccessor chunkDataView) throws InterruptedException, IllegalArgumentException
|
||||
{
|
||||
final DhSectionPos pos = render.getSectionPos();
|
||||
final int renderOffsetX = (chunkDataView.pos.x * LodUtil.CHUNK_WIDTH) - pos.getCorner().getCornerBlockPos().x;
|
||||
final int renderOffsetZ = (chunkDataView.pos.z * LodUtil.CHUNK_WIDTH) - pos.getCorner().getCornerBlockPos().z;
|
||||
final int blockX = pos.getCorner().getCornerBlockPos().x;
|
||||
final int blockZ = pos.getCorner().getCornerBlockPos().z;
|
||||
final int perRenderWidth = 1 << render.getDataDetail();
|
||||
final int perDataWidth = 1 << chunkDataView.detailLevel;
|
||||
render.markNotEmpty();
|
||||
final DhSectionPos renderSourcePos = renderSource.getSectionPos();
|
||||
|
||||
if (chunkDataView.detailLevel == render.getDataDetail())
|
||||
final int sourceBlockX = renderSourcePos.getCorner().getCornerBlockPos().x;
|
||||
final int sourceBlockZ = renderSourcePos.getCorner().getCornerBlockPos().z;
|
||||
|
||||
// offset between the incoming chunk data and this render source
|
||||
final int blockOffsetX = (chunkDataView.pos.x * LodUtil.CHUNK_WIDTH) - sourceBlockX;
|
||||
final int blockOffsetZ = (chunkDataView.pos.z * LodUtil.CHUNK_WIDTH) - sourceBlockZ;
|
||||
|
||||
final int sourceDataPointBlockWidth = BitShiftUtil.powerOfTwo(renderSource.getDataDetail());
|
||||
|
||||
|
||||
|
||||
if (chunkDataView.detailLevel == renderSource.getDataDetail())
|
||||
{
|
||||
if (renderOffsetX < 0 || renderOffsetX + LodUtil.CHUNK_WIDTH > render.getDataSize() || renderOffsetZ < 0 || renderOffsetZ + LodUtil.CHUNK_WIDTH > render.getDataSize())
|
||||
// confirm the render source contains this chunk
|
||||
if (blockOffsetX < 0
|
||||
|| blockOffsetX + LodUtil.CHUNK_WIDTH > renderSource.getWidthInDataPoints()
|
||||
|| blockOffsetZ < 0
|
||||
|| blockOffsetZ + LodUtil.CHUNK_WIDTH > renderSource.getWidthInDataPoints())
|
||||
{
|
||||
throw new IllegalArgumentException("Data offset is out of bounds");
|
||||
}
|
||||
@@ -187,56 +187,23 @@ public class FullToColumnTransformer
|
||||
{
|
||||
throwIfThreadInterrupted();
|
||||
|
||||
ColumnArrayView columnArrayView = render.getVerticalDataPointView(renderOffsetX + x, renderOffsetZ + z);
|
||||
ColumnArrayView columnArrayView = renderSource.getVerticalDataPointView(blockOffsetX + x, blockOffsetZ + z);
|
||||
SingleColumnFullDataAccessor fullArrayView = chunkDataView.get(x, z);
|
||||
convertColumnData(level, blockX + perRenderWidth * (renderOffsetX + x),
|
||||
blockZ + perRenderWidth * (renderOffsetZ + z),
|
||||
|
||||
convertColumnData(level,
|
||||
sourceBlockX + sourceDataPointBlockWidth * (blockOffsetX + x),
|
||||
sourceBlockZ + sourceDataPointBlockWidth * (blockOffsetZ + z),
|
||||
columnArrayView, fullArrayView, 2);
|
||||
|
||||
if (fullArrayView.doesColumnExist())
|
||||
{
|
||||
LodUtil.assertTrue(render.doesDataPointExist(renderOffsetX + x, renderOffsetZ + z));
|
||||
LodUtil.assertTrue(renderSource.doesDataPointExist(blockOffsetX + x, blockOffsetZ + z));
|
||||
}
|
||||
}
|
||||
}
|
||||
render.fillDebugFlag(renderOffsetX, renderOffsetZ, LodUtil.CHUNK_WIDTH, LodUtil.CHUNK_WIDTH, ColumnRenderSource.DebugSourceFlag.DIRECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
final int dataPerRender = 1 << (render.getDataDetail() - chunkDataView.detailLevel);
|
||||
final int dataSize = LodUtil.CHUNK_WIDTH / dataPerRender;
|
||||
final int vertSize = render.getVerticalSize();
|
||||
long[] tempRender = new long[dataPerRender * dataPerRender * vertSize];
|
||||
if (renderOffsetX < 0 || renderOffsetX + dataSize > render.getDataSize() || renderOffsetZ < 0 || renderOffsetZ + dataSize > render.getDataSize())
|
||||
{
|
||||
throw new IllegalArgumentException("Data offset is out of bounds");
|
||||
}
|
||||
renderSource.fillDebugFlag(blockOffsetX, blockOffsetZ, LodUtil.CHUNK_WIDTH, LodUtil.CHUNK_WIDTH, ColumnRenderSource.DebugSourceFlag.DIRECT);
|
||||
|
||||
for (int x = 0; x < dataSize; x++)
|
||||
{
|
||||
for (int z = 0; z < dataSize; z++)
|
||||
{
|
||||
|
||||
ColumnQuadView tempQuadView = new ColumnQuadView(tempRender, dataPerRender, vertSize, 0, 0, dataPerRender, dataPerRender);
|
||||
for (int ox = 0; ox < dataPerRender; ox++)
|
||||
{
|
||||
for (int oz = 0; oz < dataPerRender; oz++)
|
||||
{
|
||||
throwIfThreadInterrupted();
|
||||
|
||||
|
||||
ColumnArrayView columnArrayView = tempQuadView.get(ox, oz);
|
||||
SingleColumnFullDataAccessor fullArrayView = chunkDataView.get(x * dataPerRender + ox, z * dataPerRender + oz);
|
||||
convertColumnData(level, blockX + perRenderWidth * (renderOffsetX + x) + perDataWidth * ox,
|
||||
blockZ + perRenderWidth * (renderOffsetZ + z) + perDataWidth * oz,
|
||||
columnArrayView, fullArrayView, 2);
|
||||
}
|
||||
}
|
||||
ColumnArrayView downSampledArrayView = render.getVerticalDataPointView(renderOffsetX + x, renderOffsetZ + z);
|
||||
downSampledArrayView.mergeMultiDataFrom(tempQuadView);
|
||||
}
|
||||
}
|
||||
render.fillDebugFlag(renderOffsetX, renderOffsetZ, dataSize, dataSize, ColumnRenderSource.DebugSourceFlag.DIRECT);
|
||||
renderSource.markNotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-20
@@ -18,12 +18,12 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
{
|
||||
@@ -37,6 +37,8 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
|
||||
private final IDhClientLevel level;
|
||||
private final File saveDir;
|
||||
/** This is the lowest (highest numeric) detail level that this {@link RenderSourceFileHandler} is keeping track of. */
|
||||
AtomicInteger lowestDetailLevel = new AtomicInteger(6);
|
||||
private final IFullDataSourceProvider fullDataSourceProvider;
|
||||
|
||||
private final ConcurrentHashMap<DhSectionPos, Object> cacheUpdateLockBySectionPos = new ConcurrentHashMap<>();
|
||||
@@ -141,8 +143,15 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
fileToUse = metaFiles.iterator().next();
|
||||
}
|
||||
|
||||
|
||||
// Add this file to the list of files.
|
||||
this.filesBySectionPos.put(pos, fileToUse);
|
||||
|
||||
// increase the lowest detail level if a new lower detail file is found
|
||||
if (this.lowestDetailLevel.get() < pos.sectionDetailLevel)
|
||||
{
|
||||
this.lowestDetailLevel.set(pos.sectionDetailLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,14 +183,21 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
metaFile = this.filesBySectionPos.putIfAbsent(pos, newMetaFile); // This is a CAS with expected null value.
|
||||
if (metaFile == null)
|
||||
{
|
||||
metaFile = newMetaFile;
|
||||
}
|
||||
|
||||
// increase the lowest detail level if a new lower detail file was added
|
||||
if (this.lowestDetailLevel.get() < pos.sectionDetailLevel)
|
||||
{
|
||||
this.lowestDetailLevel.set(pos.sectionDetailLevel);
|
||||
}
|
||||
}
|
||||
|
||||
return metaFile.loadOrGetCached(this.renderCacheThread, this.level).handle(
|
||||
return metaFile.loadOrGetCachedDataSourceAsync(this.renderCacheThread, this.level).handle(
|
||||
(renderSource, exception) ->
|
||||
{
|
||||
if (exception != null)
|
||||
@@ -215,30 +231,43 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
@Override
|
||||
public void writeChunkDataToFile(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkDataView)
|
||||
{
|
||||
this.writeChunkDataToFileRecursively(sectionPos,chunkDataView);
|
||||
// convert to the lowest detail level so all detail levels are updated
|
||||
this.writeChunkDataToFileRecursively(sectionPos.convertToDetailLevel((byte) this.lowestDetailLevel.get()), chunkDataView);
|
||||
this.fullDataSourceProvider.write(sectionPos, chunkDataView);
|
||||
}
|
||||
private void writeChunkDataToFileRecursively(DhSectionPos sectPos, ChunkSizedFullDataAccessor chunkDataView)
|
||||
private void writeChunkDataToFileRecursively(DhSectionPos sectionPos, ChunkSizedFullDataAccessor chunkDataView)
|
||||
{
|
||||
if (!sectPos.getSectionBBoxPos().overlapsExactly(chunkDataView.getLodPos()))
|
||||
// only continue if the chunk data is in this sectionPos
|
||||
if (!sectionPos.getSectionBBoxPos().overlapsExactly(chunkDataView.getLodPos()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (sectPos.sectionDetailLevel > ColumnRenderSource.SECTION_SIZE_OFFSET)
|
||||
|
||||
if (sectionPos.sectionDetailLevel > ColumnRenderSource.SECTION_SIZE_OFFSET)
|
||||
{
|
||||
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(0), chunkDataView);
|
||||
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(1), chunkDataView);
|
||||
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(2), chunkDataView);
|
||||
this.writeChunkDataToFileRecursively(sectPos.getChildByIndex(3), chunkDataView);
|
||||
this.writeChunkDataToFileRecursively(sectionPos.getChildByIndex(0), chunkDataView);
|
||||
this.writeChunkDataToFileRecursively(sectionPos.getChildByIndex(1), chunkDataView);
|
||||
this.writeChunkDataToFileRecursively(sectionPos.getChildByIndex(2), chunkDataView);
|
||||
this.writeChunkDataToFileRecursively(sectionPos.getChildByIndex(3), chunkDataView);
|
||||
}
|
||||
|
||||
RenderMetaDataFile metaFile = this.filesBySectionPos.get(sectPos);
|
||||
// Fast path: if there is a file for this section, just write to it.
|
||||
|
||||
|
||||
RenderMetaDataFile metaFile = this.filesBySectionPos.get(sectionPos);
|
||||
if (metaFile != null)
|
||||
{
|
||||
metaFile.updateChunkIfNeeded(chunkDataView, this.level);
|
||||
metaFile.updateChunkIfSourceExists(chunkDataView, this.level);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a new file if necessary
|
||||
this.readAsync(sectionPos).whenComplete((renderSource, ex) ->
|
||||
{
|
||||
RenderMetaDataFile newMetaFile = this.filesBySectionPos.get(sectionPos);
|
||||
newMetaFile.updateChunkIfSourceExists(chunkDataView, this.level);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,15 +302,9 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
}
|
||||
|
||||
// get the full data source loading future
|
||||
final WeakReference<ColumnRenderSource> renderSourceReference = new WeakReference<>(renderSource); // TODO why is this a week reference?
|
||||
CompletableFuture<IFullDataSource> fullDataSourceFuture = this.fullDataSourceProvider.read(renderSource.getSectionPos());
|
||||
fullDataSourceFuture = fullDataSourceFuture.thenApply((fullDataSource) ->
|
||||
{
|
||||
if (renderSourceReference.get() == null)
|
||||
{
|
||||
throw new UncheckedInterruptedException();
|
||||
}
|
||||
|
||||
// the fullDataSource can be null if the thread this was running on was interrupted
|
||||
return fullDataSource;
|
||||
}).exceptionally((ex) ->
|
||||
@@ -301,7 +324,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
|
||||
{
|
||||
if (ex == null)
|
||||
{
|
||||
this.writeRenderSourceToFile(renderSourceReference.get(), file, newRenderSource);
|
||||
this.writeRenderSourceToFile(renderSource, file, newRenderSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user