Merge branch 'main' of https://gitlab.com/jeseibel/distant-horizons-core
This commit is contained in:
+8
-2
@@ -65,6 +65,7 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
|
||||
public final int dataPointsPerSection;
|
||||
public boolean isEmpty = true;
|
||||
public EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.EMPTY;
|
||||
private boolean isPromoted = false;
|
||||
|
||||
|
||||
|
||||
@@ -614,10 +615,15 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
isPromoted = true;
|
||||
CompleteFullDataSource fullDataSource = CompleteFullDataSource.createEmpty(this.sectionPos);
|
||||
this.applyToFullDataSource(fullDataSource);
|
||||
return fullDataSource;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasBeenPromoted() {
|
||||
return isPromoted;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-4
@@ -52,6 +52,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
|
||||
|
||||
private boolean isEmpty = true;
|
||||
public EDhApiWorldGenerationStep worldGenStep = EDhApiWorldGenerationStep.EMPTY;
|
||||
private boolean isPromoted = false;
|
||||
|
||||
|
||||
|
||||
@@ -514,12 +515,16 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
isPromoted = true;
|
||||
return new CompleteFullDataSource(this.sectionPos, this.mapping, this.dataArrays);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasBeenPromoted() {
|
||||
return isPromoted;
|
||||
}
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
+2
-1
@@ -17,5 +17,6 @@ public interface IIncompleteFullDataSource extends IFullDataSource
|
||||
* @return a new {@link CompleteFullDataSource} if successful, this if the promotion failed, .
|
||||
*/
|
||||
IFullDataSource tryPromotingToCompleteDataSource();
|
||||
|
||||
|
||||
boolean hasBeenPromoted();
|
||||
}
|
||||
|
||||
+11
-8
@@ -3,6 +3,7 @@ package com.seibel.lod.core.dataObjects.render.bufferBuilding;
|
||||
import com.seibel.lod.core.pos.DhBlockPos2D;
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.lod.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.lod.core.render.renderer.LodRenderer;
|
||||
import com.seibel.lod.core.render.AbstractRenderBuffer;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
@@ -27,7 +28,7 @@ import static com.seibel.lod.core.render.glObject.GLProxy.GL_LOGGER;
|
||||
*
|
||||
* @see ColumnRenderBufferBuilder
|
||||
*/
|
||||
public class ColumnRenderBuffer extends AbstractRenderBuffer
|
||||
public class ColumnRenderBuffer extends AbstractRenderBuffer implements IDebugRenderable
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
@@ -55,14 +56,16 @@ public class ColumnRenderBuffer extends AbstractRenderBuffer
|
||||
this.debugPos = debugPos;
|
||||
vbos = new GLVertexBuffer[0];
|
||||
vbosTransparent = new GLVertexBuffer[0];
|
||||
DebugRenderer.register(this, (r) -> {
|
||||
if (closed || this.vbos == null) {
|
||||
return;
|
||||
}
|
||||
DebugRenderer.register(this);
|
||||
}
|
||||
|
||||
Color c = Color.green;
|
||||
r.renderBox(debugPos, -32, 32, c);
|
||||
});
|
||||
public void debugRender(DebugRenderer r)
|
||||
{
|
||||
if (closed || vbos == null) {
|
||||
return;
|
||||
}
|
||||
Color c = Color.green;
|
||||
r.renderBox(debugPos, 128, 128, 0.05f, c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
|
||||
while (--sectionDetail >= this.minDetailLevel)
|
||||
{
|
||||
DhLodPos minPos = pos.getCorner().getCornerLodPos(sectionDetail);
|
||||
int count = pos.getSectionBBoxPos().getBlockWidth(sectionDetail);
|
||||
int count = pos.getSectionBBoxPos().getWidthAtDetail(sectionDetail);
|
||||
|
||||
for (int xOffset = 0; xOffset < count; xOffset++)
|
||||
{
|
||||
|
||||
+18
-2
@@ -1,10 +1,12 @@
|
||||
package com.seibel.lod.core.file.fullDatafile;
|
||||
|
||||
import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
|
||||
import com.seibel.lod.core.dataObjects.fullData.sources.CompleteFullDataSource;
|
||||
import com.seibel.lod.core.dataObjects.fullData.sources.HighDetailIncompleteFullDataSource;
|
||||
import com.seibel.lod.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
|
||||
import com.seibel.lod.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource;
|
||||
import com.seibel.lod.core.dataObjects.fullData.sources.LowDetailIncompleteFullDataSource;
|
||||
import com.seibel.lod.core.file.metaData.BaseMetaData;
|
||||
import com.seibel.lod.core.generation.tasks.IWorldGenTaskTracker;
|
||||
import com.seibel.lod.core.generation.WorldGenerationQueue;
|
||||
import com.seibel.lod.core.generation.tasks.WorldGenResult;
|
||||
@@ -21,6 +23,7 @@ import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
{
|
||||
@@ -173,7 +176,17 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
.thenApply((voidValue) -> incompleteFullDataSource.tryPromotingToCompleteDataSource());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* @Override
|
||||
public CompletableFuture<IFullDataSource> onDataFileRefresh(IFullDataSource source, BaseMetaData metaData, Function<IFullDataSource, Boolean> updater, Consumer<IFullDataSource> onUpdated)
|
||||
{
|
||||
return super.onDataFileRefresh(source, metaData, updater, (IFullDataSource d) -> {
|
||||
if (d instanceof CompleteFullDataSource) {
|
||||
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Checks if the given {@link IFullDataSource} is fully generated and
|
||||
* if it isn't, creates the necessary world gen request(s) to finish it. <br>
|
||||
@@ -351,7 +364,10 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isMemoryAddressValid() { return this.targetFullDataSourceRef.get() != null; }
|
||||
public boolean isMemoryAddressValid() {
|
||||
IFullDataSource ref = this.targetFullDataSourceRef.get();
|
||||
return ref != null && !((IIncompleteFullDataSource)ref).hasBeenPromoted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consumer<ChunkSizedFullDataAccessor> getOnGenTaskCompleteConsumer()
|
||||
|
||||
@@ -10,6 +10,8 @@ import com.seibel.lod.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.lod.core.file.fullDatafile.FullDataFileHandler;
|
||||
import com.seibel.lod.core.generation.tasks.*;
|
||||
import com.seibel.lod.core.pos.*;
|
||||
import com.seibel.lod.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.lod.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.lod.core.util.ThreadUtil;
|
||||
import com.seibel.lod.core.util.objects.quadTree.QuadNode;
|
||||
import com.seibel.lod.core.util.objects.quadTree.QuadTree;
|
||||
@@ -20,12 +22,13 @@ import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.Closeable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class WorldGenerationQueue implements Closeable
|
||||
public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
@@ -95,6 +98,7 @@ public class WorldGenerationQueue implements Closeable
|
||||
{
|
||||
throw new IllegalArgumentException(IDhApiWorldGenerator.class.getSimpleName() + ": max granularity smaller than min granularity!");
|
||||
}
|
||||
DebugRenderer.register(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +246,9 @@ public class WorldGenerationQueue implements Closeable
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
private final Set<WorldGenTask> CheckingTasks = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
/**
|
||||
* @param targetPos the position to center the generation around
|
||||
* @return false if no tasks were found to generate
|
||||
@@ -252,6 +258,7 @@ public class WorldGenerationQueue implements Closeable
|
||||
long closestGenDist = Long.MAX_VALUE;
|
||||
|
||||
WorldGenTask closestTask = null;
|
||||
CheckingTasks.clear();
|
||||
|
||||
// TODO improve, having to go over every node isn't super efficient, removing null nodes from the tree would help
|
||||
Iterator<QuadNode<WorldGenTask>> nodeIterator = this.waitingTaskQuadTree.nodeIterator();
|
||||
@@ -263,10 +270,11 @@ public class WorldGenerationQueue implements Closeable
|
||||
|
||||
if (newGenTask != null) // TODO add an option to skip leaves with null values and potentially auto-prune them
|
||||
{
|
||||
CheckingTasks.add(newGenTask);
|
||||
// TODO this isn't a long term fix, in the long term the tree should automatically remove out of bound nodes when moved
|
||||
if (!this.waitingTaskQuadTree.isSectionPosInBounds(taskSectionPos))
|
||||
if (!this.waitingTaskQuadTree.isSectionPosInBounds(taskSectionPos) || !newGenTask.StillValid())
|
||||
{
|
||||
// skip and remove out-of-bound tasks
|
||||
// skip and remove out-of-bound tasks or tasks that are no longer valid
|
||||
taskNode.value = null;
|
||||
continue;
|
||||
}
|
||||
@@ -289,14 +297,10 @@ public class WorldGenerationQueue implements Closeable
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// remove the task we found, we are going to start it and don't want to run it multiple times
|
||||
// TODO the setValue can fail if the user is moving and the task that was once in range is no longer in range
|
||||
WorldGenTask removedWorldGenTask = this.waitingTaskQuadTree.setValue(new DhSectionPos(closestTask.pos.detailLevel, closestTask.pos.x, closestTask.pos.z), null);
|
||||
|
||||
|
||||
|
||||
// do we need to modify this task to generate it?
|
||||
if(this.canGeneratePos((byte) 0, closestTask.pos)) // TODO should detail level 0 be replaced?
|
||||
{
|
||||
@@ -371,7 +375,6 @@ public class WorldGenerationQueue implements Closeable
|
||||
|
||||
DhChunkPos chunkPosMin = new DhChunkPos(taskPos.getCornerBlockPos());
|
||||
|
||||
|
||||
// check if this is a duplicate generation task
|
||||
if (this.alreadyGeneratedPosHashSet.contains(inProgressTaskGroup.group.pos))
|
||||
{
|
||||
@@ -578,6 +581,8 @@ public class WorldGenerationQueue implements Closeable
|
||||
|
||||
|
||||
LOGGER.info("Finished closing "+WorldGenerationQueue.class.getSimpleName());
|
||||
|
||||
DebugRenderer.unregister(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -616,6 +621,16 @@ public class WorldGenerationQueue implements Closeable
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void debugRender(DebugRenderer r) {
|
||||
CheckingTasks.forEach((t) -> {
|
||||
DhLodPos pos = t.pos;
|
||||
r.renderBox(pos, -32f, 64f, 0.05f, Color.blue);
|
||||
});
|
||||
this.inProgressGenTasksByLodPos.forEach((pos, t) -> {
|
||||
r.renderBox(pos, -30f, 64f, 0.05f, Color.red);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,8 @@ public final class WorldGenTask
|
||||
this.taskTracker = taskTracker;
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
|
||||
public boolean StillValid() {
|
||||
return taskTracker.isMemoryAddressValid();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,19 +39,22 @@ public class DhLodPos implements Comparable<DhLodPos>
|
||||
|
||||
public DhLodUnit getX() { return new DhLodUnit(this.detailLevel, this.x); }
|
||||
public DhLodUnit getZ() { return new DhLodUnit(this.detailLevel, this.z); }
|
||||
|
||||
public int getBlockWidth() { return this.getBlockWidth(this.detailLevel); }
|
||||
public int getBlockWidth(byte detailLevel) // TODO this needs some documentation or a better name describing what is happening, why is there an assert here?
|
||||
|
||||
// Get the width of this pos, measured in the mc block unit. (i.e. detail 0)
|
||||
public int getBlockWidth() { return this.getWidthAtDetail((byte)0); }
|
||||
|
||||
// Get the width of this pos, measured in the target detail level.
|
||||
public int getWidthAtDetail(byte targetLevel)
|
||||
{
|
||||
LodUtil.assertTrue(detailLevel <= this.detailLevel);
|
||||
return BitShiftUtil.powerOfTwo(this.detailLevel - detailLevel);
|
||||
LodUtil.assertTrue(targetLevel <= this.detailLevel);
|
||||
return BitShiftUtil.powerOfTwo(this.detailLevel - targetLevel);
|
||||
}
|
||||
|
||||
public DhBlockPos2D getCenterBlockPos()
|
||||
{
|
||||
return new DhBlockPos2D(
|
||||
this.getX().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth()),
|
||||
this.getZ().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth()));
|
||||
this.getZ().toBlockWidth() + BitShiftUtil.half(this.getBlockWidth()));
|
||||
}
|
||||
public DhBlockPos2D getCornerBlockPos() { return new DhBlockPos2D(this.getX().toBlockWidth(), this.getZ().toBlockWidth()); }
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* This quadTree structure is our core data structure and holds
|
||||
@@ -32,9 +33,9 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
|
||||
|
||||
/**
|
||||
* This holds every {@link DhSectionPos} that should be reloaded next tick. <br>
|
||||
* This is a {@link ConcurrentHashMap} because new sections can be added to this list via the world generator threads.
|
||||
* This is a {@link ConcurrentLinkedQueue} because new sections can be added to this list via the world generator threads.
|
||||
*/
|
||||
private final ConcurrentHashMap<DhSectionPos, Boolean> sectionsToReload = new ConcurrentHashMap<>();
|
||||
private final ConcurrentLinkedQueue<DhSectionPos> sectionsToReload = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private final IDhClientLevel level; //FIXME: Proper hierarchy to remove this reference!
|
||||
|
||||
@@ -80,7 +81,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
|
||||
try
|
||||
{
|
||||
// recenter if necessary, removing out of bounds sections
|
||||
this.setCenterBlockPos(playerPos, LodRenderSection::disposeRenderData);
|
||||
this.setCenterBlockPos(playerPos, LodRenderSection::dispose);
|
||||
|
||||
updateAllRenderSections(playerPos);
|
||||
}
|
||||
@@ -92,12 +93,11 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
|
||||
private void updateAllRenderSections(DhBlockPos2D playerPos)
|
||||
{
|
||||
// reload any sections that need it
|
||||
DhSectionPos[] reloadSectionArray = this.sectionsToReload.keySet().toArray(new DhSectionPos[0]);
|
||||
this.sectionsToReload.clear();
|
||||
for (DhSectionPos pos : reloadSectionArray)
|
||||
DhSectionPos pos;
|
||||
while ((pos = this.sectionsToReload.poll()) != null)
|
||||
{
|
||||
// walk up the tree until we hit the root node
|
||||
// this is done so any high detail changes flow up to the lower detail render sections as well
|
||||
// this is done so any high detail changes flow up to the lower detail render sections as well
|
||||
while (pos.sectionDetailLevel <= this.treeMaxDetailLevel)
|
||||
{
|
||||
try
|
||||
@@ -110,12 +110,11 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
|
||||
}
|
||||
catch (IndexOutOfBoundsException e)
|
||||
{ /* the section is now out of bounds, it doesn't need to be reloaded */ }
|
||||
|
||||
|
||||
pos = pos.getParentPos();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// walk through each root node
|
||||
Iterator<DhSectionPos> rootPosIterator = this.rootNodePosIterator();
|
||||
while (rootPosIterator.hasNext())
|
||||
@@ -352,7 +351,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
|
||||
}
|
||||
|
||||
//LOGGER.info("LodQuadTree reloadPos ["+pos+"].");
|
||||
this.sectionsToReload.put(pos, true);
|
||||
this.sectionsToReload.add(pos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,12 @@ import com.seibel.lod.core.level.IDhClientLevel;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.file.renderfile.ILodRenderSourceProvider;
|
||||
import com.seibel.lod.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.lod.core.render.renderer.IDebugRenderable;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -15,7 +19,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
* A render section represents an area that could be rendered.
|
||||
* For more information see {@link LodQuadTree}.
|
||||
*/
|
||||
public class LodRenderSection
|
||||
public class LodRenderSection implements IDebugRenderable
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
@@ -38,7 +42,30 @@ public class LodRenderSection
|
||||
|
||||
|
||||
|
||||
public LodRenderSection(DhSectionPos pos) { this.pos = pos; }
|
||||
public LodRenderSection(DhSectionPos pos) {
|
||||
this.pos = pos;
|
||||
|
||||
DebugRenderer.register(this);
|
||||
}
|
||||
|
||||
public void debugRender(DebugRenderer r)
|
||||
{
|
||||
Color color = Color.red;
|
||||
|
||||
if (this.renderSourceProvider == null) color = Color.black;
|
||||
|
||||
if (this.renderSourceLoadFuture != null) color = Color.yellow;
|
||||
|
||||
if (renderSource != null) {
|
||||
color = Color.blue;
|
||||
if (isRenderingEnabled) color = Color.cyan;
|
||||
if (isRenderingEnabled && isRenderDataLoaded()) color = Color.green;
|
||||
}
|
||||
|
||||
float yOffset = Objects.hashCode(this) / (float) Integer.MAX_VALUE * 16f;
|
||||
|
||||
r.renderBox(this.pos, yOffset, yOffset, 0.1f, color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -160,6 +187,8 @@ public class LodRenderSection
|
||||
this.renderSourceLoadFuture.cancel(true);
|
||||
this.renderSourceLoadFuture = null;
|
||||
}
|
||||
|
||||
this.renderSourceProvider = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -208,5 +237,9 @@ public class LodRenderSection
|
||||
", isRenderEnabled=" + this.isRenderingEnabled +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
public void dispose() {
|
||||
DebugRenderer.unregister(this);
|
||||
disposeRenderData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import com.seibel.lod.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.lod.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
|
||||
import com.seibel.lod.core.pos.DhBlockPos2D;
|
||||
import com.seibel.lod.core.pos.DhLodPos;
|
||||
import com.seibel.lod.core.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.render.glObject.GLProxy;
|
||||
import com.seibel.lod.core.render.glObject.GLState;
|
||||
import com.seibel.lod.core.render.glObject.buffer.GLElementBuffer;
|
||||
import com.seibel.lod.core.render.glObject.buffer.GLVertexBuffer;
|
||||
@@ -22,11 +22,10 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.*;
|
||||
|
||||
public class DebugRenderer {
|
||||
public static DebugRenderer INSTANCE = new DebugRenderer();
|
||||
@@ -74,12 +73,34 @@ public class DebugRenderer {
|
||||
VertexAttribute va;
|
||||
boolean init = false;
|
||||
|
||||
public static void unregister(IDebugRenderable r) {
|
||||
if (INSTANCE == null) return;
|
||||
INSTANCE.removeRenderer(r);
|
||||
}
|
||||
|
||||
private void removeRenderer(IDebugRenderable r) {
|
||||
synchronized (renderers) {
|
||||
Iterator<WeakReference<IDebugRenderable>> it = renderers.iterator();
|
||||
while (it.hasNext()) {
|
||||
WeakReference<IDebugRenderable> ref = it.next();
|
||||
if (ref.get() == null) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
if (ref.get() == r) {
|
||||
it.remove();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (init) return;
|
||||
init = true;
|
||||
va = VertexAttribute.create();
|
||||
va.bind();
|
||||
// Pos
|
||||
// Pos\
|
||||
va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec3Pointer(false));
|
||||
va.completeAndCheck(Float.BYTES * 3);
|
||||
basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag",
|
||||
@@ -105,30 +126,40 @@ public class DebugRenderer {
|
||||
boxOutlineBuffer.uploadBuffer(buffer, EGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IDebugRender {
|
||||
void render(DebugRenderer r);
|
||||
}
|
||||
private final LinkedList<WeakReference<IDebugRenderable>> renderers = new LinkedList<>();
|
||||
|
||||
private final Map<Object, IDebugRender> renderers = Collections.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
public void addRenderer(Object o, IDebugRender r) {
|
||||
public void addRenderer(IDebugRenderable r) {
|
||||
if (!Config.Client.Advanced.Debugging.debugWireframeRendering.get()) return;
|
||||
renderers.put(o, r);
|
||||
synchronized (renderers) {
|
||||
renderers.add(new WeakReference<>(r));
|
||||
}
|
||||
}
|
||||
|
||||
public static void register(Object o, IDebugRender r) {
|
||||
public static void register(IDebugRenderable r) {
|
||||
if (INSTANCE == null) return;
|
||||
INSTANCE.addRenderer(o, r);
|
||||
INSTANCE.addRenderer(r);
|
||||
}
|
||||
|
||||
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) {
|
||||
DhBlockPos2D blockMin = sectPos.getCorner().getCornerBlockPos();
|
||||
DhBlockPos2D blockMax = blockMin.add(sectPos.getWidth().toBlockWidth(), sectPos.getWidth().toBlockWidth());
|
||||
renderBox(blockMin.x, minY, blockMin.z, blockMax.x, maxY, blockMax.z, 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) {
|
||||
@@ -165,9 +196,22 @@ public class DebugRenderer {
|
||||
basicShader.bind();
|
||||
va.bind();
|
||||
va.bindBufferToAllBindingPoint(boxBuffer.getId());
|
||||
|
||||
boxOutlineBuffer.bind();
|
||||
|
||||
renderers.forEach((o, r) -> r.render(this));
|
||||
synchronized (renderers)
|
||||
{
|
||||
Iterator<WeakReference<IDebugRenderable>> it = renderers.iterator();
|
||||
while (it.hasNext()) {
|
||||
WeakReference<IDebugRenderable> ref = it.next();
|
||||
IDebugRenderable r = ref.get();
|
||||
if (r == null) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
r.debugRender(this);
|
||||
}
|
||||
}
|
||||
|
||||
state.restore();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.seibel.lod.core.render.renderer;
|
||||
|
||||
public interface IDebugRenderable {
|
||||
void debugRender(DebugRenderer r);
|
||||
}
|
||||
Reference in New Issue
Block a user