Parse raw buffer instead of intercepting all BufferBuilder calls
This commit is contained in:
@@ -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<DMesh.Vertex> vertices = new ArrayList<>();
|
||||
private final List<Vector2f> uvs = new ArrayList<>();
|
||||
private final List<Integer> 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<DMesh.Vertex> vertices = new ArrayList<>(vertexCount);
|
||||
List<Vector2f> uvs = new ArrayList<>(vertexCount);
|
||||
List<Integer> 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<VertexFormatElement> 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
|
||||
}
|
||||
|
||||
@@ -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<Pair<RenderChunk, EnumWorldBlockLayer>> 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<RenderChunk, BlockRenderLayer> 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;
|
||||
|
||||
Reference in New Issue
Block a user