338 lines
11 KiB
Java
338 lines
11 KiB
Java
//#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<DrawArrayParameters, ByteBuffer> 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<DMesh.Vertex> vertices = new ArrayList<>(vertexCount);
|
|
List<Vector2f> uvs = new ArrayList<>(vertexCount);
|
|
List<Integer> 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
|