//#if MC>=10800 package com.replaymod.render.blend; import com.replaymod.render.blend.data.DMaterial; import com.replaymod.render.blend.data.DMesh; import de.johni0702.minecraft.gui.utils.lwjgl.vector.ReadableVector3f; import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector2f; import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector3f; import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormatElement; import net.minecraft.client.render.VertexFormats; import org.lwjgl.opengl.GL11; //#if MC>=11500 import com.mojang.datafixers.util.Pair; //#endif //#if MC>=10904 //#if MC>=11200 import net.minecraft.client.render.BufferBuilder; //#else //$$ import net.minecraft.client.renderer.VertexBuffer; //#endif //#else //$$ import net.minecraft.client.renderer.WorldRenderer; //#endif import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import static com.replaymod.core.versions.MCVer.*; public class BlendMeshBuilder //#if MC>=10904 //#if MC>=11200 extends BufferBuilder //#else //$$ extends VertexBuffer //#endif //#else //$$ extends WorldRenderer //#endif { private static final ReadableVector3f VEC3F_ZERO = new Vector3f(0, 0, 0); private final DMesh mesh; private Vector3f offset; private boolean isDrawing; private boolean wellBehaved; public BlendMeshBuilder(DMesh mesh) { super(1024); this.mesh = mesh; } public void setWellBehaved(boolean wellBehaved) { this.wellBehaved = wellBehaved; } public void setReverseOffset(Vector3f offset) { this.offset = offset; } @Override //#if MC>=11700 //$$ public void begin(VertexFormat.DrawMode mode, VertexFormat vertexFormat) { //#elseif MC>=10809 public void begin(int mode, VertexFormat vertexFormat) { //#else //$$ public void startDrawing(int mode) { //#endif if (isDrawing) { if (!wellBehaved) { // 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) super.end(); addBufferToMesh(); } else { throw new IllegalStateException("Already drawing!"); } } this.isDrawing = true; if (!wellBehaved) { // In case the calling code finishes with Tessellator.getInstance().draw() Tessellator.getInstance().getBuffer().begin(mode, VertexFormats.POSITION_TEXTURE_COLOR); } //#if MC>=10809 super.begin(mode, vertexFormat); //#else //$$ super.startDrawing(mode); //#endif } public void maybeFinishDrawing() { if (isDrawing) { isDrawing = false; super.end(); addBufferToMesh(); } } @Override //#if MC>=10809 public void end() { //#else //$$ public int finishDrawing() { //#endif if (!isDrawing) { throw new IllegalStateException("Not building!"); } else { if (!wellBehaved) { Tessellator.getInstance().getBuffer().end(); } //#if MC<10809 //$$ int ret = //#endif super.end(); addBufferToMesh(); //#if MC<10809 //$$ return ret; //#endif } } private void addBufferToMesh() { addBufferToMesh(this, mesh, offset); } //#if MC>=10904 //#if MC>=11200 public static DMesh addBufferToMesh(BufferBuilder bufferBuilder, DMesh mesh, ReadableVector3f vertOffset) { //#else //$$ public static DMesh addBufferToMesh(VertexBuffer bufferBuilder, DMesh mesh, Vector3f vertOffset) { //#endif //#else //$$ public static DMesh addBufferToMesh(WorldRenderer bufferBuilder, DMesh mesh, Vector3f vertOffset) { //#endif //#if MC>=11500 Pair data = bufferBuilder.popData(); return addBufferToMesh(data.getSecond(), data.getFirst().getMode(), data.getFirst().getVertexFormat(), mesh, vertOffset); //#else //$$ return addBufferToMesh(bufferBuilder.getByteBuffer(), bufferBuilder.getDrawMode(), bufferBuilder.getVertexFormat(), mesh, vertOffset); //#endif } public static DMesh addBufferToMesh( ByteBuffer buffer, //#if MC>=11700 //$$ VertexFormat.DrawMode mode, //#else int mode, //#endif VertexFormat vertexFormat, DMesh mesh, ReadableVector3f vertOffset ) { //#if MC>=11400 int vertexCount = buffer.remaining() / vertexFormat.getVertexSize(); //#else //$$ int vertexCount = buffer.remaining() / vertexFormat.getNextOffset(); //#endif return addBufferToMesh(buffer, vertexCount, mode, vertexFormat, mesh, vertOffset); } public static DMesh addBufferToMesh( ByteBuffer buffer, int vertexCount, //#if MC>=11700 //$$ VertexFormat.DrawMode mode, //#else int mode, //#endif 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; //#if MC>=11500 int elementOffset = 0; //#endif for (VertexFormatElement element : getElements(vertexFormat)) { //#if MC>=11500 int offset = elementOffset; elementOffset += element.getSize(); //#else //#if MC>=10809 //$$ int offset = vertexFormat.getElementOffset(index); //#else //$$ int offset = element.getOffset(); //#endif //#endif switch (element.getType()) { case POSITION: //#if MC>=11400 if (element.getFormat() != VertexFormatElement.Format.FLOAT) { //#else //$$ if (element.getType() != VertexFormatElement.EnumType.FLOAT) { //#endif throw new UnsupportedOperationException("Only float is supported for position elements!"); } posOffset = offset; break; case COLOR: //#if MC>=11400 if (element.getFormat() != VertexFormatElement.Format.UBYTE) { //#else //$$ if (element.getType() != VertexFormatElement.EnumType.UBYTE) { //#endif throw new UnsupportedOperationException("Only unsigned byte is supported for color elements!"); } colorOffset = offset; break; case UV: if (element.getIndex() != 0) break; //#if MC>=11400 if (element.getFormat() != VertexFormatElement.Format.FLOAT) { //#else //$$ if (element.getType() != VertexFormatElement.EnumType.UBYTE) { //#endif 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); //#if MC>=11400 int step = vertexFormat.getVertexSize(); //#else //$$ int step = vertexFormat.getNextOffset(); //#endif 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) { materialSlot = mesh.materials.size(); mesh.materials.add(activeMaterial); } // Bundle vertices into shapes and add them to the mesh switch (mode) { //#if MC>=11700 //$$ case TRIANGLES: //#else case GL11.GL_TRIANGLES: //#endif for (int i = 0; i < vertices.size(); i+=3) { mesh.addTriangle( vertices.get(i ), vertices.get(i + 1), vertices.get(i + 2), uvs.get(i ), uvs.get(i + 1), uvs.get(i + 2), colors.get(i ), colors.get(i + 1), colors.get(i + 2), materialSlot ); } break; //#if MC>=11700 //$$ case QUADS: //#else case GL11.GL_QUADS: //#endif for (int i = 0; i < vertices.size(); i+=4) { mesh.addQuad( vertices.get(i ), vertices.get(i + 1), vertices.get(i + 2), vertices.get(i + 3), uvs.get(i ), uvs.get(i + 1), uvs.get(i + 2), uvs.get(i + 3), colors.get(i ), colors.get(i + 1), colors.get(i + 2), colors.get(i + 3), materialSlot ); } break; default: throw new UnsupportedOperationException("Unsupported mode: " + mode); } return mesh; } } //#endif