Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32bff85526 | ||
|
|
02fc95f239 | ||
|
|
07fd6d78a0 |
No files matched your search
@@ -638,6 +638,9 @@ public class GLStateManager {
|
||||
RENDER_BACKEND.bindVertexArray(defaultVAO);
|
||||
boundVAO = defaultVAO;
|
||||
VAOManager.init(defaultVAO);
|
||||
if (defaultVAO != 0) {
|
||||
RENDER_BACKEND.provokingVertex(GL32.GL_LAST_VERTEX_CONVENTION);
|
||||
}
|
||||
if (initCallback != null) {
|
||||
initCallback.run();
|
||||
}
|
||||
@@ -2237,6 +2240,10 @@ public class GLStateManager {
|
||||
FeedbackManager.processDrawElements(mode, indices);
|
||||
return;
|
||||
}
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(indices.remaining(), GL11.GL_UNSIGNED_BYTE, indices);
|
||||
return;
|
||||
}
|
||||
preDraw(mode);
|
||||
RENDER_BACKEND.drawElements(mode, indices);
|
||||
}
|
||||
@@ -2350,10 +2357,29 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glDrawElementsInstanced(int mode, int count, int type, long indices, int primcount) {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTrianglesInstanced(count, type, indices, primcount);
|
||||
return;
|
||||
}
|
||||
preDraw(mode);
|
||||
RENDER_BACKEND.drawElementsInstanced(mode, count, type, indices, primcount);
|
||||
}
|
||||
|
||||
public static void glDrawArraysInstanced(int mode, int first, int count, int primcount) {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadsAsTrianglesInstanced(first, count, primcount);
|
||||
} else if (mode == GL11.GL_QUAD_STRIP) {
|
||||
preDraw();
|
||||
RENDER_BACKEND.drawArraysInstanced(GL11.GL_TRIANGLE_STRIP, first, count & ~1, primcount);
|
||||
} else if (mode == GL11.GL_POLYGON) {
|
||||
preDraw();
|
||||
RENDER_BACKEND.drawArraysInstanced(GL11.GL_TRIANGLE_FAN, first, count, primcount);
|
||||
} else {
|
||||
preDraw(mode);
|
||||
RENDER_BACKEND.drawArraysInstanced(mode, first, count, primcount);
|
||||
}
|
||||
}
|
||||
|
||||
private static void prepareClientArrays() {
|
||||
if (VAOManager.hasAnyClientSideEnabledAttrib()) {
|
||||
VAOManager.uploadClientArraysToVBO();
|
||||
|
||||
@@ -83,6 +83,14 @@ public final class QuadConverter {
|
||||
* @param vertexCount number of vertices (must be multiple of 4)
|
||||
*/
|
||||
public static void drawQuadsAsTriangles(int first, int vertexCount) {
|
||||
drawSharedQuadEbo(first, vertexCount, 1, false);
|
||||
}
|
||||
|
||||
public static void drawQuadsAsTrianglesInstanced(int first, int vertexCount, int primcount) {
|
||||
drawSharedQuadEbo(first, vertexCount, primcount, true);
|
||||
}
|
||||
|
||||
private static void drawSharedQuadEbo(int first, int vertexCount, int primcount, boolean instanced) {
|
||||
GLStateManager.preDraw();
|
||||
assert first % 4 == 0 : "QuadConverter: first (" + first + ") must be a multiple of 4";
|
||||
assert vertexCount % 4 == 0 : "QuadConverter: vertexCount (" + vertexCount + ") must be a multiple of 4";
|
||||
@@ -92,7 +100,11 @@ public final class QuadConverter {
|
||||
RENDER_BACKEND.bindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, eboId);
|
||||
// Index offset: first vertex / 4 quads * 6 indices * 4 bytes per int
|
||||
final long indexOffset = (long) (first / 4) * 6 * 4;
|
||||
RENDER_BACKEND.drawElements(GL11.GL_TRIANGLES, quadCount * 6, INDEX_TYPE, indexOffset);
|
||||
if (instanced) {
|
||||
RENDER_BACKEND.drawElementsInstanced(GL11.GL_TRIANGLES, quadCount * 6, INDEX_TYPE, indexOffset, primcount);
|
||||
} else {
|
||||
RENDER_BACKEND.drawElements(GL11.GL_TRIANGLES, quadCount * 6, INDEX_TYPE, indexOffset);
|
||||
}
|
||||
RENDER_BACKEND.bindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, prevEbo);
|
||||
}
|
||||
|
||||
@@ -107,6 +119,10 @@ public final class QuadConverter {
|
||||
* @param bytesPerIndex bytes per index element
|
||||
*/
|
||||
private static void uploadAndDraw(ByteBuffer dst, int triIndexCount, int indexType, int bytesPerIndex) {
|
||||
uploadAndDraw(dst, triIndexCount, indexType, bytesPerIndex, 1, false);
|
||||
}
|
||||
|
||||
private static void uploadAndDraw(ByteBuffer dst, int triIndexCount, int indexType, int bytesPerIndex, int primcount, boolean instanced) {
|
||||
GLStateManager.preDraw();
|
||||
final int needed = triIndexCount * bytesPerIndex;
|
||||
final int prevEbo = GLStateManager.getBoundEBO();
|
||||
@@ -126,7 +142,11 @@ public final class QuadConverter {
|
||||
}
|
||||
RENDER_BACKEND.bufferSubData(GL15.GL_ELEMENT_ARRAY_BUFFER, 0, dst);
|
||||
|
||||
RENDER_BACKEND.drawElements(GL11.GL_TRIANGLES, triIndexCount, indexType, 0L);
|
||||
if (instanced) {
|
||||
RENDER_BACKEND.drawElementsInstanced(GL11.GL_TRIANGLES, triIndexCount, indexType, 0L, primcount);
|
||||
} else {
|
||||
RENDER_BACKEND.drawElements(GL11.GL_TRIANGLES, triIndexCount, indexType, 0L);
|
||||
}
|
||||
|
||||
RENDER_BACKEND.bindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, prevEbo);
|
||||
memFree(dst);
|
||||
@@ -141,6 +161,14 @@ public final class QuadConverter {
|
||||
* @param offset byte offset into the currently bound EBO
|
||||
*/
|
||||
public static void drawQuadElementsAsTriangles(int indexCount, int type, long offset) {
|
||||
drawQuadElementsFromEbo(indexCount, type, offset, 1, false);
|
||||
}
|
||||
|
||||
public static void drawQuadElementsAsTrianglesInstanced(int indexCount, int type, long offset, int primcount) {
|
||||
drawQuadElementsFromEbo(indexCount, type, offset, primcount, true);
|
||||
}
|
||||
|
||||
private static void drawQuadElementsFromEbo(int indexCount, int type, long offset, int primcount, boolean instanced) {
|
||||
if (indexCount == 0) return;
|
||||
assert indexCount % 4 == 0 : "QuadConverter: indexCount must be multiple of 4";
|
||||
final int quadCount = indexCount / 4;
|
||||
@@ -155,7 +183,7 @@ public final class QuadConverter {
|
||||
triangulateQuads(memAddress0(src), type, memAddress0(dst), GL11.GL_UNSIGNED_INT, quadCount);
|
||||
|
||||
memFree(src);
|
||||
uploadAndDraw(dst, triIndexCount, GL11.GL_UNSIGNED_INT, 4);
|
||||
uploadAndDraw(dst, triIndexCount, GL11.GL_UNSIGNED_INT, 4, primcount, instanced);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -310,6 +310,16 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL31.glDrawElementsInstanced(mode, count, type, indices, primcount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawArraysInstanced(int mode, int first, int count, int primcount) {
|
||||
GL31.glDrawArraysInstanced(mode, first, count, primcount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provokingVertex(int provokeMode) {
|
||||
GL32.glProvokingVertex(provokeMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void multiDrawElementsIndirect(int mode, int type, long indirect, int drawcount, int stride) {
|
||||
org.lwjgl.opengl.GL43.glMultiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
|
||||
|
||||
@@ -87,6 +87,8 @@ public abstract class RenderBackend {
|
||||
public abstract void multiDrawElementsIndirect(int mode, int type, long indirect, int drawcount, int stride);
|
||||
public abstract void copyBufferSubData(int readTarget, int writeTarget, long readOffset, long writeOffset, long size);
|
||||
public abstract void drawElementsInstanced(int mode, int count, int type, long indices, int primcount);
|
||||
public abstract void drawArraysInstanced(int mode, int first, int count, int primcount);
|
||||
public void provokingVertex(int provokeMode) {}
|
||||
public abstract void drawElementsBaseVertex(int mode, int count, int type, long indices, int baseVertex);
|
||||
public abstract void multiDrawElementsBaseVertex(int mode, long pCount, int type, long pIndices, int drawcount, long pBaseVertex);
|
||||
public abstract void drawBuffer(int mode);
|
||||
|
||||
@@ -46,6 +46,8 @@ public class GLSMRedirector {
|
||||
private static final String ARBMultiTexture = "org/lwjgl/opengl/ARBMultitexture";
|
||||
private static final String ARBShaderObjects = "org/lwjgl/opengl/ARBShaderObjects";
|
||||
private static final String ARBInstancedArrays = "org/lwjgl/opengl/ARBInstancedArrays";
|
||||
private static final String ARBDrawInstanced = "org/lwjgl/opengl/ARBDrawInstanced";
|
||||
private static final String EXTDrawInstanced = "org/lwjgl/opengl/EXTDrawInstanced";
|
||||
|
||||
// Redirect VAO related calls from NHLib
|
||||
private static final String UniversalVAO = "com/gtnewhorizon/gtnhlib/client/opengl/UniversalVAO";
|
||||
@@ -356,7 +358,8 @@ public class GLSMRedirector {
|
||||
.add("glGetFramebufferAttachmentParameteri")
|
||||
.add("glBlitFramebuffer");
|
||||
final var gl31 = RedirectMap.newMap()
|
||||
.add("glDrawElementsInstanced");
|
||||
.add("glDrawElementsInstanced")
|
||||
.add("glDrawArraysInstanced");
|
||||
final var gl32 = RedirectMap.newMap()
|
||||
.add("glFramebufferTexture");
|
||||
final var gl33 = RedirectMap.newMap()
|
||||
@@ -459,6 +462,14 @@ public class GLSMRedirector {
|
||||
methodRedirects.put(ARBInstancedArrays, RedirectMap.newMap()
|
||||
.add("glVertexAttribDivisorARB")
|
||||
);
|
||||
methodRedirects.put(ARBDrawInstanced, RedirectMap.newMap()
|
||||
.add("glDrawArraysInstancedARB", "glDrawArraysInstanced")
|
||||
.add("glDrawElementsInstancedARB", "glDrawElementsInstanced")
|
||||
);
|
||||
methodRedirects.put(EXTDrawInstanced, RedirectMap.newMap()
|
||||
.add("glDrawArraysInstancedEXT", "glDrawArraysInstanced")
|
||||
.add("glDrawElementsInstancedEXT", "glDrawElementsInstanced")
|
||||
);
|
||||
|
||||
// APPLE
|
||||
methodRedirects.put(APPLEVertexArrayObject, RedirectMap.newMap()
|
||||
|
||||
@@ -21,7 +21,7 @@ class CompatUniformManagerTest {
|
||||
void cleanup() {
|
||||
if (program != 0) {
|
||||
GL20.glUseProgram(0);
|
||||
GL20.glDeleteProgram(program);
|
||||
GLStateManager.glDeleteProgram(program);
|
||||
program = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLDebug;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
@ExtendWith(GLSMCoreExtension.class)
|
||||
class InstancedQuadDrawGLTest {
|
||||
|
||||
private static final String VS = "#version 330 core\nlayout(location=0) in vec2 aPos;\nvoid main(){ gl_Position = vec4(aPos, 0.0, 1.0); }\n";
|
||||
private static final String FS = "#version 330 core\nout vec4 o;\nvoid main(){ o = vec4(1.0); }\n";
|
||||
|
||||
private int program;
|
||||
private int vbo;
|
||||
private int ebo;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
program = buildProgram();
|
||||
GLStateManager.glUseProgram(program);
|
||||
|
||||
final FloatBuffer verts = BufferUtils.createFloatBuffer(8);
|
||||
verts.put(new float[] {0, 0, 1, 0, 1, 1, 0, 1}).flip();
|
||||
vbo = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glBufferData(GL15.GL_ARRAY_BUFFER, verts, GL15.GL_STATIC_DRAW);
|
||||
GLStateManager.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0L);
|
||||
GLStateManager.glEnableVertexAttribArray(0);
|
||||
|
||||
final IntBuffer idx = BufferUtils.createIntBuffer(4);
|
||||
idx.put(new int[] {0, 1, 2, 3}).flip();
|
||||
ebo = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
GLStateManager.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, idx, GL15.GL_STATIC_DRAW);
|
||||
|
||||
drainErrors();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
GLStateManager.glUseProgram(0);
|
||||
if (program != 0) GL20.glDeleteProgram(program);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
if (vbo != 0) GLStateManager.glDeleteBuffers(vbo);
|
||||
if (ebo != 0) GLStateManager.glDeleteBuffers(ebo);
|
||||
drainErrors();
|
||||
}
|
||||
|
||||
@Test
|
||||
void drawArraysInstanced_quads_noInvalidEnum() {
|
||||
GLStateManager.glDrawArraysInstanced(GL11.GL_QUADS, 0, 4, 3);
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "GL_QUADS instanced array draw must be emulated, not rejected");
|
||||
}
|
||||
|
||||
@Test
|
||||
void drawArraysInstanced_triangles_fastPathClean() {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glDrawArraysInstanced(GL11.GL_TRIANGLES, 0, 3, 3);
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "non-quad instanced array draw passes through cleanly");
|
||||
}
|
||||
|
||||
@Test
|
||||
void drawElementsInstanced_quads_noInvalidEnum() {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
GLStateManager.glDrawElementsInstanced(GL11.GL_QUADS, 4, GL11.GL_UNSIGNED_INT, 0L, 3);
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "GL_QUADS instanced element draw must be emulated, not rejected");
|
||||
}
|
||||
|
||||
private static int buildProgram() {
|
||||
final int vs = compile(GL20.GL_VERTEX_SHADER, VS);
|
||||
final int fs = compile(GL20.GL_FRAGMENT_SHADER, FS);
|
||||
final int p = GL20.glCreateProgram();
|
||||
GL20.glAttachShader(p, vs);
|
||||
GL20.glAttachShader(p, fs);
|
||||
GL20.glLinkProgram(p);
|
||||
assertNotEquals(0, GL20.glGetProgrami(p, GL20.GL_LINK_STATUS), "test shader must link: " + GL20.glGetProgramInfoLog(p, 1024));
|
||||
GL20.glDeleteShader(vs);
|
||||
GL20.glDeleteShader(fs);
|
||||
return p;
|
||||
}
|
||||
|
||||
private static int compile(int type, String src) {
|
||||
final int s = GL20.glCreateShader(type);
|
||||
GL20.glShaderSource(s, src);
|
||||
GL20.glCompileShader(s);
|
||||
assertNotEquals(0, GL20.glGetShaderi(s, GL20.GL_COMPILE_STATUS), "test shader must compile: " + GL20.glGetShaderInfoLog(s, 1024));
|
||||
return s;
|
||||
}
|
||||
|
||||
private static void drainErrors() {
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) { /* clear */ }
|
||||
}
|
||||
}
|
||||
@@ -348,6 +348,16 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
GL31C.glDrawElementsInstanced(mode, count, type, indices, primcount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawArraysInstanced(int mode, int first, int count, int primcount) {
|
||||
GL31C.glDrawArraysInstanced(mode, first, count, primcount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void provokingVertex(int provokeMode) {
|
||||
GL32C.glProvokingVertex(provokeMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void multiDrawElementsIndirect(int mode, int type, long indirect, int drawcount, int stride) {
|
||||
GL43C.glMultiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
|
||||
|
||||
@@ -269,6 +269,13 @@ public class AngelicaConfig {
|
||||
@Config.DefaultStringList({"jewelrycraft2:blockCrystal"})
|
||||
public static String[] alwaysTranslucentSprites;
|
||||
|
||||
@Config.Comment({"TileEntity classnames whose render bounds change at runtime (e.g. OpenBlocks Guide).",
|
||||
"These are always rendered and frustum-tested against their live bounds instead of the cached."})
|
||||
@Config.DefaultStringList({"openblocks.common.tileentity.TileEntityGuide",
|
||||
"openblocks.common.tileentity.TileEntityBuilderGuide"})
|
||||
@Config.RequiresMcRestart
|
||||
public static String[] dynamicBoundsTileEntities;
|
||||
|
||||
@Config.Comment("Register HardcodedCustomUniforms in Iris Shaders. May help with compatibility in certain shader packs")
|
||||
@Config.DefaultBoolean(false)
|
||||
public static boolean enableHardcodedCustomUniforms;
|
||||
@@ -350,4 +357,8 @@ public class AngelicaConfig {
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean disableErrorChecks;
|
||||
|
||||
@Config.Comment("Fixes various issues with entity overlays, such as z-fighting, damage animations and eyes.")
|
||||
@Config.DefaultBoolean(true)
|
||||
@Config.RequiresMcRestart
|
||||
public static boolean entityOverlayFixes;
|
||||
}
|
||||
@@ -47,9 +47,7 @@ public enum Mixins implements IMixins {
|
||||
, "angelica.bugfixes.MixinRenderGlobal_DestroyBlock"
|
||||
, "angelica.bugfixes.MixinRenderMooshroom_MushroomTint"
|
||||
, "angelica.bugfixes.MixinRendererLivingEntity_DeferredEntityOverlay"
|
||||
, "angelica.bugfixes.MixinRendererLivingEntity_OverlayTint"
|
||||
, "angelica.bugfixes.MixinRenderWither_ArmorCentering"
|
||||
, "angelica.bugfixes.MixinRendererLivingEntity_EyeDepth"
|
||||
, "angelica.debug.MixinMinecraft_FPSCap"
|
||||
, "angelica.ffp.MixinTessellator_CoreProfile"
|
||||
, "angelica.glsm.MixinSplashProgressCaching"
|
||||
@@ -60,6 +58,16 @@ public enum Mixins implements IMixins {
|
||||
)
|
||||
),
|
||||
|
||||
ANGELICA_ENTITY_OVERLAYS(new MixinBuilder()
|
||||
.setPhase(Phase.EARLY)
|
||||
.setApplyIf(() -> AngelicaConfig.entityOverlayFixes)
|
||||
.addExcludedMod(TargetedMod.CUSTOM_PLAYER_MODELS)
|
||||
.addClientMixins(
|
||||
"angelica.bugfixes.MixinRendererLivingEntity_EyeDepth"
|
||||
, "angelica.bugfixes.MixinRendererLivingEntity_OverlayTint"
|
||||
)
|
||||
),
|
||||
|
||||
ANGELICA_VBO_CLOUDS(
|
||||
new MixinBuilder()
|
||||
.setApplyIf(() -> AngelicaConfig.enableVBOClouds)
|
||||
|
||||
@@ -28,6 +28,7 @@ public enum TargetedMod implements ITargetMod {
|
||||
TINKERS_CONSTRUCT(null, "TConstruct"),
|
||||
TWILIGHT_FOREST(null, "TwilightForest"),
|
||||
BIOMES_O_PLENTY(null, "BiomesOPlenty"),
|
||||
CUSTOM_PLAYER_MODELS("com.tom.cpmcore.CPMLoadingPlugin", "customplayermodels"),
|
||||
WITCHERY(null, "witchery");
|
||||
|
||||
private final TargetModBuilder builder;
|
||||
|
||||
@@ -5,5 +5,5 @@ import net.minecraft.util.AxisAlignedBB;
|
||||
public interface ITileEntityBoundingBoxCache {
|
||||
AxisAlignedBB angelica$getCachedRenderBoundingBox();
|
||||
|
||||
boolean angelica$isInfiniteExtent();
|
||||
byte angelica$boundsClass();
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.gtnewhorizons.angelica.common.BlockError;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.compat.bettercrashes.BetterCrashesCompat;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.rendering.TileEntityRenderBoundsRegistry;
|
||||
import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import com.gtnewhorizons.angelica.config.ConfigMigrator;
|
||||
import com.gtnewhorizons.angelica.debug.F3Direction;
|
||||
@@ -102,6 +103,7 @@ public final class ClientProxy extends CommonProxy {
|
||||
@Override
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
ModStatus.preInit();
|
||||
for (String name : AngelicaConfig.dynamicBoundsTileEntities) TileEntityRenderBoundsRegistry.registerDynamicClass(name);
|
||||
super.preInit(event);
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
@@ -4,48 +4,60 @@ import it.unimi.dsi.fastutil.objects.Reference2ByteOpenHashMap;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Registry for tracking which TileEntity classes always return INFINITE_EXTENT_AABB.
|
||||
* Registry for tracking which TileEntity classes always return INFINITE_EXTENT_AABB or are known to change at runtime
|
||||
*/
|
||||
public final class TileEntityRenderBoundsRegistry {
|
||||
private static final byte UNKNOWN = 0;
|
||||
private static final byte FINITE = 1;
|
||||
private static final byte INFINITE = 2;
|
||||
public static final byte STATIC = 1;
|
||||
public static final byte INFINITE = 2;
|
||||
public static final byte DYNAMIC = 3;
|
||||
|
||||
private static final Reference2ByteOpenHashMap<Class<? extends TileEntity>> classRegistry = new Reference2ByteOpenHashMap<>();
|
||||
|
||||
private static final Set<String> dynamicClassNames = ConcurrentHashMap.newKeySet();
|
||||
|
||||
static {
|
||||
classRegistry.defaultReturnValue(UNKNOWN);
|
||||
}
|
||||
|
||||
private TileEntityRenderBoundsRegistry() {}
|
||||
|
||||
public static void registerDynamicClass(String className) {
|
||||
if (className != null && !className.isEmpty()) dynamicClassNames.add(className);
|
||||
}
|
||||
|
||||
public static boolean isInfiniteExtentsBox(AxisAlignedBB box) {
|
||||
return box == null || Double.isInfinite(box.minX) || Double.isInfinite(box.minY) || Double.isInfinite(box.minZ) || Double.isInfinite(box.maxX) || Double.isInfinite(box.maxY) || Double.isInfinite(box.maxZ);
|
||||
}
|
||||
|
||||
public static boolean isAlwaysInfiniteExtent(TileEntity te) {
|
||||
public static byte classify(TileEntity te) {
|
||||
final Class<? extends TileEntity> clazz = te.getClass();
|
||||
synchronized (classRegistry) {
|
||||
final byte result = classRegistry.getByte(clazz);
|
||||
if (result != UNKNOWN) return result == INFINITE;
|
||||
final byte cached = classRegistry.getByte(clazz);
|
||||
if (cached != UNKNOWN) return cached;
|
||||
}
|
||||
return probeAndCache(te, clazz);
|
||||
}
|
||||
|
||||
private static boolean probeAndCache(TileEntity te, Class<? extends TileEntity> clazz) {
|
||||
boolean isInfinite;
|
||||
try {
|
||||
final AxisAlignedBB aabb = te.getRenderBoundingBox();
|
||||
isInfinite = isInfiniteExtentsBox(aabb);
|
||||
} catch (Throwable t) {
|
||||
isInfinite = true;
|
||||
final byte result;
|
||||
if (dynamicClassNames.contains(clazz.getName())) {
|
||||
result = DYNAMIC;
|
||||
} else {
|
||||
boolean isInfinite;
|
||||
try {
|
||||
isInfinite = isInfiniteExtentsBox(te.getRenderBoundingBox());
|
||||
} catch (Throwable t) {
|
||||
isInfinite = true;
|
||||
}
|
||||
result = isInfinite ? INFINITE : STATIC;
|
||||
}
|
||||
|
||||
synchronized (classRegistry) {
|
||||
classRegistry.put(clazz, isInfinite ? INFINITE : FINITE);
|
||||
classRegistry.put(clazz, result);
|
||||
}
|
||||
return isInfinite;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
|
||||
@@ -151,7 +151,8 @@ public abstract class AngelicaChunkBuilderMeshingTask extends ChunkBuilderTask<C
|
||||
final TileEntity tileEntity = region.getTileEntity(x, y, z);
|
||||
if (tileEntity != null && TileEntityRendererDispatcher.instance.hasSpecialRenderer(tileEntity)) {
|
||||
final boolean isGlobal;
|
||||
if (TileEntityRenderBoundsRegistry.isAlwaysInfiniteExtent(tileEntity)) {
|
||||
final byte boundsClass = TileEntityRenderBoundsRegistry.classify(tileEntity);
|
||||
if (boundsClass == TileEntityRenderBoundsRegistry.INFINITE || boundsClass == TileEntityRenderBoundsRegistry.DYNAMIC) {
|
||||
isGlobal = true;
|
||||
} else {
|
||||
AxisAlignedBB aabb;
|
||||
|
||||
@@ -346,8 +346,9 @@ public class CeleritasWorldRenderer extends SimpleWorldRenderer<WorldClient, Ang
|
||||
|
||||
final ITileEntityBoundingBoxCache teCache = (ITileEntityBoundingBoxCache) tileEntity;
|
||||
|
||||
if (!teCache.angelica$isInfiniteExtent()) {
|
||||
final AxisAlignedBB aabb = teCache.angelica$getCachedRenderBoundingBox();
|
||||
final byte boundsClass = teCache.angelica$boundsClass();
|
||||
if (boundsClass != TileEntityRenderBoundsRegistry.INFINITE) {
|
||||
final AxisAlignedBB aabb = boundsClass == TileEntityRenderBoundsRegistry.DYNAMIC ? tileEntity.getRenderBoundingBox() : teCache.angelica$getCachedRenderBoundingBox();
|
||||
if (aabb != null && !this.currentViewport.isBoxVisible(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 595 B After Width: | Height: | Size: 548 B |
|
Before Width: | Height: | Size: 554 B |
|
Before Width: | Height: | Size: 551 B |
|
Before Width: | Height: | Size: 597 B |
|
Before Width: | Height: | Size: 586 B |
|
Before Width: | Height: | Size: 561 B |
|
Before Width: | Height: | Size: 595 B |
|
Before Width: | Height: | Size: 591 B |
|
Before Width: | Height: | Size: 594 B |
|
Before Width: | Height: | Size: 577 B |
|
Before Width: | Height: | Size: 591 B |
|
Before Width: | Height: | Size: 587 B After Width: | Height: | Size: 595 B |
|
Before Width: | Height: | Size: 554 B |
|
Before Width: | Height: | Size: 553 B |
|
Before Width: | Height: | Size: 551 B |
|
Before Width: | Height: | Size: 549 B |
|
Before Width: | Height: | Size: 595 B |
|
Before Width: | Height: | Size: 579 B |
|
Before Width: | Height: | Size: 548 B |
|
Before Width: | Height: | Size: 590 B |
|
Before Width: | Height: | Size: 580 B |
|
Before Width: | Height: | Size: 564 B |
|
Before Width: | Height: | Size: 596 B After Width: | Height: | Size: 587 B |
|
Before Width: | Height: | Size: 580 B |
|
Before Width: | Height: | Size: 562 B |
|
Before Width: | Height: | Size: 550 B |
|
Before Width: | Height: | Size: 548 B |
|
Before Width: | Height: | Size: 550 B |
|
Before Width: | Height: | Size: 552 B |
|
Before Width: | Height: | Size: 598 B |
|
Before Width: | Height: | Size: 590 B |
|
Before Width: | Height: | Size: 574 B |
|
Before Width: | Height: | Size: 592 B |
|
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 553 B |
|
Before Width: | Height: | Size: 574 B |
|
Before Width: | Height: | Size: 590 B |
|
Before Width: | Height: | Size: 577 B |
|
Before Width: | Height: | Size: 591 B |
|
Before Width: | Height: | Size: 551 B |
|
Before Width: | Height: | Size: 548 B |
|
Before Width: | Height: | Size: 553 B |
|
Before Width: | Height: | Size: 593 B |
|
Before Width: | Height: | Size: 582 B |
|
Before Width: | Height: | Size: 564 B |
|
Before Width: | Height: | Size: 551 B |
|
Before Width: | Height: | Size: 552 B |
@@ -1,6 +1,6 @@
|
||||
matchBlocks=minecraft:glass minecraft:glass_pane
|
||||
matchBlocks=glass
|
||||
metadata=0
|
||||
method=ctm
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-46
|
||||
connect=block
|
||||
tiles=0-4
|
||||
connect=block
|
||||
@@ -0,0 +1,6 @@
|
||||
matchBlocks=glass_pane
|
||||
metadata=0
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=sides
|
||||
|
After Width: | Height: | Size: 203 B |
|
After Width: | Height: | Size: 231 B |
|
After Width: | Height: | Size: 255 B |
|
After Width: | Height: | Size: 252 B |
|
After Width: | Height: | Size: 254 B |
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass
|
||||
metadata=15
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=block
|
||||
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass_pane
|
||||
metadata=15
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=sides
|
||||
|
After Width: | Height: | Size: 206 B |
|
After Width: | Height: | Size: 235 B |
|
After Width: | Height: | Size: 259 B |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 249 B |
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass
|
||||
metadata=11
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=block
|
||||
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass_pane
|
||||
metadata=11
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=sides
|
||||
|
After Width: | Height: | Size: 205 B |
|
After Width: | Height: | Size: 234 B |
|
After Width: | Height: | Size: 259 B |
|
After Width: | Height: | Size: 260 B |
|
After Width: | Height: | Size: 258 B |
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass
|
||||
metadata=12
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=block
|
||||
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass_pane
|
||||
metadata=12
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=sides
|
||||
|
After Width: | Height: | Size: 205 B |
|
After Width: | Height: | Size: 236 B |
|
After Width: | Height: | Size: 259 B |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 249 B |
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass
|
||||
metadata=9
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=block
|
||||
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass_pane
|
||||
metadata=9
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=sides
|
||||
|
After Width: | Height: | Size: 203 B |
|
After Width: | Height: | Size: 232 B |
|
After Width: | Height: | Size: 256 B |
|
After Width: | Height: | Size: 258 B |
|
After Width: | Height: | Size: 255 B |
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass
|
||||
metadata=7
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=block
|
||||
@@ -0,0 +1,6 @@
|
||||
matchBlocks=stained_glass_pane
|
||||
metadata=7
|
||||
method=compact
|
||||
faces=all
|
||||
tiles=0-4
|
||||
connect=sides
|
||||