From 58d26dedd69292f6aef580d5f11632126fedf243 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 26 Jun 2024 12:58:18 -0500 Subject: [PATCH 001/104] Show overloaded message in chat and increase message timeout 5 -> 30 sec --- .../distanthorizons/core/api/internal/SharedApi.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index 51d0b529f..000685011 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -56,7 +56,7 @@ public class SharedApi private static final Set UPDATING_CHUNK_POS_SET = ConcurrentHashMap.newKeySet(); /** how many chunks can be queued for updating per thread, used to prevent updates from infinitely pilling up if the user flys around extremely fast */ private static final int MAX_UPDATING_CHUNK_COUNT_PER_THREAD = 500; - private static final int MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE = 5_000; + private static final int MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE = 30_000; private static final Timer CHUNK_UPDATE_TIMER = TimerUtil.CreateTimer("ChunkUpdateTimer"); @@ -210,7 +210,13 @@ public class SharedApi if (msBetweenLastLog >= MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE) { lastOverloadedLogMessageMsTime = System.currentTimeMillis(); - LOGGER.warn("Too many chunks queued for updating, max queue count ["+maxQueueCount+"] (["+MAX_UPDATING_CHUNK_COUNT_PER_THREAD+"] per thread). This may result in holes in your LODs. Please move through the world slower, decrease your vanilla render distance, slow down your world pre-generator, or increase the CPU load config."); + + String message = "Distant Horizons overloaded, too many chunks queued for updating. " + + "\nThis may result in holes in your LODs. " + + "\nPlease move through the world slower, decrease your vanilla render distance, slow down your world pre-generator, or increase the Distant Horizons' CPU load config. " + + "\nMax queue count ["+maxQueueCount+"] (["+MAX_UPDATING_CHUNK_COUNT_PER_THREAD+"] per thread)."; + ClientApi.INSTANCE.showChatMessageNextFrame(message); + LOGGER.warn(message); } return; From 352abc40e612a1c30b3fbe33254086613af4284a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 27 Jun 2024 06:22:15 -0600 Subject: [PATCH 002/104] Add proof-of-concept cube rendering --- .../core/render/renderer/DebugRenderer.java | 107 +++++++++++++----- .../core/render/renderer/LodRenderer.java | 1 + 2 files changed, 82 insertions(+), 26 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java index 42d893b9d..36c3db42b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java @@ -64,13 +64,14 @@ public class DebugRenderer // rendering setup private ShaderProgram basicShader; - private GLVertexBuffer boxBuffer; - private GLElementBuffer boxOutlineBuffer; + private GLVertexBuffer vertexBuffer; + private GLElementBuffer outlineIndexBuffer; + private GLElementBuffer solidIndexBuffer; private AbstractVertexAttribute va; private boolean init = false; // used when rendering - private Mat4f transformThiFrame; + private Mat4f transformationMatrixThisFrame; private Vec3f camPosFloatThisFrame; @@ -79,8 +80,8 @@ public class DebugRenderer - // A box from 0,0,0 to 1,1,1 - private static final float[] box_vertices = { + /** A box from 0,0,0 to 1,1,1 */ + private static final float[] BOX_VERTICIES = { // Pos x y z 0, 0, 0, 1, 0, 0, @@ -92,7 +93,7 @@ public class DebugRenderer 0, 1, 1, }; - private static final int[] box_outline_indices = { + private static final int[] BOX_OUTLINE_INDICES = { 0, 1, 1, 2, 2, 3, @@ -109,6 +110,30 @@ public class DebugRenderer 3, 7, }; + private static final int[] SOLID_BOX_INDICES = { + // min Z, vertical face + 0, 3, 2, + 2, 1, 0, + // max Z, vertical face + 4, 5, 6, + 6, 7, 4, + + // min X, vertical face + 7, 3, 0, + 0, 4, 7, + // max X, vertical face + 2, 6, 5, + 5, 1, 2, + + // min Y, horizontal face + 1, 5, 4, + 4, 0, 1, + // max Y, horizontal face + 3, 7, 6, + 6, 2, 3, + }; + + //=============// @@ -167,27 +192,39 @@ public class DebugRenderer private void createBuffer() { - ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(box_vertices); - buffer.rewind(); + // box vertices + ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICIES.length * Float.BYTES); + boxVerticesBuffer.order(ByteOrder.nativeOrder()); + boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICIES); + boxVerticesBuffer.rewind(); + this.vertexBuffer = new GLVertexBuffer(false); + this.vertexBuffer.bind(); + this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICIES.length * Float.BYTES); - this.boxBuffer = new GLVertexBuffer(false); - this.boxBuffer.bind(); - this.boxBuffer.uploadBuffer(buffer, 8, EDhApiGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); - buffer = ByteBuffer.allocateDirect(box_outline_indices.length * Integer.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asIntBuffer().put(box_outline_indices); - buffer.rewind(); + // outline vertex indexes + ByteBuffer boxOutlineBuffer = ByteBuffer.allocateDirect(BOX_OUTLINE_INDICES.length * Integer.BYTES); + boxOutlineBuffer.order(ByteOrder.nativeOrder()); + boxOutlineBuffer.asIntBuffer().put(BOX_OUTLINE_INDICES); + boxOutlineBuffer.rewind(); + this.outlineIndexBuffer = new GLElementBuffer(false); + this.outlineIndexBuffer.uploadBuffer(boxOutlineBuffer, EDhApiGpuUploadMethod.DATA, BOX_OUTLINE_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + + + // solid vertex indexes + ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); + solidIndexBuffer.order(ByteOrder.nativeOrder()); + solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); + solidIndexBuffer.rewind(); + this.solidIndexBuffer = new GLElementBuffer(false); + this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + this.solidIndexBuffer.bind(); - this.boxOutlineBuffer = new GLElementBuffer(false); - this.boxOutlineBuffer.uploadBuffer(buffer, EDhApiGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW); } public void render(Mat4f transform) { - this.transformThiFrame = transform; + this.transformationMatrixThisFrame = transform; Vec3d camPos = MC_RENDER.getCameraExactPosition(); this.camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z); @@ -199,28 +236,35 @@ public class DebugRenderer this.basicShader.bind(); this.va.bind(); - this.va.bindBufferToAllBindingPoints(this.boxBuffer.getId()); + this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId()); - this.boxOutlineBuffer.bind(); + this.outlineIndexBuffer.bind(); this.rendererLists.render(this); BoxParticle head = null; while ((head = this.particles.poll()) != null && head.isDead(System.nanoTime())) - { - } + { /* remove dead particles */ } if (head != null) { + // re-add the popped off head this.particles.add(head); } + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); for (BoxParticle particle : this.particles) { this.renderBox(particle.getBox()); } + this.solidIndexBuffer.bind(); + renderSolidBox(new Box(new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), Color.CYAN), SOLID_BOX_INDICES); + + + + this.basicShader.unbind(); glState.restore(); } @@ -228,11 +272,22 @@ public class DebugRenderer { Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - this.camPosFloatThisFrame.x, box.a.y - this.camPosFloatThisFrame.y, box.a.z - this.camPosFloatThisFrame.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 = this.transformThiFrame.copy(); + Mat4f t = this.transformationMatrixThisFrame.copy(); t.multiply(boxTransform); this.basicShader.setUniform(this.basicShader.getUniformLocation("transform"), t); this.basicShader.setUniform(this.basicShader.getUniformLocation("uColor"), box.color); - GL32.glDrawElements(GL32.GL_LINES, box_outline_indices.length, GL32.GL_UNSIGNED_INT, 0); + GL32.glDrawElements(GL32.GL_LINES, BOX_OUTLINE_INDICES.length, GL32.GL_UNSIGNED_INT, 0); + } + + public void renderSolidBox(Box box, int[] drawIndices) + { + Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - this.camPosFloatThisFrame.x, box.a.y - this.camPosFloatThisFrame.y, box.a.z - this.camPosFloatThisFrame.z); + boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); + Mat4f transformMatrix = this.transformationMatrixThisFrame.copy(); + transformMatrix.multiply(boxTransform); + this.basicShader.setUniform(this.basicShader.getUniformLocation("transform"), transformMatrix); + this.basicShader.setUniform(this.basicShader.getUniformLocation("uColor"), box.color); + GL32.glDrawElements(GL32.GL_TRIANGLES , drawIndices.length, GL32.GL_UNSIGNED_INT, 0); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 6ea356fd8..780afd0fb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -616,6 +616,7 @@ public class LodRenderer boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get(); if (renderWireframe) { + // TODO fix GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE); //GL32.glDisable(GL32.GL_CULL_FACE); } From 6bfa3a422eae8f3ac42e1072c36b0126450e7ab8 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 27 Jun 2024 06:36:30 -0600 Subject: [PATCH 003/104] Move generic cube rendering into it's own class --- .../core/render/renderer/DebugRenderer.java | 52 -- .../render/renderer/GenericCubeRenderer.java | 470 ++++++++++++++++++ .../core/render/renderer/LodRenderer.java | 9 + 3 files changed, 479 insertions(+), 52 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericCubeRenderer.java diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java index 36c3db42b..ecced576b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java @@ -66,7 +66,6 @@ public class DebugRenderer private ShaderProgram basicShader; private GLVertexBuffer vertexBuffer; private GLElementBuffer outlineIndexBuffer; - private GLElementBuffer solidIndexBuffer; private AbstractVertexAttribute va; private boolean init = false; @@ -110,30 +109,6 @@ public class DebugRenderer 3, 7, }; - private static final int[] SOLID_BOX_INDICES = { - // min Z, vertical face - 0, 3, 2, - 2, 1, 0, - // max Z, vertical face - 4, 5, 6, - 6, 7, 4, - - // min X, vertical face - 7, 3, 0, - 0, 4, 7, - // max X, vertical face - 2, 6, 5, - 5, 1, 2, - - // min Y, horizontal face - 1, 5, 4, - 4, 0, 1, - // max Y, horizontal face - 3, 7, 6, - 6, 2, 3, - }; - - //=============// @@ -210,16 +185,6 @@ public class DebugRenderer this.outlineIndexBuffer = new GLElementBuffer(false); this.outlineIndexBuffer.uploadBuffer(boxOutlineBuffer, EDhApiGpuUploadMethod.DATA, BOX_OUTLINE_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); - - // solid vertex indexes - ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); - solidIndexBuffer.order(ByteOrder.nativeOrder()); - solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); - solidIndexBuffer.rewind(); - this.solidIndexBuffer = new GLElementBuffer(false); - this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); - this.solidIndexBuffer.bind(); - } public void render(Mat4f transform) @@ -259,12 +224,6 @@ public class DebugRenderer } - this.solidIndexBuffer.bind(); - renderSolidBox(new Box(new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), Color.CYAN), SOLID_BOX_INDICES); - - - - this.basicShader.unbind(); glState.restore(); } @@ -279,17 +238,6 @@ public class DebugRenderer GL32.glDrawElements(GL32.GL_LINES, BOX_OUTLINE_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } - public void renderSolidBox(Box box, int[] drawIndices) - { - Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - this.camPosFloatThisFrame.x, box.a.y - this.camPosFloatThisFrame.y, box.a.z - this.camPosFloatThisFrame.z); - boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); - Mat4f transformMatrix = this.transformationMatrixThisFrame.copy(); - transformMatrix.multiply(boxTransform); - this.basicShader.setUniform(this.basicShader.getUniformLocation("transform"), transformMatrix); - this.basicShader.setUniform(this.basicShader.getUniformLocation("uColor"), box.color); - GL32.glDrawElements(GL32.GL_TRIANGLES , drawIndices.length, GL32.GL_UNSIGNED_INT, 0); - } - //================// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericCubeRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericCubeRenderer.java new file mode 100644 index 000000000..1a68cefae --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericCubeRenderer.java @@ -0,0 +1,470 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer; + +import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; +import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.config.types.ConfigEntry; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; +import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; +import com.seibel.distanthorizons.core.pos.DhBlockPos2D; +import com.seibel.distanthorizons.core.pos.DhLodPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; +import com.seibel.distanthorizons.core.render.glObject.GLState; +import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer; +import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; +import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute; +import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +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.*; +import java.io.Closeable; +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.concurrent.PriorityBlockingQueue; + +public class GenericCubeRenderer +{ + public static GenericCubeRenderer INSTANCE = new GenericCubeRenderer(); + + public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(GenericCubeRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT); + public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(TestRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1); + + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + + // rendering setup + private ShaderProgram basicUnlitShader; + private GLVertexBuffer vertexBuffer; + private GLElementBuffer solidIndexBuffer; + private AbstractVertexAttribute va; + private boolean init = false; + + // used when rendering + private Mat4f transformationMatrixThisFrame; + private Vec3f camPosFloatThisFrame; + + + //private final RendererLists rendererLists = new RendererLists(); + //private final PriorityBlockingQueue particles = new PriorityBlockingQueue<>(); + + + + /** A box from 0,0,0 to 1,1,1 */ + private static final float[] BOX_VERTICIES = { + // Pos x y z + 0, 0, 0, + 1, 0, 0, + 1, 1, 0, + 0, 1, 0, + 0, 0, 1, + 1, 0, 1, + 1, 1, 1, + 0, 1, 1, + }; + + private static final int[] SOLID_BOX_INDICES = { + // min Z, vertical face + 0, 3, 2, + 2, 1, 0, + // max Z, vertical face + 4, 5, 6, + 6, 7, 4, + + // min X, vertical face + 7, 3, 0, + 0, 4, 7, + // max X, vertical face + 2, 6, 5, + 5, 1, 2, + + // min Y, horizontal face + 1, 5, 4, + 4, 0, 1, + // max Y, horizontal face + 3, 7, 6, + 6, 2, 3, + }; + + + + //=============// + // constructor // + //=============// + + public GenericCubeRenderer() { } + + + + //==============// + // registration // + //==============// + + //public static void makeParticle(BoxParticle particle) + //{ + // if (INSTANCE != null && Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) + // { + // INSTANCE.particles.add(particle); + // } + //} + // + //public static void register(IDebugRenderable renderable, ConfigEntry config) { if (INSTANCE != null) { INSTANCE.addRenderer(renderable, config); } } + //public void addRenderer(IDebugRenderable renderable, ConfigEntry config) { this.rendererLists.addRenderable(renderable, config); } + // + //public static void unregister(IDebugRenderable renderable, ConfigEntry config) { if (INSTANCE != null) { INSTANCE.removeRenderer(renderable, config); } } + //private void removeRenderer(IDebugRenderable renderable, ConfigEntry config) { this.rendererLists.removeRenderable(renderable, config); } + // + //public static void clearRenderables() { INSTANCE.rendererLists.clearRenderables(); } + + + + //===========// + // rendering // + //===========// + + public void init() + { + if (this.init) + { + return; + } + + this.init = true; + this.va = AbstractVertexAttribute.create(); + this.va.bind(); + // Pos + this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false)); + this.va.completeAndCheck(Float.BYTES * 3); + this.basicUnlitShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag", + "fragColor", new String[]{"vPosition"}); + this.createBuffers(); + } + + private void createBuffers() + { + // cube vertices + ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICIES.length * Float.BYTES); + boxVerticesBuffer.order(ByteOrder.nativeOrder()); + boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICIES); + boxVerticesBuffer.rewind(); + this.vertexBuffer = new GLVertexBuffer(false); + this.vertexBuffer.bind(); + this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICIES.length * Float.BYTES); + + + // cube vertex indexes + ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); + solidIndexBuffer.order(ByteOrder.nativeOrder()); + solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); + solidIndexBuffer.rewind(); + this.solidIndexBuffer = new GLElementBuffer(false); + this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + this.solidIndexBuffer.bind(); + + } + + public void render(Mat4f transform) + { + this.transformationMatrixThisFrame = transform; + Vec3d camPos = MC_RENDER.getCameraExactPosition(); + this.camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z); + + GLState glState = new GLState(); + this.init(); + + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); + GL32.glEnable(GL32.GL_DEPTH_TEST); + + this.basicUnlitShader.bind(); + this.va.bind(); + this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId()); + + this.solidIndexBuffer.bind(); + + //this.rendererLists.render(this); + + renderUnlitCube(new Box(new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), Color.CYAN)); + + + this.basicUnlitShader.unbind(); + glState.restore(); + } + + private void renderUnlitCube(Box box) + { + Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - this.camPosFloatThisFrame.x, box.a.y - this.camPosFloatThisFrame.y, box.a.z - this.camPosFloatThisFrame.z); + boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); + Mat4f transformMatrix = this.transformationMatrixThisFrame.copy(); + transformMatrix.multiply(boxTransform); + this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("transform"), transformMatrix); + + this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("uColor"), box.color); + + GL32.glDrawElements(GL32.GL_TRIANGLES , SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); + } + + + + //================// + // helper classes // + //================// + + public static final class Box + { + public Vec3f a; + public Vec3f b; + public 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(long pos, float minY, float maxY, float marginPercent, Color color) + { + this(DhSectionPos.getSectionBBoxPos(pos), minY, maxY, marginPercent, color); + } + + public Box(long pos, float y, float yDiff, Object hash, float marginPercent, Color color) + { + this(DhSectionPos.getSectionBBoxPos(pos), y, yDiff, hash, marginPercent, color); + } + + } + + //public static final class BoxParticle implements Comparable + //{ + // public Box box; + // public long startTime; + // public long duration; + // public 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 nanoSecondDuratoin, float yChange) { this(box, System.nanoTime(), nanoSecondDuratoin, yChange); } + // + // public BoxParticle(Box box, double secondDuration, float yChange) { this(box, System.nanoTime(), (long) (secondDuration * 1000000000), yChange); } + // + // + // @Override + // public int compareTo(@NotNull BoxParticle particle) + // { + // return Long.compare(this.startTime + this.duration, particle.startTime + particle.duration); + // } + // + // public Box getBox() + // { + // long now = System.nanoTime(); + // float percent = (now - this.startTime) / (float) this.duration; + // percent = (float) Math.pow(percent, 4); + // float yDiff = this.yChange * percent; + // return new Box(new Vec3f(this.box.a.x, this.box.a.y + yDiff, this.box.a.z), new Vec3f(this.box.b.x, this.box.b.y + yDiff, this.box.b.z), this.box.color); + // } + // + // public boolean isDead(long time) { return (time - this.startTime) > this.duration; } + // + //} + + + //private static class RendererLists + //{ + // public final LinkedList> generalRenderableList = new LinkedList<>(); + // + // private final HashMap, LinkedList>> renderableListByConfig = new HashMap<>(); + // + // + // + // // registration // + // + // public void addRenderable(IDebugRenderable renderable, @Nullable ConfigEntry config) + // { + // synchronized (this) + // { + // if (config != null) + // { + // if (!this.renderableListByConfig.containsKey(config)) + // { + // this.renderableListByConfig.put(config, new LinkedList<>()); + // } + // + // LinkedList> renderableList = this.renderableListByConfig.get(config); + // renderableList.add(new WeakReference<>(renderable)); + // } + // else + // { + // this.generalRenderableList.add(new WeakReference<>(renderable)); + // } + // } + // } + // + // public void removeRenderable(IDebugRenderable renderable, @Nullable ConfigEntry config) + // { + // synchronized (this) + // { + // if (config != null) + // { + // if (this.renderableListByConfig.containsKey(config)) + // { + // LinkedList> renderableList = this.renderableListByConfig.get(config); + // this.removeRenderableFromInternalList(renderableList, renderable); + // } + // } + // else + // { + // this.removeRenderableFromInternalList(this.generalRenderableList, renderable); + // } + // } + // } + // private void removeRenderableFromInternalList(LinkedList> rendererList, IDebugRenderable renderable) + // { + // Iterator> iterator = rendererList.iterator(); + // while (iterator.hasNext()) + // { + // WeakReference renderableRef = iterator.next(); + // if (renderableRef.get() == null) + // { + // iterator.remove(); + // continue; + // } + // + // if (renderableRef.get() == renderable) + // { + // iterator.remove(); + // return; + // } + // } + // } + // + // public void clearRenderables() + // { + // for (ConfigEntry config : this.renderableListByConfig.keySet()) + // { + // LinkedList> renderableList = this.renderableListByConfig.get(config); + // if (config.get() && renderableList != null) + // { + // renderableList.clear(); + // } + // } + // } + // + // + // + // // rendering // + // + // public void render(GenericCubeRenderer debugRenderer) + // { + // this.renderList(debugRenderer, this.generalRenderableList); + // + // for (ConfigEntry config : this.renderableListByConfig.keySet()) + // { + // LinkedList> renderableList = this.renderableListByConfig.get(config); + // if (config.get() && renderableList != null && renderableList.size() != 0) + // { + // this.renderList(debugRenderer, renderableList); + // } + // } + // } + // private void renderList(GenericCubeRenderer debugRenderer, LinkedList> rendererList) + // { + // synchronized (this) + // { + // try + // { + // Iterator> iterator = rendererList.iterator(); + // while (iterator.hasNext()) + // { + // WeakReference ref = iterator.next(); + // IDebugRenderable renderable = ref.get(); + // if (renderable == null) + // { + // iterator.remove(); + // continue; + // } + // + // renderable.debugRender(debugRenderer); + // } + // } + // catch (Exception e) + // { + // SPAM_LOGGER.error("Unexpected Debug renderer error, Error: "+e.getMessage(), e); + // } + // } + // } + //} + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 780afd0fb..f23c4fb8f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -422,6 +422,15 @@ public class LodRenderer // Note: this can be very slow if a lot of boxes are being rendered DebugRenderer.INSTANCE.render(combinedMatrix); + } + + profiler.popPush("Generic Cubes"); + + { + Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); + combinedMatrix.multiply(renderEventParam.dhModelViewMatrix); + + GenericCubeRenderer.INSTANCE.render(combinedMatrix); profiler.popPush("LOD cleanup"); } From 0d0826f319ff4ffc281d69f4aa1b5d5d31145071 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 28 Jun 2024 16:53:05 -0600 Subject: [PATCH 004/104] Separate out Generic object rendering --- .../com/seibel/distanthorizons/api/DhApi.java | 2 + .../render/IDhApiCustomRenderRegister.java | 18 + .../render/IDhApiRenderableBoxGroup.java | 21 + .../objects/render/DhApiRenderableBox.java | 26 + .../distanthorizons/core/Initializer.java | 2 + .../core/render/renderer/DebugRenderer.java | 124 +++-- .../render/renderer/GenericCubeRenderer.java | 470 ----------------- .../renderer/GenericObjectRenderer.java | 496 ++++++++++++++++++ .../core/render/renderer/LodRenderer.java | 14 +- .../resources/shaders/genericObject/frag.frag | 9 + .../resources/shaders/genericObject/vert.vert | 10 + 11 files changed, 648 insertions(+), 544 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java delete mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericCubeRenderer.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java create mode 100644 core/src/main/resources/shaders/genericObject/frag.frag create mode 100644 core/src/main/resources/shaders/genericObject/vert.vert diff --git a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java index 7a3a31e02..4b0b9969d 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java @@ -23,6 +23,7 @@ import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector; import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGeneratorOverrideRegister; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent; import com.seibel.distanthorizons.api.methods.override.DhApiWorldGeneratorOverrideRegister; @@ -127,6 +128,7 @@ public class DhApi */ public static IDhApiWrapperFactory wrapperFactory = null; + public static IDhApiCustomRenderRegister renderRegister = null; } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java new file mode 100644 index 000000000..0f3ef03a8 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java @@ -0,0 +1,18 @@ +package com.seibel.distanthorizons.api.interfaces.render; + +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; + +import java.util.List; + +public interface IDhApiCustomRenderRegister +{ + void add(IDhApiRenderableBoxGroup cubeGroup) throws IllegalArgumentException; + + IDhApiRenderableBoxGroup remove(long id); + + + IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube); + IDhApiRenderableBoxGroup createRelativePositionedGroup(float originBlockX, float originBlockY, float originBlockZ, List cubeList); + IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList); + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java new file mode 100644 index 000000000..2ecd2e900 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -0,0 +1,21 @@ +package com.seibel.distanthorizons.api.interfaces.render; + +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; + +import java.util.List; +import java.util.function.Consumer; + +public interface IDhApiRenderableBoxGroup extends List +{ + + + long getId(); + void setOriginBlockPos(float x, float y, float z); + float getOriginBlockX(); + float getOriginBlockY(); + float getOriginBlockZ(); + + void setPreRenderFunc(Consumer renderEventParam); + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java new file mode 100644 index 000000000..37276cc42 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java @@ -0,0 +1,26 @@ +package com.seibel.distanthorizons.api.objects.render; + + +import com.seibel.distanthorizons.coreapi.util.math.Vec3f; + +import java.awt.*; + +public final class DhApiRenderableBox +{ + public Vec3f minPos; + public Vec3f maxPos; + public Color color; + + public boolean fullBright = false; + + + + public DhApiRenderableBox(Vec3f minPos, Vec3f maxPos, Color color) + { + this.minPos = minPos; + this.maxPos = maxPos; + this.color = color; + } + +} + diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java index 76c2f0515..be1e4c20a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.sql.DatabaseUpdater; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.coreapi.ModInfo; @@ -93,6 +94,7 @@ public class Initializer DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE; DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE; DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE; + DhApi.Delayed.renderRegister = GenericObjectRenderer.INSTANCE; DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class); if (DhApi.Delayed.wrapperFactory == null) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java index ecced576b..7bc0ac7d7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java @@ -80,7 +80,7 @@ public class DebugRenderer /** A box from 0,0,0 to 1,1,1 */ - private static final float[] BOX_VERTICIES = { + private static final float[] BOX_VERTICES = { // Pos x y z 0, 0, 0, 1, 0, 0, @@ -115,7 +115,47 @@ public class DebugRenderer // constructor // //=============// - public DebugRenderer() { } + private DebugRenderer() { } + + public void init() + { + if (this.init) + { + return; + } + this.init = true; + + this.va = AbstractVertexAttribute.create(); + this.va.bind(); + // Pos + this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false)); + this.va.completeAndCheck(Float.BYTES * 3); + this.basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag", + "fragColor", new String[]{"vPosition"}); + this.createBuffer(); + } + + private void createBuffer() + { + // box vertices + ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES); + boxVerticesBuffer.order(ByteOrder.nativeOrder()); + boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES); + boxVerticesBuffer.rewind(); + this.vertexBuffer = new GLVertexBuffer(false); + this.vertexBuffer.bind(); + this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES); + + + // outline vertex indexes + ByteBuffer boxOutlineBuffer = ByteBuffer.allocateDirect(BOX_OUTLINE_INDICES.length * Integer.BYTES); + boxOutlineBuffer.order(ByteOrder.nativeOrder()); + boxOutlineBuffer.asIntBuffer().put(BOX_OUTLINE_INDICES); + boxOutlineBuffer.rewind(); + this.outlineIndexBuffer = new GLElementBuffer(false); + this.outlineIndexBuffer.uploadBuffer(boxOutlineBuffer, EDhApiGpuUploadMethod.DATA, BOX_OUTLINE_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + + } @@ -141,52 +181,10 @@ public class DebugRenderer - - //===========// // rendering // //===========// - public void init() - { - if (this.init) - { - return; - } - - this.init = true; - this.va = AbstractVertexAttribute.create(); - this.va.bind(); - // Pos - this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false)); - this.va.completeAndCheck(Float.BYTES * 3); - this.basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag", - "fragColor", new String[]{"vPosition"}); - this.createBuffer(); - } - - private void createBuffer() - { - // box vertices - ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICIES.length * Float.BYTES); - boxVerticesBuffer.order(ByteOrder.nativeOrder()); - boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICIES); - boxVerticesBuffer.rewind(); - this.vertexBuffer = new GLVertexBuffer(false); - this.vertexBuffer.bind(); - this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICIES.length * Float.BYTES); - - - // outline vertex indexes - ByteBuffer boxOutlineBuffer = ByteBuffer.allocateDirect(BOX_OUTLINE_INDICES.length * Integer.BYTES); - boxOutlineBuffer.order(ByteOrder.nativeOrder()); - boxOutlineBuffer.asIntBuffer().put(BOX_OUTLINE_INDICES); - boxOutlineBuffer.rewind(); - this.outlineIndexBuffer = new GLElementBuffer(false); - this.outlineIndexBuffer.uploadBuffer(boxOutlineBuffer, EDhApiGpuUploadMethod.DATA, BOX_OUTLINE_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); - - } - public void render(Mat4f transform) { this.transformationMatrixThisFrame = transform; @@ -229,8 +227,8 @@ public class DebugRenderer public void renderBox(Box box) { - Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - this.camPosFloatThisFrame.x, box.a.y - this.camPosFloatThisFrame.y, box.a.z - this.camPosFloatThisFrame.z); - boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); + Mat4f boxTransform = Mat4f.createTranslateMatrix(box.minPos.x - this.camPosFloatThisFrame.x, box.minPos.y - this.camPosFloatThisFrame.y, box.minPos.z - this.camPosFloatThisFrame.z); + boxTransform.multiply(Mat4f.createScaleMatrix(box.maxPos.x - box.minPos.x, box.maxPos.y - box.minPos.y, box.maxPos.z - box.minPos.z)); Mat4f t = this.transformationMatrixThisFrame.copy(); t.multiply(boxTransform); this.basicShader.setUniform(this.basicShader.getUniformLocation("transform"), t); @@ -246,25 +244,25 @@ public class DebugRenderer public static final class Box { - public Vec3f a; - public Vec3f b; + public Vec3f minPos; + public Vec3f maxPos; public Color color; - public Box(Vec3f a, Vec3f b, Color color) + public Box(Vec3f minPos, Vec3f maxPos, Color color) { - this.a = a; - this.b = b; + this.minPos = minPos; + this.maxPos = maxPos; this.color = color; } - public Box(Vec3f a, Vec3f b, Color color, Vec3f margin) + public Box(Vec3f minPos, Vec3f maxPos, Color color, Vec3f margin) { - this.a = a; - this.a.add(margin); - this.b = b; - this.b.subtract(margin); + this.minPos = minPos; + this.minPos.add(margin); + this.maxPos = maxPos; + this.maxPos.subtract(margin); this.color = color; } @@ -275,8 +273,8 @@ public class DebugRenderer 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.minPos = a; + this.maxPos = b; this.color = color; } @@ -288,8 +286,8 @@ public class DebugRenderer 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.minPos = a; + this.maxPos = b; this.color = color; } @@ -337,7 +335,7 @@ public class DebugRenderer float percent = (now - this.startTime) / (float) this.duration; percent = (float) Math.pow(percent, 4); float yDiff = this.yChange * percent; - return new Box(new Vec3f(this.box.a.x, this.box.a.y + yDiff, this.box.a.z), new Vec3f(this.box.b.x, this.box.b.y + yDiff, this.box.b.z), this.box.color); + return new Box(new Vec3f(this.box.minPos.x, this.box.minPos.y + yDiff, this.box.minPos.z), new Vec3f(this.box.maxPos.x, this.box.maxPos.y + yDiff, this.box.maxPos.z), this.box.color); } public boolean isDead(long time) { return (time - this.startTime) > this.duration; } @@ -353,7 +351,7 @@ public class DebugRenderer public BoxWithLife(Box box, long ns, float yChange, Color deathColor) { this.box = box; - this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), -1, ns, yChange); + this.particaleOnClose = new BoxParticle(new Box(box.minPos, box.maxPos, deathColor), -1, ns, yChange); register(this, null); } @@ -363,7 +361,7 @@ public class DebugRenderer public BoxWithLife(Box box, double s, float yChange, Color deathColor) { this.box = box; - this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), s, yChange); + this.particaleOnClose = new BoxParticle(new Box(box.minPos, box.maxPos, deathColor), s, yChange); } public BoxWithLife(Box box, double s, float yChange) { this(box, s, yChange, box.color); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericCubeRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericCubeRenderer.java deleted file mode 100644 index 1a68cefae..000000000 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericCubeRenderer.java +++ /dev/null @@ -1,470 +0,0 @@ -/* - * This file is part of the Distant Horizons mod - * licensed under the GNU LGPL v3 License. - * - * Copyright (C) 2020-2023 James Seibel - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.seibel.distanthorizons.core.render.renderer; - -import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; -import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; -import com.seibel.distanthorizons.core.config.Config; -import com.seibel.distanthorizons.core.config.types.ConfigEntry; -import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; -import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; -import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.pos.DhLodPos; -import com.seibel.distanthorizons.core.pos.DhSectionPos; -import com.seibel.distanthorizons.core.render.glObject.GLState; -import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer; -import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; -import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; -import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute; -import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; -import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; -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.*; -import java.io.Closeable; -import java.lang.ref.WeakReference; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.concurrent.PriorityBlockingQueue; - -public class GenericCubeRenderer -{ - public static GenericCubeRenderer INSTANCE = new GenericCubeRenderer(); - - public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(GenericCubeRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT); - public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(TestRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1); - - private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - - - // rendering setup - private ShaderProgram basicUnlitShader; - private GLVertexBuffer vertexBuffer; - private GLElementBuffer solidIndexBuffer; - private AbstractVertexAttribute va; - private boolean init = false; - - // used when rendering - private Mat4f transformationMatrixThisFrame; - private Vec3f camPosFloatThisFrame; - - - //private final RendererLists rendererLists = new RendererLists(); - //private final PriorityBlockingQueue particles = new PriorityBlockingQueue<>(); - - - - /** A box from 0,0,0 to 1,1,1 */ - private static final float[] BOX_VERTICIES = { - // Pos x y z - 0, 0, 0, - 1, 0, 0, - 1, 1, 0, - 0, 1, 0, - 0, 0, 1, - 1, 0, 1, - 1, 1, 1, - 0, 1, 1, - }; - - private static final int[] SOLID_BOX_INDICES = { - // min Z, vertical face - 0, 3, 2, - 2, 1, 0, - // max Z, vertical face - 4, 5, 6, - 6, 7, 4, - - // min X, vertical face - 7, 3, 0, - 0, 4, 7, - // max X, vertical face - 2, 6, 5, - 5, 1, 2, - - // min Y, horizontal face - 1, 5, 4, - 4, 0, 1, - // max Y, horizontal face - 3, 7, 6, - 6, 2, 3, - }; - - - - //=============// - // constructor // - //=============// - - public GenericCubeRenderer() { } - - - - //==============// - // registration // - //==============// - - //public static void makeParticle(BoxParticle particle) - //{ - // if (INSTANCE != null && Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) - // { - // INSTANCE.particles.add(particle); - // } - //} - // - //public static void register(IDebugRenderable renderable, ConfigEntry config) { if (INSTANCE != null) { INSTANCE.addRenderer(renderable, config); } } - //public void addRenderer(IDebugRenderable renderable, ConfigEntry config) { this.rendererLists.addRenderable(renderable, config); } - // - //public static void unregister(IDebugRenderable renderable, ConfigEntry config) { if (INSTANCE != null) { INSTANCE.removeRenderer(renderable, config); } } - //private void removeRenderer(IDebugRenderable renderable, ConfigEntry config) { this.rendererLists.removeRenderable(renderable, config); } - // - //public static void clearRenderables() { INSTANCE.rendererLists.clearRenderables(); } - - - - //===========// - // rendering // - //===========// - - public void init() - { - if (this.init) - { - return; - } - - this.init = true; - this.va = AbstractVertexAttribute.create(); - this.va.bind(); - // Pos - this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false)); - this.va.completeAndCheck(Float.BYTES * 3); - this.basicUnlitShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag", - "fragColor", new String[]{"vPosition"}); - this.createBuffers(); - } - - private void createBuffers() - { - // cube vertices - ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICIES.length * Float.BYTES); - boxVerticesBuffer.order(ByteOrder.nativeOrder()); - boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICIES); - boxVerticesBuffer.rewind(); - this.vertexBuffer = new GLVertexBuffer(false); - this.vertexBuffer.bind(); - this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICIES.length * Float.BYTES); - - - // cube vertex indexes - ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); - solidIndexBuffer.order(ByteOrder.nativeOrder()); - solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); - solidIndexBuffer.rewind(); - this.solidIndexBuffer = new GLElementBuffer(false); - this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); - this.solidIndexBuffer.bind(); - - } - - public void render(Mat4f transform) - { - this.transformationMatrixThisFrame = transform; - Vec3d camPos = MC_RENDER.getCameraExactPosition(); - this.camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z); - - GLState glState = new GLState(); - this.init(); - - GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); - GL32.glEnable(GL32.GL_DEPTH_TEST); - - this.basicUnlitShader.bind(); - this.va.bind(); - this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId()); - - this.solidIndexBuffer.bind(); - - //this.rendererLists.render(this); - - renderUnlitCube(new Box(new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), Color.CYAN)); - - - this.basicUnlitShader.unbind(); - glState.restore(); - } - - private void renderUnlitCube(Box box) - { - Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - this.camPosFloatThisFrame.x, box.a.y - this.camPosFloatThisFrame.y, box.a.z - this.camPosFloatThisFrame.z); - boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); - Mat4f transformMatrix = this.transformationMatrixThisFrame.copy(); - transformMatrix.multiply(boxTransform); - this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("transform"), transformMatrix); - - this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("uColor"), box.color); - - GL32.glDrawElements(GL32.GL_TRIANGLES , SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); - } - - - - //================// - // helper classes // - //================// - - public static final class Box - { - public Vec3f a; - public Vec3f b; - public 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(long pos, float minY, float maxY, float marginPercent, Color color) - { - this(DhSectionPos.getSectionBBoxPos(pos), minY, maxY, marginPercent, color); - } - - public Box(long pos, float y, float yDiff, Object hash, float marginPercent, Color color) - { - this(DhSectionPos.getSectionBBoxPos(pos), y, yDiff, hash, marginPercent, color); - } - - } - - //public static final class BoxParticle implements Comparable - //{ - // public Box box; - // public long startTime; - // public long duration; - // public 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 nanoSecondDuratoin, float yChange) { this(box, System.nanoTime(), nanoSecondDuratoin, yChange); } - // - // public BoxParticle(Box box, double secondDuration, float yChange) { this(box, System.nanoTime(), (long) (secondDuration * 1000000000), yChange); } - // - // - // @Override - // public int compareTo(@NotNull BoxParticle particle) - // { - // return Long.compare(this.startTime + this.duration, particle.startTime + particle.duration); - // } - // - // public Box getBox() - // { - // long now = System.nanoTime(); - // float percent = (now - this.startTime) / (float) this.duration; - // percent = (float) Math.pow(percent, 4); - // float yDiff = this.yChange * percent; - // return new Box(new Vec3f(this.box.a.x, this.box.a.y + yDiff, this.box.a.z), new Vec3f(this.box.b.x, this.box.b.y + yDiff, this.box.b.z), this.box.color); - // } - // - // public boolean isDead(long time) { return (time - this.startTime) > this.duration; } - // - //} - - - //private static class RendererLists - //{ - // public final LinkedList> generalRenderableList = new LinkedList<>(); - // - // private final HashMap, LinkedList>> renderableListByConfig = new HashMap<>(); - // - // - // - // // registration // - // - // public void addRenderable(IDebugRenderable renderable, @Nullable ConfigEntry config) - // { - // synchronized (this) - // { - // if (config != null) - // { - // if (!this.renderableListByConfig.containsKey(config)) - // { - // this.renderableListByConfig.put(config, new LinkedList<>()); - // } - // - // LinkedList> renderableList = this.renderableListByConfig.get(config); - // renderableList.add(new WeakReference<>(renderable)); - // } - // else - // { - // this.generalRenderableList.add(new WeakReference<>(renderable)); - // } - // } - // } - // - // public void removeRenderable(IDebugRenderable renderable, @Nullable ConfigEntry config) - // { - // synchronized (this) - // { - // if (config != null) - // { - // if (this.renderableListByConfig.containsKey(config)) - // { - // LinkedList> renderableList = this.renderableListByConfig.get(config); - // this.removeRenderableFromInternalList(renderableList, renderable); - // } - // } - // else - // { - // this.removeRenderableFromInternalList(this.generalRenderableList, renderable); - // } - // } - // } - // private void removeRenderableFromInternalList(LinkedList> rendererList, IDebugRenderable renderable) - // { - // Iterator> iterator = rendererList.iterator(); - // while (iterator.hasNext()) - // { - // WeakReference renderableRef = iterator.next(); - // if (renderableRef.get() == null) - // { - // iterator.remove(); - // continue; - // } - // - // if (renderableRef.get() == renderable) - // { - // iterator.remove(); - // return; - // } - // } - // } - // - // public void clearRenderables() - // { - // for (ConfigEntry config : this.renderableListByConfig.keySet()) - // { - // LinkedList> renderableList = this.renderableListByConfig.get(config); - // if (config.get() && renderableList != null) - // { - // renderableList.clear(); - // } - // } - // } - // - // - // - // // rendering // - // - // public void render(GenericCubeRenderer debugRenderer) - // { - // this.renderList(debugRenderer, this.generalRenderableList); - // - // for (ConfigEntry config : this.renderableListByConfig.keySet()) - // { - // LinkedList> renderableList = this.renderableListByConfig.get(config); - // if (config.get() && renderableList != null && renderableList.size() != 0) - // { - // this.renderList(debugRenderer, renderableList); - // } - // } - // } - // private void renderList(GenericCubeRenderer debugRenderer, LinkedList> rendererList) - // { - // synchronized (this) - // { - // try - // { - // Iterator> iterator = rendererList.iterator(); - // while (iterator.hasNext()) - // { - // WeakReference ref = iterator.next(); - // IDebugRenderable renderable = ref.get(); - // if (renderable == null) - // { - // iterator.remove(); - // continue; - // } - // - // renderable.debugRender(debugRenderer); - // } - // } - // catch (Exception e) - // { - // SPAM_LOGGER.error("Unexpected Debug renderer error, Error: "+e.getMessage(), e); - // } - // } - // } - //} - -} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java new file mode 100644 index 000000000..bd6b24dd5 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -0,0 +1,496 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer; + +import com.seibel.distanthorizons.api.DhApi; +import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; +import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; +import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; +import com.seibel.distanthorizons.core.render.glObject.GLState; +import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer; +import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; +import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute; +import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +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 it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongSet; +import org.apache.logging.log4j.LogManager; +import org.lwjgl.opengl.GL32; + +import javax.annotation.Nullable; +import java.awt.*; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Spliterator; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import java.util.stream.Stream; + +public class GenericObjectRenderer implements IDhApiCustomRenderRegister +{ + public static GenericObjectRenderer INSTANCE = new GenericObjectRenderer(); + + public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(GenericObjectRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT); + public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(TestRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1); + + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + + // rendering setup + private ShaderProgram basicUnlitShader; + private GLVertexBuffer vertexBuffer; + private GLElementBuffer solidIndexBuffer; + private AbstractVertexAttribute va; + private boolean init = false; + + // used when rendering + private Mat4f transformationMatrixThisFrame; + private Vec3f camPosFloatThisFrame; + + + // TODO may need to be double buffered to prevent rendering lag + private final Long2ReferenceOpenHashMap boxGroupById = new Long2ReferenceOpenHashMap<>(); + private final ReentrantLock mapModifyLock = new ReentrantLock(); + + + + /** A box from 0,0,0 to 1,1,1 */ + private static final float[] BOX_VERTICES = { + // Pos x y z + 0, 0, 0, + 1, 0, 0, + 1, 1, 0, + 0, 1, 0, + 0, 0, 1, + 1, 0, 1, + 1, 1, 1, + 0, 1, 1, + }; + + private static final int[] SOLID_BOX_INDICES = { + // min Z, vertical face + 0, 3, 2, + 2, 1, 0, + // max Z, vertical face + 4, 5, 6, + 6, 7, 4, + + // min X, vertical face + 7, 3, 0, + 0, 4, 7, + // max X, vertical face + 2, 6, 5, + 5, 1, 2, + + // min Y, horizontal face + 1, 5, 4, + 4, 0, 1, + // max Y, horizontal face + 3, 7, 6, + 6, 2, 3, + }; + + + + //=============// + // constructor // + //=============// + + private GenericObjectRenderer() { } + + public void init() + { + if (this.init) + { + return; + } + this.init = true; + + this.va = AbstractVertexAttribute.create(); + this.va.bind(); + // Pos + this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false)); + this.va.completeAndCheck(Float.BYTES * 3); + this.basicUnlitShader = new ShaderProgram("shaders/genericObject/vert.vert", "shaders/genericObject/frag.frag", + "fragColor", new String[]{"vPosition"}); + + this.createBuffers(); + + + + // testing // + + // single giant cube + IDhApiRenderableBoxGroup singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( + new DhApiRenderableBox( + new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), + new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) + ); + DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); + + // single slender cube + singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( + new DhApiRenderableBox( + new Vec3f(16f,0f,31f), new Vec3f(17f,2000f,32f), + new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) + ); + DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); + + // absolute cube group + ArrayList absCubeList = new ArrayList<>(); + for (int i = 0; i < 18; i++) + { + absCubeList.add(new DhApiRenderableBox( + new Vec3f(0f+i,150f+i,24f), new Vec3f(1f+i,151f+i,25f), + new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); + } + IDhApiRenderableBoxGroup absolutePosCubeGroup = DhApi.Delayed.renderRegister.createAbsolutePositionedGroup(absCubeList); + DhApi.Delayed.renderRegister.add(absolutePosCubeGroup); + + // relative cube group + ArrayList relCubeList = new ArrayList<>(); + for (int i = 0; i < 8; i+=2) + { + relCubeList.add(new DhApiRenderableBox( + new Vec3f(0f,0f+i,0f), new Vec3f(1f,1f+i,1f), + new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); + } + IDhApiRenderableBoxGroup relativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( + 24f, 140f, 24f, + relCubeList); + AtomicInteger frameCount = new AtomicInteger(0); + relativePosCubeGroup.setPreRenderFunc((event) -> + { + float x = relativePosCubeGroup.getOriginBlockX(); + x += event.partialTicks / 2; + x %= 32; + relativePosCubeGroup.setOriginBlockPos(x, relativePosCubeGroup.getOriginBlockY(), relativePosCubeGroup.getOriginBlockZ()); + }); + DhApi.Delayed.renderRegister.add(relativePosCubeGroup); + + } + private void createBuffers() + { + // cube vertices + ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES); + boxVerticesBuffer.order(ByteOrder.nativeOrder()); + boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES); + boxVerticesBuffer.rewind(); + this.vertexBuffer = new GLVertexBuffer(false); + this.vertexBuffer.bind(); + this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES); + + + // cube vertex indexes + ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); + solidIndexBuffer.order(ByteOrder.nativeOrder()); + solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); + solidIndexBuffer.rewind(); + this.solidIndexBuffer = new GLElementBuffer(false); + this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + this.solidIndexBuffer.bind(); + + } + + + + //================// + // group creation // + //================// + + @Override + public IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox box) + { + ArrayList list = new ArrayList<>(); + list.add(box); + return new DhApiRenderableBoxGroup(0, 0, 0, list, false); + } + + @Override + public IDhApiRenderableBoxGroup createRelativePositionedGroup(float originBlockX, float originBlockY, float originBlockZ, List cubeList) + { return new DhApiRenderableBoxGroup(originBlockX, originBlockY, originBlockZ, cubeList, true); } + + @Override + public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList) + { return new DhApiRenderableBoxGroup(0, 0, 0, boxList, false); } + + + + //==============// + // registration // + //==============// + + @Override + public void add(IDhApiRenderableBoxGroup boxGroup) throws IllegalArgumentException + { + try + { + mapModifyLock.lock(); + + long id = boxGroup.getId(); + if (this.boxGroupById.containsKey(id)) + { + throw new IllegalArgumentException("A cube group with the ID [" + id + "] is already present."); + } + + this.boxGroupById.put(id, (DhApiRenderableBoxGroup) boxGroup); + + // TODO add to DB async? + } + finally + { + mapModifyLock.unlock(); + } + } + + @Override + public IDhApiRenderableBoxGroup remove(long id) + { + try + { + mapModifyLock.lock(); + // TODO remove from DB async? + return this.boxGroupById.remove(id); + } + finally + { + mapModifyLock.unlock(); + } + } + + public void clear() + { + try + { + mapModifyLock.lock(); + this.boxGroupById.clear(); + } + finally + { + mapModifyLock.unlock(); + } + } + + + + //===========// + // rendering // + //===========// + + public void render(DhApiRenderParam renderEventParam) + { + Mat4f transform = new Mat4f(renderEventParam.dhProjectionMatrix); + transform.multiply(renderEventParam.dhModelViewMatrix); + + this.transformationMatrixThisFrame = transform; + Vec3d camPos = MC_RENDER.getCameraExactPosition(); + this.camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z); + + GLState glState = new GLState(); + this.init(); + + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); + GL32.glEnable(GL32.GL_DEPTH_TEST); + + GL32.glEnable(GL32.GL_BLEND); + GL32.glBlendEquation(GL32.GL_FUNC_ADD); + GL32.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); + + this.basicUnlitShader.bind(); + this.va.bind(); + this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId()); + + this.solidIndexBuffer.bind(); + + LongSet keys = boxGroupById.keySet(); + for (long key : keys) + { + DhApiRenderableBoxGroup cubeGroup = boxGroupById.get(key); + this.renderCubeGroup(cubeGroup, renderEventParam); + } + + + this.basicUnlitShader.unbind(); + glState.restore(); + } + + private void renderCubeGroup(DhApiRenderableBoxGroup cubeGroup, DhApiRenderParam renderEventParam) + { + cubeGroup.preRender(renderEventParam); + + for (DhApiRenderableBox cube : cubeGroup.cubeList) + { + renderCube(cubeGroup, cube); + } + } + private void renderCube(DhApiRenderableBoxGroup cubeGroup, DhApiRenderableBox cube) + { + float originOffsetX = 0; + float originOffsetY = 0; + float originOffsetZ = 0; + if (cubeGroup.positionCubesRelativeToGroupOrigin) + { + originOffsetX = cubeGroup.originBlockX; + originOffsetY = cubeGroup.originBlockY; + originOffsetZ = cubeGroup.originBlockZ; + } + + Mat4f boxTransform = Mat4f.createTranslateMatrix( + cube.minPos.x + originOffsetX - this.camPosFloatThisFrame.x, + cube.minPos.y + originOffsetY - this.camPosFloatThisFrame.y, + cube.minPos.z + originOffsetZ - this.camPosFloatThisFrame.z); + boxTransform.multiply(Mat4f.createScaleMatrix( + cube.maxPos.x - cube.minPos.x, + cube.maxPos.y - cube.minPos.y, + cube.maxPos.z - cube.minPos.z)); + Mat4f transformMatrix = this.transformationMatrixThisFrame.copy(); + transformMatrix.multiply(boxTransform); + this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("transform"), transformMatrix); + + this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("uColor"), cube.color); + + GL32.glDrawElements(GL32.GL_TRIANGLES , SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); + } + + + + //================// + // helper classes // + //================// + + private static final class DhApiRenderableBoxGroup extends AbstractList implements IDhApiRenderableBoxGroup + { + public final static AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0); + + public final long id; + + /** If false the cubes will be positioned relative to the level's origin */ + public final boolean positionCubesRelativeToGroupOrigin; + + private final ArrayList cubeList; + + private float originBlockX; + private float originBlockY; + private float originBlockZ; + + @Nullable + public Consumer beforeRenderFunc; + + + // setters/getters // + + @Override + public long getId() { return this.id; } + + @Override + public void setOriginBlockPos(float x, float y, float z) + { + this.originBlockX = x; + this.originBlockY = y; + this.originBlockZ = z; + } + + @Override + public float getOriginBlockX() { return this.originBlockX; } + @Override + public float getOriginBlockY() { return this.originBlockY; } + @Override + public float getOriginBlockZ() { return this.originBlockZ; } + + + + // constructor // + + public DhApiRenderableBoxGroup(float originBlockX, float originBlockY, float originBlockZ, List cubeList, boolean positionCubesRelativeToGroupOrigin) + { + // TODO save to database + // TODO when? + + this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); + this.cubeList = new ArrayList<>(cubeList); + + this.originBlockX = originBlockX; + this.originBlockY = originBlockY; + this.originBlockZ = originBlockZ; + this.positionCubesRelativeToGroupOrigin = positionCubesRelativeToGroupOrigin; + } + + + + // methods // + + @Override + public boolean add(DhApiRenderableBox cube) { return this.cubeList.add(cube); } + + @Override + public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; } + + //@Override + public void preRender(DhApiRenderParam renderEventParam) + { + if (this.beforeRenderFunc != null) + { + beforeRenderFunc.accept(renderEventParam); + } + } + + + + // overrides // + + @Override + public DhApiRenderableBox get(int index) { return this.cubeList.get(index); } + @Override + public int size() { return this.cubeList.size(); } + @Override + public boolean removeIf(Predicate filter) { return this.cubeList.removeIf(filter); } + @Override + public void replaceAll(UnaryOperator operator) { this.cubeList.replaceAll(operator); } + @Override + public void sort(Comparator c) { this.cubeList.sort(c); } + @Override + public void forEach(Consumer action) { this.cubeList.forEach(action); } + @Override + public Spliterator spliterator() { return this.cubeList.spliterator(); } + @Override + public Stream stream() { return this.cubeList.stream(); } + @Override + public Stream parallelStream() { return this.cubeList.parallelStream(); } + + } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index f23c4fb8f..8e6c3f148 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -57,9 +57,6 @@ import org.apache.logging.log4j.LogManager; import org.lwjgl.opengl.GL32; import java.awt.*; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; import java.time.Duration; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; @@ -424,15 +421,10 @@ public class LodRenderer DebugRenderer.INSTANCE.render(combinedMatrix); } - profiler.popPush("Generic Cubes"); + profiler.popPush("Custom Objects"); + GenericObjectRenderer.INSTANCE.render(renderEventParam); - { - Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); - combinedMatrix.multiply(renderEventParam.dhModelViewMatrix); - - GenericCubeRenderer.INSTANCE.render(combinedMatrix); - profiler.popPush("LOD cleanup"); - } + profiler.popPush("LOD cleanup"); diff --git a/core/src/main/resources/shaders/genericObject/frag.frag b/core/src/main/resources/shaders/genericObject/frag.frag new file mode 100644 index 000000000..1f22d751c --- /dev/null +++ b/core/src/main/resources/shaders/genericObject/frag.frag @@ -0,0 +1,9 @@ +#version 150 core + +uniform vec4 uColor; +out vec4 fragColor; + +void main() +{ + fragColor = uColor; +} \ No newline at end of file diff --git a/core/src/main/resources/shaders/genericObject/vert.vert b/core/src/main/resources/shaders/genericObject/vert.vert new file mode 100644 index 000000000..e32ec6e80 --- /dev/null +++ b/core/src/main/resources/shaders/genericObject/vert.vert @@ -0,0 +1,10 @@ +#version 150 core + +uniform mat4 transform; + +in vec3 vPosition; + +void main() +{ + gl_Position = transform * vec4(vPosition, 1.0); +} \ No newline at end of file From c1a90c9350be84e42158e93db9408099db67cc62 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 29 Jun 2024 09:11:49 -0600 Subject: [PATCH 005/104] Add instanced generic object rendering --- .../renderer/GenericObjectRenderer.java | 235 ++++++++++++------ .../resources/shaders/genericObject/frag.frag | 5 +- .../resources/shaders/genericObject/vert.vert | 10 +- 3 files changed, 175 insertions(+), 75 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index bd6b24dd5..6f69a2c8d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -43,6 +43,7 @@ import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; import it.unimi.dsi.fastutil.longs.LongSet; import org.apache.logging.log4j.LogManager; import org.lwjgl.opengl.GL32; +import org.lwjgl.opengl.GL33; import javax.annotation.Nullable; import java.awt.*; @@ -77,9 +78,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private AbstractVertexAttribute va; private boolean init = false; - // used when rendering - private Mat4f transformationMatrixThisFrame; - private Vec3f camPosFloatThisFrame; + // instance data + private int instanceTransformVBO; + private int instanceColorVBO; // TODO may need to be double buffered to prevent rendering lag @@ -154,21 +155,21 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // testing // - // single giant cube - IDhApiRenderableBoxGroup singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( - new DhApiRenderableBox( - new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), - new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) - ); - DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); - - // single slender cube - singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( - new DhApiRenderableBox( - new Vec3f(16f,0f,31f), new Vec3f(17f,2000f,32f), - new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) - ); - DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); + //// single giant cube + //IDhApiRenderableBoxGroup singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( + // new DhApiRenderableBox( + // new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), + // new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) + // ); + //DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); + // + //// single slender cube + //singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( + // new DhApiRenderableBox( + // new Vec3f(16f,0f,31f), new Vec3f(17f,2000f,32f), + // new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) + //); + //DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); // absolute cube group ArrayList absCubeList = new ArrayList<>(); @@ -181,26 +182,26 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister IDhApiRenderableBoxGroup absolutePosCubeGroup = DhApi.Delayed.renderRegister.createAbsolutePositionedGroup(absCubeList); DhApi.Delayed.renderRegister.add(absolutePosCubeGroup); - // relative cube group - ArrayList relCubeList = new ArrayList<>(); - for (int i = 0; i < 8; i+=2) - { - relCubeList.add(new DhApiRenderableBox( - new Vec3f(0f,0f+i,0f), new Vec3f(1f,1f+i,1f), - new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); - } - IDhApiRenderableBoxGroup relativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( - 24f, 140f, 24f, - relCubeList); - AtomicInteger frameCount = new AtomicInteger(0); - relativePosCubeGroup.setPreRenderFunc((event) -> - { - float x = relativePosCubeGroup.getOriginBlockX(); - x += event.partialTicks / 2; - x %= 32; - relativePosCubeGroup.setOriginBlockPos(x, relativePosCubeGroup.getOriginBlockY(), relativePosCubeGroup.getOriginBlockZ()); - }); - DhApi.Delayed.renderRegister.add(relativePosCubeGroup); + //// relative cube group + //ArrayList relCubeList = new ArrayList<>(); + //for (int i = 0; i < 8; i+=2) + //{ + // relCubeList.add(new DhApiRenderableBox( + // new Vec3f(0f,0f+i,0f), new Vec3f(1f,1f+i,1f), + // new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); + //} + //IDhApiRenderableBoxGroup relativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( + // 24f, 140f, 24f, + // relCubeList); + //AtomicInteger frameCount = new AtomicInteger(0); + //relativePosCubeGroup.setPreRenderFunc((event) -> + //{ + // float x = relativePosCubeGroup.getOriginBlockX(); + // x += event.partialTicks / 2; + // x %= 32; + // relativePosCubeGroup.setOriginBlockPos(x, relativePosCubeGroup.getOriginBlockY(), relativePosCubeGroup.getOriginBlockZ()); + //}); + //DhApi.Delayed.renderRegister.add(relativePosCubeGroup); } private void createBuffers() @@ -224,6 +225,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); this.solidIndexBuffer.bind(); + + // instance buffers + this.instanceTransformVBO = GL32.glGenBuffers(); + this.instanceColorVBO = GL32.glGenBuffers(); } @@ -313,13 +318,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister public void render(DhApiRenderParam renderEventParam) { - Mat4f transform = new Mat4f(renderEventParam.dhProjectionMatrix); - transform.multiply(renderEventParam.dhModelViewMatrix); - - this.transformationMatrixThisFrame = transform; - Vec3d camPos = MC_RENDER.getCameraExactPosition(); - this.camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z); - GLState glState = new GLState(); this.init(); @@ -350,44 +348,141 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private void renderCubeGroup(DhApiRenderableBoxGroup cubeGroup, DhApiRenderParam renderEventParam) { + Mat4f transformMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); + transformMatrix.multiply(renderEventParam.dhModelViewMatrix); + + Vec3d camPos = MC_RENDER.getCameraExactPosition(); + Vec3f camPosFloat = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z); + + + + // update instance data // + cubeGroup.preRender(renderEventParam); + int boxCount = updateInstanceBuffers(camPosFloat, transformMatrix); // Update instance data - for (DhApiRenderableBox cube : cubeGroup.cubeList) - { - renderCube(cubeGroup, cube); - } + + + // Bind instance data // + + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVBO); + GL32.glEnableVertexAttribArray(1); + GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0); + GL33.glVertexAttribDivisor(1, 1); + + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTransformVBO); + GL32.glEnableVertexAttribArray(2); + GL33.glVertexAttribDivisor(2, 1); + GL32.glVertexAttribPointer(2, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 0); + GL32.glEnableVertexAttribArray(3); + GL33.glVertexAttribDivisor(3, 1); + GL32.glVertexAttribPointer(3, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 16); + GL32.glEnableVertexAttribArray(4); + GL33.glVertexAttribDivisor(4, 1); + GL32.glVertexAttribPointer(4, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 32); + GL32.glEnableVertexAttribArray(5); + GL33.glVertexAttribDivisor(5, 1); + GL32.glVertexAttribPointer(5, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 48); + + + + // Draw instanced + GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxCount); + + + // Clean up + GL32.glDisableVertexAttribArray(1); + GL32.glDisableVertexAttribArray(2); + GL32.glDisableVertexAttribArray(3); + GL32.glDisableVertexAttribArray(4); + GL32.glDisableVertexAttribArray(5); } - private void renderCube(DhApiRenderableBoxGroup cubeGroup, DhApiRenderableBox cube) + private int updateInstanceBuffers(Vec3f camPos, Mat4f transformationMatrix) { - float originOffsetX = 0; - float originOffsetY = 0; - float originOffsetZ = 0; - if (cubeGroup.positionCubesRelativeToGroupOrigin) + int boxCount = 0; + LongSet keys = boxGroupById.keySet(); + for (long key : keys) { - originOffsetX = cubeGroup.originBlockX; - originOffsetY = cubeGroup.originBlockY; - originOffsetZ = cubeGroup.originBlockZ; + DhApiRenderableBoxGroup cubeGroup = boxGroupById.get(key); + boxCount += cubeGroup.size(); } - Mat4f boxTransform = Mat4f.createTranslateMatrix( - cube.minPos.x + originOffsetX - this.camPosFloatThisFrame.x, - cube.minPos.y + originOffsetY - this.camPosFloatThisFrame.y, - cube.minPos.z + originOffsetZ - this.camPosFloatThisFrame.z); - boxTransform.multiply(Mat4f.createScaleMatrix( - cube.maxPos.x - cube.minPos.x, - cube.maxPos.y - cube.minPos.y, - cube.maxPos.z - cube.minPos.z)); - Mat4f transformMatrix = this.transformationMatrixThisFrame.copy(); - transformMatrix.multiply(boxTransform); - this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("transform"), transformMatrix); - this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("uColor"), cube.color); + // Prepare transformation matrices + float[] transformationData = new float[boxCount * 16]; + int cubeIndex = 0; + for (long key : keys) + { + DhApiRenderableBoxGroup cubeGroup = boxGroupById.get(key); + for (DhApiRenderableBox cube : cubeGroup) + { + float originOffsetX = 0; + float originOffsetY = 0; + float originOffsetZ = 0; + if (cubeGroup.positionCubesRelativeToGroupOrigin) + { + originOffsetX = cubeGroup.originBlockX; + originOffsetY = cubeGroup.originBlockY; + originOffsetZ = cubeGroup.originBlockZ; + } + + Mat4f boxTransform = Mat4f.createTranslateMatrix( + cube.minPos.x + originOffsetX - camPos.x, + cube.minPos.y + originOffsetY - camPos.y, + cube.minPos.z + originOffsetZ - camPos.z); + boxTransform.multiply(Mat4f.createScaleMatrix( + cube.maxPos.x - cube.minPos.x, + cube.maxPos.y - cube.minPos.y, + cube.maxPos.z - cube.minPos.z)); + Mat4f transformMatrix = transformationMatrix.copy(); + transformMatrix.multiply(boxTransform); + // TODO transformation matrix could be passed on to shader, only box offset needed here + //this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("transform"), transformMatrix); + + // due to how the matrix is being read in by GL, we need to transpose it + // (This is probably a bug due to how James set up the vertex array attributes) + transformMatrix.transpose(); + System.arraycopy(transformMatrix.getValuesAsArray(), 0, transformationData, cubeIndex * 16, 16); + + cubeIndex++; + } + } - GL32.glDrawElements(GL32.GL_TRIANGLES , SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); + // Upload transformation matrices + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTransformVBO); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, transformationData, GL32.GL_DYNAMIC_DRAW); + + + + // Prepare colors + float[] colors = new float[boxCount * 4]; + cubeIndex = 0; + for (long key : keys) + { + DhApiRenderableBoxGroup cubeGroup = boxGroupById.get(key); + for (DhApiRenderableBox cube : cubeGroup) + { + Color color = cube.color; + colors[cubeIndex * 4] = color.getRed() / 255.0f; + colors[cubeIndex * 4 + 1] = color.getGreen() / 255.0f; + colors[cubeIndex * 4 + 2] = color.getBlue() / 255.0f; + colors[cubeIndex * 4 + 3] = color.getAlpha() / 255.0f; + + cubeIndex++; + } + } + + // Upload colors + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVBO); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colors, GL32.GL_DYNAMIC_DRAW); + + return boxCount; } + + //================// // helper classes // //================// diff --git a/core/src/main/resources/shaders/genericObject/frag.frag b/core/src/main/resources/shaders/genericObject/frag.frag index 1f22d751c..c3d2ac8c4 100644 --- a/core/src/main/resources/shaders/genericObject/frag.frag +++ b/core/src/main/resources/shaders/genericObject/frag.frag @@ -1,9 +1,10 @@ #version 150 core -uniform vec4 uColor; +in vec4 fColor; + out vec4 fragColor; void main() { - fragColor = uColor; + fragColor = fColor; } \ No newline at end of file diff --git a/core/src/main/resources/shaders/genericObject/vert.vert b/core/src/main/resources/shaders/genericObject/vert.vert index e32ec6e80..7774dd406 100644 --- a/core/src/main/resources/shaders/genericObject/vert.vert +++ b/core/src/main/resources/shaders/genericObject/vert.vert @@ -1,10 +1,14 @@ -#version 150 core +#version 330 core -uniform mat4 transform; +layout (location = 1) in vec4 aColor; +layout (location = 2) in mat4 aTransform; in vec3 vPosition; +out vec4 fColor; + void main() { - gl_Position = transform * vec4(vPosition, 1.0); + gl_Position = aTransform * vec4(vPosition, 1.0); + fColor = aColor; } \ No newline at end of file From 62e5183c54d032ae5bcb0d8ef4e9b05d1bb6312f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 29 Jun 2024 10:18:27 -0600 Subject: [PATCH 006/104] Improve GLProxy creation validation/logging --- .../distanthorizons/core/render/glObject/GLProxy.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java index ffe831b00..1184c57c5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java @@ -91,17 +91,15 @@ public class GLProxy private GLProxy() throws IllegalStateException { // this must be created on minecraft's render context to work correctly - - GL_LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see there must have been an OpenGL error."); - GL_LOGGER.info("Lod Render OpenGL version [" + GL32.glGetString(GL32.GL_VERSION) + "]."); - - // getting Minecraft's context has to be done on the render thread, - // where the GL context is if (GLFW.glfwGetCurrentContext() == 0L) { throw new IllegalStateException(GLProxy.class.getSimpleName() + " was created outside the render thread!"); } + GL_LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see there must have been an OpenGL error."); + GL_LOGGER.info("Lod Render OpenGL version [" + GL32.glGetString(GL32.GL_VERSION) + "]."); + + //============================// From f2bba7f3df1eadb35e57500236e5ec4f1a6f4160 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 29 Jun 2024 10:29:30 -0600 Subject: [PATCH 007/104] Add instanced and direct genericObject rendering --- .../core/render/glObject/GLProxy.java | 22 +- .../render/glObject/shader/ShaderProgram.java | 2 +- .../AbstractVertexAttribute.java | 2 +- .../renderer/GenericObjectRenderer.java | 239 +++++++++++++----- .../render/renderer/LodRenderProgram.java | 2 +- .../shaders/genericObject/direct/frag.frag | 9 + .../shaders/genericObject/direct/vert.vert | 10 + .../genericObject/{ => instanced}/frag.frag | 0 .../genericObject/{ => instanced}/vert.vert | 0 9 files changed, 211 insertions(+), 75 deletions(-) create mode 100644 core/src/main/resources/shaders/genericObject/direct/frag.frag create mode 100644 core/src/main/resources/shaders/genericObject/direct/vert.vert rename core/src/main/resources/shaders/genericObject/{ => instanced}/frag.frag (100%) rename core/src/main/resources/shaders/genericObject/{ => instanced}/vert.vert (100%) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java index 1184c57c5..4bbfbd6e8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/GLProxy.java @@ -27,7 +27,6 @@ import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.util.objects.GLMessage; import com.seibel.distanthorizons.core.util.objects.GLMessageOutputStream; -import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.LogManager; @@ -40,8 +39,6 @@ import org.lwjgl.opengl.GLUtil; import java.io.PrintStream; import java.lang.invoke.MethodHandles; -import java.util.ArrayList; -import java.util.Arrays; import java.util.concurrent.ConcurrentLinkedQueue; /** @@ -76,7 +73,9 @@ public class GLProxy public boolean namedObjectSupported = false; // ~OpenGL 4.5 (UNUSED CURRENTLY) public boolean bufferStorageSupported = false; // ~OpenGL 4.4 - public boolean VertexAttributeBufferBindingSupported = false; // ~OpenGL 4.3 + public boolean vertexAttributeBufferBindingSupported = false; // ~OpenGL 4.3 + public boolean instancedArraysSupported = false; + public boolean vertexAttribDivisorSupported = false; // OpenGL 3.3 or newer private final EDhApiGpuUploadMethod preferredUploadMethod; @@ -133,21 +132,26 @@ public class GLProxy // get GPU capabilities // //======================// - // Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after - this.VertexAttributeBufferBindingSupported = this.glCapabilities.glBindVertexBuffer != 0L; // Nullptr - // UNUSED currently // Check if we can use the named version of all calls, which is available in GL4.5 or after this.namedObjectSupported = this.glCapabilities.glNamedBufferData != 0L; //Nullptr - // get specific capabilities // Check if we can use the Buffer Storage, which is available in GL4.4 or after this.bufferStorageSupported = this.glCapabilities.glBufferStorage != 0L; // Nullptr if (!this.bufferStorageSupported) { - GL_LOGGER.warn("This GPU doesn't support Buffer Storage (OpenGL 4.4), falling back to using other methods."); + GL_LOGGER.info("This GPU doesn't support Buffer Storage (OpenGL 4.4), falling back to using other methods."); } + // Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after + this.vertexAttributeBufferBindingSupported = this.glCapabilities.glBindVertexBuffer != 0L; // Nullptr + + // used by instanced rendering + this.vertexAttribDivisorSupported = this.glCapabilities.OpenGL33; + // denotes if ARBInstancedArrays.glVertexAttribDivisorARB() is available or not + // can be used as a backup if MC didn't create a GL 3.3+ context + this.instancedArraysSupported = this.glCapabilities.GL_ARB_instanced_arrays; + // get the best automatic upload method String vendor = GL32.glGetString(GL32.GL_VENDOR).toUpperCase(); // example return: "NVIDIA CORPORATION" if (vendor.contains("NVIDIA") || vendor.contains("GEFORCE")) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java index 8ade515eb..2870cf76a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java @@ -154,7 +154,7 @@ public class ShaderProgram * @return Location of the Uniform * @throws RuntimeException if uniform not found */ - public int getUniformLocation(CharSequence name) + public int getUniformLocation(CharSequence name) throws RuntimeException { int i = GL32.glGetUniformLocation(id, name); if (i == -1) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/AbstractVertexAttribute.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/AbstractVertexAttribute.java index 3c7267c71..3f27d12b6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/AbstractVertexAttribute.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/vertexAttribute/AbstractVertexAttribute.java @@ -48,7 +48,7 @@ public abstract class AbstractVertexAttribute public static AbstractVertexAttribute create() { - if (GLProxy.getInstance().VertexAttributeBufferBindingSupported) + if (GLProxy.getInstance().vertexAttributeBufferBindingSupported) { return new VertexAttributePostGL43(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 6f69a2c8d..2ee336f4e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -29,6 +29,8 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer; import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; @@ -42,6 +44,8 @@ import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; import it.unimi.dsi.fastutil.longs.LongSet; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.lwjgl.opengl.ARBInstancedArrays; import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL33; @@ -65,23 +69,33 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { public static GenericObjectRenderer INSTANCE = new GenericObjectRenderer(); - public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(GenericObjectRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT); + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(TestRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); // rendering setup - private ShaderProgram basicUnlitShader; + private boolean init = false; + + private ShaderProgram shader; private GLVertexBuffer vertexBuffer; private GLElementBuffer solidIndexBuffer; private AbstractVertexAttribute va; - private boolean init = false; + + private boolean useInstancedRendering; + private boolean vertexAttribDivisorSupported; + private boolean instancedArraysSupported; + // instance data private int instanceTransformVBO; private int instanceColorVBO; + // shader uniforms + private int transformUniformLocation; + private int directShaderColorUniformLocation; + // TODO may need to be double buffered to prevent rendering lag private final Long2ReferenceOpenHashMap boxGroupById = new Long2ReferenceOpenHashMap<>(); @@ -141,35 +155,50 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } this.init = true; + this.vertexAttribDivisorSupported = GLProxy.getInstance().vertexAttribDivisorSupported; + this.instancedArraysSupported = GLProxy.getInstance().instancedArraysSupported; + this.useInstancedRendering = this.vertexAttribDivisorSupported || this.instancedArraysSupported; + if (!this.useInstancedRendering) + { + LOGGER.info("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering may be slow."); + } + + this.va = AbstractVertexAttribute.create(); this.va.bind(); // Pos this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false)); this.va.completeAndCheck(Float.BYTES * 3); - this.basicUnlitShader = new ShaderProgram("shaders/genericObject/vert.vert", "shaders/genericObject/frag.frag", + + this.shader = new ShaderProgram( + this.useInstancedRendering ? "shaders/genericObject/instanced/vert.vert" : "shaders/genericObject/direct/vert.vert", + this.useInstancedRendering ? "shaders/genericObject/instanced/frag.frag" : "shaders/genericObject/direct/frag.frag", "fragColor", new String[]{"vPosition"}); + this.transformUniformLocation = this.shader.tryGetUniformLocation("transform"); + this.directShaderColorUniformLocation = this.shader.tryGetUniformLocation("uColor"); + this.createBuffers(); // testing // - //// single giant cube - //IDhApiRenderableBoxGroup singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( - // new DhApiRenderableBox( - // new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), - // new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) - // ); - //DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); - // - //// single slender cube - //singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( - // new DhApiRenderableBox( - // new Vec3f(16f,0f,31f), new Vec3f(17f,2000f,32f), - // new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) - //); - //DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); + // single giant cube + IDhApiRenderableBoxGroup singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( + new DhApiRenderableBox( + new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), + new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) + ); + DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); + + // single slender cube + singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( + new DhApiRenderableBox( + new Vec3f(16f,0f,31f), new Vec3f(17f,2000f,32f), + new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) + ); + DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); // absolute cube group ArrayList absCubeList = new ArrayList<>(); @@ -182,26 +211,26 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister IDhApiRenderableBoxGroup absolutePosCubeGroup = DhApi.Delayed.renderRegister.createAbsolutePositionedGroup(absCubeList); DhApi.Delayed.renderRegister.add(absolutePosCubeGroup); - //// relative cube group - //ArrayList relCubeList = new ArrayList<>(); - //for (int i = 0; i < 8; i+=2) - //{ - // relCubeList.add(new DhApiRenderableBox( - // new Vec3f(0f,0f+i,0f), new Vec3f(1f,1f+i,1f), - // new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); - //} - //IDhApiRenderableBoxGroup relativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( - // 24f, 140f, 24f, - // relCubeList); - //AtomicInteger frameCount = new AtomicInteger(0); - //relativePosCubeGroup.setPreRenderFunc((event) -> - //{ - // float x = relativePosCubeGroup.getOriginBlockX(); - // x += event.partialTicks / 2; - // x %= 32; - // relativePosCubeGroup.setOriginBlockPos(x, relativePosCubeGroup.getOriginBlockY(), relativePosCubeGroup.getOriginBlockZ()); - //}); - //DhApi.Delayed.renderRegister.add(relativePosCubeGroup); + // relative cube group + ArrayList relCubeList = new ArrayList<>(); + for (int i = 0; i < 8; i+=2) + { + relCubeList.add(new DhApiRenderableBox( + new Vec3f(0f,0f+i,0f), new Vec3f(1f,1f+i,1f), + new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); + } + IDhApiRenderableBoxGroup relativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( + 24f, 140f, 24f, + relCubeList); + AtomicInteger frameCount = new AtomicInteger(0); + relativePosCubeGroup.setPreRenderFunc((event) -> + { + float x = relativePosCubeGroup.getOriginBlockX(); + x += event.partialTicks / 2; + x %= 32; + relativePosCubeGroup.setOriginBlockPos(x, relativePosCubeGroup.getOriginBlockY(), relativePosCubeGroup.getOriginBlockZ()); + }); + DhApi.Delayed.renderRegister.add(relativePosCubeGroup); } private void createBuffers() @@ -318,6 +347,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister public void render(DhApiRenderParam renderEventParam) { + // render setup // + GLState glState = new GLState(); this.init(); @@ -328,38 +359,57 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GL32.glBlendEquation(GL32.GL_FUNC_ADD); GL32.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); - this.basicUnlitShader.bind(); + this.shader.bind(); this.va.bind(); this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId()); this.solidIndexBuffer.bind(); - LongSet keys = boxGroupById.keySet(); - for (long key : keys) - { - DhApiRenderableBoxGroup cubeGroup = boxGroupById.get(key); - this.renderCubeGroup(cubeGroup, renderEventParam); - } - - - this.basicUnlitShader.unbind(); - glState.restore(); - } - - private void renderCubeGroup(DhApiRenderableBoxGroup cubeGroup, DhApiRenderParam renderEventParam) - { Mat4f transformMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); transformMatrix.multiply(renderEventParam.dhModelViewMatrix); - Vec3d camPos = MC_RENDER.getCameraExactPosition(); - Vec3f camPosFloat = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z); + Vec3d camPosDouble = MC_RENDER.getCameraExactPosition(); + Vec3f camPos = new Vec3f((float) camPosDouble.x, (float) camPosDouble.y, (float) camPosDouble.z); + // rendering // + + LongSet keys = boxGroupById.keySet(); + for (long key : keys) + { + DhApiRenderableBoxGroup boxGroup = boxGroupById.get(key); + if (this.useInstancedRendering) + { + this.renderBoxGroupInstanced(boxGroup, renderEventParam, transformMatrix, camPos); + } + else + { + this.renderBoxGroupDirect(boxGroup, renderEventParam, transformMatrix, camPos); + } + } + + + + // clean up // + + this.shader.unbind(); + glState.restore(); + } + + + + //=====================// + // instanced rendering // + //=====================// + + private void renderBoxGroupInstanced(DhApiRenderableBoxGroup cubeGroup, + DhApiRenderParam renderEventParam, Mat4f transformMatrix, Vec3f camPos) + { // update instance data // cubeGroup.preRender(renderEventParam); - int boxCount = updateInstanceBuffers(camPosFloat, transformMatrix); // Update instance data + int boxCount = updateInstanceBuffers(camPos, transformMatrix); // Update instance data @@ -368,24 +418,23 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVBO); GL32.glEnableVertexAttribArray(1); GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0); - GL33.glVertexAttribDivisor(1, 1); + vertexAttribDivisor(1, 1); GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTransformVBO); GL32.glEnableVertexAttribArray(2); - GL33.glVertexAttribDivisor(2, 1); + vertexAttribDivisor(2, 1); GL32.glVertexAttribPointer(2, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 0); GL32.glEnableVertexAttribArray(3); - GL33.glVertexAttribDivisor(3, 1); + vertexAttribDivisor(3, 1); GL32.glVertexAttribPointer(3, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 16); GL32.glEnableVertexAttribArray(4); - GL33.glVertexAttribDivisor(4, 1); + vertexAttribDivisor(4, 1); GL32.glVertexAttribPointer(4, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 32); GL32.glEnableVertexAttribArray(5); - GL33.glVertexAttribDivisor(5, 1); + vertexAttribDivisor(5, 1); GL32.glVertexAttribPointer(5, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 48); - // Draw instanced GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxCount); @@ -397,6 +446,26 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GL32.glDisableVertexAttribArray(4); GL32.glDisableVertexAttribArray(5); } + /** + * Clean way to handle both {@link GL33#glVertexAttribDivisor} and {@link ARBInstancedArrays#glVertexAttribDivisorARB} + * based on which one is supported. + */ + private void vertexAttribDivisor(int index, int divisor) + { + if (this.vertexAttribDivisorSupported) + { + GL33.glVertexAttribDivisor(index, divisor); + } + else if(this.instancedArraysSupported) + { + ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor); + } + else + { + throw new IllegalStateException("Instanced rendering isn't supported by this machine. Direct rendering should have been used instead."); + } + } + private int updateInstanceBuffers(Vec3f camPos, Mat4f transformationMatrix) { int boxCount = 0; @@ -481,6 +550,50 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister + //==================// + // direct rendering // + //==================// + + private void renderBoxGroupDirect(DhApiRenderableBoxGroup cubeGroup, + DhApiRenderParam renderEventParam, Mat4f transformMatrix, Vec3f camPos) + { + cubeGroup.preRender(renderEventParam); + for (DhApiRenderableBox box : cubeGroup.cubeList) + { + renderBox(cubeGroup, box, transformMatrix, camPos); + } + } + private void renderBox( + DhApiRenderableBoxGroup cubeGroup, DhApiRenderableBox cube, + Mat4f transformationMatrix, Vec3f camPos) + { + float originOffsetX = 0; + float originOffsetY = 0; + float originOffsetZ = 0; + if (cubeGroup.positionCubesRelativeToGroupOrigin) + { + originOffsetX = cubeGroup.originBlockX; + originOffsetY = cubeGroup.originBlockY; + originOffsetZ = cubeGroup.originBlockZ; + } + + Mat4f boxTransform = Mat4f.createTranslateMatrix( + cube.minPos.x + originOffsetX - camPos.x, + cube.minPos.y + originOffsetY - camPos.y, + cube.minPos.z + originOffsetZ - camPos.z); + boxTransform.multiply(Mat4f.createScaleMatrix( + cube.maxPos.x - cube.minPos.x, + cube.maxPos.y - cube.minPos.y, + cube.maxPos.z - cube.minPos.z)); + Mat4f transformMatrix = transformationMatrix.copy(); + transformMatrix.multiply(boxTransform); + this.shader.setUniform(this.shader.getUniformLocation("transform"), transformMatrix); + + this.shader.setUniform(this.shader.getUniformLocation("uColor"), cube.color); + + GL32.glDrawElements(GL32.GL_TRIANGLES , SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); + } + //================// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java index 5f95bb689..a9a8f9693 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java @@ -102,7 +102,7 @@ public class LodRenderProgram extends ShaderProgram implements IDhApiShaderProgr // TODO: Add better use of the LODFormat thing int vertexByteCount = LodUtil.LOD_VERTEX_FORMAT.getByteSize(); - if (GLProxy.getInstance().VertexAttributeBufferBindingSupported) + if (GLProxy.getInstance().vertexAttributeBufferBindingSupported) vao = new VertexAttributePostGL43(); // also binds AbstractVertexAttribute else vao = new VertexAttributePreGL43(); // also binds AbstractVertexAttribute diff --git a/core/src/main/resources/shaders/genericObject/direct/frag.frag b/core/src/main/resources/shaders/genericObject/direct/frag.frag new file mode 100644 index 000000000..1f22d751c --- /dev/null +++ b/core/src/main/resources/shaders/genericObject/direct/frag.frag @@ -0,0 +1,9 @@ +#version 150 core + +uniform vec4 uColor; +out vec4 fragColor; + +void main() +{ + fragColor = uColor; +} \ No newline at end of file diff --git a/core/src/main/resources/shaders/genericObject/direct/vert.vert b/core/src/main/resources/shaders/genericObject/direct/vert.vert new file mode 100644 index 000000000..e32ec6e80 --- /dev/null +++ b/core/src/main/resources/shaders/genericObject/direct/vert.vert @@ -0,0 +1,10 @@ +#version 150 core + +uniform mat4 transform; + +in vec3 vPosition; + +void main() +{ + gl_Position = transform * vec4(vPosition, 1.0); +} \ No newline at end of file diff --git a/core/src/main/resources/shaders/genericObject/frag.frag b/core/src/main/resources/shaders/genericObject/instanced/frag.frag similarity index 100% rename from core/src/main/resources/shaders/genericObject/frag.frag rename to core/src/main/resources/shaders/genericObject/instanced/frag.frag diff --git a/core/src/main/resources/shaders/genericObject/vert.vert b/core/src/main/resources/shaders/genericObject/instanced/vert.vert similarity index 100% rename from core/src/main/resources/shaders/genericObject/vert.vert rename to core/src/main/resources/shaders/genericObject/instanced/vert.vert From bf1361c7c3120da5e0044951529509f714ac4e8d Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 29 Jun 2024 10:34:58 -0600 Subject: [PATCH 008/104] GenericObjectRenderer forgot cached uniform location --- .../core/render/renderer/GenericObjectRenderer.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 2ee336f4e..06babd03c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -27,7 +27,6 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegist import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.render.glObject.GLProxy; @@ -587,9 +586,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister cube.maxPos.z - cube.minPos.z)); Mat4f transformMatrix = transformationMatrix.copy(); transformMatrix.multiply(boxTransform); - this.shader.setUniform(this.shader.getUniformLocation("transform"), transformMatrix); + this.shader.setUniform(this.transformUniformLocation, transformMatrix); - this.shader.setUniform(this.shader.getUniformLocation("uColor"), cube.color); + this.shader.setUniform(this.directShaderColorUniformLocation, cube.color); GL32.glDrawElements(GL32.GL_TRIANGLES , SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } From 2c71d97c154e7f11144bf0845a704812108d9c1a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 29 Jun 2024 11:00:53 -0600 Subject: [PATCH 009/104] fix instanced generic duplicate rendering --- .../renderer/GenericObjectRenderer.java | 100 +++++++----------- .../shaders/genericObject/direct/vert.vert | 4 +- .../shaders/genericObject/instanced/vert.vert | 4 +- 3 files changed, 44 insertions(+), 64 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 06babd03c..c89d385d8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -92,9 +92,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private int instanceColorVBO; // shader uniforms - private int transformUniformLocation; + private int directShaderTransformUniformLocation; private int directShaderColorUniformLocation; + private int instancedShaderOriginOffsetUniformLocation; + // TODO may need to be double buffered to prevent rendering lag private final Long2ReferenceOpenHashMap boxGroupById = new Long2ReferenceOpenHashMap<>(); @@ -174,9 +176,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.useInstancedRendering ? "shaders/genericObject/instanced/frag.frag" : "shaders/genericObject/direct/frag.frag", "fragColor", new String[]{"vPosition"}); - this.transformUniformLocation = this.shader.tryGetUniformLocation("transform"); + this.directShaderTransformUniformLocation = this.shader.tryGetUniformLocation("uTransform"); this.directShaderColorUniformLocation = this.shader.tryGetUniformLocation("uColor"); + this.instancedShaderOriginOffsetUniformLocation = this.shader.tryGetUniformLocation("uOriginOffset"); + this.createBuffers(); @@ -221,7 +225,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister IDhApiRenderableBoxGroup relativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( 24f, 140f, 24f, relCubeList); - AtomicInteger frameCount = new AtomicInteger(0); relativePosCubeGroup.setPreRenderFunc((event) -> { float x = relativePosCubeGroup.getOriginBlockX(); @@ -408,7 +411,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // update instance data // cubeGroup.preRender(renderEventParam); - int boxCount = updateInstanceBuffers(camPos, transformMatrix); // Update instance data + int boxCount = updateCubeGroupInstanceBuffers(cubeGroup, camPos, transformMatrix); // Update instance data + + this.shader.setUniform(this.instancedShaderOriginOffsetUniformLocation, new Vec3f(cubeGroup.originBlockX, cubeGroup.originBlockY, cubeGroup.originBlockZ)); + @@ -465,55 +471,32 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } } - private int updateInstanceBuffers(Vec3f camPos, Mat4f transformationMatrix) + private int updateCubeGroupInstanceBuffers(DhApiRenderableBoxGroup cubeGroup, Vec3f camPos, Mat4f transformationMatrix) { - int boxCount = 0; - LongSet keys = boxGroupById.keySet(); - for (long key : keys) - { - DhApiRenderableBoxGroup cubeGroup = boxGroupById.get(key); - boxCount += cubeGroup.size(); - } + int boxCount = cubeGroup.size(); // Prepare transformation matrices float[] transformationData = new float[boxCount * 16]; - int cubeIndex = 0; - for (long key : keys) + for (int i = 0; i < cubeGroup.size(); i++) { - DhApiRenderableBoxGroup cubeGroup = boxGroupById.get(key); - for (DhApiRenderableBox cube : cubeGroup) - { - float originOffsetX = 0; - float originOffsetY = 0; - float originOffsetZ = 0; - if (cubeGroup.positionCubesRelativeToGroupOrigin) - { - originOffsetX = cubeGroup.originBlockX; - originOffsetY = cubeGroup.originBlockY; - originOffsetZ = cubeGroup.originBlockZ; - } - - Mat4f boxTransform = Mat4f.createTranslateMatrix( - cube.minPos.x + originOffsetX - camPos.x, - cube.minPos.y + originOffsetY - camPos.y, - cube.minPos.z + originOffsetZ - camPos.z); - boxTransform.multiply(Mat4f.createScaleMatrix( - cube.maxPos.x - cube.minPos.x, - cube.maxPos.y - cube.minPos.y, - cube.maxPos.z - cube.minPos.z)); - Mat4f transformMatrix = transformationMatrix.copy(); - transformMatrix.multiply(boxTransform); - // TODO transformation matrix could be passed on to shader, only box offset needed here - //this.basicUnlitShader.setUniform(this.basicUnlitShader.getUniformLocation("transform"), transformMatrix); - - // due to how the matrix is being read in by GL, we need to transpose it - // (This is probably a bug due to how James set up the vertex array attributes) - transformMatrix.transpose(); - System.arraycopy(transformMatrix.getValuesAsArray(), 0, transformationData, cubeIndex * 16, 16); - - cubeIndex++; - } + DhApiRenderableBox cube = cubeGroup.get(i); + + Mat4f boxTransform = Mat4f.createTranslateMatrix( + cube.minPos.x - camPos.x, + cube.minPos.y - camPos.y, + cube.minPos.z - camPos.z); + boxTransform.multiply(Mat4f.createScaleMatrix( + cube.maxPos.x - cube.minPos.x, + cube.maxPos.y - cube.minPos.y, + cube.maxPos.z - cube.minPos.z)); + Mat4f transformMatrix = transformationMatrix.copy(); + transformMatrix.multiply(boxTransform); + + // due to how the matrix is being read in by GL, we need to transpose it + // (This is probably a bug due to how James set up the vertex array attributes) + transformMatrix.transpose(); + System.arraycopy(transformMatrix.getValuesAsArray(), 0, transformationData, i * 16, 16); } // Upload transformation matrices @@ -524,20 +507,15 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // Prepare colors float[] colors = new float[boxCount * 4]; - cubeIndex = 0; - for (long key : keys) + for (int i = 0; i < cubeGroup.size(); i++) { - DhApiRenderableBoxGroup cubeGroup = boxGroupById.get(key); - for (DhApiRenderableBox cube : cubeGroup) - { - Color color = cube.color; - colors[cubeIndex * 4] = color.getRed() / 255.0f; - colors[cubeIndex * 4 + 1] = color.getGreen() / 255.0f; - colors[cubeIndex * 4 + 2] = color.getBlue() / 255.0f; - colors[cubeIndex * 4 + 3] = color.getAlpha() / 255.0f; - - cubeIndex++; - } + DhApiRenderableBox cube = cubeGroup.get(i); + Color color = cube.color; + int colorIndex = i * 4; + colors[colorIndex] = color.getRed() / 255.0f; + colors[colorIndex + 1] = color.getGreen() / 255.0f; + colors[colorIndex + 2] = color.getBlue() / 255.0f; + colors[colorIndex + 3] = color.getAlpha() / 255.0f; } // Upload colors @@ -586,7 +564,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister cube.maxPos.z - cube.minPos.z)); Mat4f transformMatrix = transformationMatrix.copy(); transformMatrix.multiply(boxTransform); - this.shader.setUniform(this.transformUniformLocation, transformMatrix); + this.shader.setUniform(this.directShaderTransformUniformLocation, transformMatrix); this.shader.setUniform(this.directShaderColorUniformLocation, cube.color); diff --git a/core/src/main/resources/shaders/genericObject/direct/vert.vert b/core/src/main/resources/shaders/genericObject/direct/vert.vert index e32ec6e80..befc43200 100644 --- a/core/src/main/resources/shaders/genericObject/direct/vert.vert +++ b/core/src/main/resources/shaders/genericObject/direct/vert.vert @@ -1,10 +1,10 @@ #version 150 core -uniform mat4 transform; +uniform mat4 uTransform; in vec3 vPosition; void main() { - gl_Position = transform * vec4(vPosition, 1.0); + gl_Position = uTransform * vec4(vPosition, 1.0); } \ No newline at end of file diff --git a/core/src/main/resources/shaders/genericObject/instanced/vert.vert b/core/src/main/resources/shaders/genericObject/instanced/vert.vert index 7774dd406..33491329e 100644 --- a/core/src/main/resources/shaders/genericObject/instanced/vert.vert +++ b/core/src/main/resources/shaders/genericObject/instanced/vert.vert @@ -3,12 +3,14 @@ layout (location = 1) in vec4 aColor; layout (location = 2) in mat4 aTransform; +uniform vec3 uOriginOffset; + in vec3 vPosition; out vec4 fColor; void main() { - gl_Position = aTransform * vec4(vPosition, 1.0); + gl_Position = aTransform * vec4(vPosition + uOriginOffset, 1.0); fColor = aColor; } \ No newline at end of file From db786290e8714f648387850d9cd0d1796dc70d3e Mon Sep 17 00:00:00 2001 From: yeshi Date: Sat, 29 Jun 2024 21:56:38 +0200 Subject: [PATCH 010/104] tell user to restart the game if the renderer dies --- .../com/seibel/distanthorizons/core/api/internal/ClientApi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index 4682c9de0..26aa8da32 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -584,6 +584,7 @@ public class ClientApi MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!"); MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues."); + MC.sendChatMessage("\u00A74Please restart your game to re-enable Distant Horizons' LOD rendering."); MC.sendChatMessage("\u00A74Exception detail: " + e); } finally From 7f8b5579c514e86b5a88a2a614ed1f93005a8b35 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 09:25:12 -0500 Subject: [PATCH 011/104] Add generic rendering profilers and move some vertex attribs to uniforms --- .../renderer/GenericObjectRenderer.java | 148 ++++++++++++------ .../core/render/renderer/LodRenderer.java | 2 +- .../shaders/genericObject/instanced/vert.vert | 28 +++- 3 files changed, 127 insertions(+), 51 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index c89d385d8..a0036e6c9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -37,6 +37,7 @@ import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute; import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.coreapi.util.math.Vec3d; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; @@ -88,14 +89,17 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // instance data - private int instanceTransformVBO; + private int instanceTranslateVBO; + private int instanceScaleVBO; private int instanceColorVBO; // shader uniforms private int directShaderTransformUniformLocation; private int directShaderColorUniformLocation; - private int instancedShaderOriginOffsetUniformLocation; + private int instancedShaderOffsetUniformLocation; + private int instancedShaderCameraPosUniformLocation; + private int instancedShaderProjectionModelViewMatrixUniformLocation; // TODO may need to be double buffered to prevent rendering lag @@ -179,7 +183,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.directShaderTransformUniformLocation = this.shader.tryGetUniformLocation("uTransform"); this.directShaderColorUniformLocation = this.shader.tryGetUniformLocation("uColor"); - this.instancedShaderOriginOffsetUniformLocation = this.shader.tryGetUniformLocation("uOriginOffset"); + this.instancedShaderOffsetUniformLocation = this.shader.tryGetUniformLocation("uOffset"); + this.instancedShaderCameraPosUniformLocation = this.shader.tryGetUniformLocation("uCameraPos"); + this.instancedShaderProjectionModelViewMatrixUniformLocation = this.shader.tryGetUniformLocation("uProjectionMvm"); this.createBuffers(); @@ -234,6 +240,36 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister }); DhApi.Delayed.renderRegister.add(relativePosCubeGroup); + + + + // massive relative cube group + ArrayList massRelCubeList = new ArrayList<>(); + for (int x = 0; x < 40*2; x+=2) + { + for (int z = 0; z < 40*2; z+=2) + { + massRelCubeList.add(new DhApiRenderableBox( + new Vec3f(0f-x, 0f, 0f-z), new Vec3f(1f-x, 1f, 1f-z), + new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()))); + } + } + IDhApiRenderableBoxGroup massRelativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( + -25f, 140f, 0f, + massRelCubeList); + massRelativePosCubeGroup.setPreRenderFunc((event) -> + { + float y = massRelativePosCubeGroup.getOriginBlockY(); + y += event.partialTicks / 4; + if (y > 150f) + { + y = 140f; + } + massRelativePosCubeGroup.setOriginBlockPos(massRelativePosCubeGroup.getOriginBlockX(), y, massRelativePosCubeGroup.getOriginBlockZ()); + }); + DhApi.Delayed.renderRegister.add(massRelativePosCubeGroup); + + } private void createBuffers() { @@ -258,7 +294,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // instance buffers - this.instanceTransformVBO = GL32.glGenBuffers(); + this.instanceTranslateVBO = GL32.glGenBuffers(); + this.instanceScaleVBO = GL32.glGenBuffers(); this.instanceColorVBO = GL32.glGenBuffers(); } @@ -273,7 +310,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { ArrayList list = new ArrayList<>(); list.add(box); - return new DhApiRenderableBoxGroup(0, 0, 0, list, false); + return this.createAbsolutePositionedGroup(list); } @Override @@ -347,9 +384,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // rendering // //===========// - public void render(DhApiRenderParam renderEventParam) + public void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) { // render setup // + profiler.push("setup"); GLState glState = new GLState(); this.init(); @@ -367,8 +405,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.solidIndexBuffer.bind(); - Mat4f transformMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); - transformMatrix.multiply(renderEventParam.dhModelViewMatrix); + Mat4f projectionMvmMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); + projectionMvmMatrix.multiply(renderEventParam.dhModelViewMatrix); Vec3d camPosDouble = MC_RENDER.getCameraExactPosition(); Vec3f camPos = new Vec3f((float) camPosDouble.x, (float) camPosDouble.y, (float) camPosDouble.z); @@ -377,26 +415,38 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // rendering // + LongSet keys = boxGroupById.keySet(); for (long key : keys) { + profiler.popPush("render prep"); + DhApiRenderableBoxGroup boxGroup = boxGroupById.get(key); + boxGroup.preRender(renderEventParam); + if (this.useInstancedRendering) { - this.renderBoxGroupInstanced(boxGroup, renderEventParam, transformMatrix, camPos); + updateCubeGroupInstanceBuffers(boxGroup, camPos, projectionMvmMatrix); + + profiler.popPush("rendering"); + this.renderBoxGroupInstanced(boxGroup, camPos, projectionMvmMatrix); } else { - this.renderBoxGroupDirect(boxGroup, renderEventParam, transformMatrix, camPos); + profiler.popPush("rendering"); + this.renderBoxGroupDirect(boxGroup, projectionMvmMatrix, camPos); } } // clean up // + profiler.popPush("cleanup"); this.shader.unbind(); glState.restore(); + + profiler.pop(); } @@ -405,15 +455,26 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // instanced rendering // //=====================// - private void renderBoxGroupInstanced(DhApiRenderableBoxGroup cubeGroup, - DhApiRenderParam renderEventParam, Mat4f transformMatrix, Vec3f camPos) + private void renderBoxGroupInstanced(DhApiRenderableBoxGroup cubeGroup, Vec3f camPos, Mat4f projectionMvmMatrix) { // update instance data // - cubeGroup.preRender(renderEventParam); - int boxCount = updateCubeGroupInstanceBuffers(cubeGroup, camPos, transformMatrix); // Update instance data + this.shader.setUniform(this.instancedShaderOffsetUniformLocation, + new Vec3f( + cubeGroup.originBlockX, + cubeGroup.originBlockY, + cubeGroup.originBlockZ + )); - this.shader.setUniform(this.instancedShaderOriginOffsetUniformLocation, new Vec3f(cubeGroup.originBlockX, cubeGroup.originBlockY, cubeGroup.originBlockZ)); + this.shader.setUniform(this.instancedShaderCameraPosUniformLocation, + new Vec3f( + camPos.x, + camPos.y, + camPos.z + )); + + this.shader.setUniform(this.instancedShaderProjectionModelViewMatrixUniformLocation, + projectionMvmMatrix); @@ -425,23 +486,19 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0); vertexAttribDivisor(1, 1); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTransformVBO); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslateVBO); GL32.glEnableVertexAttribArray(2); vertexAttribDivisor(2, 1); - GL32.glVertexAttribPointer(2, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 0); + GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); + + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVBO); GL32.glEnableVertexAttribArray(3); vertexAttribDivisor(3, 1); - GL32.glVertexAttribPointer(3, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 16); - GL32.glEnableVertexAttribArray(4); - vertexAttribDivisor(4, 1); - GL32.glVertexAttribPointer(4, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 32); - GL32.glEnableVertexAttribArray(5); - vertexAttribDivisor(5, 1); - GL32.glVertexAttribPointer(5, 4, GL32.GL_FLOAT, false, 16 * Float.BYTES, 48); + GL32.glVertexAttribPointer(3, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); // Draw instanced - GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxCount); + GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, cubeGroup.size()); // Clean up @@ -471,37 +528,38 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } } - private int updateCubeGroupInstanceBuffers(DhApiRenderableBoxGroup cubeGroup, Vec3f camPos, Mat4f transformationMatrix) + private void updateCubeGroupInstanceBuffers(DhApiRenderableBoxGroup cubeGroup, Vec3f camPos, Mat4f projectionMvmMatrix) { int boxCount = cubeGroup.size(); // Prepare transformation matrices - float[] transformationData = new float[boxCount * 16]; + float[] translateData = new float[boxCount * 3]; + float[] scaleData = new float[boxCount * 3]; for (int i = 0; i < cubeGroup.size(); i++) { DhApiRenderableBox cube = cubeGroup.get(i); - Mat4f boxTransform = Mat4f.createTranslateMatrix( - cube.minPos.x - camPos.x, - cube.minPos.y - camPos.y, - cube.minPos.z - camPos.z); - boxTransform.multiply(Mat4f.createScaleMatrix( + System.arraycopy(new float[] + { + cube.minPos.x, + cube.minPos.y, + cube.minPos.z + }, 0, translateData, i * 3, 3); + + System.arraycopy(new float[] + { cube.maxPos.x - cube.minPos.x, cube.maxPos.y - cube.minPos.y, - cube.maxPos.z - cube.minPos.z)); - Mat4f transformMatrix = transformationMatrix.copy(); - transformMatrix.multiply(boxTransform); - - // due to how the matrix is being read in by GL, we need to transpose it - // (This is probably a bug due to how James set up the vertex array attributes) - transformMatrix.transpose(); - System.arraycopy(transformMatrix.getValuesAsArray(), 0, transformationData, i * 16, 16); + cube.maxPos.z - cube.minPos.z + }, 0, scaleData, i * 3, 3); } // Upload transformation matrices - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTransformVBO); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, transformationData, GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslateVBO); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translateData, GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVBO); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scaleData, GL32.GL_DYNAMIC_DRAW); @@ -521,8 +579,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // Upload colors GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVBO); GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colors, GL32.GL_DYNAMIC_DRAW); - - return boxCount; } @@ -531,10 +587,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // direct rendering // //==================// - private void renderBoxGroupDirect(DhApiRenderableBoxGroup cubeGroup, - DhApiRenderParam renderEventParam, Mat4f transformMatrix, Vec3f camPos) + private void renderBoxGroupDirect(DhApiRenderableBoxGroup cubeGroup, Mat4f transformMatrix, Vec3f camPos) { - cubeGroup.preRender(renderEventParam); for (DhApiRenderableBox box : cubeGroup.cubeList) { renderBox(cubeGroup, box, transformMatrix, camPos); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 8e6c3f148..6a89ef21f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -422,7 +422,7 @@ public class LodRenderer } profiler.popPush("Custom Objects"); - GenericObjectRenderer.INSTANCE.render(renderEventParam); + GenericObjectRenderer.INSTANCE.render(renderEventParam, profiler); profiler.popPush("LOD cleanup"); diff --git a/core/src/main/resources/shaders/genericObject/instanced/vert.vert b/core/src/main/resources/shaders/genericObject/instanced/vert.vert index 33491329e..0849e9f7c 100644 --- a/core/src/main/resources/shaders/genericObject/instanced/vert.vert +++ b/core/src/main/resources/shaders/genericObject/instanced/vert.vert @@ -1,9 +1,12 @@ #version 330 core layout (location = 1) in vec4 aColor; -layout (location = 2) in mat4 aTransform; +layout (location = 2) in vec3 aTranslate; +layout (location = 3) in vec3 aScale; -uniform vec3 uOriginOffset; +uniform vec3 uOffset; +uniform vec3 uCameraPos; +uniform mat4 uProjectionMvm; in vec3 vPosition; @@ -11,6 +14,25 @@ out vec4 fColor; void main() { - gl_Position = aTransform * vec4(vPosition + uOriginOffset, 1.0); + // aTranslate - moves the vertex to the boxGroup's relative position + // uOffset - moves the vertex to the boxGroup's position + // uCameraPos - moves the vertex into camera space + float transX = aTranslate.x + uOffset.x - uCameraPos.x; + float transY = aTranslate.y + uOffset.y - uCameraPos.y; + float transZ = aTranslate.z + uOffset.z - uCameraPos.z; + + float scaleX = aScale.x; + float scaleY = aScale.y; + float scaleZ = aScale.z; + + // combination translation and scaling matrix + mat4 transform = mat4( + scaleX, 0.0, 0.0, 0.0, + 0.0, scaleY, 0.0, 0.0, + 0.0, 0.0, scaleZ, 0.0, + transX, transY, transZ, 1.0 + ); + + gl_Position = uProjectionMvm * transform * vec4(vPosition, 1.0); fColor = aColor; } \ No newline at end of file From f282d78fb9f1963f312c117770cf95b06836416e Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 09:31:45 -0500 Subject: [PATCH 012/104] minor generic obj cleanup --- .../renderer/GenericObjectRenderer.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index a0036e6c9..9349ef18b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -538,21 +538,18 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister float[] scaleData = new float[boxCount * 3]; for (int i = 0; i < cubeGroup.size(); i++) { - DhApiRenderableBox cube = cubeGroup.get(i); + DhApiRenderableBox box = cubeGroup.get(i); - System.arraycopy(new float[] - { - cube.minPos.x, - cube.minPos.y, - cube.minPos.z - }, 0, translateData, i * 3, 3); + int dataIndex = i * 3; + + translateData[dataIndex] = box.minPos.x; + translateData[dataIndex + 1] = box.minPos.y; + translateData[dataIndex + 2] = box.minPos.z; + + scaleData[dataIndex] = box.maxPos.x - box.minPos.x; + scaleData[dataIndex + 1] = box.maxPos.y - box.minPos.y; + scaleData[dataIndex + 2] = box.maxPos.z - box.minPos.z; - System.arraycopy(new float[] - { - cube.maxPos.x - cube.minPos.x, - cube.maxPos.y - cube.minPos.y, - cube.maxPos.z - cube.minPos.z - }, 0, scaleData, i * 3, 3); } // Upload transformation matrices From 28c86145507aa84d95a4e081a29b2b94e87b4eaf Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 13:46:03 -0500 Subject: [PATCH 013/104] Store generic object instance VBOs if possible --- .../renderer/GenericObjectRenderer.java | 217 +++++++++++------- 1 file changed, 137 insertions(+), 80 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 9349ef18b..2302915ac 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -51,13 +51,12 @@ import org.lwjgl.opengl.GL33; import javax.annotation.Nullable; import java.awt.*; +import java.io.Closeable; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Comparator; +import java.util.*; import java.util.List; -import java.util.Spliterator; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; @@ -88,11 +87,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private boolean instancedArraysSupported; - // instance data - private int instanceTranslateVBO; - private int instanceScaleVBO; - private int instanceColorVBO; - // shader uniforms private int directShaderTransformUniformLocation; private int directShaderColorUniformLocation; @@ -245,9 +239,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // massive relative cube group ArrayList massRelCubeList = new ArrayList<>(); - for (int x = 0; x < 40*2; x+=2) + for (int x = 0; x < 50*2; x+=2) { - for (int z = 0; z < 40*2; z+=2) + for (int z = 0; z < 50*2; z+=2) { massRelCubeList.add(new DhApiRenderableBox( new Vec3f(0f-x, 0f, 0f-z), new Vec3f(1f-x, 1f, 1f-z), @@ -292,11 +286,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); this.solidIndexBuffer.bind(); - - // instance buffers - this.instanceTranslateVBO = GL32.glGenBuffers(); - this.instanceScaleVBO = GL32.glGenBuffers(); - this.instanceColorVBO = GL32.glGenBuffers(); } @@ -328,8 +317,15 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister //==============// @Override - public void add(IDhApiRenderableBoxGroup boxGroup) throws IllegalArgumentException + public void add(IDhApiRenderableBoxGroup iBoxGroup) throws IllegalArgumentException { + if (!(iBoxGroup instanceof DhApiRenderableBoxGroup)) + { + throw new IllegalArgumentException("Box group must be of type ["+DhApiRenderableBoxGroup.class.getSimpleName()+"]."); + } + DhApiRenderableBoxGroup boxGroup = (DhApiRenderableBoxGroup) iBoxGroup; + + try { mapModifyLock.lock(); @@ -337,10 +333,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister long id = boxGroup.getId(); if (this.boxGroupById.containsKey(id)) { - throw new IllegalArgumentException("A cube group with the ID [" + id + "] is already present."); + throw new IllegalArgumentException("A box group with the ID [" + id + "] is already present."); } - this.boxGroupById.put(id, (DhApiRenderableBoxGroup) boxGroup); + this.boxGroupById.put(id, boxGroup); // TODO add to DB async? } @@ -426,8 +422,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister if (this.useInstancedRendering) { - updateCubeGroupInstanceBuffers(boxGroup, camPos, projectionMvmMatrix); - profiler.popPush("rendering"); this.renderBoxGroupInstanced(boxGroup, camPos, projectionMvmMatrix); } @@ -455,15 +449,17 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // instanced rendering // //=====================// - private void renderBoxGroupInstanced(DhApiRenderableBoxGroup cubeGroup, Vec3f camPos, Mat4f projectionMvmMatrix) + private void renderBoxGroupInstanced(DhApiRenderableBoxGroup boxGroup, Vec3f camPos, Mat4f projectionMvmMatrix) { // update instance data // + boxGroup.updateVertexAttributeData(); + this.shader.setUniform(this.instancedShaderOffsetUniformLocation, new Vec3f( - cubeGroup.originBlockX, - cubeGroup.originBlockY, - cubeGroup.originBlockZ + boxGroup.originBlockX, + boxGroup.originBlockY, + boxGroup.originBlockZ )); this.shader.setUniform(this.instancedShaderCameraPosUniformLocation, @@ -481,24 +477,24 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // Bind instance data // - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVBO); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceColorVbo); GL32.glEnableVertexAttribArray(1); GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0); vertexAttribDivisor(1, 1); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslateVBO); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceTranslationVbo); GL32.glEnableVertexAttribArray(2); vertexAttribDivisor(2, 1); GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVBO); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceScaleVbo); GL32.glEnableVertexAttribArray(3); vertexAttribDivisor(3, 1); GL32.glVertexAttribPointer(3, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); // Draw instanced - GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, cubeGroup.size()); + GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxGroup.size()); // Clean up @@ -528,55 +524,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } } - private void updateCubeGroupInstanceBuffers(DhApiRenderableBoxGroup cubeGroup, Vec3f camPos, Mat4f projectionMvmMatrix) - { - int boxCount = cubeGroup.size(); - - - // Prepare transformation matrices - float[] translateData = new float[boxCount * 3]; - float[] scaleData = new float[boxCount * 3]; - for (int i = 0; i < cubeGroup.size(); i++) - { - DhApiRenderableBox box = cubeGroup.get(i); - - int dataIndex = i * 3; - - translateData[dataIndex] = box.minPos.x; - translateData[dataIndex + 1] = box.minPos.y; - translateData[dataIndex + 2] = box.minPos.z; - - scaleData[dataIndex] = box.maxPos.x - box.minPos.x; - scaleData[dataIndex + 1] = box.maxPos.y - box.minPos.y; - scaleData[dataIndex + 2] = box.maxPos.z - box.minPos.z; - - } - - // Upload transformation matrices - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslateVBO); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translateData, GL32.GL_DYNAMIC_DRAW); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVBO); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scaleData, GL32.GL_DYNAMIC_DRAW); - - - - // Prepare colors - float[] colors = new float[boxCount * 4]; - for (int i = 0; i < cubeGroup.size(); i++) - { - DhApiRenderableBox cube = cubeGroup.get(i); - Color color = cube.color; - int colorIndex = i * 4; - colors[colorIndex] = color.getRed() / 255.0f; - colors[colorIndex + 1] = color.getGreen() / 255.0f; - colors[colorIndex + 2] = color.getBlue() / 255.0f; - colors[colorIndex + 3] = color.getAlpha() / 255.0f; - } - - // Upload colors - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVBO); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colors, GL32.GL_DYNAMIC_DRAW); - } @@ -619,7 +566,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.shader.setUniform(this.directShaderColorUniformLocation, cube.color); - GL32.glDrawElements(GL32.GL_TRIANGLES , SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); + GL32.glDrawElements(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } @@ -628,10 +575,14 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // helper classes // //================// - private static final class DhApiRenderableBoxGroup extends AbstractList implements IDhApiRenderableBoxGroup + private static final class DhApiRenderableBoxGroup + extends AbstractList + implements IDhApiRenderableBoxGroup, Closeable { public final static AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0); + + public final long id; /** If false the cubes will be positioned relative to the level's origin */ @@ -646,6 +597,14 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister @Nullable public Consumer beforeRenderFunc; + private boolean vertexDataDirty = true; + + // instance data + private int instanceTranslationVbo = 0; + private int instanceScaleVbo = 0; + private int instanceColorVbo = 0; + + // setters/getters // @@ -727,6 +686,104 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister @Override public Stream parallelStream() { return this.cubeList.parallelStream(); } + + + //===================// + // vertex attributes // + //===================// + + private void updateVertexAttributeData() + { + if (!this.vertexDataDirty) + { + return; + } + this.vertexDataDirty = false; + + if (this.instanceTranslationVbo == 0) + { + this.instanceTranslationVbo = GL32.glGenBuffers(); + this.instanceScaleVbo = GL32.glGenBuffers(); + this.instanceColorVbo = GL32.glGenBuffers(); + } + + int boxCount = this.size(); + + + // transformation / scaling // + + float[] translationData = new float[boxCount * 3]; + float[] scalingData = new float[boxCount * 3]; + for (int i = 0; i < boxCount; i++) + { + DhApiRenderableBox box = this.get(i); + + int dataIndex = i * 3; + + translationData[dataIndex] = box.minPos.x; + translationData[dataIndex + 1] = box.minPos.y; + translationData[dataIndex + 2] = box.minPos.z; + + scalingData[dataIndex] = box.maxPos.x - box.minPos.x; + scalingData[dataIndex + 1] = box.maxPos.y - box.minPos.y; + scalingData[dataIndex + 2] = box.maxPos.z - box.minPos.z; + + } + + + // colors // + + float[] colorData = new float[boxCount * 4]; + for (int i = 0; i < boxCount; i++) + { + DhApiRenderableBox cube = this.get(i); + Color color = cube.color; + int colorIndex = i * 4; + colorData[colorIndex] = color.getRed() / 255.0f; + colorData[colorIndex + 1] = color.getGreen() / 255.0f; + colorData[colorIndex + 2] = color.getBlue() / 255.0f; + colorData[colorIndex + 3] = color.getAlpha() / 255.0f; + } + + + // Upload transformation matrices + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslationVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translationData ,GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW); + + // Upload colors + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW); + } + + + + @Override + public void close() + { + GLProxy.getInstance().queueRunningOnRenderThread(() -> + { + if (this.instanceTranslationVbo != 0) + { + GL32.glDeleteBuffers(this.instanceTranslationVbo); + this.instanceTranslationVbo = 0; + } + + if (this.instanceScaleVbo != 0) + { + GL32.glDeleteBuffers(this.instanceScaleVbo); + this.instanceScaleVbo = 0; + } + + if (this.instanceColorVbo != 0) + { + GL32.glDeleteBuffers(this.instanceColorVbo); + this.instanceColorVbo = 0; + } + }); + } + } } From 305a6bb459a780b814919e25272087f5562847d6 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 14:02:44 -0500 Subject: [PATCH 014/104] Improve generic rendering pos objects --- .../render/IDhApiCustomRenderRegister.java | 3 +- .../render/IDhApiRenderableBoxGroup.java | 7 +- .../api/objects/math/DhApiVec3f.java | 93 +++++++++++++++++++ .../coreapi/util/math/Vec3f.java | 10 ++ .../renderer/GenericObjectRenderer.java | 65 ++++++------- 5 files changed, 137 insertions(+), 41 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3f.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java index 0f3ef03a8..1dfff0a29 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.api.interfaces.render; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import java.util.List; @@ -12,7 +13,7 @@ public interface IDhApiCustomRenderRegister IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube); - IDhApiRenderableBoxGroup createRelativePositionedGroup(float originBlockX, float originBlockY, float originBlockZ, List cubeList); + IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList); IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList); } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java index 2ecd2e900..b37b43a4c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -1,6 +1,7 @@ package com.seibel.distanthorizons.api.interfaces.render; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import java.util.List; @@ -11,10 +12,8 @@ public interface IDhApiRenderableBoxGroup extends List long getId(); - void setOriginBlockPos(float x, float y, float z); - float getOriginBlockX(); - float getOriginBlockY(); - float getOriginBlockZ(); + void setOriginBlockPos(DhApiVec3f pos); + DhApiVec3f getOriginBlockPos(); void setPreRenderFunc(Consumer renderEventParam); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3f.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3f.java new file mode 100644 index 000000000..5fa60d8d1 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3f.java @@ -0,0 +1,93 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.objects.math; + +/** + * Often used to store block positions or any other + * position in 3D space. + * + * @author James Seibel + * @version 2024-6-3 + * @since API 2.2.0 + */ +public class DhApiVec3f +{ + public float x; + public float y; + public float z; + + + + /** creates a Vec3 at (0,0,0) */ + public DhApiVec3f() + { + this.x = 0; + this.y = 0; + this.z = 0; + } + + public DhApiVec3f(float x, float y, float z) + { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + else if (obj != null && this.getClass() == obj.getClass()) + { + DhApiVec3f Vec3f = (DhApiVec3f) obj; + if (Float.compare(Vec3f.x, this.x) != 0) + { + return false; + } + else if (Float.compare(Vec3f.y, this.y) != 0) + { + return false; + } + else + { + return Float.compare(Vec3f.z, this.z) == 0; + } + } + else + { + return false; + } + } + + @Override + public int hashCode() + { + int i = Float.floatToIntBits(this.x); + i = 31 * i + Float.floatToIntBits(this.y); + return 31 * i + Float.floatToIntBits(this.z); + } + + @Override + public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; } + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java index b45ba98be..50488535a 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.coreapi.util.math; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.coreapi.util.MathUtil; /** @@ -56,6 +57,15 @@ public class Vec3f this.z = z; } + public Vec3f(DhApiVec3f pos) + { + this.x = pos.x; + this.y = pos.y; + this.z = pos.z; + } + + + @Override public boolean equals(Object obj) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 2302915ac..d5383a64b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -25,6 +25,7 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; @@ -223,14 +224,14 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); } IDhApiRenderableBoxGroup relativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( - 24f, 140f, 24f, + new DhApiVec3f(24f, 140f, 24f), relCubeList); relativePosCubeGroup.setPreRenderFunc((event) -> { - float x = relativePosCubeGroup.getOriginBlockX(); - x += event.partialTicks / 2; - x %= 32; - relativePosCubeGroup.setOriginBlockPos(x, relativePosCubeGroup.getOriginBlockY(), relativePosCubeGroup.getOriginBlockZ()); + DhApiVec3f pos = relativePosCubeGroup.getOriginBlockPos(); + pos.x += event.partialTicks / 2; + pos.x %= 32; + relativePosCubeGroup.setOriginBlockPos(pos); }); DhApi.Delayed.renderRegister.add(relativePosCubeGroup); @@ -249,17 +250,17 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } } IDhApiRenderableBoxGroup massRelativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( - -25f, 140f, 0f, + new DhApiVec3f(-25f, 140f, 0f), massRelCubeList); massRelativePosCubeGroup.setPreRenderFunc((event) -> { - float y = massRelativePosCubeGroup.getOriginBlockY(); - y += event.partialTicks / 4; - if (y > 150f) + DhApiVec3f blockPos = massRelativePosCubeGroup.getOriginBlockPos(); + blockPos.y += event.partialTicks / 4; + if (blockPos.y > 150f) { - y = 140f; + blockPos.y = 140f; } - massRelativePosCubeGroup.setOriginBlockPos(massRelativePosCubeGroup.getOriginBlockX(), y, massRelativePosCubeGroup.getOriginBlockZ()); + massRelativePosCubeGroup.setOriginBlockPos(blockPos); }); DhApi.Delayed.renderRegister.add(massRelativePosCubeGroup); @@ -303,12 +304,12 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } @Override - public IDhApiRenderableBoxGroup createRelativePositionedGroup(float originBlockX, float originBlockY, float originBlockZ, List cubeList) - { return new DhApiRenderableBoxGroup(originBlockX, originBlockY, originBlockZ, cubeList, true); } + public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList) + { return new DhApiRenderableBoxGroup(new Vec3f(originBlockPos), cubeList, true); } @Override public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList) - { return new DhApiRenderableBoxGroup(0, 0, 0, boxList, false); } + { return new DhApiRenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); } @@ -457,9 +458,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.shader.setUniform(this.instancedShaderOffsetUniformLocation, new Vec3f( - boxGroup.originBlockX, - boxGroup.originBlockY, - boxGroup.originBlockZ + boxGroup.originBlockPos.x, + boxGroup.originBlockPos.y, + boxGroup.originBlockPos.z )); this.shader.setUniform(this.instancedShaderCameraPosUniformLocation, @@ -547,9 +548,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister float originOffsetZ = 0; if (cubeGroup.positionCubesRelativeToGroupOrigin) { - originOffsetX = cubeGroup.originBlockX; - originOffsetY = cubeGroup.originBlockY; - originOffsetZ = cubeGroup.originBlockZ; + originOffsetX = cubeGroup.originBlockPos.x; + originOffsetY = cubeGroup.originBlockPos.y; + originOffsetZ = cubeGroup.originBlockPos.z; } Mat4f boxTransform = Mat4f.createTranslateMatrix( @@ -590,9 +591,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private final ArrayList cubeList; - private float originBlockX; - private float originBlockY; - private float originBlockZ; + private final Vec3f originBlockPos; @Nullable public Consumer beforeRenderFunc; @@ -612,25 +611,21 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister public long getId() { return this.id; } @Override - public void setOriginBlockPos(float x, float y, float z) + public void setOriginBlockPos(DhApiVec3f pos) { - this.originBlockX = x; - this.originBlockY = y; - this.originBlockZ = z; + this.originBlockPos.x = pos.x; + this.originBlockPos.y = pos.y; + this.originBlockPos.z = pos.z; } @Override - public float getOriginBlockX() { return this.originBlockX; } - @Override - public float getOriginBlockY() { return this.originBlockY; } - @Override - public float getOriginBlockZ() { return this.originBlockZ; } + public DhApiVec3f getOriginBlockPos() { return new DhApiVec3f(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } // constructor // - public DhApiRenderableBoxGroup(float originBlockX, float originBlockY, float originBlockZ, List cubeList, boolean positionCubesRelativeToGroupOrigin) + public DhApiRenderableBoxGroup(Vec3f originBlockPos, List cubeList, boolean positionCubesRelativeToGroupOrigin) { // TODO save to database // TODO when? @@ -638,9 +633,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); this.cubeList = new ArrayList<>(cubeList); - this.originBlockX = originBlockX; - this.originBlockY = originBlockY; - this.originBlockZ = originBlockZ; + this.originBlockPos = originBlockPos; this.positionCubesRelativeToGroupOrigin = positionCubesRelativeToGroupOrigin; } From aefa0d6797c8438e9aa149561129d309fe3ea52a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 14:27:09 -0500 Subject: [PATCH 015/104] generic renderable active flag and renaming cube -> box --- .../render/IDhApiRenderableBoxGroup.java | 14 +- .../renderer/GenericObjectRenderer.java | 202 ++++++++++-------- 2 files changed, 125 insertions(+), 91 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java index b37b43a4c..79abc7efb 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -10,11 +10,23 @@ import java.util.function.Consumer; public interface IDhApiRenderableBoxGroup extends List { - long getId(); + + void setActive(boolean active); + boolean isActive(); + void setOriginBlockPos(DhApiVec3f pos); DhApiVec3f getOriginBlockPos(); void setPreRenderFunc(Consumer renderEventParam); + /** + * If a cube's color, position, or other property are changed this method + * must be called for those changes to render.

+ * + * Note: changing the group's position via {@link #setOriginBlockPos} doesn't + * require calling this method. + */ + void triggerBoxChange(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index d5383a64b..bd14fba0b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -53,7 +53,6 @@ import org.lwjgl.opengl.GL33; import javax.annotation.Nullable; import java.awt.*; import java.io.Closeable; -import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.*; @@ -98,7 +97,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // TODO may need to be double buffered to prevent rendering lag - private final Long2ReferenceOpenHashMap boxGroupById = new Long2ReferenceOpenHashMap<>(); + private final Long2ReferenceOpenHashMap boxGroupById = new Long2ReferenceOpenHashMap<>(); private final ReentrantLock mapModifyLock = new ReentrantLock(); @@ -160,7 +159,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.useInstancedRendering = this.vertexAttribDivisorSupported || this.instancedArraysSupported; if (!this.useInstancedRendering) { - LOGGER.info("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering may be slow."); + LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering may be slow."); } @@ -188,87 +187,92 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // testing // - // single giant cube - IDhApiRenderableBoxGroup singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( + // single giant box + IDhApiRenderableBoxGroup singleGiantBoxGroup = DhApi.Delayed.renderRegister.createForSingleBox( new DhApiRenderableBox( new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) ); - DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); + DhApi.Delayed.renderRegister.add(singleGiantBoxGroup); - // single slender cube - singleGiantCubeGroup = DhApi.Delayed.renderRegister.createForSingleBox( + // single slender box + IDhApiRenderableBoxGroup singleTallBoxGroup = DhApi.Delayed.renderRegister.createForSingleBox( new DhApiRenderableBox( new Vec3f(16f,0f,31f), new Vec3f(17f,2000f,32f), new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) ); - DhApi.Delayed.renderRegister.add(singleGiantCubeGroup); + DhApi.Delayed.renderRegister.add(singleTallBoxGroup); - // absolute cube group - ArrayList absCubeList = new ArrayList<>(); + // absolute box group + ArrayList absBoxList = new ArrayList<>(); for (int i = 0; i < 18; i++) { - absCubeList.add(new DhApiRenderableBox( + absBoxList.add(new DhApiRenderableBox( new Vec3f(0f+i,150f+i,24f), new Vec3f(1f+i,151f+i,25f), new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); } - IDhApiRenderableBoxGroup absolutePosCubeGroup = DhApi.Delayed.renderRegister.createAbsolutePositionedGroup(absCubeList); - DhApi.Delayed.renderRegister.add(absolutePosCubeGroup); + IDhApiRenderableBoxGroup absolutePosBoxGroup = DhApi.Delayed.renderRegister.createAbsolutePositionedGroup(absBoxList); + DhApi.Delayed.renderRegister.add(absolutePosBoxGroup); - // relative cube group - ArrayList relCubeList = new ArrayList<>(); + // relative box group + ArrayList relBoxList = new ArrayList<>(); for (int i = 0; i < 8; i+=2) { - relCubeList.add(new DhApiRenderableBox( + relBoxList.add(new DhApiRenderableBox( new Vec3f(0f,0f+i,0f), new Vec3f(1f,1f+i,1f), new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); } - IDhApiRenderableBoxGroup relativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( + IDhApiRenderableBoxGroup relativePosBoxGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( new DhApiVec3f(24f, 140f, 24f), - relCubeList); - relativePosCubeGroup.setPreRenderFunc((event) -> + relBoxList); + relativePosBoxGroup.setPreRenderFunc((event) -> { - DhApiVec3f pos = relativePosCubeGroup.getOriginBlockPos(); + DhApiVec3f pos = relativePosBoxGroup.getOriginBlockPos(); pos.x += event.partialTicks / 2; pos.x %= 32; - relativePosCubeGroup.setOriginBlockPos(pos); + relativePosBoxGroup.setOriginBlockPos(pos); }); - DhApi.Delayed.renderRegister.add(relativePosCubeGroup); + DhApi.Delayed.renderRegister.add(relativePosBoxGroup); - // massive relative cube group - ArrayList massRelCubeList = new ArrayList<>(); + // massive relative box group + ArrayList massRelBoxList = new ArrayList<>(); for (int x = 0; x < 50*2; x+=2) { for (int z = 0; z < 50*2; z+=2) { - massRelCubeList.add(new DhApiRenderableBox( + massRelBoxList.add(new DhApiRenderableBox( new Vec3f(0f-x, 0f, 0f-z), new Vec3f(1f-x, 1f, 1f-z), new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()))); } } - IDhApiRenderableBoxGroup massRelativePosCubeGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( + IDhApiRenderableBoxGroup massRelativePosBoxGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( new DhApiVec3f(-25f, 140f, 0f), - massRelCubeList); - massRelativePosCubeGroup.setPreRenderFunc((event) -> + massRelBoxList); + massRelativePosBoxGroup.setPreRenderFunc((event) -> { - DhApiVec3f blockPos = massRelativePosCubeGroup.getOriginBlockPos(); + DhApiVec3f blockPos = massRelativePosBoxGroup.getOriginBlockPos(); blockPos.y += event.partialTicks / 4; if (blockPos.y > 150f) { blockPos.y = 140f; + + Color newColor = (massRelativePosBoxGroup.get(0).color == Color.RED) ? Color.RED.darker() : Color.RED; + massRelativePosBoxGroup.forEach((box) -> { box.color = newColor; }); + massRelativePosBoxGroup.triggerBoxChange(); } - massRelativePosCubeGroup.setOriginBlockPos(blockPos); + + massRelativePosBoxGroup.setOriginBlockPos(blockPos); }); - DhApi.Delayed.renderRegister.add(massRelativePosCubeGroup); + DhApi.Delayed.renderRegister.add(massRelativePosBoxGroup); } private void createBuffers() { - // cube vertices + // box vertices ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES); boxVerticesBuffer.order(ByteOrder.nativeOrder()); boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES); @@ -278,7 +282,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES); - // cube vertex indexes + // box vertex indexes ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); solidIndexBuffer.order(ByteOrder.nativeOrder()); solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); @@ -304,12 +308,12 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } @Override - public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList) - { return new DhApiRenderableBoxGroup(new Vec3f(originBlockPos), cubeList, true); } + public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List boxList) + { return new RenderableBoxGroup(new Vec3f(originBlockPos), boxList, true); } @Override public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList) - { return new DhApiRenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); } + { return new RenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); } @@ -320,11 +324,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister @Override public void add(IDhApiRenderableBoxGroup iBoxGroup) throws IllegalArgumentException { - if (!(iBoxGroup instanceof DhApiRenderableBoxGroup)) + if (!(iBoxGroup instanceof RenderableBoxGroup)) { - throw new IllegalArgumentException("Box group must be of type ["+DhApiRenderableBoxGroup.class.getSimpleName()+"]."); + throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"]."); } - DhApiRenderableBoxGroup boxGroup = (DhApiRenderableBoxGroup) iBoxGroup; + RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup; try @@ -412,24 +416,26 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // rendering // - LongSet keys = boxGroupById.keySet(); for (long key : keys) { - profiler.popPush("render prep"); - - DhApiRenderableBoxGroup boxGroup = boxGroupById.get(key); - boxGroup.preRender(renderEventParam); - - if (this.useInstancedRendering) + RenderableBoxGroup boxGroup = boxGroupById.get(key); + // ignore inactive groups + if (boxGroup.active) { - profiler.popPush("rendering"); - this.renderBoxGroupInstanced(boxGroup, camPos, projectionMvmMatrix); - } - else - { - profiler.popPush("rendering"); - this.renderBoxGroupDirect(boxGroup, projectionMvmMatrix, camPos); + profiler.popPush("render prep"); + boxGroup.preRender(renderEventParam); + + if (this.useInstancedRendering) + { + profiler.popPush("rendering"); + this.renderBoxGroupInstanced(boxGroup, camPos, projectionMvmMatrix); + } + else + { + profiler.popPush("rendering"); + this.renderBoxGroupDirect(boxGroup, projectionMvmMatrix, camPos); + } } } @@ -450,7 +456,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // instanced rendering // //=====================// - private void renderBoxGroupInstanced(DhApiRenderableBoxGroup boxGroup, Vec3f camPos, Mat4f projectionMvmMatrix) + private void renderBoxGroupInstanced(RenderableBoxGroup boxGroup, Vec3f camPos, Mat4f projectionMvmMatrix) { // update instance data // @@ -532,40 +538,40 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // direct rendering // //==================// - private void renderBoxGroupDirect(DhApiRenderableBoxGroup cubeGroup, Mat4f transformMatrix, Vec3f camPos) + private void renderBoxGroupDirect(RenderableBoxGroup boxGroup, Mat4f transformMatrix, Vec3f camPos) { - for (DhApiRenderableBox box : cubeGroup.cubeList) + for (DhApiRenderableBox box : boxGroup.boxList) { - renderBox(cubeGroup, box, transformMatrix, camPos); + renderBox(boxGroup, box, transformMatrix, camPos); } } private void renderBox( - DhApiRenderableBoxGroup cubeGroup, DhApiRenderableBox cube, + RenderableBoxGroup boxGroup, DhApiRenderableBox box, Mat4f transformationMatrix, Vec3f camPos) { float originOffsetX = 0; float originOffsetY = 0; float originOffsetZ = 0; - if (cubeGroup.positionCubesRelativeToGroupOrigin) + if (boxGroup.positionBoxesRelativeToGroupOrigin) { - originOffsetX = cubeGroup.originBlockPos.x; - originOffsetY = cubeGroup.originBlockPos.y; - originOffsetZ = cubeGroup.originBlockPos.z; + originOffsetX = boxGroup.originBlockPos.x; + originOffsetY = boxGroup.originBlockPos.y; + originOffsetZ = boxGroup.originBlockPos.z; } Mat4f boxTransform = Mat4f.createTranslateMatrix( - cube.minPos.x + originOffsetX - camPos.x, - cube.minPos.y + originOffsetY - camPos.y, - cube.minPos.z + originOffsetZ - camPos.z); + box.minPos.x + originOffsetX - camPos.x, + box.minPos.y + originOffsetY - camPos.y, + box.minPos.z + originOffsetZ - camPos.z); boxTransform.multiply(Mat4f.createScaleMatrix( - cube.maxPos.x - cube.minPos.x, - cube.maxPos.y - cube.minPos.y, - cube.maxPos.z - cube.minPos.z)); + box.maxPos.x - box.minPos.x, + box.maxPos.y - box.minPos.y, + box.maxPos.z - box.minPos.z)); Mat4f transformMatrix = transformationMatrix.copy(); transformMatrix.multiply(boxTransform); this.shader.setUniform(this.directShaderTransformUniformLocation, transformMatrix); - this.shader.setUniform(this.directShaderColorUniformLocation, cube.color); + this.shader.setUniform(this.directShaderColorUniformLocation, box.color); GL32.glDrawElements(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } @@ -576,7 +582,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // helper classes // //================// - private static final class DhApiRenderableBoxGroup + private static final class RenderableBoxGroup extends AbstractList implements IDhApiRenderableBoxGroup, Closeable { @@ -586,10 +592,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister public final long id; - /** If false the cubes will be positioned relative to the level's origin */ - public final boolean positionCubesRelativeToGroupOrigin; + /** If false the boxes will be positioned relative to the level's origin */ + public final boolean positionBoxesRelativeToGroupOrigin; - private final ArrayList cubeList; + private final ArrayList boxList; private final Vec3f originBlockPos; @@ -597,6 +603,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister public Consumer beforeRenderFunc; private boolean vertexDataDirty = true; + public boolean active = true; // instance data private int instanceTranslationVbo = 0; @@ -625,16 +632,16 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // constructor // - public DhApiRenderableBoxGroup(Vec3f originBlockPos, List cubeList, boolean positionCubesRelativeToGroupOrigin) + public RenderableBoxGroup(Vec3f originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) { // TODO save to database // TODO when? this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); - this.cubeList = new ArrayList<>(cubeList); + this.boxList = new ArrayList<>(boxList); this.originBlockPos = originBlockPos; - this.positionCubesRelativeToGroupOrigin = positionCubesRelativeToGroupOrigin; + this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin; } @@ -642,12 +649,19 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // methods // @Override - public boolean add(DhApiRenderableBox cube) { return this.cubeList.add(cube); } + public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); } @Override public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; } - //@Override + @Override + public void triggerBoxChange() { this.vertexDataDirty = true; } + + @Override + public void setActive(boolean active) { this.active = active; } + @Override + public boolean isActive() { return this.active; } + public void preRender(DhApiRenderParam renderEventParam) { if (this.beforeRenderFunc != null) @@ -661,23 +675,23 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // overrides // @Override - public DhApiRenderableBox get(int index) { return this.cubeList.get(index); } + public DhApiRenderableBox get(int index) { return this.boxList.get(index); } @Override - public int size() { return this.cubeList.size(); } + public int size() { return this.boxList.size(); } @Override - public boolean removeIf(Predicate filter) { return this.cubeList.removeIf(filter); } + public boolean removeIf(Predicate filter) { return this.boxList.removeIf(filter); } @Override - public void replaceAll(UnaryOperator operator) { this.cubeList.replaceAll(operator); } + public void replaceAll(UnaryOperator operator) { this.boxList.replaceAll(operator); } @Override - public void sort(Comparator c) { this.cubeList.sort(c); } + public void sort(Comparator c) { this.boxList.sort(c); } @Override - public void forEach(Consumer action) { this.cubeList.forEach(action); } + public void forEach(Consumer action) { this.boxList.forEach(action); } @Override - public Spliterator spliterator() { return this.cubeList.spliterator(); } + public Spliterator spliterator() { return this.boxList.spliterator(); } @Override - public Stream stream() { return this.cubeList.stream(); } + public Stream stream() { return this.boxList.stream(); } @Override - public Stream parallelStream() { return this.cubeList.parallelStream(); } + public Stream parallelStream() { return this.boxList.parallelStream(); } @@ -685,6 +699,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // vertex attributes // //===================// + /** Does nothing if the vertex data is already up-to-date */ private void updateVertexAttributeData() { if (!this.vertexDataDirty) @@ -729,8 +744,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister float[] colorData = new float[boxCount * 4]; for (int i = 0; i < boxCount; i++) { - DhApiRenderableBox cube = this.get(i); - Color color = cube.color; + DhApiRenderableBox box = this.get(i); + Color color = box.color; int colorIndex = i * 4; colorData[colorIndex] = color.getRed() / 255.0f; colorData[colorIndex + 1] = color.getGreen() / 255.0f; @@ -752,6 +767,13 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister + //================// + // base overrides // + //================// + + @Override + public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; } + @Override public void close() { From f68edcbfea9db46eb28b0d3600ec389a49600efc Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 14:38:35 -0500 Subject: [PATCH 016/104] Add debug render code toggle --- .../renderer/GenericObjectRenderer.java | 65 ++++++++++--------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index bd14fba0b..d678fdc41 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -73,6 +73,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + public static boolean RENDER_DEBUG_OBJECTS = true; + // rendering setup private boolean init = false; @@ -183,18 +185,44 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.createBuffers(); + if (RENDER_DEBUG_OBJECTS) + { + this.addGenericDebugObjects(); + } + } + private void createBuffers() + { + // box vertices + ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES); + boxVerticesBuffer.order(ByteOrder.nativeOrder()); + boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES); + boxVerticesBuffer.rewind(); + this.vertexBuffer = new GLVertexBuffer(false); + this.vertexBuffer.bind(); + this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES); - // testing // + // box vertex indexes + ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); + solidIndexBuffer.order(ByteOrder.nativeOrder()); + solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); + solidIndexBuffer.rewind(); + this.solidIndexBuffer = new GLElementBuffer(false); + this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + this.solidIndexBuffer.bind(); + } + private void addGenericDebugObjects() + { // single giant box IDhApiRenderableBoxGroup singleGiantBoxGroup = DhApi.Delayed.renderRegister.createForSingleBox( new DhApiRenderableBox( new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) - ); + ); DhApi.Delayed.renderRegister.add(singleGiantBoxGroup); - + + // single slender box IDhApiRenderableBoxGroup singleTallBoxGroup = DhApi.Delayed.renderRegister.createForSingleBox( new DhApiRenderableBox( @@ -203,6 +231,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister ); DhApi.Delayed.renderRegister.add(singleTallBoxGroup); + // absolute box group ArrayList absBoxList = new ArrayList<>(); for (int i = 0; i < 18; i++) @@ -214,6 +243,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister IDhApiRenderableBoxGroup absolutePosBoxGroup = DhApi.Delayed.renderRegister.createAbsolutePositionedGroup(absBoxList); DhApi.Delayed.renderRegister.add(absolutePosBoxGroup); + // relative box group ArrayList relBoxList = new ArrayList<>(); for (int i = 0; i < 8; i+=2) @@ -225,7 +255,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister IDhApiRenderableBoxGroup relativePosBoxGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( new DhApiVec3f(24f, 140f, 24f), relBoxList); - relativePosBoxGroup.setPreRenderFunc((event) -> + relativePosBoxGroup.setPreRenderFunc((event) -> { DhApiVec3f pos = relativePosBoxGroup.getOriginBlockPos(); pos.x += event.partialTicks / 2; @@ -235,8 +265,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister DhApi.Delayed.renderRegister.add(relativePosBoxGroup); - - // massive relative box group ArrayList massRelBoxList = new ArrayList<>(); for (int x = 0; x < 50*2; x+=2) @@ -267,34 +295,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister massRelativePosBoxGroup.setOriginBlockPos(blockPos); }); DhApi.Delayed.renderRegister.add(massRelativePosBoxGroup); - - - } - private void createBuffers() - { - // box vertices - ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES); - boxVerticesBuffer.order(ByteOrder.nativeOrder()); - boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES); - boxVerticesBuffer.rewind(); - this.vertexBuffer = new GLVertexBuffer(false); - this.vertexBuffer.bind(); - this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES); - - - // box vertex indexes - ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); - solidIndexBuffer.order(ByteOrder.nativeOrder()); - solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); - solidIndexBuffer.rewind(); - this.solidIndexBuffer = new GLElementBuffer(false); - this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); - this.solidIndexBuffer.bind(); - } + //================// // group creation // //================// From 5a71e4015ce1f8242a1b43ebaeba74ce8f3bf1a3 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 15:28:00 -0500 Subject: [PATCH 017/104] Add javadocs to generic rendering objects --- .../com/seibel/distanthorizons/api/DhApi.java | 4 ++ .../render/IDhApiCustomRenderRegister.java | 10 +++++ .../render/IDhApiRenderableBoxGroup.java | 22 ++++++++++- .../objects/render/DhApiRenderableBox.java | 37 ++++++++++++++++--- .../renderer/GenericObjectRenderer.java | 24 ++++++++---- .../core/render/renderer/LodRenderer.java | 13 ++++--- 6 files changed, 90 insertions(+), 20 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java index 4b0b9969d..a79885503 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java @@ -128,6 +128,10 @@ public class DhApi */ public static IDhApiWrapperFactory wrapperFactory = null; + /** + * Used to add custom objects to DH's render pass. + * @since API 3.0.0 + */ public static IDhApiCustomRenderRegister renderRegister = null; } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java index 1dfff0a29..6b9b06daf 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java @@ -5,6 +5,16 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import java.util.List; +/** + * Handles adding, removing, and creating + * {@link IDhApiRenderableBoxGroup} objects, + * which can be used to render custom objects into + * DH's terrain. + * + * @author James Seibel + * @version 2024-6-30 + * @since API 3.0.0 + */ public interface IDhApiCustomRenderRegister { void add(IDhApiRenderableBoxGroup cubeGroup) throws IllegalArgumentException; diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java index 79abc7efb..78174b76d 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -7,21 +7,39 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import java.util.List; import java.util.function.Consumer; +/** + * A list of {@link DhApiRenderableBox}'s that + * can be rendered to DH's terrain pass. + * + * @see DhApiRenderableBox + * + * @author James Seibel + * @version 2024-6-30 + * @since API 3.0.0 + */ public interface IDhApiRenderableBoxGroup extends List { - + /** @return the ID for this specific group */ long getId(); + /** Sets whether this group should render or not. */ void setActive(boolean active); + /** @return if active this group will render. */ boolean isActive(); + /** Sets where this group will render in the level. */ void setOriginBlockPos(DhApiVec3f pos); + /** @return the block position in the level that all {@see DhApiRenderableBox} will render relative to. */ DhApiVec3f getOriginBlockPos(); + /** + * Called right before this group is rendered.
+ * This is a good place to change the origin or notify of any box changes. + */ void setPreRenderFunc(Consumer renderEventParam); /** - * If a cube's color, position, or other property are changed this method + * If a cube's color, position, or other property is changed this method * must be called for those changes to render.

* * Note: changing the group's position via {@link #setOriginBlockPos} doesn't diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java index 37276cc42..6969d33ee 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java @@ -1,21 +1,46 @@ package com.seibel.distanthorizons.api.objects.render; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import java.awt.*; -public final class DhApiRenderableBox +/** + * @see IDhApiRenderableBoxGroup + * + * @author James Seibel + * @version 2024-6-30 + * @since API 3.0.0 + */ +public class DhApiRenderableBox { - public Vec3f minPos; - public Vec3f maxPos; + /** the position closest to (-inf,-inf) */ + public DhApiVec3f minPos; + /** the position closest to (+inf,+inf) */ + public DhApiVec3f maxPos; + public Color color; - public boolean fullBright = false; + /* TODO */ + //public boolean fullBright = false; - public DhApiRenderableBox(Vec3f minPos, Vec3f maxPos, Color color) + //==============// + // constructors // + //==============// + + public DhApiRenderableBox(DhApiVec3f minPos, float width, Color color) + { + this(minPos, new DhApiVec3f( + minPos.x + width, + minPos.y + width, + minPos.z + width + ), color); + } + + public DhApiRenderableBox(DhApiVec3f minPos, DhApiVec3f maxPos, Color color) { this.minPos = minPos; this.maxPos = maxPos; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index d678fdc41..64382386b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -64,16 +64,26 @@ import java.util.function.Predicate; import java.util.function.UnaryOperator; import java.util.stream.Stream; +/** + * Handles rendering generic groups of {@link DhApiRenderableBox}. + * + * @see IDhApiCustomRenderRegister + * @see DhApiRenderableBox + */ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { public static GenericObjectRenderer INSTANCE = new GenericObjectRenderer(); private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(TestRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1); + public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(GenericObjectRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - public static boolean RENDER_DEBUG_OBJECTS = true; + /** + * Can be used to troubleshoot the renderer. + * If enabled several debug objects will render around (0,150,0). + */ + public static final boolean RENDER_DEBUG_OBJECTS = true; // rendering setup @@ -217,7 +227,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single giant box IDhApiRenderableBoxGroup singleGiantBoxGroup = DhApi.Delayed.renderRegister.createForSingleBox( new DhApiRenderableBox( - new Vec3f(0f,0f,0f), new Vec3f(16f,190f,16f), + new DhApiVec3f(0f,0f,0f), new DhApiVec3f(16f,190f,16f), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) ); DhApi.Delayed.renderRegister.add(singleGiantBoxGroup); @@ -226,7 +236,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single slender box IDhApiRenderableBoxGroup singleTallBoxGroup = DhApi.Delayed.renderRegister.createForSingleBox( new DhApiRenderableBox( - new Vec3f(16f,0f,31f), new Vec3f(17f,2000f,32f), + new DhApiVec3f(16f,0f,31f), new DhApiVec3f(17f,2000f,32f), new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) ); DhApi.Delayed.renderRegister.add(singleTallBoxGroup); @@ -237,7 +247,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int i = 0; i < 18; i++) { absBoxList.add(new DhApiRenderableBox( - new Vec3f(0f+i,150f+i,24f), new Vec3f(1f+i,151f+i,25f), + new DhApiVec3f(0f+i,150f+i,24f), new DhApiVec3f(1f+i,151f+i,25f), new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); } IDhApiRenderableBoxGroup absolutePosBoxGroup = DhApi.Delayed.renderRegister.createAbsolutePositionedGroup(absBoxList); @@ -249,7 +259,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int i = 0; i < 8; i+=2) { relBoxList.add(new DhApiRenderableBox( - new Vec3f(0f,0f+i,0f), new Vec3f(1f,1f+i,1f), + new DhApiVec3f(0f,0f+i,0f), new DhApiVec3f(1f,1f+i,1f), new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); } IDhApiRenderableBoxGroup relativePosBoxGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( @@ -272,7 +282,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int z = 0; z < 50*2; z+=2) { massRelBoxList.add(new DhApiRenderableBox( - new Vec3f(0f-x, 0f, 0f-z), new Vec3f(1f-x, 1f, 1f-z), + new DhApiVec3f(0f-x, 0f, 0f-z), new DhApiVec3f(1f-x, 1f, 1f-z), new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()))); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 6a89ef21f..564bc25a7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -371,12 +371,18 @@ public class LodRenderer // Disable blending for opaque rendering GL32.glDisable(GL32.GL_BLEND); + + // terrain profiler.popPush("LOD Opaque"); ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam); - - // TODO: Directional culling this.bufferHandler.renderOpaque(this, renderEventParam); + // custom objects + profiler.popPush("Custom Objects"); + GenericObjectRenderer.INSTANCE.render(renderEventParam, profiler); + + + // SSAO if (Config.Client.Advanced.Graphics.Ssao.enabled.get()) { profiler.popPush("LOD SSAO"); @@ -421,9 +427,6 @@ public class LodRenderer DebugRenderer.INSTANCE.render(combinedMatrix); } - profiler.popPush("Custom Objects"); - GenericObjectRenderer.INSTANCE.render(renderEventParam, profiler); - profiler.popPush("LOD cleanup"); From 0c0987b66b683deb4b6f58463f8ef96555e04311 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 16:33:38 -0500 Subject: [PATCH 018/104] Replace Vec3f and Mat4f in API with API versions --- .../rendering/IDhApiCullingFrustum.java | 4 +- .../rendering/IDhApiShaderProgram.java | 5 +- .../rendering/IDhApiShadowCullingFrustum.java | 4 - .../DhApiBeforeBufferRenderEvent.java | 6 +- .../DhApiRenderParam.java | 14 +- .../api/objects/data/DhApiRaycastResult.java | 3 +- .../objects/math/DhApiMat4f.java} | 486 +++++------------- .../coreapi/util/math/Vec3f.java | 273 ---------- .../methods/data/DhApiTerrainDataRepo.java | 8 +- .../core/api/internal/ClientApi.java | 2 +- .../core/enums/EDhDirection.java | 2 +- .../core/render/DhFrustumBounds.java | 7 +- .../core/render/NeverCullFrustum.java | 5 +- .../core/render/RenderBufferHandler.java | 6 +- .../render/glObject/shader/ShaderProgram.java | 6 +- .../core/render/renderer/DebugRenderer.java | 6 +- .../renderer/GenericObjectRenderer.java | 6 +- .../render/renderer/LodRenderProgram.java | 7 +- .../core/render/renderer/LodRenderer.java | 8 +- .../core/render/renderer/SSAORenderer.java | 2 +- .../render/renderer/shaders/FogShader.java | 2 +- .../render/renderer/shaders/SSAOShader.java | 2 +- .../distanthorizons/core/util/RenderUtil.java | 4 +- .../distanthorizons/core/util/math/Mat4f.java | 249 +++++++++ .../core}/util/math/Vec3d.java | 2 +- .../distanthorizons/core/util/math/Vec3f.java | 150 ++++++ .../core}/util/math/Vec3i.java | 2 +- .../minecraft/IMinecraftRenderWrapper.java | 6 +- 28 files changed, 581 insertions(+), 696 deletions(-) rename api/src/main/java/com/seibel/distanthorizons/{coreapi/util/math/Mat4f.java => api/objects/math/DhApiMat4f.java} (57%) delete mode 100644 api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/util/math/Mat4f.java rename {api/src/main/java/com/seibel/distanthorizons/coreapi => core/src/main/java/com/seibel/distanthorizons/core}/util/math/Vec3d.java (99%) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3f.java rename {api/src/main/java/com/seibel/distanthorizons/coreapi => core/src/main/java/com/seibel/distanthorizons/core}/util/math/Vec3i.java (98%) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiCullingFrustum.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiCullingFrustum.java index 44106b82a..33cebacd2 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiCullingFrustum.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiCullingFrustum.java @@ -21,7 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.override.rendering; import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; /** * Used to determine if a LOD should be rendered or is outside the @@ -41,7 +41,7 @@ public interface IDhApiCullingFrustum extends IDhApiOverrideable * @param worldMaxBlockY the highest block position this level allows. * @param worldViewProjection the projection matrix used in this render pass. */ - void update(int worldMinBlockY, int worldMaxBlockY, Mat4f worldViewProjection); + void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection); /** * returns true if the LOD bounds intersect this frustum diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java index 6f329121d..61e853b06 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java @@ -21,8 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.override.rendering; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; /** * @author James Seibel @@ -57,7 +56,7 @@ public interface IDhApiShaderProgram extends IDhApiOverrideable void fillUniformData(DhApiRenderParam renderParameters); /** sets the vec3 that all DH verticies should be offset by when rendering */ - void setModelOffsetPos(Vec3f modelPos); + void setModelOffsetPos(DhApiVec3f modelPos); /** Binds the given Vertex Buffer Object to this shader program for rendering. */ void bindVertexBuffer(int vbo); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java index 5748d06d9..564c27838 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java @@ -19,10 +19,6 @@ package com.seibel.distanthorizons.api.interfaces.override.rendering; -import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel; -import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; - /** * The culling frustum used during Distant Horizons' shadow pass * if another mod has enabled Distant Horizons' shadow diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java index 7716fda0c..f1d9156a5 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java @@ -22,7 +22,7 @@ package com.seibel.distanthorizons.api.methods.events.abstractEvents; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; /** * Called before Distant Horizons starts rendering a buffer.
@@ -58,10 +58,10 @@ public abstract class DhApiBeforeBufferRenderEvent implements IDhApiEvent. */ -package com.seibel.distanthorizons.coreapi.util.math; - -import org.joml.Matrix4f; -import org.joml.Matrix4fc; - -import java.nio.FloatBuffer; +package com.seibel.distanthorizons.api.objects.math; /** * An (almost) exact copy of Minecraft's 1.16.5 - * implementation of a 4x4 float matrix. + * implementation of a 4x4 float matrix.

* + * + * m00, m10, m20, m30,
+ * m01, m11, m21, m31,
+ * m02, m12, m22, m32,
+ * m03, m13, m23, m33
+ *
+ * * @author James Seibel - * @version 11-11-2021 + * @version 2024-6-30 */ -public class Mat4f +public class DhApiMat4f { - private float m00; - private float m01; - private float m02; - private float m03; - private float m10; - private float m11; - private float m12; - private float m13; - private float m20; - private float m21; - private float m22; - private float m23; - private float m30; - private float m31; - private float m32; - private float m33; + public float m00; + public float m01; + public float m02; + public float m03; + + public float m10; + public float m11; + public float m12; + public float m13; + + public float m20; + public float m21; + public float m22; + public float m23; + + public float m30; + public float m31; + public float m32; + public float m33; - public Mat4f() - { - - } - public Mat4f(Mat4f sourceMatrix) + //==============// + // constructors // + //==============// + + public DhApiMat4f() { /* all values are 0 */ } + + public DhApiMat4f(DhApiMat4f sourceMatrix) { this.m00 = sourceMatrix.m00; this.m01 = sourceMatrix.m01; @@ -76,163 +83,36 @@ public class Mat4f this.m33 = sourceMatrix.m33; } - public Mat4f(Matrix4fc sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); } - private static float[] convertJomlMatrixToArray(Matrix4fc sourceMatrix) + /** Expects the values of the input array to be in row major order (AKA rows then columns) */ + public DhApiMat4f(float[] values) { - FloatBuffer buffer = FloatBuffer.allocate(16); + m00 = values[0]; + m01 = values[1]; + m02 = values[2]; + m03 = values[3]; - buffer.put(bufferIndex(0, 0), sourceMatrix.m00()); - buffer.put(bufferIndex(0, 1), sourceMatrix.m01()); - buffer.put(bufferIndex(0, 2), sourceMatrix.m02()); - buffer.put(bufferIndex(0, 3), sourceMatrix.m03()); - buffer.put(bufferIndex(1, 0), sourceMatrix.m10()); - buffer.put(bufferIndex(1, 1), sourceMatrix.m11()); - buffer.put(bufferIndex(1, 2), sourceMatrix.m12()); - buffer.put(bufferIndex(1, 3), sourceMatrix.m13()); - buffer.put(bufferIndex(2, 0), sourceMatrix.m20()); - buffer.put(bufferIndex(2, 1), sourceMatrix.m21()); - buffer.put(bufferIndex(2, 2), sourceMatrix.m22()); - buffer.put(bufferIndex(2, 3), sourceMatrix.m23()); - buffer.put(bufferIndex(3, 0), sourceMatrix.m30()); - buffer.put(bufferIndex(3, 1), sourceMatrix.m31()); - buffer.put(bufferIndex(3, 2), sourceMatrix.m32()); - buffer.put(bufferIndex(3, 3), sourceMatrix.m33()); + m10 = values[4]; + m11 = values[5]; + m12 = values[6]; + m13 = values[7]; - return buffer.array(); - } - - /* Quaternions are not currently needed/implemented - public Matrix4float(Quaternion p_i48104_1_) - { - float f = p_i48104_1_.i(); - float f1 = p_i48104_1_.j(); - float f2 = p_i48104_1_.k(); - float f3 = p_i48104_1_.r(); - float f4 = 2.0F * f * f; - float f5 = 2.0F * f1 * f1; - float f6 = 2.0F * f2 * f2; - this.m00 = 1.0F - f5 - f6; - this.m11 = 1.0F - f6 - f4; - this.m22 = 1.0F - f4 - f5; - this.m33 = 1.0F; - float f7 = f * f1; - float f8 = f1 * f2; - float f9 = f2 * f; - float f10 = f * f3; - float f11 = f1 * f3; - float f12 = f2 * f3; - this.m10 = 2.0F * (f7 + f12); - this.m01 = 2.0F * (f7 - f12); - this.m20 = 2.0F * (f9 - f11); - this.m02 = 2.0F * (f9 + f11); - this.m21 = 2.0F * (f8 + f10); - this.m12 = 2.0F * (f8 - f10); - } - */ - - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - else if (obj != null && this.getClass() == obj.getClass()) - { - Mat4f otherMatrix = (Mat4f) obj; - return Float.compare(otherMatrix.m00, this.m00) == 0 - && Float.compare(otherMatrix.m01, this.m01) == 0 - && Float.compare(otherMatrix.m02, this.m02) == 0 - && Float.compare(otherMatrix.m03, this.m03) == 0 - && Float.compare(otherMatrix.m10, this.m10) == 0 - && Float.compare(otherMatrix.m11, this.m11) == 0 - && Float.compare(otherMatrix.m12, this.m12) == 0 - && Float.compare(otherMatrix.m13, this.m13) == 0 - && Float.compare(otherMatrix.m20, this.m20) == 0 - && Float.compare(otherMatrix.m21, this.m21) == 0 - && Float.compare(otherMatrix.m22, this.m22) == 0 - && Float.compare(otherMatrix.m23, this.m23) == 0 - && Float.compare(otherMatrix.m30, this.m30) == 0 - && Float.compare(otherMatrix.m31, this.m31) == 0 - && Float.compare(otherMatrix.m32, this.m32) == 0 - && Float.compare(otherMatrix.m33, this.m33) == 0; - } - else - { - return false; - } - } - - @Override - public int hashCode() - { - int i = this.m00 != 0.0F ? Float.floatToIntBits(this.m00) : 0; - i = 31 * i + (this.m01 != 0.0F ? Float.floatToIntBits(this.m01) : 0); - i = 31 * i + (this.m02 != 0.0F ? Float.floatToIntBits(this.m02) : 0); - i = 31 * i + (this.m03 != 0.0F ? Float.floatToIntBits(this.m03) : 0); - i = 31 * i + (this.m10 != 0.0F ? Float.floatToIntBits(this.m10) : 0); - i = 31 * i + (this.m11 != 0.0F ? Float.floatToIntBits(this.m11) : 0); - i = 31 * i + (this.m12 != 0.0F ? Float.floatToIntBits(this.m12) : 0); - i = 31 * i + (this.m13 != 0.0F ? Float.floatToIntBits(this.m13) : 0); - i = 31 * i + (this.m20 != 0.0F ? Float.floatToIntBits(this.m20) : 0); - i = 31 * i + (this.m21 != 0.0F ? Float.floatToIntBits(this.m21) : 0); - i = 31 * i + (this.m22 != 0.0F ? Float.floatToIntBits(this.m22) : 0); - i = 31 * i + (this.m23 != 0.0F ? Float.floatToIntBits(this.m23) : 0); - i = 31 * i + (this.m30 != 0.0F ? Float.floatToIntBits(this.m30) : 0); - i = 31 * i + (this.m31 != 0.0F ? Float.floatToIntBits(this.m31) : 0); - i = 31 * i + (this.m32 != 0.0F ? Float.floatToIntBits(this.m32) : 0); - return 31 * i + (this.m33 != 0.0F ? Float.floatToIntBits(this.m33) : 0); + m20 = values[8]; + m21 = values[9]; + m22 = values[10]; + m23 = values[11]; + + m30 = values[12]; + m31 = values[13]; + m32 = values[14]; + m33 = values[15]; } - @Override - public String toString() - { - return "Matrix4f:\n" + - this.m00 + " " + this.m01 + " " + this.m02 + " " + this.m03 + "\n" + - this.m10 + " " + this.m11 + " " + this.m12 + " " + this.m13 + "\n" + - this.m20 + " " + this.m21 + " " + this.m22 + " " + this.m23 + "\n" + - this.m30 + " " + this.m31 + " " + this.m32 + " " + this.m33 + "\n"; - } - public void store(FloatBuffer floatBuffer) - { - floatBuffer.put(bufferIndex(0, 0), this.m00); - floatBuffer.put(bufferIndex(0, 1), this.m01); - floatBuffer.put(bufferIndex(0, 2), this.m02); - floatBuffer.put(bufferIndex(0, 3), this.m03); - floatBuffer.put(bufferIndex(1, 0), this.m10); - floatBuffer.put(bufferIndex(1, 1), this.m11); - floatBuffer.put(bufferIndex(1, 2), this.m12); - floatBuffer.put(bufferIndex(1, 3), this.m13); - floatBuffer.put(bufferIndex(2, 0), this.m20); - floatBuffer.put(bufferIndex(2, 1), this.m21); - floatBuffer.put(bufferIndex(2, 2), this.m22); - floatBuffer.put(bufferIndex(2, 3), this.m23); - floatBuffer.put(bufferIndex(3, 0), this.m30); - floatBuffer.put(bufferIndex(3, 1), this.m31); - floatBuffer.put(bufferIndex(3, 2), this.m32); - floatBuffer.put(bufferIndex(3, 3), this.m33); - } - - public Matrix4f createJomlMatrix() - { - return new Matrix4f( - this.m00, this.m10, this.m20, this.m30, - this.m01, this.m11, this.m21, this.m31, - this.m02, this.m12, this.m22, this.m32, - this.m03, this.m13, this.m23, this.m33 - ); - } - - - private static int bufferIndex(int xIndex, int zIndex) - { - return (zIndex * 4) + xIndex; - } - + //=========// + // methods // + //=========// public void setIdentity() { @@ -341,7 +221,7 @@ public class Mat4f } } - public void multiply(Mat4f multMatrix) + public void multiply(DhApiMat4f multMatrix) { float f = this.m00 * multMatrix.m00 + this.m01 * multMatrix.m10 + this.m02 * multMatrix.m20 + this.m03 * multMatrix.m30; float f1 = this.m00 * multMatrix.m01 + this.m01 * multMatrix.m11 + this.m02 * multMatrix.m21 + this.m03 * multMatrix.m31; @@ -377,13 +257,6 @@ public class Mat4f this.m33 = f15; } - /* Quaternions aren't currently needed/implemented - public void multiply(Quaternion p_226596_1_) - { - this.multiply(new Matrix4f(p_226596_1_)); - } - */ - public void multiply(float scalar) { this.m00 *= scalar; @@ -404,81 +277,7 @@ public class Mat4f this.m33 *= scalar; } - public static Mat4f perspective(double fov, float widthHeightRatio, float nearClipPlane, float farClipPlane) - { - float f = (float) (1.0D / Math.tan(fov * ((float) Math.PI / 180F) / 2.0D)); - Mat4f matrix = new Mat4f(); - matrix.m00 = f / widthHeightRatio; - matrix.m11 = f; - matrix.m22 = (farClipPlane + nearClipPlane) / (nearClipPlane - farClipPlane); - matrix.m32 = -1.0F; - matrix.m23 = 2.0F * farClipPlane * nearClipPlane / (nearClipPlane - farClipPlane); - return matrix; - } - - - /* not currently needed/implemented - * Also the parameter names should be double checked as they may be incorrect - public static Matrix4Float orthographic(float left, float right, float top, float bottom) - { - Matrix4Float matrix4f = new Matrix4Float(); - matrix4f.m00 = 2.0F / left; - matrix4f.m11 = 2.0F / right; - float f = bottom - top; - matrix4f.m22 = -2.0F / f; - matrix4f.m33 = 1.0F; - matrix4f.m03 = -1.0F; - matrix4f.m13 = -1.0F; - matrix4f.m23 = -(bottom + top) / f; - return matrix4f; - } - */ - - /** - * TODO: what kind of translation is this? - * and how is this different from "multiplyTranslationMatrix"? - * Answer: This is faster and direct (but only if this is pure translation matrix without rotate) - */ - public void translate(Vec3f vec) - { - this.m03 += vec.x; - this.m13 += vec.y; - this.m23 += vec.z; - } - - /** originally "translate" from Minecraft's MatrixStack */ - public void multiplyTranslationMatrix(double x, double y, double z) - { - multiply(createTranslateMatrix((float) x, (float) y, (float) z)); - } - - public Mat4f copy() - { - return new Mat4f(this); - } - - public static Mat4f createScaleMatrix(float x, float y, float z) - { - Mat4f matrix = new Mat4f(); - matrix.m00 = x; - matrix.m11 = y; - matrix.m22 = z; - matrix.m33 = 1.0F; - return matrix; - } - - public static Mat4f createTranslateMatrix(float x, float y, float z) - { - Mat4f matrix = new Mat4f(); - matrix.m00 = 1.0F; - matrix.m11 = 1.0F; - matrix.m22 = 1.0F; - matrix.m33 = 1.0F; - matrix.m03 = x; - matrix.m13 = y; - matrix.m23 = z; - return matrix; - } + public DhApiMat4f copy() { return new DhApiMat4f(this); } @@ -487,6 +286,8 @@ public class Mat4f // methods // //==================// + private static int getArrayIndex(int xIndex, int zIndex) { return (zIndex * 4) + xIndex; } + /** Returns the values of this matrix in row major order (AKA rows then columns) */ public float[] getValuesAsArray() { @@ -513,113 +314,74 @@ public class Mat4f }; } - public Vec3f asNonNormalizedLookForwardVector() + + + //================// + // base overrides // + //================// + + @Override + public boolean equals(Object obj) { - return new Vec3f(this.m02, this.m12, this.m22); + if (this == obj) + { + return true; + } + else if (obj != null && this.getClass() == obj.getClass()) + { + DhApiMat4f otherMatrix = (DhApiMat4f) obj; + return Float.compare(otherMatrix.m00, this.m00) == 0 + && Float.compare(otherMatrix.m01, this.m01) == 0 + && Float.compare(otherMatrix.m02, this.m02) == 0 + && Float.compare(otherMatrix.m03, this.m03) == 0 + && Float.compare(otherMatrix.m10, this.m10) == 0 + && Float.compare(otherMatrix.m11, this.m11) == 0 + && Float.compare(otherMatrix.m12, this.m12) == 0 + && Float.compare(otherMatrix.m13, this.m13) == 0 + && Float.compare(otherMatrix.m20, this.m20) == 0 + && Float.compare(otherMatrix.m21, this.m21) == 0 + && Float.compare(otherMatrix.m22, this.m22) == 0 + && Float.compare(otherMatrix.m23, this.m23) == 0 + && Float.compare(otherMatrix.m30, this.m30) == 0 + && Float.compare(otherMatrix.m31, this.m31) == 0 + && Float.compare(otherMatrix.m32, this.m32) == 0 + && Float.compare(otherMatrix.m33, this.m33) == 0; + } + else + { + return false; + } } - //===============// - // Forge methods // - //===============// - - public Mat4f(float[] values) + @Override + public int hashCode() { - m00 = values[0]; - m01 = values[1]; - m02 = values[2]; - m03 = values[3]; - m10 = values[4]; - m11 = values[5]; - m12 = values[6]; - m13 = values[7]; - m20 = values[8]; - m21 = values[9]; - m22 = values[10]; - m23 = values[11]; - m30 = values[12]; - m31 = values[13]; - m32 = values[14]; - m33 = values[15]; + int i = this.m00 != 0.0F ? Float.floatToIntBits(this.m00) : 0; + i = 31 * i + (this.m01 != 0.0F ? Float.floatToIntBits(this.m01) : 0); + i = 31 * i + (this.m02 != 0.0F ? Float.floatToIntBits(this.m02) : 0); + i = 31 * i + (this.m03 != 0.0F ? Float.floatToIntBits(this.m03) : 0); + i = 31 * i + (this.m10 != 0.0F ? Float.floatToIntBits(this.m10) : 0); + i = 31 * i + (this.m11 != 0.0F ? Float.floatToIntBits(this.m11) : 0); + i = 31 * i + (this.m12 != 0.0F ? Float.floatToIntBits(this.m12) : 0); + i = 31 * i + (this.m13 != 0.0F ? Float.floatToIntBits(this.m13) : 0); + i = 31 * i + (this.m20 != 0.0F ? Float.floatToIntBits(this.m20) : 0); + i = 31 * i + (this.m21 != 0.0F ? Float.floatToIntBits(this.m21) : 0); + i = 31 * i + (this.m22 != 0.0F ? Float.floatToIntBits(this.m22) : 0); + i = 31 * i + (this.m23 != 0.0F ? Float.floatToIntBits(this.m23) : 0); + i = 31 * i + (this.m30 != 0.0F ? Float.floatToIntBits(this.m30) : 0); + i = 31 * i + (this.m31 != 0.0F ? Float.floatToIntBits(this.m31) : 0); + i = 31 * i + (this.m32 != 0.0F ? Float.floatToIntBits(this.m32) : 0); + return 31 * i + (this.m33 != 0.0F ? Float.floatToIntBits(this.m33) : 0); } - public Mat4f(FloatBuffer buffer) + @Override + public String toString() { - this(buffer.array()); - } - - public void set(Mat4f mat) - { - this.m00 = mat.m00; - this.m01 = mat.m01; - this.m02 = mat.m02; - this.m03 = mat.m03; - this.m10 = mat.m10; - this.m11 = mat.m11; - this.m12 = mat.m12; - this.m13 = mat.m13; - this.m20 = mat.m20; - this.m21 = mat.m21; - this.m22 = mat.m22; - this.m23 = mat.m23; - this.m30 = mat.m30; - this.m31 = mat.m31; - this.m32 = mat.m32; - this.m33 = mat.m33; - } - - public void add(Mat4f other) - { - m00 += other.m00; - m01 += other.m01; - m02 += other.m02; - m03 += other.m03; - m10 += other.m10; - m11 += other.m11; - m12 += other.m12; - m13 += other.m13; - m20 += other.m20; - m21 += other.m21; - m22 += other.m22; - m23 += other.m23; - m30 += other.m30; - m31 += other.m31; - m32 += other.m32; - m33 += other.m33; - } - - public void multiplyBackward(Mat4f other) - { - Mat4f copy = other.copy(); - copy.multiply(this); - this.set(copy); - } - - public void setTranslation(float x, float y, float z) - { - this.m00 = 1.0F; - this.m11 = 1.0F; - this.m22 = 1.0F; - this.m33 = 1.0F; - this.m03 = x; - this.m13 = y; - this.m23 = z; - } - - /** - * Changes the values that store the clipping planes. - * Formula for calculating matrix values is the same that OpenGL uses when making matrices. - * - * @param nearClip New near clipping plane value. - * @param farClip New far clipping plane value. - */ - public void setClipPlanes(float nearClip, float farClip) - { - //convert to matrix values, formula copied from a textbook / openGL specification. - float matNearClip = -((farClip + nearClip) / (farClip - nearClip)); - float matFarClip = -((2 * farClip * nearClip) / (farClip - nearClip)); - //set new values for the clip planes. - this.m22 = matNearClip; - this.m23 = matFarClip; + return "Matrix4f:\n" + + this.m00 + " " + this.m01 + " " + this.m02 + " " + this.m03 + "\n" + + this.m10 + " " + this.m11 + " " + this.m12 + " " + this.m13 + "\n" + + this.m20 + " " + this.m21 + " " + this.m22 + " " + this.m23 + "\n" + + this.m30 + " " + this.m31 + " " + this.m32 + " " + this.m33 + "\n"; } } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java deleted file mode 100644 index 50488535a..000000000 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3f.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * This file is part of the Distant Horizons mod - * licensed under the GNU LGPL v3 License. - * - * Copyright (C) 2020-2023 James Seibel - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.seibel.distanthorizons.coreapi.util.math; - -import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; -import com.seibel.distanthorizons.coreapi.util.MathUtil; - -/** - * A (almost) exact copy of Minecraft's 1.16.5 - * implementation of a 3 element float vector. - * - * @author James Seibel - * @version 11-11-2021 - */ -public class Vec3f -{ - public static Vec3f XNeg = new Vec3f(-1.0F, 0.0F, 0.0F); - public static Vec3f XPos = new Vec3f(1.0F, 0.0F, 0.0F); - public static Vec3f YNeg = new Vec3f(0.0F, -1.0F, 0.0F); - public static Vec3f YPos = new Vec3f(0.0F, 1.0F, 0.0F); - public static Vec3f ZNeg = new Vec3f(0.0F, 0.0F, -1.0F); - public static Vec3f ZPos = new Vec3f(0.0F, 0.0F, 1.0F); - - - public float x; - public float y; - public float z; - - - - public Vec3f() - { - - } - - public Vec3f(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - } - - public Vec3f(DhApiVec3f pos) - { - this.x = pos.x; - this.y = pos.y; - this.z = pos.z; - } - - - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - else if (obj != null && this.getClass() == obj.getClass()) - { - Vec3f Vec3f = (Vec3f) obj; - if (Float.compare(Vec3f.x, this.x) != 0) - { - return false; - } - else if (Float.compare(Vec3f.y, this.y) != 0) - { - return false; - } - else - { - return Float.compare(Vec3f.z, this.z) == 0; - } - } - else - { - return false; - } - } - - @Override - public int hashCode() - { - int i = Float.floatToIntBits(this.x); - i = 31 * i + Float.floatToIntBits(this.y); - return 31 * i + Float.floatToIntBits(this.z); - } - - public void mul(float scalar) - { - this.x *= scalar; - this.y *= scalar; - this.z *= scalar; - } - - public void mul(float x, float y, float z) - { - this.x *= x; - this.y *= y; - this.z *= z; - } - - public void clamp(float min, float max) - { - this.x = MathUtil.clamp(min, this.x, max); - this.y = MathUtil.clamp(min, this.y, max); - this.z = MathUtil.clamp(min, this.z, max); - } - - public void set(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - } - - public void add(float x, float y, float z) - { - this.x += x; - this.y += y; - this.z += z; - } - - public void add(Vec3f vector) - { - this.x += vector.x; - this.y += vector.y; - this.z += vector.z; - } - - public void subtract(Vec3f vector) - { - this.x -= vector.x; - this.y -= vector.y; - this.z -= vector.z; - } - - public float dotProduct(Vec3f vector) - { - return this.x * vector.x + this.y * vector.y + this.z * vector.z; - } - - /** Returns true if normalization had to be done */ - public boolean normalize() - { - float squaredSum = this.x * this.x + this.y * this.y + this.z * this.z; - if (squaredSum < 1.0E-5D) - { - return false; - } - else - { - float f1 = MathUtil.fastInvSqrt(squaredSum); - this.x *= f1; - this.y *= f1; - this.z *= f1; - return true; - } - } - - public void crossProduct(Vec3f vector) - { - float f = this.x; - float f1 = this.y; - float f2 = this.z; - float f3 = vector.x; - float f4 = vector.y; - float f5 = vector.z; - this.x = f1 * f5 - f2 * f4; - this.y = f2 * f3 - f * f5; - this.z = f * f4 - f1 * f3; - } - - /* Matrix3f is not currently needed/implemented - public void transform(Matrix3f p_229188_1_) - { - float f = this.x; - float f1 = this.y; - float f2 = this.z; - this.x = p_229188_1_.m00 * f + p_229188_1_.m01 * f1 + p_229188_1_.m02 * f2; - this.y = p_229188_1_.m10 * f + p_229188_1_.m11 * f1 + p_229188_1_.m12 * f2; - this.z = p_229188_1_.m20 * f + p_229188_1_.m21 * f1 + p_229188_1_.m22 * f2; - } - */ - - /* Quaternions are not currently needed/implemented - public void transform(Quaternion p_214905_1_) - { - Quaternion quaternion = new Quaternion(p_214905_1_); - quaternion.mul(new Quaternion(this.x(), this.y(), this.z(), 0.0F)); - Quaternion quaternion1 = new Quaternion(p_214905_1_); - quaternion1.conj(); - quaternion.mul(quaternion1); - this.set(quaternion.i(), quaternion.j(), quaternion.k()); - } - */ - - /* not currently needed - * percent may actually be partial ticks (which is available when rendering) - public void linearInterp(Vec3f resultingVector, float percent) - { - float f = 1.0F - percent; - this.x = this.x * f + resultingVector.x * percent; - this.y = this.y * f + resultingVector.y * percent; - this.z = this.z * f + resultingVector.z * percent; - } - */ - - /* Quaternions are not currently needed/implemented - public Quaternion rotation(float p_229193_1_) - { - return new Quaternion(this, p_229193_1_, false); - } - - - @OnlyIn(Dist.CLIENT) - public Quaternion rotationDegrees(float p_229187_1_) - { - return new Quaternion(this, p_229187_1_, true); - } - */ - - public Vec3f copy() - { - return new Vec3f(this.x, this.y, this.z); - } - - /* not currently needed/implemented - public void map(Float2FloatFunction p_229191_1_) - { - this.x = p_229191_1_.get(this.x); - this.y = p_229191_1_.get(this.y); - this.z = p_229191_1_.get(this.z); - } - */ - - @Override - public String toString() - { - return "[" + this.x + ", " + this.y + ", " + this.z + "]"; - } - - // Forge start - public Vec3f(float[] values) - { - set(values); - } - - public void set(float[] values) - { - this.x = values[0]; - this.y = values[1]; - this.z = values[2]; - } - -} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java index d08989ad8..5380546b7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java @@ -35,6 +35,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RayCastUtil; +import com.seibel.distanthorizons.core.util.math.Vec3f; import com.seibel.distanthorizons.core.world.AbstractDhWorld; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; @@ -43,9 +44,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRen import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; -import com.seibel.distanthorizons.coreapi.util.math.Vec3d; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; -import com.seibel.distanthorizons.coreapi.util.math.Vec3i; +import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3i; import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -414,7 +414,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo */ private static ArrayList getIntersectingColumnsAtPosition(Vec3i rayEndingPos, Vec3f rayDirection) { - ArrayList returnList = new ArrayList(9); + ArrayList returnList = new ArrayList<>(9); for (int x = -1; x <= 1; x++) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index 4682c9de0..5ba929f49 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -38,7 +38,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.logging.SpamReducedLogger; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.renderer.TestRenderer; import com.seibel.distanthorizons.core.util.RenderUtil; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/enums/EDhDirection.java b/core/src/main/java/com/seibel/distanthorizons/core/enums/EDhDirection.java index ff7cebd50..757200b18 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/enums/EDhDirection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/enums/EDhDirection.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.function.Predicate; import java.util.stream.Collectors; -import com.seibel.distanthorizons.coreapi.util.math.Vec3i; +import com.seibel.distanthorizons.core.util.math.Vec3i; /** * An (almost) exact copy of Minecraft's diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/DhFrustumBounds.java b/core/src/main/java/com/seibel/distanthorizons/core/render/DhFrustumBounds.java index cf18751b8..0ef0b5f56 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/DhFrustumBounds.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/DhFrustumBounds.java @@ -1,8 +1,9 @@ package com.seibel.distanthorizons.core.render; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import org.joml.FrustumIntersection; import org.joml.Matrix4f; import org.joml.Matrix4fc; @@ -35,12 +36,12 @@ public class DhFrustumBounds implements IDhApiCullingFrustum //=========// @Override - public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f dhWorldViewProjection) + public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f dhWorldViewProjection) { this.worldMinY = worldMinBlockY; this.worldMaxY = worldMaxBlockY; - Matrix4f worldViewProjection = new Matrix4f(dhWorldViewProjection.createJomlMatrix()); + Matrix4f worldViewProjection = new Matrix4f(Mat4f.createJomlMatrix(dhWorldViewProjection)); this.frustum.set(worldViewProjection); Matrix4fc matWorldViewProjectionInv = new Matrix4f(worldViewProjection).invert(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java b/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java index 7e10b0b44..611aa0ad6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java @@ -2,8 +2,9 @@ package com.seibel.distanthorizons.core.render; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; /** * Dummy {@link IDhApiCullingFrustum} that allows everything through.
@@ -24,7 +25,7 @@ public class NeverCullFrustum implements IDhApiCullingFrustum, IDhApiShadowCulli //=========// @Override - public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f dhWorldViewProjection) { /* update isn't needed */ } + public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f dhWorldViewProjection) { /* update isn't needed */ } @Override public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) { return true; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index f36280ae8..39e7a26e5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -41,9 +41,9 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRen import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector; -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 com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3f; import org.apache.logging.log4j.Logger; import org.joml.Matrix4f; import org.joml.Matrix4fc; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java index 2870cf76a..b7e932e2d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java @@ -29,9 +29,9 @@ import java.util.function.Supplier; import org.lwjgl.opengl.GL32; import org.lwjgl.system.MemoryStack; -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 com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3f; /** diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java index 7bc0ac7d7..d2b573f7b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java @@ -36,9 +36,9 @@ import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute; import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; -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 com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3f; import org.apache.logging.log4j.LogManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 64382386b..8589a0d53 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -39,9 +39,9 @@ import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractV import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; -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 com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3f; import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; import it.unimi.dsi.fastutil.longs.LongSet; import org.apache.logging.log4j.LogManager; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java index a9a8f9693..7f63649c5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java @@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.render.renderer; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShaderProgram; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.shader.Shader; @@ -31,8 +32,8 @@ import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAtt import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RenderUtil; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; +import com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3f; public class LodRenderProgram extends ShaderProgram implements IDhApiShaderProgram { @@ -201,7 +202,7 @@ public class LodRenderProgram extends ShaderProgram implements IDhApiShaderProgr } @Override - public void setModelOffsetPos(Vec3f modelOffsetPos) { this.setUniform(this.modelOffsetUniform, modelOffsetPos); } + public void setModelOffsetPos(DhApiVec3f modelOffsetPos) { this.setUniform(this.modelOffsetUniform, new Vec3f(modelOffsetPos)); } @Override public int getId() { return this.id; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 564bc25a7..0e8768c48 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -50,9 +50,9 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccess import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; -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 com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3f; import org.apache.logging.log4j.LogManager; import org.lwjgl.opengl.GL32; @@ -386,7 +386,7 @@ public class LodRenderer if (Config.Client.Advanced.Graphics.Ssao.enabled.get()) { profiler.popPush("LOD SSAO"); - SSAORenderer.INSTANCE.render(minecraftGlState, renderEventParam.dhProjectionMatrix, renderEventParam.partialTicks); + SSAORenderer.INSTANCE.render(minecraftGlState, new Mat4f(renderEventParam.dhProjectionMatrix), renderEventParam.partialTicks); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java index 77519aa8c..97c5d1cde 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java @@ -24,7 +24,7 @@ import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOApplyShader; import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOShader; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import org.lwjgl.opengl.GL32; import java.nio.ByteBuffer; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java index e5a1fc255..73bfb846e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java @@ -31,7 +31,7 @@ import com.seibel.distanthorizons.core.render.renderer.ScreenQuad; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import org.lwjgl.opengl.GL32; import java.awt.*; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java index 867f891e0..d7659a1e0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java @@ -24,7 +24,7 @@ import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; import com.seibel.distanthorizons.core.render.renderer.LodRenderer; import com.seibel.distanthorizons.core.render.renderer.SSAORenderer; import com.seibel.distanthorizons.core.render.renderer.ScreenQuad; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Mat4f; import org.lwjgl.opengl.GL32; /** diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java index 05fb69b54..e49c2028a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java @@ -30,8 +30,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftCli import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.coreapi.util.MathUtil; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; -import com.seibel.distanthorizons.coreapi.util.math.Vec3f; +import com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3f; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; /** diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/math/Mat4f.java b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Mat4f.java new file mode 100644 index 000000000..27c8bbb97 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Mat4f.java @@ -0,0 +1,249 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.util.math; + +import com.seibel.distanthorizons.api.objects.math.DhApiMat4f; +import org.joml.Matrix4f; +import org.joml.Matrix4fc; + +import java.nio.FloatBuffer; + +/** + * An (almost) exact copy of Minecraft's 1.16.5 + * implementation of a 4x4 float matrix. + * + * @author James Seibel + * @version 11-11-2021 + */ +public class Mat4f extends DhApiMat4f +{ + + //==============// + // constructors // + //==============// + + public Mat4f() { /* all values are 0 */ } + + public Mat4f(DhApiMat4f sourceMatrix) { super(sourceMatrix); } + + /** Expects the values of the input buffer to be in row major order (AKA rows then columns) */ + public Mat4f(FloatBuffer buffer) { this(buffer.array()); } + /** Expects the values of the input array to be in row major order (AKA rows then columns) */ + public Mat4f(float[] values) { super(values); } + + public Mat4f(Matrix4fc sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); } + private static float[] convertJomlMatrixToArray(Matrix4fc sourceMatrix) + { + FloatBuffer buffer = FloatBuffer.allocate(16); + + buffer.put(bufferIndex(0, 0), sourceMatrix.m00()); + buffer.put(bufferIndex(0, 1), sourceMatrix.m01()); + buffer.put(bufferIndex(0, 2), sourceMatrix.m02()); + buffer.put(bufferIndex(0, 3), sourceMatrix.m03()); + + buffer.put(bufferIndex(1, 0), sourceMatrix.m10()); + buffer.put(bufferIndex(1, 1), sourceMatrix.m11()); + buffer.put(bufferIndex(1, 2), sourceMatrix.m12()); + buffer.put(bufferIndex(1, 3), sourceMatrix.m13()); + + buffer.put(bufferIndex(2, 0), sourceMatrix.m20()); + buffer.put(bufferIndex(2, 1), sourceMatrix.m21()); + buffer.put(bufferIndex(2, 2), sourceMatrix.m22()); + buffer.put(bufferIndex(2, 3), sourceMatrix.m23()); + + buffer.put(bufferIndex(3, 0), sourceMatrix.m30()); + buffer.put(bufferIndex(3, 1), sourceMatrix.m31()); + buffer.put(bufferIndex(3, 2), sourceMatrix.m32()); + buffer.put(bufferIndex(3, 3), sourceMatrix.m33()); + + return buffer.array(); + } + private static int bufferIndex(int xIndex, int zIndex) { return (zIndex * 4) + xIndex; } + + + public void store(FloatBuffer floatBuffer) + { + floatBuffer.put(bufferIndex(0, 0), this.m00); + floatBuffer.put(bufferIndex(0, 1), this.m01); + floatBuffer.put(bufferIndex(0, 2), this.m02); + floatBuffer.put(bufferIndex(0, 3), this.m03); + floatBuffer.put(bufferIndex(1, 0), this.m10); + floatBuffer.put(bufferIndex(1, 1), this.m11); + floatBuffer.put(bufferIndex(1, 2), this.m12); + floatBuffer.put(bufferIndex(1, 3), this.m13); + floatBuffer.put(bufferIndex(2, 0), this.m20); + floatBuffer.put(bufferIndex(2, 1), this.m21); + floatBuffer.put(bufferIndex(2, 2), this.m22); + floatBuffer.put(bufferIndex(2, 3), this.m23); + floatBuffer.put(bufferIndex(3, 0), this.m30); + floatBuffer.put(bufferIndex(3, 1), this.m31); + floatBuffer.put(bufferIndex(3, 2), this.m32); + floatBuffer.put(bufferIndex(3, 3), this.m33); + } + + + public static Matrix4f createJomlMatrix(DhApiMat4f matrix) + { + return new Matrix4f( + matrix.m00, matrix.m10, matrix.m20, matrix.m30, + matrix.m01, matrix.m11, matrix.m21, matrix.m31, + matrix.m02, matrix.m12, matrix.m22, matrix.m32, + matrix.m03, matrix.m13, matrix.m23, matrix.m33 + ); + } + public Matrix4f createJomlMatrix() + { + return new Matrix4f( + this.m00, this.m10, this.m20, this.m30, + this.m01, this.m11, this.m21, this.m31, + this.m02, this.m12, this.m22, this.m32, + this.m03, this.m13, this.m23, this.m33 + ); + } + + + + //=========// + // methods // + //=========// + + public static Mat4f perspective(double fov, float widthHeightRatio, float nearClipPlane, float farClipPlane) + { + float f = (float) (1.0D / Math.tan(fov * ((float) Math.PI / 180F) / 2.0D)); + Mat4f matrix = new Mat4f(); + matrix.m00 = f / widthHeightRatio; + matrix.m11 = f; + matrix.m22 = (farClipPlane + nearClipPlane) / (nearClipPlane - farClipPlane); + matrix.m32 = -1.0F; + matrix.m23 = 2.0F * farClipPlane * nearClipPlane / (nearClipPlane - farClipPlane); + return matrix; + } + + /** originally "translate" from Minecraft's MatrixStack */ + public void multiplyTranslationMatrix(double x, double y, double z) + { multiply(createTranslateMatrix((float) x, (float) y, (float) z)); } + + public static Mat4f createScaleMatrix(float x, float y, float z) + { + Mat4f matrix = new Mat4f(); + matrix.m00 = x; + matrix.m11 = y; + matrix.m22 = z; + matrix.m33 = 1.0F; + return matrix; + } + + public static Mat4f createTranslateMatrix(float x, float y, float z) + { + Mat4f matrix = new Mat4f(); + matrix.m00 = 1.0F; + matrix.m11 = 1.0F; + matrix.m22 = 1.0F; + matrix.m33 = 1.0F; + matrix.m03 = x; + matrix.m13 = y; + matrix.m23 = z; + return matrix; + } + + + + //===============// + // Forge methods // + //===============// + + public void set(DhApiMat4f mat) + { + this.m00 = mat.m00; + this.m01 = mat.m01; + this.m02 = mat.m02; + this.m03 = mat.m03; + this.m10 = mat.m10; + this.m11 = mat.m11; + this.m12 = mat.m12; + this.m13 = mat.m13; + this.m20 = mat.m20; + this.m21 = mat.m21; + this.m22 = mat.m22; + this.m23 = mat.m23; + this.m30 = mat.m30; + this.m31 = mat.m31; + this.m32 = mat.m32; + this.m33 = mat.m33; + } + + public void add(DhApiMat4f other) + { + m00 += other.m00; + m01 += other.m01; + m02 += other.m02; + m03 += other.m03; + m10 += other.m10; + m11 += other.m11; + m12 += other.m12; + m13 += other.m13; + m20 += other.m20; + m21 += other.m21; + m22 += other.m22; + m23 += other.m23; + m30 += other.m30; + m31 += other.m31; + m32 += other.m32; + m33 += other.m33; + } + + public void multiplyBackward(DhApiMat4f other) + { + DhApiMat4f copy = other.copy(); + copy.multiply(this); + this.set(copy); + } + + public void setTranslation(float x, float y, float z) + { + this.m00 = 1.0F; + this.m11 = 1.0F; + this.m22 = 1.0F; + this.m33 = 1.0F; + this.m03 = x; + this.m13 = y; + this.m23 = z; + } + + /** + * Changes the values that store the clipping planes. + * Formula for calculating matrix values is the same that OpenGL uses when making matrices. + * + * @param nearClip New near clipping plane value. + * @param farClip New far clipping plane value. + */ + public void setClipPlanes(float nearClip, float farClip) + { + //convert to matrix values, formula copied from a textbook / openGL specification. + float matNearClip = -((farClip + nearClip) / (farClip - nearClip)); + float matFarClip = -((2 * farClip * nearClip) / (farClip - nearClip)); + //set new values for the clip planes. + this.m22 = matNearClip; + this.m23 = matFarClip; + } + + public Mat4f copy() { return new Mat4f(this); } + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3d.java b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3d.java similarity index 99% rename from api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3d.java rename to core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3d.java index a1374d8de..1eb4da89a 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3d.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3d.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.seibel.distanthorizons.coreapi.util.math; +package com.seibel.distanthorizons.core.util.math; import com.seibel.distanthorizons.coreapi.util.MathUtil; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3f.java b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3f.java new file mode 100644 index 000000000..dbc502f52 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3f.java @@ -0,0 +1,150 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.util.math; + +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.coreapi.util.MathUtil; + +/** + * A (almost) exact copy of Minecraft's 1.16.5 + * implementation of a 3 element float vector. + * + * @author James Seibel + * @version 11-11-2021 + */ +public class Vec3f extends DhApiVec3f +{ + //==============// + // constructors // + //==============// + + public Vec3f() { this(0,0,0); } + + public Vec3f(float x, float y, float z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public Vec3f(DhApiVec3f pos) + { + this.x = pos.x; + this.y = pos.y; + this.z = pos.z; + } + + + + //==============// + // math methods // + //==============// + + public void mul(float scalar) + { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + } + + public void mul(float x, float y, float z) + { + this.x *= x; + this.y *= y; + this.z *= z; + } + + public void clamp(float min, float max) + { + this.x = MathUtil.clamp(min, this.x, max); + this.y = MathUtil.clamp(min, this.y, max); + this.z = MathUtil.clamp(min, this.z, max); + } + + public void add(float x, float y, float z) + { + this.x += x; + this.y += y; + this.z += z; + } + + public void add(Vec3f vector) + { + this.x += vector.x; + this.y += vector.y; + this.z += vector.z; + } + + public void subtract(Vec3f vector) + { + this.x -= vector.x; + this.y -= vector.y; + this.z -= vector.z; + } + + public float dotProduct(Vec3f vector) { return this.x * vector.x + this.y * vector.y + this.z * vector.z; } + + /** @return true if normalization had to be done */ + public boolean normalize() + { + float squaredSum = this.x * this.x + this.y * this.y + this.z * this.z; + if (squaredSum < 1.0E-5D) + { + return false; + } + else + { + float f1 = MathUtil.fastInvSqrt(squaredSum); + this.x *= f1; + this.y *= f1; + this.z *= f1; + return true; + } + } + + public void crossProduct(Vec3f vector) + { + float f = this.x; + float f1 = this.y; + float f2 = this.z; + float f3 = vector.x; + float f4 = vector.y; + float f5 = vector.z; + this.x = f1 * f5 - f2 * f4; + this.y = f2 * f3 - f * f5; + this.z = f * f4 - f1 * f3; + } + + + + //==============// + // misc methods // + //==============// + + public void set(float x, float y, float z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public Vec3f copy() { return new Vec3f(this.x, this.y, this.z); } + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3i.java b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3i.java similarity index 98% rename from api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3i.java rename to core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3i.java index c85fdea51..bd4d609e1 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/util/math/Vec3i.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3i.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.seibel.distanthorizons.coreapi.util.math; +package com.seibel.distanthorizons.core.util.math; import com.seibel.distanthorizons.coreapi.util.MathUtil; import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java index 42d355520..2fc860772 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftRenderWrapper.java @@ -28,9 +28,9 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; -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 com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.core.util.math.Vec3f; import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor; From 6c8060fa87268ba04011c6a6703d694e8b6722f9 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 16:33:54 -0500 Subject: [PATCH 019/104] Up API version 2.1.0 -> 3.0.0 --- .../main/java/com/seibel/distanthorizons/coreapi/ModInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java index 9f2740bb6..023da56cd 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/ModInfo.java @@ -39,9 +39,9 @@ public final class ModInfo public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev"); /** This version should only be updated when breaking changes are introduced to the DH API */ - public static final int API_MAJOR_VERSION = 2; + public static final int API_MAJOR_VERSION = 3; /** This version should be updated whenever new methods are added to the DH API */ - public static final int API_MINOR_VERSION = 1; + public static final int API_MINOR_VERSION = 0; /** This version should be updated whenever non-breaking fixes are added to the DH API */ public static final int API_PATH_VERSION = 0; From 4a025de9d6a35cea17620b6dbed69b8df19c3383 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 17:45:50 -0500 Subject: [PATCH 020/104] Add generic object sky/block light --- .../render/IDhApiRenderableBoxGroup.java | 8 ++ .../objects/render/DhApiRenderableBox.java | 3 - .../renderer/GenericObjectRenderer.java | 83 +++++++++++++++---- .../shaders/genericObject/direct/frag.frag | 10 ++- .../shaders/genericObject/instanced/vert.vert | 10 ++- 5 files changed, 93 insertions(+), 21 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java index 78174b76d..bf5280941 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -47,4 +47,12 @@ public interface IDhApiRenderableBoxGroup extends List */ void triggerBoxChange(); + /** Only accepts values between 0 and 15 */ + void setSkyLight(int skyLight); + int getSkyLight(); + + /** Only accepts values between 0 and 15 */ + void setBlockLight(int blockLight); + int getBlockLight(); + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java index 6969d33ee..23e1296d4 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java @@ -22,9 +22,6 @@ public class DhApiRenderableBox public Color color; - /* TODO */ - //public boolean fullBright = false; - //==============// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 8589a0d53..6a01a7072 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -37,6 +37,7 @@ import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute; import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; +import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.util.math.Mat4f; @@ -100,12 +101,16 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // shader uniforms - private int directShaderTransformUniformLocation; - private int directShaderColorUniformLocation; + private int directShaderTransformUniform; + private int directShaderColorUniform; - private int instancedShaderOffsetUniformLocation; - private int instancedShaderCameraPosUniformLocation; - private int instancedShaderProjectionModelViewMatrixUniformLocation; + private int instancedShaderOffsetUniform; + private int instancedShaderCameraPosUniform; + private int instancedShaderProjectionModelViewMatrixUniform; + + private int lightMapUniform; + private int skyLightUniform; + private int blockLightUniform; // TODO may need to be double buffered to prevent rendering lag @@ -171,7 +176,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.useInstancedRendering = this.vertexAttribDivisorSupported || this.instancedArraysSupported; if (!this.useInstancedRendering) { - LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering may be slow."); + LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering will be slow."); } @@ -186,12 +191,16 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.useInstancedRendering ? "shaders/genericObject/instanced/frag.frag" : "shaders/genericObject/direct/frag.frag", "fragColor", new String[]{"vPosition"}); - this.directShaderTransformUniformLocation = this.shader.tryGetUniformLocation("uTransform"); - this.directShaderColorUniformLocation = this.shader.tryGetUniformLocation("uColor"); + this.directShaderTransformUniform = this.shader.tryGetUniformLocation("uTransform"); + this.directShaderColorUniform = this.shader.tryGetUniformLocation("uColor"); - this.instancedShaderOffsetUniformLocation = this.shader.tryGetUniformLocation("uOffset"); - this.instancedShaderCameraPosUniformLocation = this.shader.tryGetUniformLocation("uCameraPos"); - this.instancedShaderProjectionModelViewMatrixUniformLocation = this.shader.tryGetUniformLocation("uProjectionMvm"); + this.instancedShaderOffsetUniform = this.shader.tryGetUniformLocation("uOffset"); + this.instancedShaderCameraPosUniform = this.shader.tryGetUniformLocation("uCameraPos"); + this.instancedShaderProjectionModelViewMatrixUniform = this.shader.tryGetUniformLocation("uProjectionMvm"); + + this.lightMapUniform = this.shader.getUniformLocation("uLightMap"); + this.skyLightUniform = this.shader.getUniformLocation("uSkyLight"); + this.blockLightUniform = this.shader.getUniformLocation("uBlockLight"); this.createBuffers(); @@ -230,6 +239,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new DhApiVec3f(0f,0f,0f), new DhApiVec3f(16f,190f,16f), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) ); + singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); + singleGiantBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); DhApi.Delayed.renderRegister.add(singleGiantBoxGroup); @@ -239,6 +250,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new DhApiVec3f(16f,0f,31f), new DhApiVec3f(17f,2000f,32f), new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) ); + singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); + singleTallBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); DhApi.Delayed.renderRegister.add(singleTallBoxGroup); @@ -477,23 +490,27 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister boxGroup.updateVertexAttributeData(); - this.shader.setUniform(this.instancedShaderOffsetUniformLocation, + this.shader.setUniform(this.instancedShaderOffsetUniform, new Vec3f( boxGroup.originBlockPos.x, boxGroup.originBlockPos.y, boxGroup.originBlockPos.z )); - this.shader.setUniform(this.instancedShaderCameraPosUniformLocation, + this.shader.setUniform(this.instancedShaderCameraPosUniform, new Vec3f( camPos.x, camPos.y, camPos.z )); - this.shader.setUniform(this.instancedShaderProjectionModelViewMatrixUniformLocation, + this.shader.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, projectionMvmMatrix); + this.shader.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in + this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); + this.shader.setUniform(this.blockLightUniform, boxGroup.blockLight); + @@ -555,6 +572,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private void renderBoxGroupDirect(RenderableBoxGroup boxGroup, Mat4f transformMatrix, Vec3f camPos) { + this.shader.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in + this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); + this.shader.setUniform(this.blockLightUniform, boxGroup.blockLight); + for (DhApiRenderableBox box : boxGroup.boxList) { renderBox(boxGroup, box, transformMatrix, camPos); @@ -584,9 +605,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister box.maxPos.z - box.minPos.z)); Mat4f transformMatrix = transformationMatrix.copy(); transformMatrix.multiply(boxTransform); - this.shader.setUniform(this.directShaderTransformUniformLocation, transformMatrix); + this.shader.setUniform(this.directShaderTransformUniform, transformMatrix); - this.shader.setUniform(this.directShaderColorUniformLocation, box.color); + this.shader.setUniform(this.directShaderColorUniform, box.color); GL32.glDrawElements(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } @@ -614,6 +635,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private final Vec3f originBlockPos; + public int skyLight = 15; + public int blockLight = 0; + @Nullable public Consumer beforeRenderFunc; @@ -644,8 +668,35 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister public DhApiVec3f getOriginBlockPos() { return new DhApiVec3f(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } + @Override + public void setSkyLight(int skyLight) + { + if (skyLight < LodUtil.MIN_MC_LIGHT || skyLight > LodUtil.MAX_MC_LIGHT) + { + throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); + } + this.skyLight = skyLight; + } + @Override + public int getSkyLight() { return this.skyLight; } + @Override + public void setBlockLight(int blockLight) + { + if (blockLight < LodUtil.MIN_MC_LIGHT || blockLight > LodUtil.MAX_MC_LIGHT) + { + throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); + } + this.blockLight = blockLight; + } + @Override + public int getBlockLight() { return this.blockLight; } + + + + //=============// // constructor // + //=============// public RenderableBoxGroup(Vec3f originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) { diff --git a/core/src/main/resources/shaders/genericObject/direct/frag.frag b/core/src/main/resources/shaders/genericObject/direct/frag.frag index 1f22d751c..31bd493b0 100644 --- a/core/src/main/resources/shaders/genericObject/direct/frag.frag +++ b/core/src/main/resources/shaders/genericObject/direct/frag.frag @@ -1,9 +1,17 @@ #version 150 core uniform vec4 uColor; +uniform int uSkyLight; +uniform int uBlockLight; +uniform sampler2D uLightMap; + out vec4 fragColor; void main() { - fragColor = uColor; + float blockLight = (float(uBlockLight)+0.5) / 16.0; + float skyLight = (float(uSkyLight)+0.5) / 16.0; + vec4 lightColor = vec4(texture(uLightMap, vec2(blockLight, skyLight)).xyz, 1.0); + + fragColor = lightColor * uColor; } \ No newline at end of file diff --git a/core/src/main/resources/shaders/genericObject/instanced/vert.vert b/core/src/main/resources/shaders/genericObject/instanced/vert.vert index 0849e9f7c..42625d29f 100644 --- a/core/src/main/resources/shaders/genericObject/instanced/vert.vert +++ b/core/src/main/resources/shaders/genericObject/instanced/vert.vert @@ -7,6 +7,9 @@ layout (location = 3) in vec3 aScale; uniform vec3 uOffset; uniform vec3 uCameraPos; uniform mat4 uProjectionMvm; +uniform int uSkyLight; +uniform int uBlockLight; +uniform sampler2D uLightMap; in vec3 vPosition; @@ -34,5 +37,10 @@ void main() ); gl_Position = uProjectionMvm * transform * vec4(vPosition, 1.0); - fColor = aColor; + + float blockLight = (float(uBlockLight)+0.5) / 16.0; + float skyLight = (float(uSkyLight)+0.5) / 16.0; + vec4 lightColor = vec4(texture(uLightMap, vec2(blockLight, skyLight)).xyz, 1.0); + + fColor = lightColor * aColor; } \ No newline at end of file From 72d6cb9697a8b010cc3a157948e11ce810d76c93 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 18:08:00 -0500 Subject: [PATCH 021/104] Disable debug generic object rendering --- .../core/render/renderer/GenericObjectRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 6a01a7072..027e10361 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -84,7 +84,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister * Can be used to troubleshoot the renderer. * If enabled several debug objects will render around (0,150,0). */ - public static final boolean RENDER_DEBUG_OBJECTS = true; + public static final boolean RENDER_DEBUG_OBJECTS = false; // rendering setup From 51de347bdd4b23c6ca14e801f27daa0de8755217 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 30 Jun 2024 18:08:47 -0500 Subject: [PATCH 022/104] Add temporary proof-of-concept beacon rendering --- .../transformers/LodDataBuilder.java | 27 +++++++++++++++++++ .../renderer/GenericObjectRenderer.java | 6 +++++ 2 files changed, 33 insertions(+) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index 5f3001621..34bd93883 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -19,12 +19,16 @@ package com.seibel.distanthorizons.core.dataObjects.transformers; +import java.awt.*; import java.util.List; import com.seibel.distanthorizons.api.enums.config.EDhApiWorldCompressionMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.objects.data.DhApiChunk; import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -33,6 +37,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.DataCorruptedException; @@ -212,6 +217,28 @@ public class LodDataBuilder longs.add(FullDataPointUtil.encode(mappedId, lastY - y, y + 1 - chunkWrapper.getMinBuildHeight(), blockLight, skyLight)); biome = newBiome; blockState = newBlockState; + + // TODO temp + if (blockState.getSerialString().contains("beacon")) + { + int blockX = chunkWrapper.getChunkPos().x * LodUtil.CHUNK_WIDTH + relBlockX; + int blockZ = chunkWrapper.getChunkPos().z * LodUtil.CHUNK_WIDTH + relBlockZ; + + if (GenericObjectRenderer.INSTANCE.testBeaconPosSet + .add(new DhBlockPos(blockX, y, blockZ))) + { + IDhApiRenderableBoxGroup beaconBeam = GenericObjectRenderer.INSTANCE.createForSingleBox( + new DhApiRenderableBox( + new DhApiVec3f(blockX, y+1, blockZ), + new DhApiVec3f(blockX+1, 5_000, blockZ+1), + Color.WHITE) + ); + beaconBeam.setBlockLight(15); + beaconBeam.setSkyLight(15); + GenericObjectRenderer.INSTANCE.add(beaconBeam); + } + } + mappedId = dataSource.mapping.addIfNotPresentAndGetId(biome, blockState); blockLight = newBlockLight; skyLight = newSkyLight; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 027e10361..7c5b3bf70 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -30,6 +30,7 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer; @@ -118,6 +119,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private final ReentrantLock mapModifyLock = new ReentrantLock(); + // TODO just for testing + @Deprecated + public final HashSet testBeaconPosSet = new HashSet<>(); + + /** A box from 0,0,0 to 1,1,1 */ private static final float[] BOX_VERTICES = { From 6a398e65145d93bc6b2d731b5974238ffae40ddc Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 1 Jul 2024 07:51:08 -0500 Subject: [PATCH 023/104] Start adding beacon beam repo handling --- .../core/api/internal/SharedApi.java | 10 +- .../core/level/AbstractDhLevel.java | 122 +++++++++++++- .../core/level/DhClientLevel.java | 2 +- .../core/level/DhClientServerLevel.java | 2 +- .../core/level/DhServerLevel.java | 2 +- .../distanthorizons/core/level/IDhLevel.java | 5 + .../renderer/GenericObjectRenderer.java | 1 + .../core/sql/dto/BeaconBeamDTO.java | 55 +++++++ .../core/sql/repo/BeaconBeamRepo.java | 152 ++++++++++++++++++ .../chunk/IChunkWrapper.java | 22 +++ .../0070-sqlite-createBeaconBeamTable.sql | 16 ++ .../main/resources/sqlScripts/scriptList.txt | 1 + 12 files changed, 385 insertions(+), 5 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/sql/dto/BeaconBeamDTO.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java create mode 100644 core/src/main/resources/sqlScripts/0070-sqlite-createBeaconBeamTable.sql diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index 000685011..6b1ccc4d3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -26,10 +26,12 @@ import com.seibel.distanthorizons.core.generation.DhLightingEngine; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; +import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; -import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.util.TimerUtil; import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; @@ -345,6 +347,12 @@ public class SharedApi DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, dhLevel.hasSkyLight() ? 15 : 0); } + + // get this chunk's active beacons + List beaconBeamList = chunkWrapper.getAllActiveBeacons(); + dhLevel.ensureBeaconBeamsAtPos(DhSectionPos.encode(chunkWrapper.getChunkPos()), beaconBeamList); + + dhLevel.updateChunkAsync(chunkWrapper); dhLevel.setChunkHash(chunkWrapper.getChunkPos(), newChunkHash); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 6cb44e31e..6831cb403 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -19,14 +19,21 @@ package com.seibel.distanthorizons.core.level; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkModifiedEvent; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dataObjects.transformers.ChunkToLodBuilder; import com.seibel.distanthorizons.core.file.fullDatafile.DelayedFullDataSourceSaveCache; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO; +import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; import com.seibel.distanthorizons.core.sql.repo.ChunkHashRepo; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; @@ -35,7 +42,10 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; public abstract class AbstractDhLevel implements IDhLevel @@ -47,6 +57,9 @@ public abstract class AbstractDhLevel implements IDhLevel /** if this is null then the other handler is probably null too, but just in case */ @Nullable public ChunkHashRepo chunkHashRepo; + /** if this is null then the other handler is probably null too, but just in case */ + @Nullable + public BeaconBeamRepo beaconBeamRepo; protected final DelayedFullDataSourceSaveCache delayedFullDataSourceSaveCache = new DelayedFullDataSourceSaveCache(this::onDataSourceSave, 2_000); /** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */ @@ -60,8 +73,9 @@ public abstract class AbstractDhLevel implements IDhLevel protected AbstractDhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); } - protected void createAndSetChunkHashRepo(File databaseFile) + protected void createAndSetSupportingRepos(File databaseFile) { + // chunk hash ChunkHashRepo newChunkHashRepo = null; try { @@ -72,6 +86,19 @@ public abstract class AbstractDhLevel implements IDhLevel LOGGER.error("Unable to create [ChunkHashRepo], error: ["+e.getMessage()+"].", e); } this.chunkHashRepo = newChunkHashRepo; + + + // beacon beam + BeaconBeamRepo newBeaconBeamRepo = null; + try + { + newBeaconBeamRepo = new BeaconBeamRepo("jdbc:sqlite", databaseFile); + } + catch (SQLException e) + { + LOGGER.error("Unable to create [BeaconBeamRepo], error: ["+e.getMessage()+"].", e); + } + this.beaconBeamRepo = newBeaconBeamRepo; } @@ -126,6 +153,13 @@ public abstract class AbstractDhLevel implements IDhLevel } + + //=======// + // repos // + //=======// + + // chunk hash // + @Override public int getChunkHash(DhChunkPos pos) { @@ -148,6 +182,92 @@ public abstract class AbstractDhLevel implements IDhLevel + // beacon beam // + + @Override + public List getAllBeamsForSectionPos(long pos) + { + if (this.beaconBeamRepo != null) + { + return this.beaconBeamRepo.getAllBeamsForSectionPos(pos); + } + else + { + return new ArrayList<>(0); + } + } + + + HashMap beamRenderGroupByPos = new HashMap<>(); + + @Override + public void ensureBeaconBeamsAtPos(long pos, List newBeamList) + { + if (this.beaconBeamRepo != null) + { + HashSet allPosSet = new HashSet<>(); + + // sort new beams + HashMap newBeamByPos = new HashMap<>(newBeamList.size()); + for (int i = 0; i < newBeamList.size(); i++) + { + BeaconBeamDTO beam = newBeamList.get(i); + newBeamByPos.put(beam.pos, beam); + allPosSet.add(beam.pos); + } + + // get existing beams + List existingBeamList = this.beaconBeamRepo.getAllBeamsForSectionPos(pos); + HashMap existingBeamByPos = new HashMap<>(existingBeamList.size()); + for (int i = 0; i < existingBeamList.size(); i++) + { + BeaconBeamDTO beam = existingBeamList.get(i); + existingBeamByPos.put(beam.pos, beam); + allPosSet.add(beam.pos); + } + + + + for (DhBlockPos beaconPos : allPosSet) + { + BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos); + BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos); + + if (existingBeam != null && newBeam != null) + { + // beam still exists in chunk, do nothing + } + else if (existingBeam == null && newBeam != null) + { + // new beam found, add to DB + this.beaconBeamRepo.save(newBeam); + + IDhApiRenderableBoxGroup beaconBox = GenericObjectRenderer.INSTANCE.createForSingleBox(new DhApiRenderableBox( + new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), + new DhApiVec3f(newBeam.pos.x+1, 2_000, newBeam.pos.z+1), + newBeam.color + )); + beamRenderGroupByPos.put(newBeam.pos, beaconBox); + GenericObjectRenderer.INSTANCE.add(beaconBox); + } + else if (existingBeam != null && newBeam == null) + { + // beam no longer exists at position, remove + this.beaconBeamRepo.deleteWithKey(beaconPos); + IDhApiRenderableBoxGroup beaconBox = beamRenderGroupByPos.remove(newBeam.pos); + if (beaconBox != null) + { + GenericObjectRenderer.INSTANCE.remove(beaconBox.getId()); + } + } + + } + + } + } + + + //================// // base overrides // //================// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index f3fa99055..f54db8781 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -62,7 +62,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel this.dataFileHandler = new RemoteFullDataSourceProvider(this, saveStructure, fullDataSaveDirOverride); this.clientside = new ClientLevelModule(this); - this.createAndSetChunkHashRepo(this.dataFileHandler.repo.databaseFile); + this.createAndSetSupportingRepos(this.dataFileHandler.repo.databaseFile); if (enableRendering) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index 5a210bf08..c961240ed 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -68,7 +68,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev this.serverLevelWrapper = serverLevelWrapper; this.serverside = new ServerLevelModule(this, saveStructure); this.clientside = new ClientLevelModule(this); - this.createAndSetChunkHashRepo(this.serverside.fullDataFileHandler.repo.databaseFile); + this.createAndSetSupportingRepos(this.serverside.fullDataFileHandler.repo.databaseFile); LOGGER.info("Started " + DhClientServerLevel.class.getSimpleName() + " for " + serverLevelWrapper + " with saves at " + saveStructure); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index 13a520ff8..c14eb617b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -47,7 +47,7 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel } this.serverLevelWrapper = serverLevelWrapper; this.serverside = new ServerLevelModule(this, saveStructure); - this.createAndSetChunkHashRepo(this.serverside.fullDataFileHandler.repo.databaseFile); + this.createAndSetSupportingRepos(this.serverside.fullDataFileHandler.repo.databaseFile); LOGGER.info("Started DHLevel for {} with saves at {}", serverLevelWrapper, saveStructure); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java index 66e32c3da..5a52cd29a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java @@ -22,7 +22,9 @@ package com.seibel.distanthorizons.core.level; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; +import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; @@ -44,6 +46,9 @@ public interface IDhLevel extends AutoCloseable void setChunkHash(DhChunkPos pos, int chunkHash); void updateChunkAsync(IChunkWrapper chunk); + List getAllBeamsForSectionPos(long pos); + void ensureBeaconBeamsAtPos(long pos, List beamList); + FullDataSourceProviderV2 getFullDataProvider(); AbstractSaveStructure getSaveStructure(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 7c5b3bf70..39983e77e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -74,6 +74,7 @@ import java.util.stream.Stream; */ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { + @Deprecated public static GenericObjectRenderer INSTANCE = new GenericObjectRenderer(); private static final Logger LOGGER = DhLoggerBuilder.getLogger(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/BeaconBeamDTO.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/BeaconBeamDTO.java new file mode 100644 index 000000000..452af3873 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/dto/BeaconBeamDTO.java @@ -0,0 +1,55 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.sql.dto; + +import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; +import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.pos.DhBlockPos; + +import java.awt.*; + +/** handles storing {@link FullDataSourceV2}'s in the database. */ +public class BeaconBeamDTO implements IBaseDTO +{ + public DhBlockPos pos; + public Color color; + + + + //=============// + // constructor // + //=============// + + public BeaconBeamDTO(DhBlockPos pos, Color color) + { + this.pos = pos; + this.color = color; + } + + + + //===========// + // overrides // + //===========// + + @Override + public DhBlockPos getKey() { return this.pos; } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java new file mode 100644 index 000000000..5c9767bea --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java @@ -0,0 +1,152 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.sql.repo; + +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; +import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; +import org.apache.logging.log4j.Logger; + +import java.awt.*; +import java.io.File; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +public class BeaconBeamRepo extends AbstractDhRepo +{ + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + + + + //=============// + // constructor // + //=============// + + public BeaconBeamRepo(String databaseType, File databaseFile) throws SQLException + { + super(databaseType, databaseFile, BeaconBeamDTO.class); + } + + + + //===========// + // overrides // + //===========// + + @Override + public String getTableName() { return "BeaconBeam"; } + + @Override + public String createWhereStatement(DhBlockPos pos) { return "BlockPosX = "+pos.x+" AND BlockPosY = "+pos.y+" AND BlockPosZ = "+pos.z; } + + + + //=======================// + // repo required methods // + //=======================// + + @Override + public BeaconBeamDTO convertDictionaryToDto(Map objectMap) throws ClassCastException + { + int posX = (Integer) objectMap.get("BlockPosX"); + int posY = (Integer) objectMap.get("BlockPosY"); + int posZ = (Integer) objectMap.get("BlockPosZ"); + + int red = (Integer) objectMap.get("ColorR"); + int green = (Integer) objectMap.get("ColorG"); + int blue = (Integer) objectMap.get("ColorB"); + + + BeaconBeamDTO dto = new BeaconBeamDTO(new DhBlockPos(posX, posY, posZ), new Color(red, green, blue)); + return dto; + } + + @Override + public PreparedStatement createInsertStatement(BeaconBeamDTO dto) throws SQLException + { + String sql = + "INSERT INTO "+this.getTableName() + " (\n" + + " BlockPosX, BlockPosY, BlockPosZ, \n" + + " ColorR, ColorG, ColorB, \n" + + " LastModifiedUnixDateTime, CreatedUnixDateTime) \n" + + "VALUES( \n" + + " ?, ?, ?, \n" + + " ?, ?, ?, \n" + + " ?, ? \n" + + ");"; + PreparedStatement statement = this.createPreparedStatement(sql); + + int i = 1; + statement.setObject(i++, dto.pos.x); + statement.setObject(i++, dto.pos.y); + statement.setObject(i++, dto.pos.z); + + statement.setObject(i++, dto.color.getRed()); + statement.setObject(i++, dto.color.getGreen()); + statement.setObject(i++, dto.color.getBlue()); + + statement.setObject(i++, System.currentTimeMillis()); // last modified unix time + statement.setObject(i++, System.currentTimeMillis()); // created unix time + + return statement; + } + + @Override + public PreparedStatement createUpdateStatement(BeaconBeamDTO dto) throws SQLException + { + String sql = + "UPDATE "+this.getTableName()+" \n" + + "SET \n" + + " ColorR = ?, ColorG = ?, ColorB = ?, \n" + + " ,LastModifiedUnixDateTime = ? \n" + + "WHERE BlockPosX = ? AND BlockPosY = ? AND BlockPosZ = ?"; + PreparedStatement statement = this.createPreparedStatement(sql); + + int i = 1; + statement.setObject(i++, dto.color.getRed()); + statement.setObject(i++, dto.color.getGreen()); + statement.setObject(i++, dto.color.getBlue()); + + statement.setObject(i++, System.currentTimeMillis()); // last modified unix time + + statement.setObject(i++, dto.pos.x); + statement.setObject(i++, dto.pos.y); + statement.setObject(i++, dto.pos.z); + + return statement; + } + + + + //====================// + // additional methods // + //====================// + + public List getAllBeamsForSectionPos(long pos) + { + return null; + } + + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index d63633f43..ca79eb837 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -22,13 +22,16 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.chunk; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; +import java.awt.*; import java.util.ArrayList; +import java.util.List; public interface IChunkWrapper extends IBindable { @@ -243,5 +246,24 @@ public interface IChunkWrapper extends IBindable return hash; } + default List getAllActiveBeacons() + { + ArrayList beaconPosList = new ArrayList<>(); + + // since beacons emit light we can check only the positions that are emitting light + ArrayList blockPosList = this.getBlockLightPosList(); + for (int i = 0; i < blockPosList.size(); i++) + { + DhBlockPos pos = blockPosList.get(i).convertToChunkRelativePos(); + IBlockStateWrapper block = this.getBlockState(pos); + if (block.getSerialString().equalsIgnoreCase("minecraft:beacon")) + { + BeaconBeamDTO beam = new BeaconBeamDTO(pos, Color.WHITE); // TODO + beaconPosList.add(beam); + } + } + + return beaconPosList; + } } diff --git a/core/src/main/resources/sqlScripts/0070-sqlite-createBeaconBeamTable.sql b/core/src/main/resources/sqlScripts/0070-sqlite-createBeaconBeamTable.sql new file mode 100644 index 000000000..48a5040a6 --- /dev/null +++ b/core/src/main/resources/sqlScripts/0070-sqlite-createBeaconBeamTable.sql @@ -0,0 +1,16 @@ + +CREATE TABLE BeaconBeam( + -- compound primary key + BlockPosX INT NOT NULL + ,BlockPosY INT NOT NULL + ,BlockPosZ INT NOT NULL + + ,ColorR INT NOT NULL + ,ColorG INT NOT NULL + ,ColorB INT NOT NULL + + ,LastModifiedUnixDateTime BIGINT NOT NULL -- in GMT 0 + ,CreatedUnixDateTime BIGINT NOT NULL -- in GMT 0 + + ,PRIMARY KEY (BlockPosX, BlockPosY, BlockPosZ) +); diff --git a/core/src/main/resources/sqlScripts/scriptList.txt b/core/src/main/resources/sqlScripts/scriptList.txt index 52027a061..7c6ed02ea 100644 --- a/core/src/main/resources/sqlScripts/scriptList.txt +++ b/core/src/main/resources/sqlScripts/scriptList.txt @@ -6,3 +6,4 @@ 0040-sqlite-removeRenderCache.sql 0050-sqlite-addApplyToParentIndex.sql 0060-sqlite-createChunkHashTable.sql +0070-sqlite-createBeaconBeamTable.sql From e91afc17a327434671f0273a0f957419ffa78c39 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 1 Jul 2024 19:02:36 -0500 Subject: [PATCH 024/104] Fix beacon beams for loaded chunks --- .../transformers/LodDataBuilder.java | 21 ----------------- .../core/level/AbstractDhLevel.java | 7 ++++-- .../renderer/GenericObjectRenderer.java | 5 ---- .../core/sql/repo/BeaconBeamRepo.java | 23 ++++++++++++++++++- .../chunk/IChunkWrapper.java | 2 +- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index 34bd93883..9cf58eecc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -218,27 +218,6 @@ public class LodDataBuilder biome = newBiome; blockState = newBlockState; - // TODO temp - if (blockState.getSerialString().contains("beacon")) - { - int blockX = chunkWrapper.getChunkPos().x * LodUtil.CHUNK_WIDTH + relBlockX; - int blockZ = chunkWrapper.getChunkPos().z * LodUtil.CHUNK_WIDTH + relBlockZ; - - if (GenericObjectRenderer.INSTANCE.testBeaconPosSet - .add(new DhBlockPos(blockX, y, blockZ))) - { - IDhApiRenderableBoxGroup beaconBeam = GenericObjectRenderer.INSTANCE.createForSingleBox( - new DhApiRenderableBox( - new DhApiVec3f(blockX, y+1, blockZ), - new DhApiVec3f(blockX+1, 5_000, blockZ+1), - Color.WHITE) - ); - beaconBeam.setBlockLight(15); - beaconBeam.setSkyLight(15); - GenericObjectRenderer.INSTANCE.add(beaconBeam); - } - } - mappedId = dataSource.mapping.addIfNotPresentAndGetId(biome, blockState); blockLight = newBlockLight; skyLight = newSkyLight; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 6831cb403..d6badae9b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -35,6 +35,7 @@ import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO; import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; import com.seibel.distanthorizons.core.sql.repo.ChunkHashRepo; +import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import org.apache.logging.log4j.Logger; @@ -247,14 +248,16 @@ public abstract class AbstractDhLevel implements IDhLevel new DhApiVec3f(newBeam.pos.x+1, 2_000, newBeam.pos.z+1), newBeam.color )); - beamRenderGroupByPos.put(newBeam.pos, beaconBox); + beaconBox.setBlockLight(LodUtil.MAX_MC_LIGHT); + beaconBox.setSkyLight(LodUtil.MAX_MC_LIGHT); + this.beamRenderGroupByPos.put(newBeam.pos, beaconBox); GenericObjectRenderer.INSTANCE.add(beaconBox); } else if (existingBeam != null && newBeam == null) { // beam no longer exists at position, remove this.beaconBeamRepo.deleteWithKey(beaconPos); - IDhApiRenderableBoxGroup beaconBox = beamRenderGroupByPos.remove(newBeam.pos); + IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByPos.remove(existingBeam.pos); if (beaconBox != null) { GenericObjectRenderer.INSTANCE.remove(beaconBox.getId()); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 39983e77e..9d4b56d62 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -120,11 +120,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private final ReentrantLock mapModifyLock = new ReentrantLock(); - // TODO just for testing - @Deprecated - public final HashSet testBeaconPosSet = new HashSet<>(); - - /** A box from 0,0,0 to 1,1,1 */ private static final float[] BOX_VERTICES = { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java index 5c9767bea..6433ff3e9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java @@ -22,6 +22,7 @@ package com.seibel.distanthorizons.core.sql.repo; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import org.apache.logging.log4j.Logger; @@ -30,6 +31,7 @@ import java.awt.*; import java.io.File; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -145,7 +147,26 @@ public class BeaconBeamRepo extends AbstractDhRepo public List getAllBeamsForSectionPos(long pos) { - return null; + int minBlockX = DhSectionPos.getMinCornerBlockX(pos); + int minBlockZ = DhSectionPos.getMinCornerBlockZ(pos); + int maxBlockX = minBlockX + DhSectionPos.getBlockWidth(pos); + int maxBlockZ = minBlockZ + DhSectionPos.getBlockWidth(pos); + + + List> objectMapList = this.queryDictionary( + "SELECT * " + + "FROM "+this.getTableName()+" " + + "WHERE " + + "BlockPosX >= "+minBlockX+" AND BlockPosX <= "+maxBlockX+" " + + "AND BlockPosZ >= "+minBlockZ+" AND BlockPosX <= "+maxBlockZ); + + ArrayList beamList = new ArrayList<>(); + for (Map objectMap : objectMapList) + { + beamList.add(this.convertDictionaryToDto(objectMap)); + } + + return beamList; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index ca79eb837..52e12c9e8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -256,7 +256,7 @@ public interface IChunkWrapper extends IBindable { DhBlockPos pos = blockPosList.get(i).convertToChunkRelativePos(); IBlockStateWrapper block = this.getBlockState(pos); - if (block.getSerialString().equalsIgnoreCase("minecraft:beacon")) + if (block.getSerialString().toLowerCase().contains("minecraft:beacon")) { BeaconBeamDTO beam = new BeaconBeamDTO(pos, Color.WHITE); // TODO beaconPosList.add(beam); From 55cb4595bdadcf425b79510fcd35989aaa5e3ee3 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 2 Jul 2024 07:50:21 -0500 Subject: [PATCH 025/104] Fix beacons un-loading incorrectly in some situations Specifically neighboring chunks updating and in some cases flying away too fast --- .../core/api/internal/SharedApi.java | 4 +- .../core/level/AbstractDhLevel.java | 108 +++++++++++++++++- .../distanthorizons/core/level/IDhLevel.java | 5 +- .../distanthorizons/core/pos/DhChunkPos.java | 26 +++++ .../core/render/LodQuadTree.java | 6 + .../core/render/LodRenderSection.java | 10 ++ .../core/sql/repo/BeaconBeamRepo.java | 2 +- .../chunk/IChunkWrapper.java | 6 +- 8 files changed, 152 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index 6b1ccc4d3..192e60d5e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -26,10 +26,8 @@ import com.seibel.distanthorizons.core.generation.DhLightingEngine; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; -import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhChunkPos; -import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.util.TimerUtil; @@ -350,7 +348,7 @@ public class SharedApi // get this chunk's active beacons List beaconBeamList = chunkWrapper.getAllActiveBeacons(); - dhLevel.ensureBeaconBeamsAtPos(DhSectionPos.encode(chunkWrapper.getChunkPos()), beaconBeamList); + dhLevel.setBeaconBeamsForChunk(chunkWrapper.getChunkPos(), beaconBeamList); dhLevel.updateChunkAsync(chunkWrapper); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index d6badae9b..be6bbe0a8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -48,6 +48,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; public abstract class AbstractDhLevel implements IDhLevel { @@ -199,11 +200,13 @@ public abstract class AbstractDhLevel implements IDhLevel } - HashMap beamRenderGroupByPos = new HashMap<>(); + HashMap beamRenderGroupByBlockPos = new HashMap<>(); + HashMap beamRefCountByPos = new HashMap<>(); @Override - public void ensureBeaconBeamsAtPos(long pos, List newBeamList) + public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List newBeamList) { + long pos = DhSectionPos.encode(chunkPos); if (this.beaconBeamRepo != null) { HashSet allPosSet = new HashSet<>(); @@ -231,6 +234,12 @@ public abstract class AbstractDhLevel implements IDhLevel for (DhBlockPos beaconPos : allPosSet) { + if (!chunkPos.contains(beaconPos)) + { + // don't update beacons outside the updated chunk + continue; + } + BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos); BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos); @@ -245,19 +254,31 @@ public abstract class AbstractDhLevel implements IDhLevel IDhApiRenderableBoxGroup beaconBox = GenericObjectRenderer.INSTANCE.createForSingleBox(new DhApiRenderableBox( new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), - new DhApiVec3f(newBeam.pos.x+1, 2_000, newBeam.pos.z+1), + new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), newBeam.color )); beaconBox.setBlockLight(LodUtil.MAX_MC_LIGHT); beaconBox.setSkyLight(LodUtil.MAX_MC_LIGHT); - this.beamRenderGroupByPos.put(newBeam.pos, beaconBox); + + this.beamRenderGroupByBlockPos.put(newBeam.pos, beaconBox); + this.beamRefCountByPos.compute(newBeam.pos, (beamPos, refCount) -> + { + if (refCount == null) + { + refCount = new AtomicInteger(0); + } + refCount.getAndIncrement(); + return refCount; + }); + GenericObjectRenderer.INSTANCE.add(beaconBox); } else if (existingBeam != null && newBeam == null) { // beam no longer exists at position, remove - this.beaconBeamRepo.deleteWithKey(beaconPos); - IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByPos.remove(existingBeam.pos); + this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks + this.beamRefCountByPos.remove(existingBeam.pos); + IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByBlockPos.remove(existingBeam.pos); if (beaconBox != null) { GenericObjectRenderer.INSTANCE.remove(beaconBox.getId()); @@ -269,6 +290,81 @@ public abstract class AbstractDhLevel implements IDhLevel } } + @Override + public void loadBeaconBeamsInPos(long pos) + { + if (this.beaconBeamRepo != null) + { + // get beams in pos + List existingBeamList = this.beaconBeamRepo.getAllBeamsForSectionPos(pos); + for (int i = 0; i < existingBeamList.size(); i++) + { + BeaconBeamDTO beam = existingBeamList.get(i); + + IDhApiRenderableBoxGroup beaconBox = GenericObjectRenderer.INSTANCE.createForSingleBox(new DhApiRenderableBox( + new DhApiVec3f(beam.pos.x, beam.pos.y+1, beam.pos.z), + new DhApiVec3f(beam.pos.x+1, 6_000, beam.pos.z+1), + beam.color + )); + beaconBox.setBlockLight(LodUtil.MAX_MC_LIGHT); + beaconBox.setSkyLight(LodUtil.MAX_MC_LIGHT); + + this.beamRefCountByPos.compute(beam.pos, (beamPos, refCount) -> + { + if (refCount == null) + { + refCount = new AtomicInteger(0); + } + + if (refCount.getAndIncrement() == 0) + { + this.beamRenderGroupByBlockPos.put(beam.pos, beaconBox); + GenericObjectRenderer.INSTANCE.add(beaconBox); + } + + return refCount; + }); + } + } + } + + @Override + public void unloadBeaconBeamsInPos(long pos) + { + if (this.beaconBeamRepo != null) + { + // get beams in pos + List existingBeamList = this.beaconBeamRepo.getAllBeamsForSectionPos(pos); + for (int i = 0; i < existingBeamList.size(); i++) + { + BeaconBeamDTO beam = existingBeamList.get(i); + + // beam no longer exists at position, remove + this.beamRefCountByPos.compute(beam.pos, (beamPos, refCount) -> + { + if (refCount == null) + { + return null; + } + + if (refCount.decrementAndGet() == 0) + { + IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByBlockPos.remove(beam.pos); + if (beaconBox != null) + { + GenericObjectRenderer.INSTANCE.remove(beaconBox.getId()); + } + return null; + } + else + { + return refCount; + } + }); + } + } + } + //================// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java index 5a52cd29a..accaaa11c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java @@ -22,7 +22,6 @@ package com.seibel.distanthorizons.core.level; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; -import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; @@ -46,8 +45,10 @@ public interface IDhLevel extends AutoCloseable void setChunkHash(DhChunkPos pos, int chunkHash); void updateChunkAsync(IChunkWrapper chunk); + void loadBeaconBeamsInPos(long pos); List getAllBeamsForSectionPos(long pos); - void ensureBeaconBeamsAtPos(long pos, List beamList); + void setBeaconBeamsForChunk(DhChunkPos chunkPos, List beamList); + void unloadBeaconBeamsInPos(long pos); FullDataSourceProviderV2 getFullDataProvider(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhChunkPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhChunkPos.java index e9cd29ba0..1bfd83218 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhChunkPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhChunkPos.java @@ -19,6 +19,8 @@ package com.seibel.distanthorizons.core.pos; +import com.seibel.distanthorizons.core.util.LodUtil; + public class DhChunkPos { public final int x; // Low 32 bits @@ -29,6 +31,10 @@ public class DhChunkPos + //==============// + // constructors // + //==============// + public DhChunkPos(int x, int z) { this.x = x; @@ -51,6 +57,10 @@ public class DhChunkPos + //=========// + // methods // + //=========// + public DhBlockPos center() { return new DhBlockPos(8 + this.x << 4, 0, 8 + this.z << 4); } public DhBlockPos corner() { return new DhBlockPos(this.x << 4, 0, this.z << 4); } @@ -64,8 +74,24 @@ public class DhChunkPos public DhBlockPos2D getMinBlockPos() { return new DhBlockPos2D(this.x << 4, this.z << 4); } + public boolean contains(DhBlockPos pos) + { + int minBlockX = this.getMinBlockX(); + int minBlockZ = this.getMinBlockZ(); + int maxBlockX = minBlockX + LodUtil.CHUNK_WIDTH; + int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH; + + return minBlockX <= pos.x && pos.x <= maxBlockX + && minBlockZ <= pos.z && pos.z <= maxBlockZ; + } + public long getLong() { return toLong(this.x, this.z); } + + //================// + // base overrides // + //================// + @Override public boolean equals(Object obj) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java index 49c349a42..ffadc3c9d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java @@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; +import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.ThreadUtil; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode; @@ -329,6 +330,10 @@ public class LodQuadTree extends QuadTree implements IDebugRen } // all child positions are loaded, disable this section and enable its children. + if (renderSection.renderingEnabled) + { + this.level.unloadBeaconBeamsInPos(renderSection.pos); + } renderSection.renderingEnabled = false; // walk back down the tree and enable the child sections //TODO there are probably more efficient ways of doing this, but this will work for now @@ -383,6 +388,7 @@ public class LodQuadTree extends QuadTree implements IDebugRen if (!renderSection.renderingEnabled) { renderSection.renderingEnabled = true; + this.level.loadBeaconBeamsInPos(renderSection.pos); // delete/disable children, all of them will be a lower detail level than requested quadNode.deleteAllChildren((childRenderSection) -> diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index fbfd9a2ed..372e64f7c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -19,6 +19,9 @@ package com.seibel.distanthorizons.core.render; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource; @@ -28,11 +31,16 @@ import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.glObject.GLProxy; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.ColumnRenderBuffer; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; +import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; +import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; +import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.Logger; @@ -41,6 +49,7 @@ import org.jetbrains.annotations.Nullable; import javax.annotation.WillNotClose; import java.awt.*; import java.util.*; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; @@ -416,6 +425,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable } + this.level.unloadBeaconBeamsInPos(this.pos); if (this.renderBuffer != null) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java index 6433ff3e9..5882c3729 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java @@ -121,7 +121,7 @@ public class BeaconBeamRepo extends AbstractDhRepo "UPDATE "+this.getTableName()+" \n" + "SET \n" + " ColorR = ?, ColorG = ?, ColorB = ?, \n" + - " ,LastModifiedUnixDateTime = ? \n" + + " LastModifiedUnixDateTime = ? \n" + "WHERE BlockPosX = ? AND BlockPosY = ? AND BlockPosZ = ?"; PreparedStatement statement = this.createPreparedStatement(sql); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index 52e12c9e8..09d8538ba 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -254,11 +254,11 @@ public interface IChunkWrapper extends IBindable ArrayList blockPosList = this.getBlockLightPosList(); for (int i = 0; i < blockPosList.size(); i++) { - DhBlockPos pos = blockPosList.get(i).convertToChunkRelativePos(); - IBlockStateWrapper block = this.getBlockState(pos); + DhBlockPos pos = blockPosList.get(i); + IBlockStateWrapper block = this.getBlockState(pos.convertToChunkRelativePos()); if (block.getSerialString().toLowerCase().contains("minecraft:beacon")) { - BeaconBeamDTO beam = new BeaconBeamDTO(pos, Color.WHITE); // TODO + BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), Color.WHITE); beaconPosList.add(beam); } } From 3b4a0ff4bcf555a8fd755c5b11c78fe4f8bcc627 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 2 Jul 2024 17:08:55 -0500 Subject: [PATCH 026/104] test --- .../core/level/AbstractDhLevel.java | 8 ++-- .../renderer/GenericObjectRenderer.java | 1 + .../core/sql/repo/BeaconBeamRepo.java | 39 +++++++++++++++---- .../chunk/IChunkWrapper.java | 39 +++++++++++++++++-- 4 files changed, 72 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index be6bbe0a8..b2a1b08b8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -191,7 +191,7 @@ public abstract class AbstractDhLevel implements IDhLevel { if (this.beaconBeamRepo != null) { - return this.beaconBeamRepo.getAllBeamsForSectionPos(pos); + return this.beaconBeamRepo.getAllBeamsForPos(pos); } else { @@ -221,7 +221,7 @@ public abstract class AbstractDhLevel implements IDhLevel } // get existing beams - List existingBeamList = this.beaconBeamRepo.getAllBeamsForSectionPos(pos); + List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos); HashMap existingBeamByPos = new HashMap<>(existingBeamList.size()); for (int i = 0; i < existingBeamList.size(); i++) { @@ -296,7 +296,7 @@ public abstract class AbstractDhLevel implements IDhLevel if (this.beaconBeamRepo != null) { // get beams in pos - List existingBeamList = this.beaconBeamRepo.getAllBeamsForSectionPos(pos); + List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); for (int i = 0; i < existingBeamList.size(); i++) { BeaconBeamDTO beam = existingBeamList.get(i); @@ -334,7 +334,7 @@ public abstract class AbstractDhLevel implements IDhLevel if (this.beaconBeamRepo != null) { // get beams in pos - List existingBeamList = this.beaconBeamRepo.getAllBeamsForSectionPos(pos); + List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); for (int i = 0; i < existingBeamList.size(); i++) { BeaconBeamDTO beam = existingBeamList.get(i); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 9d4b56d62..25b6b2f30 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -74,6 +74,7 @@ import java.util.stream.Stream; */ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { + // TODO should be level specific, not global @Deprecated public static GenericObjectRenderer INSTANCE = new GenericObjectRenderer(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java index 5882c3729..9616a79b2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/BeaconBeamRepo.java @@ -21,10 +21,10 @@ package com.seibel.distanthorizons.core.sql.repo; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; -import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; -import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; +import com.seibel.distanthorizons.core.util.LodUtil; import org.apache.logging.log4j.Logger; import java.awt.*; @@ -145,20 +145,43 @@ public class BeaconBeamRepo extends AbstractDhRepo // additional methods // //====================// - public List getAllBeamsForSectionPos(long pos) + public List getAllBeamsForPos(DhChunkPos chunkPos) + { + int minBlockX = chunkPos.getMinBlockX(); + int minBlockZ = chunkPos.getMinBlockZ(); + int maxBlockX = minBlockX + LodUtil.CHUNK_WIDTH; + int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH; + + return this.getAllBeamsInBlockPosRange( + minBlockX, minBlockZ, + maxBlockX, maxBlockZ + ); + } + + public List getAllBeamsForPos(long pos) { int minBlockX = DhSectionPos.getMinCornerBlockX(pos); int minBlockZ = DhSectionPos.getMinCornerBlockZ(pos); int maxBlockX = minBlockX + DhSectionPos.getBlockWidth(pos); int maxBlockZ = minBlockZ + DhSectionPos.getBlockWidth(pos); - + return this.getAllBeamsInBlockPosRange( + minBlockX, minBlockZ, + maxBlockX, maxBlockZ + ); + } + + public List getAllBeamsInBlockPosRange( + int minBlockX, int minBlockZ, + int maxBlockX, int maxBlockZ + ) + { List> objectMapList = this.queryDictionary( "SELECT * " + - "FROM "+this.getTableName()+" " + - "WHERE " + - "BlockPosX >= "+minBlockX+" AND BlockPosX <= "+maxBlockX+" " + - "AND BlockPosZ >= "+minBlockZ+" AND BlockPosX <= "+maxBlockZ); + "FROM "+this.getTableName()+" " + + "WHERE " + + minBlockX+" <= BlockPosX AND BlockPosX <= "+maxBlockX+" AND " + + minBlockZ+" <= BlockPosZ AND BlockPosZ <= "+maxBlockZ); ArrayList beamList = new ArrayList<>(); for (Map objectMap : objectMapList) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index 09d8538ba..d31b005fc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -255,15 +255,48 @@ public interface IChunkWrapper extends IBindable for (int i = 0; i < blockPosList.size(); i++) { DhBlockPos pos = blockPosList.get(i); - IBlockStateWrapper block = this.getBlockState(pos.convertToChunkRelativePos()); + DhBlockPos relPos = pos.convertToChunkRelativePos(); + + IBlockStateWrapper block = this.getBlockState(relPos); if (block.getSerialString().toLowerCase().contains("minecraft:beacon")) { - BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), Color.WHITE); - beaconPosList.add(beam); + if (isBeaconActive(relPos.x, relPos.y, relPos.z, this)) + { + BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), Color.WHITE); + beaconPosList.add(beam); + } } } return beaconPosList; } + static boolean isBeaconActive(int relBlockX, int y, int relBlockZ, IChunkWrapper chunkWrapper) + { + for (int x = -1; x<= 1; x++) + { + for (int z = -1; z <= 1; z++) + { + if ((relBlockX + x < 0 || relBlockX + x >= LodUtil.CHUNK_WIDTH) + || (relBlockZ + z < 0 || relBlockZ + z >= LodUtil.CHUNK_WIDTH)) + { + // if the beacon is on the border of a chunk and all other blocks are there, assume it's complete + //TODO! Check adjacent chunk, if possible + continue; + } + String blockId = chunkWrapper.getBlockState(relBlockX + x, y -1, relBlockZ + z).getSerialString(); + + if (!(blockId.contains("diamond_block") + || blockId.contains("iron_block") + || blockId.contains("emerald_block") + || blockId.contains("netherite_block") + || blockId.contains("gold_block"))) + { + return false; + } + } + } + return true; + } + } From e90c7cd8a01d9687abb854cec7066119aefd4b79 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 2 Jul 2024 17:50:25 -0500 Subject: [PATCH 027/104] Add beacon activation logic from merge 60 Closes !60 --- .../core/api/internal/ServerApi.java | 2 +- .../core/api/internal/SharedApi.java | 27 ++-- .../core/generation/AdjacentChunkHolder.java | 117 ++++++++++++++++++ .../core/generation/DhLightingEngine.java | 58 --------- .../chunk/IChunkWrapper.java | 62 +++++++--- 5 files changed, 176 insertions(+), 90 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/generation/AdjacentChunkHolder.java diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java index 0d1e97862..962c7b323 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java @@ -141,7 +141,7 @@ public class ServerApi //=======================// public void serverChunkLoadEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); } - public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); } + public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, true); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index 192e60d5e..86565a6b3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -311,6 +311,18 @@ public class SharedApi } + // having a list of the nearby chunks is needed for lighting and beacon generation + ArrayList nearbyChunkList; + if (neighbourChunkList != null) + { + nearbyChunkList = neighbourChunkList; + } + else + { + nearbyChunkList = new ArrayList<>(1); + nearbyChunkList.add(chunkWrapper); + } + // Save or populate the chunk wrapper's lighting // this is done so we don't have to worry about MC unloading the lighting data for this chunk @@ -330,24 +342,13 @@ public class SharedApi else { // generate the chunk's lighting, using neighboring chunks if present - - ArrayList nearbyChunkList; - if (neighbourChunkList != null) - { - nearbyChunkList = neighbourChunkList; - } - else - { - nearbyChunkList = new ArrayList<>(1); - nearbyChunkList.add(chunkWrapper); - } - DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, dhLevel.hasSkyLight() ? 15 : 0); } + // get this chunk's active beacons - List beaconBeamList = chunkWrapper.getAllActiveBeacons(); + List beaconBeamList = chunkWrapper.getAllActiveBeacons(nearbyChunkList); dhLevel.setBeaconBeamsForChunk(chunkWrapper.getChunkPos(), beaconBeamList); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/AdjacentChunkHolder.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/AdjacentChunkHolder.java new file mode 100644 index 000000000..a3d5603e3 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/AdjacentChunkHolder.java @@ -0,0 +1,117 @@ +package com.seibel.distanthorizons.core.generation; + +import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; +import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashSet; + +/** holds adjacent chunks without having to create new Pos objects */ +public class AdjacentChunkHolder +{ + final IChunkWrapper[] chunkArray = new IChunkWrapper[9]; + + + //==============// + // constructors // + //==============// + + public AdjacentChunkHolder(IChunkWrapper centerWrapper) { this.chunkArray[4] = centerWrapper; } + + public AdjacentChunkHolder(IChunkWrapper centerWrapper, @NotNull ArrayList nearbyChunkList) + { + this.chunkArray[4] = centerWrapper; + + DhChunkPos centerChunkPos = centerWrapper.getChunkPos(); + + // generate the list of chunk pos we need, + // currently a 3x3 grid + HashSet requestedAdjacentPositions = new HashSet<>(9); + for (int xOffset = -1; xOffset <= 1; xOffset++) + { + for (int zOffset = -1; zOffset <= 1; zOffset++) + { + DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.x + xOffset, centerChunkPos.z + zOffset); + requestedAdjacentPositions.add(adjacentPos); + } + } + + for (int chunkIndex = 0; chunkIndex < nearbyChunkList.size(); chunkIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead + { + IChunkWrapper chunk = nearbyChunkList.get(chunkIndex); + if (chunk != null && requestedAdjacentPositions.contains(chunk.getChunkPos())) + { + // remove the newly found position + requestedAdjacentPositions.remove(chunk.getChunkPos()); + + // add the adjacent chunk + this.add(chunk); + } + + if (requestedAdjacentPositions.isEmpty()) + { + // we found every chunk we needed, we don't need to keep iterating + break; + } + } + } + + + + //=========// + // methods // + //=========// + + public void add(IChunkWrapper centerWrapper) + { + DhChunkPos centerPos = this.chunkArray[4].getChunkPos(); + DhChunkPos offsetPos = centerWrapper.getChunkPos(); + + int offsetX = offsetPos.x - centerPos.x; + if (offsetX < -1 || offsetX > 1) + { + return; + } + + int offsetZ = offsetPos.z - centerPos.z; + if (offsetZ < -1 || offsetZ > 1) + { + return; + } + + // equivalent to 4 + offsetX + (offsetZ * 3). + this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)] = centerWrapper; + } + + public IChunkWrapper getByBlockPos(int blockX, int blockZ) + { + int chunkX = BitShiftUtil.divideByPowerOfTwo(blockX, 4); + int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4); + IChunkWrapper centerChunk = this.chunkArray[4]; + DhChunkPos centerPos = centerChunk.getChunkPos(); + if (centerPos.x == chunkX && centerPos.z == chunkZ) + { + return centerChunk; + } + + int offsetX = chunkX - centerPos.x; + if (offsetX < -1 || offsetX > 1) + { + return null; + } + + int offsetZ = chunkZ - centerPos.z; + if (offsetZ < -1 || offsetZ > 1) + { + return null; + } + + // equivalent to 4 + offsetX + (offsetZ * 3). + return this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)]; + } + + +} + \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java index 6648f62ee..34f1cec9b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java @@ -306,64 +306,6 @@ public class DhLightingEngine } - /** holds the adjacent chunks without having to create new Pos objects */ - private static class AdjacentChunkHolder - { - final IChunkWrapper[] chunkArray = new IChunkWrapper[9]; - - - public AdjacentChunkHolder(IChunkWrapper centerWrapper) { this.chunkArray[4] = centerWrapper; } - - - public void add(IChunkWrapper centerWrapper) - { - DhChunkPos centerPos = this.chunkArray[4].getChunkPos(); - DhChunkPos offsetPos = centerWrapper.getChunkPos(); - - int offsetX = offsetPos.x - centerPos.x; - if (offsetX < -1 || offsetX > 1) - { - return; - } - - int offsetZ = offsetPos.z - centerPos.z; - if (offsetZ < -1 || offsetZ > 1) - { - return; - } - - // equivalent to 4 + offsetX + (offsetZ * 3). - this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)] = centerWrapper; - } - - public IChunkWrapper getByBlockPos(int blockX, int blockZ) - { - int chunkX = BitShiftUtil.divideByPowerOfTwo(blockX, 4); - int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4); - IChunkWrapper centerChunk = this.chunkArray[4]; - DhChunkPos centerPos = centerChunk.getChunkPos(); - if (centerPos.x == chunkX && centerPos.z == chunkZ) - { - return centerChunk; - } - - int offsetX = chunkX - centerPos.x; - if (offsetX < -1 || offsetX > 1) - { - return null; - } - - int offsetZ = chunkZ - centerPos.z; - if (offsetZ < -1 || offsetZ > 1) - { - return null; - } - - // equivalent to 4 + offsetX + (offsetZ * 3). - return this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)]; - } - } - /** * Holds all potential {@link LightPos} objects a lighting task may need. * This is done so existing {@link LightPos} objects can be repurposed instead of destroyed, diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index d31b005fc..b0670c271 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.chunk; +import com.seibel.distanthorizons.core.generation.AdjacentChunkHolder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhChunkPos; @@ -31,6 +32,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import java.awt.*; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; public interface IChunkWrapper extends IBindable @@ -38,6 +41,15 @@ public interface IChunkWrapper extends IBindable /** useful for debugging, but can slow down chunk operations quite a bit due to being called every time. */ boolean RUN_RELATIVE_POS_INDEX_VALIDATION = ModInfo.IS_DEV_BUILD; + /** should be all lowercase */ + List BEACON_BASE_BLOCK_NAME_LIST = Arrays.asList( + "iron_block", + "gold_block", + "diamond_block", + "emerald_block", + "netherite_block" + ); + DhChunkPos getChunkPos(); @@ -246,10 +258,12 @@ public interface IChunkWrapper extends IBindable return hash; } - default List getAllActiveBeacons() + default List getAllActiveBeacons(ArrayList neighbourChunkList) { ArrayList beaconPosList = new ArrayList<>(); + AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(this, neighbourChunkList); + // since beacons emit light we can check only the positions that are emitting light ArrayList blockPosList = this.getBlockLightPosList(); for (int i = 0; i < blockPosList.size(); i++) @@ -260,7 +274,7 @@ public interface IChunkWrapper extends IBindable IBlockStateWrapper block = this.getBlockState(relPos); if (block.getSerialString().toLowerCase().contains("minecraft:beacon")) { - if (isBeaconActive(relPos.x, relPos.y, relPos.z, this)) + if (isBeaconActive(pos, adjacentChunkHolder)) { BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), Color.WHITE); beaconPosList.add(beam); @@ -270,31 +284,43 @@ public interface IChunkWrapper extends IBindable return beaconPosList; } - static boolean isBeaconActive(int relBlockX, int y, int relBlockZ, IChunkWrapper chunkWrapper) + static boolean isBeaconActive(DhBlockPos beaconPos, AdjacentChunkHolder chunkHolder) { + DhBlockPos beaconRelPos = beaconPos.convertToChunkRelativePos(); + DhBlockPos baseRelPos = new DhBlockPos(0, beaconRelPos.y-1, 0); + for (int x = -1; x<= 1; x++) { for (int z = -1; z <= 1; z++) { - if ((relBlockX + x < 0 || relBlockX + x >= LodUtil.CHUNK_WIDTH) - || (relBlockZ + z < 0 || relBlockZ + z >= LodUtil.CHUNK_WIDTH)) - { - // if the beacon is on the border of a chunk and all other blocks are there, assume it's complete - //TODO! Check adjacent chunk, if possible - continue; - } - String blockId = chunkWrapper.getBlockState(relBlockX + x, y -1, relBlockZ + z).getSerialString(); + baseRelPos.x = beaconRelPos.x + x; + baseRelPos.z = beaconRelPos.z + z; + baseRelPos.mutateToChunkRelativePos(baseRelPos); - if (!(blockId.contains("diamond_block") - || blockId.contains("iron_block") - || blockId.contains("emerald_block") - || blockId.contains("netherite_block") - || blockId.contains("gold_block"))) - { - return false; + IChunkWrapper chunk = chunkHolder.getByBlockPos(beaconPos.x + x, beaconPos.z + z); + if (chunk != null) + { + String blockSerial = chunk.getBlockState(baseRelPos.x, baseRelPos.y, baseRelPos.z).getSerialString(); + + boolean baseBlockFound = false; + for (int i = 0; i < BEACON_BASE_BLOCK_NAME_LIST.size(); i++) + { + String baseBlockName = BEACON_BASE_BLOCK_NAME_LIST.get(i); + if (blockSerial.contains(baseBlockName)) + { + baseBlockFound = true; + break; + } + } + + if (!baseBlockFound) + { + return false; + } } } } + return true; } From 5b905a9ab3606172761dd72b322fbe3418a65207 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 2 Jul 2024 19:23:02 -0500 Subject: [PATCH 028/104] minor LodRenderer refactor --- .../core/render/renderer/LodRenderer.java | 162 +++++++++--------- 1 file changed, 84 insertions(+), 78 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 0e8768c48..930cd0976 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -94,84 +94,6 @@ public class LodRenderer private int cachedWidth; private int cachedHeight; - - /** called by each {@link ColumnRenderBuffer} before rendering */ - public void setModelViewMatrixOffset(DhBlockPos pos, DhApiRenderParam renderEventParam) throws IllegalStateException - { - Vec3d cam = MC_RENDER.getCameraExactPosition(); - Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z)); - - - IDhApiShaderProgram shaderProgram = this.lodRenderProgram; - IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class); - if (shaderProgramOverride != null && shaderProgram.overrideThisFrame()) - { - shaderProgram = shaderProgramOverride; - } - - if (!GL32.glIsProgram(shaderProgram.getId())) - { - throw new IllegalStateException("No GL program exists with the ID: [" + shaderProgram.getId() + "]. This either means a shader program was freed while it was still in use or was never created."); - } - - shaderProgram.bind(); - shaderProgram.setModelOffsetPos(modelPos); - - ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos)); - } - - public void drawVbo(GLVertexBuffer vbo) - { - //// can be uncommented to add additional debug validation to prevent crashes if invalid buffers are being created - //// shouldn't be used in production due to the performance hit - //if (GL32.glIsBuffer(vbo.getId())) - { - IDhApiShaderProgram shaderProgram = this.lodRenderProgram; - IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class); - if (shaderProgramOverride != null && shaderProgram.overrideThisFrame()) - { - shaderProgram = shaderProgramOverride; - } - - - vbo.bind(); - shaderProgram.bindVertexBuffer(vbo.getId()); - GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount() / 4) * 6, // TODO what does the 4 and 6 here represent? - this.quadIBO.getType(), 0); - vbo.unbind(); - } - //else - //{ - // // will spam the log if uncommented, but helpful for validation - // //LOGGER.warn("Unable to draw VBO: "+vbo.getId()); - //} - } - - - public static class LagSpikeCatcher - { - long timer = System.nanoTime(); - - public LagSpikeCatcher() { } - - public void end(String source) - { - if (!ENABLE_DRAW_LAG_SPIKE_LOGGING) - { - return; - } - - this.timer = System.nanoTime() - this.timer; - if (this.timer > DRAW_LAG_SPIKE_THRESHOLD_NS) - { - //4 ms - EVENT_LOGGER.debug("NOTE: " + source + " took " + Duration.ofNanos(this.timer) + "!"); - } - - } - - } - private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); @@ -528,6 +450,59 @@ public class LodRenderer } } + /** called by each {@link ColumnRenderBuffer} before rendering */ + public void setModelViewMatrixOffset(DhBlockPos pos, DhApiRenderParam renderEventParam) throws IllegalStateException + { + Vec3d cam = MC_RENDER.getCameraExactPosition(); + Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z)); + + + IDhApiShaderProgram shaderProgram = this.lodRenderProgram; + IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class); + if (shaderProgramOverride != null && shaderProgram.overrideThisFrame()) + { + shaderProgram = shaderProgramOverride; + } + + if (!GL32.glIsProgram(shaderProgram.getId())) + { + throw new IllegalStateException("No GL program exists with the ID: [" + shaderProgram.getId() + "]. This either means a shader program was freed while it was still in use or was never created."); + } + + shaderProgram.bind(); + shaderProgram.setModelOffsetPos(modelPos); + + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos)); + } + + public void drawVbo(GLVertexBuffer vbo) + { + //// can be uncommented to add additional debug validation to prevent crashes if invalid buffers are being created + //// shouldn't be used in production due to the performance hit + //if (GL32.glIsBuffer(vbo.getId())) + { + IDhApiShaderProgram shaderProgram = this.lodRenderProgram; + IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class); + if (shaderProgramOverride != null && shaderProgram.overrideThisFrame()) + { + shaderProgram = shaderProgramOverride; + } + + + vbo.bind(); + shaderProgram.bindVertexBuffer(vbo.getId()); + GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount() / 4) * 6, // TODO what does the 4 and 6 here represent? + this.quadIBO.getType(), 0); + vbo.unbind(); + } + //else + //{ + // // will spam the log if uncommented, but helpful for validation + // //LOGGER.warn("Unable to draw VBO: "+vbo.getId()); + //} + } + + //=================// @@ -873,4 +848,35 @@ public class LodRenderer } } + + + //================// + // helper classes // + //================// + + public static class LagSpikeCatcher + { + long timer = System.nanoTime(); + + public LagSpikeCatcher() { } + + public void end(String source) + { + if (!ENABLE_DRAW_LAG_SPIKE_LOGGING) + { + return; + } + + this.timer = System.nanoTime() - this.timer; + if (this.timer > DRAW_LAG_SPIKE_THRESHOLD_NS) + { + //4 ms + EVENT_LOGGER.debug("NOTE: " + source + " took " + Duration.ofNanos(this.timer) + "!"); + } + + } + + } + + } From 131b2835e58f26ff28db1e4b219a3941ff7ccbe6 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 2 Jul 2024 22:11:06 -0500 Subject: [PATCH 029/104] Make generic renderer level dependent --- .../com/seibel/distanthorizons/api/DhApi.java | 10 ++-- .../distanthorizons/core/Initializer.java | 2 +- .../core/level/AbstractDhLevel.java | 25 +++++---- .../core/level/ClientLevelModule.java | 32 ++++++++---- .../core/level/DhClientLevel.java | 8 +++ .../core/level/DhClientServerLevel.java | 22 ++++---- .../core/level/DhServerLevel.java | 8 +++ .../distanthorizons/core/level/IDhLevel.java | 9 ++++ .../renderer/GenericObjectRenderer.java | 52 +++++++++---------- .../core/render/renderer/LodRenderer.java | 7 ++- .../chunk/IChunkWrapper.java | 2 + 11 files changed, 107 insertions(+), 70 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java index a79885503..a04faaad0 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java @@ -128,11 +128,11 @@ public class DhApi */ public static IDhApiWrapperFactory wrapperFactory = null; - /** - * Used to add custom objects to DH's render pass. - * @since API 3.0.0 - */ - public static IDhApiCustomRenderRegister renderRegister = null; + ///** + // * Used to add custom objects to DH's render pass. + // * @since API 3.0.0 + // */ + //public static IDhApiCustomRenderRegister renderRegister = null; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java index be1e4c20a..dbf715181 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java @@ -94,7 +94,7 @@ public class Initializer DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE; DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE; DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE; - DhApi.Delayed.renderRegister = GenericObjectRenderer.INSTANCE; + //DhApi.Delayed.renderRegister = GenericObjectRenderer.INSTANCE; DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class); if (DhApi.Delayed.wrapperFactory == null) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index b2a1b08b8..56eb78972 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -206,8 +206,9 @@ public abstract class AbstractDhLevel implements IDhLevel @Override public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List newBeamList) { - long pos = DhSectionPos.encode(chunkPos); - if (this.beaconBeamRepo != null) + GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); + if (this.beaconBeamRepo != null + && genericObjectRenderer != null) { HashSet allPosSet = new HashSet<>(); @@ -252,7 +253,7 @@ public abstract class AbstractDhLevel implements IDhLevel // new beam found, add to DB this.beaconBeamRepo.save(newBeam); - IDhApiRenderableBoxGroup beaconBox = GenericObjectRenderer.INSTANCE.createForSingleBox(new DhApiRenderableBox( + IDhApiRenderableBoxGroup beaconBox = genericObjectRenderer.createForSingleBox(new DhApiRenderableBox( new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), newBeam.color @@ -271,7 +272,7 @@ public abstract class AbstractDhLevel implements IDhLevel return refCount; }); - GenericObjectRenderer.INSTANCE.add(beaconBox); + genericObjectRenderer.add(beaconBox); } else if (existingBeam != null && newBeam == null) { @@ -281,7 +282,7 @@ public abstract class AbstractDhLevel implements IDhLevel IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByBlockPos.remove(existingBeam.pos); if (beaconBox != null) { - GenericObjectRenderer.INSTANCE.remove(beaconBox.getId()); + genericObjectRenderer.remove(beaconBox.getId()); } } @@ -293,7 +294,9 @@ public abstract class AbstractDhLevel implements IDhLevel @Override public void loadBeaconBeamsInPos(long pos) { - if (this.beaconBeamRepo != null) + GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); + if (this.beaconBeamRepo != null + && genericObjectRenderer != null) { // get beams in pos List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); @@ -301,7 +304,7 @@ public abstract class AbstractDhLevel implements IDhLevel { BeaconBeamDTO beam = existingBeamList.get(i); - IDhApiRenderableBoxGroup beaconBox = GenericObjectRenderer.INSTANCE.createForSingleBox(new DhApiRenderableBox( + IDhApiRenderableBoxGroup beaconBox = genericObjectRenderer.createForSingleBox(new DhApiRenderableBox( new DhApiVec3f(beam.pos.x, beam.pos.y+1, beam.pos.z), new DhApiVec3f(beam.pos.x+1, 6_000, beam.pos.z+1), beam.color @@ -319,7 +322,7 @@ public abstract class AbstractDhLevel implements IDhLevel if (refCount.getAndIncrement() == 0) { this.beamRenderGroupByBlockPos.put(beam.pos, beaconBox); - GenericObjectRenderer.INSTANCE.add(beaconBox); + genericObjectRenderer.add(beaconBox); } return refCount; @@ -331,7 +334,9 @@ public abstract class AbstractDhLevel implements IDhLevel @Override public void unloadBeaconBeamsInPos(long pos) { - if (this.beaconBeamRepo != null) + GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); + if (this.beaconBeamRepo != null + && genericObjectRenderer != null) { // get beams in pos List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); @@ -352,7 +357,7 @@ public abstract class AbstractDhLevel implements IDhLevel IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByBlockPos.remove(beam.pos); if (beaconBox != null) { - GenericObjectRenderer.INSTANCE.remove(beaconBox.getId()); + genericObjectRenderer.remove(beaconBox.getId()); } return null; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java index 7ed8e1e43..97bc4d87a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java @@ -27,13 +27,12 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.file.AbstractDataSourceHandler; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.logging.f3.F3Screen; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.render.LodQuadTree; import com.seibel.distanthorizons.core.render.RenderBufferHandler; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.render.renderer.LodRenderer; import com.seibel.distanthorizons.core.util.LodUtil; -import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; @@ -41,9 +40,7 @@ import org.apache.logging.log4j.Logger; import javax.annotation.WillNotClose; import java.io.Closeable; -import java.util.ArrayList; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.atomic.AtomicReference; public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.IDataSourceUpdateFunc @@ -128,7 +125,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I } if (isBuffersDirty) { - clientRenderState.renderer.bufferHandler.MarkAllBuffersDirty(); + clientRenderState.lodRenderer.bufferHandler.MarkAllBuffersDirty(); } } @@ -167,7 +164,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I // either the renderer hasn't been started yet, or is being reloaded return; } - ClientRenderState.renderer.drawLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler); + ClientRenderState.lodRenderer.drawLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler); } public void renderDeferred(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) @@ -178,7 +175,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I // either the renderer hasn't been started yet, or is being reloaded return; } - ClientRenderState.renderer.drawDeferredLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler); + ClientRenderState.lodRenderer.drawDeferredLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler); } public void stopRenderer() @@ -275,13 +272,20 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I // helper classes // //================// - public static class ClientRenderState + public static class ClientRenderState implements Closeable { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); public final IClientLevelWrapper clientLevelWrapper; public final LodQuadTree quadtree; - public final LodRenderer renderer; + public final LodRenderer lodRenderer; + public final GenericObjectRenderer genericRenderer; + + + + //=============// + // constructor // + //=============// public ClientRenderState(IDhClientLevel dhClientLevel, IClientLevelWrapper clientLevelWrapper, FullDataSourceProviderV2 fullDataSourceProvider) { @@ -293,16 +297,22 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I fullDataSourceProvider); RenderBufferHandler renderBufferHandler = new RenderBufferHandler(this.quadtree); - this.renderer = new LodRenderer(renderBufferHandler); + this.genericRenderer = new GenericObjectRenderer(); + this.lodRenderer = new LodRenderer(renderBufferHandler, this.genericRenderer); } + //================// + // base overrides // + //================// + + @Override public void close() { LOGGER.info("Shutting down " + ClientRenderState.class.getSimpleName()); - this.renderer.close(); + this.lodRenderer.close(); this.quadtree.close(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index f54db8781..e8823d0b1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -26,6 +26,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.RemoteFullDataSourcePro import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; @@ -170,4 +171,11 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel public boolean hasSkyLight() { return this.levelWrapper.hasSkyLight(); } + @Override + public GenericObjectRenderer getGenericRenderer() + { + ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); + return (renderState != null) ? renderState.genericRenderer : null; + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index c961240ed..a63fd71eb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -29,6 +29,7 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; @@ -102,20 +103,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev if (shouldDoWorldGen && !isWorldGenRunning) { // start world gen - - // create a new queue this.serverside.worldGenModule.startWorldGen(this.serverside.fullDataFileHandler, new ServerLevelModule.WorldGenState(this)); - - // TODO I think this used to queue the world gen - // is it still needed? - // populate the queue based on the current rendering tree - //ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); - //Iterator> iterator = renderState.quadtree.leafNodeIterator(); - //while (iterator.hasNext()) - //{ - // QuadNode node = iterator.next(); - // //this.serverside.dataFileHandler.getAsync(node.sectionPos); - //} } else if (!shouldDoWorldGen && isWorldGenRunning) { @@ -237,6 +225,14 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev } + @Override + public GenericObjectRenderer getGenericRenderer() + { + ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); + return (renderState != null) ? renderState.genericRenderer : null; + } + + //===============// // data handling // diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index c14eb617b..63ed6266e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import org.apache.logging.log4j.Logger; @@ -116,6 +117,13 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel //TODO: Send packet to client } + @Override + public GenericObjectRenderer getGenericRenderer() + { + // server-only levels don't support rendering + return null; + } + //===========// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java index accaaa11c..5cfb22dc5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java @@ -19,13 +19,16 @@ package com.seibel.distanthorizons.core.level; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -66,5 +69,11 @@ public interface IDhLevel extends AutoCloseable void addDebugMenuStringsToList(List messageList); + /** + * Will return null if the renderer isn't set up yet.
+ * Not supported on the server-side. + */ + @Nullable + GenericObjectRenderer getGenericRenderer(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 25b6b2f30..208b39b9e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -74,10 +74,6 @@ import java.util.stream.Stream; */ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { - // TODO should be level specific, not global - @Deprecated - public static GenericObjectRenderer INSTANCE = new GenericObjectRenderer(); - private static final Logger LOGGER = DhLoggerBuilder.getLogger(); public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(GenericObjectRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1); @@ -164,7 +160,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // constructor // //=============// - private GenericObjectRenderer() { } + public GenericObjectRenderer() { } public void init() { @@ -237,27 +233,27 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private void addGenericDebugObjects() { // single giant box - IDhApiRenderableBoxGroup singleGiantBoxGroup = DhApi.Delayed.renderRegister.createForSingleBox( + IDhApiRenderableBoxGroup singleGiantBoxGroup = this.createForSingleBox( new DhApiRenderableBox( new DhApiVec3f(0f,0f,0f), new DhApiVec3f(16f,190f,16f), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) ); singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); singleGiantBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); - DhApi.Delayed.renderRegister.add(singleGiantBoxGroup); - - + this.add(singleGiantBoxGroup); + + // single slender box - IDhApiRenderableBoxGroup singleTallBoxGroup = DhApi.Delayed.renderRegister.createForSingleBox( + IDhApiRenderableBoxGroup singleTallBoxGroup = this.createForSingleBox( new DhApiRenderableBox( new DhApiVec3f(16f,0f,31f), new DhApiVec3f(17f,2000f,32f), new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) ); singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); singleTallBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); - DhApi.Delayed.renderRegister.add(singleTallBoxGroup); - - + this.add(singleTallBoxGroup); + + // absolute box group ArrayList absBoxList = new ArrayList<>(); for (int i = 0; i < 18; i++) @@ -266,10 +262,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new DhApiVec3f(0f+i,150f+i,24f), new DhApiVec3f(1f+i,151f+i,25f), new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); } - IDhApiRenderableBoxGroup absolutePosBoxGroup = DhApi.Delayed.renderRegister.createAbsolutePositionedGroup(absBoxList); - DhApi.Delayed.renderRegister.add(absolutePosBoxGroup); - - + IDhApiRenderableBoxGroup absolutePosBoxGroup = this.createAbsolutePositionedGroup(absBoxList); + this.add(absolutePosBoxGroup); + + // relative box group ArrayList relBoxList = new ArrayList<>(); for (int i = 0; i < 8; i+=2) @@ -278,7 +274,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new DhApiVec3f(0f,0f+i,0f), new DhApiVec3f(1f,1f+i,1f), new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); } - IDhApiRenderableBoxGroup relativePosBoxGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( + IDhApiRenderableBoxGroup relativePosBoxGroup = this.createRelativePositionedGroup( new DhApiVec3f(24f, 140f, 24f), relBoxList); relativePosBoxGroup.setPreRenderFunc((event) -> @@ -288,9 +284,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister pos.x %= 32; relativePosBoxGroup.setOriginBlockPos(pos); }); - DhApi.Delayed.renderRegister.add(relativePosBoxGroup); - - + this.add(relativePosBoxGroup); + + // massive relative box group ArrayList massRelBoxList = new ArrayList<>(); for (int x = 0; x < 50*2; x+=2) @@ -302,7 +298,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()))); } } - IDhApiRenderableBoxGroup massRelativePosBoxGroup = DhApi.Delayed.renderRegister.createRelativePositionedGroup( + IDhApiRenderableBoxGroup massRelativePosBoxGroup = this.createRelativePositionedGroup( new DhApiVec3f(-25f, 140f, 0f), massRelBoxList); massRelativePosBoxGroup.setPreRenderFunc((event) -> @@ -312,15 +308,15 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister if (blockPos.y > 150f) { blockPos.y = 140f; - + Color newColor = (massRelativePosBoxGroup.get(0).color == Color.RED) ? Color.RED.darker() : Color.RED; massRelativePosBoxGroup.forEach((box) -> { box.color = newColor; }); massRelativePosBoxGroup.triggerBoxChange(); } - + massRelativePosBoxGroup.setOriginBlockPos(blockPos); }); - DhApi.Delayed.renderRegister.add(massRelativePosBoxGroup); + this.add(massRelativePosBoxGroup); } @@ -522,16 +518,16 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceColorVbo); GL32.glEnableVertexAttribArray(1); GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0); - vertexAttribDivisor(1, 1); + this.vertexAttribDivisor(1, 1); GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceTranslationVbo); GL32.glEnableVertexAttribArray(2); - vertexAttribDivisor(2, 1); + this.vertexAttribDivisor(2, 1); GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceScaleVbo); GL32.glEnableVertexAttribArray(3); - vertexAttribDivisor(3, 1); + this.vertexAttribDivisor(3, 1); GL32.glVertexAttribPointer(3, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 930cd0976..e6df38b6d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -100,6 +100,8 @@ public class LodRenderer private final ReentrantLock setupLock = new ReentrantLock(); public final RenderBufferHandler bufferHandler; + public final GenericObjectRenderer genericObjectRenderer; + // The shader program IDhApiShaderProgram lodRenderProgram = null; @@ -124,9 +126,10 @@ public class LodRenderer // constructor // //=============// - public LodRenderer(RenderBufferHandler bufferHandler) + public LodRenderer(RenderBufferHandler bufferHandler, GenericObjectRenderer genericObjectRenderer) { this.bufferHandler = bufferHandler; + this.genericObjectRenderer = genericObjectRenderer; } private boolean rendererClosed = false; @@ -301,7 +304,7 @@ public class LodRenderer // custom objects profiler.popPush("Custom Objects"); - GenericObjectRenderer.INSTANCE.render(renderEventParam, profiler); + this.genericObjectRenderer.render(renderEventParam, profiler); // SSAO diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index b0670c271..21c35ea79 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -321,6 +321,8 @@ public interface IChunkWrapper extends IBindable } } + // TODO check if the sky is visible + return true; } From ae72e627c598ca11f5f588f1ffc8aaa2be88f9e7 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 3 Jul 2024 20:30:49 -0500 Subject: [PATCH 030/104] Add a config to use pre-existing lighting --- .../core/api/internal/SharedApi.java | 2 +- .../seibel/distanthorizons/core/config/Config.java | 14 ++++++++++++++ .../assets/distanthorizons/lang/en_us.json | 4 ++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index 86565a6b3..7e0f58aa8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -332,7 +332,7 @@ public class SharedApi try { // If MC's lighting engine isn't thread safe this may cause the server thread to lag - chunkWrapper.bakeDhLightingUsingMcLightingEngine(); // TODO handle unlit chunks, would pulling in the chunk from disk be a good idea? Look at ChunkLoader in the world gen code for an example + chunkWrapper.bakeDhLightingUsingMcLightingEngine(); } catch (IllegalStateException e) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index f424807d5..dc9581d20 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -752,6 +752,20 @@ public class Config + "") .build(); + public static ConfigEntry pullLightingForPregeneratedChunks = new ConfigEntry.Builder() + .set(false) + .comment("" + + "If true LOD generation for pre-existing chunks will attempt to pull the lighting data \n" + + "saved in Minecraft's Region files. \n" + + "If false DH will pull in chunks without lighting and re-light them. \n" + + " \n" + + "Setting this to true will result in faster LOD generation \n" + + "for already generated worlds, but is broken by most lighting mods. \n" + + " \n" + + "Set this to false if LODs are black. \n" + + "") + .build(); + public static ConfigEntry dataCompression = new ConfigEntry.Builder() .set(EDhApiDataCompressionMode.LZMA2) .comment("" diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 2aaf12c3b..2c5243d02 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -348,6 +348,10 @@ "Only Use DH Lighting Engine", "distanthorizons.config.client.advanced.lodBuilding.onlyUseDhLightingEngine.@tooltip": "If false LODs will be lit by Minecraft's lighting engine when possible \nand fall back to the DH lighting engine only when necessary. \n\nIf true LODs will only be lit using Distant Horizons' lighting engine. \n\nGenerally it is best to leave this disabled and should only be enabled \nif there are lighting issues or for debugging.", + "distanthorizons.config.client.advanced.lodBuilding.pullLightingForPregeneratedChunks": + "Pull Lighting For Pre-generated Chunks", + "distanthorizons.config.client.advanced.lodBuilding.pullLightingForPregeneratedChunks.@tooltip": + "If true LOD generation for pre-existing chunks will attempt to pull the lighting data \nsaved in Minecraft's Region files. \nIf false DH will pull in chunks without lighting and re-light them. \n\nSetting this to true will result in faster LOD generation \nfor already generated worlds, but is broken by most lighting mods. \n\nSet this to false if LODs are black.", "distanthorizons.config.client.advanced.lodBuilding.dataCompression": "Data Compression", "distanthorizons.config.client.advanced.lodBuilding.dataCompression.@tooltip": From 81bfa9a02b67f063e699109e0eea72bd59d870b5 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 3 Jul 2024 20:46:11 -0500 Subject: [PATCH 031/104] Add generic rendering to the F3 menu --- .../core/level/ClientLevelModule.java | 5 +- .../core/level/DhClientLevel.java | 7 +++ .../core/level/DhClientServerLevel.java | 7 +++ .../core/level/DhServerLevel.java | 8 +++- .../distanthorizons/core/level/IDhLevel.java | 7 +++ .../core/logging/f3/F3Screen.java | 47 +++++++------------ .../core/render/RenderBufferHandler.java | 5 -- .../renderer/GenericObjectRenderer.java | 29 ++++++++++++ 8 files changed, 78 insertions(+), 37 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java index 97bc4d87a..7e2d13cc7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java @@ -278,6 +278,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I public final IClientLevelWrapper clientLevelWrapper; public final LodQuadTree quadtree; + public final RenderBufferHandler renderBufferHandler; public final LodRenderer lodRenderer; public final GenericObjectRenderer genericRenderer; @@ -296,9 +297,9 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I 0, 0, fullDataSourceProvider); - RenderBufferHandler renderBufferHandler = new RenderBufferHandler(this.quadtree); this.genericRenderer = new GenericObjectRenderer(); - this.lodRenderer = new LodRenderer(renderBufferHandler, this.genericRenderer); + this.renderBufferHandler = new RenderBufferHandler(this.quadtree); + this.lodRenderer = new LodRenderer(this.renderBufferHandler, this.genericRenderer); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index e8823d0b1..166b0a1df 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -26,6 +26,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.RemoteFullDataSourcePro import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.render.RenderBufferHandler; import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; @@ -177,5 +178,11 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); return (renderState != null) ? renderState.genericRenderer : null; } + @Override + public RenderBufferHandler getRenderBufferHandler() + { + ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); + return (renderState != null) ? renderState.renderBufferHandler : null; + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index a63fd71eb..5d6f6ca79 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.logging.f3.F3Screen; +import com.seibel.distanthorizons.core.render.RenderBufferHandler; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; @@ -231,6 +232,12 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); return (renderState != null) ? renderState.genericRenderer : null; } + @Override + public RenderBufferHandler getRenderBufferHandler() + { + ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); + return (renderState != null) ? renderState.renderBufferHandler : null; + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index 63ed6266e..0b950ed39 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.render.RenderBufferHandler; import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; @@ -123,7 +124,12 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel // server-only levels don't support rendering return null; } - + @Override + public RenderBufferHandler getRenderBufferHandler() + { + // server-only levels don't support rendering + return null; + } //===========// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java index 5cfb22dc5..575ade4a6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.render.RenderBufferHandler; import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; @@ -75,5 +76,11 @@ public interface IDhLevel extends AutoCloseable */ @Nullable GenericObjectRenderer getGenericRenderer(); + /** + * Will return null if the renderer isn't set up yet.
+ * Not supported on the server-side. + */ + @Nullable + RenderBufferHandler getRenderBufferHandler(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java b/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java index a3d4666be..6719ada25 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java @@ -22,6 +22,7 @@ package com.seibel.distanthorizons.core.logging.f3; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.render.RenderBufferHandler; +import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.world.AbstractDhWorld; import com.seibel.distanthorizons.coreapi.ModInfo; @@ -42,23 +43,6 @@ public class F3Screen - //============// - // properties // - //============// - - private static WeakReference renderBufferHandlerRef = new WeakReference<>(null); - public static void setRenderBufferHandler(@Nullable RenderBufferHandler renderBufferHandler) - { - if (renderBufferHandler != null && renderBufferHandlerRef.get() != null) - { - LOGGER.warn("multiple RenderBufferHandlers are active at once, the F3 menu may not be accurate."); - } - - renderBufferHandlerRef = new WeakReference<>(renderBufferHandler); - } - - - //=================// // injection point // //=================// @@ -106,23 +90,28 @@ public class F3Screen // chunk updates messageList.add(SharedApi.INSTANCE.getDebugMenuString()); messageList.add(""); - // rendering - RenderBufferHandler renderBufferHandler = renderBufferHandlerRef.get(); - if (renderBufferHandler != null) - { - messageList.add(renderBufferHandler.getVboRenderDebugMenuString()); - String showPassString = renderBufferHandler.getShadowPassRenderDebugMenuString(); - if (showPassString != null) - { - messageList.add(showPassString); - } - messageList.add(""); - } // world / levels messageList.add(world.GetDebugMenuString()); for (IDhLevel level : levelIterator) { level.addDebugMenuStringsToList(messageList); + // LOD rendering + RenderBufferHandler renderBufferHandler = level.getRenderBufferHandler(); + if (renderBufferHandler != null) + { + messageList.add(renderBufferHandler.getVboRenderDebugMenuString()); + String showPassString = renderBufferHandler.getShadowPassRenderDebugMenuString(); + if (showPassString != null) + { + messageList.add(showPassString); + } + } + // Generic rendering + GenericObjectRenderer genericRenderer = level.getGenericRenderer(); + if (genericRenderer != null) + { + messageList.add(genericRenderer.getVboRenderDebugMenuString()); + } } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index 39e7a26e5..8a952bb93 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -100,9 +100,6 @@ public class RenderBufferHandler implements AutoCloseable { DhApi.overrides.bind(IDhApiShadowCullingFrustum.class, new NeverCullFrustum()); } - - - F3Screen.setRenderBufferHandler(this); } @@ -417,8 +414,6 @@ public class RenderBufferHandler implements AutoCloseable renderSection.close(); } } - - F3Screen.setRenderBufferHandler(null); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 208b39b9e..ea73498bd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -27,9 +27,11 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegist import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.logging.f3.F3Screen; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLState; @@ -613,6 +615,33 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister + + //=========// + // F3 menu // + //=========// + + public String getVboRenderDebugMenuString() + { + // get counts + int totalCount = this.boxGroupById.size(); + int activeCount = 0; + for (long key : this.boxGroupById.keySet()) + { + RenderableBoxGroup renderGroup = this.boxGroupById.get(key); + if (renderGroup.active) + { + activeCount++; + } + } + + + String totalCountText = F3Screen.NUMBER_FORMAT.format(totalCount); + String activeCountText = F3Screen.NUMBER_FORMAT.format(activeCount); + return LodUtil.formatLog("Generic Obj Count: " + activeCountText + "/" + totalCountText); + } + + + //================// // helper classes // //================// From 88db5c95947593d21187ea98a3a7cf88884c9c64 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 3 Jul 2024 22:37:52 -0500 Subject: [PATCH 032/104] re-add generic rendering to the API --- .../com/seibel/distanthorizons/api/DhApi.java | 14 +- .../IDhApiCustomRenderObjectFactory.java | 26 ++ .../render/IDhApiCustomRenderRegister.java | 27 +- .../interfaces/world/IDhApiLevelWrapper.java | 7 + .../distanthorizons/core/Initializer.java | 4 +- .../core/level/AbstractDhLevel.java | 11 +- .../core/level/DhClientLevel.java | 4 +- .../core/level/DhServerLevel.java | 8 + .../renderer/GenericObjectRenderer.java | 310 +----------------- .../renderer/GenericRenderObjectFactory.java | 76 +++++ .../render/renderer/RenderableBoxGroup.java | 268 +++++++++++++++ .../core/world/DhApiWorldProxy.java | 8 + .../world/IClientLevelWrapper.java | 3 + .../objects/LevelWrapperTest.java | 6 + 14 files changed, 454 insertions(+), 318 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java index a04faaad0..79f67940b 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java @@ -23,8 +23,9 @@ import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector; import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGeneratorOverrideRegister; -import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy; +import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent; import com.seibel.distanthorizons.api.methods.override.DhApiWorldGeneratorOverrideRegister; import com.seibel.distanthorizons.coreapi.ModInfo; @@ -128,11 +129,12 @@ public class DhApi */ public static IDhApiWrapperFactory wrapperFactory = null; - ///** - // * Used to add custom objects to DH's render pass. - // * @since API 3.0.0 - // */ - //public static IDhApiCustomRenderRegister renderRegister = null; + /** + * Used to create custom renderable objects.
+ * These objects can be added to the renderer in {@link IDhApiLevelWrapper} + * @since API 3.0.0 + */ + public static IDhApiCustomRenderObjectFactory customRenderObjectFactory = null; } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java new file mode 100644 index 000000000..7e78e0c60 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java @@ -0,0 +1,26 @@ +package com.seibel.distanthorizons.api.interfaces.render; + +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; + +import java.util.List; + +/** + * Handles creating + * {@link IDhApiRenderableBoxGroup} objects, + * which can be added via a {@link IDhApiCustomRenderRegister}. + * + * @see IDhApiCustomRenderRegister + * @see IDhApiRenderableBoxGroup + * + * @author James Seibel + * @version 2024-7-3 + * @since API 3.0.0 + */ +public interface IDhApiCustomRenderObjectFactory +{ + IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube); + IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList); + IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList); + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java index 6b9b06daf..c156c0c8c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java @@ -1,18 +1,24 @@ package com.seibel.distanthorizons.api.interfaces.render; -import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; -import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; - -import java.util.List; +import com.seibel.distanthorizons.api.DhApi; +import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; +import com.seibel.distanthorizons.api.interfaces.world.IDhApiWorldProxy; /** - * Handles adding, removing, and creating + * Handles adding and removing * {@link IDhApiRenderableBoxGroup} objects, - * which can be used to render custom objects into - * DH's terrain. + * from DH's renderer.

+ * + * Can be accessed in + * {@link DhApi.Delayed#worldProxy} -> {@link IDhApiLevelWrapper}. + * + * @see IDhApiCustomRenderObjectFactory + * @see IDhApiRenderableBoxGroup + * @see IDhApiWorldProxy + * @see IDhApiLevelWrapper * * @author James Seibel - * @version 2024-6-30 + * @version 2024-7-3 * @since API 3.0.0 */ public interface IDhApiCustomRenderRegister @@ -21,9 +27,4 @@ public interface IDhApiCustomRenderRegister IDhApiRenderableBoxGroup remove(long id); - - IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube); - IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList); - IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList); - } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java index 2583dfb4a..30d9e161c 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java @@ -21,6 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.world; import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; /** * Can be either a Server or Client level.
@@ -49,4 +50,10 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper */ default int getMinHeight() { return 0; } + /** + * Will return null if called on the server, + * or if called before the renderer has been set up. + */ + IDhApiCustomRenderRegister getRenderRegister(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java index dbf715181..91a4d88f7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java @@ -20,7 +20,7 @@ package com.seibel.distanthorizons.core; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory; import com.seibel.distanthorizons.core.sql.DatabaseUpdater; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.coreapi.ModInfo; @@ -94,7 +94,7 @@ public class Initializer DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE; DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE; DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE; - //DhApi.Delayed.renderRegister = GenericObjectRenderer.INSTANCE; + DhApi.Delayed.customRenderObjectFactory = GenericRenderObjectFactory.INSTANCE; DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class); if (DhApi.Delayed.wrapperFactory == null) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 56eb78972..5ecc362dc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO; import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; @@ -207,6 +208,8 @@ public abstract class AbstractDhLevel implements IDhLevel public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List newBeamList) { GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); + + // should always be non-null, but just in case if (this.beaconBeamRepo != null && genericObjectRenderer != null) { @@ -253,7 +256,7 @@ public abstract class AbstractDhLevel implements IDhLevel // new beam found, add to DB this.beaconBeamRepo.save(newBeam); - IDhApiRenderableBoxGroup beaconBox = genericObjectRenderer.createForSingleBox(new DhApiRenderableBox( + IDhApiRenderableBoxGroup beaconBox = GenericRenderObjectFactory.INSTANCE.createForSingleBox(new DhApiRenderableBox( new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), newBeam.color @@ -295,6 +298,8 @@ public abstract class AbstractDhLevel implements IDhLevel public void loadBeaconBeamsInPos(long pos) { GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); + + // should always be non-null, but just in case if (this.beaconBeamRepo != null && genericObjectRenderer != null) { @@ -304,7 +309,7 @@ public abstract class AbstractDhLevel implements IDhLevel { BeaconBeamDTO beam = existingBeamList.get(i); - IDhApiRenderableBoxGroup beaconBox = genericObjectRenderer.createForSingleBox(new DhApiRenderableBox( + IDhApiRenderableBoxGroup beaconBox = GenericRenderObjectFactory.INSTANCE.createForSingleBox(new DhApiRenderableBox( new DhApiVec3f(beam.pos.x, beam.pos.y+1, beam.pos.z), new DhApiVec3f(beam.pos.x+1, 6_000, beam.pos.z+1), beam.color @@ -335,6 +340,8 @@ public abstract class AbstractDhLevel implements IDhLevel public void unloadBeaconBeamsInPos(long pos) { GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); + + // should always be non-null, but just in case if (this.beaconBeamRepo != null && genericObjectRenderer != null) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index 166b0a1df..1f7e19a9b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -60,6 +60,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel public DhClientLevel(AbstractSaveStructure saveStructure, IClientLevelWrapper clientLevelWrapper, @Nullable File fullDataSaveDirOverride, boolean enableRendering) { this.levelWrapper = clientLevelWrapper; + this.levelWrapper.setParentClientLevel(this); this.saveStructure = saveStructure; this.dataFileHandler = new RemoteFullDataSourceProvider(this, saveStructure, fullDataSaveDirOverride); this.clientside = new ClientLevelModule(this); @@ -156,10 +157,11 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel @Override public void close() { + this.levelWrapper.setParentClientLevel(null); this.clientside.close(); super.close(); this.dataFileHandler.close(); - LOGGER.info("Closed " + DhClientLevel.class.getSimpleName() + " for " + levelWrapper); + LOGGER.info("Closed [" + DhClientLevel.class.getSimpleName() + "] for [" + this.levelWrapper + "]"); } @Override diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index 0b950ed39..c6b4c6911 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -41,6 +41,10 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel + //=============// + // constructor // + //=============// + public DhServerLevel(AbstractSaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper) { if (saveStructure.getFullDataFolder(serverLevelWrapper).mkdirs()) @@ -56,6 +60,10 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel + //=========// + // methods // + //=========// + public void serverTick() { this.chunkToLodBuilder.tick(); } @Override diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index ea73498bd..420a4a3fa 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -19,7 +19,6 @@ package com.seibel.distanthorizons.core.render.renderer; -import com.seibel.distanthorizons.api.DhApi; import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; @@ -27,12 +26,10 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegist import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; -import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; -import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer; @@ -234,8 +231,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } private void addGenericDebugObjects() { + GenericRenderObjectFactory factory = GenericRenderObjectFactory.INSTANCE; + + // single giant box - IDhApiRenderableBoxGroup singleGiantBoxGroup = this.createForSingleBox( + IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox( new DhApiRenderableBox( new DhApiVec3f(0f,0f,0f), new DhApiVec3f(16f,190f,16f), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) @@ -246,7 +246,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single slender box - IDhApiRenderableBoxGroup singleTallBoxGroup = this.createForSingleBox( + IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox( new DhApiRenderableBox( new DhApiVec3f(16f,0f,31f), new DhApiVec3f(17f,2000f,32f), new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) @@ -264,7 +264,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new DhApiVec3f(0f+i,150f+i,24f), new DhApiVec3f(1f+i,151f+i,25f), new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); } - IDhApiRenderableBoxGroup absolutePosBoxGroup = this.createAbsolutePositionedGroup(absBoxList); + IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(absBoxList); this.add(absolutePosBoxGroup); @@ -276,7 +276,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new DhApiVec3f(0f,0f+i,0f), new DhApiVec3f(1f,1f+i,1f), new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); } - IDhApiRenderableBoxGroup relativePosBoxGroup = this.createRelativePositionedGroup( + IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup( new DhApiVec3f(24f, 140f, 24f), relBoxList); relativePosBoxGroup.setPreRenderFunc((event) -> @@ -300,7 +300,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()))); } } - IDhApiRenderableBoxGroup massRelativePosBoxGroup = this.createRelativePositionedGroup( + IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup( new DhApiVec3f(-25f, 140f, 0f), massRelBoxList); massRelativePosBoxGroup.setPreRenderFunc((event) -> @@ -323,29 +323,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister - - //================// - // group creation // - //================// - - @Override - public IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox box) - { - ArrayList list = new ArrayList<>(); - list.add(box); - return this.createAbsolutePositionedGroup(list); - } - - @Override - public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List boxList) - { return new RenderableBoxGroup(new Vec3f(originBlockPos), boxList, true); } - - @Override - public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList) - { return new RenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); } - - - //==============// // registration // //==============// @@ -355,7 +332,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { if (!(iBoxGroup instanceof RenderableBoxGroup)) { - throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"]."); + throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"], type received: ["+(iBoxGroup != null ? iBoxGroup.getClass() : "NULL")+"]."); } RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup; @@ -493,9 +470,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.shader.setUniform(this.instancedShaderOffsetUniform, new Vec3f( - boxGroup.originBlockPos.x, - boxGroup.originBlockPos.y, - boxGroup.originBlockPos.z + boxGroup.getOriginBlockPos().x, + boxGroup.getOriginBlockPos().y, + boxGroup.getOriginBlockPos().z )); this.shader.setUniform(this.instancedShaderCameraPosUniform, @@ -577,7 +554,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); this.shader.setUniform(this.blockLightUniform, boxGroup.blockLight); - for (DhApiRenderableBox box : boxGroup.boxList) + for (DhApiRenderableBox box : boxGroup) { renderBox(boxGroup, box, transformMatrix, camPos); } @@ -591,9 +568,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister float originOffsetZ = 0; if (boxGroup.positionBoxesRelativeToGroupOrigin) { - originOffsetX = boxGroup.originBlockPos.x; - originOffsetY = boxGroup.originBlockPos.y; - originOffsetZ = boxGroup.originBlockPos.z; + originOffsetX = boxGroup.getOriginBlockPos().x; + originOffsetY = boxGroup.getOriginBlockPos().y; + originOffsetZ = boxGroup.getOriginBlockPos().z; } Mat4f boxTransform = Mat4f.createTranslateMatrix( @@ -640,259 +617,4 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister return LodUtil.formatLog("Generic Obj Count: " + activeCountText + "/" + totalCountText); } - - - //================// - // helper classes // - //================// - - private static final class RenderableBoxGroup - extends AbstractList - implements IDhApiRenderableBoxGroup, Closeable - { - public final static AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0); - - - - public final long id; - - /** If false the boxes will be positioned relative to the level's origin */ - public final boolean positionBoxesRelativeToGroupOrigin; - - private final ArrayList boxList; - - private final Vec3f originBlockPos; - - public int skyLight = 15; - public int blockLight = 0; - - @Nullable - public Consumer beforeRenderFunc; - - private boolean vertexDataDirty = true; - public boolean active = true; - - // instance data - private int instanceTranslationVbo = 0; - private int instanceScaleVbo = 0; - private int instanceColorVbo = 0; - - - - // setters/getters // - - @Override - public long getId() { return this.id; } - - @Override - public void setOriginBlockPos(DhApiVec3f pos) - { - this.originBlockPos.x = pos.x; - this.originBlockPos.y = pos.y; - this.originBlockPos.z = pos.z; - } - - @Override - public DhApiVec3f getOriginBlockPos() { return new DhApiVec3f(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } - - - @Override - public void setSkyLight(int skyLight) - { - if (skyLight < LodUtil.MIN_MC_LIGHT || skyLight > LodUtil.MAX_MC_LIGHT) - { - throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); - } - this.skyLight = skyLight; - } - @Override - public int getSkyLight() { return this.skyLight; } - - @Override - public void setBlockLight(int blockLight) - { - if (blockLight < LodUtil.MIN_MC_LIGHT || blockLight > LodUtil.MAX_MC_LIGHT) - { - throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); - } - this.blockLight = blockLight; - } - @Override - public int getBlockLight() { return this.blockLight; } - - - - //=============// - // constructor // - //=============// - - public RenderableBoxGroup(Vec3f originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) - { - // TODO save to database - // TODO when? - - this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); - this.boxList = new ArrayList<>(boxList); - - this.originBlockPos = originBlockPos; - this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin; - } - - - - // methods // - - @Override - public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); } - - @Override - public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; } - - @Override - public void triggerBoxChange() { this.vertexDataDirty = true; } - - @Override - public void setActive(boolean active) { this.active = active; } - @Override - public boolean isActive() { return this.active; } - - public void preRender(DhApiRenderParam renderEventParam) - { - if (this.beforeRenderFunc != null) - { - beforeRenderFunc.accept(renderEventParam); - } - } - - - - // overrides // - - @Override - public DhApiRenderableBox get(int index) { return this.boxList.get(index); } - @Override - public int size() { return this.boxList.size(); } - @Override - public boolean removeIf(Predicate filter) { return this.boxList.removeIf(filter); } - @Override - public void replaceAll(UnaryOperator operator) { this.boxList.replaceAll(operator); } - @Override - public void sort(Comparator c) { this.boxList.sort(c); } - @Override - public void forEach(Consumer action) { this.boxList.forEach(action); } - @Override - public Spliterator spliterator() { return this.boxList.spliterator(); } - @Override - public Stream stream() { return this.boxList.stream(); } - @Override - public Stream parallelStream() { return this.boxList.parallelStream(); } - - - - //===================// - // vertex attributes // - //===================// - - /** Does nothing if the vertex data is already up-to-date */ - private void updateVertexAttributeData() - { - if (!this.vertexDataDirty) - { - return; - } - this.vertexDataDirty = false; - - if (this.instanceTranslationVbo == 0) - { - this.instanceTranslationVbo = GL32.glGenBuffers(); - this.instanceScaleVbo = GL32.glGenBuffers(); - this.instanceColorVbo = GL32.glGenBuffers(); - } - - int boxCount = this.size(); - - - // transformation / scaling // - - float[] translationData = new float[boxCount * 3]; - float[] scalingData = new float[boxCount * 3]; - for (int i = 0; i < boxCount; i++) - { - DhApiRenderableBox box = this.get(i); - - int dataIndex = i * 3; - - translationData[dataIndex] = box.minPos.x; - translationData[dataIndex + 1] = box.minPos.y; - translationData[dataIndex + 2] = box.minPos.z; - - scalingData[dataIndex] = box.maxPos.x - box.minPos.x; - scalingData[dataIndex + 1] = box.maxPos.y - box.minPos.y; - scalingData[dataIndex + 2] = box.maxPos.z - box.minPos.z; - - } - - - // colors // - - float[] colorData = new float[boxCount * 4]; - for (int i = 0; i < boxCount; i++) - { - DhApiRenderableBox box = this.get(i); - Color color = box.color; - int colorIndex = i * 4; - colorData[colorIndex] = color.getRed() / 255.0f; - colorData[colorIndex + 1] = color.getGreen() / 255.0f; - colorData[colorIndex + 2] = color.getBlue() / 255.0f; - colorData[colorIndex + 3] = color.getAlpha() / 255.0f; - } - - - // Upload transformation matrices - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslationVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translationData ,GL32.GL_DYNAMIC_DRAW); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW); - - // Upload colors - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW); - } - - - - //================// - // base overrides // - //================// - - @Override - public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; } - - @Override - public void close() - { - GLProxy.getInstance().queueRunningOnRenderThread(() -> - { - if (this.instanceTranslationVbo != 0) - { - GL32.glDeleteBuffers(this.instanceTranslationVbo); - this.instanceTranslationVbo = 0; - } - - if (this.instanceScaleVbo != 0) - { - GL32.glDeleteBuffers(this.instanceScaleVbo); - this.instanceScaleVbo = 0; - } - - if (this.instanceColorVbo != 0) - { - GL32.glDeleteBuffers(this.instanceColorVbo); - this.instanceColorVbo = 0; - } - }); - } - - } - } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java new file mode 100644 index 000000000..bae8c24af --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java @@ -0,0 +1,76 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer; + +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.math.Vec3f; +import org.apache.logging.log4j.Logger; + +import java.util.List; +import java.util.*; + +/** + * Handles creating {@link DhApiRenderableBox}. + * + * @see IDhApiCustomRenderRegister + * @see DhApiRenderableBox + */ +public class GenericRenderObjectFactory implements IDhApiCustomRenderObjectFactory +{ + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + + public static final GenericRenderObjectFactory INSTANCE = new GenericRenderObjectFactory(); + + + + //=============// + // constructor // + //=============// + + private GenericRenderObjectFactory() { } + + + + //================// + // group creation // + //================// + + @Override + public IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox box) + { + ArrayList list = new ArrayList<>(); + list.add(box); + return this.createAbsolutePositionedGroup(list); + } + + @Override + public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List boxList) + { return new RenderableBoxGroup(new Vec3f(originBlockPos), boxList, true); } + + @Override + public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList) + { return new RenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java new file mode 100644 index 000000000..0e87d046e --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java @@ -0,0 +1,268 @@ +package com.seibel.distanthorizons.core.render.renderer; + +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.core.render.glObject.GLProxy; +import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.util.math.Vec3f; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.GL32; + +import java.awt.*; +import java.io.Closeable; +import java.util.*; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import java.util.stream.Stream; + +public class RenderableBoxGroup + extends AbstractList + implements IDhApiRenderableBoxGroup, Closeable + { + public final static AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0); + + + + public final long id; + + /** If false the boxes will be positioned relative to the level's origin */ + public final boolean positionBoxesRelativeToGroupOrigin; + + private final ArrayList boxList; + + private final Vec3f originBlockPos; + + public int skyLight = 15; + public int blockLight = 0; + + @Nullable + public Consumer beforeRenderFunc; + + private boolean vertexDataDirty = true; + public boolean active = true; + + // instance data + public int instanceTranslationVbo = 0; + public int instanceScaleVbo = 0; + public int instanceColorVbo = 0; + + + + // setters/getters // + + @Override + public long getId() { return this.id; } + + @Override + public void setOriginBlockPos(DhApiVec3f pos) + { + this.originBlockPos.x = pos.x; + this.originBlockPos.y = pos.y; + this.originBlockPos.z = pos.z; + } + + @Override + public DhApiVec3f getOriginBlockPos() { return new DhApiVec3f(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } + + + @Override + public void setSkyLight(int skyLight) + { + if (skyLight < LodUtil.MIN_MC_LIGHT || skyLight > LodUtil.MAX_MC_LIGHT) + { + throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); + } + this.skyLight = skyLight; + } + @Override + public int getSkyLight() { return this.skyLight; } + + @Override + public void setBlockLight(int blockLight) + { + if (blockLight < LodUtil.MIN_MC_LIGHT || blockLight > LodUtil.MAX_MC_LIGHT) + { + throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive)."); + } + this.blockLight = blockLight; + } + @Override + public int getBlockLight() { return this.blockLight; } + + + + //=============// + // constructor // + //=============// + + public RenderableBoxGroup(Vec3f originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) + { + this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); + this.boxList = new ArrayList<>(boxList); + + this.originBlockPos = originBlockPos; + this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin; + } + + + + // methods // + + @Override + public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); } + + @Override + public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; } + + @Override + public void triggerBoxChange() { this.vertexDataDirty = true; } + + @Override + public void setActive(boolean active) { this.active = active; } + @Override + public boolean isActive() { return this.active; } + + public void preRender(DhApiRenderParam renderEventParam) + { + if (this.beforeRenderFunc != null) + { + beforeRenderFunc.accept(renderEventParam); + } + } + + + + // overrides // + + @Override + public DhApiRenderableBox get(int index) { return this.boxList.get(index); } + @Override + public int size() { return this.boxList.size(); } + @Override + public boolean removeIf(Predicate filter) { return this.boxList.removeIf(filter); } + @Override + public void replaceAll(UnaryOperator operator) { this.boxList.replaceAll(operator); } + @Override + public void sort(Comparator c) { this.boxList.sort(c); } + @Override + public void forEach(Consumer action) { this.boxList.forEach(action); } + @Override + public Spliterator spliterator() { return this.boxList.spliterator(); } + @Override + public Stream stream() { return this.boxList.stream(); } + @Override + public Stream parallelStream() { return this.boxList.parallelStream(); } + + + + //===================// + // vertex attributes // + //===================// + + /** Does nothing if the vertex data is already up-to-date */ + public void updateVertexAttributeData() + { + if (!this.vertexDataDirty) + { + return; + } + this.vertexDataDirty = false; + + if (this.instanceTranslationVbo == 0) + { + this.instanceTranslationVbo = GL32.glGenBuffers(); + this.instanceScaleVbo = GL32.glGenBuffers(); + this.instanceColorVbo = GL32.glGenBuffers(); + } + + int boxCount = this.size(); + + + // transformation / scaling // + + float[] translationData = new float[boxCount * 3]; + float[] scalingData = new float[boxCount * 3]; + for (int i = 0; i < boxCount; i++) + { + DhApiRenderableBox box = this.get(i); + + int dataIndex = i * 3; + + translationData[dataIndex] = box.minPos.x; + translationData[dataIndex + 1] = box.minPos.y; + translationData[dataIndex + 2] = box.minPos.z; + + scalingData[dataIndex] = box.maxPos.x - box.minPos.x; + scalingData[dataIndex + 1] = box.maxPos.y - box.minPos.y; + scalingData[dataIndex + 2] = box.maxPos.z - box.minPos.z; + + } + + + // colors // + + float[] colorData = new float[boxCount * 4]; + for (int i = 0; i < boxCount; i++) + { + DhApiRenderableBox box = this.get(i); + Color color = box.color; + int colorIndex = i * 4; + colorData[colorIndex] = color.getRed() / 255.0f; + colorData[colorIndex + 1] = color.getGreen() / 255.0f; + colorData[colorIndex + 2] = color.getBlue() / 255.0f; + colorData[colorIndex + 3] = color.getAlpha() / 255.0f; + } + + + // Upload transformation matrices + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslationVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translationData ,GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW); + + // Upload colors + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW); + } + + + + //================// + // base overrides // + //================// + + @Override + public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; } + + @Override + public void close() + { + GLProxy.getInstance().queueRunningOnRenderThread(() -> + { + if (this.instanceTranslationVbo != 0) + { + GL32.glDeleteBuffers(this.instanceTranslationVbo); + this.instanceTranslationVbo = 0; + } + + if (this.instanceScaleVbo != 0) + { + GL32.glDeleteBuffers(this.instanceScaleVbo); + this.instanceScaleVbo = 0; + } + + if (this.instanceColorVbo != 0) + { + GL32.glDeleteBuffers(this.instanceColorVbo); + this.instanceColorVbo = 0; + } + }); + } + + } + \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java index d7855be30..bc23212f7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java @@ -50,10 +50,18 @@ public class DhApiWorldProxy implements IDhApiWorldProxy + //=============// + // constructor // + //=============// + private DhApiWorldProxy() { } + //=========// + // methods // + //=========// + @Override public boolean worldLoaded() { return SharedApi.getAbstractDhWorld() != null; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java index 9aef5d00c..17a49bc82 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.world; +import com.seibel.distanthorizons.core.level.DhClientLevel; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import org.jetbrains.annotations.Nullable; @@ -41,4 +42,6 @@ public interface IClientLevelWrapper extends ILevelWrapper @Nullable IBiomeWrapper getPlainsBiomeWrapper(); + void setParentClientLevel(DhClientLevel parentClientLevel); + } diff --git a/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java b/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java index 187a86c41..b297fa03a 100644 --- a/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java +++ b/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java @@ -20,6 +20,7 @@ package testItems.worldGeneratorInjection.objects; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.interfaces.world.IDhApiDimensionTypeWrapper; import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; @@ -52,4 +53,9 @@ public class LevelWrapperTest implements IDhApiLevelWrapper @Override public int getMinHeight() { return IDhApiLevelWrapper.super.getMinHeight(); } + @Override + public IDhApiCustomRenderRegister getRenderRegister() { return null; } + + + } From cc4cb10307b11838e68f570fd55f0d1ed9841691 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 4 Jul 2024 14:34:01 -0500 Subject: [PATCH 033/104] Fix uploading generic objects crashing --- .../core/render/renderer/GenericObjectRenderer.java | 5 ++++- .../core/render/renderer/RenderableBoxGroup.java | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index 420a4a3fa..c1d2b2f5b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -511,7 +511,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // Draw instanced - GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxGroup.size()); + if (boxGroup.uploadedBoxCount > 0) + { + GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxGroup.uploadedBoxCount); + } // Clean up diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java index 0e87d046e..ce170105b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java @@ -50,6 +50,7 @@ public class RenderableBoxGroup public int instanceTranslationVbo = 0; public int instanceScaleVbo = 0; public int instanceColorVbo = 0; + public int uploadedBoxCount = -1; @@ -131,7 +132,7 @@ public class RenderableBoxGroup { if (this.beforeRenderFunc != null) { - beforeRenderFunc.accept(renderEventParam); + this.beforeRenderFunc.accept(renderEventParam); } } @@ -181,6 +182,7 @@ public class RenderableBoxGroup } int boxCount = this.size(); + this.uploadedBoxCount = boxCount; // transformation / scaling // From ca711bbc72e9d918eaa8d8682e63c835c9148746 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 4 Jul 2024 14:34:12 -0500 Subject: [PATCH 034/104] Instance beacon rendering --- .../core/level/AbstractDhLevel.java | 237 +++++++++--------- 1 file changed, 122 insertions(+), 115 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 5ecc362dc..fb78f23e9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -68,13 +68,25 @@ public abstract class AbstractDhLevel implements IDhLevel /** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */ protected final ConcurrentHashMap> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>(); + protected final IDhApiRenderableBoxGroup beaconBoxGroup; + protected final HashSet beaconPosSet = new HashSet<>(); + + protected boolean beaconGroupBound = false; + //=============// // constructor // //=============// - protected AbstractDhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); } + protected AbstractDhLevel() + { + this.chunkToLodBuilder = new ChunkToLodBuilder(); + + this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(new ArrayList<>(0)); + this.beaconBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); + this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); + } protected void createAndSetSupportingRepos(File databaseFile) { @@ -201,96 +213,98 @@ public abstract class AbstractDhLevel implements IDhLevel } - HashMap beamRenderGroupByBlockPos = new HashMap<>(); - HashMap beamRefCountByPos = new HashMap<>(); - @Override public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List newBeamList) { - GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); - - // should always be non-null, but just in case - if (this.beaconBeamRepo != null - && genericObjectRenderer != null) + synchronized (this) { - HashSet allPosSet = new HashSet<>(); + GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); - // sort new beams - HashMap newBeamByPos = new HashMap<>(newBeamList.size()); - for (int i = 0; i < newBeamList.size(); i++) + // should always be non-null, but just in case + if (this.beaconBeamRepo != null + && genericObjectRenderer != null) { - BeaconBeamDTO beam = newBeamList.get(i); - newBeamByPos.put(beam.pos, beam); - allPosSet.add(beam.pos); - } - - // get existing beams - List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos); - HashMap existingBeamByPos = new HashMap<>(existingBeamList.size()); - for (int i = 0; i < existingBeamList.size(); i++) - { - BeaconBeamDTO beam = existingBeamList.get(i); - existingBeamByPos.put(beam.pos, beam); - allPosSet.add(beam.pos); - } - - - - for (DhBlockPos beaconPos : allPosSet) - { - if (!chunkPos.contains(beaconPos)) + if (!this.beaconGroupBound) { - // don't update beacons outside the updated chunk - continue; + this.beaconGroupBound = true; + genericObjectRenderer.add(this.beaconBoxGroup); } - BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos); - BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos); - if (existingBeam != null && newBeam != null) + HashSet allPosSet = new HashSet<>(); + + // sort new beams + HashMap newBeamByPos = new HashMap<>(newBeamList.size()); + for (int i = 0; i < newBeamList.size(); i++) { - // beam still exists in chunk, do nothing + BeaconBeamDTO beam = newBeamList.get(i); + newBeamByPos.put(beam.pos, beam); + allPosSet.add(beam.pos); } - else if (existingBeam == null && newBeam != null) + + // get existing beams + List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos); + HashMap existingBeamByPos = new HashMap<>(existingBeamList.size()); + for (int i = 0; i < existingBeamList.size(); i++) { - // new beam found, add to DB - this.beaconBeamRepo.save(newBeam); - - IDhApiRenderableBoxGroup beaconBox = GenericRenderObjectFactory.INSTANCE.createForSingleBox(new DhApiRenderableBox( - new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), - new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), - newBeam.color - )); - beaconBox.setBlockLight(LodUtil.MAX_MC_LIGHT); - beaconBox.setSkyLight(LodUtil.MAX_MC_LIGHT); - - this.beamRenderGroupByBlockPos.put(newBeam.pos, beaconBox); - this.beamRefCountByPos.compute(newBeam.pos, (beamPos, refCount) -> - { - if (refCount == null) - { - refCount = new AtomicInteger(0); - } - refCount.getAndIncrement(); - return refCount; - }); - - genericObjectRenderer.add(beaconBox); + BeaconBeamDTO beam = existingBeamList.get(i); + existingBeamByPos.put(beam.pos, beam); + allPosSet.add(beam.pos); } - else if (existingBeam != null && newBeam == null) + + + + for (DhBlockPos beaconPos : allPosSet) { - // beam no longer exists at position, remove - this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks - this.beamRefCountByPos.remove(existingBeam.pos); - IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByBlockPos.remove(existingBeam.pos); - if (beaconBox != null) + if (!chunkPos.contains(beaconPos)) { - genericObjectRenderer.remove(beaconBox.getId()); + // don't update beacons outside the updated chunk + continue; } + + BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos); + BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos); + + if (existingBeam != null && newBeam != null) + { + // beam still exists in chunk, do nothing + } + else if (existingBeam == null && newBeam != null) + { + // new beam found, add to DB + this.beaconBeamRepo.save(newBeam); + + // TODO put everything in a single group + DhApiRenderableBox beaconBox = new DhApiRenderableBox( + new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), + new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), + newBeam.color + ); + + if (this.beaconPosSet.add(beaconPos)) + { + this.beaconBoxGroup.add(beaconBox); + this.beaconBoxGroup.triggerBoxChange(); + } + } + else if (existingBeam != null && newBeam == null) + { + // beam no longer exists at position, remove + this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks + if (this.beaconPosSet.remove(existingBeam.pos)) + { + this.beaconBoxGroup.removeIf((box) -> + box.minPos.x == beaconPos.x + && box.minPos.y == beaconPos.y+1 // plus 1 because the beam starts above the beacon + && box.minPos.z == beaconPos.z + ); + this.beaconBoxGroup.triggerBoxChange(); + } + } + } } - } } @@ -303,35 +317,29 @@ public abstract class AbstractDhLevel implements IDhLevel if (this.beaconBeamRepo != null && genericObjectRenderer != null) { + if (!this.beaconGroupBound) + { + this.beaconGroupBound = true; + genericObjectRenderer.add(this.beaconBoxGroup); + } + + // get beams in pos List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); for (int i = 0; i < existingBeamList.size(); i++) { - BeaconBeamDTO beam = existingBeamList.get(i); + BeaconBeamDTO newBeam = existingBeamList.get(i); - IDhApiRenderableBoxGroup beaconBox = GenericRenderObjectFactory.INSTANCE.createForSingleBox(new DhApiRenderableBox( - new DhApiVec3f(beam.pos.x, beam.pos.y+1, beam.pos.z), - new DhApiVec3f(beam.pos.x+1, 6_000, beam.pos.z+1), - beam.color - )); - beaconBox.setBlockLight(LodUtil.MAX_MC_LIGHT); - beaconBox.setSkyLight(LodUtil.MAX_MC_LIGHT); - - this.beamRefCountByPos.compute(beam.pos, (beamPos, refCount) -> + DhApiRenderableBox beaconBox = new DhApiRenderableBox( + new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), + new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), + newBeam.color + ); + if (this.beaconPosSet.add(newBeam.pos)) { - if (refCount == null) - { - refCount = new AtomicInteger(0); - } - - if (refCount.getAndIncrement() == 0) - { - this.beamRenderGroupByBlockPos.put(beam.pos, beaconBox); - genericObjectRenderer.add(beaconBox); - } - - return refCount; - }); + this.beaconBoxGroup.add(beaconBox); + this.beaconBoxGroup.triggerBoxChange(); + } } } } @@ -352,27 +360,16 @@ public abstract class AbstractDhLevel implements IDhLevel BeaconBeamDTO beam = existingBeamList.get(i); // beam no longer exists at position, remove - this.beamRefCountByPos.compute(beam.pos, (beamPos, refCount) -> + this.beaconBeamRepo.deleteWithKey(beam.pos); // TODO broken when updating adjacent chunks + if (this.beaconPosSet.remove(beam.pos)) { - if (refCount == null) - { - return null; - } - - if (refCount.decrementAndGet() == 0) - { - IDhApiRenderableBoxGroup beaconBox = this.beamRenderGroupByBlockPos.remove(beam.pos); - if (beaconBox != null) - { - genericObjectRenderer.remove(beaconBox.getId()); - } - return null; - } - else - { - return refCount; - } - }); + this.beaconBoxGroup.removeIf((box) -> + box.minPos.x == beam.pos.x + && box.minPos.y == beam.pos.y+1 // plus 1 because the beam starts above the beacon + && box.minPos.z == beam.pos.z + ); + this.beaconBoxGroup.triggerBoxChange(); + } } } } @@ -384,6 +381,16 @@ public abstract class AbstractDhLevel implements IDhLevel //================// @Override - public void close() { this.chunkToLodBuilder.close(); } + public void close() + { + this.chunkToLodBuilder.close(); + + GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); + if (genericObjectRenderer != null) + { + genericObjectRenderer.remove(this.beaconBoxGroup.getId()); + this.beaconGroupBound = false; + } + } } From 120dddf84420f656934802ee4c7e1f4cc7d9c837 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 4 Jul 2024 16:14:32 -0500 Subject: [PATCH 035/104] Fix Api client level not containing the generic renderer --- .../com/seibel/distanthorizons/core/level/DhClientLevel.java | 4 ++-- .../distanthorizons/core/level/DhClientServerLevel.java | 1 + .../distanthorizons/core/world/DhClientServerWorld.java | 1 + .../core/wrapperInterfaces/world/IClientLevelWrapper.java | 5 ++--- .../core/wrapperInterfaces/world/ILevelWrapper.java | 4 ++++ 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index 1f7e19a9b..b4c82336e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -60,7 +60,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel public DhClientLevel(AbstractSaveStructure saveStructure, IClientLevelWrapper clientLevelWrapper, @Nullable File fullDataSaveDirOverride, boolean enableRendering) { this.levelWrapper = clientLevelWrapper; - this.levelWrapper.setParentClientLevel(this); + this.levelWrapper.setParentLevel(this); this.saveStructure = saveStructure; this.dataFileHandler = new RemoteFullDataSourceProvider(this, saveStructure, fullDataSaveDirOverride); this.clientside = new ClientLevelModule(this); @@ -157,7 +157,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel @Override public void close() { - this.levelWrapper.setParentClientLevel(null); + this.levelWrapper.setParentLevel(null); this.clientside.close(); super.close(); this.dataFileHandler.close(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index 5d6f6ca79..af8f78cdf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -68,6 +68,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev LOGGER.warn("unable to create data folder."); } this.serverLevelWrapper = serverLevelWrapper; + this.serverLevelWrapper.setParentLevel(this); this.serverside = new ServerLevelModule(this, saveStructure); this.clientside = new ClientLevelModule(this); this.createAndSetSupportingRepos(this.serverside.fullDataFileHandler.repo.databaseFile); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java index 7b39f48e7..020f5289f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientServerWorld.java @@ -98,6 +98,7 @@ public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWor } level.startRenderer(clientLevelWrapper); + clientLevelWrapper.setParentLevel(level); return level; }); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java index 17a49bc82..e21cf6a8e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java @@ -19,7 +19,8 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.world; -import com.seibel.distanthorizons.core.level.DhClientLevel; +import com.seibel.distanthorizons.core.level.IDhClientLevel; +import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import org.jetbrains.annotations.Nullable; @@ -42,6 +43,4 @@ public interface IClientLevelWrapper extends ILevelWrapper @Nullable IBiomeWrapper getPlainsBiomeWrapper(); - void setParentClientLevel(DhClientLevel parentClientLevel); - } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java index 127ff04fa..ac52dd9b2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java @@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.world; import com.seibel.distanthorizons.api.interfaces.world.IDhApiDimensionTypeWrapper; import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; +import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; @@ -64,4 +65,7 @@ public interface ILevelWrapper extends IDhApiLevelWrapper, IBindable /** Fired when the level is being unloaded. Doesn't unload the level. */ void onUnload(); + @Deprecated + void setParentLevel(IDhLevel parentLevel); + } From e98f17f63bddcc4c6ea3bcb4bf1a5cb3fe933129 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 4 Jul 2024 16:23:39 -0500 Subject: [PATCH 036/104] Remove useless IServerLevelWrapper.tryGetClientLevelWrapper() --- .../seibel/distanthorizons/core/level/DhClientServerLevel.java | 2 +- .../core/wrapperInterfaces/world/IServerLevelWrapper.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index af8f78cdf..ad52ba5cf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -150,7 +150,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev } @Override - public IClientLevelWrapper getClientLevelWrapper() { return this.serverLevelWrapper.tryGetClientLevelWrapper(); } + public IClientLevelWrapper getClientLevelWrapper() { return MC_CLIENT.getWrappedClientLevel(); } @Override public void clearRenderCache() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java index b6740bb13..3b4a00b60 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IServerLevelWrapper.java @@ -24,9 +24,6 @@ import java.io.File; public interface IServerLevelWrapper extends ILevelWrapper { - @Nullable - IClientLevelWrapper tryGetClientLevelWrapper(); - File getSaveFolder(); } From fce703579fd1a004e22cfd32b53e4b02b9ca5540 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 4 Jul 2024 21:41:57 -0500 Subject: [PATCH 037/104] Fix concurrent modification for GenericObjectRenderer --- .../renderer/GenericObjectRenderer.java | 60 ++++--------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java index c1d2b2f5b..6d5b8a4ec 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java @@ -58,6 +58,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.*; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; @@ -111,9 +112,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private int blockLightUniform; - // TODO may need to be double buffered to prevent rendering lag - private final Long2ReferenceOpenHashMap boxGroupById = new Long2ReferenceOpenHashMap<>(); - private final ReentrantLock mapModifyLock = new ReentrantLock(); + private final ConcurrentHashMap boxGroupById = new ConcurrentHashMap<>(); @@ -337,53 +336,19 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup; - try + long id = boxGroup.getId(); + if (this.boxGroupById.containsKey(id)) { - mapModifyLock.lock(); - - long id = boxGroup.getId(); - if (this.boxGroupById.containsKey(id)) - { - throw new IllegalArgumentException("A box group with the ID [" + id + "] is already present."); - } - - this.boxGroupById.put(id, boxGroup); - - // TODO add to DB async? - } - finally - { - mapModifyLock.unlock(); + throw new IllegalArgumentException("A box group with the ID [" + id + "] is already present."); } + + this.boxGroupById.put(id, boxGroup); } @Override - public IDhApiRenderableBoxGroup remove(long id) - { - try - { - mapModifyLock.lock(); - // TODO remove from DB async? - return this.boxGroupById.remove(id); - } - finally - { - mapModifyLock.unlock(); - } - } + public IDhApiRenderableBoxGroup remove(long id) { return this.boxGroupById.remove(id); } - public void clear() - { - try - { - mapModifyLock.lock(); - this.boxGroupById.clear(); - } - finally - { - mapModifyLock.unlock(); - } - } + public void clear() { this.boxGroupById.clear(); } @@ -422,12 +387,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // rendering // - LongSet keys = boxGroupById.keySet(); - for (long key : keys) + Collection boxList = this.boxGroupById.values(); + for (RenderableBoxGroup boxGroup : boxList) { - RenderableBoxGroup boxGroup = boxGroupById.get(key); // ignore inactive groups - if (boxGroup.active) + if (boxGroup != null && boxGroup.active) { profiler.popPush("render prep"); boxGroup.preRender(renderEventParam); From c2c8bf861309efb6cbae67566bf8b6e87271d287 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 5 Jul 2024 06:56:46 -0500 Subject: [PATCH 038/104] minor generic render refactor --- .../seibel/distanthorizons/core/Initializer.java | 2 +- .../dataObjects/transformers/LodDataBuilder.java | 5 ----- .../distanthorizons/core/level/AbstractDhLevel.java | 6 ++---- .../core/level/ClientLevelModule.java | 2 +- .../distanthorizons/core/level/DhClientLevel.java | 2 +- .../core/level/DhClientServerLevel.java | 2 +- .../distanthorizons/core/level/DhServerLevel.java | 2 +- .../seibel/distanthorizons/core/level/IDhLevel.java | 3 +-- .../distanthorizons/core/logging/f3/F3Screen.java | 4 +--- .../core/render/LodRenderSection.java | 9 --------- .../core/render/renderer/LodRenderer.java | 1 + .../{ => generic}/GenericObjectRenderer.java | 13 +------------ .../{ => generic}/GenericRenderObjectFactory.java | 2 +- .../renderer/{ => generic}/RenderableBoxGroup.java | 2 +- 14 files changed, 13 insertions(+), 42 deletions(-) rename core/src/main/java/com/seibel/distanthorizons/core/render/renderer/{ => generic}/GenericObjectRenderer.java (97%) rename core/src/main/java/com/seibel/distanthorizons/core/render/renderer/{ => generic}/GenericRenderObjectFactory.java (97%) rename core/src/main/java/com/seibel/distanthorizons/core/render/renderer/{ => generic}/RenderableBoxGroup.java (99%) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java index 91a4d88f7..a68a42253 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java @@ -20,7 +20,7 @@ package com.seibel.distanthorizons.core; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory; import com.seibel.distanthorizons.core.sql.DatabaseUpdater; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.coreapi.ModInfo; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index 9cf58eecc..e2dc80925 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -19,16 +19,12 @@ package com.seibel.distanthorizons.core.dataObjects.transformers; -import java.awt.*; import java.util.List; import com.seibel.distanthorizons.api.enums.config.EDhApiWorldCompressionMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep; -import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.objects.data.DhApiChunk; import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint; -import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; -import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -37,7 +33,6 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.DataCorruptedException; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index fb78f23e9..69a5ec429 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -30,8 +30,8 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; -import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO; import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; @@ -49,7 +49,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; public abstract class AbstractDhLevel implements IDhLevel { @@ -274,7 +273,6 @@ public abstract class AbstractDhLevel implements IDhLevel // new beam found, add to DB this.beaconBeamRepo.save(newBeam); - // TODO put everything in a single group DhApiRenderableBox beaconBox = new DhApiRenderableBox( new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java index 7e2d13cc7..d56cdd07f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java @@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.render.LodQuadTree; import com.seibel.distanthorizons.core.render.RenderBufferHandler; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.render.renderer.LodRenderer; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index b4c82336e..842bf1fe8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -27,7 +27,7 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.render.RenderBufferHandler; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index ad52ba5cf..07fd566d4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index c6b4c6911..60d8a2fbc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -25,7 +25,7 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.render.RenderBufferHandler; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import org.apache.logging.log4j.Logger; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java index 575ade4a6..00e12ba3d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java @@ -19,13 +19,12 @@ package com.seibel.distanthorizons.core.level; -import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.render.RenderBufferHandler; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java b/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java index 6719ada25..b0e0f5449 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/logging/f3/F3Screen.java @@ -22,15 +22,13 @@ package com.seibel.distanthorizons.core.logging.f3; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.render.RenderBufferHandler; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.world.AbstractDhWorld; import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Nullable; -import java.lang.ref.WeakReference; import java.text.NumberFormat; import java.util.*; import java.util.concurrent.ThreadPoolExecutor; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index 372e64f7c..22605df90 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -19,9 +19,6 @@ package com.seibel.distanthorizons.core.render; -import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; -import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; -import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource; @@ -31,16 +28,11 @@ import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.render.glObject.GLProxy; -import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.ColumnRenderBuffer; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; -import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; -import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; -import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.Logger; @@ -49,7 +41,6 @@ import org.jetbrains.annotations.Nullable; import javax.annotation.WillNotClose; import java.awt.*; import java.util.*; -import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index e6df38b6d..0eda3a554 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -38,6 +38,7 @@ import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; import com.seibel.distanthorizons.core.render.glObject.buffer.QuadElementBuffer; import com.seibel.distanthorizons.core.render.glObject.texture.*; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.render.renderer.shaders.*; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java similarity index 97% rename from core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java rename to core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 6d5b8a4ec..54c4c40da 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.seibel.distanthorizons.core.render.renderer; +package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; @@ -43,28 +43,17 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrap import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3f; -import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongSet; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.opengl.ARBInstancedArrays; import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL33; -import javax.annotation.Nullable; import java.awt.*; -import java.io.Closeable; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.*; -import java.util.List; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.Predicate; -import java.util.function.UnaryOperator; -import java.util.stream.Stream; /** * Handles rendering generic groups of {@link DhApiRenderableBox}. diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java similarity index 97% rename from core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java rename to core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java index bae8c24af..a9234a2c6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.seibel.distanthorizons.core.render.renderer; +package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java similarity index 99% rename from core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java rename to core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java index ce170105b..f8f3fe60d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java @@ -1,4 +1,4 @@ -package com.seibel.distanthorizons.core.render.renderer; +package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; From 197e6e8178f3a3ab3218b9d31c4a4d2248c3e97a Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 14:52:30 -0500 Subject: [PATCH 039/104] add vec3f distance methods --- .../distanthorizons/core/util/math/Vec3f.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3f.java b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3f.java index dbc502f52..11f4b8f46 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3f.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3f.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.util.math; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.coreapi.util.MathUtil; /** @@ -51,6 +52,14 @@ public class Vec3f extends DhApiVec3f this.z = pos.z; } + public Vec3f(Vec3d pos) + { + this.x = (float) pos.x; + this.y = (float) pos.y; + this.z = (float) pos.z; + } + + //==============// @@ -132,6 +141,20 @@ public class Vec3f extends DhApiVec3f this.z = f * f4 - f1 * f3; } + public static float getManhattanDistance(DhApiVec3f a, DhApiVec3f b) + { + return Math.abs(a.x - b.x) + + Math.abs(a.y - b.y) + + Math.abs(a.z - b.z); + } + + public static double getDistance(DhApiVec3f a, DhApiVec3f b) + { + return Math.sqrt(Math.pow(a.x - b.x, 2) + + Math.pow(a.y - b.y, 2) + + Math.pow(a.z - b.z, 2)); + } + //==============// From f4a8bfeb0a380a6b6e0369a353ef5ec928c8db9e Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 18:02:43 -0500 Subject: [PATCH 040/104] Add cloud rendering --- .../render/IDhApiRenderableBoxGroup.java | 11 + .../DhApiRenderableBoxGroupShading.java | 93 ++++++ .../core/level/AbstractDhLevel.java | 11 +- .../core/render/renderer/LodRenderer.java | 17 +- .../renderer/generic/CloudRenderHandler.java | 301 ++++++++++++++++++ .../generic/GenericObjectRenderer.java | 158 ++++++--- .../renderer/generic/RenderableBoxGroup.java | 35 +- .../distanthorizons/textures/clouds.png | Bin 0 -> 6214 bytes .../shaders/genericObject/instanced/vert.vert | 21 +- 9 files changed, 590 insertions(+), 57 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBoxGroupShading.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java create mode 100644 core/src/main/resources/assets/distanthorizons/textures/clouds.png diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java index bf5280941..061f75455 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -1,8 +1,10 @@ package com.seibel.distanthorizons.api.interfaces.render; +import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import java.util.List; import java.util.function.Consumer; @@ -27,6 +29,11 @@ public interface IDhApiRenderableBoxGroup extends List /** @return if active this group will render. */ boolean isActive(); + /** Sets whether this group should render with Screen Space Ambient Occlusioning. */ + void setSsaoEnabled(boolean ssaoEnabled); + /** @return if active this group will render with Screen Space Ambient Occlusioning. */ + boolean isSsaoEnabled(); + /** Sets where this group will render in the level. */ void setOriginBlockPos(DhApiVec3f pos); /** @return the block position in the level that all {@see DhApiRenderableBox} will render relative to. */ @@ -37,6 +44,7 @@ public interface IDhApiRenderableBoxGroup extends List * This is a good place to change the origin or notify of any box changes. */ void setPreRenderFunc(Consumer renderEventParam); + void setPostRenderFunc(Consumer renderEventParam); // TODO name? /** * If a cube's color, position, or other property is changed this method @@ -55,4 +63,7 @@ public interface IDhApiRenderableBoxGroup extends List void setBlockLight(int blockLight); int getBlockLight(); + void setShading(DhApiRenderableBoxGroupShading shading); + DhApiRenderableBoxGroupShading getShading(); + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBoxGroupShading.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBoxGroupShading.java new file mode 100644 index 000000000..396f73bc5 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBoxGroupShading.java @@ -0,0 +1,93 @@ +package com.seibel.distanthorizons.api.objects.render; + + +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; + +import java.awt.*; + +/** + * @see IDhApiRenderableBoxGroup + * + * Shading values are multiplied against the color for each direction, + * for example:
+ * A shading value of 1.0 indicates the color is unchanged.
+ * A shading value of 0.0 changes the color to black.
+ * + * @author James Seibel + * @version 2024-7-7 + * @since API 3.0.0 + */ +public class DhApiRenderableBoxGroupShading +{ + /** negative X */ + public float north = 1.0f; + /** positive X */ + public float south = 1.0f; + + /** positive X */ + public float east = 1.0f; + /** negative X */ + public float west = 1.0f; + + /** positive Y */ + public float top = 1.0f; + /** negative Y */ + public float bottom = 1.0f; + + + + //==============// + // constructors // + //==============// + + public static DhApiRenderableBoxGroupShading getDefaultShaded() + { + DhApiRenderableBoxGroupShading shading = new DhApiRenderableBoxGroupShading(); + shading.setDefaultShaded(); + return shading; + } + + public static DhApiRenderableBoxGroupShading getUnshaded() + { + DhApiRenderableBoxGroupShading shading = new DhApiRenderableBoxGroupShading(); + shading.setUnshaded(); + return shading; + } + + + + //=========// + // methods // + //=========// + + /** + * Directions will have different brightness similar to Minecraft blocks.
+ * This is a good default for un-lit objects. + */ + public void setDefaultShaded() + { + this.north = 0.8f; + this.south = 0.8f; + this.east = 0.6f; + this.west = 0.6f; + this.top = 1.0f; + this.bottom = 0.5f; + } + + /** + * All directions render with the same brightness.
+ * This is best used for glowing objects like beacons. + */ + public void setUnshaded() + { + this.north = 1.0f; + this.south = 1.0f; + this.east = 1.0f; + this.west = 1.0f; + this.top = 1.0f; + this.bottom = 1.0f; + } + +} + diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 69a5ec429..899ef4ce6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -23,6 +23,8 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkModifiedEvent; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; +import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dataObjects.transformers.ChunkToLodBuilder; import com.seibel.distanthorizons.core.file.fullDatafile.DelayedFullDataSourceSaveCache; @@ -30,6 +32,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; +import com.seibel.distanthorizons.core.render.renderer.generic.CloudRenderHandler; import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; @@ -72,6 +75,8 @@ public abstract class AbstractDhLevel implements IDhLevel protected boolean beaconGroupBound = false; + protected CloudRenderHandler cloudRenderHandler; + //=============// @@ -85,6 +90,8 @@ public abstract class AbstractDhLevel implements IDhLevel this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(new ArrayList<>(0)); this.beaconBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); + this.beaconBoxGroup.setShading(DhApiRenderableBoxGroupShading.getUnshaded()); + this.beaconBoxGroup.setPreRenderFunc((renderEventParam) -> this.beaconBoxGroup.setActive(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering.get())); } protected void createAndSetSupportingRepos(File databaseFile) @@ -221,12 +228,13 @@ public abstract class AbstractDhLevel implements IDhLevel // should always be non-null, but just in case if (this.beaconBeamRepo != null - && genericObjectRenderer != null) + && genericObjectRenderer != null) { if (!this.beaconGroupBound) { this.beaconGroupBound = true; genericObjectRenderer.add(this.beaconBoxGroup); + this.cloudRenderHandler = new CloudRenderHandler(this, genericObjectRenderer); } @@ -319,6 +327,7 @@ public abstract class AbstractDhLevel implements IDhLevel { this.beaconGroupBound = true; genericObjectRenderer.add(this.beaconBoxGroup); + this.cloudRenderHandler = new CloudRenderHandler(this, genericObjectRenderer); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 0eda3a554..4648be93b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -303,9 +303,12 @@ public class LodRenderer ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam); this.bufferHandler.renderOpaque(this, renderEventParam); - // custom objects - profiler.popPush("Custom Objects"); - this.genericObjectRenderer.render(renderEventParam, profiler); + // custom objects with SSAO + if (Config.Client.Advanced.Graphics.GenericRendering.enableRendering.get()) + { + profiler.popPush("Custom Objects"); + this.genericObjectRenderer.render(renderEventParam, profiler, true); + } // SSAO @@ -316,6 +319,14 @@ public class LodRenderer } + // custom objects without SSAO + if (Config.Client.Advanced.Graphics.GenericRendering.enableRendering.get()) + { + profiler.popPush("Custom Objects"); + this.genericObjectRenderer.render(renderEventParam, profiler, false); + } + + if (Config.Client.Advanced.Graphics.Fog.drawMode.get() != EDhApiFogDrawMode.FOG_DISABLED) { profiler.popPush("LOD Fog"); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java new file mode 100644 index 000000000..3557bf5cf --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -0,0 +1,301 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer.generic; + +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.level.IDhLevel; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import org.apache.logging.log4j.Logger; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; + +public class CloudRenderHandler +{ + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + private static final String CLOUD_RESOURCE_TEXTURE_PATH = "assets/distanthorizons/textures/clouds.png"; + // FIXME transparency sorting makes having transparent clouds impossible + private static final Color CLOUD_COLOR = new Color(255,255,255,255); + + private static final boolean DEBUG_BORDER_COLORS = false; + + /** + * How wide an individual box is.
+ * Measured in blocks. + */ + private static final int CLOUD_BOX_WIDTH = 128; + /** measured in blocks */ + private static final int CLOUD_BOX_THICKNESS = 32; + + private final IDhApiRenderableBoxGroup[][] boxGroupByOffset; + private final IDhLevel level; + + private float moveSpeedInBlocksPerSecond = 3.0f; + + + + //=============// + // constructor // + //=============// + + public CloudRenderHandler(IDhLevel level, GenericObjectRenderer renderer) + { + this.level = level; + + + // default to a single empty slot in case the texture is broken + boolean[][] cloudLocations = new boolean[1][1]; + try + { + cloudLocations = getCloudsFromTexture(); + } + catch (FileNotFoundException e) + { + LOGGER.error(e.getMessage(), e); + } + catch (IOException e) + { + LOGGER.error("Unexpected issue getting cloud texture, error: ["+e.getMessage()+"].", e); + } + + if (cloudLocations.length != 0 && + cloudLocations.length != cloudLocations[0].length) + { + LOGGER.warn("Non-square cloud texture found, some parts of the texture will be clipped off."); + } + + + + int textureWidth = cloudLocations.length; + ArrayList boxList = new ArrayList<>(512); + for (int x = 0; x < textureWidth; x ++) + { + for (int z = 0; z < textureWidth; z ++) + { + if (cloudLocations[x][z]) + { + int minX = x * CLOUD_BOX_WIDTH; + int minZ = z * CLOUD_BOX_WIDTH; + int maxX = minX + CLOUD_BOX_WIDTH; + int maxZ = minZ + CLOUD_BOX_WIDTH; + + Color color = CLOUD_COLOR; + if (DEBUG_BORDER_COLORS) + { + // equals is included so the board is 2 blocks wide, it makes it easier to see + if (x <= 1) { color = Color.RED; } + else if (x >= textureWidth-2) { color = Color.GREEN; } + if (z <= 1) { color = Color.BLUE; } + else if (z >= textureWidth-2) { color = Color.BLACK; } + } + + DhApiRenderableBox box = new DhApiRenderableBox( + new DhApiVec3f(minX, 0, minZ), + new DhApiVec3f(maxX, CLOUD_BOX_THICKNESS, maxZ), + color + ); + boxList.add(box); + } + } + } + + + // slightly lighter shading than the default + DhApiRenderableBoxGroupShading cloudShading = DhApiRenderableBoxGroupShading.getUnshaded(); + cloudShading.north = cloudShading.south = 0.9f; + cloudShading.east = cloudShading.west = 0.8f; + cloudShading.top = 1.0f; + cloudShading.bottom = 0.7f; + + this.boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3]; + for (int x = -1; x <= 1; x++) + { + for (int z = -1; z <= 1; z++) + { + IDhApiRenderableBoxGroup boxGroup = GenericRenderObjectFactory.INSTANCE.createRelativePositionedGroup( + new DhApiVec3f(0, 0, 0), // the offset will be set during rendering + boxList); + boxGroup.setBlockLight(LodUtil.MIN_MC_LIGHT); + boxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); + boxGroup.setSsaoEnabled(false); + boxGroup.setShading(cloudShading); + + CloudParams offset = new CloudParams(textureWidth, x, z); + boxGroup.setPreRenderFunc((renderParam) -> this.preRender(offset)); + + renderer.add(boxGroup); + this.boxGroupByOffset[x+1][z+1] = boxGroup; + } + } + } + + public void preRender(CloudParams clouds) + { + IDhApiRenderableBoxGroup boxGroup = this.boxGroupByOffset[clouds.instanceOffsetX+1][clouds.instanceOffsetZ+1]; + + boolean renderClouds = Config.Client.Advanced.Graphics.GenericRendering.enableCloudRendering.get(); + boxGroup.setActive(renderClouds); + if(!renderClouds) + { + return; + } + + + + //================// + // cloud movement // + //================// + + long currentTime = System.currentTimeMillis(); + float deltaTime = (currentTime - clouds.lastFrameTime) / 1000.0f; // Delta time in seconds + clouds.lastFrameTime = currentTime; + + float deltaX = this.moveSpeedInBlocksPerSecond * deltaTime; + // negative delta is to match vanilla's cloud movement + clouds.xOffset -= deltaX; + // wrap the cloud around after reaching the edge + clouds.xOffset %= clouds.widthInBlocks; + + + + //============================// + // camera movement and offset // + //============================// + + // camera position + int cameraPosX = (int)MC_RENDER.getCameraExactPosition().x; + int cameraPosZ = (int)MC_RENDER.getCameraExactPosition().z; + // offset the camera position by negative 1 width when below zero to fix off-by-one errors in the negative direction + if (cameraPosX < 0) { cameraPosX -= clouds.widthInBlocks; } + if (cameraPosZ < 0) { cameraPosZ -= clouds.widthInBlocks; } + + // determine how many cloud instances away from the origin we are + int cloudInstanceOffsetX = cameraPosX / (int)clouds.widthInBlocks; + int cloudInstanceOffsetZ = cameraPosZ / (int)clouds.widthInBlocks; + + // calculate the new offset + float xOffset = (cloudInstanceOffsetX * clouds.widthInBlocks); + float zOffset = (cloudInstanceOffsetZ * clouds.widthInBlocks); + + + + //==============// + // update group // + //==============// + + boxGroup.setOriginBlockPos( + new DhApiVec3f( + clouds.xOffset + (clouds.instanceOffsetX * clouds.widthInBlocks) + xOffset + clouds.halfWidthInBlocks, + this.level.getLevelWrapper().getHeight() + 200, + clouds.zOffset + (clouds.instanceOffsetZ * clouds.widthInBlocks) + zOffset + clouds.halfWidthInBlocks + ) + ); + } + + + + //==================// + // texture handling // + //==================// + + public static boolean[][] getCloudsFromTexture() throws FileNotFoundException, IOException + { + final ClassLoader loader = Thread.currentThread().getContextClassLoader(); + + boolean[][] whitePixels = null; + try(InputStream imageInputStream = loader.getResourceAsStream(CLOUD_RESOURCE_TEXTURE_PATH)) + { + if (imageInputStream == null) + { + throw new FileNotFoundException("Unable to find cloud texture at resource path: ["+CLOUD_RESOURCE_TEXTURE_PATH+"]."); + } + + BufferedImage image = ImageIO.read(imageInputStream); + + int width = image.getWidth(); + int height = image.getHeight(); + + whitePixels = new boolean[width][height]; + + for (int x = 0; x < width; x ++) + { + for (int z = 0; z < width; z ++) + { + Color color = new Color(image.getRGB(x,z)); + whitePixels[x][z] = color.equals(Color.WHITE); + } + } + } + + return whitePixels; + } + + + + //================// + // helper classes // + //================// + + private static class CloudParams + { + public final float textureWidth; + public final float widthInBlocks; + public final float halfWidthInBlocks; + + public final int instanceOffsetX; + public final int instanceOffsetZ; + + + public float xOffset = 0; + public float zOffset = 0; + + public long lastFrameTime = System.currentTimeMillis(); + + + + // constructor // + + public CloudParams(float textureWidth, int instanceOffsetX, int instanceOffsetZ) + { + this.textureWidth = textureWidth; + this.widthInBlocks = (this.textureWidth * CLOUD_BOX_WIDTH); + this.halfWidthInBlocks = this.widthInBlocks / 2; + + this.instanceOffsetX = instanceOffsetX; + this.instanceOffsetZ = instanceOffsetZ; + } + + } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 54c4c40da..2ab9efdea 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -26,6 +26,7 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegist import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; @@ -79,8 +80,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private boolean init = false; private ShaderProgram shader; - private GLVertexBuffer vertexBuffer; - private GLElementBuffer solidIndexBuffer; + private GLVertexBuffer boxVertexBuffer; + private GLElementBuffer boxIndexBuffer; private AbstractVertexAttribute va; private boolean useInstancedRendering; @@ -100,6 +101,13 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private int skyLightUniform; private int blockLightUniform; + private int northShadingUniform; + private int southShadingUniform; + private int eastShadingUniform; + private int westShadingUniform; + private int topShadingUniform; + private int bottomShadingUniform; + private final ConcurrentHashMap boxGroupById = new ConcurrentHashMap<>(); @@ -108,37 +116,62 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister /** A box from 0,0,0 to 1,1,1 */ private static final float[] BOX_VERTICES = { // Pos x y z + + // min X, vertical face 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, + // max X, vertical face + 0, 1, 1, + 1, 1, 1, + 1, 0, 1, 0, 0, 1, + + // min Z, vertical face + 0, 0, 1, + 0, 0, 0, + 0, 1, 0, + 0, 1, 1, + // max Z, vertical face 1, 0, 1, 1, 1, 1, - 0, 1, 1, - }; - - private static final int[] SOLID_BOX_INDICES = { - // min Z, vertical face - 0, 3, 2, - 2, 1, 0, - // max Z, vertical face - 4, 5, 6, - 6, 7, 4, - - // min X, vertical face - 7, 3, 0, - 0, 4, 7, - // max X, vertical face - 2, 6, 5, - 5, 1, 2, + 1, 1, 0, + 1, 0, 0, // min Y, horizontal face - 1, 5, 4, - 4, 0, 1, + 0, 0, 1, + 1, 0, 1, + 1, 0, 0, + 0, 0, 0, // max Y, horizontal face - 3, 7, 6, - 6, 2, 3, + 0, 1, 1, + 1, 1, 1, + 1, 1, 0, + 0, 1, 0, + }; + + private static final int[] BOX_INDICES = { + // min X, vertical face + 2, 1, 0, + 0, 3, 2, + // max X, vertical face + 6, 5, 4, + 4, 7, 6, + + // min Z, vertical face + 10, 9, 8, + 8, 11, 10, + // max Z, vertical face + 14, 13, 12, + 12, 15, 14, + + // min Y, horizontal face + 18, 17, 16, + 16, 19, 18, + // max Y, horizontal face + 20, 21, 22, + 22, 23, 20, }; @@ -187,6 +220,14 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.lightMapUniform = this.shader.getUniformLocation("uLightMap"); this.skyLightUniform = this.shader.getUniformLocation("uSkyLight"); this.blockLightUniform = this.shader.getUniformLocation("uBlockLight"); + //this.shadingModeUniform = this.shader.getUniformLocation("uShadingMode"); + this.northShadingUniform = this.shader.getUniformLocation("uNorthShading"); + this.southShadingUniform = this.shader.getUniformLocation("uSouthShading"); + this.eastShadingUniform = this.shader.getUniformLocation("uEastShading"); + this.westShadingUniform = this.shader.getUniformLocation("uWestShading"); + this.topShadingUniform = this.shader.getUniformLocation("uTopShading"); + this.bottomShadingUniform = this.shader.getUniformLocation("uBottomShading"); + this.createBuffers(); @@ -202,19 +243,19 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister boxVerticesBuffer.order(ByteOrder.nativeOrder()); boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES); boxVerticesBuffer.rewind(); - this.vertexBuffer = new GLVertexBuffer(false); - this.vertexBuffer.bind(); - this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES); + this.boxVertexBuffer = new GLVertexBuffer(false); + this.boxVertexBuffer.bind(); + this.boxVertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES); // box vertex indexes - ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(SOLID_BOX_INDICES.length * Integer.BYTES); + ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(BOX_INDICES.length * Integer.BYTES); solidIndexBuffer.order(ByteOrder.nativeOrder()); - solidIndexBuffer.asIntBuffer().put(SOLID_BOX_INDICES); + solidIndexBuffer.asIntBuffer().put(BOX_INDICES); solidIndexBuffer.rewind(); - this.solidIndexBuffer = new GLElementBuffer(false); - this.solidIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, SOLID_BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); - this.solidIndexBuffer.bind(); + this.boxIndexBuffer = new GLElementBuffer(false); + this.boxIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + this.boxIndexBuffer.bind(); } private void addGenericDebugObjects() @@ -345,7 +386,12 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // rendering // //===========// - public void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler) + /** + * @param renderingWithSsao + * if true that means this render call is happening before the SSAO pass + * and any objects rendered in this pass will have SSAO applied to them. + */ + public void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler, boolean renderingWithSsao) { // render setup // profiler.push("setup"); @@ -362,9 +408,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.shader.bind(); this.va.bind(); - this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId()); + this.va.bindBufferToAllBindingPoints(this.boxVertexBuffer.getId()); - this.solidIndexBuffer.bind(); + this.boxIndexBuffer.bind(); Mat4f projectionMvmMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); projectionMvmMatrix.multiply(renderEventParam.dhModelViewMatrix); @@ -379,21 +425,27 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister Collection boxList = this.boxGroupById.values(); for (RenderableBoxGroup boxGroup : boxList) { - // ignore inactive groups - if (boxGroup != null && boxGroup.active) + // skip boxes that shouldn't render this pass + if (boxGroup.ssaoEnabled == renderingWithSsao) { profiler.popPush("render prep"); boxGroup.preRender(renderEventParam); - if (this.useInstancedRendering) + // ignore inactive groups + if (boxGroup.active) { - profiler.popPush("rendering"); - this.renderBoxGroupInstanced(boxGroup, camPos, projectionMvmMatrix); - } - else - { - profiler.popPush("rendering"); - this.renderBoxGroupDirect(boxGroup, projectionMvmMatrix, camPos); + if (this.useInstancedRendering) + { + profiler.popPush("rendering"); + this.renderBoxGroupInstanced(boxGroup, camPos, projectionMvmMatrix); + } + else + { + profiler.popPush("rendering"); + this.renderBoxGroupDirect(boxGroup, projectionMvmMatrix, camPos); + } + + boxGroup.postRender(renderEventParam); } } } @@ -442,6 +494,18 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); this.shader.setUniform(this.blockLightUniform, boxGroup.blockLight); + DhApiRenderableBoxGroupShading shading = boxGroup.shading; + if (shading == null) + { + shading = DhApiRenderableBoxGroupShading.getUnshaded(); + } + this.shader.setUniform(this.northShadingUniform, shading.north); + this.shader.setUniform(this.southShadingUniform, shading.south); + this.shader.setUniform(this.eastShadingUniform, shading.east); + this.shader.setUniform(this.westShadingUniform, shading.west); + this.shader.setUniform(this.topShadingUniform, shading.top); + this.shader.setUniform(this.bottomShadingUniform, shading.bottom); + @@ -466,7 +530,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // Draw instanced if (boxGroup.uploadedBoxCount > 0) { - GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxGroup.uploadedBoxCount); + GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxGroup.uploadedBoxCount); } @@ -512,7 +576,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (DhApiRenderableBox box : boxGroup) { - renderBox(boxGroup, box, transformMatrix, camPos); + this.renderBox(boxGroup, box, transformMatrix, camPos); } } private void renderBox( @@ -543,7 +607,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.shader.setUniform(this.directShaderColorUniform, box.color); - GL32.glDrawElements(GL32.GL_TRIANGLES, SOLID_BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); + GL32.glDrawElements(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java index f8f3fe60d..7fc2c74cf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java @@ -4,6 +4,7 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.math.Vec3f; @@ -37,14 +38,18 @@ public class RenderableBoxGroup private final Vec3f originBlockPos; + + public boolean active = true; + public boolean ssaoEnabled = true; + private boolean vertexDataDirty = true; + public int skyLight = 15; public int blockLight = 0; + public DhApiRenderableBoxGroupShading shading = DhApiRenderableBoxGroupShading.getDefaultShaded(); @Nullable public Consumer beforeRenderFunc; - - private boolean vertexDataDirty = true; - public boolean active = true; + public Consumer afterRenderFunc; // instance data public int instanceTranslationVbo = 0; @@ -120,6 +125,9 @@ public class RenderableBoxGroup @Override public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; } + @Override + public void setPostRenderFunc(Consumer func) { this.afterRenderFunc = func; } + @Override public void triggerBoxChange() { this.vertexDataDirty = true; } @@ -128,6 +136,11 @@ public class RenderableBoxGroup @Override public boolean isActive() { return this.active; } + @Override + public void setSsaoEnabled(boolean ssaoEnabled) { this.ssaoEnabled = ssaoEnabled; } + @Override + public boolean isSsaoEnabled() { return this.ssaoEnabled; } + public void preRender(DhApiRenderParam renderEventParam) { if (this.beforeRenderFunc != null) @@ -135,10 +148,24 @@ public class RenderableBoxGroup this.beforeRenderFunc.accept(renderEventParam); } } + public void postRender(DhApiRenderParam renderEventParam) + { + if (this.afterRenderFunc != null) + { + this.afterRenderFunc.accept(renderEventParam); + } + } + + @Override + public void setShading(DhApiRenderableBoxGroupShading shading) { this.shading = shading; } + @Override + public DhApiRenderableBoxGroupShading getShading() { return this.shading; } - // overrides // + //================// + // List Overrides // + //================// @Override public DhApiRenderableBox get(int index) { return this.boxList.get(index); } diff --git a/core/src/main/resources/assets/distanthorizons/textures/clouds.png b/core/src/main/resources/assets/distanthorizons/textures/clouds.png new file mode 100644 index 0000000000000000000000000000000000000000..825f4814e3fab7899db0e991087484a908873d5f GIT binary patch literal 6214 zcmV-M7`f+(P)Px#1ZP1_K>z@;j|==^1poj522e~?MF0Q*|NsA`*`M72000SaNLh0L01m?j~gZYoErBeyQB=cj_p-0I=rLVQ)}o zX;6sM?D;ZSxmyPL8$XLp<>oVCn8;hlxgU}{YnO7-aJ30Pm&!L>086(&v>*ZaTTf2i z1WW_;x2ojbp#vBqFaZ7H{i6U}4m=>X-|>M`YbH}SX^ zabDL|LB5VokLw92$f8Yu10&lKPTR-LAJj=I00NoF6#!)IU|mX`zAnTf0H&Kojqi^P zo~64l0jJ+={zqwg%;;kjr0 zVm@IVRo_rz8+n0MzzP6+b9E?iL@_)fLSMSVNQv-^{c7~E7)f;mr?C5KvQJiiX5RYE4Y~7NwGfkD z(=8-W%v*mU3Gw_}0B7Qe*RU(*{3vO09*%yfMrp#ojrS1~Y0S8UF4vLSodmr5JhwU3 zF*K1lbNlN@dkQ-`DsVU<(}KX5&sESk{~E573K^_MCAx9^AR~8`e%2WIMwt*Y`35&^ zqy`|(3#UynNOYkJRjxixl7=CqyJ^WMDyj~EluN{A9h^5u_^g=-L0iiY^2COhD7GX; zg^xdfQvy_7d+keHmsnnMa*hk z08L&@b&LxDH(Up>5OD8o+!|R?>TZ7ZII|Zq3iC&rrZ_CNU-$H@UnnI8%W(GL-D(&b z`^7osCJEP$=|r+#YNB7SL+Zn{z$NXjtTk7f>{pI#v8HZGE%L7cafSjfA!Pp0=Oaxm z_0~J-@UYgMv`9WzG7ayF^glC?)&ZyiKrm10bi<*G39oZvFxB_c3H1pLFKz` z+oh9&vW{PxNJm}fdBHbk5I;1>1NDL(fs{Oz#cBG()m|f?OlDFw4r)=x0l33b2Y(>Y zU_%B#$fqbPW#zLH7$(QlB!b21+fRonRsd=j!u`CF*eNH6&c%b~IwZSx+o*OaB1i&P zybiJjM71#=P4u!x6vXr=+PogxCYDHbvd50KU9L1SR+)fSd}?X@0bnJ7XdUvl(bHTe zor>a5_DJT0)m7R5XH1SljMhOg*NgH@QHNNn6lyC=xK#}zYY^*8HSWa(N>)w@X!E-M zA**Aem)lbp8Y@^AvYN3&oa3by<@Y&9iJ*_VJbKoWY)m0Y;vWa;!ZFCt&$1)KZXSRO zca4Z+XthwXkIOHEA8T0^z!aweSY0%8r7wvUu&(AnM0TrK>lQ{MxHNq3~1wP0KZG0G(Ir%h1M>Nyfv_PIJ|b5_eFwQtyTbSk_G!s04nwx z3zHEV(JW=5bUU(#YJ!mx+O+9zQL4K=);kOr+&%#mK0yd7h|)KYjBAHM=F2i2NZoKD zSJ(isZ{zh~z&`O?+QWGidfDVyiV)TXDS*XF)?706D(00O18i)u<4HJMdUf)Y_k9_)9QKcxVHV!ybkmz3gMQfI_ZouVwS6(1TR&KO3*5 zQMvyr0iGMQtks=$eDx;NNW02W+Ljj<is)bzMZqxsuudC`9hv(WF1+8(z0iaH}N9 zHZk_C2CRMetilPHSKwx8YXPv;#?c6K9iVkqbz}w)r0&LO5vuX0`e7}y-0Q|u0?-*m z_))>`SyAms*l!`q3IO>Q@N&4&FRDQRbe=9lb&f@kDpuTBx$S%~AbuHsO zcTF`w0kE54No`Lm8kaPufL<3+NNZV61hcWf+oqhXjT$27d28AsT#9Qg6x6-+?3OQ^ zkB5HpeiTO%7BhpKAU)noxTu-{rrZ?P{hd=M!OKLIyeuj5iJG!^7~e~7FLy#MZa}Lj z$34e^UBc|!{uPq*w%q=4x6)xVgHwB3c2OEaEhDk;WJ-FBn2G(-lAn3vv2GHAOqN{Js{+d8?CCPJa3PK&vm)pN@Q<9 zw{-O+LOb^!CtdoVsjNo;xF7vVxhzNMnCC6VpV(v5Aie<^7d;7#dTQM!S^?A@n)>G>osf?h6%p%3mpmU=)9~h-x6n?Xk5B~Ry|7gee2Fb$qbc%; zlb8>2d8J$3eja}mT+Z$}%WOIW7H|Sf(khkWJZ`senVvLByCntA2QL;E%_e?+tD2O` z$RTL|?uZ}){0qgkVw?ZB*5+8#uUOP3rLK`@$*ATv z(GQti8(JOO^6eNxcg~P)2c(C$AqG7o!JGl$%?Swta!+?Op#ac&yPfK3zGNYH!t`|w zbX8eG#JXb2s8kVMo{_(>kA&vlGWcyiB7sy$Wf2Hm09Xdd5l3!5a|rSRK%rW55#IHN z03h-vaqk}9D7Ca>XLtJOhhy-#KFgjdZ8(kgWSmt(a?3FiDN${KwRXb}GbD9lD#u8u z2i}_z#19#SN|LR4v|&8i@aBFP^0@_N4{BuRcQ5BtJIBCraP9oHDvLjgbvom_1R$Rd zGHIBQMc28fjHJ%fn9mp++yrz63qy?Np>gPkx*$Coht1KQ@FFumdWghJ*i1)`knon! zTEsTslzSBlQss4a5oC!V;>{oEG3Qhn}eSq$Xv7`jEGT8GV zXb|7%g#$hOoKYdv)tfPd#Q*Q7I`Uy1@Hy{AU!*i`2HwXa!re*Q8lpRI&sr^ z<3bEPG$N?c5ghXv4`ryia^OpV(HZQYIRBf!1WVG=93%;g5TfbL<az5f3v!Kgl7-%s9IgXB;hF&<6xS_vHcG7vyvRj_siUH@|rN z6Y@#7v7>qaG$qehNO_uzK=~zs@6yO~JK82iOkNDE)&cuxY@>?!DLq+g!`d@2sM;8j zyf~~i!Mj*S{-h?R$Qq}NKx%#0idMWBGjGpb-%^SV00sae)Wl8!*iM($9;XH9a5Eex zzx@q>7X|F$bPs&;^HGOK99i0Y0pR;wKM|C~4GLB10+da+Q=LW9s5sLf>q`qEa9{ms zY~w+B01e4 z*n4Fvk4ho&ZvFP&2mPWS;iHTlEhwZYz)R9A3uC*}uK?J1+>3o$>4q&+r`mxCsEP8Z zXYz))GY`oWk&s?!fj%V=*;3UxCrH%l?MTUh?$n3mz`_-Q_=22}v|R}C*H%x2a?K=* zD6D4H0-fJ&4Ls18yDw{r6i4A{0`S*9nK{!9K-HllNx2X0Nf~w0$)r>UwO2TyGjAH* z0l->u&ht=@yteR;OCK^R&L@p|J~VV>?+FZ7{7^@@7JG%2F4imOGO>PF$7i-E zYeTQD=p=bL@IqY%-+ZkIR(}1}PEC=Z`d15!u|iq_+GBsu)|~NkOQ};KQCtvf>fgI` z_-!{&;=on01HcPBYh!1yh+wiT*R^s1<(%sEbhzK$s>U~_$in=nA44}uc~R|W4Hi>6>CXa1B`FD@vq{D@gZaV25d0?YTR-T;$t;<+t&vk- zE!i4J^`Csma-Y0}te4?KWfI4)YMF9AGz{EdT@vr4xDaZId0Z3}m$$I=7Er82r_UdA z+6>SMMV5f#%ABwUL*vLMRBNitrhf_tYL}GKHB!pl1kj5;T;||==(C)Dy2C2~WorGE z8jn?&+hW-T>|QLq0)rL%=Q$2*pu_gC?}g{(=>-I8t3J~K+lQ2I>Z#MwY7eqfW<-w$ zg4i4fC;dIFuS&`O@~y);34oOJRN|>aG57&ln`mNT&2THzAyZsCJ+T4c@Mm3(^h@bB zzgvU*`0GcK7t$NJze6W==6skJ1nwj>C&kNq^Hu=*lg~Sqcn2WeYRi{5%y__p&$+Jw zkUehHSBVsGN;Vi&eUhG?YngMu)LdVO7w*vCA(R>%6>);i%k?u0*>#HW2mt$IRnb5L zqVk=S+KfVke#i?fQwRK@0jB+;YwbUJw5m@i7DL{=Xrmz0e#8`Y)un#uYe+i@On#@3u7b(^VJkOQi|r3Euv#R zeIvrnu^O*&h%-@|ML|sG6?LbPVs~T!cGV4@=bdpxL{(wzjd0c?;#nI6+vEv)wQ0Kn zKxpr?%y|Xays$a5`WJeS+P7p_ClR{53P@AHye%Bl@zo?6FS`P`J~0pzHkQHIDnGd! zdm$B4pOn@lwX3Nnxc&<9pq7sheWS7*Im(X-WH*n8HRx>ihYn+nc1tFw9Ctqt0O-fkHuGM_*9p|ON|%hYzAxy;6FatpF2qa$kWX_ z6xof`iasz-2%ei?0q}fr6rl3ncmsN=V)}PWl+!-Bcy@dneS;|{eS{drvv+Nj7pCuL z&?Fe&C4d_MSzWEFXyB}QN9kj8^*IH@*Jl}&_Ch7$Y>&$%iWY-4LbqyX%=-FIByh^8 zY9C5QG)-wOc(*640McLAeJ|Fc#d1Y;Qdt>6OK9$UW9_443HN>doI6SDoc5tqy?gd^ zl7D`$UTXI@0#v%{-D_abIE>uOEV}i_J@JH~o+)?{t#z6}*d7$&L{%jYX8>rZX-h0c zj|)_eGZC=FJAEFDA{vJ3%ByXVOOeJ>Y&oG=$0n)S4FL8pFl+!AO=6s6BDF%R)ybim zl4Yum&kr^L$A({ywOG~C9T7t4BWC+I0I}A*^(Ko$nc(u0)WwIjvV{8Yt7*1n_tHA8 zmrp-7+Vo_`4A6wZ^enfq6PJ)*F7a-7YBYHS%t_OlpRweK@?hBd0&?W964+K;)Vy_> zuO3`yhaM`g$=N}7(#zoDIAXIbo3`||`auHMaJn!CPcf5sxljN}B;^|AD_8mD%{HR^ z#+<|*HS8t7M|>;b>OWJ1P1dybrWHQYf@}I)ByAJO=t;>9a156p83}G?0T*>$@^XpZ)+Z z{cKv+^#=gBapew*36{rR050JIK5Hw7kZd%xV@Y6SV; zVbgLWtO_KWEt8;~RhXq+oM0t%AdD0IsYM(uYqx1z8ZPhN;yjP#at{w0;P5TG$&5(z z#4}R41M5$Ge;_BiBnLpRO~oG`JCv5prF=jL7XIzM*k z?;qiyz7h)nLtp{ETPtbtS9Ed}eC&sHPNM&YGTT7C?+ie1;I{CceK%DuQ&}$DmVTEW z@_bD-cLsZ7wAyWp`4TsZpXYxL0Mgof3Mao_mRR*+HKhwEIpQigT{<6O zwL^6@BdthMA${8FB=l@tach~r7;I4i$p0bE9(W{a-Nx`>yCxDrC?AF!YcE1=ydCwK zPfcLiic>|AE&#C9$Y1Aj7 z&SNT@knU4!X2h=*Pb)LU= 0 && gl_VertexID < 4) { fColor.rgb *= uNorthShading; } + else if (gl_VertexID >= 4 && gl_VertexID < 8) { fColor.rgb *= uSouthShading; } + else if (gl_VertexID >= 8 && gl_VertexID < 12) { fColor.rgb *= uWestShading; } + else if (gl_VertexID >= 12 && gl_VertexID < 16) { fColor.rgb *= uEastShading; } + else if (gl_VertexID >= 16 && gl_VertexID < 20) { fColor.rgb *= uBottomShading; } + else if (gl_VertexID >= 20 && gl_VertexID < 24) { fColor.rgb *= uTopShading; } + +} From c73c3f849018a3bc2af25edd2efb33adb122e94f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 18:11:18 -0500 Subject: [PATCH 041/104] Add missing generic rendering config options --- .../distanthorizons/core/config/Config.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index dc9581d20..ed1733ff5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -137,6 +137,7 @@ public class Config public static ConfigCategory ssao = new ConfigCategory.Builder().set(Ssao.class).build(); public static ConfigCategory noiseTextureSettings = new ConfigCategory.Builder().set(NoiseTextureSettings.class).build(); public static ConfigCategory advancedGraphics = new ConfigCategory.Builder().set(AdvancedGraphics.class).build(); + public static ConfigCategory genericRendering = new ConfigCategory.Builder().set(GenericRendering.class).build(); public static class Quality @@ -660,6 +661,31 @@ public class Config } + public static class GenericRendering + { + public static ConfigEntry enableRendering = new ConfigEntry.Builder() + .set(true) + .comment("" + + "\n" + + "") + .build(); + + public static ConfigEntry enableBeaconRendering = new ConfigEntry.Builder() + .set(true) + .comment("" + + "\n" + + "") + .build(); + + public static ConfigEntry enableCloudRendering = new ConfigEntry.Builder() + .set(true) + .comment("" + + "\n" + + "") + .build(); + + } + } public static class WorldGenerator From bacdfa96e35319203050b4df3645ddf171f3146f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 18:16:00 -0500 Subject: [PATCH 042/104] rename ILevelWrapper.getHeight -> getMaxHeight --- .../api/interfaces/world/IDhApiLevelWrapper.java | 2 +- .../core/api/external/methods/data/DhApiTerrainDataRepo.java | 2 +- .../distanthorizons/core/render/RenderBufferHandler.java | 2 +- .../core/render/renderer/generic/CloudRenderHandler.java | 2 +- .../core/render/renderer/shaders/FogShader.java | 2 +- .../java/com/seibel/distanthorizons/core/util/RenderUtil.java | 2 +- .../core/wrapperInterfaces/world/ILevelWrapper.java | 3 +-- .../worldGeneratorInjection/objects/LevelWrapperTest.java | 2 +- 8 files changed, 8 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java index 30d9e161c..ee28ad06a 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java @@ -42,7 +42,7 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper boolean hasSkyLight(); /** Returns the max block height of the level(?) */ - int getHeight(); + int getMaxHeight(); /** * Returns the lowest possible block position for the level.
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java index 5380546b7..c04d786ab 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java @@ -322,7 +322,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo rayDirection.normalize(); int minBlockHeight = levelWrapper.getMinHeight(); - int maxBlockHeight = levelWrapper.getHeight(); + int maxBlockHeight = levelWrapper.getMaxHeight(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index 8a952bb93..d02a238fb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -244,7 +244,7 @@ public class RenderBufferHandler implements AutoCloseable if (enableFrustumCulling) { int worldMinY = clientLevelWrapper.getMinHeight(); - int worldHeight = clientLevelWrapper.getHeight(); + int worldHeight = clientLevelWrapper.getMaxHeight(); Vec3d cameraPos = MC_RENDER.getCameraExactPosition(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index 3557bf5cf..dc22ae4c2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -217,7 +217,7 @@ public class CloudRenderHandler boxGroup.setOriginBlockPos( new DhApiVec3f( clouds.xOffset + (clouds.instanceOffsetX * clouds.widthInBlocks) + xOffset + clouds.halfWidthInBlocks, - this.level.getLevelWrapper().getHeight() + 200, + this.level.getLevelWrapper().getMaxHeight() + 200, clouds.zOffset + (clouds.instanceOffsetZ * clouds.widthInBlocks) + zOffset + clouds.halfWidthInBlocks ) ); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java index 73bfb846e..98e0b0b1b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java @@ -116,7 +116,7 @@ public class FogShader extends AbstractShaderRenderer if (this.nearFogStartUniform != -1) this.shader.setUniform(this.nearFogStartUniform, nearFogStart); if (this.nearFogLengthUniform != -1) this.shader.setUniform(this.nearFogLengthUniform, nearFogLen); if (this.fogScaleUniform != -1) this.shader.setUniform(this.fogScaleUniform, 1.f / lodDrawDistance); - if (this.fogVerticalScaleUniform != -1) this.shader.setUniform(this.fogVerticalScaleUniform, 1.f / MC.getWrappedClientLevel().getHeight()); + if (this.fogVerticalScaleUniform != -1) this.shader.setUniform(this.fogVerticalScaleUniform, 1.f / MC.getWrappedClientLevel().getMaxHeight()); } private Color getFogColor(float partialTicks) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java index e49c2028a..b4967d0e5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java @@ -244,7 +244,7 @@ public class RenderUtil // if the player is a significant distance above the work, increase the // near clip plane to fix Z imprecision issues int playerHeight = MC.getPlayerBlockPos().y; - int levelMaxHeight = level.getHeight(); + int levelMaxHeight = level.getMaxHeight(); if (playerHeight > levelMaxHeight + 1_000) { return playerHeight - (levelMaxHeight + 1000); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java index ac52dd9b2..25d8858fb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java @@ -47,8 +47,7 @@ public interface ILevelWrapper extends IDhApiLevelWrapper, IBindable boolean hasSkyLight(); @Override - int getHeight(); - + int getMaxHeight(); @Override default int getMinHeight() { return 0; } diff --git a/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java b/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java index b297fa03a..2d652cbce 100644 --- a/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java +++ b/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java @@ -48,7 +48,7 @@ public class LevelWrapperTest implements IDhApiLevelWrapper public boolean hasSkyLight() { return false; } @Override - public int getHeight() { return 0; } + public int getMaxHeight() { return 0; } @Override public int getMinHeight() { return IDhApiLevelWrapper.super.getMinHeight(); } From 578a9f9309bf106b555813180ef5fc5866b4a80e Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 18:31:43 -0500 Subject: [PATCH 043/104] add directional shading to direct generic rendering --- .../generic/GenericObjectRenderer.java | 13 +++++++++ .../shaders/genericObject/direct/frag.frag | 11 ++----- .../shaders/genericObject/direct/vert.vert | 29 +++++++++++++++++++ .../shaders/genericObject/instanced/vert.vert | 1 - 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 2ab9efdea..b8ef144c1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -574,6 +574,19 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); this.shader.setUniform(this.blockLightUniform, boxGroup.blockLight); + DhApiRenderableBoxGroupShading shading = boxGroup.shading; + if (shading == null) + { + shading = DhApiRenderableBoxGroupShading.getUnshaded(); + } + this.shader.setUniform(this.northShadingUniform, shading.north); + this.shader.setUniform(this.southShadingUniform, shading.south); + this.shader.setUniform(this.eastShadingUniform, shading.east); + this.shader.setUniform(this.westShadingUniform, shading.west); + this.shader.setUniform(this.topShadingUniform, shading.top); + this.shader.setUniform(this.bottomShadingUniform, shading.bottom); + + for (DhApiRenderableBox box : boxGroup) { this.renderBox(boxGroup, box, transformMatrix, camPos); diff --git a/core/src/main/resources/shaders/genericObject/direct/frag.frag b/core/src/main/resources/shaders/genericObject/direct/frag.frag index 31bd493b0..c3d2ac8c4 100644 --- a/core/src/main/resources/shaders/genericObject/direct/frag.frag +++ b/core/src/main/resources/shaders/genericObject/direct/frag.frag @@ -1,17 +1,10 @@ #version 150 core -uniform vec4 uColor; -uniform int uSkyLight; -uniform int uBlockLight; -uniform sampler2D uLightMap; +in vec4 fColor; out vec4 fragColor; void main() { - float blockLight = (float(uBlockLight)+0.5) / 16.0; - float skyLight = (float(uSkyLight)+0.5) / 16.0; - vec4 lightColor = vec4(texture(uLightMap, vec2(blockLight, skyLight)).xyz, 1.0); - - fragColor = lightColor * uColor; + fragColor = fColor; } \ No newline at end of file diff --git a/core/src/main/resources/shaders/genericObject/direct/vert.vert b/core/src/main/resources/shaders/genericObject/direct/vert.vert index befc43200..ec528ae44 100644 --- a/core/src/main/resources/shaders/genericObject/direct/vert.vert +++ b/core/src/main/resources/shaders/genericObject/direct/vert.vert @@ -1,10 +1,39 @@ #version 150 core uniform mat4 uTransform; +uniform vec4 uColor; +uniform int uSkyLight; +uniform int uBlockLight; +uniform sampler2D uLightMap; +uniform float uNorthShading; +uniform float uSouthShading; +uniform float uEastShading; +uniform float uWestShading; +uniform float uTopShading; +uniform float uBottomShading; in vec3 vPosition; +out vec4 fColor; + void main() { gl_Position = uTransform * vec4(vPosition, 1.0); + + + float blockLight = (float(uBlockLight)+0.5) / 16.0; + float skyLight = (float(uSkyLight)+0.5) / 16.0; + vec4 lightColor = vec4(texture(uLightMap, vec2(blockLight, skyLight)).xyz, 1.0); + + + fColor = lightColor * uColor; + + // apply directional shading + if (gl_VertexID >= 0 && gl_VertexID < 4) { fColor.rgb *= uNorthShading; } + else if (gl_VertexID >= 4 && gl_VertexID < 8) { fColor.rgb *= uSouthShading; } + else if (gl_VertexID >= 8 && gl_VertexID < 12) { fColor.rgb *= uWestShading; } + else if (gl_VertexID >= 12 && gl_VertexID < 16) { fColor.rgb *= uEastShading; } + else if (gl_VertexID >= 16 && gl_VertexID < 20) { fColor.rgb *= uBottomShading; } + else if (gl_VertexID >= 20 && gl_VertexID < 24) { fColor.rgb *= uTopShading; } + } \ No newline at end of file diff --git a/core/src/main/resources/shaders/genericObject/instanced/vert.vert b/core/src/main/resources/shaders/genericObject/instanced/vert.vert index 919da6331..eee0d4142 100644 --- a/core/src/main/resources/shaders/genericObject/instanced/vert.vert +++ b/core/src/main/resources/shaders/genericObject/instanced/vert.vert @@ -10,7 +10,6 @@ uniform mat4 uProjectionMvm; uniform int uSkyLight; uniform int uBlockLight; uniform sampler2D uLightMap; - uniform float uNorthShading; uniform float uSouthShading; uniform float uEastShading; From 23d07aa92d2d5057b8a8a770db7b7165363648f7 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 18:42:11 -0500 Subject: [PATCH 044/104] Disable cloud rendering if instanced rendering isn't available --- .../renderer/generic/CloudRenderHandler.java | 38 +++++++++++++++---- .../generic/GenericObjectRenderer.java | 7 ++++ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index dc22ae4c2..4933e46c7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -58,7 +58,7 @@ public class CloudRenderHandler /** measured in blocks */ private static final int CLOUD_BOX_THICKNESS = 32; - private final IDhApiRenderableBoxGroup[][] boxGroupByOffset; + private final IDhApiRenderableBoxGroup[][] boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3]; private final IDhLevel level; private float moveSpeedInBlocksPerSecond = 3.0f; @@ -73,6 +73,17 @@ public class CloudRenderHandler { this.level = level; + if (!renderer.getUseInstancedRendering()) + { + LOGGER.warn("Instanced rendering unavailable, cloud rendering disabled."); + } + + + + + //=======================// + // get the cloud texture // + //=======================// // default to a single empty slot in case the texture is broken boolean[][] cloudLocations = new boolean[1][1]; @@ -97,6 +108,10 @@ public class CloudRenderHandler + //===================// + // parse the texture // + //===================// + int textureWidth = cloudLocations.length; ArrayList boxList = new ArrayList<>(512); for (int x = 0; x < textureWidth; x ++) @@ -131,6 +146,11 @@ public class CloudRenderHandler } + + //========================// + // create the renderables // + //========================// + // slightly lighter shading than the default DhApiRenderableBoxGroupShading cloudShading = DhApiRenderableBoxGroupShading.getUnshaded(); cloudShading.north = cloudShading.south = 0.9f; @@ -138,7 +158,7 @@ public class CloudRenderHandler cloudShading.top = 1.0f; cloudShading.bottom = 0.7f; - this.boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3]; + // 3x3 area so we clouds should always be overhead for (int x = -1; x <= 1; x++) { for (int z = -1; z <= 1; z++) @@ -151,16 +171,20 @@ public class CloudRenderHandler boxGroup.setSsaoEnabled(false); boxGroup.setShading(cloudShading); - CloudParams offset = new CloudParams(textureWidth, x, z); - boxGroup.setPreRenderFunc((renderParam) -> this.preRender(offset)); + CloudParams params = new CloudParams(textureWidth, x, z); + boxGroup.setPreRenderFunc((renderParam) -> this.preRender(params)); - renderer.add(boxGroup); + // we only stop before adding to the renderer to prevent accidental issues with null pointers and such + if (renderer.getUseInstancedRendering()) + { + renderer.add(boxGroup); + } this.boxGroupByOffset[x+1][z+1] = boxGroup; } } } - public void preRender(CloudParams clouds) + private void preRender(CloudParams clouds) { IDhApiRenderableBoxGroup boxGroup = this.boxGroupByOffset[clouds.instanceOffsetX+1][clouds.instanceOffsetZ+1]; @@ -229,7 +253,7 @@ public class CloudRenderHandler // texture handling // //==================// - public static boolean[][] getCloudsFromTexture() throws FileNotFoundException, IOException + private static boolean[][] getCloudsFromTexture() throws FileNotFoundException, IOException { final ClassLoader loader = Thread.currentThread().getContextClassLoader(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index b8ef144c1..090329588 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -625,6 +625,13 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister + //=========// + // getters // + //=========// + + public boolean getUseInstancedRendering() { return this.useInstancedRendering; } + + //=========// // F3 menu // From 22167081f00d40369f23fc064e7ecf0e5726e189 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 19:16:33 -0500 Subject: [PATCH 045/104] Fix generic render un-binding when moving between levels --- .../core/level/AbstractDhLevel.java | 21 ++++++++++--------- .../core/level/ClientLevelModule.java | 21 +++++++++++++------ .../core/level/DhClientLevel.java | 6 +----- .../core/level/DhClientServerLevel.java | 6 +----- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 899ef4ce6..765494f27 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -75,6 +75,8 @@ public abstract class AbstractDhLevel implements IDhLevel protected boolean beaconGroupBound = false; + /** Will be null if clouds shouldn't be rendered for this level. */ + @Nullable protected CloudRenderHandler cloudRenderHandler; @@ -203,7 +205,9 @@ public abstract class AbstractDhLevel implements IDhLevel - // beacon beam // + //=================// + // beacon handling // + //=================// @Override public List getAllBeamsForSectionPos(long pos) @@ -230,14 +234,6 @@ public abstract class AbstractDhLevel implements IDhLevel if (this.beaconBeamRepo != null && genericObjectRenderer != null) { - if (!this.beaconGroupBound) - { - this.beaconGroupBound = true; - genericObjectRenderer.add(this.beaconBoxGroup); - this.cloudRenderHandler = new CloudRenderHandler(this, genericObjectRenderer); - } - - HashSet allPosSet = new HashSet<>(); // sort new beams @@ -327,7 +323,12 @@ public abstract class AbstractDhLevel implements IDhLevel { this.beaconGroupBound = true; genericObjectRenderer.add(this.beaconBoxGroup); - this.cloudRenderHandler = new CloudRenderHandler(this, genericObjectRenderer); + + if (!this.getLevelWrapper().hasCeiling() + && !this.getLevelWrapper().getDimensionType().isTheEnd()) + { + this.cloudRenderHandler = new CloudRenderHandler(this, genericObjectRenderer); + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java index d56cdd07f..99dd8fcf7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ClientLevelModule.java @@ -53,6 +53,14 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I @WillNotClose public final FullDataSourceProviderV2 fullDataSourceProvider; public final AtomicReference ClientRenderStateRef = new AtomicReference<>(); + /** + * This is handled outside of the {@link ClientRenderState} to prevent destroying + * the {@link GenericObjectRenderer} when changing render distances or enabling/disabling rendering.

+ * + * Destroying the {@link GenericObjectRenderer} would cause any existing bindings to be + * erroneously removed. + */ + public final GenericObjectRenderer genericRenderer = new GenericObjectRenderer(); @@ -105,7 +113,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I } clientRenderState.close(); - clientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider()); + clientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider(), this.genericRenderer); if (!this.ClientRenderStateRef.compareAndSet(null, clientRenderState)) { //FIXME: How to handle this? @@ -138,7 +146,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I public boolean startRenderer(IClientLevelWrapper clientLevelWrapper) { // TODO why are we passing in a level wrapper? Our client level is already defined. - ClientRenderState ClientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider()); + ClientRenderState ClientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider(), this.genericRenderer); if (!this.ClientRenderStateRef.compareAndSet(null, ClientRenderState)) { LOGGER.warn("Failed to start renderer due to concurrency"); @@ -280,7 +288,6 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I public final LodQuadTree quadtree; public final RenderBufferHandler renderBufferHandler; public final LodRenderer lodRenderer; - public final GenericObjectRenderer genericRenderer; @@ -288,7 +295,10 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I // constructor // //=============// - public ClientRenderState(IDhClientLevel dhClientLevel, IClientLevelWrapper clientLevelWrapper, FullDataSourceProviderV2 fullDataSourceProvider) + public ClientRenderState( + IDhClientLevel dhClientLevel, IClientLevelWrapper clientLevelWrapper, + FullDataSourceProviderV2 fullDataSourceProvider, + GenericObjectRenderer genericRenderer) { this.clientLevelWrapper = clientLevelWrapper; @@ -297,9 +307,8 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I 0, 0, fullDataSourceProvider); - this.genericRenderer = new GenericObjectRenderer(); this.renderBufferHandler = new RenderBufferHandler(this.quadtree); - this.lodRenderer = new LodRenderer(this.renderBufferHandler, this.genericRenderer); + this.lodRenderer = new LodRenderer(this.renderBufferHandler, genericRenderer); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index 842bf1fe8..15a67565d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -175,11 +175,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel @Override - public GenericObjectRenderer getGenericRenderer() - { - ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); - return (renderState != null) ? renderState.genericRenderer : null; - } + public GenericObjectRenderer getGenericRenderer() { return this.clientside.genericRenderer; } @Override public RenderBufferHandler getRenderBufferHandler() { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index 07fd566d4..f97d4019f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -228,11 +228,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev @Override - public GenericObjectRenderer getGenericRenderer() - { - ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get(); - return (renderState != null) ? renderState.genericRenderer : null; - } + public GenericObjectRenderer getGenericRenderer() { return this.clientside.genericRenderer; } @Override public RenderBufferHandler getRenderBufferHandler() { From 8eb70cbaed43ff290176dd07a32be02d21f206d4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 19:18:40 -0500 Subject: [PATCH 046/104] fix unloading chunks removing beacon beams --- .../com/seibel/distanthorizons/core/level/AbstractDhLevel.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 765494f27..016569dba 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -367,8 +367,7 @@ public abstract class AbstractDhLevel implements IDhLevel { BeaconBeamDTO beam = existingBeamList.get(i); - // beam no longer exists at position, remove - this.beaconBeamRepo.deleteWithKey(beam.pos); // TODO broken when updating adjacent chunks + // beam no longer needs to be rendered, remove it from the renderer if (this.beaconPosSet.remove(beam.pos)) { this.beaconBoxGroup.removeIf((box) -> From 3c173685ead0d003db5b4e498c127a8dc3a768a4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 19:45:27 -0500 Subject: [PATCH 047/104] Fix beacons disappearing when unloading LODs --- .../core/level/AbstractDhLevel.java | 95 ++++++++++--------- 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 016569dba..71e2af40b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -52,6 +52,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; public abstract class AbstractDhLevel implements IDhLevel { @@ -71,7 +72,7 @@ public abstract class AbstractDhLevel implements IDhLevel protected final ConcurrentHashMap> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>(); protected final IDhApiRenderableBoxGroup beaconBoxGroup; - protected final HashSet beaconPosSet = new HashSet<>(); + protected final HashMap beaconRefCountByBlockPos = new HashMap<>(); protected boolean beaconGroupBound = false; @@ -226,6 +227,7 @@ public abstract class AbstractDhLevel implements IDhLevel @Override public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List newBeamList) { + // synchronized to prevent two threads from updating the same chunk at the same time synchronized (this) { GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); @@ -276,32 +278,13 @@ public abstract class AbstractDhLevel implements IDhLevel { // new beam found, add to DB this.beaconBeamRepo.save(newBeam); - - DhApiRenderableBox beaconBox = new DhApiRenderableBox( - new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), - new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), - newBeam.color - ); - - if (this.beaconPosSet.add(beaconPos)) - { - this.beaconBoxGroup.add(beaconBox); - this.beaconBoxGroup.triggerBoxChange(); - } + this.startRenderingBeacon(newBeam); } else if (existingBeam != null && newBeam == null) { // beam no longer exists at position, remove this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks - if (this.beaconPosSet.remove(existingBeam.pos)) - { - this.beaconBoxGroup.removeIf((box) -> - box.minPos.x == beaconPos.x - && box.minPos.y == beaconPos.y+1 // plus 1 because the beam starts above the beacon - && box.minPos.z == beaconPos.z - ); - this.beaconBoxGroup.triggerBoxChange(); - } + this.stopRenderingBeaconAtPos(beaconPos); } } @@ -319,6 +302,7 @@ public abstract class AbstractDhLevel implements IDhLevel if (this.beaconBeamRepo != null && genericObjectRenderer != null) { + // generic setup is delayed to allow for the main renderer to start up if (!this.beaconGroupBound) { this.beaconGroupBound = true; @@ -337,17 +321,7 @@ public abstract class AbstractDhLevel implements IDhLevel for (int i = 0; i < existingBeamList.size(); i++) { BeaconBeamDTO newBeam = existingBeamList.get(i); - - DhApiRenderableBox beaconBox = new DhApiRenderableBox( - new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z), - new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1), - newBeam.color - ); - if (this.beaconPosSet.add(newBeam.pos)) - { - this.beaconBoxGroup.add(beaconBox); - this.beaconBoxGroup.triggerBoxChange(); - } + this.startRenderingBeacon(newBeam); } } } @@ -366,21 +340,54 @@ public abstract class AbstractDhLevel implements IDhLevel for (int i = 0; i < existingBeamList.size(); i++) { BeaconBeamDTO beam = existingBeamList.get(i); - - // beam no longer needs to be rendered, remove it from the renderer - if (this.beaconPosSet.remove(beam.pos)) - { - this.beaconBoxGroup.removeIf((box) -> - box.minPos.x == beam.pos.x - && box.minPos.y == beam.pos.y+1 // plus 1 because the beam starts above the beacon - && box.minPos.z == beam.pos.z - ); - this.beaconBoxGroup.triggerBoxChange(); - } + this.stopRenderingBeaconAtPos(beam.pos); } } } + private void startRenderingBeacon(BeaconBeamDTO beacon) + { + this.beaconRefCountByBlockPos.compute(beacon.pos, (beamPos, beaconRefCount) -> + { + if (beaconRefCount == null) { beaconRefCount = new AtomicInteger(); } + if (beaconRefCount.getAndIncrement() == 0) + { + DhApiRenderableBox beaconBox = new DhApiRenderableBox( + new DhApiVec3f(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), + new DhApiVec3f(beacon.pos.x+1, 6_000, beacon.pos.z+1), + // TODO calculate color + beacon.color + ); + + this.beaconBoxGroup.add(beaconBox); + this.beaconBoxGroup.triggerBoxChange(); + } + return beaconRefCount; + }); + } + + private void stopRenderingBeaconAtPos(DhBlockPos beaconPos) + { + this.beaconRefCountByBlockPos.compute(beaconPos, (pos, beaconRefCount) -> + { + if (beaconRefCount == null) { beaconRefCount = new AtomicInteger(); } + if (beaconRefCount.decrementAndGet() == 0) + { + this.beaconBoxGroup.removeIf((box) -> + box.minPos.x == beaconPos.x + && box.minPos.y == beaconPos.y+1 // plus 1 because the beam starts above the beacon + && box.minPos.z == beaconPos.z + ); + this.beaconBoxGroup.triggerBoxChange(); + return null; + } + else + { + return beaconRefCount; + } + }); + } + //================// From 9e13b2719718b5946072fc5117a46a628705a987 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 7 Jul 2024 19:54:17 -0500 Subject: [PATCH 048/104] Fix double unloading beacons --- .../seibel/distanthorizons/core/level/AbstractDhLevel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 71e2af40b..5dfccea8c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -370,8 +370,8 @@ public abstract class AbstractDhLevel implements IDhLevel { this.beaconRefCountByBlockPos.compute(beaconPos, (pos, beaconRefCount) -> { - if (beaconRefCount == null) { beaconRefCount = new AtomicInteger(); } - if (beaconRefCount.decrementAndGet() == 0) + if (beaconRefCount != null + && beaconRefCount.decrementAndGet() <= 0) { this.beaconBoxGroup.removeIf((box) -> box.minPos.x == beaconPos.x From c45f9f442ff86b1c541e124a0e0d6d1d6ee2f7c2 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 8 Jul 2024 07:32:29 -0500 Subject: [PATCH 049/104] Clean up beacon render handling logic --- .../core/level/AbstractDhLevel.java | 208 +++------------- .../core/level/DhClientLevel.java | 1 + .../core/level/DhClientServerLevel.java | 1 + .../core/level/DhServerLevel.java | 1 + .../distanthorizons/core/level/IDhLevel.java | 1 - .../renderer/generic/BeaconRenderHandler.java | 228 ++++++++++++++++++ .../renderer/generic/CloudRenderHandler.java | 24 +- .../generic/GenericObjectRenderer.java | 11 +- 8 files changed, 288 insertions(+), 187 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 5dfccea8c..0d2a02812 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -32,6 +32,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; +import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler; import com.seibel.distanthorizons.core.render.renderer.generic.CloudRenderHandler; import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory; @@ -71,14 +72,10 @@ public abstract class AbstractDhLevel implements IDhLevel /** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */ protected final ConcurrentHashMap> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>(); - protected final IDhApiRenderableBoxGroup beaconBoxGroup; - protected final HashMap beaconRefCountByBlockPos = new HashMap<>(); - - protected boolean beaconGroupBound = false; - /** Will be null if clouds shouldn't be rendered for this level. */ @Nullable protected CloudRenderHandler cloudRenderHandler; + protected BeaconRenderHandler beaconRenderHandler; @@ -89,14 +86,12 @@ public abstract class AbstractDhLevel implements IDhLevel protected AbstractDhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); - - this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(new ArrayList<>(0)); - this.beaconBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); - this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); - this.beaconBoxGroup.setShading(DhApiRenderableBoxGroupShading.getUnshaded()); - this.beaconBoxGroup.setPreRenderFunc((renderEventParam) -> this.beaconBoxGroup.setActive(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering.get())); } + /** + * Creating the repos requires access to the level file, which isn't + * available at constructor time. + */ protected void createAndSetSupportingRepos(File databaseFile) { // chunk hash @@ -125,6 +120,28 @@ public abstract class AbstractDhLevel implements IDhLevel this.beaconBeamRepo = newBeaconBeamRepo; } + /** handles any setup that needs the repos to be created */ + protected void runRepoReliantSetup() + { + GenericObjectRenderer genericRenderer = this.getGenericRenderer(); + if (genericRenderer != null) + { + // only add clouds for certain dimension types + if (!this.getLevelWrapper().hasCeiling() + && !this.getLevelWrapper().getDimensionType().isTheEnd()) + { + this.cloudRenderHandler = new CloudRenderHandler(this, genericRenderer); + } + + + // shouldn't happen, but just in case + if (this.beaconBeamRepo != null) + { + this.beaconRenderHandler = new BeaconRenderHandler(this.beaconBeamRepo, genericRenderer); + } + } + } + //=================// @@ -210,184 +227,32 @@ public abstract class AbstractDhLevel implements IDhLevel // beacon handling // //=================// - @Override - public List getAllBeamsForSectionPos(long pos) - { - if (this.beaconBeamRepo != null) - { - return this.beaconBeamRepo.getAllBeamsForPos(pos); - } - else - { - return new ArrayList<>(0); - } - } - - @Override public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List newBeamList) { - // synchronized to prevent two threads from updating the same chunk at the same time - synchronized (this) + if (this.beaconRenderHandler != null) { - GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); - - // should always be non-null, but just in case - if (this.beaconBeamRepo != null - && genericObjectRenderer != null) - { - HashSet allPosSet = new HashSet<>(); - - // sort new beams - HashMap newBeamByPos = new HashMap<>(newBeamList.size()); - for (int i = 0; i < newBeamList.size(); i++) - { - BeaconBeamDTO beam = newBeamList.get(i); - newBeamByPos.put(beam.pos, beam); - allPosSet.add(beam.pos); - } - - // get existing beams - List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos); - HashMap existingBeamByPos = new HashMap<>(existingBeamList.size()); - for (int i = 0; i < existingBeamList.size(); i++) - { - BeaconBeamDTO beam = existingBeamList.get(i); - existingBeamByPos.put(beam.pos, beam); - allPosSet.add(beam.pos); - } - - - - for (DhBlockPos beaconPos : allPosSet) - { - if (!chunkPos.contains(beaconPos)) - { - // don't update beacons outside the updated chunk - continue; - } - - BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos); - BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos); - - if (existingBeam != null && newBeam != null) - { - // beam still exists in chunk, do nothing - } - else if (existingBeam == null && newBeam != null) - { - // new beam found, add to DB - this.beaconBeamRepo.save(newBeam); - this.startRenderingBeacon(newBeam); - } - else if (existingBeam != null && newBeam == null) - { - // beam no longer exists at position, remove - this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks - this.stopRenderingBeaconAtPos(beaconPos); - } - - } - - } + this.beaconRenderHandler.setBeaconBeamsForChunk(chunkPos, newBeamList); } } @Override public void loadBeaconBeamsInPos(long pos) { - GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); - - // should always be non-null, but just in case - if (this.beaconBeamRepo != null - && genericObjectRenderer != null) + if (this.beaconRenderHandler != null) { - // generic setup is delayed to allow for the main renderer to start up - if (!this.beaconGroupBound) - { - this.beaconGroupBound = true; - genericObjectRenderer.add(this.beaconBoxGroup); - - if (!this.getLevelWrapper().hasCeiling() - && !this.getLevelWrapper().getDimensionType().isTheEnd()) - { - this.cloudRenderHandler = new CloudRenderHandler(this, genericObjectRenderer); - } - } - - - // get beams in pos - List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); - for (int i = 0; i < existingBeamList.size(); i++) - { - BeaconBeamDTO newBeam = existingBeamList.get(i); - this.startRenderingBeacon(newBeam); - } + this.beaconRenderHandler.loadBeaconBeamsInPos(pos); } } - @Override public void unloadBeaconBeamsInPos(long pos) { - GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); - - // should always be non-null, but just in case - if (this.beaconBeamRepo != null - && genericObjectRenderer != null) + if (this.beaconRenderHandler != null) { - // get beams in pos - List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); - for (int i = 0; i < existingBeamList.size(); i++) - { - BeaconBeamDTO beam = existingBeamList.get(i); - this.stopRenderingBeaconAtPos(beam.pos); - } + this.beaconRenderHandler.unloadBeaconBeamsInPos(pos); } } - private void startRenderingBeacon(BeaconBeamDTO beacon) - { - this.beaconRefCountByBlockPos.compute(beacon.pos, (beamPos, beaconRefCount) -> - { - if (beaconRefCount == null) { beaconRefCount = new AtomicInteger(); } - if (beaconRefCount.getAndIncrement() == 0) - { - DhApiRenderableBox beaconBox = new DhApiRenderableBox( - new DhApiVec3f(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), - new DhApiVec3f(beacon.pos.x+1, 6_000, beacon.pos.z+1), - // TODO calculate color - beacon.color - ); - - this.beaconBoxGroup.add(beaconBox); - this.beaconBoxGroup.triggerBoxChange(); - } - return beaconRefCount; - }); - } - - private void stopRenderingBeaconAtPos(DhBlockPos beaconPos) - { - this.beaconRefCountByBlockPos.compute(beaconPos, (pos, beaconRefCount) -> - { - if (beaconRefCount != null - && beaconRefCount.decrementAndGet() <= 0) - { - this.beaconBoxGroup.removeIf((box) -> - box.minPos.x == beaconPos.x - && box.minPos.y == beaconPos.y+1 // plus 1 because the beam starts above the beacon - && box.minPos.z == beaconPos.z - ); - this.beaconBoxGroup.triggerBoxChange(); - return null; - } - else - { - return beaconRefCount; - } - }); - } - //================// @@ -400,11 +265,6 @@ public abstract class AbstractDhLevel implements IDhLevel this.chunkToLodBuilder.close(); GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); - if (genericObjectRenderer != null) - { - genericObjectRenderer.remove(this.beaconBoxGroup.getId()); - this.beaconGroupBound = false; - } } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index 15a67565d..f29b35f21 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -66,6 +66,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel this.clientside = new ClientLevelModule(this); this.createAndSetSupportingRepos(this.dataFileHandler.repo.databaseFile); + this.runRepoReliantSetup(); if (enableRendering) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index f97d4019f..c2f925bad 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -72,6 +72,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev this.serverside = new ServerLevelModule(this, saveStructure); this.clientside = new ClientLevelModule(this); this.createAndSetSupportingRepos(this.serverside.fullDataFileHandler.repo.databaseFile); + this.runRepoReliantSetup(); LOGGER.info("Started " + DhClientServerLevel.class.getSimpleName() + " for " + serverLevelWrapper + " with saves at " + saveStructure); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index 60d8a2fbc..238b50e46 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -54,6 +54,7 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel this.serverLevelWrapper = serverLevelWrapper; this.serverside = new ServerLevelModule(this, saveStructure); this.createAndSetSupportingRepos(this.serverside.fullDataFileHandler.repo.databaseFile); + this.runRepoReliantSetup(); LOGGER.info("Started DHLevel for {} with saves at {}", serverLevelWrapper, saveStructure); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java index 00e12ba3d..13b43665e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java @@ -49,7 +49,6 @@ public interface IDhLevel extends AutoCloseable void updateChunkAsync(IChunkWrapper chunk); void loadBeaconBeamsInPos(long pos); - List getAllBeamsForSectionPos(long pos); void setBeaconBeamsForChunk(DhChunkPos chunkPos, List beamList); void unloadBeaconBeamsInPos(long pos); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java new file mode 100644 index 000000000..8593f871d --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java @@ -0,0 +1,228 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer.generic; + +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.level.IDhLevel; +import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.pos.DhBlockPos; +import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; +import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; +import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +public class BeaconRenderHandler +{ + private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + + /** if this is null then the other handler is probably null too, but just in case */ + private final BeaconBeamRepo beaconBeamRepo; + + private final IDhApiRenderableBoxGroup beaconBoxGroup; + private final HashMap beaconRefCountByBlockPos = new HashMap<>(); + + + + //=============// + // constructor // + //=============// + + public BeaconRenderHandler(@NotNull BeaconBeamRepo beaconBeamRepo, @NotNull GenericObjectRenderer renderer) + { + this.beaconBeamRepo = beaconBeamRepo; + + this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(new ArrayList<>(0)); + this.beaconBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); + this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); + this.beaconBoxGroup.setShading(DhApiRenderableBoxGroupShading.getUnshaded()); + this.beaconBoxGroup.setPreRenderFunc((renderEventParam) -> this.beaconBoxGroup.setActive(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering.get())); + + renderer.add(this.beaconBoxGroup); + } + + + + // + // + // + + public List getAllBeamsForSectionPos(long pos) + { + if (this.beaconBeamRepo != null) + { + return this.beaconBeamRepo.getAllBeamsForPos(pos); + } + else + { + return new ArrayList<>(0); + } + } + + public void setBeaconBeamsForChunk(DhChunkPos chunkPos, java.util.List newBeamList) + { + // TODO move beacon handling to its own BeaconRenderHandler class + + // synchronized to prevent two threads from updating the same chunk at the same time + synchronized (this) + { + HashSet allPosSet = new HashSet<>(); + + // sort new beams + HashMap newBeamByPos = new HashMap<>(newBeamList.size()); + for (int i = 0; i < newBeamList.size(); i++) + { + BeaconBeamDTO beam = newBeamList.get(i); + newBeamByPos.put(beam.pos, beam); + allPosSet.add(beam.pos); + } + + // get existing beams + java.util.List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos); + HashMap existingBeamByPos = new HashMap<>(existingBeamList.size()); + for (int i = 0; i < existingBeamList.size(); i++) + { + BeaconBeamDTO beam = existingBeamList.get(i); + existingBeamByPos.put(beam.pos, beam); + allPosSet.add(beam.pos); + } + + + + for (DhBlockPos beaconPos : allPosSet) + { + if (!chunkPos.contains(beaconPos)) + { + // don't update beacons outside the updated chunk + continue; + } + + BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos); + BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos); + + if (existingBeam != null && newBeam != null) + { + // beam still exists in chunk, do nothing + } + else if (existingBeam == null && newBeam != null) + { + // new beam found, add to DB + this.beaconBeamRepo.save(newBeam); + this.startRenderingBeacon(newBeam); + } + else if (existingBeam != null && newBeam == null) + { + // beam no longer exists at position, remove from DB + this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks + this.stopRenderingBeaconAtPos(beaconPos); + } + + } + } + } + + public void loadBeaconBeamsInPos(long pos) + { + // get all beams in pos + List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); + for (int i = 0; i < existingBeamList.size(); i++) + { + BeaconBeamDTO newBeam = existingBeamList.get(i); + this.startRenderingBeacon(newBeam); + } + } + + public void unloadBeaconBeamsInPos(long pos) + { + // get all beams in pos + List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos); + for (int i = 0; i < existingBeamList.size(); i++) + { + BeaconBeamDTO beam = existingBeamList.get(i); + this.stopRenderingBeaconAtPos(beam.pos); + } + } + + + + // + // + // + + private void startRenderingBeacon(BeaconBeamDTO beacon) + { + this.beaconRefCountByBlockPos.compute(beacon.pos, (beamPos, beaconRefCount) -> + { + if (beaconRefCount == null) { beaconRefCount = new AtomicInteger(); } + if (beaconRefCount.getAndIncrement() == 0) + { + DhApiRenderableBox beaconBox = new DhApiRenderableBox( + new DhApiVec3f(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), + new DhApiVec3f(beacon.pos.x+1, 6_000, beacon.pos.z+1), + // TODO calculate color + beacon.color + ); + + this.beaconBoxGroup.add(beaconBox); + this.beaconBoxGroup.triggerBoxChange(); + } + return beaconRefCount; + }); + } + + private void stopRenderingBeaconAtPos(DhBlockPos beaconPos) + { + this.beaconRefCountByBlockPos.compute(beaconPos, (pos, beaconRefCount) -> + { + if (beaconRefCount != null + && beaconRefCount.decrementAndGet() <= 0) + { + this.beaconBoxGroup.removeIf((box) -> + box.minPos.x == beaconPos.x + && box.minPos.y == beaconPos.y+1 // plus 1 because the beam starts above the beacon + && box.minPos.z == beaconPos.z + ); + this.beaconBoxGroup.triggerBoxChange(); + return null; + } + else + { + return beaconRefCount; + } + }); + } + + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index 4933e46c7..adbc8f725 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -60,8 +60,10 @@ public class CloudRenderHandler private final IDhApiRenderableBoxGroup[][] boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3]; private final IDhLevel level; + private final GenericObjectRenderer renderer; private float moveSpeedInBlocksPerSecond = 3.0f; + private boolean disabledWarningLogged = false; @@ -72,12 +74,7 @@ public class CloudRenderHandler public CloudRenderHandler(IDhLevel level, GenericObjectRenderer renderer) { this.level = level; - - if (!renderer.getUseInstancedRendering()) - { - LOGGER.warn("Instanced rendering unavailable, cloud rendering disabled."); - } - + this.renderer = renderer; @@ -174,11 +171,7 @@ public class CloudRenderHandler CloudParams params = new CloudParams(textureWidth, x, z); boxGroup.setPreRenderFunc((renderParam) -> this.preRender(params)); - // we only stop before adding to the renderer to prevent accidental issues with null pointers and such - if (renderer.getUseInstancedRendering()) - { - renderer.add(boxGroup); - } + renderer.add(boxGroup); this.boxGroupByOffset[x+1][z+1] = boxGroup; } } @@ -195,6 +188,15 @@ public class CloudRenderHandler return; } + if (!this.renderer.getUseInstancedRendering()) + { + if (!this.disabledWarningLogged) + { + this.disabledWarningLogged = true; + LOGGER.warn("Instanced rendering unavailable, cloud rendering disabled."); + } + return; + } //================// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 090329588..3472f9602 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -629,7 +629,16 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // getters // //=========// - public boolean getUseInstancedRendering() { return this.useInstancedRendering; } + /** @throws IllegalStateException if {@link #init()} function hasn't been called yet */ + public boolean getUseInstancedRendering() throws IllegalStateException + { + if (!this.init) + { + throw new IllegalStateException("GL initialization hasn't been completed."); + } + + return this.useInstancedRendering; + } From baa89edd0374c9d1d43602719ec1d81d50ec734f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 8 Jul 2024 07:35:34 -0500 Subject: [PATCH 050/104] Add a few missing items from beacon render handler --- .../renderer/generic/BeaconRenderHandler.java | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java index 8593f871d..ddcefaf41 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java @@ -75,26 +75,12 @@ public class BeaconRenderHandler - // - // - // - - public List getAllBeamsForSectionPos(long pos) - { - if (this.beaconBeamRepo != null) - { - return this.beaconBeamRepo.getAllBeamsForPos(pos); - } - else - { - return new ArrayList<>(0); - } - } + //=========================// + // level loading/unloading // + //=========================// public void setBeaconBeamsForChunk(DhChunkPos chunkPos, java.util.List newBeamList) { - // TODO move beacon handling to its own BeaconRenderHandler class - // synchronized to prevent two threads from updating the same chunk at the same time synchronized (this) { @@ -177,9 +163,9 @@ public class BeaconRenderHandler - // - // - // + //=================// + // render handling // + //=================// private void startRenderingBeacon(BeaconBeamDTO beacon) { @@ -224,5 +210,4 @@ public class BeaconRenderHandler }); } - } From 63dea2515e0753dfb9886b217b02f55f707bb523 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 8 Jul 2024 07:42:56 -0500 Subject: [PATCH 051/104] Add generic rendering US localization --- .../distanthorizons/core/config/Config.java | 13 ++++++++----- .../assets/distanthorizons/lang/en_us.json | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index ed1733ff5..e14fc5210 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -512,7 +512,8 @@ public class Config public static ConfigEntry noiseSteps = new ConfigEntry.Builder() .setMinDefaultMax(1, 4, null) .comment("" - + "How many steps of noise should be applied to LODs?") + + "How many steps of noise should be applied to LODs?" + + "") .build(); public static ConfigEntry noiseIntensity = new ConfigEntry.Builder() // TODO: Make this a float (the ClassicConfigGUI doesn't support floats) @@ -525,7 +526,8 @@ public class Config .setMinDefaultMax(0, 1024, null) .comment("" + "Defines how far should the noise texture render before it fades away. (in blocks) \n" - + "Set to 0 to disable noise from fading away") + + "Set to 0 to disable noise from fading away \n" + + "") .build(); } @@ -666,21 +668,22 @@ public class Config public static ConfigEntry enableRendering = new ConfigEntry.Builder() .set(true) .comment("" - + "\n" + + "If true non terrain objects will be rendered in DH's terrain. \n" + + "This includes beacon beams and clouds. \n" + "") .build(); public static ConfigEntry enableBeaconRendering = new ConfigEntry.Builder() .set(true) .comment("" - + "\n" + + "If true LOD beacon beams will be rendered. \n" + "") .build(); public static ConfigEntry enableCloudRendering = new ConfigEntry.Builder() .set(true) .comment("" - + "\n" + + "If true LOD clouds will be rendered. \n" + "") .build(); diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 2c5243d02..08ba41a32 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -309,6 +309,23 @@ "Grass Side Rendering", "distanthorizons.config.client.advanced.graphics.advancedGraphics.grassSideRendering.@tooltip": "How should the sides and bottom of grass block LODs render?", + + + "distanthorizons.config.client.advanced.graphics.genericRendering": + "Generic Rendering", + + "distanthorizons.config.client.advanced.graphics.genericRendering.enableRendering": + "Enable Rendering", + "distanthorizons.config.client.advanced.graphics.genericRendering.enableRendering.@tooltip": + "If true non terrain objects will be rendered in DH's terrain. \nThis includes beacon beams and clouds.", + "distanthorizons.config.client.advanced.graphics.genericRendering.enableBeaconRendering": + "Enable Beacon Rendering", + "distanthorizons.config.client.advanced.graphics.genericRendering.enableBeaconRendering.@tooltip": + "If true LOD beacon beams will be rendered.", + "distanthorizons.config.client.advanced.graphics.genericRendering.enableCloudRendering": + "Enable Cloud Rendering", + "distanthorizons.config.client.advanced.graphics.genericRendering.enableCloudRendering.@tooltip": + "If true LOD clouds will be rendered.", "distanthorizons.config.client.advanced.worldGenerator": From bd5054e7621f420fcf93b1f6b69f4c6dabff43ce Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 8 Jul 2024 07:44:41 -0500 Subject: [PATCH 052/104] re-arrange the generic rendering config --- .../distanthorizons/core/config/Config.java | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index e14fc5210..71654580c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -136,8 +136,8 @@ public class Config public static ConfigCategory fog = new ConfigCategory.Builder().set(Fog.class).build(); public static ConfigCategory ssao = new ConfigCategory.Builder().set(Ssao.class).build(); public static ConfigCategory noiseTextureSettings = new ConfigCategory.Builder().set(NoiseTextureSettings.class).build(); - public static ConfigCategory advancedGraphics = new ConfigCategory.Builder().set(AdvancedGraphics.class).build(); public static ConfigCategory genericRendering = new ConfigCategory.Builder().set(GenericRendering.class).build(); + public static ConfigCategory advancedGraphics = new ConfigCategory.Builder().set(AdvancedGraphics.class).build(); public static class Quality @@ -532,6 +532,32 @@ public class Config } + public static class GenericRendering + { + public static ConfigEntry enableRendering = new ConfigEntry.Builder() + .set(true) + .comment("" + + "If true non terrain objects will be rendered in DH's terrain. \n" + + "This includes beacon beams and clouds. \n" + + "") + .build(); + + public static ConfigEntry enableBeaconRendering = new ConfigEntry.Builder() + .set(true) + .comment("" + + "If true LOD beacon beams will be rendered. \n" + + "") + .build(); + + public static ConfigEntry enableCloudRendering = new ConfigEntry.Builder() + .set(true) + .comment("" + + "If true LOD clouds will be rendered. \n" + + "") + .build(); + + } + public static class AdvancedGraphics { public static ConfigEntry overdrawPrevention = new ConfigEntry.Builder() @@ -663,32 +689,6 @@ public class Config } - public static class GenericRendering - { - public static ConfigEntry enableRendering = new ConfigEntry.Builder() - .set(true) - .comment("" - + "If true non terrain objects will be rendered in DH's terrain. \n" - + "This includes beacon beams and clouds. \n" - + "") - .build(); - - public static ConfigEntry enableBeaconRendering = new ConfigEntry.Builder() - .set(true) - .comment("" - + "If true LOD beacon beams will be rendered. \n" - + "") - .build(); - - public static ConfigEntry enableCloudRendering = new ConfigEntry.Builder() - .set(true) - .comment("" - + "If true LOD clouds will be rendered. \n" - + "") - .build(); - - } - } public static class WorldGenerator From 0d79a856b26584d257aa557af5baae0e99e4bae0 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 8 Jul 2024 18:45:42 -0500 Subject: [PATCH 053/104] Add cloud greedy meshing --- .../renderer/generic/CloudRenderHandler.java | 90 ++++++++++++++++--- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index adbc8f725..9710708de 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -117,24 +117,94 @@ public class CloudRenderHandler { if (cloudLocations[x][z]) { - int minX = x * CLOUD_BOX_WIDTH; - int minZ = z * CLOUD_BOX_WIDTH; - int maxX = minX + CLOUD_BOX_WIDTH; - int maxZ = minZ + CLOUD_BOX_WIDTH; + // start a new box in Z direction + int startZ = z; + int startX = x; + int endZ = startZ; + int endX = x+1; + + + + //==========================// + // merge in the Z direction // + //==========================// + + // Find the cloud's length in the Z direction + while (endZ < textureWidth + && cloudLocations[x][endZ]) + { + endZ++; + } + // update the z iterator so we can skip over everything included in this cloud + z = endZ - 1; + + + + //==========================// + // merge in the X direction // + //==========================// + + for (int currentX = startX + 1; currentX < textureWidth; currentX++) + { + boolean canMergeInXDir = true; + + // check if all locations in this column are true + for (int adjacentZ = startZ; adjacentZ < endZ; adjacentZ++) + { + if (!cloudLocations[currentX][adjacentZ]) + { + // at least one pixel in the texture is false, + // so we can't merge in this direction + canMergeInXDir = false; + break; + } + } + + + if (canMergeInXDir) + { + // mark the adjacent column as processed + for (int currentZ = startZ; currentZ < endZ; currentZ++) + { + // by flipping all the pixels in the adjacent column to false, + // we don't have to worry about adding another cloud + cloudLocations[currentX][currentZ] = false; + } + + endX = (currentX + 1); + } + else + { + break; + } + } + + + + //============================// + // Create the renderable box // + //============================// + + // endZ contains the last cloud index + // so the cloud now goes from startZ to endZ (inclusive) + int minXBlockPos = startX * CLOUD_BOX_WIDTH; + int minZBlockPos = startZ * CLOUD_BOX_WIDTH; + int maxXBlockPos = endX * CLOUD_BOX_WIDTH; + int maxZBlockPos = endZ * CLOUD_BOX_WIDTH; Color color = CLOUD_COLOR; if (DEBUG_BORDER_COLORS) { // equals is included so the board is 2 blocks wide, it makes it easier to see - if (x <= 1) { color = Color.RED; } - else if (x >= textureWidth-2) { color = Color.GREEN; } - if (z <= 1) { color = Color.BLUE; } - else if (z >= textureWidth-2) { color = Color.BLACK; } + if (startX <= 1) { color = Color.RED; } + else if (startX >= textureWidth - 2) { color = Color.GREEN; } + if (startZ <= 1) { color = Color.BLUE; } + else if (endZ >= textureWidth - 2) { color = Color.BLACK; } } DhApiRenderableBox box = new DhApiRenderableBox( - new DhApiVec3f(minX, 0, minZ), - new DhApiVec3f(maxX, CLOUD_BOX_THICKNESS, maxZ), + new DhApiVec3f(minXBlockPos, 0, minZBlockPos), + new DhApiVec3f(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos), color ); boxList.add(box); From 29ef95387c4183b927e5f9b70a591044a397c843 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 8 Jul 2024 19:56:20 -0500 Subject: [PATCH 054/104] Shrink cloud texture to improve performance --- .../renderer/generic/CloudRenderHandler.java | 4 ++-- .../textures/clouds - original.png | Bin 0 -> 6214 bytes .../distanthorizons/textures/clouds.png | Bin 6214 -> 1777 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 core/src/main/resources/assets/distanthorizons/textures/clouds - original.png diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index 9710708de..f7325bfc6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -54,9 +54,9 @@ public class CloudRenderHandler * How wide an individual box is.
* Measured in blocks. */ - private static final int CLOUD_BOX_WIDTH = 128; + private static final int CLOUD_BOX_WIDTH = 192; /** measured in blocks */ - private static final int CLOUD_BOX_THICKNESS = 32; + private static final int CLOUD_BOX_THICKNESS = 48; private final IDhApiRenderableBoxGroup[][] boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3]; private final IDhLevel level; diff --git a/core/src/main/resources/assets/distanthorizons/textures/clouds - original.png b/core/src/main/resources/assets/distanthorizons/textures/clouds - original.png new file mode 100644 index 0000000000000000000000000000000000000000..825f4814e3fab7899db0e991087484a908873d5f GIT binary patch literal 6214 zcmV-M7`f+(P)Px#1ZP1_K>z@;j|==^1poj522e~?MF0Q*|NsA`*`M72000SaNLh0L01m?j~gZYoErBeyQB=cj_p-0I=rLVQ)}o zX;6sM?D;ZSxmyPL8$XLp<>oVCn8;hlxgU}{YnO7-aJ30Pm&!L>086(&v>*ZaTTf2i z1WW_;x2ojbp#vBqFaZ7H{i6U}4m=>X-|>M`YbH}SX^ zabDL|LB5VokLw92$f8Yu10&lKPTR-LAJj=I00NoF6#!)IU|mX`zAnTf0H&Kojqi^P zo~64l0jJ+={zqwg%;;kjr0 zVm@IVRo_rz8+n0MzzP6+b9E?iL@_)fLSMSVNQv-^{c7~E7)f;mr?C5KvQJiiX5RYE4Y~7NwGfkD z(=8-W%v*mU3Gw_}0B7Qe*RU(*{3vO09*%yfMrp#ojrS1~Y0S8UF4vLSodmr5JhwU3 zF*K1lbNlN@dkQ-`DsVU<(}KX5&sESk{~E573K^_MCAx9^AR~8`e%2WIMwt*Y`35&^ zqy`|(3#UynNOYkJRjxixl7=CqyJ^WMDyj~EluN{A9h^5u_^g=-L0iiY^2COhD7GX; zg^xdfQvy_7d+keHmsnnMa*hk z08L&@b&LxDH(Up>5OD8o+!|R?>TZ7ZII|Zq3iC&rrZ_CNU-$H@UnnI8%W(GL-D(&b z`^7osCJEP$=|r+#YNB7SL+Zn{z$NXjtTk7f>{pI#v8HZGE%L7cafSjfA!Pp0=Oaxm z_0~J-@UYgMv`9WzG7ayF^glC?)&ZyiKrm10bi<*G39oZvFxB_c3H1pLFKz` z+oh9&vW{PxNJm}fdBHbk5I;1>1NDL(fs{Oz#cBG()m|f?OlDFw4r)=x0l33b2Y(>Y zU_%B#$fqbPW#zLH7$(QlB!b21+fRonRsd=j!u`CF*eNH6&c%b~IwZSx+o*OaB1i&P zybiJjM71#=P4u!x6vXr=+PogxCYDHbvd50KU9L1SR+)fSd}?X@0bnJ7XdUvl(bHTe zor>a5_DJT0)m7R5XH1SljMhOg*NgH@QHNNn6lyC=xK#}zYY^*8HSWa(N>)w@X!E-M zA**Aem)lbp8Y@^AvYN3&oa3by<@Y&9iJ*_VJbKoWY)m0Y;vWa;!ZFCt&$1)KZXSRO zca4Z+XthwXkIOHEA8T0^z!aweSY0%8r7wvUu&(AnM0TrK>lQ{MxHNq3~1wP0KZG0G(Ir%h1M>Nyfv_PIJ|b5_eFwQtyTbSk_G!s04nwx z3zHEV(JW=5bUU(#YJ!mx+O+9zQL4K=);kOr+&%#mK0yd7h|)KYjBAHM=F2i2NZoKD zSJ(isZ{zh~z&`O?+QWGidfDVyiV)TXDS*XF)?706D(00O18i)u<4HJMdUf)Y_k9_)9QKcxVHV!ybkmz3gMQfI_ZouVwS6(1TR&KO3*5 zQMvyr0iGMQtks=$eDx;NNW02W+Ljj<is)bzMZqxsuudC`9hv(WF1+8(z0iaH}N9 zHZk_C2CRMetilPHSKwx8YXPv;#?c6K9iVkqbz}w)r0&LO5vuX0`e7}y-0Q|u0?-*m z_))>`SyAms*l!`q3IO>Q@N&4&FRDQRbe=9lb&f@kDpuTBx$S%~AbuHsO zcTF`w0kE54No`Lm8kaPufL<3+NNZV61hcWf+oqhXjT$27d28AsT#9Qg6x6-+?3OQ^ zkB5HpeiTO%7BhpKAU)noxTu-{rrZ?P{hd=M!OKLIyeuj5iJG!^7~e~7FLy#MZa}Lj z$34e^UBc|!{uPq*w%q=4x6)xVgHwB3c2OEaEhDk;WJ-FBn2G(-lAn3vv2GHAOqN{Js{+d8?CCPJa3PK&vm)pN@Q<9 zw{-O+LOb^!CtdoVsjNo;xF7vVxhzNMnCC6VpV(v5Aie<^7d;7#dTQM!S^?A@n)>G>osf?h6%p%3mpmU=)9~h-x6n?Xk5B~Ry|7gee2Fb$qbc%; zlb8>2d8J$3eja}mT+Z$}%WOIW7H|Sf(khkWJZ`senVvLByCntA2QL;E%_e?+tD2O` z$RTL|?uZ}){0qgkVw?ZB*5+8#uUOP3rLK`@$*ATv z(GQti8(JOO^6eNxcg~P)2c(C$AqG7o!JGl$%?Swta!+?Op#ac&yPfK3zGNYH!t`|w zbX8eG#JXb2s8kVMo{_(>kA&vlGWcyiB7sy$Wf2Hm09Xdd5l3!5a|rSRK%rW55#IHN z03h-vaqk}9D7Ca>XLtJOhhy-#KFgjdZ8(kgWSmt(a?3FiDN${KwRXb}GbD9lD#u8u z2i}_z#19#SN|LR4v|&8i@aBFP^0@_N4{BuRcQ5BtJIBCraP9oHDvLjgbvom_1R$Rd zGHIBQMc28fjHJ%fn9mp++yrz63qy?Np>gPkx*$Coht1KQ@FFumdWghJ*i1)`knon! zTEsTslzSBlQss4a5oC!V;>{oEG3Qhn}eSq$Xv7`jEGT8GV zXb|7%g#$hOoKYdv)tfPd#Q*Q7I`Uy1@Hy{AU!*i`2HwXa!re*Q8lpRI&sr^ z<3bEPG$N?c5ghXv4`ryia^OpV(HZQYIRBf!1WVG=93%;g5TfbL<az5f3v!Kgl7-%s9IgXB;hF&<6xS_vHcG7vyvRj_siUH@|rN z6Y@#7v7>qaG$qehNO_uzK=~zs@6yO~JK82iOkNDE)&cuxY@>?!DLq+g!`d@2sM;8j zyf~~i!Mj*S{-h?R$Qq}NKx%#0idMWBGjGpb-%^SV00sae)Wl8!*iM($9;XH9a5Eex zzx@q>7X|F$bPs&;^HGOK99i0Y0pR;wKM|C~4GLB10+da+Q=LW9s5sLf>q`qEa9{ms zY~w+B01e4 z*n4Fvk4ho&ZvFP&2mPWS;iHTlEhwZYz)R9A3uC*}uK?J1+>3o$>4q&+r`mxCsEP8Z zXYz))GY`oWk&s?!fj%V=*;3UxCrH%l?MTUh?$n3mz`_-Q_=22}v|R}C*H%x2a?K=* zD6D4H0-fJ&4Ls18yDw{r6i4A{0`S*9nK{!9K-HllNx2X0Nf~w0$)r>UwO2TyGjAH* z0l->u&ht=@yteR;OCK^R&L@p|J~VV>?+FZ7{7^@@7JG%2F4imOGO>PF$7i-E zYeTQD=p=bL@IqY%-+ZkIR(}1}PEC=Z`d15!u|iq_+GBsu)|~NkOQ};KQCtvf>fgI` z_-!{&;=on01HcPBYh!1yh+wiT*R^s1<(%sEbhzK$s>U~_$in=nA44}uc~R|W4Hi>6>CXa1B`FD@vq{D@gZaV25d0?YTR-T;$t;<+t&vk- zE!i4J^`Csma-Y0}te4?KWfI4)YMF9AGz{EdT@vr4xDaZId0Z3}m$$I=7Er82r_UdA z+6>SMMV5f#%ABwUL*vLMRBNitrhf_tYL}GKHB!pl1kj5;T;||==(C)Dy2C2~WorGE z8jn?&+hW-T>|QLq0)rL%=Q$2*pu_gC?}g{(=>-I8t3J~K+lQ2I>Z#MwY7eqfW<-w$ zg4i4fC;dIFuS&`O@~y);34oOJRN|>aG57&ln`mNT&2THzAyZsCJ+T4c@Mm3(^h@bB zzgvU*`0GcK7t$NJze6W==6skJ1nwj>C&kNq^Hu=*lg~Sqcn2WeYRi{5%y__p&$+Jw zkUehHSBVsGN;Vi&eUhG?YngMu)LdVO7w*vCA(R>%6>);i%k?u0*>#HW2mt$IRnb5L zqVk=S+KfVke#i?fQwRK@0jB+;YwbUJw5m@i7DL{=Xrmz0e#8`Y)un#uYe+i@On#@3u7b(^VJkOQi|r3Euv#R zeIvrnu^O*&h%-@|ML|sG6?LbPVs~T!cGV4@=bdpxL{(wzjd0c?;#nI6+vEv)wQ0Kn zKxpr?%y|Xays$a5`WJeS+P7p_ClR{53P@AHye%Bl@zo?6FS`P`J~0pzHkQHIDnGd! zdm$B4pOn@lwX3Nnxc&<9pq7sheWS7*Im(X-WH*n8HRx>ihYn+nc1tFw9Ctqt0O-fkHuGM_*9p|ON|%hYzAxy;6FatpF2qa$kWX_ z6xof`iasz-2%ei?0q}fr6rl3ncmsN=V)}PWl+!-Bcy@dneS;|{eS{drvv+Nj7pCuL z&?Fe&C4d_MSzWEFXyB}QN9kj8^*IH@*Jl}&_Ch7$Y>&$%iWY-4LbqyX%=-FIByh^8 zY9C5QG)-wOc(*640McLAeJ|Fc#d1Y;Qdt>6OK9$UW9_443HN>doI6SDoc5tqy?gd^ zl7D`$UTXI@0#v%{-D_abIE>uOEV}i_J@JH~o+)?{t#z6}*d7$&L{%jYX8>rZX-h0c zj|)_eGZC=FJAEFDA{vJ3%ByXVOOeJ>Y&oG=$0n)S4FL8pFl+!AO=6s6BDF%R)ybim zl4Yum&kr^L$A({ywOG~C9T7t4BWC+I0I}A*^(Ko$nc(u0)WwIjvV{8Yt7*1n_tHA8 zmrp-7+Vo_`4A6wZ^enfq6PJ)*F7a-7YBYHS%t_OlpRweK@?hBd0&?W964+K;)Vy_> zuO3`yhaM`g$=N}7(#zoDIAXIbo3`||`auHMaJn!CPcf5sxljN}B;^|AD_8mD%{HR^ z#+<|*HS8t7M|>;b>OWJ1P1dybrWHQYf@}I)ByAJO=t;>9a156p83}G?0T*>$@^XpZ)+Z z{cKv+^#=gBapew*36{rR050JIK5Hw7kZd%xV@Y6SV; zVbgLWtO_KWEt8;~RhXq+oM0t%AdD0IsYM(uYqx1z8ZPhN;yjP#at{w0;P5TG$&5(z z#4}R41M5$Ge;_BiBnLpRO~oG`JCv5prF=jL7XIzM*k z?;qiyz7h)nLtp{ETPtbtS9Ed}eC&sHPNM&YGTT7C?+ie1;I{CceK%DuQ&}$DmVTEW z@_bD-cLsZ7wAyWp`4TsZpXYxL0Mgof3Mao_mRR*+HKhwEIpQigT{<6O zwL^6@BdthMA${8FB=l@tach~r7;I4i$p0bE9(W{a-Nx`>yCxDrC?AF!YcE1=ydCwK zPfcLiic>|AE&#C9$Y1Aj7 z&SNT@knU4!X2h=*Pb)LUmzxf589% z4#5Gqk!$S$00wkPL_t(&-i=ual4~Idgd5QJzwAUd0W}$`{?E&cw(Q$bEQS!%e->E8 z_S;uGt}j6ACCf(rJR-lsKZSwM{<6m?sC!~mO1m0Q{jNfc>)(_GLMM)3FZff7>OQe**}XApF1rSYoCB0<4Xy2H4#T&er=p4*)2J z0et?0Y-L=QEYsOg4840{m>z_T{x`{0I#BV$uZPm6G=RUcfbtagE8X%rrgpiu@IPe0 zD!%~G6P)_LX+h3cDnC{Z48VMg{;5VbM-p+9TsUU~KD71Ik~Ze+Gfy0P2?T zlbo+uqr?|uXv;LH2aRT4$_>Cm)+T#=#j(ir7(WT6K? ze9dB_#hFO}egr&=v1*4{f7UJYerCKv7W)=5@6dl!L(53zP{bg?594NtALhh}@ZI(y zxlw~mHSLShtuP=|z}cdiKCt>m;j#N}__$}nB*XWs4+@%)1_f-PHvvv%EIn(iru)*g zrRIC65(z-`0$`3`ER%O(aS(ZAmL2QTw06vNQ$gin6L-2oU~^G1f42>levUF}yIM(X z5;s%;4k}A=h4UU$egq?6J2T7@xk`bz;Yu*3SwIw^yKN@>YL6+V6tx0`woygl$0e&C zN@~oEk<}TuLdq+{yua#V~+FU^fxNKJm}L%*0$JM*LfFNH{H>&^P)N(K0ZJ)$zMEeu~OiLBs8RKJz2 zTD0Bo-}Tg{e}GRGB7WTfb|oP}*ook2ss-xu#C@xrMyKiIB3wScGtPZR*&&8%=~5xD zWt|aLXxE&`s$S}jqQ&#*IlI3YsK!!P0hioLSA)?yW%{P(VCv1R71w9Yr*o(pI>a;L zP{S&x_|nBP9h7P1ky&tGX&uC-IoQa$;!Ku%pLs7 zbOpF)OD+1AAC@xuMnkPvh8EZ~{&n0`5Gbphxd&LsE%sQrv206)aG)3l#pnN`xq5|7x5@-P~GJ~Fa0)rWMOPj&Um zG=Ulm+Al~coZ}kXWPc^l;O8}+&QFRVGOh`WvKMy^SwLeyUj4uK(;I;84Z=fXLM}jI zf}bS{2L)ke$bo81dYx+AAsE@<2zhFY=C>Q|f5nw(M;-4fZ8ToYzMh|^s_Dk|Ngc>= zMJVesTrE|IGN~Y&1W2LQ&K@8OANpSRS=|N00)PMyMok z=}Mn5B-(HP-$o+JRZWC0E0!2?G~xn4Cu%;U@Ig$Re-5@NFVgYGn&E1scOJsB%thob ze}QGM-rb51*pz}YT7VHm4*+D35`$27OAfkCsP=f_U;{`VHonZA!&K#7I2eGNE_U>_ zU)4qSPWFNQPy)5q08X&QSmTQ+RAbciIYiJc78~kxD5wb{P1cwxQ`~qRU`vd1DCUo@ ztS$i!l{y8FX0Z--Ofb$0U&iEi@gBeJf7qq~3pPCC5+WGkB>~V1Bewi(VoCt7i=wey zrW-%2%FzH=bdG06#YW1ohDx4xFWeHBsf;agrEy}25k7|nUjpB*X4y!U{EM<}bpd)F zc($?1o9i;o)R6mVaG+SGgd2T~)N)+qBR@*3 j#}Jd7X3G17+62)bmXUyD->=@y00000NkvXXu0mjfiR(UQ delta 6213 zcmV-L7`o^24aP7biBL{Q4GJ0x0000DNk~Le00031000311Oos70IpoMRgob&f5HF& z4#EKyC`y0;02j$gL_t(|+Lc`imgFi9lx`s1|FT_1`-0P*^X6Ao8bctogamejeUJ$d zzI+&oq5$>+6r<@Usod{(>L|Pbu;$WX zZ%}4wP>9p)`7&6!TL$?XKZ{M}f95k`n8;hlxgU}{YnO7-aJ30Pm&!L>086(&v>*Za zTTf2i1WW_;x2ojbp#vBqFaZ7H{i6U}4m=>X-|>MDI4%^%cBDgXkR$Q1x&?OoxU!_A^@hF zMUC%|44$RCF9E0DZ2m`XbOrD-ZX4(L)n^F&paXdH&j1`xt-`?X0LJ(#;LQqX^Xq>Y z#NoMT{9-;~9aY~@VjFxke?yc&bo|QkFvk+0@+KJxe8DaoYv zt_a(g9MlU1;JY8d3IKa^btrH|F+3tdU%J9biSUd4YV@!eNp%FLu={GVPgZ_r-ulfA zx$|7L5R+chEhJFPTYn)5@%&o=XX1$0uq)>LC~0vXj((^{X~Msa_Yo6m%(#Ru*OA$s z1ibq^w>i}@G?6%SfBWl4dkQ-`DsVU<(}KX5&sESk{~E573K^_MCAx9^AR~8`e%2WI zMwt*Y`35&^qy`|(3#UynNOYkJRjxixl7=CqyJ^WMDyj~EluN{A9h^5u_^g=-L0iiY z^2COhD7GX;g^xdfQvy_7d+keHmsnnM|XUES|79ub^8BizJ9V4lw0o)>eDPEntOxi#FKp zDF0D7N?3XV$ywD;pyH@OsZd-}IF%h? zJqelCtPf{ zYEi}kxWiHhe<09cLk2*|rzk6B<+BnPCdbnxg2n0EPlqX10BRS){k)ObDJO@{#e?QL zB)fLof2ejTB1i&PybiJjM71#=P4u!x6vXr=+PogxCYDHbvd50KU9L1SR+)fSd}?X@ z0bnJ7XdUvl(bHTeor>a5_DJT0)m7R5XH1SljMhOg*NgH@QHNNn6lyC=xK#}zYY^*8 zHSWa(N>)w@X!E-MA**Aem)lbp8Y@^AvYN3&f1Kl`7UlOjM~R@1x;%Q;l59*NNa7y{ z>B2F{&(E?W!)_jc3wMo(V`#NdvX9FzgCA>I6~Gjy0a#r$bEPkd6|k=6Kty({SnLY> zAj2=xZ1thgI<)aBVgO63#gXIQr$(MHbqr|ZYXHAXpEN!&^M%$fjJ!3lb~wCtnfFD4 ze_E|p0Bw>5`%M5U_8JS55gO4fWubICvWIGdkrLXp>26V~yFJ!B3>Vx!0Tez#2r7uu zH;;^Khe77cG95_Wa3NRN0I+Z4^v1op?)ur1n|?fo zLauACW%H-dgH-N68?U8Nx&JBwo*T5R)tz;G^(NCuyUJ18mKP5~YmZ!YT|~#ZlG*?$ zMDE?uq(9{wUbj$it0c%aG4`zntbO;a!U>pH;AUxS0kGA^(Fk)LpmkPtWCjnUf9}R; z5vuX0`e7}y-0Q|u0?-*m_))>`SyAms*l!`q3IO>Q@N&4&FRDQRbe=9lb&f@kDpuTBx$S%~AbuHsOcTF`w0kE54No`Lm8kaPufL<3+NNZV61hcWf+oqhXjT$27 zd28AsT#9Qg6x6-+?3OQ^kB5Hpe|{845*9OqoFF~kOSq_-0H)j&*8QDRC&9}^mAot| z@`;+VcNpJGZZCI2Ep9-oD91g=fnCDv+x``j^S0dnaktW8GlNrmTXs<`$=W|J0aV#l zL7=C%q*kShojldCmhN>pZd?Yx5^uYq0k9&=zLiFRBN}ida=p3IuebCAf6oqfb1sEU zkKD1XL9GqIP=t31rfa8Zc9!^p+L&_VFx>^GORM817%VRsLNU`7KnM&6 zN~K&_98p&1ngd7`vjTt|g~o@|)g`b<&GC4F6v;|LPX&-N{Sc~^gXf}2FPsFs03a!O zq0m=?R`1;BR8GIy@kJMMe;38wI~)K?BM_oA=VRa4Z_O6Z49N43NfchQZ|nge1K6rP zAmoo5t*WIwZ;yk|b-CV3WN$#XboC@cJNF(ZUHYG?tVaO2AN@(WEJx^==Pkyc*l9jq zn%7a<@|ROK8Ni!*%`p`cjnVx3xYiTh1V)!YSlB)wz5y8*Jqe6@e`?((S^?A@n)>7!?ugMwdJvSJUw3 zo43$TpN~)k;k~d`4}6I&VxuYYh?AHPae1X%-F_Z_6kN{ke>ux+Is+DP0!z{=mEt^Z zw{V%BG)cQ91oa$T*?HEFL&X8>fq=&a520bIeoB`m? z2?+vnPj@t-0ML57o$6`6WFdFL^mPq%RarvBx?;+xR1saCk-xBygy!Bd_-#HSfmBFk z5eQrWSO&-uM{YiI2=W3zp;~hh-t~q6Ao3=0?;hSLf3>t@XLtJOhhy-#KFgjdZ8(kg zWSmt(a?3FiDN${KwRXb}GbD9lD#u8u2i}_z#19#SN|LR4v|&8i@aBFP^0@_N4{BuR zcQ5BtJIBCraP9oHDvLjgbvom_1R$RdGHIBQMc28fjHJ%fn9mp++yrz63qy?Np>gPk zx*$Coe}~P{o$w+vKYED7OV~_Dj*#${&|1Vc^CPL5+EPr1Y!gq%&qP^9@2M*NR5doE z){;$%@G>p+V7yo{`tGa&ILd=-?v^R?dH`NyITnT?b)le1V09teSbSWkUG_PyUh`M# zs3{Z|07xVc4*4b%_q~BE9x@)j4R$GirUvKUe|&6Q!XK$DFc@V?&CF7s|68owP7dNg zqG)S~9zMbq0_+sJ?+I&tMLkE`dsru^zhLh?H`!N;&f2Iga_J|YxXk_B7Q9k@?rB*K z<^?xA6_7lRlLd~CenW4C0gRhZyh$q}%WET)AHs)ti{MzSRHfKvwuf?ctU;p%09F7Q ze>!jSku1(VJ;S1ZT$phEX%1Ggqy)1v*z+K05Z~y913oR2E$N_4gF45v+~87ssfZUA zc`1Vh@CE=NJv)>5{wP**O^c*aHL&A4anpI@LJT}KBB;?39P=0tWvIDw;7fqf8SI}p z|C_%AOVZLDBngWUqUp`$)L0P#!CT5=e*p5v18cI73s|gaXd%^=h!-whCiGSnXD&oU z`_?Qa)uH9Fn(RF+H-M{dVQ!j-q%xFji$s0(OwA$+)$E}aitk7EHW>az5f3v!Kgl7- z%s9IgXB;hF&<6xS_vHcG7vyvRj_siUH@|rN6Y@#7v7>qaG$qehNO_uzK=~zsfA7-B zb3585MND1{tkwbhXKbU2_$fVEYQx$yFsRxXk-RvpHNm@BM*gHGrpOwnj6iCA*NRrW z7&C9rUEflQ4FCoJBGklA0oYEL)*hz?=x{R}Ccpg+fENYq;dBpt^7B!LM;uw&d;#G5 zTt5+%#0?5n=>n8Zw^N-((x^Doe;?~h3n6e{{b+3CL3scXdjs@C)^V>^d`6#~7T_m< z7)C{4B&k^nIjx6i$U0XWh#$KA@Oeg_TC5mq95U-j2$f~ zq$t2k(klyNyVI`#*m&HFeOl>;EmNo3fe5IH@~CI>hPX2i$rO>0UTA?neNXdZi)Q9B2!WDt|f}D`FT?p~lR!@X-%_NH`tY*~$o!@N@JkXfCFKdYuN8xD# z@Yg<>Inxb5)uAFuxex708FkXhq*MmAS2&?FZyMbJz*=$6^H7hxw(yQiA2KPPF$7i-EYeTQD=p=bL@IqY%-+ZkIR(}1} zPEC=Z`d15!u|iq_+GBsu)|~NkOQ};KQCtvf>fgI`_-!{&;=on01HcPBYh!1yh+wiT z*R^s1<(%sEbhzK$s>U~_$in=nA44}uc~(W5WT;?s4&7%}fsrLn?7LXode&fig_S-Hd<}`{g+zl2} zI_b{>MI|W-ptDKFG=urU!Vvr>?pr_T#K|m~wylv4 zs?4T;3I}SJl+ra)%G?Cdi#=TC;Ctw^oPN5)D*$C`{goPzRhZji*#+!gEW84P75nEo z4r`#p_OS1T=jG`I1Zt~3(*fIulyB;()6r@VvQlP5j|PI+e;fxV{XML&O3D86t;0D9 zfRyx9;;BP1_yJj)XkuZ_a4XXxQ(QYeu>s)lXI+i-OX)VhTZ8-f>qn9o(i^zHLnn3S ze3%ym?j$rP#mjs1Rsi~w&pVZP2O!;Q%a=FIc))_sxvv3`J#N%ji4<^3HW*ZWlAfJw znRCC?TwjM5f9}xVA(R>%6>);i%k?u0*>#HW2mt$IRnb5LqVk=S+KfVke#i?fQwRK@ z0jB+;YwbUJw5m@i7DL{=Xrmz0e#8`Y)un#uYe+i@OBv*Hd1FM=c=7s0p_GE#v1n2r&Oi_hpZs$)n6|$tD=-ud$%eG{s zzvy3Jf8U+4{5U*wKIuvo0LIHPXa``jRD;lOsWh2sKt4H9bG}4Q4&cQ`!oPW~qGDG>6u8$8O+q<7UwD~TT z%*gp)N;DIhpaOtb0FWd=1AuN7hF>jY45yRif5JqA9txZoRj#7Kz1dd0sw*7{#T58? zsj3#c;PiNjM6e!1^f;MnNd@BR0;akPV+P7p_ClR{53P@AHye%Bl@zo?6FS`P`J~0pzHkQHIDnGd!dm$B4pOn@lwX3Nn zxc&<9pq7sheWS7*Im(X-WH*n8HRx>ihYn+nc1tFw9C_T``#evk=P9C0 zu&9#g8m_qN5Upr7(yjWZj!o$uaJZ$t;?bA$v)5we_)YP!om&n7U~F5g0C~Jf!S=8g zCy_*ekuqH}9jhZh8;`|TY4}u^!b^=8eg(DJOk|7{#-9ZIldBb(%of9u(n3RV5B*0BERbODsi?3sjCX5wOHN zeIAP<8iwl1t8I`=k;YPNIiXm`CaKvC0QN61YycQdVw_|mwL+`a$)TB&e`TtT&kr^L z$A({ywOG~C9T7t4BWC+I0I}A*^(Ko$nc(u0)WwIjvV{8Yt7*1n_tHA8mrp-7+Vo_` z4A6wZ^enfq6PJ)*F7a-7YBYHS%t_OlpRweK@?hBd0&?W964+K;)Vy_>uO3`yhaM`g z$=N}7(#zoDIAXIbo3`||fBHcJ*KoQp22U}QcezjiNhIYOe@MT(sXWTZ~}mBWX=FyR*A_OtcoSSdeJmgwDmFZ7W|kmTXyxG zB`-;emG+{d%iNy%_rL0%8d^Gk)z3Tz`e5m^E{+t5=yx=bgHr3eGDn~O05AP)TGsUk z0Jw4G4vGnu$6f$7fATJ)^PN;+Yr1__UY!BNmH_Vnv<^Zy1tx2Izuezy1o_`#({dxM z3M85>lc1edn5A8uU?p@Qj1&B+MI0?_w`p4%F7MvrJdfpa4-XpP@GZN^j7amuGg7$& z>rZ@tASb#c2SBe)#UCC!l$Oln$fY!FGOnMImssr+7oEcxf7!kX=jL7XIzM*k?;qiy zz7h)nLtp{ETPtbtS9Ed}eC&sHPNM&YGTT7C?+ie1;I{CceK%DuQ&}$DmVTEW@_bD- zcLsZ7wAyWp`Lm1RTyblez8Gv#0m%O$&K`IqY2C)~e_*>N5lN$76rjS7@DuJ2&6~&00000NkvXXu0mjfmDH}W From f144a9ebc1282e5101f894588a5f48016ba0d791 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 8 Jul 2024 20:20:48 -0500 Subject: [PATCH 055/104] Optimize beacon detection --- .../block/IBlockStateWrapper.java | 15 ++++++++++ .../chunk/IChunkWrapper.java | 30 ++++--------------- .../LightingTestBlockStateWrapper.java | 7 +++++ 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java index b26481a87..68fe9a194 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java @@ -21,6 +21,9 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.block; import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; +import java.util.Arrays; +import java.util.List; + /** A Minecraft version independent way of handling Blocks. */ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper { @@ -31,6 +34,15 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper int FULLY_TRANSPARENT = 0; int FULLY_OPAQUE = 16; + /** should be all lowercase */ + List BEACON_BASE_BLOCK_NAME_LIST = Arrays.asList( + "iron_block", + "gold_block", + "diamond_block", + "emerald_block", + "netherite_block" + ); + /** contains the indices used by Iris to determine how different block types should be rendered */ class IrisBlockMaterial { @@ -77,4 +89,7 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper byte getIrisBlockMaterialId(); + boolean isBeaconBlock(); + boolean isBeaconBaseBlock(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index 21c35ea79..ea774036b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -41,15 +41,6 @@ public interface IChunkWrapper extends IBindable /** useful for debugging, but can slow down chunk operations quite a bit due to being called every time. */ boolean RUN_RELATIVE_POS_INDEX_VALIDATION = ModInfo.IS_DEV_BUILD; - /** should be all lowercase */ - List BEACON_BASE_BLOCK_NAME_LIST = Arrays.asList( - "iron_block", - "gold_block", - "diamond_block", - "emerald_block", - "netherite_block" - ); - DhChunkPos getChunkPos(); @@ -271,8 +262,9 @@ public interface IChunkWrapper extends IBindable DhBlockPos pos = blockPosList.get(i); DhBlockPos relPos = pos.convertToChunkRelativePos(); + IBlockStateWrapper block = this.getBlockState(relPos); - if (block.getSerialString().toLowerCase().contains("minecraft:beacon")) + if (block.isBeaconBlock()) { if (isBeaconActive(pos, adjacentChunkHolder)) { @@ -299,21 +291,9 @@ public interface IChunkWrapper extends IBindable IChunkWrapper chunk = chunkHolder.getByBlockPos(beaconPos.x + x, beaconPos.z + z); if (chunk != null) - { - String blockSerial = chunk.getBlockState(baseRelPos.x, baseRelPos.y, baseRelPos.z).getSerialString(); - - boolean baseBlockFound = false; - for (int i = 0; i < BEACON_BASE_BLOCK_NAME_LIST.size(); i++) - { - String baseBlockName = BEACON_BASE_BLOCK_NAME_LIST.get(i); - if (blockSerial.contains(baseBlockName)) - { - baseBlockFound = true; - break; - } - } - - if (!baseBlockFound) + { + IBlockStateWrapper block = chunk.getBlockState(baseRelPos.x, baseRelPos.y, baseRelPos.z); + if (!block.isBeaconBaseBlock()) { return false; } diff --git a/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java b/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java index 1ecea8ab5..58eb1bdb0 100644 --- a/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java +++ b/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java @@ -104,4 +104,11 @@ public class LightingTestBlockStateWrapper implements IBlockStateWrapper @Override public byte getIrisBlockMaterialId() { throw new UnsupportedOperationException("Not Implemented"); } + @Override + public boolean isBeaconBlock() { throw new UnsupportedOperationException("Not Implemented"); } + @Override + public boolean isBeaconBaseBlock() { throw new UnsupportedOperationException("Not Implemented"); } + + + } From b762c0561d5e67e78e723f9b19b3692954e7ede3 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 9 Jul 2024 07:33:17 -0500 Subject: [PATCH 056/104] Add beacon colors --- .../renderer/generic/BeaconRenderHandler.java | 35 ++++++++-- .../distanthorizons/core/util/ColorUtil.java | 5 ++ .../block/IBlockStateWrapper.java | 4 ++ .../chunk/IChunkWrapper.java | 68 ++++++++++++++++--- .../LightingTestBlockStateWrapper.java | 7 ++ 5 files changed, 102 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java index ddcefaf41..0e0243040 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java @@ -25,7 +25,6 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; -import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; @@ -47,6 +46,8 @@ public class BeaconRenderHandler private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + private static final int BEAM_TOP_Y = 6_000; + /** if this is null then the other handler is probably null too, but just in case */ private final BeaconBeamRepo beaconBeamRepo; @@ -79,7 +80,7 @@ public class BeaconRenderHandler // level loading/unloading // //=========================// - public void setBeaconBeamsForChunk(DhChunkPos chunkPos, java.util.List newBeamList) + public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List newBeamList) { // synchronized to prevent two threads from updating the same chunk at the same time synchronized (this) @@ -96,7 +97,7 @@ public class BeaconRenderHandler } // get existing beams - java.util.List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos); + List existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos); HashMap existingBeamByPos = new HashMap<>(existingBeamList.size()); for (int i = 0; i < existingBeamList.size(); i++) { @@ -120,7 +121,13 @@ public class BeaconRenderHandler if (existingBeam != null && newBeam != null) { - // beam still exists in chunk, do nothing + // beam still exists in chunk + if (!existingBeam.color.equals(newBeam.color)) + { + // beam colors were changed + this.beaconBeamRepo.save(newBeam); + this.updateBeaconColor(newBeam); + } } else if (existingBeam == null && newBeam != null) { @@ -176,8 +183,7 @@ public class BeaconRenderHandler { DhApiRenderableBox beaconBox = new DhApiRenderableBox( new DhApiVec3f(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), - new DhApiVec3f(beacon.pos.x+1, 6_000, beacon.pos.z+1), - // TODO calculate color + new DhApiVec3f(beacon.pos.x+1, BEAM_TOP_Y, beacon.pos.z+1), beacon.color ); @@ -210,4 +216,21 @@ public class BeaconRenderHandler }); } + private void updateBeaconColor(BeaconBeamDTO newBeam) + { + DhBlockPos pos = newBeam.pos; + for (int i = 0; i < this.beaconBoxGroup.size(); i++) + { + DhApiRenderableBox box = this.beaconBoxGroup.get(i); + if (box.minPos.x == pos.x + && box.minPos.y == pos.y+1 // plus 1 because the beam starts above the beacon + && box.minPos.z == pos.z) + { + box.color = newBeam.color; + this.beaconBoxGroup.triggerBoxChange(); + break; + } + } + } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java index 222fcbb9b..6e4b3acc9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java @@ -19,6 +19,8 @@ package com.seibel.distanthorizons.core.util; +import java.awt.*; + /** * Handles the bit-wise math used when * dealing with colors stored as integers. @@ -212,4 +214,7 @@ public class ColorUtil ",B:" + getBlue(color); } + public static Color toColorObjRGB(int color) { return new Color(getRed(color), getGreen(color), getBlue(color)); } + public static Color toColorObjRGBA(int color) { return new Color(getRed(color), getGreen(color), getBlue(color), getAlpha(color)); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java index 68fe9a194..8ddef3213 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java @@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.block; import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; +import java.awt.*; import java.util.Arrays; import java.util.List; @@ -92,4 +93,7 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper boolean isBeaconBlock(); boolean isBeaconBaseBlock(); + Color getMapColor(); + boolean isGlassBlock(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index ea774036b..f7062d774 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -29,11 +29,10 @@ import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; import java.util.List; public interface IChunkWrapper extends IBindable @@ -251,7 +250,7 @@ public interface IChunkWrapper extends IBindable default List getAllActiveBeacons(ArrayList neighbourChunkList) { - ArrayList beaconPosList = new ArrayList<>(); + ArrayList beaconBeamList = new ArrayList<>(); AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(this, neighbourChunkList); @@ -266,21 +265,30 @@ public interface IChunkWrapper extends IBindable IBlockStateWrapper block = this.getBlockState(relPos); if (block.isBeaconBlock()) { - if (isBeaconActive(pos, adjacentChunkHolder)) + Color beaconColor = getBeaconColor(pos, adjacentChunkHolder); + if (beaconColor != null) { - BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), Color.WHITE); - beaconPosList.add(beam); + BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), beaconColor); + beaconBeamList.add(beam); } } } - return beaconPosList; + return beaconBeamList; } - static boolean isBeaconActive(DhBlockPos beaconPos, AdjacentChunkHolder chunkHolder) + /** @return Null if the position isn't valid for a beacon beam. */ + @Nullable + static Color getBeaconColor(DhBlockPos beaconPos, AdjacentChunkHolder chunkHolder) { DhBlockPos beaconRelPos = beaconPos.convertToChunkRelativePos(); DhBlockPos baseRelPos = new DhBlockPos(0, beaconRelPos.y-1, 0); + + + //===========================// + // check for the base blocks // + //===========================// + for (int x = -1; x<= 1; x++) { for (int z = -1; z <= 1; z++) @@ -295,15 +303,53 @@ public interface IChunkWrapper extends IBindable IBlockStateWrapper block = chunk.getBlockState(baseRelPos.x, baseRelPos.y, baseRelPos.z); if (!block.isBeaconBaseBlock()) { - return false; + return null; } } } } - // TODO check if the sky is visible - return true; + + //=========================// + // get the beacon color // + // and check for occlusion // + //=========================// + + int red = 0; + int green = 0; + int blue = 0; + boolean glassBlockFound = false; + + IChunkWrapper centerChunk = chunkHolder.getByBlockPos(beaconPos.x, beaconPos.z); + int maxY = centerChunk.getMaxNonEmptyHeight(); + for (int y = beaconRelPos.y+1; y <= maxY; y++) + { + IBlockStateWrapper block = centerChunk.getBlockState(beaconRelPos.x, y, beaconRelPos.z); + if (!block.isAir() && block.getOpacity() == IBlockStateWrapper.FULLY_OPAQUE) + { + return null; + } + + if (block.isGlassBlock() + // ignore invisible blocks (which have pure black as their map color, luckily black stained-glass is actually extremely dark gray) + && !block.getMapColor().equals(Color.BLACK)) + { + red += block.getMapColor().getRed(); + green += block.getMapColor().getGreen(); + blue += block.getMapColor().getBlue(); + + if (glassBlockFound) + { + red /= 2; + green /= 2; + blue /= 2; + } + glassBlockFound = true; + } + } + + return glassBlockFound ? new Color(red, green, blue) : Color.WHITE; } diff --git a/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java b/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java index 58eb1bdb0..269498454 100644 --- a/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java +++ b/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java @@ -22,6 +22,8 @@ package testItems.lightingEngine; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import tests.LightingEngineTest; +import java.awt.*; + /** * @see LightingEngineTest * @see LightingTestChunkWrapper @@ -109,6 +111,11 @@ public class LightingTestBlockStateWrapper implements IBlockStateWrapper @Override public boolean isBeaconBaseBlock() { throw new UnsupportedOperationException("Not Implemented"); } + @Override + public Color getMapColor() { throw new UnsupportedOperationException("Not Implemented"); } + @Override + public boolean isGlassBlock() { throw new UnsupportedOperationException("Not Implemented"); } + } From cd5da82d0ce1b0c235909d9e0109943d8ed76d21 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 9 Jul 2024 07:33:56 -0500 Subject: [PATCH 057/104] Add a TODO to LevelWrapper --- .../core/wrapperInterfaces/world/ILevelWrapper.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java index 25d8858fb..0d3893c0a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/ILevelWrapper.java @@ -64,6 +64,7 @@ public interface ILevelWrapper extends IDhApiLevelWrapper, IBindable /** Fired when the level is being unloaded. Doesn't unload the level. */ void onUnload(); + // TODO I don't like the circular reference, can we merge the level wrapper and DhLevels? @Deprecated void setParentLevel(IDhLevel parentLevel); From 232c727b4fbbd0e3100174824ff60e179e0cc786 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 9 Jul 2024 07:38:45 -0500 Subject: [PATCH 058/104] Move IBlockStateWrapper constants into LodUtil --- .../FullDataToRenderDataTransformer.java | 3 ++- .../transformers/LodDataBuilder.java | 2 +- .../core/generation/DhLightingEngine.java | 3 +-- .../distanthorizons/core/util/LodUtil.java | 23 ++++++++++++++++--- .../block/IBlockStateWrapper.java | 19 +++------------ .../chunk/IChunkWrapper.java | 2 +- .../LightingTestChunkWrapper.java | 2 +- 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index 3f0e29f52..c2b09d258 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -32,6 +32,7 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.ColorUtil; import com.seibel.distanthorizons.core.util.FullDataPointUtil; +import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RenderDataPointUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; @@ -236,7 +237,7 @@ public class FullDataToRenderDataTransformer // solid block check - if (avoidSolidBlocks && !block.isSolid() && !block.isLiquid() && block.getOpacity() != IBlockStateWrapper.FULLY_OPAQUE) + if (avoidSolidBlocks && !block.isSolid() && !block.isLiquid() && block.getOpacity() != LodUtil.BLOCK_FULLY_OPAQUE) { if (colorBelowWithAvoidedBlocks) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index e2dc80925..1fbf49e02 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -297,7 +297,7 @@ public class LodDataBuilder // this block isn't on a chunk boundary, check if it is next to a transparent/air block IBlockStateWrapper blockState = chunkWrapper.getBlockState(testBlockPos); - return blockState.isAir() || blockState.getOpacity() != IBlockStateWrapper.FULLY_OPAQUE; + return blockState.isAir() || blockState.getOpacity() != LodUtil.BLOCK_FULLY_OPAQUE; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java index 34f1cec9b..c160ef482 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/DhLightingEngine.java @@ -26,7 +26,6 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; -import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; import org.apache.logging.log4j.Logger; import java.util.*; @@ -152,7 +151,7 @@ public class DhLightingEngine for (int y = maxY; y >= minY; y--) { IBlockStateWrapper block = chunk.getBlockState(relX, y, relZ); - if (block != null && block.getOpacity() != IBlockStateWrapper.FULLY_TRANSPARENT) + if (block != null && block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT) { // keep moving down until we find a non-transparent block break; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java index 7b43cf6a8..08ec41d1e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java @@ -19,7 +19,9 @@ package com.seibel.distanthorizons.core.util; +import java.util.Arrays; import java.util.Iterator; +import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletionException; import java.util.concurrent.RejectedExecutionException; @@ -33,6 +35,7 @@ import com.seibel.distanthorizons.core.render.vertexFormat.DefaultLodVertexForma import com.seibel.distanthorizons.core.render.vertexFormat.LodVertexFormat; import com.seibel.distanthorizons.core.util.gridList.EdgeDistanceBooleanGrid; import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException; +import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IDimensionTypeWrapper; @@ -66,9 +69,6 @@ public class LodUtil - /** The maximum number of LODs that can be rendered vertically */ - public static final int MAX_NUMBER_OF_VERTICAL_LODS = 32; - /** * alpha used when drawing chunks in debug mode */ @@ -123,6 +123,23 @@ public class LodUtil /** lowest possible light level handled by Minecraft */ public static final byte MIN_MC_LIGHT = 0; + /** the opacity value returned by {@link IBlockStateWrapper#getOpacity()} if a block is fully transparent */ + public static final int BLOCK_FULLY_TRANSPARENT = 0; + /** the opacity value returned by {@link IBlockStateWrapper#getOpacity()} if a block is fully opaque */ + public static final int BLOCK_FULLY_OPAQUE = 16; + + /** + * List of every block that can be used in a beacon's base.
+ * Should be all lowercase + */ + public static final List BEACON_BASE_BLOCK_NAME_LIST = Arrays.asList( + "iron_block", + "gold_block", + "diamond_block", + "emerald_block", + "netherite_block" + ); + /** diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java index 8ddef3213..d2a442008 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java @@ -20,10 +20,9 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.block; import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; +import com.seibel.distanthorizons.core.util.LodUtil; import java.awt.*; -import java.util.Arrays; -import java.util.List; /** A Minecraft version independent way of handling Blocks. */ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper @@ -32,18 +31,6 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper // constants // //===========// - int FULLY_TRANSPARENT = 0; - int FULLY_OPAQUE = 16; - - /** should be all lowercase */ - List BEACON_BASE_BLOCK_NAME_LIST = Arrays.asList( - "iron_block", - "gold_block", - "diamond_block", - "emerald_block", - "netherite_block" - ); - /** contains the indices used by Iris to determine how different block types should be rendered */ class IrisBlockMaterial { @@ -81,8 +68,8 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper * Returning a value of 0 means the block is completely transparent. = IBlockStateWrapper.FULLY_OPAQUE) + if (opacity >= LodUtil.BLOCK_FULLY_OPAQUE) { opacity = 3; } From 1f74f19cd940abba4dd980ea32c028775c9a115d Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 9 Jul 2024 07:49:56 -0500 Subject: [PATCH 059/104] minor cleanup --- .../seibel/distanthorizons/core/level/AbstractDhLevel.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index 0d2a02812..a26200efa 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -260,11 +260,6 @@ public abstract class AbstractDhLevel implements IDhLevel //================// @Override - public void close() - { - this.chunkToLodBuilder.close(); - - GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer(); - } + public void close() { this.chunkToLodBuilder.close(); } } From 066b23c7856b3f1a72792c8d8c65b8ca073b4dba Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 9 Jul 2024 17:40:21 -0500 Subject: [PATCH 060/104] Add toggleable logging for GL Buffer garbage collection Will need to be tested by someone who is experiencing issue #718, so far I've been unable to reproduce anything meaningful. --- .../com/seibel/distanthorizons/core/config/Config.java | 9 +++++++++ .../core/render/glObject/buffer/GLBuffer.java | 6 +++++- .../resources/assets/distanthorizons/lang/en_us.json | 6 +++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 71654580c..a84aba1ad 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -1238,6 +1238,15 @@ public class Config + "") .build(); + public static ConfigEntry logBufferGarbageCollection = new ConfigEntry.Builder() + .set(false) + .comment("" + + "If true OpenGL Buffer garbage collection will be logged \n" + + "this also includes the number of live buffers. \n" + + "") + .build(); + + // Note: This will reset on game restart, and should have a warning on the tooltip public static ConfigEntry allowUnsafeValues = new ConfigEntry.Builder() .set(false) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java index 7d8608a83..bdfee1f4b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/buffer/GLBuffer.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.render.glObject.buffer; import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; +import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.util.LodUtil; @@ -140,7 +141,10 @@ public class GLBuffer implements AutoCloseable GL32.glDeleteBuffers(id); bufferCount.decrementAndGet(); - //LOGGER.info("destroyed buffer ["+id+"], remaining: ["+BUFFER_ID_TO_PHANTOM.size()+"]"); + if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get()) + { + LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]"); + } } }); } diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 08ba41a32..b60a7e5eb 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -474,7 +474,11 @@ "distanthorizons.config.client.advanced.debugging.showOverlappingQuadErrors": "Show overlapping quad errors", "distanthorizons.config.client.advanced.debugging.showOverlappingQuadErrors.@tooltip": - "f true overlapping quads will be rendered as bright red for easy identification. \nIf false the quads will be rendered normally.", + "If true overlapping quads will be rendered as bright red for easy identification. \nIf false the quads will be rendered normally.", + "distanthorizons.config.client.advanced.debugging.logBufferGarbageCollection": + "Log Buffer Garbage Collection", + "distanthorizons.config.client.advanced.debugging.logBufferGarbageCollection.@tooltip": + "If true OpenGL Buffer garbage collection will be logged \nthis also includes the number of live buffers. ", "distanthorizons.config.client.advanced.debugging.allowUnsafeValues": "Allow Unsafe UI Values", "distanthorizons.config.client.advanced.debugging.allowUnsafeValues.@tooltip": From edec8bc0a20b1306516d88f31f44456d07ca3261 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 9 Jul 2024 19:30:59 -0500 Subject: [PATCH 061/104] Update localization --- core/src/main/resources/assets/distanthorizons/lang/en_us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index b60a7e5eb..f3022b402 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -89,7 +89,7 @@ "distanthorizons.config.client.advanced.graphics.quality.maxHorizontalResolution.@tooltip": "The maximum detail LODs are rendered at.\n\n§6Fastest:§r Chunk\n§6Fanciest:§r Block", "distanthorizons.config.client.advanced.graphics.quality.lodChunkRenderDistanceRadius": - "LOD Render Distance Radius", + "LOD Chunk Render Distance Radius", "distanthorizons.config.client.advanced.graphics.quality.lodChunkRenderDistanceRadius.@tooltip": "Distant Horizons' render distance, measured in chunks. \n\nNote: this is a best effort number. \nThe render distance may be above or below this number \ndepending on your other graphic settings.", "distanthorizons.config.client.advanced.graphics.quality.verticalQuality": From 53a2bf1748515d3017d85d3ba15417346cf13d00 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 9 Jul 2024 19:31:14 -0500 Subject: [PATCH 062/104] mark ConfigLinkedEntry localization broken --- .../distanthorizons/core/config/types/ConfigLinkedEntry.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigLinkedEntry.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigLinkedEntry.java index bac72896c..5483f7769 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigLinkedEntry.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigLinkedEntry.java @@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance * * @author coolGi */ +@Deprecated // FIXME doesn't work with localization public class ConfigLinkedEntry extends AbstractConfigType, ConfigLinkedEntry> { public ConfigLinkedEntry(AbstractConfigType value) From 4b27f39a04578977b27576126e7ca4c8bcaaa9d4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 10 Jul 2024 07:37:11 -0500 Subject: [PATCH 063/104] Fix generic rendering at extreme distances --- .../IDhApiCustomRenderObjectFactory.java | 3 +- .../render/IDhApiRenderableBoxGroup.java | 6 +- .../api/objects/math/DhApiVec3d.java | 94 +++++++++++++++ .../objects/render/DhApiRenderableBox.java | 11 +- .../render/glObject/shader/ShaderProgram.java | 6 +- .../renderer/generic/BeaconRenderHandler.java | 5 +- .../renderer/generic/CloudRenderHandler.java | 10 +- .../generic/GenericObjectRenderer.java | 107 ++++++++++-------- .../generic/GenericRenderObjectFactory.java | 8 +- .../renderer/generic/RenderableBoxGroup.java | 59 ++++++---- .../distanthorizons/core/util/LodUtil.java | 9 ++ .../shaders/genericObject/direct/vert.vert | 2 + .../shaders/genericObject/instanced/vert.vert | 41 +++---- 13 files changed, 252 insertions(+), 109 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3d.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java index 7e78e0c60..5b9b7ae66 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.api.interfaces.render; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; @@ -20,7 +21,7 @@ import java.util.List; public interface IDhApiCustomRenderObjectFactory { IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube); - IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList); + IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3d originBlockPos, List cubeList); IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList); } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java index 061f75455..5eda2969f 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -2,7 +2,9 @@ package com.seibel.distanthorizons.api.interfaces.render; import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; @@ -35,9 +37,9 @@ public interface IDhApiRenderableBoxGroup extends List boolean isSsaoEnabled(); /** Sets where this group will render in the level. */ - void setOriginBlockPos(DhApiVec3f pos); + void setOriginBlockPos(DhApiVec3d pos); /** @return the block position in the level that all {@see DhApiRenderableBox} will render relative to. */ - DhApiVec3f getOriginBlockPos(); + DhApiVec3d getOriginBlockPos(); /** * Called right before this group is rendered.
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3d.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3d.java new file mode 100644 index 000000000..9e1344262 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3d.java @@ -0,0 +1,94 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.objects.math; + +/** + * Often used to store block positions or any other + * position in 3D space. + * + * @author James Seibel + * @version 2024-7-9 + * @since API 3.0.0 + */ +public class DhApiVec3d +{ + public double x; + public double y; + public double z; + + + + /** creates a Vec3 at (0,0,0) */ + public DhApiVec3d() + { + this.x = 0; + this.y = 0; + this.z = 0; + } + + public DhApiVec3d(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + else if (obj != null && this.getClass() == obj.getClass()) + { + DhApiVec3d Vec3d = (DhApiVec3d) obj; + if (Double.compare(Vec3d.x, this.x) != 0) + { + return false; + } + else if (Double.compare(Vec3d.y, this.y) != 0) + { + return false; + } + else + { + return Double.compare(Vec3d.z, this.z) == 0; + } + } + else + { + return false; + } + } + + @Override + public int hashCode() + { + long i = Double.doubleToLongBits(this.x); + i = 31 * i + Double.doubleToLongBits(this.y); + i = 31 * i + Double.doubleToLongBits(this.z); + return Long.hashCode(i); + } + + @Override + public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; } + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java index 23e1296d4..a69684e95 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java @@ -2,6 +2,7 @@ package com.seibel.distanthorizons.api.objects.render; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import java.awt.*; @@ -16,9 +17,9 @@ import java.awt.*; public class DhApiRenderableBox { /** the position closest to (-inf,-inf) */ - public DhApiVec3f minPos; + public DhApiVec3d minPos; /** the position closest to (+inf,+inf) */ - public DhApiVec3f maxPos; + public DhApiVec3d maxPos; public Color color; @@ -28,16 +29,16 @@ public class DhApiRenderableBox // constructors // //==============// - public DhApiRenderableBox(DhApiVec3f minPos, float width, Color color) + public DhApiRenderableBox(DhApiVec3d minPos, float width, Color color) { - this(minPos, new DhApiVec3f( + this(minPos, new DhApiVec3d( minPos.x + width, minPos.y + width, minPos.z + width ), color); } - public DhApiRenderableBox(DhApiVec3f minPos, DhApiVec3f maxPos, Color color) + public DhApiRenderableBox(DhApiVec3d minPos, DhApiVec3d maxPos, Color color) { this.minPos = minPos; this.maxPos = maxPos; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java index b7e932e2d..fc821a461 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.List; import java.util.function.Supplier; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import org.lwjgl.opengl.GL32; import org.lwjgl.system.MemoryStack; @@ -195,11 +196,10 @@ public class ShaderProgram { GL32.glUniform3f(location, value.x, value.y, value.z); } - /** Requires ShaderProgram binded. */ - public void setUniform(int location, Vec3d value) + public void setUniform(int location, DhApiVec3i value) { - GL32.glUniform3f(location, (float) value.x, (float) value.y, (float) value.z); + GL32.glUniform3i(location, value.x, value.y, value.z); } /** Requires ShaderProgram binded. */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java index 0e0243040..dd4140b02 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; @@ -182,8 +183,8 @@ public class BeaconRenderHandler if (beaconRefCount.getAndIncrement() == 0) { DhApiRenderableBox beaconBox = new DhApiRenderableBox( - new DhApiVec3f(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), - new DhApiVec3f(beacon.pos.x+1, BEAM_TOP_Y, beacon.pos.z+1), + new DhApiVec3d(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), + new DhApiVec3d(beacon.pos.x+1, BEAM_TOP_Y, beacon.pos.z+1), beacon.color ); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index f7325bfc6..6fa285cfb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; @@ -203,8 +204,8 @@ public class CloudRenderHandler } DhApiRenderableBox box = new DhApiRenderableBox( - new DhApiVec3f(minXBlockPos, 0, minZBlockPos), - new DhApiVec3f(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos), + new DhApiVec3d(minXBlockPos, 0, minZBlockPos), + new DhApiVec3d(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos), color ); boxList.add(box); @@ -231,7 +232,7 @@ public class CloudRenderHandler for (int z = -1; z <= 1; z++) { IDhApiRenderableBoxGroup boxGroup = GenericRenderObjectFactory.INSTANCE.createRelativePositionedGroup( - new DhApiVec3f(0, 0, 0), // the offset will be set during rendering + new DhApiVec3d(0, 0, 0), // the offset will be set during rendering boxList); boxGroup.setBlockLight(LodUtil.MIN_MC_LIGHT); boxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); @@ -265,6 +266,7 @@ public class CloudRenderHandler this.disabledWarningLogged = true; LOGGER.warn("Instanced rendering unavailable, cloud rendering disabled."); } + boxGroup.setActive(false); return; } @@ -311,7 +313,7 @@ public class CloudRenderHandler //==============// boxGroup.setOriginBlockPos( - new DhApiVec3f( + new DhApiVec3d( clouds.xOffset + (clouds.instanceOffsetX * clouds.widthInBlocks) + xOffset + clouds.halfWidthInBlocks, this.level.getLevelWrapper().getMaxHeight() + 200, clouds.zOffset + (clouds.instanceOffsetZ * clouds.widthInBlocks) + zOffset + clouds.halfWidthInBlocks diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 3472f9602..19b2273dd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -24,7 +24,8 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; -import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -93,8 +94,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private int directShaderTransformUniform; private int directShaderColorUniform; - private int instancedShaderOffsetUniform; - private int instancedShaderCameraPosUniform; + private int instancedShaderOffsetChunkUniform; + private int instancedShaderOffsetSubChunkUniform; + private int instancedShaderCameraChunkPosUniform; + private int instancedShaderCameraSubChunkPosUniform; private int instancedShaderProjectionModelViewMatrixUniform; private int lightMapUniform; @@ -213,8 +216,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.directShaderTransformUniform = this.shader.tryGetUniformLocation("uTransform"); this.directShaderColorUniform = this.shader.tryGetUniformLocation("uColor"); - this.instancedShaderOffsetUniform = this.shader.tryGetUniformLocation("uOffset"); - this.instancedShaderCameraPosUniform = this.shader.tryGetUniformLocation("uCameraPos"); + this.instancedShaderOffsetChunkUniform = this.shader.tryGetUniformLocation("uOffsetChunk"); + this.instancedShaderOffsetSubChunkUniform = this.shader.tryGetUniformLocation("uOffsetSubChunk"); + this.instancedShaderCameraChunkPosUniform = this.shader.tryGetUniformLocation("uCameraPosChunk"); + this.instancedShaderCameraSubChunkPosUniform = this.shader.tryGetUniformLocation("uCameraPosSubChunk"); this.instancedShaderProjectionModelViewMatrixUniform = this.shader.tryGetUniformLocation("uProjectionMvm"); this.lightMapUniform = this.shader.getUniformLocation("uLightMap"); @@ -266,7 +271,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single giant box IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox( new DhApiRenderableBox( - new DhApiVec3f(0f,0f,0f), new DhApiVec3f(16f,190f,16f), + new DhApiVec3d(0,0,0), new DhApiVec3d(16,190,16), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) ); singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); @@ -277,7 +282,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single slender box IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox( new DhApiRenderableBox( - new DhApiVec3f(16f,0f,31f), new DhApiVec3f(17f,2000f,32f), + new DhApiVec3d(16,0,31), new DhApiVec3d(17,2000,32), new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) ); singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); @@ -290,7 +295,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int i = 0; i < 18; i++) { absBoxList.add(new DhApiRenderableBox( - new DhApiVec3f(0f+i,150f+i,24f), new DhApiVec3f(1f+i,151f+i,25f), + new DhApiVec3d(i,150+i,24), new DhApiVec3d(1+i,151+i,25), new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); } IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(absBoxList); @@ -302,15 +307,15 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int i = 0; i < 8; i+=2) { relBoxList.add(new DhApiRenderableBox( - new DhApiVec3f(0f,0f+i,0f), new DhApiVec3f(1f,1f+i,1f), + new DhApiVec3d(0,i,0), new DhApiVec3d(1,1+i,1), new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); } IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup( - new DhApiVec3f(24f, 140f, 24f), + new DhApiVec3d(24, 140, 24), relBoxList); relativePosBoxGroup.setPreRenderFunc((event) -> { - DhApiVec3f pos = relativePosBoxGroup.getOriginBlockPos(); + DhApiVec3d pos = relativePosBoxGroup.getOriginBlockPos(); pos.x += event.partialTicks / 2; pos.x %= 32; relativePosBoxGroup.setOriginBlockPos(pos); @@ -325,16 +330,16 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int z = 0; z < 50*2; z+=2) { massRelBoxList.add(new DhApiRenderableBox( - new DhApiVec3f(0f-x, 0f, 0f-z), new DhApiVec3f(1f-x, 1f, 1f-z), + new DhApiVec3d(-x, 0, -z), new DhApiVec3d(1-x, 1, 1-z), new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()))); } } IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup( - new DhApiVec3f(-25f, 140f, 0f), + new DhApiVec3d(-25, 140, 0), massRelBoxList); massRelativePosBoxGroup.setPreRenderFunc((event) -> { - DhApiVec3f blockPos = massRelativePosBoxGroup.getOriginBlockPos(); + DhApiVec3d blockPos = massRelativePosBoxGroup.getOriginBlockPos(); blockPos.y += event.partialTicks / 4; if (blockPos.y > 150f) { @@ -415,8 +420,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister Mat4f projectionMvmMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); projectionMvmMatrix.multiply(renderEventParam.dhModelViewMatrix); - Vec3d camPosDouble = MC_RENDER.getCameraExactPosition(); - Vec3f camPos = new Vec3f((float) camPosDouble.x, (float) camPosDouble.y, (float) camPosDouble.z); + Vec3d camPos = MC_RENDER.getCameraExactPosition(); @@ -467,24 +471,36 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // instanced rendering // //=====================// - private void renderBoxGroupInstanced(RenderableBoxGroup boxGroup, Vec3f camPos, Mat4f projectionMvmMatrix) + private void renderBoxGroupInstanced(RenderableBoxGroup boxGroup, Vec3d camPos, Mat4f projectionMvmMatrix) { // update instance data // boxGroup.updateVertexAttributeData(); - this.shader.setUniform(this.instancedShaderOffsetUniform, + this.shader.setUniform(this.instancedShaderOffsetChunkUniform, + new DhApiVec3i( + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x), + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y), + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z) + )); + this.shader.setUniform(this.instancedShaderOffsetSubChunkUniform, new Vec3f( - boxGroup.getOriginBlockPos().x, - boxGroup.getOriginBlockPos().y, - boxGroup.getOriginBlockPos().z + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x), + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y), + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z) )); - this.shader.setUniform(this.instancedShaderCameraPosUniform, + this.shader.setUniform(this.instancedShaderCameraChunkPosUniform, + new DhApiVec3i( + LodUtil.getChunkPosFromDouble(camPos.x), + LodUtil.getChunkPosFromDouble(camPos.y), + LodUtil.getChunkPosFromDouble(camPos.z) + )); + this.shader.setUniform(this.instancedShaderCameraSubChunkPosUniform, new Vec3f( - camPos.x, - camPos.y, - camPos.z + LodUtil.getSubChunkPosFromDouble(camPos.x), + LodUtil.getSubChunkPosFromDouble(camPos.y), + LodUtil.getSubChunkPosFromDouble(camPos.z) )); this.shader.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, @@ -516,15 +532,20 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0); this.vertexAttribDivisor(1, 1); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceTranslationVbo); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceScaleVbo); GL32.glEnableVertexAttribArray(2); this.vertexAttribDivisor(2, 1); GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceScaleVbo); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceChunkPosVbo); GL32.glEnableVertexAttribArray(3); this.vertexAttribDivisor(3, 1); - GL32.glVertexAttribPointer(3, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); + GL32.glVertexAttribIPointer(3, 3, GL32.GL_INT, 3 * Integer.BYTES, 0); + + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceSubChunkPosVbo); + GL32.glEnableVertexAttribArray(4); + this.vertexAttribDivisor(4, 1); + GL32.glVertexAttribPointer(4, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); // Draw instanced @@ -568,7 +589,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // direct rendering // //==================// - private void renderBoxGroupDirect(RenderableBoxGroup boxGroup, Mat4f transformMatrix, Vec3f camPos) + private void renderBoxGroupDirect(RenderableBoxGroup boxGroup, Mat4f transformMatrix, Vec3d camPos) { this.shader.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); @@ -594,32 +615,22 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } private void renderBox( RenderableBoxGroup boxGroup, DhApiRenderableBox box, - Mat4f transformationMatrix, Vec3f camPos) + Mat4f transformationMatrix, Vec3d camPos) { - float originOffsetX = 0; - float originOffsetY = 0; - float originOffsetZ = 0; - if (boxGroup.positionBoxesRelativeToGroupOrigin) - { - originOffsetX = boxGroup.getOriginBlockPos().x; - originOffsetY = boxGroup.getOriginBlockPos().y; - originOffsetZ = boxGroup.getOriginBlockPos().z; - } - Mat4f boxTransform = Mat4f.createTranslateMatrix( - box.minPos.x + originOffsetX - camPos.x, - box.minPos.y + originOffsetY - camPos.y, - box.minPos.z + originOffsetZ - camPos.z); + (float) (box.minPos.x + boxGroup.getOriginBlockPos().x - camPos.x), + (float) (box.minPos.y + boxGroup.getOriginBlockPos().y - camPos.y), + (float) (box.minPos.z + boxGroup.getOriginBlockPos().z - camPos.z)); boxTransform.multiply(Mat4f.createScaleMatrix( - box.maxPos.x - box.minPos.x, - box.maxPos.y - box.minPos.y, - box.maxPos.z - box.minPos.z)); + (float) (box.maxPos.x - box.minPos.x), + (float) (box.maxPos.y - box.minPos.y), + (float) (box.maxPos.z - box.minPos.z))); Mat4f transformMatrix = transformationMatrix.copy(); transformMatrix.multiply(boxTransform); this.shader.setUniform(this.directShaderTransformUniform, transformMatrix); - + this.shader.setUniform(this.directShaderColorUniform, box.color); - + GL32.glDrawElements(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java index a9234a2c6..263b00ece 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java @@ -22,9 +22,11 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3f; import org.apache.logging.log4j.Logger; @@ -66,11 +68,11 @@ public class GenericRenderObjectFactory implements IDhApiCustomRenderObjectFacto } @Override - public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List boxList) - { return new RenderableBoxGroup(new Vec3f(originBlockPos), boxList, true); } + public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3d originBlockPos, List boxList) + { return new RenderableBoxGroup(new DhApiVec3d(originBlockPos.x, originBlockPos.y, originBlockPos.z), boxList, true); } @Override public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList) - { return new RenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); } + { return new RenderableBoxGroup(new DhApiVec3d(0, 0, 0), boxList, false); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java index 7fc2c74cf..96fff73fa 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java @@ -2,12 +2,11 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; -import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.util.LodUtil; -import com.seibel.distanthorizons.core.util.math.Vec3f; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL32; @@ -36,7 +35,7 @@ public class RenderableBoxGroup private final ArrayList boxList; - private final Vec3f originBlockPos; + private final DhApiVec3d originBlockPos; public boolean active = true; @@ -52,9 +51,11 @@ public class RenderableBoxGroup public Consumer afterRenderFunc; // instance data - public int instanceTranslationVbo = 0; - public int instanceScaleVbo = 0; public int instanceColorVbo = 0; + public int instanceScaleVbo = 0; + public int instanceChunkPosVbo = 0; + public int instanceSubChunkPosVbo = 0; + public int uploadedBoxCount = -1; @@ -65,7 +66,7 @@ public class RenderableBoxGroup public long getId() { return this.id; } @Override - public void setOriginBlockPos(DhApiVec3f pos) + public void setOriginBlockPos(DhApiVec3d pos) { this.originBlockPos.x = pos.x; this.originBlockPos.y = pos.y; @@ -73,7 +74,7 @@ public class RenderableBoxGroup } @Override - public DhApiVec3f getOriginBlockPos() { return new DhApiVec3f(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } + public DhApiVec3d getOriginBlockPos() { return new DhApiVec3d(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } @Override @@ -106,7 +107,7 @@ public class RenderableBoxGroup // constructor // //=============// - public RenderableBoxGroup(Vec3f originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) + public RenderableBoxGroup(DhApiVec3d originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) { this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); this.boxList = new ArrayList<>(boxList); @@ -201,9 +202,10 @@ public class RenderableBoxGroup } this.vertexDataDirty = false; - if (this.instanceTranslationVbo == 0) + if (this.instanceChunkPosVbo == 0) { - this.instanceTranslationVbo = GL32.glGenBuffers(); + this.instanceChunkPosVbo = GL32.glGenBuffers(); + this.instanceSubChunkPosVbo = GL32.glGenBuffers(); this.instanceScaleVbo = GL32.glGenBuffers(); this.instanceColorVbo = GL32.glGenBuffers(); } @@ -214,7 +216,8 @@ public class RenderableBoxGroup // transformation / scaling // - float[] translationData = new float[boxCount * 3]; + int[] chunkPosData = new int[boxCount * 3]; + float[] subChunkPosData = new float[boxCount * 3]; float[] scalingData = new float[boxCount * 3]; for (int i = 0; i < boxCount; i++) { @@ -222,13 +225,17 @@ public class RenderableBoxGroup int dataIndex = i * 3; - translationData[dataIndex] = box.minPos.x; - translationData[dataIndex + 1] = box.minPos.y; - translationData[dataIndex + 2] = box.minPos.z; + chunkPosData[dataIndex] = LodUtil.getChunkPosFromDouble(box.minPos.x); + chunkPosData[dataIndex + 1] = LodUtil.getChunkPosFromDouble(box.minPos.y); + chunkPosData[dataIndex + 2] = LodUtil.getChunkPosFromDouble(box.minPos.z); - scalingData[dataIndex] = box.maxPos.x - box.minPos.x; - scalingData[dataIndex + 1] = box.maxPos.y - box.minPos.y; - scalingData[dataIndex + 2] = box.maxPos.z - box.minPos.z; + subChunkPosData[dataIndex] = LodUtil.getSubChunkPosFromDouble(box.minPos.x); + subChunkPosData[dataIndex + 1] = LodUtil.getSubChunkPosFromDouble(box.minPos.y); + subChunkPosData[dataIndex + 2] = LodUtil.getSubChunkPosFromDouble(box.minPos.z); + + scalingData[dataIndex] = (float) (box.maxPos.x - box.minPos.x); + scalingData[dataIndex + 1] = (float) (box.maxPos.y - box.minPos.y); + scalingData[dataIndex + 2] = (float) (box.maxPos.z - box.minPos.z); } @@ -249,8 +256,10 @@ public class RenderableBoxGroup // Upload transformation matrices - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslationVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translationData ,GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceChunkPosVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, chunkPosData ,GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceSubChunkPosVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, subChunkPosData ,GL32.GL_DYNAMIC_DRAW); GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo); GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW); @@ -273,10 +282,16 @@ public class RenderableBoxGroup { GLProxy.getInstance().queueRunningOnRenderThread(() -> { - if (this.instanceTranslationVbo != 0) + if (this.instanceChunkPosVbo != 0) { - GL32.glDeleteBuffers(this.instanceTranslationVbo); - this.instanceTranslationVbo = 0; + GL32.glDeleteBuffers(this.instanceChunkPosVbo); + this.instanceChunkPosVbo = 0; + } + + if (this.instanceSubChunkPosVbo != 0) + { + GL32.glDeleteBuffers(this.instanceSubChunkPosVbo); + this.instanceSubChunkPosVbo = 0; } if (this.instanceScaleVbo != 0) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java index 08ec41d1e..ad9de0b90 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java @@ -253,6 +253,15 @@ public class LodUtil renderDist * 2 + 1); } + /** Returns the chunk int position for the given double position */ + public static int getChunkPosFromDouble(double value) { return (int) Math.floor(value / CHUNK_WIDTH); } + /** Returns the float position inside the chunk for the given double position */ + public static float getSubChunkPosFromDouble(double value) + { + double chunkPos = Math.floor(value / CHUNK_WIDTH); + return (float) (value - chunkPos * CHUNK_WIDTH); + } + // True if the requested threshold pass, or false otherwise // For details, see: diff --git a/core/src/main/resources/shaders/genericObject/direct/vert.vert b/core/src/main/resources/shaders/genericObject/direct/vert.vert index ec528ae44..55cf5cad7 100644 --- a/core/src/main/resources/shaders/genericObject/direct/vert.vert +++ b/core/src/main/resources/shaders/genericObject/direct/vert.vert @@ -5,6 +5,7 @@ uniform vec4 uColor; uniform int uSkyLight; uniform int uBlockLight; uniform sampler2D uLightMap; + uniform float uNorthShading; uniform float uSouthShading; uniform float uEastShading; @@ -12,6 +13,7 @@ uniform float uWestShading; uniform float uTopShading; uniform float uBottomShading; + in vec3 vPosition; out vec4 fColor; diff --git a/core/src/main/resources/shaders/genericObject/instanced/vert.vert b/core/src/main/resources/shaders/genericObject/instanced/vert.vert index eee0d4142..25231ac39 100644 --- a/core/src/main/resources/shaders/genericObject/instanced/vert.vert +++ b/core/src/main/resources/shaders/genericObject/instanced/vert.vert @@ -1,15 +1,20 @@ #version 330 core layout (location = 1) in vec4 aColor; -layout (location = 2) in vec3 aTranslate; -layout (location = 3) in vec3 aScale; +layout (location = 2) in vec3 aScale; +layout (location = 3) in ivec3 aTranslateChunk; +layout (location = 4) in vec3 aTranslateSubChunk; + +uniform ivec3 uOffsetChunk; +uniform vec3 uOffsetSubChunk; +uniform ivec3 uCameraPosChunk; +uniform vec3 uCameraPosSubChunk; -uniform vec3 uOffset; -uniform vec3 uCameraPos; uniform mat4 uProjectionMvm; uniform int uSkyLight; uniform int uBlockLight; uniform sampler2D uLightMap; + uniform float uNorthShading; uniform float uSouthShading; uniform float uEastShading; @@ -17,6 +22,7 @@ uniform float uWestShading; uniform float uTopShading; uniform float uBottomShading; + in vec3 vPosition; out vec4 fColor; @@ -24,22 +30,19 @@ out vec4 fColor; void main() { // aTranslate - moves the vertex to the boxGroup's relative position - // uOffset - moves the vertex to the boxGroup's position + // uOffset - moves the vertex to the boxGroup's world position // uCameraPos - moves the vertex into camera space - float transX = aTranslate.x + uOffset.x - uCameraPos.x; - float transY = aTranslate.y + uOffset.y - uCameraPos.y; - float transZ = aTranslate.z + uOffset.z - uCameraPos.z; - - float scaleX = aScale.x; - float scaleY = aScale.y; - float scaleZ = aScale.z; + vec3 trans = (aTranslateChunk + uOffsetChunk - uCameraPosChunk) * 16.0f; + // separate float and int values are to fix percission loss at extreme distances from the origin (IE 10,000,000+) + // luckily large translate values minus large cameraPos generally equal values that cleanly fit in a float + trans += (aTranslateSubChunk + uOffsetSubChunk - uCameraPosSubChunk); // combination translation and scaling matrix mat4 transform = mat4( - scaleX, 0.0, 0.0, 0.0, - 0.0, scaleY, 0.0, 0.0, - 0.0, 0.0, scaleZ, 0.0, - transX, transY, transZ, 1.0 + aScale.x, 0.0, 0.0, 0.0, + 0.0, aScale.y, 0.0, 0.0, + 0.0, 0.0, aScale.z, 0.0, + trans.x, trans.y, trans.z, 1.0 ); gl_Position = uProjectionMvm * transform * vec4(vPosition, 1.0); @@ -47,10 +50,10 @@ void main() float blockLight = (float(uBlockLight)+0.5) / 16.0; float skyLight = (float(uSkyLight)+0.5) / 16.0; vec4 lightColor = vec4(texture(uLightMap, vec2(blockLight, skyLight)).xyz, 1.0); - - + + fColor = lightColor * aColor; - + // apply directional shading if (gl_VertexID >= 0 && gl_VertexID < 4) { fColor.rgb *= uNorthShading; } else if (gl_VertexID >= 4 && gl_VertexID < 8) { fColor.rgb *= uSouthShading; } From ef3cd4b43d0906b0b3f098bfc2be56068b154a35 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 10 Jul 2024 07:45:07 -0500 Subject: [PATCH 064/104] Add "IP Only" to multiplayer tooltip --- core/src/main/resources/assets/distanthorizons/lang/en_us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index f3022b402..9ea4fe0c4 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -387,7 +387,7 @@ "distanthorizons.config.client.advanced.multiplayer.serverFolderNameMode": "Server Folder Mode", "distanthorizons.config.client.advanced.multiplayer.serverFolderNameMode.@tooltip": - "Determines the folder format for local multiplayer data.\n\n§6Name Only:§r\nUses the server browser name. Ex: \"Minecraft Server\"\n§6Name IP:§r\n\"Minecraft Server, IP 192.168.1.40\"\n§6Name, IP, Port:§r\n\"Minecraft Server, IP 192.168.1.40:25565\"\n§6Name, IP, Port, MC Version:§r\n\"Minecraft Server, IP 192.168.1.40:25565, GameVersion 1.18.1\"\n\n§c§lCaution:§r changing while connected to a multiplayer server may cause glitches.", + "Determines the folder format for local multiplayer data.\n\n§6Name Only:§r\nUses the server browser name. Ex: \"Minecraft Server\"\n§6IP Only:§r\n\"192.168.1.40\"\n§6Name IP:§r\n\"Minecraft Server, IP 192.168.1.40\"\n§6Name, IP, Port:§r\n\"Minecraft Server, IP 192.168.1.40:25565\"\n§6Name, IP, Port, MC Version:§r\n\"Minecraft Server, IP 192.168.1.40:25565, GameVersion 1.18.1\"\n\n§c§lCaution:§r changing while connected to a multiplayer server may cause glitches.", "distanthorizons.config.client.advanced.multiplayer.multiverseSimilarityRequiredPercent": "Multiverse Required Similarity %", "distanthorizons.config.client.advanced.multiplayer.multiverseSimilarityRequiredPercent.@tooltip": From 116df0d99938ad16779acee9ef1f792b3a21e39d Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 16:35:38 -0500 Subject: [PATCH 065/104] Add IDhApiGenericObjectShaderProgram --- .../IDhApiGenericObjectShaderProgram.java | 78 ++++++ .../render/renderer/LodRenderProgram.java | 2 - .../generic/GenericObjectRenderer.java | 164 +++---------- .../generic/GenericObjectShaderProgram.java | 229 ++++++++++++++++++ .../distanthorizons/core/util/math/Vec3d.java | 137 +---------- 5 files changed, 348 insertions(+), 262 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectShaderProgram.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java new file mode 100644 index 000000000..0c5fcbd38 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java @@ -0,0 +1,78 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.interfaces.override.rendering; + +import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; + +/** + * @author James Seibel + * @version 2024-7-11 + * @since API 3.0.0 + */ +public interface IDhApiGenericObjectShaderProgram extends IDhApiOverrideable +{ + + /** + * If this method is called that means this program has the highest priority as defined by {@link IDhApiOverrideable#getPriority()} + * and gets to decide if it wants to be used to render this frame or not.

+ * + * If this method returns true then this program will be used for this frame.
+ * If this returns false then the default DH {@link IDhApiGenericObjectShaderProgram} will be used instead. + */ + boolean overrideThisFrame(); + + /** @return the OpenGL ID for this shader program */ + int getId(); + + /** Free any OpenGL objects owned by this program. */ + void free(); + + /** Runs any necessary binding this program needs so rendering can be done. */ + void bind(); + /** Runs any necessary unbinding this program needs so rendering can be done by another program. */ + void unbind(); + + /** Binds the given Vertex Buffer Object to this shader program for rendering. */ + void bindVertexBuffer(int vbo); + + + /** sets up the necessary uniforms for rendering */ + void fillIndirectUniformData( + DhApiRenderParam renderParameters, + DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup, + DhApiVec3d camPos); + + /** sets up the necessary uniforms for rendering */ + void fillSharedDirectUniformData( + DhApiRenderParam renderParameters, + DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup, + DhApiVec3d camPos); + void fillDirectUniformData( + DhApiRenderParam renderParameters, + IDhApiRenderableBoxGroup boxGroup, DhApiRenderableBox box, + DhApiVec3d camPos); + + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java index 7f63649c5..c7fbdd6cc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java @@ -164,8 +164,6 @@ public class LodRenderProgram extends ShaderProgram implements IDhApiShaderProgr @Override public void bindVertexBuffer(int vbo) { this.vao.bindBufferToAllBindingPoints(vbo); } - public void unbindVertexBuffer() { this.vao.unbindBuffersFromAllBindingPoint(); } - @Override public void fillUniformData(DhApiRenderParam renderParameters) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 19b2273dd..2264cf1ac 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -21,11 +21,11 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; -import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -36,15 +36,11 @@ import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLState; import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer; import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer; -import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; -import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute; -import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; -import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Vec3d; -import com.seibel.distanthorizons.core.util.math.Vec3f; +import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.opengl.ARBInstancedArrays; @@ -80,37 +76,15 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // rendering setup private boolean init = false; - private ShaderProgram shader; + private IDhApiGenericObjectShaderProgram shaderProgram; private GLVertexBuffer boxVertexBuffer; private GLElementBuffer boxIndexBuffer; - private AbstractVertexAttribute va; private boolean useInstancedRendering; private boolean vertexAttribDivisorSupported; private boolean instancedArraysSupported; - // shader uniforms - private int directShaderTransformUniform; - private int directShaderColorUniform; - - private int instancedShaderOffsetChunkUniform; - private int instancedShaderOffsetSubChunkUniform; - private int instancedShaderCameraChunkPosUniform; - private int instancedShaderCameraSubChunkPosUniform; - private int instancedShaderProjectionModelViewMatrixUniform; - - private int lightMapUniform; - private int skyLightUniform; - private int blockLightUniform; - - private int northShadingUniform; - private int southShadingUniform; - private int eastShadingUniform; - private int westShadingUniform; - private int topShadingUniform; - private int bottomShadingUniform; - private final ConcurrentHashMap boxGroupById = new ConcurrentHashMap<>(); @@ -201,37 +175,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering will be slow."); } - - this.va = AbstractVertexAttribute.create(); - this.va.bind(); - // Pos - this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false)); - this.va.completeAndCheck(Float.BYTES * 3); - - this.shader = new ShaderProgram( - this.useInstancedRendering ? "shaders/genericObject/instanced/vert.vert" : "shaders/genericObject/direct/vert.vert", - this.useInstancedRendering ? "shaders/genericObject/instanced/frag.frag" : "shaders/genericObject/direct/frag.frag", - "fragColor", new String[]{"vPosition"}); - - this.directShaderTransformUniform = this.shader.tryGetUniformLocation("uTransform"); - this.directShaderColorUniform = this.shader.tryGetUniformLocation("uColor"); - - this.instancedShaderOffsetChunkUniform = this.shader.tryGetUniformLocation("uOffsetChunk"); - this.instancedShaderOffsetSubChunkUniform = this.shader.tryGetUniformLocation("uOffsetSubChunk"); - this.instancedShaderCameraChunkPosUniform = this.shader.tryGetUniformLocation("uCameraPosChunk"); - this.instancedShaderCameraSubChunkPosUniform = this.shader.tryGetUniformLocation("uCameraPosSubChunk"); - this.instancedShaderProjectionModelViewMatrixUniform = this.shader.tryGetUniformLocation("uProjectionMvm"); - - this.lightMapUniform = this.shader.getUniformLocation("uLightMap"); - this.skyLightUniform = this.shader.getUniformLocation("uSkyLight"); - this.blockLightUniform = this.shader.getUniformLocation("uBlockLight"); - //this.shadingModeUniform = this.shader.getUniformLocation("uShadingMode"); - this.northShadingUniform = this.shader.getUniformLocation("uNorthShading"); - this.southShadingUniform = this.shader.getUniformLocation("uSouthShading"); - this.eastShadingUniform = this.shader.getUniformLocation("uEastShading"); - this.westShadingUniform = this.shader.getUniformLocation("uWestShading"); - this.topShadingUniform = this.shader.getUniformLocation("uTopShading"); - this.bottomShadingUniform = this.shader.getUniformLocation("uBottomShading"); + this.shaderProgram = new GenericObjectShaderProgram(this.useInstancedRendering); this.createBuffers(); @@ -411,15 +355,18 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GL32.glBlendEquation(GL32.GL_FUNC_ADD); GL32.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); - this.shader.bind(); - this.va.bind(); - this.va.bindBufferToAllBindingPoints(this.boxVertexBuffer.getId()); + IDhApiGenericObjectShaderProgram shaderProgram = this.shaderProgram; + IDhApiGenericObjectShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiGenericObjectShaderProgram.class); + if (shaderProgramOverride != null && shaderProgram.overrideThisFrame()) + { + shaderProgram = shaderProgramOverride; + } + + shaderProgram.bind(); + shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId()); this.boxIndexBuffer.bind(); - Mat4f projectionMvmMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); - projectionMvmMatrix.multiply(renderEventParam.dhModelViewMatrix); - Vec3d camPos = MC_RENDER.getCameraExactPosition(); @@ -441,12 +388,12 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister if (this.useInstancedRendering) { profiler.popPush("rendering"); - this.renderBoxGroupInstanced(boxGroup, camPos, projectionMvmMatrix); + this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos); } else { profiler.popPush("rendering"); - this.renderBoxGroupDirect(boxGroup, projectionMvmMatrix, camPos); + this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos); } boxGroup.postRender(renderEventParam); @@ -459,7 +406,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // clean up // profiler.popPush("cleanup"); - this.shader.unbind(); + shaderProgram.unbind(); glState.restore(); profiler.pop(); @@ -471,57 +418,22 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // instanced rendering // //=====================// - private void renderBoxGroupInstanced(RenderableBoxGroup boxGroup, Vec3d camPos, Mat4f projectionMvmMatrix) + private void renderBoxGroupInstanced(IDhApiGenericObjectShaderProgram shaderProgram, DhApiRenderParam renderEventParam, RenderableBoxGroup boxGroup, Vec3d camPos) { // update instance data // boxGroup.updateVertexAttributeData(); - this.shader.setUniform(this.instancedShaderOffsetChunkUniform, - new DhApiVec3i( - LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x), - LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y), - LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z) - )); - this.shader.setUniform(this.instancedShaderOffsetSubChunkUniform, - new Vec3f( - LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x), - LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y), - LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z) - )); - - this.shader.setUniform(this.instancedShaderCameraChunkPosUniform, - new DhApiVec3i( - LodUtil.getChunkPosFromDouble(camPos.x), - LodUtil.getChunkPosFromDouble(camPos.y), - LodUtil.getChunkPosFromDouble(camPos.z) - )); - this.shader.setUniform(this.instancedShaderCameraSubChunkPosUniform, - new Vec3f( - LodUtil.getSubChunkPosFromDouble(camPos.x), - LodUtil.getSubChunkPosFromDouble(camPos.y), - LodUtil.getSubChunkPosFromDouble(camPos.z) - )); - - this.shader.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, - projectionMvmMatrix); - - this.shader.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in - this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); - this.shader.setUniform(this.blockLightUniform, boxGroup.blockLight); - DhApiRenderableBoxGroupShading shading = boxGroup.shading; if (shading == null) { shading = DhApiRenderableBoxGroupShading.getUnshaded(); } - this.shader.setUniform(this.northShadingUniform, shading.north); - this.shader.setUniform(this.southShadingUniform, shading.south); - this.shader.setUniform(this.eastShadingUniform, shading.east); - this.shader.setUniform(this.westShadingUniform, shading.west); - this.shader.setUniform(this.topShadingUniform, shading.top); - this.shader.setUniform(this.bottomShadingUniform, shading.bottom); + shaderProgram.fillIndirectUniformData( + renderEventParam, + shading, boxGroup, + camPos); @@ -589,48 +501,28 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // direct rendering // //==================// - private void renderBoxGroupDirect(RenderableBoxGroup boxGroup, Mat4f transformMatrix, Vec3d camPos) + private void renderBoxGroupDirect(IDhApiGenericObjectShaderProgram shaderProgram, DhApiRenderParam renderEventParam, RenderableBoxGroup boxGroup, Vec3d camPos) { - this.shader.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in - this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); - this.shader.setUniform(this.blockLightUniform, boxGroup.blockLight); - DhApiRenderableBoxGroupShading shading = boxGroup.shading; if (shading == null) { shading = DhApiRenderableBoxGroupShading.getUnshaded(); } - this.shader.setUniform(this.northShadingUniform, shading.north); - this.shader.setUniform(this.southShadingUniform, shading.south); - this.shader.setUniform(this.eastShadingUniform, shading.east); - this.shader.setUniform(this.westShadingUniform, shading.west); - this.shader.setUniform(this.topShadingUniform, shading.top); - this.shader.setUniform(this.bottomShadingUniform, shading.bottom); + shaderProgram.fillSharedDirectUniformData(renderEventParam, shading, boxGroup, camPos); for (DhApiRenderableBox box : boxGroup) { - this.renderBox(boxGroup, box, transformMatrix, camPos); + this.renderBox(shaderProgram, renderEventParam, boxGroup, box, camPos); } } private void renderBox( + IDhApiGenericObjectShaderProgram shaderProgram, + DhApiRenderParam renderEventParam, RenderableBoxGroup boxGroup, DhApiRenderableBox box, - Mat4f transformationMatrix, Vec3d camPos) + Vec3d camPos) { - Mat4f boxTransform = Mat4f.createTranslateMatrix( - (float) (box.minPos.x + boxGroup.getOriginBlockPos().x - camPos.x), - (float) (box.minPos.y + boxGroup.getOriginBlockPos().y - camPos.y), - (float) (box.minPos.z + boxGroup.getOriginBlockPos().z - camPos.z)); - boxTransform.multiply(Mat4f.createScaleMatrix( - (float) (box.maxPos.x - box.minPos.x), - (float) (box.maxPos.y - box.minPos.y), - (float) (box.maxPos.z - box.minPos.z))); - Mat4f transformMatrix = transformationMatrix.copy(); - transformMatrix.multiply(boxTransform); - this.shader.setUniform(this.directShaderTransformUniform, transformMatrix); - - this.shader.setUniform(this.directShaderColorUniform, box.color); - + shaderProgram.fillDirectUniformData(renderEventParam, boxGroup, box, camPos); GL32.glDrawElements(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectShaderProgram.java new file mode 100644 index 000000000..d51b2a647 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectShaderProgram.java @@ -0,0 +1,229 @@ +package com.seibel.distanthorizons.core.render.renderer.generic; + +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; +import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute; +import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer; +import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.util.math.Vec3f; + +public class GenericObjectShaderProgram extends ShaderProgram implements IDhApiGenericObjectShaderProgram +{ + public static final String VERTEX_SHADER_INSTANCED_PATH = "shaders/genericObject/instanced/vert.vert"; + public static final String VERTEX_SHADER_DIRECT_PATH = "shaders/genericObject/direct/vert.vert"; + public static final String FRAGMENT_SHADER_INSTANCED_PATH = "shaders/genericObject/instanced/frag.frag"; + public static final String FRAGMENT_SHADER_DIRECT_PATH = "shaders/genericObject/direct/frag.frag"; + + public final AbstractVertexAttribute va; + + + // shader uniforms + private final int directShaderTransformUniform; + private final int directShaderColorUniform; + + private final int instancedShaderOffsetChunkUniform; + private final int instancedShaderOffsetSubChunkUniform; + private final int instancedShaderCameraChunkPosUniform; + private final int instancedShaderCameraSubChunkPosUniform; + private final int instancedShaderProjectionModelViewMatrixUniform; + + private final int lightMapUniform; + private final int skyLightUniform; + private final int blockLightUniform; + + private final int northShadingUniform; + private final int southShadingUniform; + private final int eastShadingUniform; + private final int westShadingUniform; + private final int topShadingUniform; + private final int bottomShadingUniform; + + + + //=============// + // constructor // + //=============// + + public GenericObjectShaderProgram(boolean useInstancedRendering) + { + super( + useInstancedRendering ? VERTEX_SHADER_INSTANCED_PATH : VERTEX_SHADER_DIRECT_PATH, + useInstancedRendering ? FRAGMENT_SHADER_INSTANCED_PATH : FRAGMENT_SHADER_DIRECT_PATH, + "fragColor", new String[]{"vPosition"}); + + this.va = AbstractVertexAttribute.create(); + this.va.bind(); + // Pos + this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false)); + this.va.completeAndCheck(Float.BYTES * 3); + + this.directShaderTransformUniform = this.tryGetUniformLocation("uTransform"); + this.directShaderColorUniform = this.tryGetUniformLocation("uColor"); + + this.instancedShaderOffsetChunkUniform = this.tryGetUniformLocation("uOffsetChunk"); + this.instancedShaderOffsetSubChunkUniform = this.tryGetUniformLocation("uOffsetSubChunk"); + this.instancedShaderCameraChunkPosUniform = this.tryGetUniformLocation("uCameraPosChunk"); + this.instancedShaderCameraSubChunkPosUniform = this.tryGetUniformLocation("uCameraPosSubChunk"); + this.instancedShaderProjectionModelViewMatrixUniform = this.tryGetUniformLocation("uProjectionMvm"); + + this.lightMapUniform = this.getUniformLocation("uLightMap"); + this.skyLightUniform = this.getUniformLocation("uSkyLight"); + this.blockLightUniform = this.getUniformLocation("uBlockLight"); + this.northShadingUniform = this.getUniformLocation("uNorthShading"); + this.southShadingUniform = this.getUniformLocation("uSouthShading"); + this.eastShadingUniform = this.getUniformLocation("uEastShading"); + this.westShadingUniform = this.getUniformLocation("uWestShading"); + this.topShadingUniform = this.getUniformLocation("uTopShading"); + this.bottomShadingUniform = this.getUniformLocation("uBottomShading"); + + } + + + + //=========// + // methods // + //=========// + + @Override + public void bind() + { + super.bind(); + this.va.bind(); + } + @Override + public void unbind() + { + super.unbind(); + this.va.unbind(); + } + + @Override + public void free() + { + this.va.free(); + super.free(); + } + + @Override + public void bindVertexBuffer(int vbo) { this.va.bindBufferToAllBindingPoints(vbo); } + + @Override + public void fillIndirectUniformData( + DhApiRenderParam renderParameters, + DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup, + DhApiVec3d camPos + ) + { + Mat4f projectionMvmMatrix = new Mat4f(renderParameters.dhProjectionMatrix); + projectionMvmMatrix.multiply(renderParameters.dhModelViewMatrix); + + super.bind(); + + + + + this.setUniform(this.instancedShaderOffsetChunkUniform, + new DhApiVec3i( + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x), + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y), + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z) + )); + this.setUniform(this.instancedShaderOffsetSubChunkUniform, + new Vec3f( + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x), + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y), + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z) + )); + + this.setUniform(this.instancedShaderCameraChunkPosUniform, + new DhApiVec3i( + LodUtil.getChunkPosFromDouble(camPos.x), + LodUtil.getChunkPosFromDouble(camPos.y), + LodUtil.getChunkPosFromDouble(camPos.z) + )); + this.setUniform(this.instancedShaderCameraSubChunkPosUniform, + new Vec3f( + LodUtil.getSubChunkPosFromDouble(camPos.x), + LodUtil.getSubChunkPosFromDouble(camPos.y), + LodUtil.getSubChunkPosFromDouble(camPos.z) + )); + + this.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, projectionMvmMatrix); + + this.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in + this.setUniform(this.skyLightUniform, boxGroup.getSkyLight()); + this.setUniform(this.blockLightUniform, boxGroup.getBlockLight()); + + + this.setUniform(this.northShadingUniform, shading.north); + this.setUniform(this.southShadingUniform, shading.south); + this.setUniform(this.eastShadingUniform, shading.east); + this.setUniform(this.westShadingUniform, shading.west); + this.setUniform(this.topShadingUniform, shading.top); + this.setUniform(this.bottomShadingUniform, shading.bottom); + + + } + + + @Override + public void fillSharedDirectUniformData( + DhApiRenderParam renderParameters, + DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup, + DhApiVec3d camPos) + { + + this.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in + this.setUniform(this.skyLightUniform, boxGroup.getSkyLight()); + this.setUniform(this.blockLightUniform, boxGroup.getBlockLight()); + + + this.setUniform(this.northShadingUniform, shading.north); + this.setUniform(this.southShadingUniform, shading.south); + this.setUniform(this.eastShadingUniform, shading.east); + this.setUniform(this.westShadingUniform, shading.west); + this.setUniform(this.topShadingUniform, shading.top); + this.setUniform(this.bottomShadingUniform, shading.bottom); + + } + + public void fillDirectUniformData( + DhApiRenderParam renderParameters, + IDhApiRenderableBoxGroup boxGroup, DhApiRenderableBox box, + DhApiVec3d camPos) + { + Mat4f projectionMvmMatrix = new Mat4f(renderParameters.dhProjectionMatrix); + projectionMvmMatrix.multiply(renderParameters.dhModelViewMatrix); + + Mat4f boxTransform = Mat4f.createTranslateMatrix( + (float) (box.minPos.x + boxGroup.getOriginBlockPos().x - camPos.x), + (float) (box.minPos.y + boxGroup.getOriginBlockPos().y - camPos.y), + (float) (box.minPos.z + boxGroup.getOriginBlockPos().z - camPos.z)); + boxTransform.multiply(Mat4f.createScaleMatrix( + (float) (box.maxPos.x - box.minPos.x), + (float) (box.maxPos.y - box.minPos.y), + (float) (box.maxPos.z - box.minPos.z))); + projectionMvmMatrix.multiply(boxTransform); + this.setUniform(this.directShaderTransformUniform, projectionMvmMatrix); + + this.setUniform(this.directShaderColorUniform, box.color); + + } + + + + @Override + public int getId() { return this.id; } + + /** The base DH render program should always render */ + @Override + public boolean overrideThisFrame() { return true; } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3d.java b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3d.java index 1eb4da89a..57911612f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3d.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/math/Vec3d.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.util.math; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.coreapi.util.MathUtil; /** @@ -29,7 +30,7 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil; * @author James Seibel * @version 11-18-2021 */ -public class Vec3d +public class Vec3d extends DhApiVec3d { public static Vec3d XNeg = new Vec3d(-1.0F, 0.0F, 0.0F); public static Vec3d XPos = new Vec3d(1.0F, 0.0F, 0.0F); @@ -40,16 +41,13 @@ public class Vec3d public static final Vec3d ZERO_VECTOR = new Vec3d(0.0D, 0.0D, 0.0D); - public double x; - public double y; - public double z; + //==============// + // constructors // + //==============// - public Vec3d() - { - - } + public Vec3d() { } public Vec3d(double x, double y, double z) { @@ -58,47 +56,11 @@ public class Vec3d this.z = z; } - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - else if (obj != null && this.getClass() == obj.getClass()) - { - Vec3d Vec3f = (Vec3d) obj; - if (Double.compare(Vec3f.x, this.x) != 0) - { - return false; - } - else if (Double.compare(Vec3f.y, this.y) != 0) - { - return false; - } - else - { - return Double.compare(Vec3f.z, this.z) == 0; - } - } - else - { - return false; - } - } - @Override - public int hashCode() - { - long longVal = Double.doubleToLongBits(this.x); - - int intVal = (int) (longVal ^ longVal >>> 32); - longVal = Double.doubleToLongBits(this.y); - intVal = 31 * intVal + (int) (longVal ^ longVal >>> 32); - longVal = Double.doubleToLongBits(this.z); - - return 31 * intVal + (int) (longVal ^ longVal >>> 32); - } + + //=========// + // methods // + //=========// public void mul(double scalar) { @@ -149,10 +111,7 @@ public class Vec3d this.z -= vector.z; } - public double dotProduct(Vec3d vector) - { - return this.x * vector.x + this.y * vector.y + this.z * vector.z; - } + public double dotProduct(Vec3d vector) { return this.x * vector.x + this.y * vector.y + this.z * vector.z; } public Vec3d normalize() { @@ -173,80 +132,10 @@ public class Vec3d this.z = f * f4 - f1 * f3; } - /* Matrix3f is not currently needed/implemented - public void transform(Matrix3f p_229188_1_) - { - double f = this.x; - double f1 = this.y; - double f2 = this.z; - this.x = p_229188_1_.m00 * f + p_229188_1_.m01 * f1 + p_229188_1_.m02 * f2; - this.y = p_229188_1_.m10 * f + p_229188_1_.m11 * f1 + p_229188_1_.m12 * f2; - this.z = p_229188_1_.m20 * f + p_229188_1_.m21 * f1 + p_229188_1_.m22 * f2; - } - */ - - /* Quaternions are not currently needed/implemented - public void transform(Quaternion p_214905_1_) - { - Quaternion quaternion = new Quaternion(p_214905_1_); - quaternion.mul(new Quaternion(this.x(), this.y(), this.z(), 0.0F)); - Quaternion quaternion1 = new Quaternion(p_214905_1_); - quaternion1.conj(); - quaternion.mul(quaternion1); - this.set(quaternion.i(), quaternion.j(), quaternion.k()); - } - */ - - /* not currently needed - * percent may actually be partial ticks (which is available when rendering) - public void linearInterp(Vec3f resultingVector, double percent) - { - double f = 1.0F - percent; - this.x = this.x * f + resultingVector.x * percent; - this.y = this.y * f + resultingVector.y * percent; - this.z = this.z * f + resultingVector.z * percent; - } - */ - - /* Quaternions are not currently needed/implemented - public Quaternion rotation(double p_229193_1_) - { - return new Quaternion(this, p_229193_1_, false); - } - - - @OnlyIn(Dist.CLIENT) - public Quaternion rotationDegrees(double p_229187_1_) - { - return new Quaternion(this, p_229187_1_, true); - } - */ - - public Vec3d copy() - { - return new Vec3d(this.x, this.y, this.z); - } - - /* not currently needed/implemented - public void map(double2doubleFunction p_229191_1_) - { - this.x = p_229191_1_.get(this.x); - this.y = p_229191_1_.get(this.y); - this.z = p_229191_1_.get(this.z); - } - */ - - @Override - public String toString() - { - return "[" + this.x + ", " + this.y + ", " + this.z + "]"; - } + public Vec3d copy() { return new Vec3d(this.x, this.y, this.z); } // Forge start - public Vec3d(double[] values) - { - set(values); - } + public Vec3d(double[] values) { this.set(values); } public void set(double[] values) { From c178afa4b937e26028921c2ef36221d41d4db28f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 16:40:32 -0500 Subject: [PATCH 066/104] Minor refactoring/renaming --- .../rendering/IDhApiGenericObjectShaderProgram.java | 2 ++ .../interfaces/override/rendering/IDhApiShaderProgram.java | 2 ++ .../{LodRenderProgram.java => DhTerrainShaderProgram.java} | 7 +++++-- .../distanthorizons/core/render/renderer/LodRenderer.java | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) rename core/src/main/java/com/seibel/distanthorizons/core/render/renderer/{LodRenderProgram.java => DhTerrainShaderProgram.java} (97%) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java index 0c5fcbd38..b521345da 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java @@ -27,6 +27,8 @@ import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; /** + * @see IDhApiShaderProgram + * * @author James Seibel * @version 2024-7-11 * @since API 3.0.0 diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java index 61e853b06..6844715cf 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShaderProgram.java @@ -24,6 +24,8 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; /** + * @see IDhApiGenericObjectShaderProgram + * * @author James Seibel * @version 2024-1-24 * @since API 2.0.0 diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhTerrainShaderProgram.java similarity index 97% rename from core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java rename to core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhTerrainShaderProgram.java index c7fbdd6cc..3f5f4a753 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhTerrainShaderProgram.java @@ -35,7 +35,10 @@ import com.seibel.distanthorizons.core.util.RenderUtil; import com.seibel.distanthorizons.core.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Vec3f; -public class LodRenderProgram extends ShaderProgram implements IDhApiShaderProgram +/** + * Handles rendering the normal LOD terrain. + */ +public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShaderProgram { public static final String VERTEX_SHADER_PATH = "shaders/standard.vert"; public static final String VERTEX_CURVE_SHADER_PATH = "shaders/curve.vert"; @@ -73,7 +76,7 @@ public class LodRenderProgram extends ShaderProgram implements IDhApiShaderProgr //=============// // This will bind AbstractVertexAttribute - public LodRenderProgram() + public DhTerrainShaderProgram() { super(() -> Shader.loadFile(Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get() != 0 ? VERTEX_CURVE_SHADER_PATH : VERTEX_SHADER_PATH, false, new StringBuilder()).toString(), diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 4648be93b..98835b259 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -645,7 +645,7 @@ public class LodRenderer this.fogConfig = newFogConfig; this.lodRenderProgram.free(); - this.lodRenderProgram = new LodRenderProgram(); + this.lodRenderProgram = new DhTerrainShaderProgram(); FogShader.INSTANCE.free(); FogShader.INSTANCE = new FogShader(newFogConfig); @@ -685,7 +685,7 @@ public class LodRenderer EVENT_LOGGER.info("Setting up renderer"); this.isSetupComplete = true; - this.lodRenderProgram = new LodRenderProgram(); + this.lodRenderProgram = new DhTerrainShaderProgram(); if (ENABLE_IBO) { this.quadIBO = new QuadElementBuffer(); From 8eceeb0226b87ae0e6764dd5b9248f2eb427c24b Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 17:20:02 -0500 Subject: [PATCH 067/104] Add namespace/path to generic rendering (including F3 piechart) --- .../IDhApiCustomRenderObjectFactory.java | 46 +++++++++++++++++-- .../render/IDhApiRenderableBoxGroup.java | 29 +++++++++++- .../renderer/generic/BeaconRenderHandler.java | 3 +- .../generic/GenericObjectRenderer.java | 14 ++++-- .../generic/GenericRenderObjectFactory.java | 12 ++--- .../renderer/generic/RenderableBoxGroup.java | 22 ++++++++- 6 files changed, 111 insertions(+), 15 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java index 5b9b7ae66..334c3edd1 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java @@ -20,8 +20,48 @@ import java.util.List; */ public interface IDhApiCustomRenderObjectFactory { - IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube); - IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3d originBlockPos, List cubeList); - IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList); + /** + * Creates a {@link IDhApiRenderableBoxGroup} from for the given {@link DhApiRenderableBox} + * where the box is positioned relative to the level's origin. + * + * @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds" + * + * @see DhApiRenderableBox + * @see IDhApiRenderableBoxGroup#getResourceLocationNamespace() + * @see IDhApiRenderableBoxGroup#getResourceLocationPath() + * + * @throws IllegalArgumentException if resourceLocation is null, isn't separated by a colon, or has multiple colons. + */ + IDhApiRenderableBoxGroup createForSingleBox(String resourceLocation, DhApiRenderableBox cube) throws IllegalArgumentException; + + /** + * Creates a {@link IDhApiRenderableBoxGroup} from the given list of {@link DhApiRenderableBox} where each + * one is positioned relative to given originBlockPos, which in turn is relative to the level's origin. + * + * @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds" + * @param originBlockPos The starting position for this {@link IDhApiRenderableBoxGroup}, can be changed during runtime. + * + * + * @see DhApiRenderableBox + * @see IDhApiRenderableBoxGroup#getResourceLocationNamespace() + * @see IDhApiRenderableBoxGroup#getResourceLocationPath() + * + * @throws IllegalArgumentException if resourceLocation is null, isn't separated by a colon, or has multiple colons. + */ + IDhApiRenderableBoxGroup createRelativePositionedGroup(String resourceLocation, DhApiVec3d originBlockPos, List cubeList); + + /** + * Creates a {@link IDhApiRenderableBoxGroup} from the given list of {@link DhApiRenderableBox} where each + * one is positioned relative to the level's origin. + * + * @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds" + * + * @see DhApiRenderableBox + * @see IDhApiRenderableBoxGroup#getResourceLocationNamespace() + * @see IDhApiRenderableBoxGroup#getResourceLocationPath() + * + * @throws IllegalArgumentException if resourceLocation is null, isn't separated by a colon, or has multiple colons. + */ + IDhApiRenderableBoxGroup createAbsolutePositionedGroup(String resourceLocation, List cubeList); } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java index 5eda2969f..399ba1571 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -23,9 +23,36 @@ import java.util.function.Consumer; */ public interface IDhApiRenderableBoxGroup extends List { - /** @return the ID for this specific group */ + /** + * A unique numerical ID used by DH during rendering. + * This can also be used to bind/unbind specific {@link IDhApiRenderableBoxGroup}'s from the renderer. + * @return the ID for this specific group + */ long getId(); + /** + * Used to determine which mods have added what to the DH renderer. + * This can be used both by the F3 pie chart so you as a mod developer can profile your code + * or by shader developers who want to render your objects differently.

+ * + * Should be used the same as a vanilla Minecraft ResourceLocation. + * For example if your mod named "Heavy Thunder" adds additional clouds named "Storm Front", + * your Resource Location would be something like "HeavyThunder:StormFront" + * and this method would return "HeavyThunder". + */ + String getResourceLocationNamespace(); + /** + * Used to determine what type of object mods have added what to the DH renderer. + * This can be used both by the F3 pie chart so you as a mod developer can profile your code + * or by shader developers who want to render your objects differently.

+ * + * Should be used the same as a vanilla Minecraft ResourceLocation. + * For example if your mod named "Heavy Thunder" adds additional clouds named "Storm Front", + * your Resource Location would be something like "HeavyThunder:StormFront" + * and this method would return "StormFront". + */ + String getResourceLocationPath(); + /** Sets whether this group should render or not. */ void setActive(boolean active); /** @return if active this group will render. */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java index dd4140b02..38eb0d470 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java @@ -33,6 +33,7 @@ import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -66,7 +67,7 @@ public class BeaconRenderHandler { this.beaconBeamRepo = beaconBeamRepo; - this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(new ArrayList<>(0)); + this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(ModInfo.NAME+":Beacons", new ArrayList<>(0)); this.beaconBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); this.beaconBoxGroup.setShading(DhApiRenderableBoxGroupShading.getUnshaded()); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 2264cf1ac..0495a3609 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -41,6 +41,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRen import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; +import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.opengl.ARBInstancedArrays; @@ -214,6 +215,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single giant box IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox( + ModInfo.NAME + ":CyanChunkBox", new DhApiRenderableBox( new DhApiVec3d(0,0,0), new DhApiVec3d(16,190,16), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) @@ -225,6 +227,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single slender box IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox( + ModInfo.NAME + ":GreenBeacon", new DhApiRenderableBox( new DhApiVec3d(16,0,31), new DhApiVec3d(17,2000,32), new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) @@ -242,7 +245,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new DhApiVec3d(i,150+i,24), new DhApiVec3d(1+i,151+i,25), new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); } - IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(absBoxList); + IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(ModInfo.NAME + ":OrangeStairs", absBoxList); this.add(absolutePosBoxGroup); @@ -255,6 +258,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); } IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup( + ModInfo.NAME + ":MovingMagentaGroup", new DhApiVec3d(24, 140, 24), relBoxList); relativePosBoxGroup.setPreRenderFunc((event) -> @@ -279,6 +283,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } } IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup( + ModInfo.NAME + ":MassRedGroup", new DhApiVec3d(-25, 140, 0), massRelBoxList); massRelativePosBoxGroup.setPreRenderFunc((event) -> @@ -385,16 +390,19 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // ignore inactive groups if (boxGroup.active) { + profiler.popPush("rendering"); + profiler.push(boxGroup.getResourceLocationNamespace()); + profiler.push(boxGroup.getResourceLocationPath()); if (this.useInstancedRendering) { - profiler.popPush("rendering"); this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos); } else { - profiler.popPush("rendering"); this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos); } + profiler.pop(); // resource path + profiler.pop(); // resource namespace boxGroup.postRender(renderEventParam); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java index 263b00ece..ca0590957 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java @@ -60,19 +60,19 @@ public class GenericRenderObjectFactory implements IDhApiCustomRenderObjectFacto //================// @Override - public IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox box) + public IDhApiRenderableBoxGroup createForSingleBox(String resourceLocation, DhApiRenderableBox box) { ArrayList list = new ArrayList<>(); list.add(box); - return this.createAbsolutePositionedGroup(list); + return this.createAbsolutePositionedGroup(resourceLocation, list); } @Override - public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3d originBlockPos, List boxList) - { return new RenderableBoxGroup(new DhApiVec3d(originBlockPos.x, originBlockPos.y, originBlockPos.z), boxList, true); } + public IDhApiRenderableBoxGroup createRelativePositionedGroup(String resourceLocation, DhApiVec3d originBlockPos, List boxList) + { return new RenderableBoxGroup(resourceLocation, new DhApiVec3d(originBlockPos.x, originBlockPos.y, originBlockPos.z), boxList, true); } @Override - public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList) - { return new RenderableBoxGroup(new DhApiVec3d(0, 0, 0), boxList, false); } + public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(String resourceLocation, List boxList) + { return new RenderableBoxGroup(resourceLocation, new DhApiVec3d(0, 0, 0), boxList, false); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java index 96fff73fa..214449ba2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java @@ -30,6 +30,9 @@ public class RenderableBoxGroup public final long id; + public final String resourceLocationNamespace; + public final String resourceLocationPath; + /** If false the boxes will be positioned relative to the level's origin */ public final boolean positionBoxesRelativeToGroupOrigin; @@ -65,6 +68,11 @@ public class RenderableBoxGroup @Override public long getId() { return this.id; } + @Override + public String getResourceLocationNamespace() { return this.resourceLocationNamespace; } + @Override + public String getResourceLocationPath() { return this.resourceLocationPath; } + @Override public void setOriginBlockPos(DhApiVec3d pos) { @@ -107,8 +115,20 @@ public class RenderableBoxGroup // constructor // //=============// - public RenderableBoxGroup(DhApiVec3d originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) + public RenderableBoxGroup( + String resourceLocation, + DhApiVec3d originBlockPos, List boxList, + boolean positionBoxesRelativeToGroupOrigin) throws IllegalArgumentException { + String[] splitResourceLocation = resourceLocation.split(":"); + if (splitResourceLocation.length != 2) + { + throw new IllegalArgumentException("Resource Location must be a string that's separated by a single colon, for example: [DistantHorizons:Beacons], your namespace ["+resourceLocation+"], contains ["+(splitResourceLocation.length-1)+"] colons."); + } + + this.resourceLocationNamespace = splitResourceLocation[0]; + this.resourceLocationPath = splitResourceLocation[1]; + this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); this.boxList = new ArrayList<>(boxList); From 31c089f82f4de9edf7f7aa29c7c6840a9e597157 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 17:32:17 -0500 Subject: [PATCH 068/104] Add DhApiBeforeGenericObjectRenderEvent --- .../DhApiBeforeGenericObjectRenderEvent.java | 74 +++++++++++++++++++ .../renderer/generic/CloudRenderHandler.java | 3 + .../generic/GenericObjectRenderer.java | 33 +++++---- .../renderer/generic/RenderableBoxGroup.java | 8 ++ 4 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericObjectRenderEvent.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericObjectRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericObjectRenderEvent.java new file mode 100644 index 000000000..e7ff4cf57 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericObjectRenderEvent.java @@ -0,0 +1,74 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; + +/** + * Called before Distant Horizons starts rendering a generic object.
+ * Canceling this event will prevent the triggering {@link IDhApiRenderableBoxGroup} from rendering this frame. + * + * @author James Seibel + * @version 2024-7-11 + * @since API 3.0.0 + */ +public abstract class DhApiBeforeGenericObjectRenderEvent implements IDhApiCancelableEvent +{ + /** Fired before Distant Horizons renders a generic object. */ + public abstract void beforeRender(DhApiCancelableEventParam event); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiCancelableEventParam input) { this.beforeRender(input); } + + + //==================// + // parameter object // + //==================// + + public static class EventParam extends DhApiRenderParam + { + public final long boxGroupId; + public final String resourceLocationNamespace; + public final String resourceLocationPath; + + public EventParam( + DhApiRenderParam renderParam, + IDhApiRenderableBoxGroup boxGroup + ) + { + super(renderParam); + + this.boxGroupId = boxGroup.getId(); + this.resourceLocationNamespace = boxGroup.getResourceLocationNamespace(); + this.resourceLocationPath = boxGroup.getResourceLocationPath(); + } + + } + +} \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index 6fa285cfb..db549e2a3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -30,6 +30,7 @@ import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.Logger; import javax.imageio.ImageIO; @@ -51,6 +52,7 @@ public class CloudRenderHandler private static final boolean DEBUG_BORDER_COLORS = false; + // TODO resize and/or make clouds thicker /** * How wide an individual box is.
* Measured in blocks. @@ -232,6 +234,7 @@ public class CloudRenderHandler for (int z = -1; z <= 1; z++) { IDhApiRenderableBoxGroup boxGroup = GenericRenderObjectFactory.INSTANCE.createRelativePositionedGroup( + ModInfo.NAME + ":Clouds", new DhApiVec3d(0, 0, 0), // the offset will be set during rendering boxList); boxGroup.setBlockLight(LodUtil.MIN_MC_LIGHT); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 0495a3609..2e83b702e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -24,6 +24,8 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericObjectRenderEvent; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiLevelLoadEvent; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; @@ -40,6 +42,7 @@ import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.distanthorizons.core.util.math.Vec3d; +import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector; import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.LogManager; @@ -390,21 +393,25 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // ignore inactive groups if (boxGroup.active) { - profiler.popPush("rendering"); - profiler.push(boxGroup.getResourceLocationNamespace()); - profiler.push(boxGroup.getResourceLocationPath()); - if (this.useInstancedRendering) + boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup)); + if (cancelRendering) { - this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos); + profiler.popPush("rendering"); + profiler.push(boxGroup.getResourceLocationNamespace()); + profiler.push(boxGroup.getResourceLocationPath()); + if (this.useInstancedRendering) + { + this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos); + } + else + { + this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos); + } + profiler.pop(); // resource path + profiler.pop(); // resource namespace + + boxGroup.postRender(renderEventParam); } - else - { - this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos); - } - profiler.pop(); // resource path - profiler.pop(); // resource namespace - - boxGroup.postRender(renderEventParam); } } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java index 214449ba2..4ac380661 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java @@ -162,6 +162,10 @@ public class RenderableBoxGroup @Override public boolean isSsaoEnabled() { return this.ssaoEnabled; } + /** + * This is called before every frame, even if {@link this#isActive()} returns false.
+ * {@link this#isActive()} can be changed at this point before the object is rendered to the frame. + */ public void preRender(DhApiRenderParam renderEventParam) { if (this.beforeRenderFunc != null) @@ -169,6 +173,10 @@ public class RenderableBoxGroup this.beforeRenderFunc.accept(renderEventParam); } } + /** + * Called after rendering is completed.
+ * Can be used to handle any necessary cleanup. + */ public void postRender(DhApiRenderParam renderEventParam) { if (this.afterRenderFunc != null) From 691d5cadedbecd1a5954cddf726f1234b62e0228 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 17:38:51 -0500 Subject: [PATCH 069/104] Add api for generic rendering config --- .../client/IDhApiGenericRenderingConfig.java | 46 +++++++++++++++++++ .../client/DhApiGenericRenderingConfig.java | 46 +++++++++++++++++++ .../config/client/DhApiGraphicsConfig.java | 6 +-- 3 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGenericRenderingConfig.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGenericRenderingConfig.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGenericRenderingConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGenericRenderingConfig.java new file mode 100644 index 000000000..3209b07ba --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGenericRenderingConfig.java @@ -0,0 +1,46 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.interfaces.config.client; + +import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigGroup; +import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; + +/** + * Distant Horizons' generic rendering configuration.

+ * + * @author James Seibel + * @version 2024-7-11 + * @since API 3.0.0 + */ +public interface IDhApiGenericRenderingConfig extends IDhApiConfigGroup +{ + /** + * If enabled DH will render generic objects into its terrain pass.
+ * This includes: clouds, beacons, and API added objects. + */ + IDhApiConfigValue renderingEnabled(); + + /** If enabled DH will render beacon beams. */ + IDhApiConfigValue beaconRenderingEnabled(); + + /** If enabled DH will render clouds. */ + IDhApiConfigValue cloudRenderingEnabled(); + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGenericRenderingConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGenericRenderingConfig.java new file mode 100644 index 000000000..f7fded3e5 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGenericRenderingConfig.java @@ -0,0 +1,46 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.api.external.methods.config.client; + +import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; +import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGenericRenderingConfig; +import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig; +import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; +import com.seibel.distanthorizons.core.config.Config; + +public class DhApiGenericRenderingConfig implements IDhApiGenericRenderingConfig +{ + public static DhApiGenericRenderingConfig INSTANCE = new DhApiGenericRenderingConfig(); + + private DhApiGenericRenderingConfig() { } + + + + @Override + public IDhApiConfigValue renderingEnabled() + { return new DhApiConfigValue(Config.Client.Advanced.Graphics.GenericRendering.enableRendering); } + @Override + public IDhApiConfigValue beaconRenderingEnabled() + { return new DhApiConfigValue(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering); } + @Override + public IDhApiConfigValue cloudRenderingEnabled() + { return new DhApiConfigValue(Config.Client.Advanced.Graphics.GenericRendering.enableCloudRendering); } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java index 27c1d48eb..a65bdffba 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java @@ -22,10 +22,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client; import com.seibel.distanthorizons.api.enums.config.*; import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; -import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiAmbientOcclusionConfig; -import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFogConfig; -import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGraphicsConfig; -import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig; +import com.seibel.distanthorizons.api.interfaces.config.client.*; import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode; import com.seibel.distanthorizons.core.config.Config; @@ -45,6 +42,7 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig public IDhApiFogConfig fog() { return DhApiFogConfig.INSTANCE; } public IDhApiAmbientOcclusionConfig ambientOcclusion() { return DhApiAmbientOcclusionConfig.INSTANCE; } public IDhApiNoiseTextureConfig noiseTexture() { return DhApiNoiseTextureConfig.INSTANCE; } + public IDhApiGenericRenderingConfig genericRendering() { return DhApiGenericRenderingConfig.INSTANCE; } From 8e1dfd688edec31d2f085c72d89bdb32916c33f1 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 17:57:30 -0500 Subject: [PATCH 070/104] Fix inverting gener rendering event cancling --- .../core/render/renderer/generic/GenericObjectRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 2e83b702e..42ae9a475 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -394,7 +394,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister if (boxGroup.active) { boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup)); - if (cancelRendering) + if (!cancelRendering) { profiler.popPush("rendering"); profiler.push(boxGroup.getResourceLocationNamespace()); From 17aa85ad24bc3d3574f396c4a6cca00222f1b1b9 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 17:57:54 -0500 Subject: [PATCH 071/104] Add EDhApiBlockMaterial --- .../enums/rendering/EDhApiBlockMaterial.java | 53 +++++++++++++++++++ .../block/IDhApiBlockStateWrapper.java | 14 +++-- .../render/bufferBuilding/ColumnBox.java | 5 +- .../bufferBuilding/CubicLodTemplate.java | 36 +++++++------ .../render/bufferBuilding/LodQuadBuilder.java | 3 +- .../FullDataToRenderDataTransformer.java | 2 +- .../block/IBlockStateWrapper.java | 33 +----------- .../LightingTestBlockStateWrapper.java | 2 +- 8 files changed, 91 insertions(+), 57 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java new file mode 100644 index 000000000..076a9f92d --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java @@ -0,0 +1,53 @@ +package com.seibel.distanthorizons.api.enums.rendering; + +/** + * contains the indices used by Iris to determine how different block types should be rendered + * + * USE_OPTIFINE_FOG_SETTING,
+ * FOG_ENABLED,
+ * FOG_DISABLED
+ * + * @author James Seibel + * @since API 3.0.0 + * @version 2024-7-11 + */ +public enum EDhApiBlockMaterial +{ + UNKOWN(0), + LEAVES(1), + STONE(2), + WOOD(3), + METAL(4), + DIRT(5), + LAVA(6), + DEEPSLATE(7), + SNOW(8), + SAND(9), + TERRACOTTA(10), + NETHER_STONE(11), + WATER(12), + GRASS(13), + /** shouldn't normally be needed, but just in case */ + AIR(14), + ILLUMINATED(15); // Max value + + + + public final byte index; + + EDhApiBlockMaterial(int index) { this.index = (byte)index;} + + public static EDhApiBlockMaterial getFromIndex(int index) + { + for(EDhApiBlockMaterial material : EDhApiBlockMaterial.values()) + { + if (material.index == index) + { + return material; + } + } + + return EDhApiBlockMaterial.UNKOWN; + } + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java index 682b04f06..4d363005d 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java @@ -30,12 +30,20 @@ import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper; */ public interface IDhApiBlockStateWrapper extends IDhApiUnsafeWrapper { + /** @since API 1.0.0 */ boolean isAir(); + /** @since API 1.0.0 */ boolean isSolid(); + /** @since API 1.0.0 */ boolean isLiquid(); - // TODO: - // boolean hasNoCollision(); - // boolean noFaceIsFullFace(); + /** + * Returns the full serialized form of the given block. + * @since API 3.0.0 + */ + String getSerialString(); + /** @since API 3.0.0 */ + byte getMaterialId(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java index edf2a4c67..0cc51e422 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.util.ColorUtil; @@ -475,10 +476,10 @@ public class ColumnBox throw new RuntimeException("Loop error"); if (previousAdjDepth > adjYMax) { - if (irisBlockMaterialId == IBlockStateWrapper.IrisBlockMaterial.GRASS) + if (irisBlockMaterialId == EDhApiBlockMaterial.GRASS.index) { // this LOD is underneath another, grass will never show here - irisBlockMaterialId = IBlockStateWrapper.IrisBlockMaterial.DIRT; + irisBlockMaterialId = EDhApiBlockMaterial.DIRT.index; } builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (previousAdjDepth - adjYMax), color, irisBlockMaterialId, diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java index 87b2e7720..e0de4eb94 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource; import com.seibel.distanthorizons.core.pos.DhLodPos; @@ -95,53 +96,54 @@ public class CubicLodTemplate } case SHOW_BLOCK_MATERIAL: { - switch (blockMaterialId) + + switch (EDhApiBlockMaterial.getFromIndex(blockMaterialId)) { - case IBlockStateWrapper.IrisBlockMaterial.UNKOWN: - case IBlockStateWrapper.IrisBlockMaterial.AIR: // shouldn't normally be rendered, but just in case + case UNKOWN: + case AIR: // shouldn't normally be rendered, but just in case color = ColorUtil.HOT_PINK; break; - case IBlockStateWrapper.IrisBlockMaterial.LEAVES: + case LEAVES: color = ColorUtil.DARK_GREEN; break; - case IBlockStateWrapper.IrisBlockMaterial.STONE: + case STONE: color = ColorUtil.GRAY; break; - case IBlockStateWrapper.IrisBlockMaterial.WOOD: + case WOOD: color = ColorUtil.BROWN; break; - case IBlockStateWrapper.IrisBlockMaterial.METAL: + case METAL: color = ColorUtil.DARK_GRAY; break; - case IBlockStateWrapper.IrisBlockMaterial.DIRT: + case DIRT: color = ColorUtil.LIGHT_BROWN; break; - case IBlockStateWrapper.IrisBlockMaterial.LAVA: + case LAVA: color = ColorUtil.ORANGE; break; - case IBlockStateWrapper.IrisBlockMaterial.DEEPSLATE: + case DEEPSLATE: color = ColorUtil.BLACK; break; - case IBlockStateWrapper.IrisBlockMaterial.SNOW: + case SNOW: color = ColorUtil.WHITE; break; - case IBlockStateWrapper.IrisBlockMaterial.SAND: + case SAND: color = ColorUtil.TAN; break; - case IBlockStateWrapper.IrisBlockMaterial.TERRACOTTA: + case TERRACOTTA: color = ColorUtil.DARK_ORANGE; break; - case IBlockStateWrapper.IrisBlockMaterial.NETHER_STONE: + case NETHER_STONE: color = ColorUtil.DARK_RED; break; - case IBlockStateWrapper.IrisBlockMaterial.WATER: + case WATER: color = ColorUtil.BLUE; break; - case IBlockStateWrapper.IrisBlockMaterial.GRASS: + case GRASS: color = ColorUtil.GREEN; break; - case IBlockStateWrapper.IrisBlockMaterial.ILLUMINATED: + case ILLUMINATED: color = ColorUtil.YELLOW; break; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java index 07744dcb9..08a593656 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java @@ -24,6 +24,7 @@ import java.nio.ByteOrder; import java.util.*; import com.seibel.distanthorizons.api.enums.config.EDhApiGrassSideRendering; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.api.enums.rendering.EDhApiDebugRendering; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -273,7 +274,7 @@ public class LodQuadBuilder int color = quad.color; // use custom side color logic for grass blocks - if (quad.irisBlockMaterialId == IBlockStateWrapper.IrisBlockMaterial.GRASS) + if (quad.irisBlockMaterialId == EDhApiBlockMaterial.GRASS.index) { // only use dirt colors if debug rendering is disabled if (this.debugRenderingMode == EDhApiDebugRendering.OFF) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index c2b09d258..00dce89d3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -285,7 +285,7 @@ public class FullDataToRenderDataTransformer { // add the block isVoid = false; - long columnData = RenderDataPointUtil.createDataPoint(bottomY + blockHeight, bottomY, color, skyLight, blockLight, block.getIrisBlockMaterialId()); + long columnData = RenderDataPointUtil.createDataPoint(bottomY + blockHeight, bottomY, color, skyLight, blockLight, block.getMaterialId()); renderColumnData.set(columnOffset, columnData); columnOffset++; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java index d2a442008..1d14d1b37 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java @@ -27,37 +27,6 @@ import java.awt.*; /** A Minecraft version independent way of handling Blocks. */ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper { - //===========// - // constants // - //===========// - - /** contains the indices used by Iris to determine how different block types should be rendered */ - class IrisBlockMaterial - { - public static final byte UNKOWN = 0; - public static final byte LEAVES = 1; - public static final byte STONE = 2; - public static final byte WOOD = 3; - public static final byte METAL = 4; - public static final byte DIRT = 5; - public static final byte LAVA = 6; - public static final byte DEEPSLATE = 7; - public static final byte SNOW = 8; - public static final byte SAND = 9; - public static final byte TERRACOTTA = 10; - public static final byte NETHER_STONE = 11; - public static final byte WATER = 12; - public static final byte GRASS = 13; - - /** shouldn't normally be needed, but just in case */ - public static final byte AIR = 14; - public static final byte ILLUMINATED = 15; // Max value - } - - - - - //=========// // methods // //=========// @@ -75,7 +44,7 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper int getLightEmission(); - byte getIrisBlockMaterialId(); + byte getMaterialId(); boolean isBeaconBlock(); boolean isBeaconBaseBlock(); diff --git a/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java b/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java index 269498454..a46f50fc3 100644 --- a/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java +++ b/core/src/test/java/testItems/lightingEngine/LightingTestBlockStateWrapper.java @@ -104,7 +104,7 @@ public class LightingTestBlockStateWrapper implements IBlockStateWrapper public boolean isLiquid() { throw new UnsupportedOperationException("Not Implemented"); } @Override - public byte getIrisBlockMaterialId() { throw new UnsupportedOperationException("Not Implemented"); } + public byte getMaterialId() { throw new UnsupportedOperationException("Not Implemented"); } @Override public boolean isBeaconBlock() { throw new UnsupportedOperationException("Not Implemented"); } From e9d254f8c457e0e7a6205ab99faedd55e5083f4c Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 18:12:58 -0500 Subject: [PATCH 072/104] Add generic object materials --- .../enums/rendering/EDhApiBlockMaterial.java | 22 ++++++++++++--- .../objects/render/DhApiRenderableBox.java | 9 ++++--- .../renderer/generic/BeaconRenderHandler.java | 4 ++- .../renderer/generic/CloudRenderHandler.java | 4 ++- .../generic/GenericObjectRenderer.java | 27 +++++++++++++++---- .../renderer/generic/RenderableBoxGroup.java | 20 +++++++++++--- .../shaders/genericObject/instanced/vert.vert | 1 + 7 files changed, 70 insertions(+), 17 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java index 076a9f92d..f0f2b64a3 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java @@ -1,11 +1,25 @@ package com.seibel.distanthorizons.api.enums.rendering; /** - * contains the indices used by Iris to determine how different block types should be rendered + * contains the indices used by shaders to determine + * how different block types should be rendered.

* - * USE_OPTIFINE_FOG_SETTING,
- * FOG_ENABLED,
- * FOG_DISABLED
+ * UNKOWN,
+ * LEAVES,
+ * STONE,
+ * WOOD,
+ * METAL,
+ * DIRT,
+ * LAVA,
+ * DEEPSLATE,
+ * SNOW,
+ * SAND,
+ * TERRACOTTA,
+ * NETHER_STONE,
+ * WATER,
+ * GRASS,
+ * AIR,
+ * ILLUMINATED,
* * @author James Seibel * @since API 3.0.0 diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java index a69684e95..d3411dc15 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java @@ -1,6 +1,7 @@ package com.seibel.distanthorizons.api.objects.render; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; @@ -22,6 +23,7 @@ public class DhApiRenderableBox public DhApiVec3d maxPos; public Color color; + public byte material; @@ -29,20 +31,21 @@ public class DhApiRenderableBox // constructors // //==============// - public DhApiRenderableBox(DhApiVec3d minPos, float width, Color color) + public DhApiRenderableBox(DhApiVec3d minPos, float width, Color color, EDhApiBlockMaterial material) { this(minPos, new DhApiVec3d( minPos.x + width, minPos.y + width, minPos.z + width - ), color); + ), color, material); } - public DhApiRenderableBox(DhApiVec3d minPos, DhApiVec3d maxPos, Color color) + public DhApiRenderableBox(DhApiVec3d minPos, DhApiVec3d maxPos, Color color, EDhApiBlockMaterial material) { this.minPos = minPos; this.maxPos = maxPos; this.color = color; + this.material = material.index; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java index 38eb0d470..6518107ca 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.render.renderer.generic; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; @@ -186,7 +187,8 @@ public class BeaconRenderHandler DhApiRenderableBox beaconBox = new DhApiRenderableBox( new DhApiVec3d(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), new DhApiVec3d(beacon.pos.x+1, BEAM_TOP_Y, beacon.pos.z+1), - beacon.color + beacon.color, + EDhApiBlockMaterial.ILLUMINATED ); this.beaconBoxGroup.add(beaconBox); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index db549e2a3..d18fc7e0c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.render.renderer.generic; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; @@ -208,7 +209,8 @@ public class CloudRenderHandler DhApiRenderableBox box = new DhApiRenderableBox( new DhApiVec3d(minXBlockPos, 0, minZBlockPos), new DhApiVec3d(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos), - color + color, + EDhApiBlockMaterial.UNKOWN ); boxList.add(box); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 42ae9a475..94ab35d92 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod; import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; @@ -221,7 +222,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister ModInfo.NAME + ":CyanChunkBox", new DhApiRenderableBox( new DhApiVec3d(0,0,0), new DhApiVec3d(16,190,16), - new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) + new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125), + EDhApiBlockMaterial.WATER) ); singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); singleGiantBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); @@ -233,7 +235,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister ModInfo.NAME + ":GreenBeacon", new DhApiRenderableBox( new DhApiVec3d(16,0,31), new DhApiVec3d(17,2000,32), - new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) + new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125), + EDhApiBlockMaterial.ILLUMINATED) ); singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); singleTallBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); @@ -246,7 +249,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { absBoxList.add(new DhApiRenderableBox( new DhApiVec3d(i,150+i,24), new DhApiVec3d(1+i,151+i,25), - new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); + new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()), + EDhApiBlockMaterial.LAVA + ) + ); } IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(ModInfo.NAME + ":OrangeStairs", absBoxList); this.add(absolutePosBoxGroup); @@ -258,7 +264,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { relBoxList.add(new DhApiRenderableBox( new DhApiVec3d(0,i,0), new DhApiVec3d(1,1+i,1), - new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); + new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()), + EDhApiBlockMaterial.METAL + ) + ); } IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup( ModInfo.NAME + ":MovingMagentaGroup", @@ -282,7 +291,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister { massRelBoxList.add(new DhApiRenderableBox( new DhApiVec3d(-x, 0, -z), new DhApiVec3d(1-x, 1, 1-z), - new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()))); + new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()), + EDhApiBlockMaterial.TERRACOTTA + ) + ); } } IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup( @@ -474,6 +486,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.vertexAttribDivisor(4, 1); GL32.glVertexAttribPointer(4, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceMaterialVbo); + GL32.glEnableVertexAttribArray(5); + this.vertexAttribDivisor(5, 1); + GL32.glVertexAttribIPointer(5, 1, GL32.GL_BYTE, Byte.BYTES, 0); + // Draw instanced if (boxGroup.uploadedBoxCount > 0) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java index 4ac380661..e02588c86 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java @@ -55,6 +55,7 @@ public class RenderableBoxGroup // instance data public int instanceColorVbo = 0; + public int instanceMaterialVbo = 0; public int instanceScaleVbo = 0; public int instanceChunkPosVbo = 0; public int instanceSubChunkPosVbo = 0; @@ -236,14 +237,15 @@ public class RenderableBoxGroup this.instanceSubChunkPosVbo = GL32.glGenBuffers(); this.instanceScaleVbo = GL32.glGenBuffers(); this.instanceColorVbo = GL32.glGenBuffers(); + this.instanceMaterialVbo = GL32.glGenBuffers(); } int boxCount = this.size(); this.uploadedBoxCount = boxCount; - // transformation / scaling // + // transformation / scaling // int[] chunkPosData = new int[boxCount * 3]; float[] subChunkPosData = new float[boxCount * 3]; float[] scalingData = new float[boxCount * 3]; @@ -268,9 +270,9 @@ public class RenderableBoxGroup } - // colors // - + // colors/materials // float[] colorData = new float[boxCount * 4]; + byte[] materialData = new byte[boxCount]; for (int i = 0; i < boxCount; i++) { DhApiRenderableBox box = this.get(i); @@ -280,6 +282,8 @@ public class RenderableBoxGroup colorData[colorIndex + 1] = color.getGreen() / 255.0f; colorData[colorIndex + 2] = color.getBlue() / 255.0f; colorData[colorIndex + 3] = color.getAlpha() / 255.0f; + + materialData[i] = box.material; } @@ -294,6 +298,10 @@ public class RenderableBoxGroup // Upload colors GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo); GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW); + + // Upload materials + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceMaterialVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW); } @@ -333,6 +341,12 @@ public class RenderableBoxGroup GL32.glDeleteBuffers(this.instanceColorVbo); this.instanceColorVbo = 0; } + + if (this.instanceMaterialVbo != 0) + { + GL32.glDeleteBuffers(this.instanceMaterialVbo); + this.instanceMaterialVbo = 0; + } }); } diff --git a/core/src/main/resources/shaders/genericObject/instanced/vert.vert b/core/src/main/resources/shaders/genericObject/instanced/vert.vert index 25231ac39..a7d9a6a96 100644 --- a/core/src/main/resources/shaders/genericObject/instanced/vert.vert +++ b/core/src/main/resources/shaders/genericObject/instanced/vert.vert @@ -4,6 +4,7 @@ layout (location = 1) in vec4 aColor; layout (location = 2) in vec3 aScale; layout (location = 3) in ivec3 aTranslateChunk; layout (location = 4) in vec3 aTranslateSubChunk; +layout (location = 5) in int aMaterial; uniform ivec3 uOffsetChunk; uniform vec3 uOffsetSubChunk; From 122ef4dce04462a5ef4fabebbe29d9d8d008696f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 22:07:09 -0500 Subject: [PATCH 073/104] Fix material typo --- .../api/enums/rendering/EDhApiBlockMaterial.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java index f0f2b64a3..031232254 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java @@ -4,7 +4,7 @@ package com.seibel.distanthorizons.api.enums.rendering; * contains the indices used by shaders to determine * how different block types should be rendered.

* - * UNKOWN,
+ * UNKNOWN,
* LEAVES,
* STONE,
* WOOD,
@@ -27,7 +27,7 @@ package com.seibel.distanthorizons.api.enums.rendering; */ public enum EDhApiBlockMaterial { - UNKOWN(0), + UNKNOWN(0), LEAVES(1), STONE(2), WOOD(3), From 0483edd2f3ec1cabadd31b0fc5577e5ad9df24f7 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 11 Jul 2024 22:51:37 -0500 Subject: [PATCH 074/104] Fix material typo 2 --- .../api/enums/rendering/EDhApiBlockMaterial.java | 2 +- .../dataObjects/render/bufferBuilding/CubicLodTemplate.java | 2 +- .../core/render/renderer/generic/CloudRenderHandler.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java index 031232254..dfedf3278 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiBlockMaterial.java @@ -61,7 +61,7 @@ public enum EDhApiBlockMaterial } } - return EDhApiBlockMaterial.UNKOWN; + return EDhApiBlockMaterial.UNKNOWN; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java index e0de4eb94..a45fb2ec4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/CubicLodTemplate.java @@ -99,7 +99,7 @@ public class CubicLodTemplate switch (EDhApiBlockMaterial.getFromIndex(blockMaterialId)) { - case UNKOWN: + case UNKNOWN: case AIR: // shouldn't normally be rendered, but just in case color = ColorUtil.HOT_PINK; break; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index d18fc7e0c..bc1dfaa49 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -210,7 +210,7 @@ public class CloudRenderHandler new DhApiVec3d(minXBlockPos, 0, minZBlockPos), new DhApiVec3d(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos), color, - EDhApiBlockMaterial.UNKOWN + EDhApiBlockMaterial.UNKNOWN ); boxList.add(box); } From e7dda9590ae513b7557750834c7d621de591a7cf Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 12 Jul 2024 07:15:57 -0500 Subject: [PATCH 075/104] Add generic object setup/cleanup events --- .../DhApiBeforeGenericRenderCleanupEvent.java | 47 +++++++++++++++++ .../DhApiBeforeGenericRenderSetupEvent.java | 50 +++++++++++++++++++ .../DhApiBeforeRenderCleanupEvent.java | 2 +- .../generic/GenericObjectRenderer.java | 7 ++- 4 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericRenderCleanupEvent.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericRenderSetupEvent.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericRenderCleanupEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericRenderCleanupEvent.java new file mode 100644 index 000000000..e9c6bfbd4 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericRenderCleanupEvent.java @@ -0,0 +1,47 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; + +/** + * Called before Distant Horizons starts the cleanup process done after rendering generic objects.
+ * This is called after all generic objects have finished rendering. + * + * @author James Seibel + * @version 2024-7-13 + * @since API 3.0.0 + */ +public abstract class DhApiBeforeGenericRenderCleanupEvent implements IDhApiEvent +{ + /** Fired before Distant Horizons starts the cleanup process once rendering has finished. */ + public abstract void beforeCleanup(DhApiEventParam event); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiEventParam event) { this.beforeCleanup(event); } + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericRenderSetupEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericRenderSetupEvent.java new file mode 100644 index 000000000..2dea2942c --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeGenericRenderSetupEvent.java @@ -0,0 +1,50 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; + +/** + * Called before Distant Horizons has started setting up OpenGL objects for rendering generic objects.
+ * If you want to modify already bound DH OpenGL objects try using {@link DhApiBeforeGenericObjectRenderEvent}. + * + * @author James Seibel + * @version 2024-7-12 + * @since API 3.0.0 + * + * @see DhApiBeforeGenericObjectRenderEvent + */ +public abstract class DhApiBeforeGenericRenderSetupEvent implements IDhApiEvent +{ + /** Fired before Distant Horizons has started setting up OpenGL objects for rendering generic objects. */ + public abstract void beforeSetup(DhApiEventParam input); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiEventParam input) { this.beforeSetup(input); } + + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderCleanupEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderCleanupEvent.java index b8eb08568..85533fa35 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderCleanupEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeRenderCleanupEvent.java @@ -33,7 +33,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp */ public abstract class DhApiBeforeRenderCleanupEvent implements IDhApiEvent { - /** Fired before Distant Horizons renders LODs. */ + /** Fired before Distant Horizons starts the cleanup process once rendering has finished. */ public abstract void beforeCleanup(DhApiEventParam event); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 94ab35d92..201eab388 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -25,8 +25,7 @@ import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; -import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericObjectRenderEvent; -import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiLevelLoadEvent; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.*; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; @@ -368,6 +367,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GLState glState = new GLState(); this.init(); + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam); + GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL); GL32.glEnable(GL32.GL_DEPTH_TEST); @@ -433,6 +434,8 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // clean up // profiler.popPush("cleanup"); + ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam); + shaderProgram.unbind(); glState.restore(); From 6bb832a48833f9fbbb90cb9765b223a9f15159da Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 12 Jul 2024 17:27:17 -0500 Subject: [PATCH 076/104] Add renderEventParam to generic rendering shader binding by IMS request --- .../override/rendering/IDhApiGenericObjectShaderProgram.java | 2 +- .../seibel/distanthorizons/core/api/internal/SharedApi.java | 3 ++- .../core/render/renderer/generic/GenericObjectRenderer.java | 2 +- .../render/renderer/generic/GenericObjectShaderProgram.java | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java index b521345da..ce1d6fcde 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiGenericObjectShaderProgram.java @@ -52,7 +52,7 @@ public interface IDhApiGenericObjectShaderProgram extends IDhApiOverrideable void free(); /** Runs any necessary binding this program needs so rendering can be done. */ - void bind(); + void bind(DhApiRenderParam renderEventParam); /** Runs any necessary unbinding this program needs so rendering can be done by another program. */ void unbind(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index 7e0f58aa8..f66c37501 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -133,7 +133,8 @@ public class SharedApi * Used to prevent getting a full chunk from MC if it isn't necessary.
* This is important since asking MC for a chunk is slow and may block the render thread. */ - public static boolean isChunkAtBlockPosAlreadyUpdating(int blockPosX, int blockPosZ) { return UPDATING_CHUNK_POS_SET.contains(new DhChunkPos(new DhBlockPos2D(blockPosX, blockPosZ))); } + public static boolean isChunkAtBlockPosAlreadyUpdating(int blockPosX, int blockPosZ) + { return UPDATING_CHUNK_POS_SET.contains(new DhChunkPos(new DhBlockPos2D(blockPosX, blockPosZ))); } /** handles both block place and break events */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 201eab388..b3768548d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -383,7 +383,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister shaderProgram = shaderProgramOverride; } - shaderProgram.bind(); + shaderProgram.bind(renderEventParam); shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId()); this.boxIndexBuffer.bind(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectShaderProgram.java index d51b2a647..d021d04e0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectShaderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectShaderProgram.java @@ -92,7 +92,7 @@ public class GenericObjectShaderProgram extends ShaderProgram implements IDhApiG //=========// @Override - public void bind() + public void bind(DhApiRenderParam renderEventParam) { super.bind(); this.va.bind(); From cab9f7c83036cd543fad17c4401f4da88822d022 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 12 Jul 2024 19:22:20 -0500 Subject: [PATCH 077/104] Clone API event parameters to reduce listener contamination --- .../api/interfaces/util/IDhApiCopyable.java | 18 +++++++++++ .../DhApiBeforeBufferRenderEvent.java | 12 ++++++- .../DhApiBeforeGenericObjectRenderEvent.java | 25 ++++++++++++++- .../DhApiChunkModifiedEvent.java | 12 ++++++- .../DhApiColorDepthTextureCreatedEvent.java | 13 +++++++- .../abstractEvents/DhApiLevelLoadEvent.java | 6 +++- .../abstractEvents/DhApiLevelUnloadEvent.java | 7 +++-- .../events/interfaces/IDhApiEventParam.java | 13 ++++++++ .../DhApiRenderParam.java | 31 +++++++++++++------ .../api/objects/math/DhApiMat4f.java | 8 +++-- .../api/objects/math/DhApiVec3f.java | 7 ++++- .../DependencyInjection/ApiEventInjector.java | 22 ++++++++++++- 12 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/util/IDhApiCopyable.java create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/interfaces/IDhApiEventParam.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/util/IDhApiCopyable.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/util/IDhApiCopyable.java new file mode 100644 index 000000000..4a86357ef --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/util/IDhApiCopyable.java @@ -0,0 +1,18 @@ +package com.seibel.distanthorizons.api.interfaces.util; + +/** + * Used for objects that need deep clones.
+ * Replacement for {@link Cloneable}. + * + * @see Cloneable + * + * @author James Seibel + * @version 2024-7-12 + * @since API 3.0.0 + */ +public interface IDhApiCopyable +{ + /** Returns a deep clone of all parameters whenever possible. */ + IDhApiCopyable copy(); + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java index f1d9156a5..01b8fcaa1 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBeforeBufferRenderEvent.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.api.methods.events.abstractEvents; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; @@ -52,7 +53,7 @@ public abstract class DhApiBeforeBufferRenderEvent implements IDhApiEvent
@@ -33,7 +35,7 @@ package com.seibel.distanthorizons.api.objects.math; * @author James Seibel * @version 2024-6-30 */ -public class DhApiMat4f +public class DhApiMat4f implements IDhApiCopyable { public float m00; public float m01; @@ -277,7 +279,6 @@ public class DhApiMat4f this.m33 *= scalar; } - public DhApiMat4f copy() { return new DhApiMat4f(this); } @@ -384,4 +385,7 @@ public class DhApiMat4f this.m30 + " " + this.m31 + " " + this.m32 + " " + this.m33 + "\n"; } + @Override + public DhApiMat4f copy() { return new DhApiMat4f(this); } + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3f.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3f.java index 5fa60d8d1..8120b149a 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3f.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3f.java @@ -19,6 +19,8 @@ package com.seibel.distanthorizons.api.objects.math; +import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable; + /** * Often used to store block positions or any other * position in 3D space. @@ -27,7 +29,7 @@ package com.seibel.distanthorizons.api.objects.math; * @version 2024-6-3 * @since API 2.2.0 */ -public class DhApiVec3f +public class DhApiVec3f implements IDhApiCopyable { public float x; public float y; @@ -90,4 +92,7 @@ public class DhApiVec3f @Override public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; } + @Override + public DhApiVec3f copy() { return new DhApiVec3f(this.x, this.y, this.z); } + } diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java index e6d49f611..386ab2aef 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java @@ -22,6 +22,7 @@ package com.seibel.distanthorizons.coreapi.DependencyInjection; import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; +import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiOneTimeEvent; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; @@ -140,7 +141,26 @@ public class ApiEventInjector extends DependencyInjector implements // fire each event and record if any of them // request to cancel the event. - DhApiEventParam eventParam = createEventParamWrapper(event, eventInput); + + // attempt to clone the event input if possible + // this is done to reduce the likely hood that one event listener + // will make change the event parameter for other listeners + T input = eventInput; + if (eventInput instanceof IDhApiEventParam) + { + try + { + //noinspection unchecked + input = (T) ((IDhApiEventParam) eventInput).copy(); + } + catch (Exception e) + { + LOGGER.error("Unable to clone event parameter ["+eventInput.getClass().getSimpleName()+"], error: ["+e.getMessage()+"].", e); + } + } + + + DhApiEventParam eventParam = createEventParamWrapper(event, input); event.fireEvent(eventParam); if (eventParam instanceof DhApiCancelableEventParam) From a153ca1fe16e9a69e955edc9d6cd63ffe89efaea Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 12 Jul 2024 20:21:57 -0500 Subject: [PATCH 078/104] Fix repo connections not getting closed --- .../core/api/internal/SharedApi.java | 3 ++ .../core/level/AbstractDhLevel.java | 14 ++++++++- .../core/sql/repo/AbstractDhRepo.java | 30 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index f66c37501..11fda5913 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -30,6 +30,7 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; +import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo; import com.seibel.distanthorizons.core.util.TimerUtil; import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; @@ -97,6 +98,8 @@ public class SharedApi ThreadPoolUtil.shutdownThreadPools(); DebugRenderer.clearRenderables(); MC_RENDER.clearTargetFrameBuffer(); + // shouldn't be necessary, but if we missed closing one of the connections this should make sure they're all closed + AbstractDhRepo.closeAllConnections(); // needs to be closed on world shutdown to clear out un-processed chunks UPDATING_CHUNK_POS_SET.clear(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index a26200efa..16f7b6694 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -260,6 +260,18 @@ public abstract class AbstractDhLevel implements IDhLevel //================// @Override - public void close() { this.chunkToLodBuilder.close(); } + public void close() + { + this.chunkToLodBuilder.close(); + + if (this.chunkHashRepo != null) + { + this.chunkHashRepo.close(); + } + if (this.beaconBeamRepo != null) + { + this.beaconBeamRepo.close(); + } + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java index b4377a85d..63ab8953d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/AbstractDhRepo.java @@ -426,6 +426,36 @@ public abstract class AbstractDhRepo> implemen } } + /** can be used to make sure everything is closed when the world closes */ + public static void closeAllConnections() + { + LOGGER.info("Closing all ["+ACTIVE_CONNECTION_STRINGS_BY_REPO.size()+"] database connections..."); + for (String connectionString : ACTIVE_CONNECTION_STRINGS_BY_REPO.values()) + { + try + { + Connection connection = CONNECTIONS_BY_CONNECTION_STRING.remove(connectionString); + if (connection != null) + { + if (!connection.isClosed()) + { + LOGGER.info("Closing database connection: [" + connectionString + "]"); + connection.close(); + } + else + { + LOGGER.warn("Attempting to close already closed database connection: [" + connectionString + "]"); + } + } + } + catch(SQLException e) + { + // connection close failed. + LOGGER.error("Unable to close the connection ["+connectionString+"], error: ["+e.getMessage()+"]"); + } + } + } + @Override public void close() { From 8eabc6ad4c45aec808e587a7c59b2aa58a14d286 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 12 Jul 2024 21:47:06 -0500 Subject: [PATCH 079/104] make clouds smaller and thinner --- .../core/render/renderer/generic/CloudRenderHandler.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index bc1dfaa49..490522720 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -53,14 +53,13 @@ public class CloudRenderHandler private static final boolean DEBUG_BORDER_COLORS = false; - // TODO resize and/or make clouds thicker /** * How wide an individual box is.
* Measured in blocks. */ - private static final int CLOUD_BOX_WIDTH = 192; + private static final int CLOUD_BOX_WIDTH = 64; /** measured in blocks */ - private static final int CLOUD_BOX_THICKNESS = 48; + private static final int CLOUD_BOX_THICKNESS = 16; private final IDhApiRenderableBoxGroup[][] boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3]; private final IDhLevel level; From 1695c41ef2d398f83441456211922040a7a5b7c1 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 13 Jul 2024 08:14:29 -0500 Subject: [PATCH 080/104] Increase default fog start distance --- .../java/com/seibel/distanthorizons/core/config/Config.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index a84aba1ad..e79137958 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -281,7 +281,7 @@ public class Config private static final Double FOG_RANGE_MAX = Math.sqrt(2.0); public static ConfigEntry farFogStart = new ConfigEntry.Builder() - .setMinDefaultMax(FOG_RANGE_MIN, 0.0, FOG_RANGE_MAX) + .setMinDefaultMax(FOG_RANGE_MIN, 0.4, FOG_RANGE_MAX) .comment("" + "At what distance should the far fog start? \n" + "\n" From 6c960a81c076f43f48525e55d130c9272e942464 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 13 Jul 2024 11:07:44 -0500 Subject: [PATCH 081/104] testDisable beacon SSAO --- .../core/render/renderer/generic/BeaconRenderHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java index 6518107ca..d1beb0701 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java @@ -71,6 +71,7 @@ public class BeaconRenderHandler this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(ModInfo.NAME+":Beacons", new ArrayList<>(0)); this.beaconBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT); this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); + this.beaconBoxGroup.setSsaoEnabled(false); this.beaconBoxGroup.setShading(DhApiRenderableBoxGroupShading.getUnshaded()); this.beaconBoxGroup.setPreRenderFunc((renderEventParam) -> this.beaconBoxGroup.setActive(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering.get())); From 859cbb6161e7beb3b5e95d08cb50e2430a902144 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 13 Jul 2024 11:09:49 -0500 Subject: [PATCH 082/104] Fix fog reading/writing to the same buffer --- .../core/render/renderer/FogRenderer.java | 135 ++++++++++++++++++ .../core/render/renderer/LodRenderer.java | 34 +++-- .../core/render/renderer/SSAORenderer.java | 9 +- .../renderer/shaders/FogApplyShader.java | 107 ++++++++++++++ .../render/renderer/shaders/FogShader.java | 67 +++++---- .../renderer/shaders/SSAOApplyShader.java | 12 ++ .../render/renderer/shaders/SSAOShader.java | 17 ++- .../src/main/resources/shaders/fog/apply.frag | 24 ++++ 8 files changed, 359 insertions(+), 46 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/FogRenderer.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogApplyShader.java create mode 100644 core/src/main/resources/shaders/fog/apply.frag diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/FogRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/FogRenderer.java new file mode 100644 index 000000000..1f2f17491 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/FogRenderer.java @@ -0,0 +1,135 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer; + +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; +import com.seibel.distanthorizons.core.render.glObject.GLState; +import com.seibel.distanthorizons.core.render.renderer.shaders.FogApplyShader; +import com.seibel.distanthorizons.core.render.renderer.shaders.FogShader; +import com.seibel.distanthorizons.core.util.math.Mat4f; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import org.lwjgl.opengl.GL32; + +import java.nio.ByteBuffer; + +/** + * Handles adding SSAO via {@link FogShader} and {@link FogApplyShader}.

+ * + * {@link FogShader} - draws the Fog to a texture.
+ * {@link FogApplyShader} - draws the Fog texture to DH's FrameBuffer.
+ */ +public class FogRenderer +{ + public static FogRenderer INSTANCE = new FogRenderer(); + + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + + private boolean init = false; + + private int width = -1; + private int height = -1; + private int fogFramebuffer = -1; + + private int fogTexture = -1; + + + + //=============// + // constructor // + //=============// + + private FogRenderer() { } + + public void init() + { + if (this.init) return; + this.init = true; + + FogShader.INSTANCE.init(); + FogApplyShader.INSTANCE.init(); + } + + private void createFramebuffer(int width, int height) + { + if (this.fogFramebuffer != -1) + { + GL32.glDeleteFramebuffers(this.fogFramebuffer); + this.fogFramebuffer = -1; + } + + if (this.fogTexture != -1) + { + GL32.glDeleteTextures(this.fogTexture); + this.fogTexture = -1; + } + + this.fogFramebuffer = GL32.glGenFramebuffers(); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fogFramebuffer); + + this.fogTexture = GL32.glGenTextures(); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.fogTexture); + GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR); + GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR); + GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fogTexture, 0); + } + + + + //========// + // render // + //========// + + public void render(GLState primaryState, Mat4f projectionMatrix, float partialTicks) + { + GLState state = new GLState(); + this.init(); + + // resize the framebuffer if necessary + int width = MC_RENDER.getTargetFrameBufferViewportWidth(); + int height = MC_RENDER.getTargetFrameBufferViewportHeight(); + if (this.width != width || this.height != height) + { + this.width = width; + this.height = height; + this.createFramebuffer(width, height); + } + + FogShader.INSTANCE.frameBuffer = this.fogFramebuffer; + FogShader.INSTANCE.setProjectionMatrix(projectionMatrix); + FogShader.INSTANCE.render(partialTicks); + + // restored so we can write the SSAO texture to the main frame buffer + primaryState.restore(); + + FogApplyShader.INSTANCE.fogTexture = this.fogTexture; + FogApplyShader.INSTANCE.render(partialTicks); + + state.restore(); + } + + public void free() + { + FogShader.INSTANCE.free(); + FogApplyShader.INSTANCE.free(); + } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 98835b259..681364ac2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -327,6 +327,14 @@ public class LodRenderer } + //DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker + + if (!deferTransparentRendering && Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled) + { + this.renderTransparentBuffers(profiler, renderEventParam, renderEventParam.partialTicks); + } + + if (Config.Client.Advanced.Graphics.Fog.drawMode.get() != EDhApiFogDrawMode.FOG_DISABLED) { profiler.popPush("LOD Fog"); @@ -334,16 +342,9 @@ public class LodRenderer Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); combinedMatrix.multiply(renderEventParam.dhModelViewMatrix); - FogShader.INSTANCE.setModelViewProjectionMatrix(combinedMatrix); - FogShader.INSTANCE.render(renderEventParam.partialTicks); + FogRenderer.INSTANCE.render(minecraftGlState, combinedMatrix, renderEventParam.partialTicks); } - //DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker - - if (!deferTransparentRendering && Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled) - { - this.renderTransparentBuffers(profiler, renderEventParam, renderEventParam.partialTicks); - } drawLagSpikeCatcher.end("LodDraw"); @@ -403,6 +404,17 @@ public class LodRenderer if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled) { this.renderTransparentBuffers(profiler, renderEventParam, renderEventParam.partialTicks); + + + if (Config.Client.Advanced.Graphics.Fog.drawMode.get() != EDhApiFogDrawMode.FOG_DISABLED) + { + profiler.popPush("LOD Fog"); + + Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); + combinedMatrix.multiply(renderEventParam.dhModelViewMatrix); + + FogRenderer.INSTANCE.render(minecraftGlState, combinedMatrix, renderEventParam.partialTicks); + } } drawLagSpikeCatcher.end("LodTranslucentDraw"); @@ -457,12 +469,6 @@ public class LodRenderer this.bufferHandler.renderTransparent(this, renderEventParam); GL32.glDepthMask(true); // Apparently the depth mask state is stored in the FBO, so glState fails to restore it... - - if (Config.Client.Advanced.Graphics.Fog.drawMode.get() != EDhApiFogDrawMode.FOG_DISABLED) - { - profiler.popPush("LOD Fog"); - FogShader.INSTANCE.render(partialTicks); - } } /** called by each {@link ColumnRenderBuffer} before rendering */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java index 97c5d1cde..b9953cd31 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/SSAORenderer.java @@ -51,6 +51,7 @@ public class SSAORenderer private int ssaoTexture = -1; + //=============// // constructor // //=============// @@ -92,6 +93,7 @@ public class SSAORenderer } + //========// // render // //========// @@ -99,12 +101,11 @@ public class SSAORenderer public void render(GLState primaryState, Mat4f projectionMatrix, float partialTicks) { GLState state = new GLState(); - this.init(); - + + // resize the framebuffer if necessary int width = MC_RENDER.getTargetFrameBufferViewportWidth(); int height = MC_RENDER.getTargetFrameBufferViewportHeight(); - if (this.width != width || this.height != height) { this.width = width; @@ -116,6 +117,7 @@ public class SSAORenderer SSAOShader.INSTANCE.setProjectionMatrix(projectionMatrix); SSAOShader.INSTANCE.render(partialTicks); + // restored so we can write the SSAO texture to the main frame buffer primaryState.restore(); SSAOApplyShader.INSTANCE.ssaoTexture = this.ssaoTexture; @@ -129,4 +131,5 @@ public class SSAORenderer SSAOShader.INSTANCE.free(); SSAOApplyShader.INSTANCE.free(); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogApplyShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogApplyShader.java new file mode 100644 index 000000000..45e2d8d39 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogApplyShader.java @@ -0,0 +1,107 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.render.renderer.shaders; + +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; +import com.seibel.distanthorizons.core.render.renderer.FogRenderer; +import com.seibel.distanthorizons.core.render.renderer.LodRenderer; +import com.seibel.distanthorizons.core.render.renderer.SSAORenderer; +import com.seibel.distanthorizons.core.render.renderer.ScreenQuad; +import com.seibel.distanthorizons.core.util.RenderUtil; +import org.lwjgl.opengl.GL32; + +/** + * Draws the Fog texture onto DH's FrameBuffer.

+ * + * See Also:
+ * {@link FogRenderer} - Parent to this shader.
+ * {@link FogShader} - draws the Fog texture.
+ */ +public class FogApplyShader extends AbstractShaderRenderer +{ + public static FogApplyShader INSTANCE = new FogApplyShader(); + + public int fogTexture; + + // uniforms + public int gColorTextureUniform; + public int gDepthTextureUniform; + + + + //=============// + // constructor // + //=============// + + @Override + public void onInit() + { + this.shader = new ShaderProgram( + "shaders/normal.vert", + "shaders/fog/apply.frag", + "fragColor", + new String[]{ "vPosition" }); + + // uniform setup + this.gColorTextureUniform = this.shader.getUniformLocation("gColorTexture"); + this.gDepthTextureUniform = this.shader.getUniformLocation("gDepthTexture"); + + } + + + + //=============// + // render prep // + //=============// + + @Override + protected void onApplyUniforms(float partialTicks) + { + GL32.glActiveTexture(GL32.GL_TEXTURE0); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.fogTexture); + GL32.glUniform1i(this.gColorTextureUniform, 0); + + GL32.glActiveTexture(GL32.GL_TEXTURE1); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, LodRenderer.getActiveDepthTextureId()); + GL32.glUniform1i(this.gDepthTextureUniform, 1); + } + + + + //========// + // render // + //========// + + @Override + protected void onRender() + { + GL32.glEnable(GL32.GL_BLEND); + GL32.glBlendEquation(GL32.GL_FUNC_ADD); + GL32.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA); + + // apply the rendered Fog to DH's framebuffer + GL32.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, FogShader.INSTANCE.frameBuffer); + GL32.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, LodRenderer.getActiveFramebufferId()); + + ScreenQuad.INSTANCE.render(); + } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java index 98e0b0b1b..a35037253 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java @@ -44,12 +44,13 @@ public class FogShader extends AbstractShaderRenderer private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class); + public int frameBuffer; + private final LodFogConfig fogConfig; private Mat4f inverseMvmProjMatrix; - public int gInvertedModelViewProjectionUniform; - public int gDepthMapUniform; - // Fog Uniforms + + // Uniforms public int fogColorUniform; public int fogScaleUniform; public int fogVerticalScaleUniform; @@ -57,11 +58,16 @@ public class FogShader extends AbstractShaderRenderer public int nearFogLengthUniform; public int fullFogModeUniform; + public int gInvertedModelViewProjectionUniform; + public int gDepthMapUniform; - public FogShader(LodFogConfig fogConfig) - { - this.fogConfig = fogConfig; - } + + + //=============// + // constructor // + //=============// + + public FogShader(LodFogConfig fogConfig) { this.fogConfig = fogConfig; } @Override public void onInit() @@ -76,8 +82,8 @@ public class FogShader extends AbstractShaderRenderer // all uniforms should be tryGet... // because disabling fog can cause the GLSL to optimize out most (if not all) uniforms - this.gInvertedModelViewProjectionUniform = this.shader.tryGetUniformLocation("gInvMvmProj"); - this.gDepthMapUniform = this.shader.tryGetUniformLocation("gDepthMap"); + this.gInvertedModelViewProjectionUniform = this.shader.getUniformLocation("gInvMvmProj"); + this.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap"); // Fog uniforms this.fogColorUniform = this.shader.tryGetUniformLocation("fogColor"); @@ -90,23 +96,24 @@ public class FogShader extends AbstractShaderRenderer this.nearFogLengthUniform = this.shader.tryGetUniformLocation("nearFogLength"); } + + + //=============// + // render prep // + //=============// + @Override protected void onApplyUniforms(float partialTicks) { - this.shader.setUniform(this.gInvertedModelViewProjectionUniform, this.inverseMvmProjMatrix); + if (this.inverseMvmProjMatrix != null) + { + this.shader.setUniform(this.gInvertedModelViewProjectionUniform, this.inverseMvmProjMatrix); + } int lodDrawDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius.get() * LodUtil.CHUNK_WIDTH; int vanillaDrawDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; vanillaDrawDistance += LodUtil.CHUNK_WIDTH * 2; // Give it a 2 chunk boundary for near fog. - // bind the depth buffer - if (this.gDepthMapUniform != -1) - { - GL32.glActiveTexture(GL32.GL_TEXTURE1); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, LodRenderer.getActiveDepthTextureId()); - GL32.glUniform1i(this.gDepthMapUniform, 1); - } - // Fog if (this.fullFogModeUniform != -1) this.shader.setUniform(this.fullFogModeUniform, MC_RENDER.isFogStateSpecial() ? 1 : 0); if (this.fogColorUniform != -1) this.shader.setUniform(this.fogColorUniform, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks)); @@ -118,7 +125,6 @@ public class FogShader extends AbstractShaderRenderer if (this.fogScaleUniform != -1) this.shader.setUniform(this.fogScaleUniform, 1.f / lodDrawDistance); if (this.fogVerticalScaleUniform != -1) this.shader.setUniform(this.fogVerticalScaleUniform, 1.f / MC.getWrappedClientLevel().getMaxHeight()); } - private Color getFogColor(float partialTicks) { Color fogColor; @@ -134,29 +140,34 @@ public class FogShader extends AbstractShaderRenderer return fogColor; } - private Color getSpecialFogColor(float partialTicks) { return MC_RENDER.getSpecialFogColor(partialTicks); } - public void setModelViewProjectionMatrix(Mat4f combinedModelViewProjectionMatrix) + public void setProjectionMatrix(Mat4f projectionMatrix) { - this.inverseMvmProjMatrix = new Mat4f(combinedModelViewProjectionMatrix); + this.inverseMvmProjMatrix = new Mat4f(projectionMatrix); this.inverseMvmProjMatrix.invert(); } + + + //========// + // render // + //========// + @Override protected void onRender() { GLState state = new GLState(); - GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.frameBuffer); GL32.glDisable(GL32.GL_SCISSOR_TEST); - - GL32.glEnable(GL32.GL_BLEND); - GL32.glBlendEquation(GL32.GL_FUNC_ADD); - GL32.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE); + GL32.glDisable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_BLEND); GL32.glActiveTexture(GL32.GL_TEXTURE0); - GL32.glBindTexture(GL32.GL_TEXTURE_2D, LodRenderer.getActiveColorTextureId()); + GL32.glBindTexture(GL32.GL_TEXTURE_2D, LodRenderer.getActiveDepthTextureId()); + GL32.glUniform1i(this.gDepthMapUniform, 0); + ScreenQuad.INSTANCE.render(); state.restore(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java index eb871c92b..43da8521f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java @@ -50,6 +50,11 @@ public class SSAOApplyShader extends AbstractShaderRenderer public int gFarUniform; + + //=============// + // constructor // + //=============// + @Override public void onInit() { @@ -68,6 +73,12 @@ public class SSAOApplyShader extends AbstractShaderRenderer this.gFarUniform = this.shader.tryGetUniformLocation("gFar"); } + + + //=============// + // render prep // + //=============// + @Override protected void onApplyUniforms(float partialTicks) { @@ -102,6 +113,7 @@ public class SSAOApplyShader extends AbstractShaderRenderer } + //========// // render // //========// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java index d7659a1e0..05834e159 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java @@ -38,11 +38,13 @@ public class SSAOShader extends AbstractShaderRenderer { public static SSAOShader INSTANCE = new SSAOShader(); + public int frameBuffer; private Mat4f projection; private Mat4f invertedProjection; + // uniforms public int gProjUniform; public int gInvProjUniform; @@ -54,11 +56,17 @@ public class SSAOShader extends AbstractShaderRenderer public int gDepthMapUniform; + + //=============// + // constructor // + //=============// + @Override public void onInit() { this.shader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag", - "fragColor", new String[]{"vPosition"}); + "fragColor", new String[]{ "vPosition" } + ); // uniform setup this.gProjUniform = this.shader.getUniformLocation("gProj"); @@ -71,6 +79,12 @@ public class SSAOShader extends AbstractShaderRenderer this.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap"); } + + + //=============// + // render prep // + //=============// + public void setProjectionMatrix(Mat4f projectionMatrix) { this.projection = projectionMatrix; @@ -108,6 +122,7 @@ public class SSAOShader extends AbstractShaderRenderer } + //========// // render // //========// diff --git a/core/src/main/resources/shaders/fog/apply.frag b/core/src/main/resources/shaders/fog/apply.frag new file mode 100644 index 000000000..390599b07 --- /dev/null +++ b/core/src/main/resources/shaders/fog/apply.frag @@ -0,0 +1,24 @@ +#version 150 core + +in vec2 TexCoord; + +out vec4 fragColor; + +uniform sampler2D gColorTexture; +uniform sampler2D gDepthTexture; + + + +void main() +{ + fragColor = vec4(1.0); + + float fragmentDepth = textureLod(gDepthTexture, TexCoord, 0).r; + + // a fragment depth of "1" means the fragment wasn't drawn to, + // only update fragments that were drawn to + if (fragmentDepth != 1) + { + fragColor = texture(gColorTexture, TexCoord); + } +} From 634738a1fc1dc2b017ba0fec208145d3320297d0 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 13 Jul 2024 11:35:25 -0500 Subject: [PATCH 083/104] Remove minimum near fog distance and rename fog uniforms --- .../core/render/fog/LodFogConfig.java | 12 ++-- .../renderer/shaders/FogApplyShader.java | 15 ++--- .../render/renderer/shaders/FogShader.java | 55 +++++++++---------- .../src/main/resources/shaders/fog/apply.frag | 8 +-- core/src/main/resources/shaders/fog/fog.frag | 34 ++++++------ 5 files changed, 60 insertions(+), 64 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java index be4adf73e..8e0873b93 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java @@ -173,7 +173,7 @@ public class LodFogConfig str.append("" + "float getNearFogThickness(float dist) \n" + "{ \n" + - " return linearFog(dist, nearFogStart, nearFogLength, 0.0, 1.0); \n" + + " return linearFog(dist, uNearFogStart, uNearFogLength, 0.0, 1.0); \n" + "} \n"); @@ -182,7 +182,7 @@ public class LodFogConfig str.append("\n" + "float getFarFogThickness(float dist) { return 0.0; } \n" + "float getHeightFogThickness(float dist) { return 0.0; } \n" + - "float calculateFarFogDepth(float horizontal, float dist, float nearFogStart) { return 0.0; } \n" + + "float calculateFarFogDepth(float horizontal, float dist, float uNearFogStart) { return 0.0; } \n" + "float calculateHeightFogDepth(float vertical, float realY) { return 0.0; } \n" + "float mixFogThickness(float near, float far, float height) \n" + "{ \n" + @@ -215,13 +215,13 @@ public class LodFogConfig "} \n"); - // Generate method: calculateFarFogDepth(float horizontal, float dist, float nearFogStart); + // Generate method: calculateFarFogDepth(float horizontal, float dist, float uNearFogStart); str.append("" + - "float calculateFarFogDepth(float horizontal, float dist, float nearFogStart) \n" + + "float calculateFarFogDepth(float horizontal, float dist, float uNearFogStart) \n" + "{ \n" + " return " + (heightFogMixMode == EDhApiHeightFogMixMode.BASIC ? - "(dist - nearFogStart)/(1.0 - nearFogStart);" : - "(horizontal - nearFogStart)/(1.0 - nearFogStart);") + + "(dist - uNearFogStart)/(1.0 - uNearFogStart);" : + "(horizontal - uNearFogStart)/(1.0 - uNearFogStart);") + "} \n"); // Generate method: float mixFogThickness(float near, float far, float height); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogApplyShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogApplyShader.java index 45e2d8d39..4906b75b2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogApplyShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogApplyShader.java @@ -19,13 +19,10 @@ package com.seibel.distanthorizons.core.render.renderer.shaders; -import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram; import com.seibel.distanthorizons.core.render.renderer.FogRenderer; import com.seibel.distanthorizons.core.render.renderer.LodRenderer; -import com.seibel.distanthorizons.core.render.renderer.SSAORenderer; import com.seibel.distanthorizons.core.render.renderer.ScreenQuad; -import com.seibel.distanthorizons.core.util.RenderUtil; import org.lwjgl.opengl.GL32; /** @@ -42,8 +39,8 @@ public class FogApplyShader extends AbstractShaderRenderer public int fogTexture; // uniforms - public int gColorTextureUniform; - public int gDepthTextureUniform; + public int colorTextureUniform; + public int depthTextureUniform; @@ -61,8 +58,8 @@ public class FogApplyShader extends AbstractShaderRenderer new String[]{ "vPosition" }); // uniform setup - this.gColorTextureUniform = this.shader.getUniformLocation("gColorTexture"); - this.gDepthTextureUniform = this.shader.getUniformLocation("gDepthTexture"); + this.colorTextureUniform = this.shader.getUniformLocation("uColorTexture"); + this.depthTextureUniform = this.shader.getUniformLocation("uDepthTexture"); } @@ -77,11 +74,11 @@ public class FogApplyShader extends AbstractShaderRenderer { GL32.glActiveTexture(GL32.GL_TEXTURE0); GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.fogTexture); - GL32.glUniform1i(this.gColorTextureUniform, 0); + GL32.glUniform1i(this.colorTextureUniform, 0); GL32.glActiveTexture(GL32.GL_TEXTURE1); GL32.glBindTexture(GL32.GL_TEXTURE_2D, LodRenderer.getActiveDepthTextureId()); - GL32.glUniform1i(this.gDepthTextureUniform, 1); + GL32.glUniform1i(this.depthTextureUniform, 1); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java index a35037253..5987af82e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java @@ -51,15 +51,16 @@ public class FogShader extends AbstractShaderRenderer // Uniforms - public int fogColorUniform; - public int fogScaleUniform; - public int fogVerticalScaleUniform; - public int nearFogStartUniform; - public int nearFogLengthUniform; - public int fullFogModeUniform; + public int uFogColor; + public int uFogScale; + public int uFogVerticalScale; + public int uNearFogStart; + public int uNearFogLength; + public int uFullFogMode; - public int gInvertedModelViewProjectionUniform; - public int gDepthMapUniform; + /** Inverted Model View Projection matrix */ + public int uInvMvmProj; + public int uDepthMap; @@ -82,18 +83,19 @@ public class FogShader extends AbstractShaderRenderer // all uniforms should be tryGet... // because disabling fog can cause the GLSL to optimize out most (if not all) uniforms - this.gInvertedModelViewProjectionUniform = this.shader.getUniformLocation("gInvMvmProj"); - this.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap"); + this.uDepthMap = this.shader.getUniformLocation("uDepthMap"); + this.uInvMvmProj = this.shader.getUniformLocation("uInvMvmProj"); // Fog uniforms - this.fogColorUniform = this.shader.tryGetUniformLocation("fogColor"); - this.fullFogModeUniform = this.shader.tryGetUniformLocation("fullFogMode"); - this.fogScaleUniform = this.shader.tryGetUniformLocation("fogScale"); - this.fogVerticalScaleUniform = this.shader.tryGetUniformLocation("fogVerticalScale"); + this.uFogScale = this.shader.tryGetUniformLocation("uFogScale"); + this.uFogVerticalScale = this.shader.tryGetUniformLocation("uFogVerticalScale"); + this.uFogColor = this.shader.tryGetUniformLocation("uFogColor"); + this.uFullFogMode = this.shader.tryGetUniformLocation("uFullFogMode"); // near fog - this.nearFogStartUniform = this.shader.tryGetUniformLocation("nearFogStart"); - this.nearFogLengthUniform = this.shader.tryGetUniformLocation("nearFogLength"); + this.uNearFogStart = this.shader.tryGetUniformLocation("uNearFogStart"); + this.uNearFogLength = this.shader.tryGetUniformLocation("uNearFogLength"); + } @@ -107,23 +109,20 @@ public class FogShader extends AbstractShaderRenderer { if (this.inverseMvmProjMatrix != null) { - this.shader.setUniform(this.gInvertedModelViewProjectionUniform, this.inverseMvmProjMatrix); + this.shader.setUniform(this.uInvMvmProj, this.inverseMvmProjMatrix); } int lodDrawDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius.get() * LodUtil.CHUNK_WIDTH; - int vanillaDrawDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH; - vanillaDrawDistance += LodUtil.CHUNK_WIDTH * 2; // Give it a 2 chunk boundary for near fog. // Fog - if (this.fullFogModeUniform != -1) this.shader.setUniform(this.fullFogModeUniform, MC_RENDER.isFogStateSpecial() ? 1 : 0); - if (this.fogColorUniform != -1) this.shader.setUniform(this.fogColorUniform, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks)); + if (this.uFullFogMode != -1) this.shader.setUniform(this.uFullFogMode, MC_RENDER.isFogStateSpecial() ? 1 : 0); + if (this.uFogColor != -1) this.shader.setUniform(this.uFogColor, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks)); - float nearFogLen = vanillaDrawDistance * 0.2f / lodDrawDistance; - float nearFogStart = vanillaDrawDistance * (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float) Math.sqrt(2.0) : 1.0f) / lodDrawDistance; - if (this.nearFogStartUniform != -1) this.shader.setUniform(this.nearFogStartUniform, nearFogStart); - if (this.nearFogLengthUniform != -1) this.shader.setUniform(this.nearFogLengthUniform, nearFogLen); - if (this.fogScaleUniform != -1) this.shader.setUniform(this.fogScaleUniform, 1.f / lodDrawDistance); - if (this.fogVerticalScaleUniform != -1) this.shader.setUniform(this.fogVerticalScaleUniform, 1.f / MC.getWrappedClientLevel().getMaxHeight()); + float nearFogStart = (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float) Math.sqrt(2.0) : 1.0f) / lodDrawDistance; + if (this.uNearFogStart != -1) this.shader.setUniform(this.uNearFogStart, nearFogStart); + if (this.uNearFogLength != -1) this.shader.setUniform(this.uNearFogLength, 0.0f); + if (this.uFogScale != -1) this.shader.setUniform(this.uFogScale, 1.f / lodDrawDistance); + if (this.uFogVerticalScale != -1) this.shader.setUniform(this.uFogVerticalScale, 1.f / MC.getWrappedClientLevel().getMaxHeight()); } private Color getFogColor(float partialTicks) { @@ -166,7 +165,7 @@ public class FogShader extends AbstractShaderRenderer GL32.glActiveTexture(GL32.GL_TEXTURE0); GL32.glBindTexture(GL32.GL_TEXTURE_2D, LodRenderer.getActiveDepthTextureId()); - GL32.glUniform1i(this.gDepthMapUniform, 0); + GL32.glUniform1i(this.uDepthMap, 0); ScreenQuad.INSTANCE.render(); diff --git a/core/src/main/resources/shaders/fog/apply.frag b/core/src/main/resources/shaders/fog/apply.frag index 390599b07..7241d1161 100644 --- a/core/src/main/resources/shaders/fog/apply.frag +++ b/core/src/main/resources/shaders/fog/apply.frag @@ -4,8 +4,8 @@ in vec2 TexCoord; out vec4 fragColor; -uniform sampler2D gColorTexture; -uniform sampler2D gDepthTexture; +uniform sampler2D uColorTexture; +uniform sampler2D uDepthTexture; @@ -13,12 +13,12 @@ void main() { fragColor = vec4(1.0); - float fragmentDepth = textureLod(gDepthTexture, TexCoord, 0).r; + float fragmentDepth = textureLod(uDepthTexture, TexCoord, 0).r; // a fragment depth of "1" means the fragment wasn't drawn to, // only update fragments that were drawn to if (fragmentDepth != 1) { - fragColor = texture(gColorTexture, TexCoord); + fragColor = texture(uColorTexture, TexCoord); } } diff --git a/core/src/main/resources/shaders/fog/fog.frag b/core/src/main/resources/shaders/fog/fog.frag index 04eb3f7c1..eed4c6b6b 100644 --- a/core/src/main/resources/shaders/fog/fog.frag +++ b/core/src/main/resources/shaders/fog/fog.frag @@ -3,17 +3,17 @@ in vec2 TexCoord; out vec4 fragColor; -uniform sampler2D gDepthMap; +uniform sampler2D uDepthMap; // inverted model view matrix and projection matrix -uniform mat4 gInvMvmProj; +uniform mat4 uInvMvmProj; -uniform float fogScale; -uniform float fogVerticalScale; -uniform float nearFogStart; -uniform float nearFogLength; -uniform int fullFogMode; +uniform float uFogScale; +uniform float uFogVerticalScale; +uniform vec4 uFogColor; +uniform int uFullFogMode; -uniform vec4 fogColor; +uniform float uNearFogStart; +uniform float uNearFogLength; /* ========MARCO DEFINED BY RUNTIME CODE GEN========= @@ -53,7 +53,7 @@ vec3 calcViewPosition(float fragmentDepth) { vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0); ndc.xyz = ndc.xyz * 2.0 - 1.0; - vec4 eyeCoord = gInvMvmProj * ndc; + vec4 eyeCoord = uInvMvmProj * ndc; return eyeCoord.xyz / eyeCoord.w; } @@ -66,19 +66,19 @@ vec3 calcViewPosition(float fragmentDepth) { void main() { float vertexYPos = 100.0f; - float fragmentDepth = texture(gDepthMap, TexCoord).r; - fragColor = vec4(fogColor.rgb, 0.0); + float fragmentDepth = texture(uDepthMap, TexCoord).r; + fragColor = vec4(uFogColor.rgb, 0.0); // a fragment depth of "1" means the fragment wasn't drawn to, // we only want to apply Fog to LODs, not to the sky outside the LODs if (fragmentDepth < 1.0) { - if (fullFogMode == 0) { + if (uFullFogMode == 0) { // render fog based on distance from the camera vec3 vertexWorldPos = calcViewPosition(fragmentDepth); - float horizontalDist = length(vertexWorldPos.xz) * fogScale; - float heightDist = calculateHeightFogDepth(vertexWorldPos.y, vertexYPos) * fogVerticalScale; - float farDist = calculateFarFogDepth(horizontalDist, length(vertexWorldPos.xyz) * fogScale, nearFogStart); + float horizontalDist = length(vertexWorldPos.xz) * uFogScale; + float heightDist = calculateHeightFogDepth(vertexWorldPos.y, vertexYPos) * uFogVerticalScale; + float farDist = calculateFarFogDepth(horizontalDist, length(vertexWorldPos.xyz) * uFogScale, uNearFogStart); float nearFogThickness = getNearFogThickness(horizontalDist); float farFogThickness = getFarFogThickness(farDist); @@ -89,7 +89,7 @@ void main() float dither = InterleavedGradientNoise(gl_FragCoord.xy) - 0.5; fragColor.a += dither / 255.0; } - else if (fullFogMode == 1) { + else if (uFullFogMode == 1) { // render everything with the fog color fragColor.a = 1.0; } @@ -101,7 +101,7 @@ void main() // a uniform we don't have to worry about GLSL optimizing away different // options when testing, causing a bunch of headaches if we just want to render the screen red. - float depthValue = textureLod(gDepthMap, TexCoord, 0).r; + float depthValue = textureLod(uDepthMap, TexCoord, 0).r; fragColor.rgb = vec3(depthValue); // Convert depth value to grayscale color fragColor.a = 1.0; } From 32861e757d3574555738de1317e9145d7ccf9299 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 13 Jul 2024 12:04:05 -0500 Subject: [PATCH 084/104] Add shader uniform "u" prefix --- .../core/render/renderer/DebugRenderer.java | 2 +- .../renderer/DhTerrainShaderProgram.java | 107 +++++++++--------- core/src/main/resources/shaders/curve.vert | 34 +++--- .../main/resources/shaders/debug/frag.frag | 1 + .../main/resources/shaders/debug/vert.vert | 4 +- .../main/resources/shaders/flat_shaded.frag | 22 ++-- .../main/resources/shaders/noise/noise.frag | 12 +- core/src/main/resources/shaders/normal.vert | 1 + core/src/main/resources/shaders/standard.vert | 30 ++--- 9 files changed, 109 insertions(+), 104 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java index d2b573f7b..02243d36f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java @@ -231,7 +231,7 @@ public class DebugRenderer boxTransform.multiply(Mat4f.createScaleMatrix(box.maxPos.x - box.minPos.x, box.maxPos.y - box.minPos.y, box.maxPos.z - box.minPos.z)); Mat4f t = this.transformationMatrixThisFrame.copy(); t.multiply(boxTransform); - this.basicShader.setUniform(this.basicShader.getUniformLocation("transform"), t); + this.basicShader.setUniform(this.basicShader.getUniformLocation("uTransform"), t); this.basicShader.setUniform(this.basicShader.getUniformLocation("uColor"), box.color); GL32.glDrawElements(GL32.GL_LINES, BOX_OUTLINE_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhTerrainShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhTerrainShaderProgram.java index 3f5f4a753..058b6b63e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhTerrainShaderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DhTerrainShaderProgram.java @@ -40,34 +40,30 @@ import com.seibel.distanthorizons.core.util.math.Vec3f; */ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShaderProgram { - public static final String VERTEX_SHADER_PATH = "shaders/standard.vert"; - public static final String VERTEX_CURVE_SHADER_PATH = "shaders/curve.vert"; - public static final String FRAGMENT_SHADER_PATH = "shaders/flat_shaded.frag"; - public final AbstractVertexAttribute vao; // Uniforms - public final int combinedMatUniform; - public final int modelOffsetUniform; - public final int worldYOffsetUniform; + public final int uCombinedMatrix; + public final int uModelOffset; + public final int uWorldYOffset; - public final int mircoOffsetUniform; + public final int uMircoOffset; - public final int earthRadiusUniform; + public final int uEarthRadius; - public final int lightMapUniform; + public final int uLightMap; // Fog/Clip Uniforms - public final int clipDistanceUniform; + public final int uClipDistance; // Noise Uniforms - public final int noiseEnabledUniform; - public final int noiseStepsUniform; - public final int noiseIntensityUniform; - public final int noiseDropoffUniform; + public final int uNoiseEnabled; + public final int uNoiseSteps; + public final int uNoiseIntensity; + public final int uNoiseDropoff; // Debug Uniform - public final int whiteWorldUniform; + public final int uWhiteWorld; @@ -78,48 +74,55 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade // This will bind AbstractVertexAttribute public DhTerrainShaderProgram() { - super(() -> Shader.loadFile(Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get() != 0 ? VERTEX_CURVE_SHADER_PATH : VERTEX_SHADER_PATH, + super( + () -> Shader.loadFile(Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get() != 0 + ? "shaders/curve.vert" + : "shaders/standard.vert", false, new StringBuilder()).toString(), - () -> Shader.loadFile(FRAGMENT_SHADER_PATH, false, new StringBuilder()).toString(), + () -> Shader.loadFile("shaders/flat_shaded.frag", false, new StringBuilder()).toString(), "fragColor", new String[]{"vPosition", "color"}); - combinedMatUniform = getUniformLocation("combinedMatrix"); - modelOffsetUniform = getUniformLocation("modelOffset"); - worldYOffsetUniform = tryGetUniformLocation("worldYOffset"); - mircoOffsetUniform = getUniformLocation("mircoOffset"); - earthRadiusUniform = tryGetUniformLocation("earthRadius"); + this.uCombinedMatrix = this.getUniformLocation("uCombinedMatrix"); + this.uModelOffset = this.getUniformLocation("uModelOffset"); + this.uWorldYOffset = this.tryGetUniformLocation("uWorldYOffset"); + this.uMircoOffset = this.getUniformLocation("uMircoOffset"); + this.uEarthRadius = this.tryGetUniformLocation("uEarthRadius"); - lightMapUniform = getUniformLocation("lightMap"); + this.uLightMap = this.getUniformLocation("uLightMap"); // Fog/Clip Uniforms - clipDistanceUniform = getUniformLocation("clipDistance"); + this.uClipDistance = this.getUniformLocation("uClipDistance"); // Noise Uniforms - noiseEnabledUniform = getUniformLocation("noiseEnabled"); - noiseStepsUniform = getUniformLocation("noiseSteps"); - noiseIntensityUniform = getUniformLocation("noiseIntensity"); - noiseDropoffUniform = getUniformLocation("noiseDropoff"); + this.uNoiseEnabled = this.getUniformLocation("uNoiseEnabled"); + this.uNoiseSteps = this.getUniformLocation("uNoiseSteps"); + this.uNoiseIntensity = this.getUniformLocation("uNoiseIntensity"); + this.uNoiseDropoff = this.getUniformLocation("uNoiseDropoff"); // Debug Uniform - whiteWorldUniform = getUniformLocation("whiteWorld"); + this.uWhiteWorld = this.getUniformLocation("uWhiteWorld"); // TODO: Add better use of the LODFormat thing int vertexByteCount = LodUtil.LOD_VERTEX_FORMAT.getByteSize(); if (GLProxy.getInstance().vertexAttributeBufferBindingSupported) - vao = new VertexAttributePostGL43(); // also binds AbstractVertexAttribute + { + this.vao = new VertexAttributePostGL43(); // also binds AbstractVertexAttribute + } else - vao = new VertexAttributePreGL43(); // also binds AbstractVertexAttribute - vao.bind(); + { + this.vao = new VertexAttributePreGL43(); // also binds AbstractVertexAttribute + } + this.vao.bind(); // TODO comment what each attribute represents - vao.setVertexAttribute(0, 0, VertexPointer.addUnsignedShortsPointer(4, false, true)); // 2+2+2+2 // TODO probably color, blockpos - vao.setVertexAttribute(0, 1, VertexPointer.addUnsignedBytesPointer(4, true, false)); // +4 // TODO ? - vao.setVertexAttribute(0, 2, VertexPointer.addUnsignedBytesPointer(4, true, true)); // +4 // TODO probably normal index and Iris block ID + this.vao.setVertexAttribute(0, 0, VertexPointer.addUnsignedShortsPointer(4, false, true)); // 2+2+2+2 // TODO probably color, blockpos + this.vao.setVertexAttribute(0, 1, VertexPointer.addUnsignedBytesPointer(4, true, false)); // +4 // TODO ? + this.vao.setVertexAttribute(0, 2, VertexPointer.addUnsignedBytesPointer(4, true, true)); // +4 // TODO probably normal index and Iris block ID try { - vao.completeAndCheck(vertexByteCount); + this.vao.completeAndCheck(vertexByteCount); } catch (RuntimeException e) { @@ -127,15 +130,15 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade throw e; } - if (earthRadiusUniform != -1) setUniform(earthRadiusUniform, + if (this.uEarthRadius != -1) this.setUniform(this.uEarthRadius, /*6371KM*/ 6371000.0f / Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get()); // Noise Uniforms - setUniform(noiseEnabledUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseEnabled.get()); - setUniform(noiseStepsUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseSteps.get()); - setUniform(noiseIntensityUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseIntensity.get().floatValue()); - setUniform(noiseDropoffUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseDropoff.get()); + this.setUniform(this.uNoiseEnabled, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseEnabled.get()); + this.setUniform(this.uNoiseSteps, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseSteps.get()); + this.setUniform(this.uNoiseIntensity, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseIntensity.get().floatValue()); + this.setUniform(this.uNoiseDropoff, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseDropoff.get()); } @@ -148,19 +151,19 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade public void bind() { super.bind(); - vao.bind(); + this.vao.bind(); } @Override public void unbind() { super.unbind(); - vao.unbind(); + this.vao.unbind(); } @Override public void free() { - vao.free(); + this.vao.free(); super.free(); } @@ -176,16 +179,16 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade super.bind(); // uniforms - setUniform(combinedMatUniform, combinedMatrix); - setUniform(mircoOffsetUniform, 0.01f); // 0.01 block offset + this.setUniform(this.uCombinedMatrix, combinedMatrix); + this.setUniform(this.uMircoOffset, 0.01f); // 0.01 block offset // setUniform(skyLightUniform, skyLight); - setUniform(lightMapUniform, 0); // TODO this should probably be passed in + this.setUniform(this.uLightMap, 0); // TODO this should probably be passed in - if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float) renderParameters.worldYOffset); + if (this.uWorldYOffset != -1) this.setUniform(this.uWorldYOffset, (float) renderParameters.worldYOffset); // Debug - setUniform(whiteWorldUniform, Config.Client.Advanced.Debugging.enableWhiteWorld.get()); + this.setUniform(this.uWhiteWorld, Config.Client.Advanced.Debugging.enableWhiteWorld.get()); // Clip Uniform float dhNearClipDistance = RenderUtil.getNearClipPlaneDistanceInBlocks(renderParameters.partialTicks); @@ -199,11 +202,11 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade { dhNearClipDistance = 1.0f; } - this.setUniform(this.clipDistanceUniform, dhNearClipDistance); + this.setUniform(this.uClipDistance, dhNearClipDistance); } @Override - public void setModelOffsetPos(DhApiVec3f modelOffsetPos) { this.setUniform(this.modelOffsetUniform, new Vec3f(modelOffsetPos)); } + public void setModelOffsetPos(DhApiVec3f modelOffsetPos) { this.setUniform(this.uModelOffset, new Vec3f(modelOffsetPos)); } @Override public int getId() { return this.id; } diff --git a/core/src/main/resources/shaders/curve.vert b/core/src/main/resources/shaders/curve.vert index 03876a40c..8b8c96755 100644 --- a/core/src/main/resources/shaders/curve.vert +++ b/core/src/main/resources/shaders/curve.vert @@ -8,17 +8,17 @@ out vec4 vertexColor; out vec3 vertexWorldPos; out float vertexYPos; -uniform bool whiteWorld; +uniform bool uWhiteWorld; -uniform mat4 combinedMatrix; -uniform vec3 modelOffset; -uniform float worldYOffset; +uniform mat4 uCombinedMatrix; +uniform vec3 uModelOffset; +uniform float uWorldYOffset; -uniform int worldSkyLight; -uniform sampler2D lightMap; -uniform float mircoOffset; +uniform int uWorldSkyLight; +uniform sampler2D uLightMap; +uniform float uMircoOffset; -uniform float earthRadius; +uniform float uEarthRadius; /** * TODO in the future this and standard.vert should be merged together to prevent inconsistencies between the two @@ -35,9 +35,9 @@ void main() { vPos = vPosition; // This is so it can be passed to the fragment shader - vertexWorldPos = vPosition.xyz + modelOffset; + vertexWorldPos = vPosition.xyz + uModelOffset; - vertexYPos = vPosition.y + worldYOffset; + vertexYPos = vPosition.y + uWorldYOffset; uint meta = vPosition.a; @@ -46,11 +46,11 @@ void main() // 0b01 = positive offset // 0b11 = negative offset // format is: 0b00zzyyxx - float mx = (mirco & 1u) != 0u ? mircoOffset : 0.0; + float mx = (mirco & 1u) != 0u ? uMircoOffset : 0.0; mx = (mirco & 2u) != 0u ? -mx : mx; - float my = (mirco & 4u) != 0u ? mircoOffset : 0.0; + float my = (mirco & 4u) != 0u ? uMircoOffset : 0.0; my = (mirco & 8u) != 0u ? -my : my; - float mz = (mirco & 16u) != 0u ? mircoOffset : 0.0; + float mz = (mirco & 16u) != 0u ? uMircoOffset : 0.0; mz = (mirco & 32u) != 0u ? -mz : mz; vertexWorldPos.x += mx; vertexWorldPos.y += my; @@ -58,7 +58,7 @@ void main() // vertex transformation logic - stduhpf - float localRadius = earthRadius + vertexYPos; + float localRadius = uEarthRadius + vertexYPos; float phi = length(vertexWorldPos.xz) / localRadius; vertexWorldPos.y += (cos(phi) - 1.0) * localRadius; vertexWorldPos.xz = vertexWorldPos.xz * sin(phi) / phi; @@ -68,12 +68,12 @@ void main() float light2 = (mod(float(lights), 16.0) + 0.5) / 16.0; float light = (float(lights / 16u) + 0.5) / 16.0; - vertexColor = vec4(texture(lightMap, vec2(light, light2)).xyz, 1.0); + vertexColor = vec4(texture(uLightMap, vec2(light, light2)).xyz, 1.0); - if (!whiteWorld) + if (!uWhiteWorld) { vertexColor *= color; } - gl_Position = combinedMatrix * vec4(vertexWorldPos, 1.0); + gl_Position = uCombinedMatrix * vec4(vertexWorldPos, 1.0); } diff --git a/core/src/main/resources/shaders/debug/frag.frag b/core/src/main/resources/shaders/debug/frag.frag index 1f22d751c..16f8de33f 100644 --- a/core/src/main/resources/shaders/debug/frag.frag +++ b/core/src/main/resources/shaders/debug/frag.frag @@ -1,6 +1,7 @@ #version 150 core uniform vec4 uColor; + out vec4 fragColor; void main() diff --git a/core/src/main/resources/shaders/debug/vert.vert b/core/src/main/resources/shaders/debug/vert.vert index e32ec6e80..befc43200 100644 --- a/core/src/main/resources/shaders/debug/vert.vert +++ b/core/src/main/resources/shaders/debug/vert.vert @@ -1,10 +1,10 @@ #version 150 core -uniform mat4 transform; +uniform mat4 uTransform; in vec3 vPosition; void main() { - gl_Position = transform * vec4(vPosition, 1.0); + gl_Position = uTransform * vec4(vPosition, 1.0); } \ No newline at end of file diff --git a/core/src/main/resources/shaders/flat_shaded.frag b/core/src/main/resources/shaders/flat_shaded.frag index e6d7a9407..0bfe32461 100644 --- a/core/src/main/resources/shaders/flat_shaded.frag +++ b/core/src/main/resources/shaders/flat_shaded.frag @@ -9,13 +9,13 @@ out vec4 fragColor; // Fog/Clip Uniforms -uniform float clipDistance = 0.0; +uniform float uClipDistance = 0.0; // Noise Uniforms -uniform bool noiseEnabled; -uniform int noiseSteps; -uniform float noiseIntensity; -uniform int noiseDropoff; +uniform bool uNoiseEnabled; +uniform int uNoiseSteps; +uniform float uNoiseIntensity; +uniform int uNoiseDropoff; // The random functions for diffrent dimentions @@ -38,13 +38,13 @@ void applyNoise(inout vec4 fragColor, const in float viewDist) // This bit of code is required to fix the vertex position problem cus of floats in the verted world position varuable vec3 fixedVPos = vPos.xyz + vertexNormal * 0.001; - float noiseAmplification = noiseIntensity * 0.01; + float noiseAmplification = uNoiseIntensity * 0.01; float lum = (fragColor.r + fragColor.g + fragColor.b) / 3.0; noiseAmplification = (1.0 - pow(lum * 2.0 - 1.0, 2.0)) * noiseAmplification; // Lessen the effect on depending on how dark the object is, equasion for this is -(2x-1)^{2}+1 noiseAmplification *= fragColor.a; // The effect would lessen on transparent objects // Random value for each position - float randomValue = rand(quantize(fixedVPos, noiseSteps)) + float randomValue = rand(quantize(fixedVPos, uNoiseSteps)) * 2.0 * noiseAmplification - noiseAmplification; // Modifies the color @@ -52,8 +52,8 @@ void applyNoise(inout vec4 fragColor, const in float viewDist) vec3 newCol = fragColor.rgb + (1.0 - fragColor.rgb) * randomValue; newCol = clamp(newCol, 0.0, 1.0); - if (noiseDropoff != 0) { - float distF = min(viewDist / noiseDropoff, 1.0); + if (uNoiseDropoff != 0) { + float distF = min(viewDist / uNoiseDropoff, 1.0); newCol = mix(newCol, fragColor.rgb, distF); // The further away it gets, the less noise gets applied } @@ -67,12 +67,12 @@ void main() fragColor = vertexColor; float viewDist = length(vertexWorldPos); - if (viewDist < clipDistance && clipDistance > 0.0) + if (viewDist < uClipDistance && uClipDistance > 0.0) { discard; } - if (noiseEnabled) + if (uNoiseEnabled) { applyNoise(fragColor, viewDist); } diff --git a/core/src/main/resources/shaders/noise/noise.frag b/core/src/main/resources/shaders/noise/noise.frag index 1156311fc..e34018619 100644 --- a/core/src/main/resources/shaders/noise/noise.frag +++ b/core/src/main/resources/shaders/noise/noise.frag @@ -7,9 +7,9 @@ out vec4 fragColor; uniform float distanceScale; -uniform int noiseSteps; -uniform float noiseIntensity; -uniform float noiseDropoff; +uniform int uNoiseSteps; +uniform float uNoiseIntensity; +uniform float uNoiseDropoff; @@ -43,12 +43,12 @@ void main() { vec3 fixedVPos = vPos.xyz - vertexNormal * 0.001; - float noiseAmplification = noiseIntensity / 100; + float noiseAmplification = uNoiseIntensity / 100; noiseAmplification = (-1 * pow(2*((vertexColor.x + vertexColor.y + vertexColor.z) / 3) - 1, 2) + 1) * noiseAmplification; // Lessen the effect on depending on how dark the object is, equasion for this is -(2x-1)^{2}+1 noiseAmplification *= vertexColor.w; // The effect would lessen on transparent objects // Random value for each position - float randomValue = rand(quantize(fixedVPos.xyz, noiseSteps)) + float randomValue = rand(quantize(fixedVPos.xyz, uNoiseSteps)) * 2.0 * noiseAmplification - noiseAmplification; @@ -57,7 +57,7 @@ void main() { vec3 newCol = (1.0 - vertexColor.rgb) * randomValue; // Clamps it and turns it back into a vec4 - float distA = length(vertexWorldPos) * distanceScale * noiseDropoff; + float distA = length(vertexWorldPos) * distanceScale * uNoiseDropoff; fragColor = clamp(vec4(newCol.rgb, distA), 0.0, 1.0); // The further away it gets, the less noise gets applied // The further away it gets, the less noise gets applied diff --git a/core/src/main/resources/shaders/normal.vert b/core/src/main/resources/shaders/normal.vert index e6a28aa8c..a7fc6cd33 100644 --- a/core/src/main/resources/shaders/normal.vert +++ b/core/src/main/resources/shaders/normal.vert @@ -1,6 +1,7 @@ #version 150 core in vec2 vPosition; + out vec2 TexCoord; /** diff --git a/core/src/main/resources/shaders/standard.vert b/core/src/main/resources/shaders/standard.vert index 316559b6e..bcff6d9c8 100644 --- a/core/src/main/resources/shaders/standard.vert +++ b/core/src/main/resources/shaders/standard.vert @@ -8,15 +8,15 @@ out vec4 vertexColor; out vec3 vertexWorldPos; out float vertexYPos; -uniform bool whiteWorld; +uniform bool uWhiteWorld; -uniform mat4 combinedMatrix; -uniform vec3 modelOffset; -uniform float worldYOffset; +uniform mat4 uCombinedMatrix; +uniform vec3 uModelOffset; +uniform float uWorldYOffset; -uniform int worldSkyLight; -uniform sampler2D lightMap; -uniform float mircoOffset; +uniform int uWorldSkyLight; +uniform sampler2D uLightMap; +uniform float uMircoOffset; /** @@ -33,9 +33,9 @@ void main() { vPos = vPosition; // This is so it can be passed to the fragment shader - vertexWorldPos = vPosition.xyz + modelOffset; + vertexWorldPos = vPosition.xyz + uModelOffset; - vertexYPos = vPosition.y + worldYOffset; + vertexYPos = vPosition.y + uWorldYOffset; uint meta = vPosition.a; @@ -44,23 +44,23 @@ void main() // 0b01 = positive offset // 0b11 = negative offset // format is: 0b00zzyyxx - float mx = (mirco & 1u)!=0u ? mircoOffset : 0.0; + float mx = (mirco & 1u)!=0u ? uMircoOffset : 0.0; mx = (mirco & 2u)!=0u ? -mx : mx; - float my = (mirco & 4u)!=0u ? mircoOffset : 0.0; + float my = (mirco & 4u)!=0u ? uMircoOffset : 0.0; my = (mirco & 8u)!=0u ? -my : my; - float mz = (mirco & 16u)!=0u ? mircoOffset : 0.0; + float mz = (mirco & 16u)!=0u ? uMircoOffset : 0.0; mz = (mirco & 32u)!=0u ? -mz : mz; uint lights = meta & 0xFFu; float light2 = (mod(float(lights), 16.0)+0.5) / 16.0; float light = (float(lights/16u)+0.5) / 16.0; - vertexColor = vec4(texture(lightMap, vec2(light, light2)).xyz, 1.0); + vertexColor = vec4(texture(uLightMap, vec2(light, light2)).xyz, 1.0); - if (!whiteWorld) + if (!uWhiteWorld) { vertexColor *= color; } - gl_Position = combinedMatrix * vec4(vertexWorldPos + vec3(mx, 0, mz), 1.0); + gl_Position = uCombinedMatrix * vec4(vertexWorldPos + vec3(mx, 0, mz), 1.0); } From 1d0cb048cd03543dafcb4ef32d95d1efd83abce6 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 13 Jul 2024 12:54:21 -0500 Subject: [PATCH 085/104] Default logging to only write errors to chat --- .../distanthorizons/core/config/Config.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index e79137958..0ace849e4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -1101,63 +1101,63 @@ public class Config // TODO add change all option // TODO default to error chat and info file public static ConfigEntry logWorldGenEvent = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log information about the world generation process. \n" + "This can be useful for debugging.") .build(); public static ConfigEntry logWorldGenPerformance = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log performance about the world generation process. \n" + "This can be useful for debugging.") .build(); public static ConfigEntry logWorldGenLoadEvent = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log information about the world generation process. \n" + "This can be useful for debugging.") .build(); public static ConfigEntry logLodBuilderEvent = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log information about the LOD generation process. \n" + "This can be useful for debugging.") .build(); public static ConfigEntry logRendererBufferEvent = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log information about the renderer buffer process. \n" + "This can be useful for debugging.") .build(); public static ConfigEntry logRendererGLEvent = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log information about the renderer OpenGL process. \n" + "This can be useful for debugging.") .build(); public static ConfigEntry logFileReadWriteEvent = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log information about file read/write operations. \n" + "This can be useful for debugging.") .build(); public static ConfigEntry logFileSubDimEvent = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log information about file sub-dimension operations. \n" + "This can be useful for debugging.") .build(); public static ConfigEntry logNetworkEvent = new ConfigEntry.Builder() - .set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) + .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT) .comment("" + "If enabled, the mod will log information about network operations. \n" + "This can be useful for debugging.") From 9c0f5865f6250212913ddd0ad85368871988fda4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 14 Jul 2024 07:25:45 -0500 Subject: [PATCH 086/104] add missing genericRendering to IDhApiGraphicsConfig --- .../api/interfaces/config/client/IDhApiGraphicsConfig.java | 1 + .../external/methods/config/client/DhApiGraphicsConfig.java | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java index d7c2792f4..f69869aeb 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java @@ -41,6 +41,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup IDhApiFogConfig fog(); IDhApiAmbientOcclusionConfig ambientOcclusion(); IDhApiNoiseTextureConfig noiseTexture(); + IDhApiGenericRenderingConfig genericRendering(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java index a65bdffba..ef4f66c74 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java @@ -39,9 +39,13 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig // inner layers // //==============// + @Override public IDhApiFogConfig fog() { return DhApiFogConfig.INSTANCE; } + @Override public IDhApiAmbientOcclusionConfig ambientOcclusion() { return DhApiAmbientOcclusionConfig.INSTANCE; } + @Override public IDhApiNoiseTextureConfig noiseTexture() { return DhApiNoiseTextureConfig.INSTANCE; } + @Override public IDhApiGenericRenderingConfig genericRendering() { return DhApiGenericRenderingConfig.INSTANCE; } From fa22a4f27b59c87351264484f36a3f2b89e4152b Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 14 Jul 2024 08:41:18 -0500 Subject: [PATCH 087/104] Add a optional memory cache to the IDhApiTerrainDataRepo --- .../block/IDhApiBlockStateWrapper.java | 3 +- .../data/IDhApiTerrainDataCache.java | 21 ++ .../data/IDhApiTerrainDataRepo.java | 81 ++++++- .../methods/data/DhApiTerrainDataCache.java | 87 +++++++ .../methods/data/DhApiTerrainDataRepo.java | 223 +++++++++++------- 5 files changed, 317 insertions(+), 98 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataCache.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataCache.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java index 4d363005d..8a71a090f 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/block/IDhApiBlockStateWrapper.java @@ -39,7 +39,8 @@ public interface IDhApiBlockStateWrapper extends IDhApiUnsafeWrapper boolean isLiquid(); /** - * Returns the full serialized form of the given block. + * Returns the full serialized form of the given block + * as defined by DH's serialization methods. * @since API 3.0.0 */ String getSerialString(); diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataCache.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataCache.java new file mode 100644 index 000000000..a57a8a56e --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataCache.java @@ -0,0 +1,21 @@ +package com.seibel.distanthorizons.api.interfaces.data; + +/** + * Can be used to drastically speed up repeat read operations in {@link IDhApiTerrainDataRepo}. + * + * @see IDhApiTerrainDataRepo + * + * @author James Seibel + * @version 2024-7-14 + * @since API 3.0.0 + */ +public interface IDhApiTerrainDataCache +{ + /** + * Removes any data that's currently stored in this cache. + * This cane be done to free up memory or invalidate + * the cache so fresh data can be pulled in. + */ + void clear(); + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataRepo.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataRepo.java index 2a4f81e24..45f8c1d72 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataRepo.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/data/IDhApiTerrainDataRepo.java @@ -29,6 +29,8 @@ import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint; /** * Used to interface with Distant Horizons' terrain data. * + * @see IDhApiTerrainDataCache + * * @author James Seibel * @version 2023-6-22 * @since API 1.0.0 @@ -40,29 +42,50 @@ public interface IDhApiTerrainDataRepo // getters // //=========// - /** Returns the terrain datapoint at the given block position, at/or containing the given Y position. */ - DhApiResult getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ); - /** Returns every datapoint in the column located at the given block X and Z position top to bottom. */ - DhApiResult getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ); + /** @see IDhApiTerrainDataRepo#getSingleDataPointAtBlockPos(IDhApiLevelWrapper, int, int, int, IDhApiTerrainDataCache) */ + default DhApiResult getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) { return this.getSingleDataPointAtBlockPos(levelWrapper, blockPosX, blockPosY, blockPosZ, null); } + /** + * Returns the terrain datapoint at the given block position, at/or containing the given Y position. + * @since API 3.0.0 + */ + DhApiResult getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ, IDhApiTerrainDataCache dataCache); + /** @see IDhApiTerrainDataRepo#getColumnDataAtBlockPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */ + default DhApiResult getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ) { return this.getColumnDataAtBlockPos(levelWrapper, blockPosX, blockPosZ, null); } + /** + * Returns every datapoint in the column located at the given block X and Z position top to bottom. + * @since API 3.0.0 + */ + DhApiResult getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ, IDhApiTerrainDataCache dataCache); + + /** @see IDhApiTerrainDataRepo#getAllTerrainDataAtChunkPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */ + default DhApiResult getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ) { return this.getAllTerrainDataAtChunkPos(levelWrapper, chunkPosX, chunkPosZ, null); } /** * Returns every datapoint in the given chunk's X and Z position.

* * The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex]
* RelativeBlockX/Z are relative to the block position closest to negative infinity in the chunk's position.
* The column data is ordered from top to bottom. Note: each column may have a different number of values.
+ * + * @since API 3.0.0 */ - DhApiResult getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ); + DhApiResult getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ, IDhApiTerrainDataCache dataCache); + /** @see IDhApiTerrainDataRepo#getAllTerrainDataAtRegionPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */ + default DhApiResult getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ) { return this.getAllTerrainDataAtRegionPos(levelWrapper, regionPosX, regionPosZ, null); } /** * Returns every datapoint in the given region's X and Z position.

* * The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex]
* RelativeBlockX/Z are relative to the block position closest to negative infinity in the region's position.
* The column data is ordered from top to bottom. Note: each column may have a different number of values.
+ * + * @since API 3.0.0 */ - DhApiResult getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ); + DhApiResult getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ, IDhApiTerrainDataCache dataCache); + /** @see IDhApiTerrainDataRepo#getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper, byte, int, int, IDhApiTerrainDataCache) */ + default DhApiResult getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ) { return this.getAllTerrainDataAtDetailLevelAndPos(levelWrapper, detailLevel, posX, posZ, null); } /** * Returns every datapoint in the column located at the given detail level and X/Z position.
* This can be used to return terrain data for non-standard sizes (IE 2x2 blocks or 2x2 chunks). @@ -71,20 +94,42 @@ public interface IDhApiTerrainDataRepo * Every increase doubles the width of the returned area.
* Example values: 0 = block, 1 = 2x2 blocks, 2 = 4x4 blocks, ... 4 = chunk (16x16 blocks), ... 9 = region (512x512 blocks)
* See {@link EDhApiDetailLevel} for more information. + * + * @since API 3.0.0 */ - DhApiResult getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ); + DhApiResult getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ, IDhApiTerrainDataCache dataCache); + + + + /** @see IDhApiTerrainDataRepo#raycast(IDhApiLevelWrapper, double, double, double, float, float, float, int, IDhApiTerrainDataCache) */ + default DhApiResult raycast( + IDhApiLevelWrapper levelWrapper, + double rayOriginX, double rayOriginY, double rayOriginZ, + float rayDirectionX, float rayDirectionY, float rayDirectionZ, + int maxRayBlockLength) + { + return this.raycast( + levelWrapper, + rayOriginX, rayOriginY, rayOriginZ, + rayDirectionX, rayDirectionY, rayDirectionZ, + maxRayBlockLength, + null); + } /** * Returns the datapoint and position of the LOD * at the end of the given ray.

* * Will return "success" with a null datapoint if the ray reaches the max length without finding any data. + * + * @since API 3.0.0 */ DhApiResult raycast( IDhApiLevelWrapper levelWrapper, double rayOriginX, double rayOriginY, double rayOriginZ, float rayDirectionX, float rayDirectionY, float rayDirectionZ, - int maxRayBlockLength); + int maxRayBlockLength, + IDhApiTerrainDataCache dataCache); @@ -98,15 +143,27 @@ public interface IDhApiTerrainDataRepo * Notes:
* - Only works if the given {@link IDhApiLevelWrapper} points to a loaded level.
* - If the player travels to this chunk, or the chunk is updated in some other way; your data will be replaced - * by whatever the current chunk is.
- * - This method may not update the LOD data immediately. Any other chunks have - * been queued to update, they will be handled first. + * by whatever the current chunk is.
+ * - This method may not update the LOD data immediately. Any other chunks that have + * been queued to update will be handled first. * * @param levelWrapper the level wrapper that the chunk should be saved to. * @param chunkObjectArray see {@link IDhApiWorldGenerator#generateChunks} for what objects are expected. * @throws ClassCastException if chunkObjectArray doesn't contain the right objects. * The exception will contain the expected object(s). */ - public DhApiResult overwriteChunkDataAsync(IDhApiLevelWrapper levelWrapper, Object[] chunkObjectArray) throws ClassCastException; + DhApiResult overwriteChunkDataAsync(IDhApiLevelWrapper levelWrapper, Object[] chunkObjectArray) throws ClassCastException; + + + + //=========// + // helpers // + //=========// + + /** + * @return a {@link IDhApiTerrainDataCache} backed by {@link java.lang.ref.SoftReference}'s. + * @since API 3.0.0 + */ + IDhApiTerrainDataCache getSoftCache(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataCache.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataCache.java new file mode 100644 index 000000000..37cabfb97 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataCache.java @@ -0,0 +1,87 @@ +package com.seibel.distanthorizons.core.api.external.methods.data; + +import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataCache; +import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongSet; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.SoftReference; + +public class DhApiTerrainDataCache implements IDhApiTerrainDataCache +{ + private final Object modificationLock = new Object(); + private Long2ReferenceOpenHashMap> posToFullDataRef = new Long2ReferenceOpenHashMap<>(); + + private static final Logger LOGGER = LogManager.getLogger(DhApiTerrainDataCache.class.getSimpleName()); + + + + //==================// + // internal methods // + //==================// + + public void add(long pos, FullDataSourceV2 dataSource) + { + synchronized (this.modificationLock) + { + this.posToFullDataRef.put(pos, new SoftReference<>(dataSource)); + } + } + + @Nullable + public FullDataSourceV2 get(long pos) + { + synchronized (this.modificationLock) + { + SoftReference ref = this.posToFullDataRef.get(pos); + if (ref != null) + { + return ref.get(); + } + else + { + return null; + } + } + } + + + + //=============// + // API methods // + //=============// + + @Override + public void clear() + { + synchronized (this.modificationLock) + { + LongSet keySet = this.posToFullDataRef.keySet(); + for (long pos : keySet) + { + SoftReference dataRef = this.posToFullDataRef.remove(pos); + if (dataRef != null) + { + FullDataSourceV2 dataSource = dataRef.get(); + if (dataSource != null) + { + try + { + dataSource.close(); + } + catch (Exception e) + { + LOGGER.warn("Unable to close data source, error: [" + e.getMessage() + "].", e); + } + } + } + } + } + } + + + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java index c04d786ab..cf7d337c0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.api.external.methods.data; +import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataCache; import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; import com.seibel.distanthorizons.api.objects.DhApiResult; import com.seibel.distanthorizons.api.objects.data.DhApiRaycastResult; @@ -49,6 +50,7 @@ import com.seibel.distanthorizons.core.util.math.Vec3i; import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.concurrent.ExecutionException; @@ -56,9 +58,6 @@ import java.util.concurrent.ExecutionException; /** * Allows interfacing with the terrain data Distant Horizons has stored. - * - * @author James Seibel - * @version 2022-11-19 */ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo { @@ -68,12 +67,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo // debugging values private static volatile boolean debugThreadRunning = false; - private static String currentDebugBiomeName = ""; - private static int currentDebugBlockColorInt = -1; + private static DhApiTerrainDataCache debugDataCache = new DhApiTerrainDataCache(); private static DhApiVec3i currentDebugVec3i = new Vec3i(); + //=============// + // constructor // + //=============// + private DhApiTerrainDataRepo() { @@ -86,41 +88,32 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo //================// @Override - public DhApiResult getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) - { - return getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY); - } + public DhApiResult getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ, @Nullable IDhApiTerrainDataCache dataCache) + { return getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY, dataCache); } @Override - public DhApiResult getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ) - { - return getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null); - } + public DhApiResult getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ, @Nullable IDhApiTerrainDataCache dataCache) + { return getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null, dataCache); } @Override - public DhApiResult getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ) - { - return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPosX, chunkPosZ)); - } + public DhApiResult getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ, @Nullable IDhApiTerrainDataCache dataCache) + { return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPosX, chunkPosZ), dataCache); } @Override - public DhApiResult getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ) - { - return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ)); - } + public DhApiResult getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ, @Nullable IDhApiTerrainDataCache dataCache) + { return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ), dataCache); } @Override - public DhApiResult getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ) - { - return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(detailLevel, posX, posZ)); - } + public DhApiResult getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ, @Nullable IDhApiTerrainDataCache dataCache) + { return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(detailLevel, posX, posZ), dataCache); } + // private getters // /** Returns a single API terrain datapoint that contains the given Y block position */ - private static DhApiResult getTerrainDataAtBlockYPos(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer blockYPos) + private static DhApiResult getTerrainDataAtBlockYPos(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer blockYPos, @Nullable IDhApiTerrainDataCache dataCache) { - DhApiResult result = getTerrainDataColumnArray(levelWrapper, requestedColumnPos, blockYPos); + DhApiResult result = getTerrainDataColumnArray(levelWrapper, requestedColumnPos, blockYPos, dataCache); if (result.success && result.payload.length > 0) { return DhApiResult.createSuccess(result.message, result.payload[0]); @@ -140,7 +133,9 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo * * will stop and return the in progress data if any errors are encountered. */ - private static DhApiResult getTerrainDataOverAreaForPositionDetailLevel(IDhApiLevelWrapper levelWrapper, DhLodPos requestedAreaPos) + private static DhApiResult getTerrainDataOverAreaForPositionDetailLevel( + IDhApiLevelWrapper levelWrapper, DhLodPos requestedAreaPos, + @Nullable IDhApiTerrainDataCache dataCache) { DhLodPos startingBlockPos = requestedAreaPos.getCornerLodPos(LodUtil.BLOCK_DETAIL_LEVEL); int widthOfAreaInBlocks = BitShiftUtil.powerOfTwo(requestedAreaPos.detailLevel); @@ -154,7 +149,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo for (int z = 0; z < widthOfAreaInBlocks; z++) { DhLodPos blockColumnPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, startingBlockPos.x + x, startingBlockPos.z + z); - DhApiResult result = getTerrainDataColumnArray(levelWrapper, blockColumnPos, null); + DhApiResult result = getTerrainDataColumnArray(levelWrapper, blockColumnPos, null, dataCache); if (result.success) { returnArray[x][z] = result.payload; @@ -177,8 +172,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo * If the ApiResult is successful there will be an array of data.
* The returned array will be empty if no data could be retrieved. */ - private static DhApiResult getTerrainDataColumnArray(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer nullableBlockYPos) + private static DhApiResult getTerrainDataColumnArray( + IDhApiLevelWrapper levelWrapper, + DhLodPos requestedColumnPos, Integer nullableBlockYPos, + @Nullable IDhApiTerrainDataCache apiDataCache) { + //============// + // validation // + //============// + AbstractDhWorld currentWorld = SharedApi.getAbstractDhWorld(); if (currentWorld == null) { @@ -194,6 +196,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper; + if (!(apiDataCache instanceof DhApiTerrainDataCache)) + { + // custom level wrappers aren't supported, + // the API user must get a level wrapper from our code somewhere + return DhApiResult.createFail("Unsupported [" + IDhApiTerrainDataCache.class.getSimpleName() + "] implementation, only the core class [" + DhApiTerrainDataCache.class.getSimpleName() + "] is a valid parameter."); + } + DhApiTerrainDataCache dataCache = (DhApiTerrainDataCache) apiDataCache; + + IDhLevel level = currentWorld.getLevel(coreLevelWrapper); if (level == null) { @@ -209,70 +220,96 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo DhLodPos relativePos = requestedColumnPos.getDhSectionRelativePositionForDetailLevel(); + + //=====================// + // get the data source // + //=====================// + try { - // attempt to get/generate the data source for this section - FullDataSourceV2 dataSource = level.getFullDataProvider().getAsync(sectionPos).get(); + FullDataSourceV2 dataSource = null; + + // try using the cached data if possible + if (dataCache != null) + { + dataSource = dataCache.get(sectionPos); + } + if (dataSource == null) { - return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + DhSectionPos.toString(sectionPos) + "]."); - } - else - { - // attempt to get the LOD data from the data source - FullDataPointIdMap mapping = dataSource.mapping; - LongArrayList dataColumn = dataSource.get(relativePos.x, relativePos.z); - if (dataColumn != null) + // attempt to get/generate the data source for this section + dataSource = level.getFullDataProvider().getAsync(sectionPos).get(); + if (dataSource == null) { - int dataColumnIndexCount = dataColumn.size(); - DhApiTerrainDataPoint[] returnArray = new DhApiTerrainDataPoint[dataColumnIndexCount]; - long dataPoint; + return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + DhSectionPos.toString(sectionPos) + "]."); + } + dataCache.add(sectionPos, dataSource); + } + + + + //===============================// + // get LOD data from data source // + //===============================// + + FullDataPointIdMap mapping = dataSource.mapping; + LongArrayList dataColumn = dataSource.get(relativePos.x, relativePos.z); + if (dataColumn != null) + { + int dataColumnIndexCount = dataColumn.size(); + DhApiTerrainDataPoint[] returnArray = new DhApiTerrainDataPoint[dataColumnIndexCount]; + long dataPoint; + + boolean getSpecificYCoordinate = nullableBlockYPos != null; + int levelMinimumHeight = levelWrapper.getMinHeight(); + + + // search for a datapoint that contains the block y position + for (int i = 0; i < dataColumnIndexCount; i++) + { + dataPoint = dataColumn.getLong(i); - boolean getSpecificYCoordinate = nullableBlockYPos != null; - int levelMinimumHeight = levelWrapper.getMinHeight(); - - - // search for a datapoint that contains the block y position - for (int i = 0; i < dataColumnIndexCount; i++) + if (!getSpecificYCoordinate) { - dataPoint = dataColumn.getLong(i); - - if (!getSpecificYCoordinate) + // if we aren't look for a specific datapoint, add each datapoint to the return array + returnArray[i] = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint); + } + else + { + // we are looking for a specific datapoint, + // don't look at null ones + if (dataPoint != 0) { - // if we aren't look for a specific datapoint, add each datapoint to the return array - returnArray[i] = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint); - } - else - { - // we are looking for a specific datapoint, - // don't look at null ones - if (dataPoint != 0) + int requestedY = nullableBlockYPos; + int bottomY = FullDataPointUtil.getBottomY(dataPoint) + levelMinimumHeight; + int height = FullDataPointUtil.getHeight(dataPoint); + int topY = bottomY + height; + + // does this datapoint contain the requested Y position? + if (bottomY <= requestedY && requestedY < topY) // blockPositions start from the bottom of the block, thus "<=" for bottomY, just "<" for topY { - int requestedY = nullableBlockYPos; - int bottomY = FullDataPointUtil.getBottomY(dataPoint) + levelMinimumHeight; - int height = FullDataPointUtil.getHeight(dataPoint); - int topY = bottomY + height; - - // does this datapoint contain the requested Y position? - if (bottomY <= requestedY && requestedY < topY) // blockPositions start from the bottom of the block, thus "<=" for bottomY, just "<" for topY - { - // this datapoint contains the requested block position, return it - DhApiTerrainDataPoint apiTerrainData = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint); - return DhApiResult.createSuccess(new DhApiTerrainDataPoint[]{apiTerrainData}); - } + // this datapoint contains the requested block position, return it + DhApiTerrainDataPoint apiTerrainData = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint); + return DhApiResult.createSuccess(new DhApiTerrainDataPoint[]{apiTerrainData}); } } } - - // return all collected data - return DhApiResult.createSuccess(returnArray); } - // the requested data wasn't present in this column (and/or the column wasn't able to be accessed/generated) - return DhApiResult.createSuccess(new DhApiTerrainDataPoint[0]); + // return all collected data + return DhApiResult.createSuccess(returnArray); } + + // the requested data wasn't present in this column (and/or the column wasn't able to be accessed/generated) + return DhApiResult.createSuccess(new DhApiTerrainDataPoint[0]); } catch (InterruptedException | ExecutionException e) + { + // shouldn't normally happen, but just in case + LOGGER.error("getTerrainDataColumnArray operation canceled. Error: [" + e.getMessage() + "]", e); + return DhApiResult.createFail("Operation cancled before it could complete: [" + e.getMessage() + "]."); + } + catch (Exception e) { // shouldn't normally happen, but just in case LOGGER.error("Unexpected exception in getTerrainDataColumnArray. Error: [" + e.getMessage() + "]", e); @@ -306,9 +343,11 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo IDhApiLevelWrapper levelWrapper, double rayOriginX, double rayOriginY, double rayOriginZ, float rayDirectionX, float rayDirectionY, float rayDirectionZ, - int maxRayBlockLength) + int maxRayBlockLength, + @Nullable + IDhApiTerrainDataCache dataCache) { - return this.raycastLodData(levelWrapper, new Vec3d(rayOriginX, rayOriginY, rayOriginZ), new Vec3f(rayDirectionX, rayDirectionY, rayDirectionZ), maxRayBlockLength); + return this.raycastLodData(levelWrapper, new Vec3d(rayOriginX, rayOriginY, rayOriginZ), new Vec3f(rayDirectionX, rayDirectionY, rayDirectionZ), maxRayBlockLength, dataCache); } /** @@ -317,7 +356,12 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo * Works by walking through the world and attempting to get the LOD
* data present at each step. */ - private DhApiResult raycastLodData(IDhApiLevelWrapper levelWrapper, Vec3d rayOrigin, Vec3f rayDirection, int maxRayBlockLength) + private DhApiResult raycastLodData( + IDhApiLevelWrapper levelWrapper, + Vec3d rayOrigin, Vec3f rayDirection, + int maxRayBlockLength, + @Nullable + IDhApiTerrainDataCache dataCache) { rayDirection.normalize(); @@ -346,7 +390,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo for (Vec3i columnPos : columnPositions) { // check each column - DhApiResult result = this.getColumnDataAtBlockPos(levelWrapper, columnPos.x, columnPos.z); + DhApiResult result = this.getColumnDataAtBlockPos(levelWrapper, columnPos.x, columnPos.z, dataCache); if (!result.success) { // if there was an error, stop and return it @@ -469,6 +513,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo + //=============// + // API helpers // + //=============// + + @Override + public IDhApiTerrainDataCache getSoftCache() { return new DhApiTerrainDataCache(); } + + + //===============// // debug methods // //===============// @@ -485,15 +538,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo Thread thread = new Thread(() -> { try { - DhApiResult single = getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY); - DhApiResult column = getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null); + DhApiResult single = getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY, debugDataCache); + DhApiResult column = getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null, debugDataCache); DhLodPos chunkPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ).convertToDetailLevel(LodUtil.CHUNK_DETAIL_LEVEL); - DhApiResult area = getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, chunkPos); + DhApiResult area = getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, chunkPos, debugDataCache); IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - DhApiResult rayCast = INSTANCE.raycastLodData(levelWrapper, MC_RENDER.getCameraExactPosition(), MC_RENDER.getLookAtVector(), 1000); + DhApiResult rayCast = INSTANCE.raycastLodData(levelWrapper, MC_RENDER.getCameraExactPosition(), MC_RENDER.getLookAtVector(), 1000, debugDataCache); if (rayCast.payload != null && !rayCast.payload.pos.equals(currentDebugVec3i)) { currentDebugVec3i = rayCast.payload.pos; From 7165c086e4c87436b6ab79d87f914009d2e284b1 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 14 Jul 2024 09:30:56 -0500 Subject: [PATCH 088/104] Remove render param from DhApiAfterRenderEvent This was causing confussion if deferred rendering (iris shaders) was enabled since the render parameters would change. --- .../abstractEvents/DhApiAfterRenderEvent.java | 15 +++++++++------ .../core/api/internal/ClientApi.java | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java index 05da17b96..7bc6dab51 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiAfterRenderEvent.java @@ -26,17 +26,20 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp /** * Fired after Distant Horizons finishes rendering a frame.
* At this point DH will have also finished cleaning up any modifications it - * did to the OpenGL state, so the state should be back to Minecraft's defaults. + * did to the OpenGL state, so the state should be back to Minecraft's defaults.

* + * Note: as of API v 3.0.0 no {@link DhApiRenderParam} is included in this event + * because the specific parameters may change + * depending on whether deferred rendering is enabled or not. + * * @author James Seibel - * @version 2024-1-31 - * @see DhApiRenderParam + * @version 2024-7-14 * @since API 1.0.0 */ -public abstract class DhApiAfterRenderEvent implements IDhApiEvent +public abstract class DhApiAfterRenderEvent implements IDhApiEvent { /** Fired after Distant Horizons finishes rendering fake chunks. */ - public abstract void afterRender(DhApiEventParam event); + public abstract void afterRender(DhApiEventParam event); //=========================// @@ -44,6 +47,6 @@ public abstract class DhApiAfterRenderEvent implements IDhApiEvent event) { this.afterRender(event); } + public final void fireEvent(DhApiEventParam event) { this.afterRender(event); } } \ No newline at end of file diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index c15d9b57f..b37910884 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -552,7 +552,7 @@ public class ClientApi if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering()) { - ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam); + ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null); } } else if (Config.Client.Advanced.Debugging.rendererMode.get() == EDhApiRendererMode.DEBUG) @@ -573,7 +573,7 @@ public class ClientApi if (DhApi.Delayed.renderProxy.getDeferTransparentRendering()) { - ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam); + ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null); } } } From 4f2b8e6d8dd953ddb77b4178e7d665e2fd83d91b Mon Sep 17 00:00:00 2001 From: James Seibel Date: Mon, 15 Jul 2024 20:22:29 -0500 Subject: [PATCH 089/104] VBO handler commenting --- .../render/bufferBuilding/ColumnRenderBuffer.java | 7 +++++-- .../render/bufferBuilding/ColumnRenderBufferBuilder.java | 5 ----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java index 8762bec32..442a83625 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java @@ -50,8 +50,11 @@ public class ColumnRenderBuffer implements AutoCloseable private static final long MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS = 1_000_000; - public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4; // TODO what does the 4 represent - public static final int MAX_QUADS_PER_BUFFER = (1024 * 1024 * 1) / QUADS_BYTE_SIZE; // TODO what do these multiples represent? + /** number of bytes a single quad takes */ + public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4; + /** how big a single VBO can be in bytes */ + public static final int MAX_VBO_BYTE_SIZE = 1024 * 1024; // 1 MB + public static final int MAX_QUADS_PER_BUFFER = MAX_VBO_BYTE_SIZE / QUADS_BYTE_SIZE; public static final int FULL_SIZED_BUFFER = MAX_QUADS_PER_BUFFER * QUADS_BYTE_SIZE; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java index 02c064408..b5751e34b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java @@ -54,11 +54,6 @@ public class ColumnRenderBufferBuilder private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public static final int MAX_NUMBER_OF_CONCURRENT_CALLS_PER_THREAD = 3; - public static int maxNumberOfConcurrentCalls = MAX_NUMBER_OF_CONCURRENT_CALLS_PER_THREAD; - - - //==============// // vbo building // From 9147b139c7c72c0af16052eec1254249ff5dd5a0 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 18 Jul 2024 07:39:52 -0500 Subject: [PATCH 090/104] Increase max VBO size 1 MB -> 10 MB --- .../dataObjects/render/bufferBuilding/ColumnRenderBuffer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java index 442a83625..8a95bc2c7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBuffer.java @@ -53,7 +53,7 @@ public class ColumnRenderBuffer implements AutoCloseable /** number of bytes a single quad takes */ public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4; /** how big a single VBO can be in bytes */ - public static final int MAX_VBO_BYTE_SIZE = 1024 * 1024; // 1 MB + public static final int MAX_VBO_BYTE_SIZE = 10 * 1024 * 1024; // 10 MB public static final int MAX_QUADS_PER_BUFFER = MAX_VBO_BYTE_SIZE / QUADS_BYTE_SIZE; public static final int FULL_SIZED_BUFFER = MAX_QUADS_PER_BUFFER * QUADS_BYTE_SIZE; From f442ab56c0ee6332a524612bf901126906093045 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 18 Jul 2024 07:40:04 -0500 Subject: [PATCH 091/104] Remove unnecessary glIsProgram() call --- .../distanthorizons/core/render/renderer/LodRenderer.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index 681364ac2..2a6e2e688 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -485,11 +485,6 @@ public class LodRenderer shaderProgram = shaderProgramOverride; } - if (!GL32.glIsProgram(shaderProgram.getId())) - { - throw new IllegalStateException("No GL program exists with the ID: [" + shaderProgram.getId() + "]. This either means a shader program was freed while it was still in use or was never created."); - } - shaderProgram.bind(); shaderProgram.setModelOffsetPos(modelPos); From 99dc644adfd9725ac2e4d1091545d19806f579bd Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 20 Jul 2024 10:45:43 -0500 Subject: [PATCH 092/104] Add AbstractDhApiChunkWorldGenerator.generateApiChunk() --- .../AbstractDhApiChunkWorldGenerator.java | 49 ++++- .../worldGenerator/IDhApiWorldGenerator.java | 1 + .../transformers/LodDataBuilder.java | 30 ++- .../SubDimensionLevelMatcher.java | 4 +- .../core/generation/WorldGenerationQueue.java | 10 +- .../distanthorizons/core/pos/DhLodPos.java | 2 +- .../core/pos/DhSectionPos.java | 30 +-- .../core/sql/repo/FullDataSourceV1Repo.java | 2 +- .../core/sql/repo/FullDataSourceV2Repo.java | 6 +- .../core/util/objects/quadTree/QuadTree.java | 2 +- .../src/test/java/tests/DhSectionPosTest.java | 191 +++++++++-------- core/src/test/java/tests/QuadTreeTest.java | 192 +++++++++--------- 12 files changed, 303 insertions(+), 216 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java index e34fe2ecb..09e71d706 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java @@ -22,6 +22,8 @@ package com.seibel.distanthorizons.api.interfaces.override.worldGenerator; import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; +import com.seibel.distanthorizons.api.objects.data.DhApiChunk; +import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; import java.io.Closeable; @@ -77,13 +79,41 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh }, worldGeneratorThreadPool); } + @Override + public final CompletableFuture generateApiChunks( + int chunkPosMinX, + int chunkPosMinZ, + byte granularity, + byte targetDataDetail, + EDhApiDistantGeneratorMode generatorMode, + ExecutorService worldGeneratorThreadPool, + Consumer resultConsumer + ) + { + return CompletableFuture.runAsync(() -> + { + // TODO what does this mean? + int genChunkWidth = BitShiftUtil.powerOfTwo(granularity - 4); + + for (int chunkX = chunkPosMinX; chunkX < chunkPosMinX + genChunkWidth; chunkX++) + { + for (int chunkZ = chunkPosMinZ; chunkZ < chunkPosMinZ + genChunkWidth; chunkZ++) + { + DhApiChunk apiChunk = this.generateApiChunk(chunkX, chunkZ, generatorMode); + resultConsumer.accept(apiChunk); + } + } + }, worldGeneratorThreadPool); + } + + /** * This method is called to generate terrain over a given area * from a thread defined by Distant Horizons.

* * @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level) * @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level) - * @param generatorMode how far into the world gen pipeline this method run. See {@link EDhApiDistantGeneratorMode} for additional documentation. + * @param generatorMode how far into the world gen pipeline this method should run. See {@link EDhApiDistantGeneratorMode} for additional documentation. * * @return See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks} * for the list of Object's this method should return along with additional documentation. @@ -92,4 +122,21 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh */ public abstract Object[] generateChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode); + /** + * This method is called to generate terrain over a given area + * from a thread defined by Distant Horizons.

+ * + * @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level) + * @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level) + * @param generatorMode how far into the world gen pipeline this method should run. See {@link EDhApiDistantGeneratorMode} for additional documentation. + * + * @return A {@link DhApiChunk} with the generated {@link DhApiTerrainDataPoint} including air blocks. + * Note: if air blocks aren't included with the proper lighting, lower detail levels will appear as black/unlit. + * + * @see IDhApiWorldGenerator#generateApiChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) + * + * @since API 3.0.0 + */ + public abstract DhApiChunk generateApiChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode); + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java index eb1831973..7861040cc 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java @@ -154,6 +154,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable * * After the {@link DhApiChunk} has been generated, it should be passed into the * resultConsumer's {@link Consumer#accept(Object)} method. + * Note: if air blocks aren't included in the with the {@link DhApiChunk} with proper lighting, lower detail levels will appear as black/unlit. * * @implNote the default implementation of this method throws an {@link UnsupportedOperationException}, * and must be overridden when {@link #getReturnType()} returns {@link EDhApiWorldGeneratorReturnType#API_CHUNKS}. diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index 1fbf49e02..2e939718a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -73,7 +73,7 @@ public class LodDataBuilder sectionPosX = (sectionPosX < 0) ? ((sectionPosX + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPosX / NUMB_OF_CHUNKS_WIDE); int sectionPosZ = chunkWrapper.getChunkPos().z; sectionPosZ = (sectionPosZ < 0) ? ((sectionPosZ + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPosZ / NUMB_OF_CHUNKS_WIDE); - long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + long pos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos); dataSource.isEmpty = false; @@ -302,14 +302,19 @@ public class LodDataBuilder /** @throws ClassCastException if an API user returns the wrong object type(s) */ - public static FullDataSourceV2 createFromApiChunkData(DhApiChunk dataPoints) throws ClassCastException, DataCorruptedException + public static FullDataSourceV2 createFromApiChunkData(DhApiChunk apiChunk) throws ClassCastException, DataCorruptedException { - FullDataSourceV2 accessor = FullDataSourceV2.createEmpty(DhSectionPos.encode(new DhChunkPos(dataPoints.chunkPosX, dataPoints.chunkPosZ))); - for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++) + // TODO + long pos = DhSectionPos.convertToDetailLevel(DhSectionPos.encodeChunkPos(apiChunk.chunkPosX, apiChunk.chunkPosZ), DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); + int relSourceBlockX = Math.abs(apiChunk.chunkPosX % 4) * LodUtil.CHUNK_WIDTH; + int relSourceBlockZ = Math.abs(apiChunk.chunkPosZ % 4) * LodUtil.CHUNK_WIDTH; + + FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos); + for (int relBlockZ = 0; relBlockZ < LodUtil.CHUNK_WIDTH; relBlockZ++) { - for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++) + for (int relBlockX = 0; relBlockX < LodUtil.CHUNK_WIDTH; relBlockX++) { - List columnDataPoints = dataPoints.getDataPoints(relX, relZ); + List columnDataPoints = apiChunk.getDataPoints(relBlockX, relBlockZ); // this null check does 2 nice things at the same time: @@ -323,7 +328,7 @@ public class LodDataBuilder { DhApiTerrainDataPoint dataPoint = columnDataPoints.get(index); - int id = accessor.mapping.addIfNotPresentAndGetId( + int id = dataSource.mapping.addIfNotPresentAndGetId( (IBiomeWrapper) (dataPoint.biomeWrapper), (IBlockStateWrapper) (dataPoint.blockStateWrapper) ); @@ -331,7 +336,7 @@ public class LodDataBuilder packedDataPoints.set(index, FullDataPointUtil.encode( id, dataPoint.topYBlockPos - dataPoint.bottomYBlockPos, - dataPoint.bottomYBlockPos - dataPoints.topYBlockPos, + dataPoint.bottomYBlockPos - apiChunk.topYBlockPos, (byte) (dataPoint.blockLightLevel), (byte) (dataPoint.skyLightLevel) )); @@ -339,11 +344,14 @@ public class LodDataBuilder // TODO add the ability for API users to define a different compression mode // or add a "unkown" compression mode - accessor.setSingleColumn(packedDataPoints, relX, relZ, EDhApiWorldGenerationStep.LIGHT, EDhApiWorldCompressionMode.MERGE_SAME_BLOCKS); + dataSource.setSingleColumn( + packedDataPoints, + relBlockX + relSourceBlockX, relBlockZ + relSourceBlockZ, + EDhApiWorldGenerationStep.LIGHT, EDhApiWorldCompressionMode.MERGE_SAME_BLOCKS); + dataSource.isEmpty = false; } } - - return accessor; + return dataSource; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java index 6089fb823..9d69994cf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java @@ -190,7 +190,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable } FullDataSourceV2 newChunkSizedFullDataView = FullDataSourceV2.createFromChunk(newlyLoadedChunk); // convert to a data source for easier comparing - FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encode(this.playerData.playerBlockPos)); + FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encodeLodPos(this.playerData.playerBlockPos)); newDataSource.update(newChunkSizedFullDataView); @@ -215,7 +215,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable // get the data source to compare against try (IDhLevel tempLevel = new DhClientLevel(new ClientOnlySaveStructure(), this.currentClientLevel, testLevelFolder, false)) { - testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encode(this.playerData.playerBlockPos)).join(); + testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encodeLodPos(this.playerData.playerBlockPos)).join(); if (testFullDataSource == null) { continue; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java index 95b712948..8e2724c32 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java @@ -343,7 +343,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb //LOGGER.trace("Duplicate generation section " + taskPos + " with granularity [" + granularity + "] at " + chunkPosMin + ". Skipping..."); // sending a success result is necessary to make sure the render sections are reloaded correctly - newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); + newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encodePos(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); return false; } this.alreadyGeneratedPosHashSet.put(newTaskGroup.group.pos, Thread.currentThread().getStackTrace()); @@ -373,21 +373,21 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb // don't log the shutdown exceptions if (!LodUtil.isInterruptOrReject(exception)) { - LOGGER.error("Error generating data for section " + taskPos, exception); + LOGGER.error("Error generating data for pos: " + DhSectionPos.toString(taskPos), exception); } newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateFail())); } else { - newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); + newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encodePos(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); } boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, newTaskGroup); - LodUtil.assertTrue(worked); + LodUtil.assertTrue(worked, "Unable to find in progress generator task with position ["+DhSectionPos.toString(taskPos)+"]"); } catch (Exception e) { - LOGGER.error("Unexpected error completing world gen task: "+taskPos, e); + LOGGER.error("Unexpected error completing world gen task at pos: ["+DhSectionPos.toString(taskPos)+"].", e); } }); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java index 7678ec3e8..af24eefd1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java @@ -174,7 +174,7 @@ public class DhLodPos implements Comparable DhLodPos lodPos = new DhLodPos(this.detailLevel, this.x, this.z); lodPos = lodPos.convertToDetailLevel(sectionDetailLevel); - return DhSectionPos.encode(lodPos.detailLevel, lodPos.x, lodPos.z); + return DhSectionPos.encodePos(lodPos.detailLevel, lodPos.x, lodPos.z); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java index c37fac961..2e74aea6d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java @@ -81,7 +81,7 @@ public class DhSectionPos * This class just holds utility methods for handling a packed * {@link DhSectionPos} and shouldn't be constructed.

* - * Use one of the {@link DhSectionPos#encode(byte, int, int)} methods instead + * Use one of the {@link DhSectionPos#encodePos(byte, int, int)} methods instead */ private DhSectionPos() { } @@ -92,7 +92,7 @@ public class DhSectionPos * no validation is done for whether the detail level is positive * or if the X/Z positions can be represented by available bits. */ - public static long encode(byte detailLevel, int x, int z) + public static long encodePos(byte detailLevel, int x, int z) { long data = 0; data |= detailLevel & DETAIL_LEVEL_MASK; @@ -101,23 +101,27 @@ public class DhSectionPos return data; } - public static long encode(DhBlockPos pos) { return encodeBlockPos(pos.x, pos.z); } - public static long encode(DhBlockPos2D pos) { return encodeBlockPos(pos.x, pos.z); } - public static long encodeBlockPos(int blockX, int blockZ) + // TODO need changing + public static long encodeLodPos(DhBlockPos pos) { return encodeLodBlockPos(pos.x, pos.z); } + public static long encodeLodPos(DhBlockPos2D pos) { return encodeLodBlockPos(pos.x, pos.z); } + public static long encodeLodBlockPos(int blockX, int blockZ) { - long pos = encode(LodUtil.BLOCK_DETAIL_LEVEL, blockX, blockZ); + long pos = encodePos(LodUtil.BLOCK_DETAIL_LEVEL, blockX, blockZ); pos = convertToDetailLevel(pos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); return pos; } - public static long encode(DhChunkPos pos) { return encodeChunkPos(pos.x, pos.z); } - public static long encodeChunkPos(int chunkX, int chunkZ) + public static long encodeLodPos(DhChunkPos pos) { return encodeLodChunkPos(pos.x, pos.z); } + public static long encodeLodChunkPos(int chunkX, int chunkZ) // TODO broken? { - long pos = encode(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ); + long pos = encodePos(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ); pos = convertToDetailLevel(pos, DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL); return pos; } + public static long encodePos(DhChunkPos pos) { return encodeChunkPos(pos.x, pos.z); } + public static long encodeChunkPos(int chunkX, int chunkZ) { return encodePos(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ); } + //============// @@ -143,7 +147,7 @@ public class DhSectionPos z = z * BitShiftUtil.powerOfTwo(detailLevel - newDetailLevel); } - return encode(newDetailLevel, x, z); + return encodePos(newDetailLevel, x, z); } @@ -279,14 +283,14 @@ public class DhSectionPos throw new IllegalStateException("section detail must be greater than 0"); } - return DhSectionPos.encode((byte) (detailLevel - 1), + return DhSectionPos.encodePos((byte) (detailLevel - 1), x * 2 + (child0to3 & 1), z * 2 + BitShiftUtil.half(child0to3 & 2)); } /** Returns this position's child index in its parent */ public static int getChildIndexOfParent(long pos) { return (getX(pos) & 1) + BitShiftUtil.square(getZ(pos) & 1); } - public static long getParentPos(long pos) { return DhSectionPos.encode((byte) (getDetailLevel(pos) + 1), BitShiftUtil.half(getX(pos)), BitShiftUtil.half(getZ(pos))); } + public static long getParentPos(long pos) { return DhSectionPos.encodePos((byte) (getDetailLevel(pos) + 1), BitShiftUtil.half(getX(pos)), BitShiftUtil.half(getZ(pos))); } @@ -297,7 +301,7 @@ public class DhSectionPos throw new IllegalArgumentException("getAdjacentPos can't be UP or DOWN, direction given: ["+dir.name()+"]."); } - return DhSectionPos.encode(getDetailLevel(pos), + return DhSectionPos.encodePos(getDetailLevel(pos), getX(pos) + dir.getNormal().x, getZ(pos) + dir.getNormal().z); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java index a61bc22ab..bc17f045a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java @@ -309,7 +309,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo { if (node != null || includeNullNodes) { - long rootPos = DhSectionPos.encode(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y); + long rootPos = DhSectionPos.encodePos(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y); if (QuadTree.this.isSectionPosInBounds(rootPos)) { this.iteratorPosQueue.enqueue(rootPos); diff --git a/core/src/test/java/tests/DhSectionPosTest.java b/core/src/test/java/tests/DhSectionPosTest.java index c0585a60e..f2ed9b8d4 100644 --- a/core/src/test/java/tests/DhSectionPosTest.java +++ b/core/src/test/java/tests/DhSectionPosTest.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; +import com.seibel.distanthorizons.core.util.LodUtil; import org.junit.Assert; import org.junit.Test; @@ -39,19 +40,19 @@ public class DhSectionPosTest long pos; // zero pos - pos = DhSectionPos.encode((byte) 0, 0, 0); + pos = DhSectionPos.encodePos((byte) 0, 0, 0); assertSectionPosEqual(0, DhSectionPos.getDetailLevel(pos)); assertSectionPosEqual(0, DhSectionPos.getX(pos)); assertSectionPosEqual(0, DhSectionPos.getZ(pos)); // positive values - pos = DhSectionPos.encode((byte) 10, 4, 1); + pos = DhSectionPos.encodePos((byte) 10, 4, 1); assertSectionPosEqual(10, DhSectionPos.getDetailLevel(pos)); assertSectionPosEqual(4, DhSectionPos.getX(pos)); assertSectionPosEqual(1, DhSectionPos.getZ(pos)); // negative position, positive detail level - pos = DhSectionPos.encode((byte) 2, -1, -4); + pos = DhSectionPos.encodePos((byte) 2, -1, -4); assertSectionPosEqual(2, DhSectionPos.getDetailLevel(pos)); assertSectionPosEqual(-1, DhSectionPos.getX(pos)); assertSectionPosEqual(-4, DhSectionPos.getZ(pos)); @@ -63,61 +64,61 @@ public class DhSectionPosTest @Test public void containsPosTest() { - long root = DhSectionPos.encode((byte) 10, 0, 0); - long child = DhSectionPos.encode((byte) 9, 1, 1); + long root = DhSectionPos.encodePos((byte) 10, 0, 0); + long child = DhSectionPos.encodePos((byte) 9, 1, 1); Assert.assertTrue("section pos contains fail", DhSectionPos.contains(root, child)); Assert.assertFalse("section pos contains fail", DhSectionPos.contains(child, root)); - root = DhSectionPos.encode((byte) 10, 1, 0); + root = DhSectionPos.encodePos((byte) 10, 1, 0); // out of bounds - child = DhSectionPos.encode((byte) 9, 0, 0); + child = DhSectionPos.encodePos((byte) 9, 0, 0); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encode((byte) 9, 1, 1); + child = DhSectionPos.encodePos((byte) 9, 1, 1); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); // in bounds - child = DhSectionPos.encode((byte) 9, 2, 0); + child = DhSectionPos.encodePos((byte) 9, 2, 0); Assert.assertTrue("position should be in bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encode((byte) 9, 3, 1); + child = DhSectionPos.encodePos((byte) 9, 3, 1); Assert.assertTrue("position should be in bounds", DhSectionPos.contains(root, child)); // out of bounds - child = DhSectionPos.encode((byte) 9, 2, 2); + child = DhSectionPos.encodePos((byte) 9, 2, 2); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encode((byte) 9, 3, 3); + child = DhSectionPos.encodePos((byte) 9, 3, 3); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encode((byte) 9, 4, 4); + child = DhSectionPos.encodePos((byte) 9, 4, 4); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encode((byte) 9, 5, 5); + child = DhSectionPos.encodePos((byte) 9, 5, 5); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 0, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 1, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 2, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 3, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 4, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 5, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 6, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 0, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 1, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 2, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 3, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 4, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 5, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 6, 0, 0))); } @Test public void containsAdjacentPosTest() { // neither should contain the other, they are single blocks that are next to each other - long left = DhSectionPos.encode((byte) 0, 4606, 0); - long right = DhSectionPos.encode((byte) 0, 4607, 0); + long left = DhSectionPos.encodePos((byte) 0, 4606, 0); + long right = DhSectionPos.encodePos((byte) 0, 4607, 0); Assert.assertFalse(DhSectionPos.contains(left, right)); Assert.assertFalse(DhSectionPos.contains(right, left)); // 512 block wide sections that are adjacent, but not overlapping - left = DhSectionPos.encode((byte) 9, 0, 0); - right = DhSectionPos.encode((byte) 9, 1, 0); + left = DhSectionPos.encodePos((byte) 9, 0, 0); + right = DhSectionPos.encodePos((byte) 9, 1, 0); Assert.assertFalse(DhSectionPos.contains(left, right)); Assert.assertFalse(DhSectionPos.contains(right, left)); @@ -126,19 +127,19 @@ public class DhSectionPosTest @Test public void parentPosTest() { - long leaf = DhSectionPos.encode((byte) 0, 0, 0); + long leaf = DhSectionPos.encodePos((byte) 0, 0, 0); long convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 1); long parent = DhSectionPos.getParentPos(leaf); assertSectionPosEqual("get parent at 0,0 fail", convert, parent); - leaf = DhSectionPos.encode((byte) 0, 1, 1); + leaf = DhSectionPos.encodePos((byte) 0, 1, 1); convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 1); parent = DhSectionPos.getParentPos(leaf); assertSectionPosEqual("get parent at 1,1 fail", convert, parent); - leaf = DhSectionPos.encode((byte) 1, 2, 2); + leaf = DhSectionPos.encodePos((byte) 1, 2, 2); convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 2); parent = DhSectionPos.getParentPos(leaf); assertSectionPosEqual("parent upscale fail", convert, parent); @@ -151,7 +152,7 @@ public class DhSectionPosTest @Test public void childPosTest() { - long node = DhSectionPos.encode((byte) 1, 2302, 0); + long node = DhSectionPos.encodePos((byte) 1, 2302, 0); long nw = DhSectionPos.getChildByIndex(node, 0); long sw = DhSectionPos.getChildByIndex(node, 1); long ne = DhSectionPos.getChildByIndex(node, 2); @@ -163,18 +164,18 @@ public class DhSectionPosTest Assert.assertNotEquals(ne, se); // confirm each child has the correct value - assertSectionPosEqual(nw, DhSectionPos.encode((byte) 0, 4604, 0)); - assertSectionPosEqual(sw, DhSectionPos.encode((byte) 0, 4605, 0)); - assertSectionPosEqual(ne, DhSectionPos.encode((byte) 0, 4604, 1)); - assertSectionPosEqual(se, DhSectionPos.encode((byte) 0, 4605, 1)); + assertSectionPosEqual(nw, DhSectionPos.encodePos((byte) 0, 4604, 0)); + assertSectionPosEqual(sw, DhSectionPos.encodePos((byte) 0, 4605, 0)); + assertSectionPosEqual(ne, DhSectionPos.encodePos((byte) 0, 4604, 1)); + assertSectionPosEqual(se, DhSectionPos.encodePos((byte) 0, 4605, 1)); } @Test public void getCenterBlock2DTest() { - long parentNode = DhSectionPos.encode((byte) 2, 1151, 0); // width 4 blocks - long inputPos = DhSectionPos.encode((byte) 0, 4606, 0); // width 1 block + long parentNode = DhSectionPos.encodePos((byte) 2, 1151, 0); // width 4 blocks + long inputPos = DhSectionPos.encodePos((byte) 0, 4606, 0); // width 1 block Assert.assertTrue(DhSectionPos.contains(parentNode, inputPos)); DhBlockPos2D parentCenter = DhSectionPos.getCenterBlockPos(parentNode); @@ -191,20 +192,20 @@ public class DhSectionPosTest // origin pos // DhBlockPos originBlockPos = new DhBlockPos(0, 0, 0); - long originsectionPos = DhSectionPos.encode(originBlockPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originsectionPos); + long originsectionPos = DhSectionPos.encodeLodPos(originBlockPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originsectionPos); // offset pos // long offsetSectionPos; DhBlockPos offsetBlockPos = new DhBlockPos(1000, 0, 42000); - offsetSectionPos = DhSectionPos.encode(offsetBlockPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos); + offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos); offsetBlockPos = new DhBlockPos(-987654, 0, 46); - offsetSectionPos = DhSectionPos.encode(offsetBlockPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); + offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); } @@ -214,19 +215,19 @@ public class DhSectionPosTest // origin pos // DhBlockPos2D originBlockPos = new DhBlockPos2D(0, 0); - long originSectionPos = DhSectionPos.encode(originBlockPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); + long originSectionPos = DhSectionPos.encodeLodPos(originBlockPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); // offset pos // DhBlockPos2D offsetBlockPos = new DhBlockPos2D(1000, 42000); - long offsetSectionPos = DhSectionPos.encode(offsetBlockPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos); + long offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos); offsetBlockPos = new DhBlockPos2D(-987654, 46); - offsetSectionPos = DhSectionPos.encode(offsetBlockPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); + offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); } @@ -236,19 +237,45 @@ public class DhSectionPosTest // origin pos // DhChunkPos originChunkPos = new DhChunkPos(0,0); - long originSectionPos = DhSectionPos.encode(originChunkPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos); + long originSectionPos = DhSectionPos.encodeLodPos(originChunkPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos); // offset pos // DhChunkPos offsetChunkPos = new DhChunkPos(1000, 42000); - long offsetSectionPos = DhSectionPos.encode(offsetChunkPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos); + long offsetSectionPos = DhSectionPos.encodeLodPos(offsetChunkPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos); offsetChunkPos = new DhChunkPos(-987654, 46); - offsetSectionPos = DhSectionPos.encode(offsetChunkPos); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); + offsetSectionPos = DhSectionPos.encodeLodPos(offsetChunkPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); + + } + + @Test + public void createFromChunkPos_test() + { + // origin pos // + + DhChunkPos originChunkPos = new DhChunkPos(0,0); + long originSectionPos = DhSectionPos.encodePos(originChunkPos); + assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos); + + + // offset pos // + + DhChunkPos offsetChunkPos = new DhChunkPos(1, 1); + long offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos); + assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 1, 1), offsetSectionPos); + + offsetChunkPos = new DhChunkPos(2, 2); + offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos); + assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 2, 2), offsetSectionPos); + + offsetChunkPos = new DhChunkPos(-3, -2); + offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos); + assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, -3, -2), offsetSectionPos); } @@ -257,38 +284,38 @@ public class DhSectionPosTest { // origin pos // - long originSectionPos = DhSectionPos.encode((byte) 0,0,0); + long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0); originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, (byte) 1); - assertSectionPosEqual(DhSectionPos.encode((byte) 1, 0, 0), originSectionPos); + assertSectionPosEqual(DhSectionPos.encodePos((byte) 1, 0, 0), originSectionPos); originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, DhSectionPos.SECTION_REGION_DETAIL_LEVEL); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos); // offset pos // - long offsetSectionPos = DhSectionPos.encode((byte) 0,-10000,5000); + long offsetSectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000); offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, (byte) 1); - assertSectionPosEqual(DhSectionPos.encode((byte) 1, -5000, 2500), offsetSectionPos); + assertSectionPosEqual(DhSectionPos.encodePos((byte) 1, -5000, 2500), offsetSectionPos); offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), offsetSectionPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), offsetSectionPos); offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, DhSectionPos.SECTION_REGION_DETAIL_LEVEL); - assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), offsetSectionPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), offsetSectionPos); } @Test public void getOffsetWidth() { - long originSectionPos = DhSectionPos.encode((byte) 0,0,0); - long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000); + long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0); + long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000); @@ -332,8 +359,8 @@ public class DhSectionPosTest @Test public void getBlockWidth() { - long originSectionPos = DhSectionPos.encode((byte) 0,0,0); - long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000); + long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0); + long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000); assertSectionPosEqual(1, DhSectionPos.getBlockWidth(originSectionPos)); @@ -359,8 +386,8 @@ public class DhSectionPosTest @Test public void getCenterBlockPosOrigin() { - long originSectionPos = DhSectionPos.encode((byte) 0,0,0); - long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000); + long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0); + long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000); @@ -406,28 +433,28 @@ public class DhSectionPosTest long pos; // origin block detail - pos = DhSectionPos.encode((byte) 0,0,0); + pos = DhSectionPos.encodePos((byte) 0,0,0); Assert.assertEquals(0, DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(0, DhSectionPos.getMinCornerBlockZ(pos)); // offset block detail - pos = DhSectionPos.encode((byte) 0,2,3); + pos = DhSectionPos.encodePos((byte) 0,2,3); Assert.assertEquals(2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(3 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos)); // negative offset block detail - pos = DhSectionPos.encode((byte) 0,-1,-2); + pos = DhSectionPos.encodePos((byte) 0,-1,-2); Assert.assertEquals(-1 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(-2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos)); // origin chunk detail - pos = DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,0,0); + pos = DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,0,0); Assert.assertEquals(0, DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(0, DhSectionPos.getMinCornerBlockZ(pos)); // offset chunk detail - pos = DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,2,3); + pos = DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,2,3); Assert.assertEquals(2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(3 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos)); @@ -437,13 +464,13 @@ public class DhSectionPosTest @Test public void getAdjacentPos() { - long pos = DhSectionPos.encode((byte) 0, 0, 0); + long pos = DhSectionPos.encodePos((byte) 0, 0, 0); - assertSectionPosEqual(DhSectionPos.encode((byte) 0, 0, -1), DhSectionPos.getAdjacentPos(pos, EDhDirection.NORTH)); - assertSectionPosEqual(DhSectionPos.encode((byte) 0, 0, 1), DhSectionPos.getAdjacentPos(pos, EDhDirection.SOUTH)); + assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 0, -1), DhSectionPos.getAdjacentPos(pos, EDhDirection.NORTH)); + assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 0, 1), DhSectionPos.getAdjacentPos(pos, EDhDirection.SOUTH)); - assertSectionPosEqual(DhSectionPos.encode((byte) 0, 1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.EAST)); - assertSectionPosEqual(DhSectionPos.encode((byte) 0, -1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.WEST)); + assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.EAST)); + assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, -1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.WEST)); // getting the adjacent position in the up and down position don't make sense Assert.assertThrows(IllegalArgumentException.class, () -> { DhSectionPos.getAdjacentPos(pos, EDhDirection.UP); }); @@ -453,7 +480,7 @@ public class DhSectionPosTest @Test public void forEachChildIterator() { - long pos = DhSectionPos.encode((byte) 1, 0, 0); + long pos = DhSectionPos.encodePos((byte) 1, 0, 0); ArrayList childPosList = new ArrayList<>(); AtomicInteger childCount = new AtomicInteger(0); @@ -463,10 +490,10 @@ public class DhSectionPosTest childPosList.add(childPos); }); - Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 0, 0))); - Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 1, 0))); - Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 0, 1))); - Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 1, 1))); + Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 0, 0))); + Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 1, 0))); + Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 0, 1))); + Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 1, 1))); } diff --git a/core/src/test/java/tests/QuadTreeTest.java b/core/src/test/java/tests/QuadTreeTest.java index 28cbfabb0..351cd9ba0 100644 --- a/core/src/test/java/tests/QuadTreeTest.java +++ b/core/src/test/java/tests/QuadTreeTest.java @@ -60,30 +60,30 @@ public class QuadTreeTest // (pseudo) root node // - testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 0); + testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 0); // first child (0,0) // - testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 1); - testSet(tree, DhSectionPos.encode((byte) 9, 1, 0), 2); - testSet(tree, DhSectionPos.encode((byte) 9, 0, 1), 3); - testSet(tree, DhSectionPos.encode((byte) 9, 1, 1), 4); + testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 1); + testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 0), 2); + testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 1), 3); + testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 1), 4); // second child (0,0) (0,0) // - testSet(tree, DhSectionPos.encode((byte) 8, 0, 0), 5); - testSet(tree, DhSectionPos.encode((byte) 8, 1, 0), 6); - testSet(tree, DhSectionPos.encode((byte) 8, 0, 1), 7); - testSet(tree, DhSectionPos.encode((byte) 8, 1, 1), 8); + testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 0), 5); + testSet(tree, DhSectionPos.encodePos((byte) 8, 1, 0), 6); + testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 1), 7); + testSet(tree, DhSectionPos.encodePos((byte) 8, 1, 1), 8); // second child (0,0) (1,1) // - testSet(tree, DhSectionPos.encode((byte) 8, 2, 2), 9); - testSet(tree, DhSectionPos.encode((byte) 8, 3, 2), 10); - testSet(tree, DhSectionPos.encode((byte) 8, 2, 3), 11); - testSet(tree, DhSectionPos.encode((byte) 8, 3, 3), 12); + testSet(tree, DhSectionPos.encodePos((byte) 8, 2, 2), 9); + testSet(tree, DhSectionPos.encodePos((byte) 8, 3, 2), 10); + testSet(tree, DhSectionPos.encodePos((byte) 8, 2, 3), 11); + testSet(tree, DhSectionPos.encodePos((byte) 8, 3, 3), 12); // third child (0,0) (1,0) (0,0) // - testSet(tree, DhSectionPos.encode((byte) 7, 5, 0), 9); - testSet(tree, DhSectionPos.encode((byte) 7, 6, 0), 10); - testSet(tree, DhSectionPos.encode((byte) 7, 5, 1), 11); - testSet(tree, DhSectionPos.encode((byte) 7, 6, 1), 12); + testSet(tree, DhSectionPos.encodePos((byte) 7, 5, 0), 9); + testSet(tree, DhSectionPos.encodePos((byte) 7, 6, 0), 10); + testSet(tree, DhSectionPos.encodePos((byte) 7, 5, 1), 11); + testSet(tree, DhSectionPos.encodePos((byte) 7, 6, 1), 12); } @@ -95,13 +95,13 @@ public class QuadTreeTest // root node // - testSet(tree, DhSectionPos.encode((byte) 10, -1, -1), 0); + testSet(tree, DhSectionPos.encodePos((byte) 10, -1, -1), 0); // first child (-1,-1) // - testSet(tree, DhSectionPos.encode((byte) 9, -2, -1), 1); - testSet(tree, DhSectionPos.encode((byte) 9, -1, -1), 2); - testSet(tree, DhSectionPos.encode((byte) 9, -2, -2), 3); - testSet(tree, DhSectionPos.encode((byte) 9, -1, -2), 4); + testSet(tree, DhSectionPos.encodePos((byte) 9, -2, -1), 1); + testSet(tree, DhSectionPos.encodePos((byte) 9, -1, -1), 2); + testSet(tree, DhSectionPos.encodePos((byte) 9, -2, -2), 3); + testSet(tree, DhSectionPos.encodePos((byte) 9, -1, -2), 4); // TODO // // second child (-1,-1) (0,0) // @@ -132,36 +132,36 @@ public class QuadTreeTest // wrong detail level on purpose, if the detail level was 0 (block) this should work - long outOfBoundsPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); + long outOfBoundsPos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); // out of bounds // - outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) + 1, 0); + outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) + 1, 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); - outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); + outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); // in bounds // - outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0); + outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount()); - outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 3, 0); + outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 3, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); // TODO this position probably has trouble with getting the center. - outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0); + outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 3, tree.leafNodeCount()); - outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0); + outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 4, tree.leafNodeCount()); @@ -174,15 +174,15 @@ public class QuadTreeTest Assert.assertEquals("Test may need to be re-calculated for different max detail level.", 9, tree.treeMinDetailLevel); - long rootPos = DhSectionPos.encode((byte) 9, 0, -1); + long rootPos = DhSectionPos.encodePos((byte) 9, 0, -1); testSet(tree, rootPos, 1); // pos is in tree, but out of range - long midPos = DhSectionPos.encode((byte) 8, 0, -1); + long midPos = DhSectionPos.encodePos((byte) 8, 0, -1); testSet(tree, midPos, 2, IndexOutOfBoundsException.class); // pos is in tree, but out of range - long leafPos = DhSectionPos.encode((byte) 7, 0, -2); + long leafPos = DhSectionPos.encodePos((byte) 7, 0, -2); testSet(tree, leafPos, 3, IndexOutOfBoundsException.class); } @@ -198,13 +198,13 @@ public class QuadTreeTest // (pseudo) root nodes // - testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1); // first child (0,0) // - long nw = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0); - long ne = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 0); - long sw = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 1); - long se = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 1); + long nw = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0); + long ne = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 0); + long sw = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 1); + long se = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 1); testSet(tree, nw, 2); testSet(tree, ne, 3); @@ -260,12 +260,12 @@ public class QuadTreeTest Assert.assertEquals("Tree center incorrect", DhBlockPos2D.ZERO, tree.getCenterBlockPos()); // on the negative X edge - long edgePos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks() / 2, 0); + long edgePos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks() / 2, 0); testSet(tree, edgePos, 1); Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount()); // +1 root node from the negative X edge - long adjacentEdgePos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0); + long adjacentEdgePos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0); testSet(tree, adjacentEdgePos, 2); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); @@ -285,14 +285,14 @@ public class QuadTreeTest // (pseudo) root nodes // - testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); - testSet(tree, DhSectionPos.encode((byte) 10, 1, 0), 2); + testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encodePos((byte) 10, 1, 0), 2); // first child (0,0) // - testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 3); - testSet(tree, DhSectionPos.encode((byte) 9, 1, 0), 4); - testSet(tree, DhSectionPos.encode((byte) 9, 0, 1), 5); - testSet(tree, DhSectionPos.encode((byte) 9, 1, 1), 6); + testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 3); + testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 0), 4); + testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 1), 5); + testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 1), 6); @@ -332,19 +332,19 @@ public class QuadTreeTest @Test public void NewQuadTreeIterationTest() { - QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); - rootNode.setValue(DhSectionPos.encode((byte) 10, 0, 0), 0); + rootNode.setValue(DhSectionPos.encodePos((byte) 10, 0, 0), 0); - rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 0), 1); - rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 0), 1); - rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 1), 1); - rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 1), null); + rootNode.setValue(DhSectionPos.encodePos((byte) 9, 0, 0), 1); + rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 0), 1); + rootNode.setValue(DhSectionPos.encodePos((byte) 9, 0, 1), 1); + rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 1), null); - rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), 2); - rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), 2); - rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), 2); - rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), null); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), 2); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 0), 2); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), 2); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), null); @@ -411,7 +411,7 @@ public class QuadTreeTest { AbstractTestTreeParams treeParams = new TinyTestTree(); final QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), treeParams.getPositiveEdgeCenterPos(), LodUtil.BLOCK_DETAIL_LEVEL); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0); // confirm the root node were added int rootNodeCount = 0; @@ -499,10 +499,10 @@ public class QuadTreeTest Assert.assertEquals("incorrect tree width", treeParams.getWidthInBlocks(), tree.diameterInBlocks()); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, -1), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, -1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); int rootNodeCount = 0; LongIterator rootNodeIterator = tree.rootNodePosIterator(); @@ -529,18 +529,18 @@ public class QuadTreeTest // 2x2 valid positions (overlap the tree's width) - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, 0), 0); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, -1), 0); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, -1), 0); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, 0), 0); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, -1), 0); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, -1), 0); // invalid positions - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, -1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, -1), -1, IndexOutOfBoundsException.class); int rootNodeCount = 0; @@ -565,17 +565,17 @@ public class QuadTreeTest Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMinDetailLevel); // valid detail levels - testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); - testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 2); - testSet(tree, DhSectionPos.encode((byte) 8, 0, 0), 3); + testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 2); + testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 0), 3); // detail level too low - testSet(tree, DhSectionPos.encode((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encode((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class); // detail level too high - testSet(tree, DhSectionPos.encode((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encode((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encodePos((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class); } @@ -587,7 +587,7 @@ public class QuadTreeTest Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMinDetailLevel); // create the root node - testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1); @@ -678,7 +678,7 @@ public class QuadTreeTest @Test public void quadNodeChildPositionIndexTest() { - QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), (byte) 0); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), (byte) 0); LongIterator directChildPosIterator = rootNode.getChildPosIterator(); while (directChildPosIterator.hasNext()) { @@ -708,7 +708,7 @@ public class QuadTreeTest // center root node - long centerNodePos = DhSectionPos.encode((byte) 1, 0, 0); + long centerNodePos = DhSectionPos.encodePos((byte) 1, 0, 0); // create node tree.setValue(centerNodePos, 0); @@ -727,7 +727,7 @@ public class QuadTreeTest // edge root node - long offsetNodePos = DhSectionPos.encode((byte) 1, -17, -16); + long offsetNodePos = DhSectionPos.encodePos((byte) 1, -17, -16); // create node tree.setValue(offsetNodePos, 0); @@ -772,7 +772,7 @@ public class QuadTreeTest // - testSet(tree, DhSectionPos.encode((byte) 0, 0, 0), 1); + testSet(tree, DhSectionPos.encodePos((byte) 0, 0, 0), 1); Assert.assertEquals(1, tree.count()); tree.setCenterBlockPos(new DhBlockPos2D(treeWidth + (treeWidth / 2), 0)); Assert.assertEquals(0, tree.count()); @@ -783,21 +783,21 @@ public class QuadTreeTest //@Test public void autoDeleteNullQuadNodeChildTest() { - QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); - rootNode.setValue(DhSectionPos.encode((byte) 10, 0, 0), 0); + rootNode.setValue(DhSectionPos.encodePos((byte) 10, 0, 0), 0); - long midNodePos = DhSectionPos.encode((byte) 9, 0, 0); + long midNodePos = DhSectionPos.encodePos((byte) 9, 0, 0); //rootNode.setValue(midNodePos, null); // holds detail 8 - rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 0), 1); - rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 1), 1); - rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 1), 1); + rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 0), 1); + rootNode.setValue(DhSectionPos.encodePos((byte) 9, 0, 1), 1); + rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 1), 1); - rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), 2); - rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), 2); - rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), 2); - rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), 2); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), 2); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 0), 2); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), 2); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), 2); @@ -810,12 +810,12 @@ public class QuadTreeTest // test removing nodes // // remove two leaf nodes from the root - long leafPos = DhSectionPos.encode((byte) 9, 1, 1); + long leafPos = DhSectionPos.encodePos((byte) 9, 1, 1); rootNode.setValue(leafPos, null); Assert.assertEquals(3, rootNode.getNonNullChildCount()); Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos)); - leafPos = DhSectionPos.encode((byte) 9, 0, 1); + leafPos = DhSectionPos.encodePos((byte) 9, 0, 1); rootNode.setValue(leafPos, null); Assert.assertEquals(2, rootNode.getNonNullChildCount()); Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos)); @@ -827,13 +827,13 @@ public class QuadTreeTest Assert.assertEquals(4, rootNode.getNode(midNodePos).getNonNullChildCount()); // remove all but one, mid-node should still be present - rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), null); - rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), null); - rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), null); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), null); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), null); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 0), null); Assert.assertEquals(1, rootNode.getNode(midNodePos).getNonNullChildCount()); // remove last mid-node child, mid-node should now be removed - rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), null); + rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), null); Assert.assertNull("Mid node not deleted.", rootNode.getNode(midNodePos)); Assert.assertEquals(3, rootNode.getNonNullChildCount()); From 4d4eeacbddd58b22c8e69da9f81f34e4a3ec3342 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 20 Jul 2024 11:20:48 -0500 Subject: [PATCH 093/104] Add IDhApiWrapperFactory resourceLocation string methods for block/biomes --- .../factories/IDhApiWrapperFactory.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/factories/IDhApiWrapperFactory.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/factories/IDhApiWrapperFactory.java index 524742f04..ce3e70662 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/factories/IDhApiWrapperFactory.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/factories/IDhApiWrapperFactory.java @@ -79,11 +79,34 @@ public interface IDhApiWrapperFactory - ///** - // * Specifically designed to be used with the API. - // * - // * @throws ClassCastException with instructions on expected objects if the object couldn't be cast - // */ - //IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException; + /** + * Constructs a {@link IDhApiBiomeWrapper} for use by other DhApi methods. + * + * @param resourceLocationString example: "minecraft:plains" + * + * @param levelWrapper Expects a {@link IDhApiLevelWrapper} returned by one of DH's {@link DhApi.Delayed#worldProxy} methods.
+ * A custom implementation of {@link IDhApiLevelWrapper} will not be accepted. + * + * @throws IOException if the resourceLocationString wasn't able to be parsed or converted into a valid {@link IDhApiBiomeWrapper} + * @throws ClassCastException if the wrong levelWrapper type was given + * + * @since API 3.0.0 + */ + IDhApiBiomeWrapper getBiomeWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException; + + /** + * Constructs a {@link IDhApiBlockStateWrapper} for use by other DhApi methods. + * This returns the default blockstate for the given resource location. + * + * @param resourceLocationString examples: "minecraft:bedrock", "minecraft:stone", "minecraft:grass_block" + * @param levelWrapper Expects a {@link IDhApiBlockStateWrapper} returned by one of DH's {@link DhApi.Delayed#worldProxy} methods.
+ * A custom implementation of {@link IDhApiBlockStateWrapper} will not be accepted. + * + * @throws IOException if the resourceLocationString wasn't able to be parsed or converted into a valid {@link IDhApiBlockStateWrapper} + * @throws ClassCastException if the wrong levelWrapper type was given + * + * @since API 3.0.0 + */ + IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException; } From 17b5ba0ae1dd6cc02388d5d390feeba7b98eac8d Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 20 Jul 2024 11:25:00 -0500 Subject: [PATCH 094/104] Fix potential issues with WorldGenQueue not being marked as stopped closes !61 --- .../core/generation/WorldGenerationQueue.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java index 8e2724c32..428203003 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java @@ -78,7 +78,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb // TODO this logic isn't great and can cause a limit to how many threads could be used for world generation, // however it won't cause duplicate requests or concurrency issues, so it will be good enough for now. // A good long term fix may be to either: - // 1. allow the generator to deal with larger sections (let the generator threads split up larger tasks into smaller one + // 1. allow the generator to deal with larger sections (let the generator threads split up larger tasks into smaller ones // 2. batch requests better. instead of sending 4 individual tasks of detail level N, send 1 task of detail level n+1 private final ExecutorService queueingThread = ThreadUtil.makeSingleThreadPool("World Gen Queue"); private boolean generationQueueRunning = false; @@ -226,6 +226,9 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb catch (Exception e) { LOGGER.error("queueing exception: " + e.getMessage(), e); + } + finally + { this.generationQueueRunning = false; } }); From 568ff40df6d346c4d5418c7d11217ff94aed1072 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 20 Jul 2024 17:57:58 -0500 Subject: [PATCH 095/104] Fix API chunk world gen --- .../api/objects/data/DhApiChunk.java | 8 ++--- .../objects/data/DhApiTerrainDataPoint.java | 8 ++--- .../transformers/LodDataBuilder.java | 32 ++++++++++++------- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiChunk.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiChunk.java index 84e92da58..8bbed6ded 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiChunk.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiChunk.java @@ -29,7 +29,7 @@ import java.util.List; * Contains a list of {@link DhApiTerrainDataPoint} representing the blocks in a Minecraft chunk. * * @author Builderb0y, James Seibel - * @version 2023-12-21 + * @version 2024-7-21 * @since API 2.0.0 * * @see IDhApiWrapperFactory @@ -41,8 +41,8 @@ public class DhApiChunk public final int chunkPosX; public final int chunkPosZ; - public final int topYBlockPos; public final int bottomYBlockPos; + public final int topYBlockPos; private final List> dataPoints; @@ -52,12 +52,12 @@ public class DhApiChunk // constructors // //==============// - public DhApiChunk(int chunkPosX, int chunkPosZ, int topYBlockPos, int bottomYBlockPos) + public DhApiChunk(int chunkPosX, int chunkPosZ, int bottomYBlockPos, int topYBlockPos) { this.chunkPosX = chunkPosX; this.chunkPosZ = chunkPosZ; - this.topYBlockPos = topYBlockPos; this.bottomYBlockPos = bottomYBlockPos; + this.topYBlockPos = topYBlockPos; // populate the array to prevent null pointers this.dataPoints = new ArrayList<>(16 * 16); // 256 diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiTerrainDataPoint.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiTerrainDataPoint.java index 0c70dfbfb..ab2cb9f01 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiTerrainDataPoint.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/data/DhApiTerrainDataPoint.java @@ -26,7 +26,7 @@ import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; * Holds a single datapoint of terrain data. * * @author James Seibel - * @version 2022-11-13 + * @version 2024-7-20 * @since API 1.0.0 */ public class DhApiTerrainDataPoint @@ -42,22 +42,22 @@ public class DhApiTerrainDataPoint public final int blockLightLevel; public final int skyLightLevel; - public final int topYBlockPos; public final int bottomYBlockPos; + public final int topYBlockPos; public final IDhApiBlockStateWrapper blockStateWrapper; public final IDhApiBiomeWrapper biomeWrapper; - public DhApiTerrainDataPoint(byte detailLevel, int blockLightLevel, int skyLightLevel, int topYBlockPos, int bottomYBlockPos, IDhApiBlockStateWrapper blockStateWrapper, IDhApiBiomeWrapper biomeWrapper) + public DhApiTerrainDataPoint(byte detailLevel, int blockLightLevel, int skyLightLevel, int bottomYBlockPos, int topYBlockPos, IDhApiBlockStateWrapper blockStateWrapper, IDhApiBiomeWrapper biomeWrapper) { this.detailLevel = detailLevel; this.blockLightLevel = blockLightLevel; this.skyLightLevel = skyLightLevel; - this.topYBlockPos = topYBlockPos; this.bottomYBlockPos = bottomYBlockPos; + this.topYBlockPos = topYBlockPos; this.blockStateWrapper = blockStateWrapper; this.biomeWrapper = biomeWrapper; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index 2e939718a..d26416ea0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -31,7 +31,6 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhBlockPos; -import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.LodUtil; @@ -67,12 +66,8 @@ public class LodDataBuilder - // get the section position - int sectionPosX = chunkWrapper.getChunkPos().x; - // negative positions start at -1 so the logic there is slightly different - sectionPosX = (sectionPosX < 0) ? ((sectionPosX + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPosX / NUMB_OF_CHUNKS_WIDE); - int sectionPosZ = chunkWrapper.getChunkPos().z; - sectionPosZ = (sectionPosZ < 0) ? ((sectionPosZ + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPosZ / NUMB_OF_CHUNKS_WIDE); + int sectionPosX = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().x); + int sectionPosZ = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().z); long pos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos); @@ -304,10 +299,14 @@ public class LodDataBuilder /** @throws ClassCastException if an API user returns the wrong object type(s) */ public static FullDataSourceV2 createFromApiChunkData(DhApiChunk apiChunk) throws ClassCastException, DataCorruptedException { - // TODO - long pos = DhSectionPos.convertToDetailLevel(DhSectionPos.encodeChunkPos(apiChunk.chunkPosX, apiChunk.chunkPosZ), DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); - int relSourceBlockX = Math.abs(apiChunk.chunkPosX % 4) * LodUtil.CHUNK_WIDTH; - int relSourceBlockZ = Math.abs(apiChunk.chunkPosZ % 4) * LodUtil.CHUNK_WIDTH; + // get the section position + int sectionPosX = getXOrZSectionPosFromChunkPos(apiChunk.chunkPosX); + int sectionPosZ = getXOrZSectionPosFromChunkPos(apiChunk.chunkPosZ); + long pos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + + // chunk relative block position in the data source + int relSourceBlockX = Math.floorMod(apiChunk.chunkPosX, 4) * LodUtil.CHUNK_WIDTH; + int relSourceBlockZ = Math.floorMod(apiChunk.chunkPosZ, 4) * LodUtil.CHUNK_WIDTH; FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos); for (int relBlockZ = 0; relBlockZ < LodUtil.CHUNK_WIDTH; relBlockZ++) @@ -336,7 +335,7 @@ public class LodDataBuilder packedDataPoints.set(index, FullDataPointUtil.encode( id, dataPoint.topYBlockPos - dataPoint.bottomYBlockPos, - dataPoint.bottomYBlockPos - apiChunk.topYBlockPos, + dataPoint.bottomYBlockPos - apiChunk.bottomYBlockPos, (byte) (dataPoint.blockLightLevel), (byte) (dataPoint.skyLightLevel) )); @@ -362,4 +361,13 @@ public class LodDataBuilder public static boolean canGenerateLodFromChunk(IChunkWrapper chunk) { return chunk != null && chunk.isLightCorrect(); } + public static int getXOrZSectionPosFromChunkPos(int chunkXOrZPos) + { + // get the section position + int sectionPos = chunkXOrZPos; + // negative positions start at -1 so the logic there is slightly different + sectionPos = (sectionPos < 0) ? ((sectionPos + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPos / NUMB_OF_CHUNKS_WIDE); + return sectionPos; + } + } From de7d22766a54bf66de760084c02829a0c6d65f8c Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 07:19:21 -0500 Subject: [PATCH 096/104] Fix RenderDataPointUtil.toString() ARGB order --- .../seibel/distanthorizons/core/util/RenderDataPointUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java index 72bb1864f..757aec211 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java @@ -245,8 +245,8 @@ public class RenderDataPointUtil " Y-:" + getYMin(dataPoint) + " argb:" + getAlpha(dataPoint) + " " + getRed(dataPoint) + " " + - getBlue(dataPoint) + " " + - getGreen(dataPoint) + + getGreen(dataPoint) + " " + + getBlue(dataPoint) + " BL:" + getLightBlock(dataPoint) + " SL:" + getLightSky(dataPoint) + " BID:" + getBlockMaterialId(dataPoint); From 589340f2dbfb5beff3f7203ee475aa2d204686bc Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 07:35:35 -0500 Subject: [PATCH 097/104] Clean up SectionPos wording for chunk/block pos converters --- .../fullData/sources/FullDataSourceV2.java | 2 + .../transformers/LodDataBuilder.java | 16 +++-- .../SubDimensionLevelMatcher.java | 4 +- .../core/pos/DhSectionPos.java | 40 +++++++----- .../src/test/java/tests/DhSectionPosTest.java | 62 +++---------------- 5 files changed, 42 insertions(+), 82 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV2.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV2.java index fcfc8271f..a727c05c5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV2.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/sources/FullDataSourceV2.java @@ -62,6 +62,8 @@ public class FullDataSourceV2 implements IDataSource /** measured in data columns */ public static final int WIDTH = 64; + /** how many chunks wide this datasource is. */ + public static final int NUMB_OF_CHUNKS_WIDE = WIDTH / LodUtil.CHUNK_WIDTH; public static final byte DATA_FORMAT_VERSION = 1; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index d26416ea0..3cefbf3b3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -46,8 +46,6 @@ public class LodDataBuilder { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final IBlockStateWrapper AIR = SingletonInjector.INSTANCE.get(IWrapperFactory.class).getAirBlockStateWrapper(); - /** how many chunks wide the {@link FullDataSourceV2} is. */ - private static final int NUMB_OF_CHUNKS_WIDE = FullDataSourceV2.WIDTH / LodUtil.CHUNK_WIDTH; private static boolean getTopErrorLogged = false; @@ -93,30 +91,30 @@ public class LodDataBuilder // -3 -> 1 // -4 -> 0 --- // -5 -> 3 - chunkOffsetX = ((chunkOffsetX) % NUMB_OF_CHUNKS_WIDE); + chunkOffsetX = ((chunkOffsetX) % FullDataSourceV2.NUMB_OF_CHUNKS_WIDE); if (chunkOffsetX != 0) { - chunkOffsetX += NUMB_OF_CHUNKS_WIDE; + chunkOffsetX += FullDataSourceV2.NUMB_OF_CHUNKS_WIDE; } } else { - chunkOffsetX %= NUMB_OF_CHUNKS_WIDE; + chunkOffsetX %= FullDataSourceV2.NUMB_OF_CHUNKS_WIDE; } chunkOffsetX *= LodUtil.CHUNK_WIDTH; int chunkOffsetZ = chunkWrapper.getChunkPos().z; if (chunkWrapper.getChunkPos().z < 0) { - chunkOffsetZ = ((chunkOffsetZ) % NUMB_OF_CHUNKS_WIDE); + chunkOffsetZ = ((chunkOffsetZ) % FullDataSourceV2.NUMB_OF_CHUNKS_WIDE); if (chunkOffsetZ != 0) { - chunkOffsetZ += NUMB_OF_CHUNKS_WIDE; + chunkOffsetZ += FullDataSourceV2.NUMB_OF_CHUNKS_WIDE; } } else { - chunkOffsetZ %= NUMB_OF_CHUNKS_WIDE; + chunkOffsetZ %= FullDataSourceV2.NUMB_OF_CHUNKS_WIDE; } chunkOffsetZ *= LodUtil.CHUNK_WIDTH; @@ -366,7 +364,7 @@ public class LodDataBuilder // get the section position int sectionPos = chunkXOrZPos; // negative positions start at -1 so the logic there is slightly different - sectionPos = (sectionPos < 0) ? ((sectionPos + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPos / NUMB_OF_CHUNKS_WIDE); + sectionPos = (sectionPos < 0) ? ((sectionPos + 1) / FullDataSourceV2.NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPos / FullDataSourceV2.NUMB_OF_CHUNKS_WIDE); return sectionPos; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java index 9d69994cf..72e56cedc 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java @@ -190,7 +190,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable } FullDataSourceV2 newChunkSizedFullDataView = FullDataSourceV2.createFromChunk(newlyLoadedChunk); // convert to a data source for easier comparing - FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encodeLodPos(this.playerData.playerBlockPos)); + FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, this.playerData.playerBlockPos)); newDataSource.update(newChunkSizedFullDataView); @@ -215,7 +215,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable // get the data source to compare against try (IDhLevel tempLevel = new DhClientLevel(new ClientOnlySaveStructure(), this.currentClientLevel, testLevelFolder, false)) { - testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encodeLodPos(this.playerData.playerBlockPos)).join(); + testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, this.playerData.playerBlockPos)).join(); if (testFullDataSource == null) { continue; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java index 2e74aea6d..40cc7ec0e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.pos; +import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; @@ -101,26 +102,33 @@ public class DhSectionPos return data; } - // TODO need changing - public static long encodeLodPos(DhBlockPos pos) { return encodeLodBlockPos(pos.x, pos.z); } - public static long encodeLodPos(DhBlockPos2D pos) { return encodeLodBlockPos(pos.x, pos.z); } - public static long encodeLodBlockPos(int blockX, int blockZ) + /** Returns the section pos at the requested detail level containing the given BlockPos */ + public static long encodeContainingPos(byte outputSectionDetailLevel, DhBlockPos pos) { - long pos = encodePos(LodUtil.BLOCK_DETAIL_LEVEL, blockX, blockZ); - pos = convertToDetailLevel(pos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); - return pos; + int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, false); + int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, false); + long blockPos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + return convertToDetailLevel(blockPos, outputSectionDetailLevel); } - - public static long encodeLodPos(DhChunkPos pos) { return encodeLodChunkPos(pos.x, pos.z); } - public static long encodeLodChunkPos(int chunkX, int chunkZ) // TODO broken? + /** Returns the section pos at the requested detail level containing the given ChunkPos */ + public static long encodeContainingPos(byte outputSectionDetailLevel, DhChunkPos pos) { - long pos = encodePos(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ); - pos = convertToDetailLevel(pos, DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL); - return pos; + int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, true); + int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, true); + long blockPos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + return convertToDetailLevel(blockPos, outputSectionDetailLevel); + } + private static int getXOrZSectionPosFromChunkOrBlockPos(int chunkXOrZPos, boolean isChunkPos) + { + int sectionPos = chunkXOrZPos; + int fullDataSourceWidth = isChunkPos ? FullDataSourceV2.NUMB_OF_CHUNKS_WIDE : (FullDataSourceV2.NUMB_OF_CHUNKS_WIDE * LodUtil.CHUNK_WIDTH); + + // negative positions start at -1 so the logic there is slightly different + sectionPos = (sectionPos < 0) + ? ((sectionPos + 1) / fullDataSourceWidth) - 1 + : (sectionPos / fullDataSourceWidth); + return sectionPos; } - - public static long encodePos(DhChunkPos pos) { return encodeChunkPos(pos.x, pos.z); } - public static long encodeChunkPos(int chunkX, int chunkZ) { return encodePos(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ); } diff --git a/core/src/test/java/tests/DhSectionPosTest.java b/core/src/test/java/tests/DhSectionPosTest.java index f2ed9b8d4..b3449cab2 100644 --- a/core/src/test/java/tests/DhSectionPosTest.java +++ b/core/src/test/java/tests/DhSectionPosTest.java @@ -192,41 +192,19 @@ public class DhSectionPosTest // origin pos // DhBlockPos originBlockPos = new DhBlockPos(0, 0, 0); - long originsectionPos = DhSectionPos.encodeLodPos(originBlockPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originsectionPos); + long originSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, originBlockPos); + assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); // offset pos // long offsetSectionPos; DhBlockPos offsetBlockPos = new DhBlockPos(1000, 0, 42000); - offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos); + offsetSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, offsetBlockPos); assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos); offsetBlockPos = new DhBlockPos(-987654, 0, 46); - offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); - - } - - @Test - public void createFromBlockPos2D() - { - // origin pos // - - DhBlockPos2D originBlockPos = new DhBlockPos2D(0, 0); - long originSectionPos = DhSectionPos.encodeLodPos(originBlockPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); - - - // offset pos // - - DhBlockPos2D offsetBlockPos = new DhBlockPos2D(1000, 42000); - long offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos); - - offsetBlockPos = new DhBlockPos2D(-987654, 46); - offsetSectionPos = DhSectionPos.encodeLodPos(offsetBlockPos); + offsetSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, offsetBlockPos); assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); } @@ -237,48 +215,22 @@ public class DhSectionPosTest // origin pos // DhChunkPos originChunkPos = new DhChunkPos(0,0); - long originSectionPos = DhSectionPos.encodeLodPos(originChunkPos); + long originSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, originChunkPos); assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos); // offset pos // DhChunkPos offsetChunkPos = new DhChunkPos(1000, 42000); - long offsetSectionPos = DhSectionPos.encodeLodPos(offsetChunkPos); + long offsetSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, offsetChunkPos); assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos); offsetChunkPos = new DhChunkPos(-987654, 46); - offsetSectionPos = DhSectionPos.encodeLodPos(offsetChunkPos); + offsetSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, offsetChunkPos); assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); } - @Test - public void createFromChunkPos_test() - { - // origin pos // - - DhChunkPos originChunkPos = new DhChunkPos(0,0); - long originSectionPos = DhSectionPos.encodePos(originChunkPos); - assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos); - - - // offset pos // - - DhChunkPos offsetChunkPos = new DhChunkPos(1, 1); - long offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos); - assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 1, 1), offsetSectionPos); - - offsetChunkPos = new DhChunkPos(2, 2); - offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos); - assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, 2, 2), offsetSectionPos); - - offsetChunkPos = new DhChunkPos(-3, -2); - offsetSectionPos = DhSectionPos.encodePos(offsetChunkPos); - assertSectionPosEqual(DhSectionPos.encodePos(LodUtil.CHUNK_DETAIL_LEVEL, -3, -2), offsetSectionPos); - - } - @Test public void convertToDetailLevel() { From 64895ba52195e148c84ed9a9af2728f1118b49fd Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 07:42:40 -0500 Subject: [PATCH 098/104] Remove unnecessary suffix from SectionPos encode method --- .../transformers/LodDataBuilder.java | 4 +- .../SubDimensionLevelMatcher.java | 4 +- .../core/generation/WorldGenerationQueue.java | 4 +- .../distanthorizons/core/pos/DhLodPos.java | 2 +- .../core/pos/DhSectionPos.java | 20 +- .../core/sql/repo/FullDataSourceV1Repo.java | 2 +- .../core/sql/repo/FullDataSourceV2Repo.java | 6 +- .../core/util/objects/quadTree/QuadTree.java | 2 +- .../src/test/java/tests/DhSectionPosTest.java | 153 +++++++------- core/src/test/java/tests/QuadTreeTest.java | 192 +++++++++--------- 10 files changed, 194 insertions(+), 195 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java index 3cefbf3b3..917aad07e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/LodDataBuilder.java @@ -66,7 +66,7 @@ public class LodDataBuilder int sectionPosX = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().x); int sectionPosZ = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().z); - long pos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos); dataSource.isEmpty = false; @@ -300,7 +300,7 @@ public class LodDataBuilder // get the section position int sectionPosX = getXOrZSectionPosFromChunkPos(apiChunk.chunkPosX); int sectionPosZ = getXOrZSectionPosFromChunkPos(apiChunk.chunkPosZ); - long pos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); // chunk relative block position in the data source int relSourceBlockX = Math.floorMod(apiChunk.chunkPosX, 4) * LodUtil.CHUNK_WIDTH; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java index 72e56cedc..89fe2a3f4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/subDimMatching/SubDimensionLevelMatcher.java @@ -190,7 +190,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable } FullDataSourceV2 newChunkSizedFullDataView = FullDataSourceV2.createFromChunk(newlyLoadedChunk); // convert to a data source for easier comparing - FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, this.playerData.playerBlockPos)); + FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encodeContaining(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, this.playerData.playerBlockPos)); newDataSource.update(newChunkSizedFullDataView); @@ -215,7 +215,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable // get the data source to compare against try (IDhLevel tempLevel = new DhClientLevel(new ClientOnlySaveStructure(), this.currentClientLevel, testLevelFolder, false)) { - testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, this.playerData.playerBlockPos)).join(); + testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encodeContaining(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, this.playerData.playerBlockPos)).join(); if (testFullDataSource == null) { continue; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java index 428203003..f03394a07 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java @@ -346,7 +346,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb //LOGGER.trace("Duplicate generation section " + taskPos + " with granularity [" + granularity + "] at " + chunkPosMin + ". Skipping..."); // sending a success result is necessary to make sure the render sections are reloaded correctly - newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encodePos(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); + newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); return false; } this.alreadyGeneratedPosHashSet.put(newTaskGroup.group.pos, Thread.currentThread().getStackTrace()); @@ -383,7 +383,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb } else { - newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encodePos(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); + newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos))))); } boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, newTaskGroup); LodUtil.assertTrue(worked, "Unable to find in progress generator task with position ["+DhSectionPos.toString(taskPos)+"]"); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java index af24eefd1..7678ec3e8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhLodPos.java @@ -174,7 +174,7 @@ public class DhLodPos implements Comparable DhLodPos lodPos = new DhLodPos(this.detailLevel, this.x, this.z); lodPos = lodPos.convertToDetailLevel(sectionDetailLevel); - return DhSectionPos.encodePos(lodPos.detailLevel, lodPos.x, lodPos.z); + return DhSectionPos.encode(lodPos.detailLevel, lodPos.x, lodPos.z); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java index 40cc7ec0e..e55072dbd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java @@ -82,7 +82,7 @@ public class DhSectionPos * This class just holds utility methods for handling a packed * {@link DhSectionPos} and shouldn't be constructed.

* - * Use one of the {@link DhSectionPos#encodePos(byte, int, int)} methods instead + * Use one of the {@link DhSectionPos#encode(byte, int, int)} methods instead */ private DhSectionPos() { } @@ -93,7 +93,7 @@ public class DhSectionPos * no validation is done for whether the detail level is positive * or if the X/Z positions can be represented by available bits. */ - public static long encodePos(byte detailLevel, int x, int z) + public static long encode(byte detailLevel, int x, int z) { long data = 0; data |= detailLevel & DETAIL_LEVEL_MASK; @@ -103,19 +103,19 @@ public class DhSectionPos } /** Returns the section pos at the requested detail level containing the given BlockPos */ - public static long encodeContainingPos(byte outputSectionDetailLevel, DhBlockPos pos) + public static long encodeContaining(byte outputSectionDetailLevel, DhBlockPos pos) { int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, false); int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, false); - long blockPos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); return convertToDetailLevel(blockPos, outputSectionDetailLevel); } /** Returns the section pos at the requested detail level containing the given ChunkPos */ - public static long encodeContainingPos(byte outputSectionDetailLevel, DhChunkPos pos) + public static long encodeContaining(byte outputSectionDetailLevel, DhChunkPos pos) { int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, true); int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, true); - long blockPos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); + long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ); return convertToDetailLevel(blockPos, outputSectionDetailLevel); } private static int getXOrZSectionPosFromChunkOrBlockPos(int chunkXOrZPos, boolean isChunkPos) @@ -155,7 +155,7 @@ public class DhSectionPos z = z * BitShiftUtil.powerOfTwo(detailLevel - newDetailLevel); } - return encodePos(newDetailLevel, x, z); + return encode(newDetailLevel, x, z); } @@ -291,14 +291,14 @@ public class DhSectionPos throw new IllegalStateException("section detail must be greater than 0"); } - return DhSectionPos.encodePos((byte) (detailLevel - 1), + return DhSectionPos.encode((byte) (detailLevel - 1), x * 2 + (child0to3 & 1), z * 2 + BitShiftUtil.half(child0to3 & 2)); } /** Returns this position's child index in its parent */ public static int getChildIndexOfParent(long pos) { return (getX(pos) & 1) + BitShiftUtil.square(getZ(pos) & 1); } - public static long getParentPos(long pos) { return DhSectionPos.encodePos((byte) (getDetailLevel(pos) + 1), BitShiftUtil.half(getX(pos)), BitShiftUtil.half(getZ(pos))); } + public static long getParentPos(long pos) { return DhSectionPos.encode((byte) (getDetailLevel(pos) + 1), BitShiftUtil.half(getX(pos)), BitShiftUtil.half(getZ(pos))); } @@ -309,7 +309,7 @@ public class DhSectionPos throw new IllegalArgumentException("getAdjacentPos can't be UP or DOWN, direction given: ["+dir.name()+"]."); } - return DhSectionPos.encodePos(getDetailLevel(pos), + return DhSectionPos.encode(getDetailLevel(pos), getX(pos) + dir.getNormal().x, getZ(pos) + dir.getNormal().z); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java index bc17f045a..a61bc22ab 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/repo/FullDataSourceV1Repo.java @@ -309,7 +309,7 @@ public class FullDataSourceV1Repo extends AbstractDhRepo { if (node != null || includeNullNodes) { - long rootPos = DhSectionPos.encodePos(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y); + long rootPos = DhSectionPos.encode(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y); if (QuadTree.this.isSectionPosInBounds(rootPos)) { this.iteratorPosQueue.enqueue(rootPos); diff --git a/core/src/test/java/tests/DhSectionPosTest.java b/core/src/test/java/tests/DhSectionPosTest.java index b3449cab2..14f29a068 100644 --- a/core/src/test/java/tests/DhSectionPosTest.java +++ b/core/src/test/java/tests/DhSectionPosTest.java @@ -24,7 +24,6 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhBlockPos2D; -import com.seibel.distanthorizons.core.util.LodUtil; import org.junit.Assert; import org.junit.Test; @@ -40,19 +39,19 @@ public class DhSectionPosTest long pos; // zero pos - pos = DhSectionPos.encodePos((byte) 0, 0, 0); + pos = DhSectionPos.encode((byte) 0, 0, 0); assertSectionPosEqual(0, DhSectionPos.getDetailLevel(pos)); assertSectionPosEqual(0, DhSectionPos.getX(pos)); assertSectionPosEqual(0, DhSectionPos.getZ(pos)); // positive values - pos = DhSectionPos.encodePos((byte) 10, 4, 1); + pos = DhSectionPos.encode((byte) 10, 4, 1); assertSectionPosEqual(10, DhSectionPos.getDetailLevel(pos)); assertSectionPosEqual(4, DhSectionPos.getX(pos)); assertSectionPosEqual(1, DhSectionPos.getZ(pos)); // negative position, positive detail level - pos = DhSectionPos.encodePos((byte) 2, -1, -4); + pos = DhSectionPos.encode((byte) 2, -1, -4); assertSectionPosEqual(2, DhSectionPos.getDetailLevel(pos)); assertSectionPosEqual(-1, DhSectionPos.getX(pos)); assertSectionPosEqual(-4, DhSectionPos.getZ(pos)); @@ -64,61 +63,61 @@ public class DhSectionPosTest @Test public void containsPosTest() { - long root = DhSectionPos.encodePos((byte) 10, 0, 0); - long child = DhSectionPos.encodePos((byte) 9, 1, 1); + long root = DhSectionPos.encode((byte) 10, 0, 0); + long child = DhSectionPos.encode((byte) 9, 1, 1); Assert.assertTrue("section pos contains fail", DhSectionPos.contains(root, child)); Assert.assertFalse("section pos contains fail", DhSectionPos.contains(child, root)); - root = DhSectionPos.encodePos((byte) 10, 1, 0); + root = DhSectionPos.encode((byte) 10, 1, 0); // out of bounds - child = DhSectionPos.encodePos((byte) 9, 0, 0); + child = DhSectionPos.encode((byte) 9, 0, 0); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encodePos((byte) 9, 1, 1); + child = DhSectionPos.encode((byte) 9, 1, 1); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); // in bounds - child = DhSectionPos.encodePos((byte) 9, 2, 0); + child = DhSectionPos.encode((byte) 9, 2, 0); Assert.assertTrue("position should be in bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encodePos((byte) 9, 3, 1); + child = DhSectionPos.encode((byte) 9, 3, 1); Assert.assertTrue("position should be in bounds", DhSectionPos.contains(root, child)); // out of bounds - child = DhSectionPos.encodePos((byte) 9, 2, 2); + child = DhSectionPos.encode((byte) 9, 2, 2); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encodePos((byte) 9, 3, 3); + child = DhSectionPos.encode((byte) 9, 3, 3); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encodePos((byte) 9, 4, 4); + child = DhSectionPos.encode((byte) 9, 4, 4); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - child = DhSectionPos.encodePos((byte) 9, 5, 5); + child = DhSectionPos.encode((byte) 9, 5, 5); Assert.assertFalse("position should be out of bounds", DhSectionPos.contains(root, child)); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 0, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 1, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 2, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 3, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 4, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 5, 0, 0))); - Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encodePos((byte) 6, 0, 0), DhSectionPos.encodePos((byte) 6, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 0, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 1, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 2, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 3, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 4, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 5, 0, 0))); + Assert.assertTrue(DhSectionPos.contains(DhSectionPos.encode((byte) 6, 0, 0), DhSectionPos.encode((byte) 6, 0, 0))); } @Test public void containsAdjacentPosTest() { // neither should contain the other, they are single blocks that are next to each other - long left = DhSectionPos.encodePos((byte) 0, 4606, 0); - long right = DhSectionPos.encodePos((byte) 0, 4607, 0); + long left = DhSectionPos.encode((byte) 0, 4606, 0); + long right = DhSectionPos.encode((byte) 0, 4607, 0); Assert.assertFalse(DhSectionPos.contains(left, right)); Assert.assertFalse(DhSectionPos.contains(right, left)); // 512 block wide sections that are adjacent, but not overlapping - left = DhSectionPos.encodePos((byte) 9, 0, 0); - right = DhSectionPos.encodePos((byte) 9, 1, 0); + left = DhSectionPos.encode((byte) 9, 0, 0); + right = DhSectionPos.encode((byte) 9, 1, 0); Assert.assertFalse(DhSectionPos.contains(left, right)); Assert.assertFalse(DhSectionPos.contains(right, left)); @@ -127,19 +126,19 @@ public class DhSectionPosTest @Test public void parentPosTest() { - long leaf = DhSectionPos.encodePos((byte) 0, 0, 0); + long leaf = DhSectionPos.encode((byte) 0, 0, 0); long convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 1); long parent = DhSectionPos.getParentPos(leaf); assertSectionPosEqual("get parent at 0,0 fail", convert, parent); - leaf = DhSectionPos.encodePos((byte) 0, 1, 1); + leaf = DhSectionPos.encode((byte) 0, 1, 1); convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 1); parent = DhSectionPos.getParentPos(leaf); assertSectionPosEqual("get parent at 1,1 fail", convert, parent); - leaf = DhSectionPos.encodePos((byte) 1, 2, 2); + leaf = DhSectionPos.encode((byte) 1, 2, 2); convert = DhSectionPos.convertToDetailLevel(leaf, (byte) 2); parent = DhSectionPos.getParentPos(leaf); assertSectionPosEqual("parent upscale fail", convert, parent); @@ -152,7 +151,7 @@ public class DhSectionPosTest @Test public void childPosTest() { - long node = DhSectionPos.encodePos((byte) 1, 2302, 0); + long node = DhSectionPos.encode((byte) 1, 2302, 0); long nw = DhSectionPos.getChildByIndex(node, 0); long sw = DhSectionPos.getChildByIndex(node, 1); long ne = DhSectionPos.getChildByIndex(node, 2); @@ -164,18 +163,18 @@ public class DhSectionPosTest Assert.assertNotEquals(ne, se); // confirm each child has the correct value - assertSectionPosEqual(nw, DhSectionPos.encodePos((byte) 0, 4604, 0)); - assertSectionPosEqual(sw, DhSectionPos.encodePos((byte) 0, 4605, 0)); - assertSectionPosEqual(ne, DhSectionPos.encodePos((byte) 0, 4604, 1)); - assertSectionPosEqual(se, DhSectionPos.encodePos((byte) 0, 4605, 1)); + assertSectionPosEqual(nw, DhSectionPos.encode((byte) 0, 4604, 0)); + assertSectionPosEqual(sw, DhSectionPos.encode((byte) 0, 4605, 0)); + assertSectionPosEqual(ne, DhSectionPos.encode((byte) 0, 4604, 1)); + assertSectionPosEqual(se, DhSectionPos.encode((byte) 0, 4605, 1)); } @Test public void getCenterBlock2DTest() { - long parentNode = DhSectionPos.encodePos((byte) 2, 1151, 0); // width 4 blocks - long inputPos = DhSectionPos.encodePos((byte) 0, 4606, 0); // width 1 block + long parentNode = DhSectionPos.encode((byte) 2, 1151, 0); // width 4 blocks + long inputPos = DhSectionPos.encode((byte) 0, 4606, 0); // width 1 block Assert.assertTrue(DhSectionPos.contains(parentNode, inputPos)); DhBlockPos2D parentCenter = DhSectionPos.getCenterBlockPos(parentNode); @@ -192,20 +191,20 @@ public class DhSectionPosTest // origin pos // DhBlockPos originBlockPos = new DhBlockPos(0, 0, 0); - long originSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, originBlockPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); + long originSectionPos = DhSectionPos.encodeContaining(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, originBlockPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); // offset pos // long offsetSectionPos; DhBlockPos offsetBlockPos = new DhBlockPos(1000, 0, 42000); - offsetSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, offsetBlockPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos); + offsetSectionPos = DhSectionPos.encodeContaining(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, offsetBlockPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 15, 656), offsetSectionPos); offsetBlockPos = new DhBlockPos(-987654, 0, 46); - offsetSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, offsetBlockPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); + offsetSectionPos = DhSectionPos.encodeContaining(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, offsetBlockPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); } @@ -215,19 +214,19 @@ public class DhSectionPosTest // origin pos // DhChunkPos originChunkPos = new DhChunkPos(0,0); - long originSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, originChunkPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos); + long originSectionPos = DhSectionPos.encodeContaining(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, originChunkPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 0, 0), originSectionPos); // offset pos // DhChunkPos offsetChunkPos = new DhChunkPos(1000, 42000); - long offsetSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, offsetChunkPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos); + long offsetSectionPos = DhSectionPos.encodeContaining(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, offsetChunkPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, 15, 656), offsetSectionPos); offsetChunkPos = new DhChunkPos(-987654, 46); - offsetSectionPos = DhSectionPos.encodeContainingPos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, offsetChunkPos); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); + offsetSectionPos = DhSectionPos.encodeContaining(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, offsetChunkPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL, -15433, 0), offsetSectionPos); } @@ -236,38 +235,38 @@ public class DhSectionPosTest { // origin pos // - long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0); + long originSectionPos = DhSectionPos.encode((byte) 0,0,0); originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, (byte) 1); - assertSectionPosEqual(DhSectionPos.encodePos((byte) 1, 0, 0), originSectionPos); + assertSectionPosEqual(DhSectionPos.encode((byte) 1, 0, 0), originSectionPos); originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0), originSectionPos); originSectionPos = DhSectionPos.convertToDetailLevel(originSectionPos, DhSectionPos.SECTION_REGION_DETAIL_LEVEL); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, 0, 0), originSectionPos); // offset pos // - long offsetSectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000); + long offsetSectionPos = DhSectionPos.encode((byte) 0,-10000,5000); offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, (byte) 1); - assertSectionPosEqual(DhSectionPos.encodePos((byte) 1, -5000, 2500), offsetSectionPos); + assertSectionPosEqual(DhSectionPos.encode((byte) 1, -5000, 2500), offsetSectionPos); offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), offsetSectionPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, -157, 78), offsetSectionPos); offsetSectionPos = DhSectionPos.convertToDetailLevel(offsetSectionPos, DhSectionPos.SECTION_REGION_DETAIL_LEVEL); - assertSectionPosEqual(DhSectionPos.encodePos(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), offsetSectionPos); + assertSectionPosEqual(DhSectionPos.encode(DhSectionPos.SECTION_REGION_DETAIL_LEVEL, -1, 0), offsetSectionPos); } @Test public void getOffsetWidth() { - long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0); - long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000); + long originSectionPos = DhSectionPos.encode((byte) 0,0,0); + long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000); @@ -311,8 +310,8 @@ public class DhSectionPosTest @Test public void getBlockWidth() { - long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0); - long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000); + long originSectionPos = DhSectionPos.encode((byte) 0,0,0); + long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000); assertSectionPosEqual(1, DhSectionPos.getBlockWidth(originSectionPos)); @@ -338,8 +337,8 @@ public class DhSectionPosTest @Test public void getCenterBlockPosOrigin() { - long originSectionPos = DhSectionPos.encodePos((byte) 0,0,0); - long sectionPos = DhSectionPos.encodePos((byte) 0,-10000,5000); + long originSectionPos = DhSectionPos.encode((byte) 0,0,0); + long sectionPos = DhSectionPos.encode((byte) 0,-10000,5000); @@ -385,28 +384,28 @@ public class DhSectionPosTest long pos; // origin block detail - pos = DhSectionPos.encodePos((byte) 0,0,0); + pos = DhSectionPos.encode((byte) 0,0,0); Assert.assertEquals(0, DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(0, DhSectionPos.getMinCornerBlockZ(pos)); // offset block detail - pos = DhSectionPos.encodePos((byte) 0,2,3); + pos = DhSectionPos.encode((byte) 0,2,3); Assert.assertEquals(2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(3 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos)); // negative offset block detail - pos = DhSectionPos.encodePos((byte) 0,-1,-2); + pos = DhSectionPos.encode((byte) 0,-1,-2); Assert.assertEquals(-1 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(-2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos)); // origin chunk detail - pos = DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,0,0); + pos = DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,0,0); Assert.assertEquals(0, DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(0, DhSectionPos.getMinCornerBlockZ(pos)); // offset chunk detail - pos = DhSectionPos.encodePos(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,2,3); + pos = DhSectionPos.encode(DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL,2,3); Assert.assertEquals(2 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockX(pos)); Assert.assertEquals(3 * DhSectionPos.getBlockWidth(pos), DhSectionPos.getMinCornerBlockZ(pos)); @@ -416,13 +415,13 @@ public class DhSectionPosTest @Test public void getAdjacentPos() { - long pos = DhSectionPos.encodePos((byte) 0, 0, 0); + long pos = DhSectionPos.encode((byte) 0, 0, 0); - assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 0, -1), DhSectionPos.getAdjacentPos(pos, EDhDirection.NORTH)); - assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 0, 1), DhSectionPos.getAdjacentPos(pos, EDhDirection.SOUTH)); + assertSectionPosEqual(DhSectionPos.encode((byte) 0, 0, -1), DhSectionPos.getAdjacentPos(pos, EDhDirection.NORTH)); + assertSectionPosEqual(DhSectionPos.encode((byte) 0, 0, 1), DhSectionPos.getAdjacentPos(pos, EDhDirection.SOUTH)); - assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, 1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.EAST)); - assertSectionPosEqual(DhSectionPos.encodePos((byte) 0, -1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.WEST)); + assertSectionPosEqual(DhSectionPos.encode((byte) 0, 1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.EAST)); + assertSectionPosEqual(DhSectionPos.encode((byte) 0, -1, 0), DhSectionPos.getAdjacentPos(pos, EDhDirection.WEST)); // getting the adjacent position in the up and down position don't make sense Assert.assertThrows(IllegalArgumentException.class, () -> { DhSectionPos.getAdjacentPos(pos, EDhDirection.UP); }); @@ -432,7 +431,7 @@ public class DhSectionPosTest @Test public void forEachChildIterator() { - long pos = DhSectionPos.encodePos((byte) 1, 0, 0); + long pos = DhSectionPos.encode((byte) 1, 0, 0); ArrayList childPosList = new ArrayList<>(); AtomicInteger childCount = new AtomicInteger(0); @@ -442,10 +441,10 @@ public class DhSectionPosTest childPosList.add(childPos); }); - Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 0, 0))); - Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 1, 0))); - Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 0, 1))); - Assert.assertTrue(childPosList.contains(DhSectionPos.encodePos((byte) 0, 1, 1))); + Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 0, 0))); + Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 1, 0))); + Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 0, 1))); + Assert.assertTrue(childPosList.contains(DhSectionPos.encode((byte) 0, 1, 1))); } diff --git a/core/src/test/java/tests/QuadTreeTest.java b/core/src/test/java/tests/QuadTreeTest.java index 351cd9ba0..28cbfabb0 100644 --- a/core/src/test/java/tests/QuadTreeTest.java +++ b/core/src/test/java/tests/QuadTreeTest.java @@ -60,30 +60,30 @@ public class QuadTreeTest // (pseudo) root node // - testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 0); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 0); // first child (0,0) // - testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 1); - testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 0), 2); - testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 1), 3); - testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 1), 4); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 9, 1, 0), 2); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 1), 3); + testSet(tree, DhSectionPos.encode((byte) 9, 1, 1), 4); // second child (0,0) (0,0) // - testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 0), 5); - testSet(tree, DhSectionPos.encodePos((byte) 8, 1, 0), 6); - testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 1), 7); - testSet(tree, DhSectionPos.encodePos((byte) 8, 1, 1), 8); + testSet(tree, DhSectionPos.encode((byte) 8, 0, 0), 5); + testSet(tree, DhSectionPos.encode((byte) 8, 1, 0), 6); + testSet(tree, DhSectionPos.encode((byte) 8, 0, 1), 7); + testSet(tree, DhSectionPos.encode((byte) 8, 1, 1), 8); // second child (0,0) (1,1) // - testSet(tree, DhSectionPos.encodePos((byte) 8, 2, 2), 9); - testSet(tree, DhSectionPos.encodePos((byte) 8, 3, 2), 10); - testSet(tree, DhSectionPos.encodePos((byte) 8, 2, 3), 11); - testSet(tree, DhSectionPos.encodePos((byte) 8, 3, 3), 12); + testSet(tree, DhSectionPos.encode((byte) 8, 2, 2), 9); + testSet(tree, DhSectionPos.encode((byte) 8, 3, 2), 10); + testSet(tree, DhSectionPos.encode((byte) 8, 2, 3), 11); + testSet(tree, DhSectionPos.encode((byte) 8, 3, 3), 12); // third child (0,0) (1,0) (0,0) // - testSet(tree, DhSectionPos.encodePos((byte) 7, 5, 0), 9); - testSet(tree, DhSectionPos.encodePos((byte) 7, 6, 0), 10); - testSet(tree, DhSectionPos.encodePos((byte) 7, 5, 1), 11); - testSet(tree, DhSectionPos.encodePos((byte) 7, 6, 1), 12); + testSet(tree, DhSectionPos.encode((byte) 7, 5, 0), 9); + testSet(tree, DhSectionPos.encode((byte) 7, 6, 0), 10); + testSet(tree, DhSectionPos.encode((byte) 7, 5, 1), 11); + testSet(tree, DhSectionPos.encode((byte) 7, 6, 1), 12); } @@ -95,13 +95,13 @@ public class QuadTreeTest // root node // - testSet(tree, DhSectionPos.encodePos((byte) 10, -1, -1), 0); + testSet(tree, DhSectionPos.encode((byte) 10, -1, -1), 0); // first child (-1,-1) // - testSet(tree, DhSectionPos.encodePos((byte) 9, -2, -1), 1); - testSet(tree, DhSectionPos.encodePos((byte) 9, -1, -1), 2); - testSet(tree, DhSectionPos.encodePos((byte) 9, -2, -2), 3); - testSet(tree, DhSectionPos.encodePos((byte) 9, -1, -2), 4); + testSet(tree, DhSectionPos.encode((byte) 9, -2, -1), 1); + testSet(tree, DhSectionPos.encode((byte) 9, -1, -1), 2); + testSet(tree, DhSectionPos.encode((byte) 9, -2, -2), 3); + testSet(tree, DhSectionPos.encode((byte) 9, -1, -2), 4); // TODO // // second child (-1,-1) (0,0) // @@ -132,36 +132,36 @@ public class QuadTreeTest // wrong detail level on purpose, if the detail level was 0 (block) this should work - long outOfBoundsPos = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); + long outOfBoundsPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); // out of bounds // - outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) + 1, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) + 1, 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); - outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2), 0); testSet(tree, outOfBoundsPos, -1, IndexOutOfBoundsException.class); Assert.assertEquals("incorrect leaf node count", 0, tree.leafNodeCount()); // in bounds // - outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 1, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount()); - outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 3, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 3, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); // TODO this position probably has trouble with getting the center. - outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 2, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 3, tree.leafNodeCount()); - outOfBoundsPos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0); + outOfBoundsPos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (treeParams.getWidthInBlocks() / 2) - 4, 0); testSet(tree, outOfBoundsPos, 0); Assert.assertEquals("incorrect leaf node count", 4, tree.leafNodeCount()); @@ -174,15 +174,15 @@ public class QuadTreeTest Assert.assertEquals("Test may need to be re-calculated for different max detail level.", 9, tree.treeMinDetailLevel); - long rootPos = DhSectionPos.encodePos((byte) 9, 0, -1); + long rootPos = DhSectionPos.encode((byte) 9, 0, -1); testSet(tree, rootPos, 1); // pos is in tree, but out of range - long midPos = DhSectionPos.encodePos((byte) 8, 0, -1); + long midPos = DhSectionPos.encode((byte) 8, 0, -1); testSet(tree, midPos, 2, IndexOutOfBoundsException.class); // pos is in tree, but out of range - long leafPos = DhSectionPos.encodePos((byte) 7, 0, -2); + long leafPos = DhSectionPos.encode((byte) 7, 0, -2); testSet(tree, leafPos, 3, IndexOutOfBoundsException.class); } @@ -198,13 +198,13 @@ public class QuadTreeTest // (pseudo) root nodes // - testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); // first child (0,0) // - long nw = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0); - long ne = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 0); - long sw = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 1); - long se = DhSectionPos.encodePos(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 1); + long nw = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 0); + long ne = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 0); + long sw = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 0, 1); + long se = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, 1, 1); testSet(tree, nw, 2); testSet(tree, ne, 3); @@ -260,12 +260,12 @@ public class QuadTreeTest Assert.assertEquals("Tree center incorrect", DhBlockPos2D.ZERO, tree.getCenterBlockPos()); // on the negative X edge - long edgePos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks() / 2, 0); + long edgePos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, -treeParams.getWidthInBlocks() / 2, 0); testSet(tree, edgePos, 1); Assert.assertEquals("incorrect leaf node count", 1, tree.leafNodeCount()); // +1 root node from the negative X edge - long adjacentEdgePos = DhSectionPos.encodePos(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0); + long adjacentEdgePos = DhSectionPos.encode(LodUtil.BLOCK_DETAIL_LEVEL, (-treeParams.getWidthInBlocks() / 2) + pseudoRootNodeWidthInBlocks, 0); testSet(tree, adjacentEdgePos, 2); Assert.assertEquals("incorrect leaf node count", 2, tree.leafNodeCount()); @@ -285,14 +285,14 @@ public class QuadTreeTest // (pseudo) root nodes // - testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1); - testSet(tree, DhSectionPos.encodePos((byte) 10, 1, 0), 2); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 10, 1, 0), 2); // first child (0,0) // - testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 3); - testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 0), 4); - testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 1), 5); - testSet(tree, DhSectionPos.encodePos((byte) 9, 1, 1), 6); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 3); + testSet(tree, DhSectionPos.encode((byte) 9, 1, 0), 4); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 1), 5); + testSet(tree, DhSectionPos.encode((byte) 9, 1, 1), 6); @@ -332,19 +332,19 @@ public class QuadTreeTest @Test public void NewQuadTreeIterationTest() { - QuadNode rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); - rootNode.setValue(DhSectionPos.encodePos((byte) 10, 0, 0), 0); + rootNode.setValue(DhSectionPos.encode((byte) 10, 0, 0), 0); - rootNode.setValue(DhSectionPos.encodePos((byte) 9, 0, 0), 1); - rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 0), 1); - rootNode.setValue(DhSectionPos.encodePos((byte) 9, 0, 1), 1); - rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 1), null); + rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 0), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 0), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 1), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 1), null); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), 2); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 0), 2); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), 2); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), null); @@ -411,7 +411,7 @@ public class QuadTreeTest { AbstractTestTreeParams treeParams = new TinyTestTree(); final QuadTree tree = new QuadTree<>(treeParams.getWidthInBlocks(), treeParams.getPositiveEdgeCenterPos(), LodUtil.BLOCK_DETAIL_LEVEL); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); // confirm the root node were added int rootNodeCount = 0; @@ -499,10 +499,10 @@ public class QuadTreeTest Assert.assertEquals("incorrect tree width", treeParams.getWidthInBlocks(), tree.diameterInBlocks()); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, -1), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, -1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); int rootNodeCount = 0; LongIterator rootNodeIterator = tree.rootNodePosIterator(); @@ -529,18 +529,18 @@ public class QuadTreeTest // 2x2 valid positions (overlap the tree's width) - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 0), 0); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, 0), 0); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, -1), 0); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, -1), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 0), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, 0), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, -1), 0); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, -1), 0); // invalid positions - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, -1, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 0, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, -1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 0, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encodePos(tree.treeMinDetailLevel, 1, -1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, 1), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode(tree.treeMinDetailLevel, 1, -1), -1, IndexOutOfBoundsException.class); int rootNodeCount = 0; @@ -565,17 +565,17 @@ public class QuadTreeTest Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMinDetailLevel); // valid detail levels - testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1); - testSet(tree, DhSectionPos.encodePos((byte) 9, 0, 0), 2); - testSet(tree, DhSectionPos.encodePos((byte) 8, 0, 0), 3); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 9, 0, 0), 2); + testSet(tree, DhSectionPos.encode((byte) 8, 0, 0), 3); // detail level too low - testSet(tree, DhSectionPos.encodePos((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encodePos((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode((byte) 7, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode((byte) 6, 0, 0), -1, IndexOutOfBoundsException.class); // detail level too high - testSet(tree, DhSectionPos.encodePos((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class); - testSet(tree, DhSectionPos.encodePos((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode((byte) 11, 0, 0), -1, IndexOutOfBoundsException.class); + testSet(tree, DhSectionPos.encode((byte) 12, 0, 0), -1, IndexOutOfBoundsException.class); } @@ -587,7 +587,7 @@ public class QuadTreeTest Assert.assertEquals("Test detail level's need to be adjusted. This isn't necessarily a failed test.", 10, tree.treeMinDetailLevel); // create the root node - testSet(tree, DhSectionPos.encodePos((byte) 10, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 10, 0, 0), 1); @@ -678,7 +678,7 @@ public class QuadTreeTest @Test public void quadNodeChildPositionIndexTest() { - QuadNode rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), (byte) 0); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), (byte) 0); LongIterator directChildPosIterator = rootNode.getChildPosIterator(); while (directChildPosIterator.hasNext()) { @@ -708,7 +708,7 @@ public class QuadTreeTest // center root node - long centerNodePos = DhSectionPos.encodePos((byte) 1, 0, 0); + long centerNodePos = DhSectionPos.encode((byte) 1, 0, 0); // create node tree.setValue(centerNodePos, 0); @@ -727,7 +727,7 @@ public class QuadTreeTest // edge root node - long offsetNodePos = DhSectionPos.encodePos((byte) 1, -17, -16); + long offsetNodePos = DhSectionPos.encode((byte) 1, -17, -16); // create node tree.setValue(offsetNodePos, 0); @@ -772,7 +772,7 @@ public class QuadTreeTest // - testSet(tree, DhSectionPos.encodePos((byte) 0, 0, 0), 1); + testSet(tree, DhSectionPos.encode((byte) 0, 0, 0), 1); Assert.assertEquals(1, tree.count()); tree.setCenterBlockPos(new DhBlockPos2D(treeWidth + (treeWidth / 2), 0)); Assert.assertEquals(0, tree.count()); @@ -783,21 +783,21 @@ public class QuadTreeTest //@Test public void autoDeleteNullQuadNodeChildTest() { - QuadNode rootNode = new QuadNode<>(DhSectionPos.encodePos((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); + QuadNode rootNode = new QuadNode<>(DhSectionPos.encode((byte) 10, 0, 0), LodUtil.BLOCK_DETAIL_LEVEL); - rootNode.setValue(DhSectionPos.encodePos((byte) 10, 0, 0), 0); + rootNode.setValue(DhSectionPos.encode((byte) 10, 0, 0), 0); - long midNodePos = DhSectionPos.encodePos((byte) 9, 0, 0); + long midNodePos = DhSectionPos.encode((byte) 9, 0, 0); //rootNode.setValue(midNodePos, null); // holds detail 8 - rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 0), 1); - rootNode.setValue(DhSectionPos.encodePos((byte) 9, 0, 1), 1); - rootNode.setValue(DhSectionPos.encodePos((byte) 9, 1, 1), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 0), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 0, 1), 1); + rootNode.setValue(DhSectionPos.encode((byte) 9, 1, 1), 1); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), 2); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 0), 2); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), 2); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), 2); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), 2); @@ -810,12 +810,12 @@ public class QuadTreeTest // test removing nodes // // remove two leaf nodes from the root - long leafPos = DhSectionPos.encodePos((byte) 9, 1, 1); + long leafPos = DhSectionPos.encode((byte) 9, 1, 1); rootNode.setValue(leafPos, null); Assert.assertEquals(3, rootNode.getNonNullChildCount()); Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos)); - leafPos = DhSectionPos.encodePos((byte) 9, 0, 1); + leafPos = DhSectionPos.encode((byte) 9, 0, 1); rootNode.setValue(leafPos, null); Assert.assertEquals(2, rootNode.getNonNullChildCount()); Assert.assertNull("Node wasn't deleted", rootNode.getNode(leafPos)); @@ -827,13 +827,13 @@ public class QuadTreeTest Assert.assertEquals(4, rootNode.getNode(midNodePos).getNonNullChildCount()); // remove all but one, mid-node should still be present - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 0), null); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 0, 1), null); - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 0), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 0), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 0, 1), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 0), null); Assert.assertEquals(1, rootNode.getNode(midNodePos).getNonNullChildCount()); // remove last mid-node child, mid-node should now be removed - rootNode.setValue(DhSectionPos.encodePos((byte) 8, 1, 1), null); + rootNode.setValue(DhSectionPos.encode((byte) 8, 1, 1), null); Assert.assertNull("Mid node not deleted.", rootNode.getNode(midNodePos)); Assert.assertEquals(3, rootNode.getNonNullChildCount()); From 36fcc46445502636dd71e15dc0a4b068700e8df5 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 07:48:52 -0500 Subject: [PATCH 099/104] Minor DataTransofmer refactor --- .../render/ColumnRenderSource.java | 2 +- .../FullDataToRenderDataTransformer.java | 92 ++++++++----------- 2 files changed, 40 insertions(+), 54 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java index 9d3407c46..a00fb750d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/ColumnRenderSource.java @@ -182,7 +182,7 @@ public class ColumnRenderSource implements IDataSource EDhApiWorldGenerationStep worldGenStep = inputFullDataSource.getWorldGenStepAtRelativePos(x, z); if (dataColumn != null && worldGenStep != EDhApiWorldGenerationStep.EMPTY) { - FullDataToRenderDataTransformer.convertColumnData( + FullDataToRenderDataTransformer.updateRenderDataViewWithFullDataColumn( level, inputFullDataSource.mapping, minBlockPos.x + x, minBlockPos.z + z, diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index 00dce89d3..dc2f05229 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -124,7 +124,7 @@ public class FullDataToRenderDataTransformer ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z); LongArrayList dataColumn = fullDataSource.get(x, z); - convertColumnData(level, fullDataSource.mapping, baseX + x, baseZ + z, columnArrayView, dataColumn); + updateRenderDataViewWithFullDataColumn(level, fullDataSource.mapping, baseX + x, baseZ + z, columnArrayView, dataColumn); } } @@ -139,30 +139,33 @@ public class FullDataToRenderDataTransformer return columnSource; } - - - //================// - // helper methods // - //================// - - /** - * Called in loops that may run for an extended period of time.
- * This is necessary to allow canceling these transformers since running - * them after the client has left a given world will throw exceptions. - */ - private static void throwIfThreadInterrupted() throws InterruptedException + /** Updates the given {@link ColumnArrayView} to match the incoming Full data {@link LongArrayList} */ + public static void updateRenderDataViewWithFullDataColumn( + IDhClientLevel level, + FullDataPointIdMap fullDataMapping, int blockX, int blockZ, + ColumnArrayView columnArrayView, + LongArrayList fullDataColumn) { - if (Thread.interrupted()) + if (fullDataColumn == null || fullDataColumn.size() == 0) { - throw new InterruptedException(FullDataToRenderDataTransformer.class.getSimpleName() + " task interrupted."); + return; + } + + int dataTotalLength = fullDataColumn.size(); + if (dataTotalLength > columnArrayView.verticalSize()) + { + ColumnArrayView totalColumnData = new ColumnArrayView(new LongArrayList(new long[dataTotalLength]), dataTotalLength, 0, dataTotalLength); + iterateAndConvert(level, fullDataMapping, blockX, blockZ, totalColumnData, fullDataColumn); + columnArrayView.changeVerticalSizeFrom(totalColumnData); + } + else + { + iterateAndConvert(level, fullDataMapping, blockX, blockZ, columnArrayView, fullDataColumn); //Directly use the arrayView since it fits. } } - - - // TODO what does this mean? private static void iterateAndConvert( - IDhClientLevel level, FullDataPointIdMap fullDataMapping, - int blockX, int blockZ, + IDhClientLevel level, FullDataPointIdMap fullDataMapping, + int blockX, int blockZ, ColumnArrayView renderColumnData, LongArrayList fullColumnData) { boolean avoidSolidBlocks = (Config.Client.Advanced.Graphics.Quality.blocksToIgnore.get() == EDhApiBlocksToAvoid.NON_COLLIDING); @@ -188,21 +191,6 @@ public class FullDataToRenderDataTransformer int blockLight = FullDataPointUtil.getBlockLight(fullData); int skyLight = FullDataPointUtil.getSkyLight(fullData); - // TODO how should corrupted data be handled? - // TODO why is the full data corrupted in the first place? FullDataPointUtil hasn't been changed in a long time, could one of the full data point objects be corrupted? - // TODO if either of these happen the ID might also be invalid - //if (bottomY + blockHeight > 300) - //{ - // // this data point is too tall, it's probably a monolith - // int k = 0; - // throw new RuntimeException(); - //} - //if (light > 16 || light < 0) - //{ - // // light is out of range - // throw new RuntimeException(); - //} - IBiomeWrapper biome; IBlockStateWrapper block; try @@ -272,7 +260,7 @@ public class FullDataToRenderDataTransformer skyLight = skylightToApplyToNextBlock; blockLight = blocklightToApplyToNextBlock; } - + //check if they share a top-bottom face and if they have same collor if (color == lastColor && bottomY + blockHeight == lastBottom && columnOffset > 0) { @@ -291,7 +279,7 @@ public class FullDataToRenderDataTransformer } lastBottom = bottomY; lastColor = color; - + } @@ -301,24 +289,22 @@ public class FullDataToRenderDataTransformer } } - // TODO what does this mean? - public static void convertColumnData(IDhClientLevel level, FullDataPointIdMap fullDataMapping, int blockX, int blockZ, ColumnArrayView columnArrayView, LongArrayList fullDataColumn) + + + //================// + // helper methods // + //================// + + /** + * Called in loops that may run for an extended period of time.
+ * This is necessary to allow canceling these transformers since running + * them after the client has left a given world will throw exceptions. + */ + private static void throwIfThreadInterrupted() throws InterruptedException { - if (fullDataColumn == null || fullDataColumn.size() == 0) + if (Thread.interrupted()) { - return; - } - - int dataTotalLength = fullDataColumn.size(); - if (dataTotalLength > columnArrayView.verticalSize()) - { - ColumnArrayView totalColumnData = new ColumnArrayView(new LongArrayList(new long[dataTotalLength]), dataTotalLength, 0, dataTotalLength); - iterateAndConvert(level, fullDataMapping, blockX, blockZ, totalColumnData, fullDataColumn); - columnArrayView.changeVerticalSizeFrom(totalColumnData); - } - else - { - iterateAndConvert(level, fullDataMapping, blockX, blockZ, columnArrayView, fullDataColumn); //Directly use the arrayView since it fits. + throw new InterruptedException(FullDataToRenderDataTransformer.class.getSimpleName() + " task interrupted."); } } From 44fe1eafb148191f0e5737f59dae7507cc6ed496 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 16:09:46 -0500 Subject: [PATCH 100/104] Fix ConfigEntry String value saving --- .../interfaces/config/IConfigEntry.java | 3 +- .../core/config/types/ConfigEntry.java | 28 +++++++++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java index a31745a8e..3297a1a26 100644 --- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java @@ -67,10 +67,11 @@ public interface IConfigEntry * Checks if the option is valid * * 0 == valid + * 2 == invalid * 1 == number too high * -1 == number too low */ - byte isValid(); + byte isValid(); // TODO replace with an enum /** Checks if a value is valid */ byte isValid(T value); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java index 12bb99e36..5ef257666 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java @@ -256,20 +256,38 @@ public class ConfigEntry extends AbstractConfigType> implem public byte isValid(T value, T min, T max) { if (this.configBase.disableMinMax) + { return 0; - - if (value == null || this.value == null || value.getClass() != this.value.getClass()) // If the 2 variables aren't the same type then it will be invalid + } + else if (min == null && max == null) + { + // no validation is needed for this field + return 0; + } + else if (value == null || this.value == null + || value.getClass() != this.value.getClass()) + { + // If the 2 variables aren't the same type then it will be invalid return 2; - if (Number.class.isAssignableFrom(value.getClass())) - { // Only check min max if it is a number + } + else if (Number.class.isAssignableFrom(value.getClass())) + { + // Only check min max if it is a number if (max != null && NumberUtil.greaterThan((Number) value, (Number) max)) + { return 1; + } if (min != null && NumberUtil.lessThan((Number) value, (Number) min)) + { return -1; + } return 0; } - return 0; + else + { + return 0; + } } /** This should normally not be called since set() automatically calls this */ From d9d9f3dad8440f0eea90ce095c146acc0341cf5d Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 17:06:58 -0500 Subject: [PATCH 101/104] minor logging fixes --- .../render/bufferBuilding/ColumnRenderBufferBuilder.java | 2 +- .../seibel/distanthorizons/core/render/LodRenderSection.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java index b5751e34b..623198fff 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java @@ -108,7 +108,7 @@ public class ColumnRenderBufferBuilder long builderEndTime = System.currentTimeMillis(); long buildMs = builderEndTime - builderStartTime; - LOGGER.debug("RenderRegion end QuadBuild @ " + renderSource.pos + " took: " + buildMs); + //LOGGER.debug("RenderRegion end QuadBuild @ " + renderSource.pos + " took: " + buildMs); return builder; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index 22605df90..bacd2eb7b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -292,7 +292,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable } catch (Exception e) { - LOGGER.warn("Unable to get render source " + this.pos + ", error: " + e.getMessage(), e); + LOGGER.warn("Unable to get render source " + DhSectionPos.toString(this.pos) + ", error: " + e.getMessage(), e); this.renderSourceLoadingRefFuture = null; return null; } From 3cef8b9a4f266ad8ab07d9dd548f3289f7c91826 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 17:27:17 -0500 Subject: [PATCH 102/104] Improve cave culling and add config for ignored/cave blocks --- .../distanthorizons/core/config/Config.java | 50 ++++++- .../ColumnRenderBufferBuilder.java | 21 +-- .../render/bufferBuilding/LodQuadBuilder.java | 8 +- .../FullDataToRenderDataTransformer.java | 125 ++++++++++++------ .../wrapperInterfaces/IWrapperFactory.java | 11 ++ .../assets/distanthorizons/lang/en_us.json | 9 +- 6 files changed, 157 insertions(+), 67 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 0ace849e4..56a3cde8e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -20,17 +20,20 @@ package com.seibel.distanthorizons.core.config; +import com.seibel.distanthorizons.api.DhApi; import com.seibel.distanthorizons.api.enums.config.*; import com.seibel.distanthorizons.api.enums.config.quickOptions.*; import com.seibel.distanthorizons.api.enums.rendering.*; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; import com.seibel.distanthorizons.core.config.eventHandlers.*; import com.seibel.distanthorizons.core.config.eventHandlers.presets.*; +import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener; import com.seibel.distanthorizons.core.config.types.*; import com.seibel.distanthorizons.core.config.types.enums.*; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhSectionPos; +import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.util.StringUtil; @@ -610,6 +613,7 @@ public class Config + " does not have a ceiling.") .build(); + @Deprecated public static ConfigEntry caveCullingHeight = new ConfigEntry.Builder() .setMinDefaultMax(-4096, 40, 4096) .comment("" @@ -843,13 +847,47 @@ public class Config + "") .build(); - //public static ConfigEntry showMigrationChatWarning = new ConfigEntry.Builder() - // .set(true) - // .comment("" - // + "Determines if a message should be displayed in the chat when LOD migration starts. \n" - // + "") - // .build(); + public static ConfigEntry ignoredRenderBlockCsv = new ConfigEntry.Builder() + .set("minecraft:barrier,minecraft:structure_void,minecraft:light,minecraft:tripwire") + .comment("" + + "A comma separated list of block resource locations that won't be rendered by DH. \n" + + "Note: air is always included in this list. \n" + + "") + .build(); + public static ConfigEntry ignoredRenderCaveBlockCsv = new ConfigEntry.Builder() + .set("minecraft:glow_lichen,minecraft:rail,minecraft:water,minecraft:lava,minecraft:bubble_column") + .comment("" + + "A comma separated list of block resource locations that shouldn't be rendered \n" + + "if they are in a 0 sky light underground area. \n" + + "Note: air is always included in this list. \n" + + "") + .build(); + + static + { + ignoredRenderBlockCsv.addListener(new ConfigChangeListener(Config.Client.Advanced.LodBuilding.ignoredRenderBlockCsv, + (blockCsv) -> + { + IWrapperFactory wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class); + if (wrapperFactory != null) + { + wrapperFactory.resetRendererIgnoredBlocksSet(); + DhApi.Delayed.renderProxy.clearRenderDataCache(); + } + })); + + ignoredRenderCaveBlockCsv.addListener(new ConfigChangeListener(Config.Client.Advanced.LodBuilding.ignoredRenderCaveBlockCsv, + (blockCsv) -> + { + IWrapperFactory wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class); + if (wrapperFactory != null) + { + wrapperFactory.resetRendererIgnoredCaveBlocks(); + DhApi.Delayed.renderProxy.clearRenderDataCache(); + } + })); + } } public static class Multiplayer diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java index 623198fff..64c1abd02 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java @@ -82,28 +82,9 @@ public class ColumnRenderBufferBuilder { boolean enableTransparency = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; - //EVENT_LOGGER.trace("RenderRegion start QuadBuild @ " + renderSource.sectionPos); - boolean enableSkyLightCulling = - Config.Client.Advanced.Graphics.AdvancedGraphics.enableCaveCulling.get() - && ( - // dimensions with a ceiling will be all caves so we don't want cave culling - !clientLevel.getLevelWrapper().hasCeiling() - // the end has a lot of overhangs with 0 lighting above the void, which look broken with - // the current cave culling logic (this could probably be improved, but just skipping it works best for now) - && !clientLevel.getLevelWrapper().getDimensionType().isTheEnd() - // FIXME temporary fix - // Cave culling is currently broken for any detail level above 0 - && DhSectionPos.getDetailLevel(renderSource.pos) == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL - ); - - int skyLightCullingBelow = Config.Client.Advanced.Graphics.AdvancedGraphics.caveCullingHeight.get(); - // FIXME: Clamp also to the max world height. - skyLightCullingBelow = Math.max(skyLightCullingBelow, clientLevel.getMinY()); - - long builderStartTime = System.currentTimeMillis(); - LodQuadBuilder builder = new LodQuadBuilder(enableSkyLightCulling, (short) (skyLightCullingBelow - clientLevel.getMinY()), enableTransparency, clientLevel.getClientLevelWrapper()); + LodQuadBuilder builder = new LodQuadBuilder(enableTransparency, clientLevel.getClientLevelWrapper()); makeLodRenderData(builder, renderSource, adjData); long builderEndTime = System.currentTimeMillis(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java index 08a593656..ab3605bdd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java @@ -51,7 +51,9 @@ public class LodQuadBuilder private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + @Deprecated public final boolean skipQuadsWithZeroSkylight; + @Deprecated public final short skyLightCullingBelow; @SuppressWarnings("unchecked") @@ -123,7 +125,7 @@ public class LodQuadBuilder // constructor // //=============// - public LodQuadBuilder(boolean enableSkylightCulling, short skyLightCullingBelow, boolean doTransparency, IClientLevelWrapper clientLevelWrapper) + public LodQuadBuilder(boolean doTransparency, IClientLevelWrapper clientLevelWrapper) { this.doTransparency = doTransparency; for (int i = 0; i < 6; i++) @@ -132,8 +134,8 @@ public class LodQuadBuilder this.transparentQuads[i] = new ArrayList<>(); } - this.skipQuadsWithZeroSkylight = enableSkylightCulling; - this.skyLightCullingBelow = skyLightCullingBelow; + this.skipQuadsWithZeroSkylight = false; + this.skyLightCullingBelow = 0; this.clientLevelWrapper = clientLevelWrapper; this.debugRenderingMode = Config.Client.Advanced.Debugging.debugRendering.get(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index dc2f05229..bbfa76a0b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.dataObjects.transformers; import com.seibel.distanthorizons.api.enums.config.EDhApiBlocksToAvoid; +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dataObjects.fullData.FullDataPointIdMap; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; @@ -110,32 +111,23 @@ public class FullDataToRenderDataTransformer } columnSource.markNotEmpty(); + int baseX = DhSectionPos.getMinCornerBlockX(pos); + int baseZ = DhSectionPos.getMinCornerBlockZ(pos); - if (dataDetail == columnSource.getDataDetailLevel()) + for (int x = 0; x < DhSectionPos.getWidthCountForLowerDetailedSection(pos, dataDetail); x++) { - int baseX = DhSectionPos.getMinCornerBlockX(pos); - int baseZ = DhSectionPos.getMinCornerBlockZ(pos); - - for (int x = 0; x < DhSectionPos.getWidthCountForLowerDetailedSection(pos, dataDetail); x++) + for (int z = 0; z < DhSectionPos.getWidthCountForLowerDetailedSection(pos, dataDetail); z++) { - for (int z = 0; z < DhSectionPos.getWidthCountForLowerDetailedSection(pos, dataDetail); z++) - { - throwIfThreadInterrupted(); - - ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z); - LongArrayList dataColumn = fullDataSource.get(x, z); - updateRenderDataViewWithFullDataColumn(level, fullDataSource.mapping, baseX + x, baseZ + z, columnArrayView, dataColumn); - } + throwIfThreadInterrupted(); + + ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z); + LongArrayList dataColumn = fullDataSource.get(x, z); + updateRenderDataViewWithFullDataColumn(level, fullDataSource.mapping, baseX + x, baseZ + z, columnArrayView, dataColumn); } - - columnSource.fillDebugFlag(0, 0, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.DebugSourceFlag.FULL); - - } - else - { - throw new UnsupportedOperationException("To be implemented"); - //FIXME: Implement different size creation of renderData } + + columnSource.fillDebugFlag(0, 0, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.DebugSourceFlag.FULL); + return columnSource; } @@ -168,19 +160,36 @@ public class FullDataToRenderDataTransformer int blockX, int blockZ, ColumnArrayView renderColumnData, LongArrayList fullColumnData) { - boolean avoidSolidBlocks = (Config.Client.Advanced.Graphics.Quality.blocksToIgnore.get() == EDhApiBlocksToAvoid.NON_COLLIDING); + boolean ignoreNonCollidingBlocks = (Config.Client.Advanced.Graphics.Quality.blocksToIgnore.get() == EDhApiBlocksToAvoid.NON_COLLIDING); boolean colorBelowWithAvoidedBlocks = Config.Client.Advanced.Graphics.Quality.tintWithAvoidedBlocks.get(); HashSet blockStatesToIgnore = WRAPPER_FACTORY.getRendererIgnoredBlocks(level.getLevelWrapper()); + HashSet caveBlockStatesToIgnore = WRAPPER_FACTORY.getRendererIgnoredCaveBlocks(level.getLevelWrapper()); + + boolean caveCullingEnabled = + Config.Client.Advanced.Graphics.AdvancedGraphics.enableCaveCulling.get() + && ( + // dimensions with a ceiling will be all caves so we don't want cave culling + !level.getLevelWrapper().hasCeiling() + // the end has a lot of overhangs with 0 lighting above the void, which look broken with + // the current cave culling logic (this could probably be improved, but just skipping it works best for now) + && !level.getLevelWrapper().getDimensionType().isTheEnd() + ); boolean isVoid = true; + int colorToApplyToNextBlock = -1; int lastColor = 0; int lastBottom = -10000; + int skylightToApplyToNextBlock = -1; int blocklightToApplyToNextBlock = -1; int columnOffset = 0; + IBiomeWrapper biome = null; + IBlockStateWrapper block = null; + + // goes from the top down for (int i = 0; i < fullColumnData.size(); i++) { @@ -191,8 +200,6 @@ public class FullDataToRenderDataTransformer int blockLight = FullDataPointUtil.getBlockLight(fullData); int skyLight = FullDataPointUtil.getSkyLight(fullData); - IBiomeWrapper biome; - IBlockStateWrapper block; try { biome = fullDataMapping.getBiomeWrapper(id); @@ -217,28 +224,72 @@ public class FullDataToRenderDataTransformer } - if (blockStatesToIgnore.contains(block)) + //====================// + // ignored block and // + // cave culling check // + //====================// + + boolean ignoreBlock = blockStatesToIgnore.contains(block); + boolean caveBlock = caveBlockStatesToIgnore.contains(block); + if (caveBlock) { - // Don't render: air, barriers, light blocks, etc. + if (caveCullingEnabled + // assume this data point is underground if it has no sky-light + && skyLight == LodUtil.MIN_MC_LIGHT + // cave culling shouldn't happen when at the top of the world + && columnOffset != 0 + // cave culling can't happen when at the bottom of the world + && columnOffset != fullColumnData.size()) + { + // we need to get the next sky/block lights because + // the air block here will always have a light of 0/0 due to only the top of the LOD's light being saved. + long nextFullData = fullColumnData.getLong(i+1); + int nextSkyLight = FullDataPointUtil.getSkyLight(nextFullData); + + if (nextSkyLight == LodUtil.MIN_MC_LIGHT + && ColorUtil.getAlpha(lastColor) == 255) + { + // replace the previous block with new bottom + long columnData = renderColumnData.get(columnOffset - 1); + columnData = RenderDataPointUtil.setYMin(columnData, bottomY); + renderColumnData.set(columnOffset - 1, columnData); + } + + continue; + } + + + if (ignoreBlock) + { + // this is a merged block and a cave block, so it should never be rendered + continue; + } + } + else if (ignoreBlock) + { + // this is an ignored block, but shouldn't be merged like a cave block continue; } - // solid block check - if (avoidSolidBlocks && !block.isSolid() && !block.isLiquid() && block.getOpacity() != LodUtil.BLOCK_FULLY_OPAQUE) + //===================// + // solid block check // + //===================// + + if (ignoreNonCollidingBlocks && !block.isSolid() && !block.isLiquid() && block.getOpacity() != LodUtil.BLOCK_FULLY_OPAQUE) { if (colorBelowWithAvoidedBlocks) { int tempColor = level.computeBaseColor(new DhBlockPos(blockX, bottomY + level.getMinY(), blockZ), biome, block); - if (ColorUtil.getAlpha(tempColor) == 0) + // don't transfer the color when alpha is 0 + if (ColorUtil.getAlpha(tempColor) != 0) { - //make sure to not transfer the color when alpha is 0 - continue; + // don't transfer alpha if for some reason grass is semi transparent + colorToApplyToNextBlock = ColorUtil.setAlpha(tempColor,255); + + skylightToApplyToNextBlock = skyLight; + blocklightToApplyToNextBlock = blockLight; } - //mare sure to not trnasfer alpha if for some reason grass is semi transparent - colorToApplyToNextBlock = ColorUtil.setAlpha(tempColor,255); - skylightToApplyToNextBlock = skyLight; - blocklightToApplyToNextBlock = blockLight; } // don't add this block @@ -261,10 +312,10 @@ public class FullDataToRenderDataTransformer blockLight = blocklightToApplyToNextBlock; } - //check if they share a top-bottom face and if they have same collor + //check if they share a top-bottom face and if they have same color if (color == lastColor && bottomY + blockHeight == lastBottom && columnOffset > 0) { - //replace the previus block with new bottom + //replace the previous block with new bottom long columnData = renderColumnData.get(columnOffset - 1); columnData = RenderDataPointUtil.setYMin(columnData, bottomY); renderColumnData.set(columnOffset - 1, columnData); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java index 139949cc4..427310ece 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java @@ -82,6 +82,17 @@ public interface IWrapperFactory extends IDhApiWrapperFactory, IBindable * Generally this contains blocks like: air, barriers, light blocks, etc. */ HashSet getRendererIgnoredBlocks(ILevelWrapper levelWrapper); + /** + * Returns the set of {@link IBlockStateWrapper}'s that shouldn't be rendered in caves.
+ * Generally this contains blocks like: air, rails, glow lichen, etc. + */ + HashSet getRendererIgnoredCaveBlocks(ILevelWrapper levelWrapper); + + /** clears the cached values */ + void resetRendererIgnoredCaveBlocks(); + /** clears the cached values */ + void resetRendererIgnoredBlocksSet(); + /** * Specifically designed to be used with the API. diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 9ea4fe0c4..f003bd700 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -379,7 +379,14 @@ "How should block data be compressed when creating LOD data? \nThis setting will only affect new or updated LOD data, \nany data already generated when this setting is changed will be \nunaffected until it is modified or re-loaded. \n\nMost Accurate: Merge Same Blocks \nHighest Compression: Visually Equal", "distanthorizons.config.client.advanced.lodBuilding.showMigrationChatWarning": "Log Migration In Chat", - + "distanthorizons.config.client.advanced.lodBuilding.ignoredRenderBlockCsv": + "Ignored Block CSV", + "distanthorizons.config.client.advanced.lodBuilding.ignoredRenderBlockCsv.@tooltip": + "A comma separated list of block resource locations that won't be rendered by DH. \nNote: air is always included in this list.", + "distanthorizons.config.client.advanced.lodBuilding.ignoredRenderCaveBlockCsv": + "Ignored Cave Block CSV", + "distanthorizons.config.client.advanced.lodBuilding.ignoredRenderCaveBlockCsv.@tooltip": + "A comma separated list of block resource locations that shouldn't be rendered \nif they are in a 0 sky light underground area. \nNote: air is always included in this list.", "distanthorizons.config.client.advanced.multiplayer": "Multiplayer", From c9b650fb7fc9a2805736852e3423953fbcc87702 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 19:27:11 -0500 Subject: [PATCH 103/104] remove unused clientLevelWrapper.getGameDirectory() --- .../seibel/distanthorizons/core/world/DhClientWorld.java | 8 -------- .../minecraft/IMinecraftClientWrapper.java | 4 ---- 2 files changed, 12 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java index 50af77234..a008eed7a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhClientWorld.java @@ -19,26 +19,18 @@ package com.seibel.distanthorizons.core.world; -import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.level.DhClientLevel; -import com.seibel.distanthorizons.core.network.NetworkClient; -import com.seibel.distanthorizons.core.network.messages.*; -import com.seibel.distanthorizons.core.network.messages.PlayerUUIDMessage; -import com.seibel.distanthorizons.core.network.messages.RemotePlayerConfigMessage; -import com.seibel.distanthorizons.core.network.objects.RemotePlayer; import com.seibel.distanthorizons.core.util.ThreadUtil; import com.seibel.distanthorizons.core.util.objects.EventLoop; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; -import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import org.jetbrains.annotations.NotNull; import java.io.File; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java index d69f66905..0c946c2aa 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java @@ -85,10 +85,6 @@ public interface IMinecraftClientWrapper extends IBindable */ IClientLevelWrapper getWrappedClientLevel(); - /** Please move over to getInstallationDirectory() within the IMinecraftSharedWrapper */ - @Deprecated - File getGameDirectory(); - IProfilerWrapper getProfiler(); /** Returns all worlds available to the server */ From d38711ca4bee9ec8bb1f9a6067993a851a66f41f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 21 Jul 2024 20:05:36 -0500 Subject: [PATCH 104/104] Fix replay mod not showing LODs --- .../core/api/internal/ClientApi.java | 25 +++++++++++++++++-- .../distanthorizons/core/config/Config.java | 8 ++++++ .../structure/ClientOnlySaveStructure.java | 24 +++++++++++++----- .../minecraft/IMinecraftClientWrapper.java | 2 ++ .../assets/distanthorizons/lang/en_us.json | 2 ++ 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index b37910884..355396630 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -23,6 +23,7 @@ import com.seibel.distanthorizons.api.DhApi; import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; import com.seibel.distanthorizons.api.methods.events.abstractEvents.*; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure; import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.render.DhApiRenderProxy; @@ -53,6 +54,7 @@ import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; +import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.Queue; @@ -125,9 +127,28 @@ public class ClientApi public synchronized void onClientOnlyConnected() { // only continue if the client is connected to a different server - if (MC.clientConnectedToDedicatedServer()) + boolean connectedToServer = MC.clientConnectedToDedicatedServer(); + boolean connectedToReplay = MC.connectedToReplay(); + if (connectedToServer || connectedToReplay) { - LOGGER.info("Client on ClientOnly mode connecting."); + if (connectedToServer) + { + LOGGER.info("Client on ClientOnly mode connecting."); + } + else + { + LOGGER.info("Replay on ClientServer mode connecting."); + + if (Config.Client.Advanced.Logging.showReplayWarningOnStartup.get()) + { + MC.sendChatMessage("\u00A76" + "Distant Horizons: Replay detected." + "\u00A7r"); // gold color + MC.sendChatMessage("DH may behave strangely or have missing functionality."); + MC.sendChatMessage("In order to use pre-generated LODs, put your DH database(s) in:"); + MC.sendChatMessage("\u00A77"+".Minecraft" + File.separator + ClientOnlySaveStructure.SERVER_DATA_FOLDER_NAME + File.separator + ClientOnlySaveStructure.REPLAY_SERVER_FOLDER_NAME + File.separator + "DIMENSION_NAME"+"\u00A7r"); // light gray color + MC.sendChatMessage("This can be disabled in DH's config under Advanced -> Logging."); + MC.sendChatMessage(""); + } + } // firing after clientLevelLoadEvent // TODO if level has prepped to load it should fire level load event diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 56a3cde8e..a2c786984 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -616,6 +616,7 @@ public class Config @Deprecated public static ConfigEntry caveCullingHeight = new ConfigEntry.Builder() .setMinDefaultMax(-4096, 40, 4096) + .setAppearance(EConfigEntryAppearance.ONLY_IN_API) .comment("" + "At what Y value should cave culling start?") .build(); @@ -1209,6 +1210,13 @@ public class Config + "memory allocated to run DH well.") .build(); + public static ConfigEntry showReplayWarningOnStartup = new ConfigEntry.Builder() + .set(true) + .comment("" + + "If enabled, a chat message will be displayed when a replay is started \n" + + "giving some basic information about how DH will function.") + .build(); + } public static class Debugging diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/structure/ClientOnlySaveStructure.java b/core/src/main/java/com/seibel/distanthorizons/core/file/structure/ClientOnlySaveStructure.java index dc8cad673..17a2c4d90 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/structure/ClientOnlySaveStructure.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/structure/ClientOnlySaveStructure.java @@ -41,13 +41,17 @@ import java.util.*; */ public class ClientOnlySaveStructure extends AbstractSaveStructure { - final File folder; - private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); - private static final IMinecraftSharedWrapper MC_SHARED = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class); + public static final String SERVER_DATA_FOLDER_NAME = "Distant_Horizons_server_data"; + public static final String REPLAY_SERVER_FOLDER_NAME = "REPLAY"; public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\/:*?\"<>|]"; - SubDimensionLevelMatcher subDimMatcher = null; - final HashMap levelWrapperToFileMap = new HashMap<>(); + private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); + private static final IMinecraftSharedWrapper MC_SHARED = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class); + + + private SubDimensionLevelMatcher subDimMatcher = null; + private final File folder; + private final HashMap levelWrapperToFileMap = new HashMap<>(); @@ -237,7 +241,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure private static String getSaveStructureFolderPath() { String path = MC_SHARED.getInstallationDirectory().getPath() + File.separatorChar - + "Distant_Horizons_server_data" + File.separatorChar + + SERVER_DATA_FOLDER_NAME + File.separatorChar + getServerFolderName(); return path; } @@ -245,6 +249,14 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure /** Generated from the server the client is currently connected to. */ private static String getServerFolderName() { + // if connected to a replay we won't have any server info + // use the dedicated replay server folder + if (MC_CLIENT.connectedToReplay()) + { + return REPLAY_SERVER_FOLDER_NAME; + } + + // parse the current server's IP ParsedIp parsedIp = new ParsedIp(MC_CLIENT.getCurrentServerIp()); String serverIpCleaned = parsedIp.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, ""); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java index 0c946c2aa..1a57a7221 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/minecraft/IMinecraftClientWrapper.java @@ -62,6 +62,8 @@ public interface IMinecraftClientWrapper extends IBindable boolean hasSinglePlayerServer(); boolean clientConnectedToDedicatedServer(); + /** for use with the Replay mod */ + boolean connectedToReplay(); String getCurrentServerName(); String getCurrentServerIp(); diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index f003bd700..8918f8820 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -558,6 +558,8 @@ "Network Events", "distanthorizons.config.client.advanced.logging.showLowMemoryWarningOnStartup": "Show Low Memory Warning", + "distanthorizons.config.client.advanced.logging.showReplayWarningOnStartup": + "Show Replay Warning",