From 5b704d1bc20c9e72f22e509389d370fdd4d6f2fc Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sun, 28 Jun 2026 16:33:58 -0700 Subject: [PATCH] Fix space elevator cable (#1896) --- .../angelica/glsm/GLStateManager.java | 55 +++++++++------- .../angelica/glsm/ffp/VAOManager.java | 16 +++++ .../angelica/glsm/GLSM_VAO_UnitTest.java | 62 +++++++++++++++++++ 3 files changed, 112 insertions(+), 21 deletions(-) diff --git a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java index fefb11996..4c132471e 100644 --- a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java +++ b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java @@ -2470,6 +2470,19 @@ public class GLStateManager { if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder); } + private static void ffpClientArrayPointer(int index, int size, int type, boolean normalized, int stride, long offset) { + if (VAOManager.isGenericPointerEnabled(index)) return; + VAOManager.setAttribute(index, size, type, normalized, stride, offset, boundVBO); + VAOManager.markConventional(index); + RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, offset); + } + + private static void ffpClientArrayPointer(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer) { + if (VAOManager.isGenericPointerEnabled(index)) return; + VAOManager.setAttribute(index, size, type, normalized, stride, pointer); + VAOManager.markConventional(index); + } + public static void glVertexPointer(int size, int stride, IntBuffer pointer) { glVertexPointer(size, GL11.GL_INT, stride, MemoryUtilities.memByteBuffer(pointer)); } @@ -2479,40 +2492,40 @@ public class GLStateManager { } public static void glVertexPointer(int size, int stride, FloatBuffer pointer) { - glVertexAttribPointer(Usage.POSITION.getAttributeLocation(), size, GL11.GL_FLOAT, false, stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(Usage.POSITION.getAttributeLocation(), size, GL11.GL_FLOAT, false, stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glVertexPointer(int size, int stride, DoubleBuffer pointer) { - glVertexAttribPointer(Usage.POSITION.getAttributeLocation(), size, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(Usage.POSITION.getAttributeLocation(), size, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glVertexPointer(int size, int type, int stride, ByteBuffer pointer) { - glVertexAttribPointer(Usage.POSITION.getAttributeLocation(), size, type, false, stride, pointer); + ffpClientArrayPointer(Usage.POSITION.getAttributeLocation(), size, type, false, stride, pointer); } public static void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset) { - glVertexAttribPointer(Usage.POSITION.getAttributeLocation(), size, type, false, stride, pointer_buffer_offset); + ffpClientArrayPointer(Usage.POSITION.getAttributeLocation(), size, type, false, stride, pointer_buffer_offset); } public static void glColorPointer(int size, int stride, FloatBuffer pointer) { - glVertexAttribPointer(Usage.COLOR.getAttributeLocation(), size, GL11.GL_FLOAT, Usage.COLOR.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(Usage.COLOR.getAttributeLocation(), size, GL11.GL_FLOAT, Usage.COLOR.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glColorPointer(int size, int stride, DoubleBuffer pointer) { - glVertexAttribPointer(Usage.COLOR.getAttributeLocation(), size, GL11.GL_DOUBLE, Usage.COLOR.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(Usage.COLOR.getAttributeLocation(), size, GL11.GL_DOUBLE, Usage.COLOR.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glColorPointer(int size, int type, int stride, ByteBuffer pointer) { - glVertexAttribPointer(Usage.COLOR.getAttributeLocation(), size, type, Usage.COLOR.isNormalized(), stride, pointer); + ffpClientArrayPointer(Usage.COLOR.getAttributeLocation(), size, type, Usage.COLOR.isNormalized(), stride, pointer); } public static void glColorPointer(int size, boolean unsigned, int stride, ByteBuffer pointer) { final int type = unsigned ? GL11.GL_UNSIGNED_BYTE : GL11.GL_BYTE; - glVertexAttribPointer(Usage.COLOR.getAttributeLocation(), size, type, Usage.COLOR.isNormalized(), stride, pointer); + ffpClientArrayPointer(Usage.COLOR.getAttributeLocation(), size, type, Usage.COLOR.isNormalized(), stride, pointer); } public static void glColorPointer(int size, int type, int stride, long pointer_buffer_offset) { - glVertexAttribPointer(Usage.COLOR.getAttributeLocation(), size, type, Usage.COLOR.isNormalized(), stride, pointer_buffer_offset); + ffpClientArrayPointer(Usage.COLOR.getAttributeLocation(), size, type, Usage.COLOR.isNormalized(), stride, pointer_buffer_offset); } public static void glNormalPointer(int stride, FloatBuffer pointer) { @@ -2532,33 +2545,33 @@ public class GLStateManager { } public static void glNormalPointer(int type, int stride, ByteBuffer pointer) { - glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, type, Usage.NORMAL.isNormalized(), stride, pointer); + ffpClientArrayPointer(Usage.NORMAL.getAttributeLocation(), 3, type, Usage.NORMAL.isNormalized(), stride, pointer); } public static void glNormalPointer(int type, int stride, FloatBuffer pointer) { - glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_FLOAT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_FLOAT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glNormalPointer(int type, int stride, ShortBuffer pointer) { - glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_SHORT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_SHORT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glNormalPointer(int type, int stride, IntBuffer pointer) { - glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_INT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_INT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glNormalPointer(int type, int stride, DoubleBuffer pointer) { - glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_DOUBLE, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(Usage.NORMAL.getAttributeLocation(), 3, GL11.GL_DOUBLE, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glNormalPointer(int type, int stride, long pointer_buffer_offset) { - glVertexAttribPointer(Usage.NORMAL.getAttributeLocation(), 3, type, Usage.NORMAL.isNormalized(), stride, pointer_buffer_offset); + ffpClientArrayPointer(Usage.NORMAL.getAttributeLocation(), 3, type, Usage.NORMAL.isNormalized(), stride, pointer_buffer_offset); } public static void glTexCoordPointer(int size, int type, int stride, ByteBuffer pointer) { final int loc = texCoordAttributeLocation(); if (loc < 0) return; - glVertexAttribPointer(loc, size, type, false, stride, pointer); + ffpClientArrayPointer(loc, size, type, false, stride, pointer); } public static void glTexCoordPointer(int size, int stride, FloatBuffer pointer) { @@ -2580,31 +2593,31 @@ public class GLStateManager { public static void glTexCoordPointer(int size, int type, int stride, FloatBuffer pointer) { final int loc = texCoordAttributeLocation(); if (loc < 0) return; - glVertexAttribPointer(loc, size, GL11.GL_FLOAT, false, stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(loc, size, GL11.GL_FLOAT, false, stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glTexCoordPointer(int size, int type, int stride, ShortBuffer pointer) { final int loc = texCoordAttributeLocation(); if (loc < 0) return; - glVertexAttribPointer(loc, size, GL11.GL_SHORT, false, stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(loc, size, GL11.GL_SHORT, false, stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glTexCoordPointer(int size, int type, int stride, IntBuffer pointer) { final int loc = texCoordAttributeLocation(); if (loc < 0) return; - glVertexAttribPointer(loc, size, GL11.GL_INT, false, stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(loc, size, GL11.GL_INT, false, stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glTexCoordPointer(int size, int type, int stride, DoubleBuffer pointer) { final int loc = texCoordAttributeLocation(); if (loc < 0) return; - glVertexAttribPointer(loc, size, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(pointer)); + ffpClientArrayPointer(loc, size, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(pointer)); } public static void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset) { final int loc = texCoordAttributeLocation(); if (loc < 0) return; - glVertexAttribPointer(loc, size, type, false, stride, pointer_buffer_offset); + ffpClientArrayPointer(loc, size, type, false, stride, pointer_buffer_offset); } public static void glEnableClientState(int cap) { diff --git a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/ffp/VAOManager.java b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/ffp/VAOManager.java index eb74cb714..0d6ba37c7 100644 --- a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/ffp/VAOManager.java +++ b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/ffp/VAOManager.java @@ -85,6 +85,7 @@ public final class VAOManager { a.offset = offset; a.vboId = vboId; a.clientPointer = null; + a.genericPointer = true; if (wasClient && a.enabled) { clientSideEnabledCount--; } @@ -101,11 +102,24 @@ public final class VAOManager { a.offset = 0; a.vboId = 0; a.clientPointer = pointer; + a.genericPointer = true; if (!wasClient && a.enabled) { clientSideEnabledCount++; } } + public static boolean isGenericPointerEnabled(int index) { + if (index < 0 || index >= MAX_ATTRIBS) return false; + final Attrib a = currentAttribs[index]; + return a != null && a.genericPointer && a.enabled; + } + + public static void markConventional(int index) { + if (index < 0 || index >= MAX_ATTRIBS) return; + final Attrib a = currentAttribs[index]; + if (a != null) a.genericPointer = false; + } + public static void setEnabled(int index, boolean enabled) { if (index < 0 || index >= MAX_ATTRIBS) return; final Attrib a = getAttrib(index); @@ -239,6 +253,7 @@ public final class VAOManager { public long offset; public int vboId; public ByteBuffer clientPointer; + public boolean genericPointer; public boolean isClientSide() { return enabled && clientPointer != null; @@ -253,6 +268,7 @@ public final class VAOManager { offset = 0; vboId = 0; clientPointer = null; + genericPointer = false; } public int effectiveStride() { diff --git a/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_VAO_UnitTest.java b/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_VAO_UnitTest.java index abaa66521..1668cd0a6 100644 --- a/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_VAO_UnitTest.java +++ b/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_VAO_UnitTest.java @@ -122,6 +122,68 @@ public class GLSM_VAO_UnitTest { UniversalVAO.deleteVertexArrays(vao); } + @Test + void testGenericAttributeSupersedesFfpConventional() { + final int vao = UniversalVAO.genVertexArrays(); + glBindVertexArray(vao); + final int vbo = GL15.glGenBuffers(); + GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo); + + GLStateManager.glVertexAttribPointer(0, 1, GL11.GL_FLOAT, false, 0, 0L); + GLStateManager.glEnableVertexAttribArray(0); + GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L); + + Assertions.assertEquals(1, VAOManager.get(0).size, "enabled generic attribute must supersede the FFP conventional array at the same location"); + Assertions.assertTrue(VAOManager.get(0).genericPointer, "location must remain generic-sourced"); + + GLStateManager.glDisableVertexAttribArray(0); + GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + GL15.glDeleteBuffers(vbo); + UniversalVAO.deleteVertexArrays(vao); + } + + @Test + void testGenericAttributeWinsRegardlessOfOrder() { + final int vao = UniversalVAO.genVertexArrays(); + glBindVertexArray(vao); + final int vbo = GL15.glGenBuffers(); + GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo); + + GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L); + GLStateManager.glVertexAttribPointer(0, 1, GL11.GL_FLOAT, false, 0, 0L); + GLStateManager.glEnableVertexAttribArray(0); + + Assertions.assertEquals(1, VAOManager.get(0).size, "generic attribute set after the FFP conventional array must still win"); + Assertions.assertTrue(VAOManager.get(0).genericPointer, "location must remain generic-sourced"); + + GLStateManager.glDisableVertexAttribArray(0); + GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + GL15.glDeleteBuffers(vbo); + UniversalVAO.deleteVertexArrays(vao); + } + + @Test + void testFfpConventionalAppliesWithoutGenericAttribute() { + final int vao = UniversalVAO.genVertexArrays(); + glBindVertexArray(vao); + final int vbo = GL15.glGenBuffers(); + GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo); + + GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L); + GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY); + + Assertions.assertEquals(3, VAOManager.get(0).size, "plain FFP conventional array must apply when no generic attribute occupies the location"); + Assertions.assertFalse(VAOManager.get(0).genericPointer, "location must be conventional-sourced"); + + GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY); + GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + GL15.glDeleteBuffers(vbo); + UniversalVAO.deleteVertexArrays(vao); + } + private static void testClientStates() { verifyState(GL11.GL_VERTEX_ARRAY, false, "GL_VERTEX_ARRAY Default State"); verifyState(GL11.GL_TEXTURE_COORD_ARRAY, false, "GL_TEXTURE_COORD_ARRAY Default State");