From 40da0d10c85ffc26813bd22e3c69932601f834c6 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 4 Mar 2018 12:02:30 +0100 Subject: [PATCH] Parse raw buffer instead of intercepting all BufferBuilder calls --- .../render/blend/BlendMeshBuilder.java | 275 +++++++----------- .../render/blend/exporters/ChunkExporter.java | 53 +--- 2 files changed, 117 insertions(+), 211 deletions(-) diff --git a/src/main/java/com/replaymod/render/blend/BlendMeshBuilder.java b/src/main/java/com/replaymod/render/blend/BlendMeshBuilder.java index 945f108b..14717875 100644 --- a/src/main/java/com/replaymod/render/blend/BlendMeshBuilder.java +++ b/src/main/java/com/replaymod/render/blend/BlendMeshBuilder.java @@ -6,6 +6,7 @@ import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.client.renderer.vertex.VertexFormatElement; import org.lwjgl.opengl.GL11; +import org.lwjgl.util.vector.ReadableVector3f; import org.lwjgl.util.vector.Vector2f; import org.lwjgl.util.vector.Vector3f; @@ -16,8 +17,6 @@ import net.minecraft.client.renderer.BufferBuilder; //#endif import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.IntBuffer; import java.util.ArrayList; import java.util.List; @@ -30,22 +29,14 @@ public class BlendMeshBuilder //$$ extends WorldRenderer //#endif { + private static final ReadableVector3f VEC3F_ZERO = new Vector3f(0, 0, 0); private final DMesh mesh; - private final List vertices = new ArrayList<>(); - private final List uvs = new ArrayList<>(); - private final List colors = new ArrayList<>(); - private Vector3f offset = new Vector3f(0, 0, 0); + private Vector3f offset; private boolean isDrawing; private boolean wellBehaved; - private int mode; - //#if MC>=11200 - private double x, y, z; - //#endif - private float u, v; - private int color = 0xffffffff; // Default not in parent class but probably set implicitly somewhere due to re-use public BlendMeshBuilder(DMesh mesh) { - super(0); + super(1024); this.mesh = mesh; } @@ -68,23 +59,31 @@ public class BlendMeshBuilder // Someone probably finished drawing with the global instance instead of this one, // let's just assume that what's happened and finish our last draw by ourselves // (might miss correct texture though) - doFinish(); + super.finishDrawing(); + addBufferToMesh(); } else { throw new IllegalStateException("Already drawing!"); } } this.isDrawing = true; - this.mode = mode; if (!wellBehaved) { // In case the calling code finishes with Tessellator.getInstance().draw() BufferBuilder_beginPosTexCol(mode); } + + //#if MC>=11200 + super.begin(mode, vertexFormat); + //#else + //$$ super.startDrawing(mode); + //#endif } public void maybeFinishDrawing() { if (isDrawing) { - doFinish(); + isDrawing = false; + super.finishDrawing(); + addBufferToMesh(); } } @@ -101,16 +100,106 @@ public class BlendMeshBuilder getBuffer(Tessellator.getInstance()).finishDrawing(); } - doFinish(); //#if MC<11200 - //$$ return -1; + //$$ int ret = + //#endif + super.finishDrawing(); + + addBufferToMesh(); + + //#if MC<11200 + //$$ return ret; //#endif } } - private void doFinish() { - this.isDrawing = false; + private void addBufferToMesh() { + addBufferToMesh(this, mesh, offset); + } + //#if MC>=11200 + public static DMesh addBufferToMesh(BufferBuilder bufferBuilder, DMesh mesh, ReadableVector3f vertOffset) { + //#else + //$$ public static DMesh addBufferToMesh(WorldRenderer bufferBuilder, DMesh mesh, Vector3f vertOffset) { + //#endif + return addBufferToMesh(bufferBuilder.getByteBuffer(), bufferBuilder.getDrawMode(), bufferBuilder.getVertexFormat(), mesh, vertOffset); + } + + public static DMesh addBufferToMesh(ByteBuffer buffer, int mode, VertexFormat vertexFormat, DMesh mesh, ReadableVector3f vertOffset) { + return addBufferToMesh(buffer, buffer.remaining() / vertexFormat.getNextOffset(), mode, vertexFormat, mesh, vertOffset); + } + + public static DMesh addBufferToMesh(ByteBuffer buffer, int vertexCount, int mode, VertexFormat vertexFormat, DMesh mesh, ReadableVector3f vertOffset) { + if (mesh == null) { + mesh = new DMesh(); + } + if (vertOffset == null) { + vertOffset = VEC3F_ZERO; + } + + // Determine offset of vertex components + int posOffset = -1, colorOffset = -1, uvOffset = -1; + int index = 0; + for (VertexFormatElement element : vertexFormat.getElements()) { + //#if MC>11200 + int offset = vertexFormat.getOffset(index); + //#else + //$$ int offset = element.getOffset(); + //#endif + switch (element.getUsage()) { + case POSITION: + if (element.getType() != VertexFormatElement.EnumType.FLOAT) { + throw new UnsupportedOperationException("Only float is supported for position elements!"); + } + posOffset = offset; + break; + case COLOR: + if (element.getType() != VertexFormatElement.EnumType.UBYTE) { + throw new UnsupportedOperationException("Only unsigned byte is supported for color elements!"); + } + colorOffset = offset; + break; + case UV: + if (element.getIndex() != 0) break; + if (element.getType() != VertexFormatElement.EnumType.FLOAT) { + throw new UnsupportedOperationException("Only float is supported for UV elements!"); + } + uvOffset = offset; + break; + } + index++; + } + if (posOffset == -1) throw new IllegalStateException("No position element in " + vertexFormat); + + // Extract vertex components from byte buffer + List vertices = new ArrayList<>(vertexCount); + List uvs = new ArrayList<>(vertexCount); + List colors = new ArrayList<>(vertexCount); + int step = vertexFormat.getNextOffset(); + for (int offset = 0; offset < vertexCount * step; offset += step) { + vertices.add(new DMesh.Vertex( + buffer.getFloat(offset ) - vertOffset.getX(), + -buffer.getFloat(offset + 8) + vertOffset.getZ(), + buffer.getFloat(offset + 4) - vertOffset.getY() + )); + + if (colorOffset != -1) { + colors.add(buffer.getInt(offset + colorOffset)); + } else { + colors.add(0xffffffff); + } + + if (uvOffset != -1) { + uvs.add(new Vector2f( + buffer.getFloat(offset + uvOffset), + 1 - buffer.getFloat(offset + uvOffset + 4) + )); + } else { + uvs.add(new Vector2f(0, 0)); + } + } + + // Determine and store current material DMaterial activeMaterial = BlendState.getState().getMaterials().getActiveMaterial(); int materialSlot = mesh.materials.indexOf(activeMaterial); if (materialSlot < 0) { @@ -118,6 +207,7 @@ public class BlendMeshBuilder mesh.materials.add(activeMaterial); } + // Bundle vertices into shapes and add them to the mesh switch (mode) { case GL11.GL_TRIANGLES: for (int i = 0; i < vertices.size(); i+=3) { @@ -157,148 +247,7 @@ public class BlendMeshBuilder default: throw new UnsupportedOperationException("Unsupported mode: " + mode); } + + return mesh; } - - //#if MC>=11200 - // TODO these should all behave differently depending on the order in which they're called - // e.g. tex may be called multiple times, if there are multiple active texture units - @Override - public BlendMeshBuilder tex(double u, double v) { - this.u = (float) u; - this.v = (float) (1 - v); - return this; - } - - @Override - public BufferBuilder lightmap(int p_187314_1_, int p_187314_2_) { - // TODO we probably do care about this - return this; - } - - @Override - public BlendMeshBuilder color(int r, int g, int b, int a) { - this.color = r | (g << 8) | (b << 16) | (a << 24); - return this; - } - - @Override - public BufferBuilder normal(float x, float y, float z) { - // TODO do we care about normals? - return this; - } - - @Override - public BlendMeshBuilder pos(double x, double y, double z) { - this.x = x - offset.x; - this.y = y - offset.y; - this.z = z - offset.z; - return this; - } - - @Override - public void endVertex() { - vertices.add(new DMesh.Vertex((float) x, (float) -z, (float) y)); - uvs.add(new Vector2f(u, v)); - colors.add(color); - } - //#else - //$$ @Override - //$$ public void setTextureUV(double u, double v) { - //$$ this.u = (float) u; - //$$ this.v = (float) (1 - v); - //$$ } - //$$ - //$$ @Override - //$$ public void setColorRGBA(int r, int g, int b, int a) { - //$$ this.color = r | (g << 8) | (b << 16) | (a << 24); - //$$ } - //$$ - //$$ @Override - //$$ public void addVertex(double x, double y, double z) { - //$$ x -= offset.x; - //$$ y -= offset.y; - //$$ z -= offset.z; - //$$ vertices.add(new DMesh.Vertex((float) x, (float) -z, (float) y)); - //$$ uvs.add(new Vector2f(u, v)); - //$$ colors.add(color); - //$$ } - //#endif - - @Override - @SuppressWarnings("unchecked") - public void addVertexData(int[] ints) { - ByteBuffer buffer = ByteBuffer.allocate(ints.length * 4).order(ByteOrder.nativeOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - intBuffer.put(ints); - - VertexFormat vertexFormat = getVertexFormat(); - int posOffset = -1, colorOffset = -1, uvOffset = -1; - List elements = vertexFormat.getElements(); - int index = 0; - for (VertexFormatElement element : elements) { - //#if MC>11200 - int offset = vertexFormat.getOffset(index); - //#else - //$$ int offset = element.getOffset(); - //#endif - switch (element.getUsage()) { - case POSITION: posOffset = offset; break; - case COLOR: colorOffset = offset; break; - case UV: if (element.getIndex() == 0) uvOffset = offset; break; - } - index++; - } - if (posOffset == -1) throw new IllegalStateException("No position element in " + vertexFormat); - if (uvOffset == -1) throw new IllegalStateException("No uv element in " + vertexFormat); - - for (int offset = 0; offset < buffer.remaining(); offset += vertexFormat.getNextOffset()) { - // TODO doesn't check buffer element types (works for vanilla because they're always the same) - if (colorOffset != -1) { - color = buffer.getInt(offset + colorOffset); - } - //#if MC>11200 - tex( - //#else - //$$ setTextureUV( - //#endif - buffer.getFloat(offset + uvOffset), - buffer.getFloat(offset + uvOffset + 4) - ); - //#if MC>11200 - pos( - //#else - //$$ addVertex( - //#endif - buffer.getFloat(offset + posOffset ), - buffer.getFloat(offset + posOffset + 4), - buffer.getFloat(offset + posOffset + 8) - ); - - //#if MC>11200 - endVertex(); - //#endif - } - } - - @Override - public int getVertexCount() { - return vertices.size(); - } - - public void putColorRGBA(int byteIndex, int r, int g, int b, int a) { - int color = r | (g << 8) | (b << 16) | (a << 24); - putColor(color, -1); // FIXME: reverse index calculation - } - - private void putColor(int color, int reverseIndex) { - colors.set(colors.size() - reverseIndex, color); - } - - public void putColor4(int color) { - for (int i = 0; i < 4; i++) { - putColor(color, i + 1); - } - } - - // FIXME overwrite putX and more } diff --git a/src/main/java/com/replaymod/render/blend/exporters/ChunkExporter.java b/src/main/java/com/replaymod/render/blend/exporters/ChunkExporter.java index 536149d4..a523fe0a 100644 --- a/src/main/java/com/replaymod/render/blend/exporters/ChunkExporter.java +++ b/src/main/java/com/replaymod/render/blend/exporters/ChunkExporter.java @@ -1,5 +1,6 @@ package com.replaymod.render.blend.exporters; +import com.replaymod.render.blend.BlendMeshBuilder; import com.replaymod.render.blend.BlendState; import com.replaymod.render.blend.Exporter; import com.replaymod.render.blend.data.DMaterial; @@ -13,10 +14,11 @@ import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.client.renderer.chunk.CompiledChunk; import net.minecraft.client.renderer.chunk.RenderChunk; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.VertexBuffer; import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; -import org.lwjgl.util.vector.Vector2f; import org.lwjgl.util.vector.Vector3f; //#if MC>=10904 @@ -47,7 +49,6 @@ public class ChunkExporter implements Exporter { //$$ private final List> chunks = new ArrayList<>(); //#endif private DObject chunksObject; - private DMaterial material; private int frame; public void addChunkUpdate(RenderChunk chunk, CompiledChunk compiledChunk) { @@ -97,9 +98,6 @@ public class ChunkExporter implements Exporter { @Override public void postFrame(int frame) throws IOException { - Minecraft.getMinecraft().getTextureManager().bindTexture(LOCATION_BLOCKS_TEXTURE); - material = BlendState.getState().getMaterials().getActiveMaterial(); - //#if MC>=10904 for (Pair pair : chunks) { BlockRenderLayer layer = pair.getRight(); @@ -168,50 +166,9 @@ public class ChunkExporter implements Exporter { GL15.glGetBufferSubData(OpenGlHelper.GL_ARRAY_BUFFER, 0, byteBuffer); vertexBuffer.unbindBuffer(); - DMesh mesh = new DMesh(); - mesh.materials.add(material); - DMesh.Vertex v1 = null, v2 = null, v3 = null; - Vector2f uv1 = new Vector2f(), - uv2 = new Vector2f(), - uv3 = new Vector2f(), - uv4 = new Vector2f(); - int c1 = 0, c2 = 0, c3 = 0; - for (int i = 0; i < size / STRIDE; i++) { - // See VboRenderList.setupArrayPointers for offsets - DMesh.Vertex vert = new DMesh.Vertex( - byteBuffer.getFloat(STRIDE * i), - -byteBuffer.getFloat(STRIDE * i + 8), - byteBuffer.getFloat(STRIDE * i + 4) - ); - float u = byteBuffer.getFloat(STRIDE * i + 16); - float v = 1 - byteBuffer.getFloat(STRIDE * i + 20); - int c = byteBuffer.getInt(STRIDE * i + 12); - // TODO tex, norm, etc. - if (v1 == null) { - v1 = vert; - uv1.set(u, v); - c1 = c; - } else if (v2 == null) { - v2 = vert; - uv2.set(u, v); - c2 = c; - } else if (v3 == null) { - v3 = vert; - uv3.set(u, v); - c3 = c; - } else { - uv4.set(u, v); - mesh.addQuad( - v1, v2, v3, vert, - uv1, uv2, uv3, uv4, - c1, c2, c3, c, - 0 - ); - v1 = v2 = v3 = null; - } - } + Minecraft.getMinecraft().getTextureManager().bindTexture(LOCATION_BLOCKS_TEXTURE); - return mesh; + return BlendMeshBuilder.addBufferToMesh(byteBuffer, GL11.GL_QUADS, DefaultVertexFormats.BLOCK, null, null); } private static final int STRIDE = 28;