2019-11-23 22:17:37 +01:00
|
|
|
package com.simibubi.create.foundation.utility;
|
|
|
|
|
|
|
|
import java.nio.ByteBuffer;
|
2020-04-05 03:54:24 +02:00
|
|
|
import java.nio.ByteOrder;
|
2019-11-23 22:17:37 +01:00
|
|
|
|
2020-03-22 20:19:01 +01:00
|
|
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
|
|
|
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
2020-04-05 03:54:24 +02:00
|
|
|
import com.mojang.datafixers.util.Pair;
|
2020-04-08 20:31:06 +02:00
|
|
|
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
2019-11-23 22:17:37 +01:00
|
|
|
|
|
|
|
import net.minecraft.client.renderer.BufferBuilder;
|
2020-04-05 03:54:24 +02:00
|
|
|
import net.minecraft.client.renderer.BufferBuilder.DrawState;
|
2019-11-23 22:17:37 +01:00
|
|
|
import net.minecraft.client.renderer.GLAllocation;
|
2020-03-22 20:19:01 +01:00
|
|
|
import net.minecraft.client.renderer.Matrix4f;
|
|
|
|
import net.minecraft.client.renderer.Vector4f;
|
2020-05-02 00:19:29 +02:00
|
|
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
2019-11-23 22:17:37 +01:00
|
|
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
2020-03-22 20:19:01 +01:00
|
|
|
import net.minecraft.util.Direction;
|
2020-03-22 22:58:13 +01:00
|
|
|
import net.minecraft.util.Direction.Axis;
|
|
|
|
import net.minecraft.util.Direction.AxisDirection;
|
2019-11-23 22:17:37 +01:00
|
|
|
|
|
|
|
public class SuperByteBuffer {
|
|
|
|
|
|
|
|
public interface IVertexLighter {
|
|
|
|
public int getPackedLight(float x, float y, float z);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static final int FORMAT_LENGTH = DefaultVertexFormats.BLOCK.getSize();
|
|
|
|
protected ByteBuffer original;
|
|
|
|
protected ByteBuffer mutable;
|
|
|
|
|
|
|
|
// Vertex Position
|
2020-03-22 20:19:01 +01:00
|
|
|
private MatrixStack transforms;
|
2019-11-23 22:17:37 +01:00
|
|
|
|
|
|
|
// Vertex Texture Coords
|
|
|
|
private boolean shouldShiftUV;
|
2020-04-08 20:31:06 +02:00
|
|
|
private boolean resetUV;
|
|
|
|
private SpriteShiftEntry spriteShift;
|
|
|
|
private float uTarget, vTarget;
|
2019-11-23 22:17:37 +01:00
|
|
|
|
|
|
|
// Vertex Lighting
|
|
|
|
private boolean shouldLight;
|
|
|
|
private IVertexLighter vertexLighter;
|
2019-12-06 19:48:15 +01:00
|
|
|
private float lightOffsetX, lightOffsetY, lightOffsetZ;
|
2019-11-23 22:17:37 +01:00
|
|
|
private int packedLightCoords;
|
|
|
|
|
|
|
|
// Vertex Coloring
|
|
|
|
private boolean shouldColor;
|
|
|
|
private int r, g, b, a;
|
2020-04-08 20:31:06 +02:00
|
|
|
private float sheetSize;
|
2019-11-23 22:17:37 +01:00
|
|
|
|
2020-03-22 20:19:01 +01:00
|
|
|
public SuperByteBuffer(BufferBuilder buf) {
|
2020-04-05 03:54:24 +02:00
|
|
|
Pair<DrawState, ByteBuffer> state = buf.popData();
|
|
|
|
ByteBuffer original = state.getSecond();
|
|
|
|
original.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers
|
2019-11-23 22:17:37 +01:00
|
|
|
this.original = original;
|
2020-04-05 03:54:24 +02:00
|
|
|
|
|
|
|
this.mutable = GLAllocation.createDirectByteBuffer(state.getFirst().getCount() * buf.getVertexFormat().getSize());
|
2019-11-23 22:17:37 +01:00
|
|
|
this.mutable.order(original.order());
|
|
|
|
this.mutable.limit(original.limit());
|
|
|
|
mutable.put(this.original);
|
|
|
|
mutable.rewind();
|
|
|
|
|
2020-03-22 20:19:01 +01:00
|
|
|
transforms = new MatrixStack();
|
2019-11-23 22:17:37 +01:00
|
|
|
}
|
|
|
|
|
2020-03-22 20:19:01 +01:00
|
|
|
public ByteBuffer build(MatrixStack input) {
|
2019-11-23 22:17:37 +01:00
|
|
|
original.rewind();
|
|
|
|
mutable.rewind();
|
|
|
|
|
2020-04-05 03:54:24 +02:00
|
|
|
Matrix4f t = input.peek().getModel().copy();
|
|
|
|
t.multiply(transforms.peek().getModel());
|
2019-11-23 22:17:37 +01:00
|
|
|
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
|
2020-03-22 20:19:01 +01:00
|
|
|
Vector4f pos = new Vector4f(getX(original, vertex), getY(original, vertex), getZ(original, vertex), 1F);
|
|
|
|
|
|
|
|
pos.transform(t);
|
|
|
|
putPos(mutable, vertex, pos.getX(), pos.getY(), pos.getZ());
|
2019-11-23 22:17:37 +01:00
|
|
|
|
|
|
|
if (shouldColor) {
|
|
|
|
byte lumByte = getR(original, vertex);
|
|
|
|
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
|
|
|
|
int r2 = (int) (r * lum);
|
|
|
|
int g2 = (int) (g * lum);
|
|
|
|
int b2 = (int) (b * lum);
|
|
|
|
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) a);
|
|
|
|
}
|
|
|
|
|
2020-04-08 20:31:06 +02:00
|
|
|
if (shouldShiftUV) {
|
|
|
|
float u = getU(original, vertex);
|
|
|
|
float v = getV(original, vertex);
|
|
|
|
float targetU = spriteShift.getTarget()
|
2020-04-12 22:27:08 +02:00
|
|
|
.getInterpolatedU((getUnInterpolatedU(spriteShift.getOriginal(), u) / sheetSize) + uTarget * 16);
|
2020-04-08 20:31:06 +02:00
|
|
|
float targetV = spriteShift.getTarget()
|
2020-04-12 22:27:08 +02:00
|
|
|
.getInterpolatedV((getUnInterpolatedV(spriteShift.getOriginal(), v) / sheetSize) + vTarget * 16);
|
2020-04-08 20:31:06 +02:00
|
|
|
putUV(mutable, vertex, targetU, targetV);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resetUV)
|
|
|
|
putUV(mutable, vertex, getU(original, vertex), getV(original, vertex));
|
2019-11-23 22:17:37 +01:00
|
|
|
|
|
|
|
if (shouldLight) {
|
|
|
|
if (vertexLighter != null)
|
2019-12-06 19:48:15 +01:00
|
|
|
putLight(mutable, vertex,
|
2020-03-22 20:19:01 +01:00
|
|
|
vertexLighter.getPackedLight(pos.getX() + lightOffsetX, pos.getY() + lightOffsetY, pos.getZ() + lightOffsetZ));
|
2019-11-23 22:17:37 +01:00
|
|
|
else
|
|
|
|
putLight(mutable, vertex, packedLightCoords);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-22 20:19:01 +01:00
|
|
|
transforms = new MatrixStack();
|
2019-11-30 00:27:03 +01:00
|
|
|
shouldShiftUV = false;
|
|
|
|
shouldColor = false;
|
|
|
|
shouldLight = false;
|
2020-04-05 03:54:24 +02:00
|
|
|
mutable.rewind();
|
2019-11-23 22:17:37 +01:00
|
|
|
return mutable;
|
|
|
|
}
|
2020-04-12 22:27:08 +02:00
|
|
|
|
|
|
|
public static float getUnInterpolatedU(TextureAtlasSprite sprite, float u) {
|
|
|
|
float f = sprite.getMaxU() - sprite.getMinU();
|
|
|
|
return (u - sprite.getMinU()) / f * 16.0F;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static float getUnInterpolatedV(TextureAtlasSprite sprite, float v) {
|
|
|
|
float f = sprite.getMaxV() - sprite.getMinV();
|
|
|
|
return (v - sprite.getMinV()) / f * 16.0F;
|
|
|
|
}
|
2019-11-23 22:17:37 +01:00
|
|
|
|
2020-03-22 20:19:01 +01:00
|
|
|
public void renderInto(MatrixStack input, IVertexBuilder buffer) {
|
2020-03-18 21:38:56 +01:00
|
|
|
if (original.limit() == 0)
|
|
|
|
return;
|
2020-03-22 20:19:01 +01:00
|
|
|
if (!(buffer instanceof BufferBuilder)) {
|
2020-03-29 17:46:00 +02:00
|
|
|
// TODO 1.15 add "slow" path that writes all the data instead of using bulk put
|
2020-03-22 20:19:01 +01:00
|
|
|
throw new IllegalArgumentException("Unsupported buffer type!");
|
|
|
|
}
|
|
|
|
((BufferBuilder)buffer).putBulkData(build(input));
|
2019-11-23 22:17:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public SuperByteBuffer translate(double x, double y, double z) {
|
|
|
|
return translate((float) x, (float) y, (float) z);
|
|
|
|
}
|
|
|
|
|
|
|
|
public SuperByteBuffer translate(float x, float y, float z) {
|
2020-03-22 20:19:01 +01:00
|
|
|
transforms.translate(x, y, z);
|
2019-11-23 22:17:37 +01:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2020-03-22 22:58:13 +01:00
|
|
|
@Deprecated
|
|
|
|
public SuperByteBuffer rotate(Axis axis, float radians) {
|
|
|
|
return rotate(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis), radians);
|
|
|
|
}
|
|
|
|
|
|
|
|
public SuperByteBuffer rotate(Direction axis, float radians) {
|
|
|
|
if (radians == 0)
|
2019-11-23 22:17:37 +01:00
|
|
|
return this;
|
2020-03-22 22:58:13 +01:00
|
|
|
transforms.multiply(axis.getUnitVector().getRadialQuaternion(radians));
|
2019-11-23 22:17:37 +01:00
|
|
|
return this;
|
|
|
|
}
|
2020-03-22 22:58:13 +01:00
|
|
|
|
|
|
|
@Deprecated
|
|
|
|
public SuperByteBuffer rotateCentered(Axis axis, float radians) {
|
|
|
|
return rotateCentered(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis), radians);
|
|
|
|
}
|
|
|
|
|
|
|
|
public SuperByteBuffer rotateCentered(Direction axis, float radians) {
|
2020-04-05 03:54:24 +02:00
|
|
|
return translate(.5f, .5f, .5f).rotate(axis, radians).translate(-.5f, -.5f, -.5f);
|
2019-11-23 22:17:37 +01:00
|
|
|
}
|
|
|
|
|
2020-04-08 20:31:06 +02:00
|
|
|
public SuperByteBuffer shiftUV(SpriteShiftEntry entry) {
|
2019-11-23 22:17:37 +01:00
|
|
|
shouldShiftUV = true;
|
2020-04-08 20:31:06 +02:00
|
|
|
resetUV = false;
|
|
|
|
spriteShift = entry;
|
|
|
|
uTarget = 0;
|
|
|
|
vTarget = 0;
|
|
|
|
sheetSize = 1;
|
2019-11-23 22:17:37 +01:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2020-04-08 20:31:06 +02:00
|
|
|
public SuperByteBuffer shiftUVtoSheet(SpriteShiftEntry entry, float uTarget, float vTarget, int sheetSize) {
|
2019-11-23 22:17:37 +01:00
|
|
|
shouldShiftUV = true;
|
2020-04-08 20:31:06 +02:00
|
|
|
resetUV = false;
|
|
|
|
spriteShift = entry;
|
|
|
|
this.uTarget = uTarget;
|
|
|
|
this.vTarget = vTarget;
|
|
|
|
this.sheetSize = sheetSize;
|
2019-11-23 22:17:37 +01:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2019-11-30 00:27:03 +01:00
|
|
|
public SuperByteBuffer dontShiftUV() {
|
|
|
|
shouldShiftUV = false;
|
2020-04-08 20:31:06 +02:00
|
|
|
resetUV = true;
|
2019-11-30 00:27:03 +01:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2019-11-23 22:17:37 +01:00
|
|
|
public SuperByteBuffer light(int packedLightCoords) {
|
|
|
|
shouldLight = true;
|
2019-12-06 19:48:15 +01:00
|
|
|
vertexLighter = null;
|
2019-11-23 22:17:37 +01:00
|
|
|
this.packedLightCoords = packedLightCoords;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public SuperByteBuffer light(IVertexLighter lighter) {
|
|
|
|
shouldLight = true;
|
|
|
|
vertexLighter = lighter;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2019-12-06 19:48:15 +01:00
|
|
|
public SuperByteBuffer offsetLighting(double x, double y, double z) {
|
|
|
|
lightOffsetX = (float) x;
|
|
|
|
lightOffsetY = (float) y;
|
|
|
|
lightOffsetZ = (float) z;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2019-11-23 22:17:37 +01:00
|
|
|
public SuperByteBuffer color(int color) {
|
|
|
|
shouldColor = true;
|
|
|
|
r = ((color >> 16) & 0xFF);
|
|
|
|
g = ((color >> 8) & 0xFF);
|
|
|
|
b = (color & 0xFF);
|
|
|
|
a = 255;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected int vertexCount(ByteBuffer buffer) {
|
|
|
|
return buffer.limit() / FORMAT_LENGTH;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected int getBufferPosition(int vertexIndex) {
|
|
|
|
return vertexIndex * FORMAT_LENGTH;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float getX(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.getFloat(getBufferPosition(index));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float getY(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.getFloat(getBufferPosition(index) + 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float getZ(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.getFloat(getBufferPosition(index) + 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected byte getR(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.get(getBufferPosition(index) + 12);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected byte getG(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.get(getBufferPosition(index) + 13);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected byte getB(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.get(getBufferPosition(index) + 14);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected byte getA(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.get(getBufferPosition(index) + 15);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float getU(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.getFloat(getBufferPosition(index) + 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float getV(ByteBuffer buffer, int index) {
|
|
|
|
return buffer.getFloat(getBufferPosition(index) + 20);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void putPos(ByteBuffer buffer, int index, float x, float y, float z) {
|
|
|
|
int pos = getBufferPosition(index);
|
|
|
|
buffer.putFloat(pos, x);
|
|
|
|
buffer.putFloat(pos + 4, y);
|
|
|
|
buffer.putFloat(pos + 8, z);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void putUV(ByteBuffer buffer, int index, float u, float v) {
|
|
|
|
int pos = getBufferPosition(index);
|
|
|
|
buffer.putFloat(pos + 16, u);
|
|
|
|
buffer.putFloat(pos + 20, v);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void putLight(ByteBuffer buffer, int index, int packedLight) {
|
2020-04-05 03:54:24 +02:00
|
|
|
buffer.putShort(getBufferPosition(index) + 24, (short) (packedLight & 0xFF));
|
|
|
|
buffer.putShort(getBufferPosition(index) + 26, (short) ((packedLight >> 16) & 0xFF));
|
2019-11-23 22:17:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void putColor(ByteBuffer buffer, int index, byte r, byte g, byte b, byte a) {
|
|
|
|
int bufferPosition = getBufferPosition(index);
|
|
|
|
buffer.put(bufferPosition + 12, r);
|
|
|
|
buffer.put(bufferPosition + 13, g);
|
|
|
|
buffer.put(bufferPosition + 14, b);
|
|
|
|
buffer.put(bufferPosition + 15, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|