Fix the issues. (Tho now render buffer would need constant refresh. Todo: Add buffer dirty flag.)
This commit is contained in:
+25
-6
@@ -40,7 +40,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
|
||||
//TODO: Atm can't find a better way to store when genQueue is checked.
|
||||
public boolean genQueueChecked = false;
|
||||
|
||||
private boolean markedNeedUpdate = false;
|
||||
private volatile boolean markedNeedUpdate = false;
|
||||
|
||||
public AbstractFullDataSourceLoader fullDataSourceLoader;
|
||||
public Class<? extends IFullDataSource> dataType;
|
||||
@@ -57,6 +57,9 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
|
||||
@Override
|
||||
public void debugRender(DebugRenderer r) {
|
||||
IFullDataSource cached = cachedFullDataSource.get();
|
||||
if (markedNeedUpdate)
|
||||
r.renderBox(new DebugRenderer.Box(pos, 0, 512, 0.05f, Color.red));
|
||||
|
||||
Color c = Color.black;
|
||||
if (cached != null) {
|
||||
if (cached instanceof CompleteFullDataSource) {
|
||||
@@ -69,7 +72,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
|
||||
} else if (doesFileExist) {
|
||||
c = Color.RED;
|
||||
}
|
||||
//r.renderBox(pos, 50, 200, 0.05f, c);
|
||||
//r.renderBox(new DebugRenderer.Box(pos, 0, 256, 0.05f, c));
|
||||
}
|
||||
|
||||
//TODO: use ConcurrentAppendSingleSwapContainer<LodDataSource> instead of below:
|
||||
@@ -168,9 +171,11 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
|
||||
|
||||
private void makeUpdateCompletionStage(CompletableFuture<IFullDataSource> completer, CompletableFuture<IFullDataSource> currentStage)
|
||||
{
|
||||
markedNeedUpdate = false;
|
||||
currentStage.thenCompose(
|
||||
(fullDataSource) -> this.fullDataSourceProvider.onDataFileUpdate(fullDataSource, this, this::_updateAndWriteDataSource, this::_applyWriteQueueToFullDataSource))
|
||||
(fullDataSource) -> {
|
||||
markedNeedUpdate = false;
|
||||
return this.fullDataSourceProvider.onDataFileUpdate(fullDataSource, this, this::_updateAndWriteDataSource, this::_applyWriteQueueToFullDataSource);
|
||||
})
|
||||
.whenComplete((fullDataSource, ex) ->
|
||||
{
|
||||
if (ex instanceof CompletionException) {
|
||||
@@ -186,11 +191,25 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
|
||||
if (fullDataSource != null) {
|
||||
new DataObjTracker(fullDataSource);
|
||||
}
|
||||
LOGGER.info("Updated file "+this.file);
|
||||
//LOGGER.info("Updated file "+this.file);
|
||||
if (pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(this.pos, 0, 256f, 0.05f, Color.green),
|
||||
0.5, 512f
|
||||
)
|
||||
);
|
||||
|
||||
this.cachedFullDataSource = new SoftReference<>(fullDataSource);
|
||||
inCrit = false;
|
||||
dataSourceLoadFutureRef.set(null);
|
||||
completer.complete(fullDataSource);
|
||||
|
||||
if (this.markedNeedUpdate)
|
||||
{
|
||||
// trigger another update
|
||||
this.loadOrGetCachedDataSourceAsync();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -413,7 +432,7 @@ public class FullDataMetaFile extends AbstractMetaDataContainerFile implements I
|
||||
public CompletableFuture<Void> flushAndSaveAsync()
|
||||
{
|
||||
debugPhantomLifeCycleCheck();
|
||||
boolean isEmpty = this.writeQueueRef.get().queue.isEmpty();
|
||||
boolean isEmpty = this.writeQueueRef.get().queue.isEmpty() && !markedNeedUpdate;
|
||||
if (!isEmpty)
|
||||
{
|
||||
// This will flush the data to disk.
|
||||
|
||||
+11
-7
@@ -1,12 +1,14 @@
|
||||
package com.seibel.distanthorizons.core.file.fullDatafile;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource;
|
||||
import com.seibel.distanthorizons.core.file.metaData.BaseMetaData;
|
||||
import com.seibel.distanthorizons.core.generation.WorldGenerationQueue;
|
||||
import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker;
|
||||
import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult;
|
||||
import com.seibel.distanthorizons.core.level.DhLevel;
|
||||
import com.seibel.distanthorizons.core.level.IDhServerLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
@@ -69,15 +71,15 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
{
|
||||
boolean oldQueueExists = this.worldGenQueueRef.compareAndSet(null, newWorldGenQueue);
|
||||
LodUtil.assertTrue(oldQueueExists, "previous world gen queue is still here!");
|
||||
|
||||
LOGGER.info("Set world gen queue for level {} to start.", this.level);
|
||||
for (FullDataMetaFile metaFile : this.fileBySectionPos.values())
|
||||
{
|
||||
metaFile.genQueueChecked = false; // unset it so it can be checked again
|
||||
IFullDataSource data = metaFile.getCachedDataSourceNowOrNull();
|
||||
if (data instanceof IIncompleteFullDataSource) {
|
||||
// need manual marking for update.
|
||||
metaFile.markNeedUpdate();
|
||||
if (data instanceof CompleteFullDataSource) {
|
||||
continue;
|
||||
}
|
||||
metaFile.genQueueChecked = false; // unset it so it can be checked again
|
||||
metaFile.markNeedUpdate();
|
||||
}
|
||||
flushAndSave(); // Trigger an update to the meta files
|
||||
}
|
||||
@@ -113,7 +115,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
if (targetDataDetailLevel > maxSectDataDetailLevel) {
|
||||
ArrayList<FullDataMetaFile> existingFiles = new ArrayList<>();
|
||||
byte sectDetailLevel = (byte) (DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL + maxSectDataDetailLevel);
|
||||
pos.forEachChildAtLevel(sectDetailLevel, this::getOrMakeFile);
|
||||
pos.forEachChildAtLevel(sectDetailLevel, p -> existingFiles.add(getOrMakeFile(p)));
|
||||
return sampleFromFiles(dataSource, existingFiles).thenApply(IIncompleteFullDataSource::tryPromotingToCompleteDataSource)
|
||||
.exceptionally((e) ->
|
||||
{
|
||||
@@ -249,6 +251,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
|
||||
private void fireOnGenPosSuccessListeners(DhSectionPos pos)
|
||||
{
|
||||
if (true) return;
|
||||
//LOGGER.info("gen task completed for pos: ["+pos+"].");
|
||||
|
||||
/* // save the full data source
|
||||
@@ -328,7 +331,8 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
{
|
||||
if (chunkSizedFullDataSource.getLodPos().overlapsExactly(this.loadedTargetFullDataSource.getSectionPos().getSectionBBoxPos()))
|
||||
{
|
||||
GeneratedFullDataFileHandler.this.write(this.loadedTargetFullDataSource.getSectionPos(), chunkSizedFullDataSource);
|
||||
((DhLevel)level).saveWrites(chunkSizedFullDataSource);
|
||||
//GeneratedFullDataFileHandler.this.write(this.loadedTargetFullDataSource.getSectionPos(), chunkSizedFullDataSource);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+9
@@ -5,6 +5,7 @@ import com.seibel.distanthorizons.core.file.metaData.AbstractMetaDataContainerFi
|
||||
import com.seibel.distanthorizons.core.file.metaData.BaseMetaData;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderLoader;
|
||||
@@ -14,6 +15,7 @@ import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -87,6 +89,13 @@ public class RenderMetaDataFile extends AbstractMetaDataContainerFile
|
||||
CompletableFuture<ColumnRenderSource> readSourceFuture = this.getCachedDataSourceAsync();
|
||||
if (readSourceFuture != null)
|
||||
{
|
||||
if (chunkDataView.getLodPos().detailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(chunkDataView.getLodPos(), 0, 256f, 0.05f, Color.blue),
|
||||
0.5, 512f
|
||||
)
|
||||
);
|
||||
readSourceFuture.thenAccept((renderSource) -> renderSource.fastWrite(chunkDataView, level));
|
||||
}
|
||||
|
||||
|
||||
+6
-10
@@ -84,6 +84,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
|
||||
public WorldGenerationQueue(IDhApiWorldGenerator generator)
|
||||
{
|
||||
LOGGER.info("Creating world gen queue");
|
||||
this.generator = generator;
|
||||
this.maxGranularity = generator.getMaxGenerationGranularity();
|
||||
this.minGranularity = generator.getMinGenerationGranularity();
|
||||
@@ -104,6 +105,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
throw new IllegalArgumentException(IDhApiWorldGenerator.class.getSimpleName() + ": max granularity smaller than min granularity!");
|
||||
}
|
||||
DebugRenderer.register(this);
|
||||
LOGGER.info("Created world gen queue");
|
||||
}
|
||||
|
||||
|
||||
@@ -156,13 +158,9 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
|
||||
public void runCurrentGenTasksUntilBusy(DhBlockPos2D targetPos)
|
||||
{
|
||||
generator.preGeneratorTaskStart();
|
||||
try
|
||||
{
|
||||
if (this.generator == null)
|
||||
{
|
||||
throw new IllegalStateException("generator is null");
|
||||
}
|
||||
|
||||
// the generator is shutting down, don't attempt to generate anything
|
||||
if (this.generatorClosingFuture != null)
|
||||
{
|
||||
@@ -496,6 +494,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
|
||||
public CompletableFuture<Void> startClosing(boolean cancelCurrentGeneration, boolean alsoInterruptRunning)
|
||||
{
|
||||
LOGGER.info("Closing world gen queue");
|
||||
this.queueingThread.shutdownNow();
|
||||
|
||||
|
||||
@@ -578,10 +577,7 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
{
|
||||
LOGGER.warn("Failed to close generation queue: ", e);
|
||||
}
|
||||
|
||||
|
||||
LOGGER.info("Finished closing "+WorldGenerationQueue.class.getSimpleName());
|
||||
|
||||
DebugRenderer.unregister(this);
|
||||
}
|
||||
|
||||
@@ -627,10 +623,10 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
public void debugRender(DebugRenderer r) {
|
||||
CheckingTasks.forEach((t) -> {
|
||||
DhLodPos pos = t.pos;
|
||||
r.renderBox(pos, -32f, 128f, 0.05f, Color.blue);
|
||||
r.renderBox(new DebugRenderer.Box(pos, -32f, 128f, 0.05f, Color.blue));
|
||||
});
|
||||
this.inProgressGenTasksByLodPos.forEach((pos, t) -> {
|
||||
r.renderBox(pos, -30f, 128f, 0.05f, Color.red);
|
||||
r.renderBox(new DebugRenderer.Box(pos, -32f, 128f, 0.05f, Color.red));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class DhClientLevel extends DhLevel implements IDhClientLevel
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveWrites(ChunkSizedFullDataAccessor data) {
|
||||
public void saveWrites(ChunkSizedFullDataAccessor data) {
|
||||
clientside.saveWrites(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.seibel.distanthorizons.core.level;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
@@ -18,6 +19,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapp
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/** The level used on a singleplayer world */
|
||||
@@ -143,7 +145,7 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveWrites(ChunkSizedFullDataAccessor data) {
|
||||
public void saveWrites(ChunkSizedFullDataAccessor data) {
|
||||
clientside.saveWrites(data);
|
||||
}
|
||||
|
||||
@@ -171,6 +173,13 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS
|
||||
@Override
|
||||
public void onWorldGenTaskComplete(DhSectionPos pos)
|
||||
{
|
||||
if (pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(pos, 0, 256f, 0.05f, Color.red),
|
||||
0.5, 512f
|
||||
)
|
||||
);
|
||||
clientside.reloadPos(pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ public abstract class DhLevel implements IDhLevel {
|
||||
this.chunkToLodBuilder = new ChunkToLodBuilder();
|
||||
}
|
||||
|
||||
protected abstract void saveWrites(ChunkSizedFullDataAccessor data);
|
||||
public abstract void saveWrites(ChunkSizedFullDataAccessor data);
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,7 +35,7 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveWrites(ChunkSizedFullDataAccessor data) {
|
||||
public void saveWrites(ChunkSizedFullDataAccessor data) {
|
||||
DhLodPos pos = data.getLodPos().convertToDetailLevel(CompleteFullDataSource.SECTION_SIZE_OFFSET);
|
||||
getFileHandler().write(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
public class ServerLevelModule {
|
||||
private static class WorldGenState
|
||||
{
|
||||
public final IDhApiWorldGenerator chunkGenerator;
|
||||
public final WorldGenerationQueue worldGenerationQueue;
|
||||
WorldGenState(IDhServerLevel level)
|
||||
{
|
||||
@@ -33,9 +32,7 @@ public class ServerLevelModule {
|
||||
// since core world generator's should have the lowest override priority
|
||||
WorldGeneratorInjector.INSTANCE.bind(level.getLevelWrapper(), worldGenerator);
|
||||
}
|
||||
this.chunkGenerator = worldGenerator;
|
||||
|
||||
this.worldGenerationQueue = new WorldGenerationQueue(this.chunkGenerator);
|
||||
this.worldGenerationQueue = new WorldGenerationQueue(worldGenerator);
|
||||
}
|
||||
|
||||
CompletableFuture<Void> closeAsync(boolean doInterrupt)
|
||||
@@ -46,13 +43,17 @@ public class ServerLevelModule {
|
||||
LOGGER.error("Error closing generation queue", ex);
|
||||
return null;
|
||||
}
|
||||
).thenRun(this.chunkGenerator::close)
|
||||
).thenRun(this.worldGenerationQueue::close)
|
||||
.exceptionally(ex ->
|
||||
{
|
||||
LOGGER.error("Error closing world gen", ex);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public void tick(DhBlockPos2D targetPosForGeneration) {
|
||||
worldGenerationQueue.runCurrentGenTasksUntilBusy(targetPosForGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
@@ -87,8 +88,8 @@ public class ServerLevelModule {
|
||||
LOGGER.warn("Failed to start world gen due to concurrency");
|
||||
newWgs.closeAsync(false);
|
||||
}
|
||||
dataFileHandler.setGenerationQueue(newWgs.worldGenerationQueue);
|
||||
dataFileHandler.addWorldGenCompleteListener(parent);
|
||||
dataFileHandler.setGenerationQueue(newWgs.worldGenerationQueue);
|
||||
}
|
||||
|
||||
public void stopWorldGen()
|
||||
@@ -125,8 +126,7 @@ public class ServerLevelModule {
|
||||
if (worldGenState != null)
|
||||
{
|
||||
// queue new world generation requests
|
||||
worldGenState.chunkGenerator.preGeneratorTaskStart();//new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()
|
||||
worldGenState.worldGenerationQueue.runCurrentGenTasksUntilBusy(targetPosForGeneration);
|
||||
worldGenState.tick(targetPosForGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,9 +81,7 @@ public class LodRenderSection implements IDebugRenderable
|
||||
if (canRenderNow() && isRenderingEnabled) color = Color.green;
|
||||
}
|
||||
|
||||
float yOffset = Objects.hashCode(this) / (float) Integer.MAX_VALUE * 16f + 16f;
|
||||
|
||||
r.renderBox(this.pos, yOffset, yOffset, 0.1f, color);
|
||||
r.renderBox(new DebugRenderer.Box(this.pos, 400, 8f, Objects.hashCode(this), 0.1f, color));
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +107,7 @@ public class LodRenderSection implements IDebugRenderable
|
||||
{
|
||||
this.renderSourceLoadFuture = null;
|
||||
this.renderSource = renderSource;
|
||||
this.lastNs = -1;
|
||||
if (this.reloadRenderSourceOnceLoaded)
|
||||
{
|
||||
this.reloadRenderSourceOnceLoaded = false;
|
||||
@@ -136,6 +135,13 @@ public class LodRenderSection implements IDebugRenderable
|
||||
|
||||
public void reload(ILodRenderSourceProvider renderDataProvider)
|
||||
{
|
||||
if (pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(pos, 0, 256f, 0.05f, Color.cyan),
|
||||
0.5, 512f
|
||||
)
|
||||
);
|
||||
this.renderSourceProvider = renderDataProvider;
|
||||
if (this.renderSourceProvider == null)
|
||||
{
|
||||
@@ -201,14 +207,14 @@ public class LodRenderSection implements IDebugRenderable
|
||||
|
||||
private boolean isInBuildBufferTimeout() {
|
||||
if (this.lastNs == -1) return false;
|
||||
return true;
|
||||
//return true;
|
||||
|
||||
//boolean inTimeout = System.nanoTime() - this.lastNs < SWAP_TIMEOUT_IN_NS;
|
||||
//if (!inTimeout && ColumnRenderBufferBuilder.isBusy()) {
|
||||
// this.lastNs += (long) (SWAP_BUSY_COLLISION_TIMEOUT_IN_NS * Math.random());
|
||||
// inTimeout = true;
|
||||
//}
|
||||
//return inTimeout;
|
||||
boolean inTimeout = System.nanoTime() - this.lastNs < SWAP_TIMEOUT_IN_NS;
|
||||
if (!inTimeout && ColumnRenderBufferBuilder.isBusy()) {
|
||||
this.lastNs += (long) (SWAP_BUSY_COLLISION_TIMEOUT_IN_NS * Math.random());
|
||||
inTimeout = true;
|
||||
}
|
||||
return inTimeout;
|
||||
}
|
||||
|
||||
/** @return true if this section is loaded and set to render */
|
||||
@@ -228,6 +234,13 @@ public class LodRenderSection implements IDebugRenderable
|
||||
{
|
||||
boolean didSwapped = false;
|
||||
if (canBuildBuffer()) {
|
||||
if (pos.sectionDetailLevel == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
|
||||
DebugRenderer.makeParticle(
|
||||
new DebugRenderer.BoxParticle(
|
||||
new DebugRenderer.Box(pos, 0, 256f, 0.1f, Color.yellow),
|
||||
0.8, 512f
|
||||
)
|
||||
);
|
||||
ColumnRenderSource[] adjacentSources = new ColumnRenderSource[ELodDirection.ADJ_DIRECTIONS.length];
|
||||
for (ELodDirection direction : ELodDirection.ADJ_DIRECTIONS) {
|
||||
try {
|
||||
|
||||
+114
-27
@@ -19,6 +19,8 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -26,6 +28,7 @@ import java.lang.ref.WeakReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
|
||||
public class DebugRenderer {
|
||||
public static DebugRenderer INSTANCE = new DebugRenderer();
|
||||
@@ -67,17 +70,117 @@ public class DebugRenderer {
|
||||
3, 7,
|
||||
};
|
||||
|
||||
public static final class Box {
|
||||
public final Vec3f a;
|
||||
public final Vec3f b;
|
||||
public final Color color;
|
||||
|
||||
public Box(Vec3f a, Vec3f b, Color color) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Box(Vec3f a, Vec3f b, Color color, Vec3f margin) {
|
||||
this.a = a;
|
||||
this.a.add(margin);
|
||||
this.b = b;
|
||||
this.b.subtract(margin);
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Box(DhLodPos pos, float minY, float maxY, float marginPercent, Color color) {
|
||||
DhBlockPos2D blockMin = pos.getCornerBlockPos();
|
||||
DhBlockPos2D blockMax = blockMin.add(pos.getBlockWidth(), pos.getBlockWidth());
|
||||
float edge = pos.getBlockWidth() * marginPercent;
|
||||
Vec3f a = new Vec3f(blockMin.x + edge, minY, blockMin.z + edge);
|
||||
Vec3f b = new Vec3f(blockMax.x - edge, maxY, blockMax.z - edge);
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Box(DhLodPos pos, float y, float yDiff, Object hash, float marginPercent, Color color) {
|
||||
float hashY = ((float)hash.hashCode() / Integer.MAX_VALUE) * yDiff;
|
||||
DhBlockPos2D blockMin = pos.getCornerBlockPos();
|
||||
DhBlockPos2D blockMax = blockMin.add(pos.getBlockWidth(), pos.getBlockWidth());
|
||||
float edge = pos.getBlockWidth() * marginPercent;
|
||||
Vec3f a = new Vec3f(blockMin.x + edge, hashY, blockMin.z + edge);
|
||||
Vec3f b = new Vec3f(blockMax.x - edge, hashY, blockMax.z - edge);
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Box(DhSectionPos pos, float minY, float maxY, float marginPercent, Color color) {
|
||||
this(pos.getSectionBBoxPos(), minY, maxY, marginPercent, color);
|
||||
}
|
||||
|
||||
public Box(DhSectionPos pos, float y, float yDiff, Object hash, float marginPercent, Color color) {
|
||||
this(pos.getSectionBBoxPos(), y, yDiff, hash, marginPercent, color);
|
||||
}
|
||||
}
|
||||
|
||||
ShaderProgram basicShader;
|
||||
GLVertexBuffer boxBuffer;
|
||||
GLElementBuffer boxOutlineBuffer;
|
||||
VertexAttribute va;
|
||||
boolean init = false;
|
||||
|
||||
private final LinkedList<WeakReference<IDebugRenderable>> renderers = new LinkedList<>();
|
||||
|
||||
public static final class BoxParticle implements Comparable<BoxParticle> {
|
||||
private final Box box;
|
||||
private final long startTime;
|
||||
private final long duration;
|
||||
private final float yChange;
|
||||
|
||||
public BoxParticle(Box box, long startTime, long duration, float yChange) {
|
||||
this.box = box;
|
||||
this.startTime = startTime;
|
||||
this.duration = duration;
|
||||
this.yChange = yChange;
|
||||
}
|
||||
|
||||
public BoxParticle(Box box, long ns, float yChange) {
|
||||
this(box, System.nanoTime(), ns, yChange);
|
||||
}
|
||||
|
||||
public BoxParticle(Box box, double s, float yChange) {
|
||||
this(box, System.nanoTime(), (long)(s * 1000000000), yChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull DebugRenderer.BoxParticle o) {
|
||||
return Long.compare(startTime, o.startTime);
|
||||
}
|
||||
|
||||
Box getBox() {
|
||||
long now = System.nanoTime();
|
||||
float percent = (now - startTime) / (float)duration;
|
||||
percent = (float)Math.pow(percent, 4);
|
||||
float yDiff = yChange * percent;
|
||||
return new Box(new Vec3f(box.a.x, box.a.y + yDiff, box.a.z), new Vec3f(box.b.x, box.b.y + yDiff, box.b.z), box.color);
|
||||
}
|
||||
|
||||
boolean isDead(long time) {
|
||||
return time - startTime > duration;
|
||||
}
|
||||
}
|
||||
|
||||
private final PriorityBlockingQueue<BoxParticle> particles = new PriorityBlockingQueue<>();
|
||||
|
||||
public static void unregister(IDebugRenderable r) {
|
||||
if (INSTANCE == null) return;
|
||||
INSTANCE.removeRenderer(r);
|
||||
}
|
||||
|
||||
public static void makeParticle(BoxParticle particle) {
|
||||
if (INSTANCE == null) return;
|
||||
if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return;
|
||||
INSTANCE.particles.add(particle);
|
||||
}
|
||||
|
||||
private void removeRenderer(IDebugRenderable r) {
|
||||
synchronized (renderers) {
|
||||
Iterator<WeakReference<IDebugRenderable>> it = renderers.iterator();
|
||||
@@ -126,8 +229,6 @@ public class DebugRenderer {
|
||||
boxOutlineBuffer.uploadBuffer(buffer, EGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
private final LinkedList<WeakReference<IDebugRenderable>> renderers = new LinkedList<>();
|
||||
|
||||
public void addRenderer(IDebugRenderable r) {
|
||||
if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return;
|
||||
synchronized (renderers) {
|
||||
@@ -143,34 +244,13 @@ public class DebugRenderer {
|
||||
private Mat4f transform_this_frame;
|
||||
private Vec3f camf;
|
||||
|
||||
public void renderBox(DhLodPos pos, float minY, float maxY, float marginPercent, Color color) {
|
||||
DhBlockPos2D blockMin = pos.getCornerBlockPos();
|
||||
DhBlockPos2D blockMax = blockMin.add(pos.getBlockWidth(), pos.getBlockWidth());
|
||||
float edge = pos.getBlockWidth() * marginPercent;
|
||||
renderBox(blockMin.x + edge, minY, blockMin.z + edge, blockMax.x - edge, maxY, blockMax.z - edge, color);
|
||||
}
|
||||
|
||||
public void renderBox(DhLodPos pos, float minY, float maxY, Color color) {
|
||||
renderBox(pos, minY, maxY, 0, color);
|
||||
}
|
||||
|
||||
public void renderBox(DhSectionPos sectPos, float minY, float maxY, Color color) {
|
||||
renderBox(sectPos.getSectionBBoxPos(), minY, maxY, 0, color);
|
||||
}
|
||||
|
||||
public void renderBox(DhSectionPos sectPos, float minY, float maxY, float marginPercent, Color color) {
|
||||
renderBox(sectPos.getSectionBBoxPos(), minY, maxY, marginPercent, color);
|
||||
}
|
||||
|
||||
public void renderBox(float x, float y, float z, float x2, float y2, float z2, Color color) {
|
||||
Vec3f boxPos = new Vec3f(x - camf.x, y - camf.y, z - camf.z);
|
||||
Mat4f boxTransform = Mat4f.createTranslateMatrix(boxPos.x, boxPos.y, boxPos.z);
|
||||
boxTransform.multiply(Mat4f.createScaleMatrix(x2-x, y2-y, z2-z));
|
||||
public void renderBox(Box box) {
|
||||
Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - camf.x, box.a.y - camf.y, box.a.z - camf.z);
|
||||
boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z));
|
||||
Mat4f t = transform_this_frame.copy();
|
||||
t.multiply(boxTransform);
|
||||
|
||||
basicShader.setUniform(basicShader.getUniformLocation("transform"), t);
|
||||
basicShader.setUniform(basicShader.getUniformLocation("uColor"), color);
|
||||
basicShader.setUniform(basicShader.getUniformLocation("uColor"), box.color);
|
||||
GL32.glDrawElements(GL32.GL_LINES, box_outline_indices.length, GL32.GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
@@ -213,6 +293,13 @@ public class DebugRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
BoxParticle head = null;
|
||||
while ((head = particles.poll()) != null && head.isDead(System.nanoTime())) {}
|
||||
if (head != null) {
|
||||
particles.add(head);
|
||||
}
|
||||
particles.forEach(b -> renderBox(b.getBox()));
|
||||
|
||||
state.restore();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user