Create/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java

255 lines
6.7 KiB
Java
Raw Normal View History

package com.simibubi.create.foundation.utility;
import java.nio.ByteBuffer;
import javax.vecmath.Matrix4f;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction.Axis;
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
private Matrix4f transforms;
private Matrix4f t;
// Vertex Texture Coords
private boolean shouldShiftUV;
private float uShift, vShift;
// Vertex Lighting
private boolean shouldLight;
private IVertexLighter vertexLighter;
private float lightOffsetX, lightOffsetY, lightOffsetZ;
private int packedLightCoords;
// Vertex Coloring
private boolean shouldColor;
private int r, g, b, a;
public SuperByteBuffer(ByteBuffer original) {
original.rewind();
this.original = original;
this.mutable = GLAllocation.createDirectByteBuffer(original.capacity());
this.mutable.order(original.order());
this.mutable.limit(original.limit());
mutable.put(this.original);
mutable.rewind();
t = new Matrix4f();
transforms = new Matrix4f();
transforms.setIdentity();
}
public ByteBuffer build() {
original.rewind();
mutable.rewind();
float x, y, z = 0;
float x2, y2, z2 = 0;
Matrix4f t = transforms;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
x = getX(original, vertex);
y = getY(original, vertex);
z = getZ(original, vertex);
x2 = t.m00 * x + t.m01 * y + t.m02 * z + t.m03;
y2 = t.m10 * x + t.m11 * y + t.m12 * z + t.m13;
z2 = t.m20 * x + t.m21 * y + t.m22 * z + t.m23;
putPos(mutable, vertex, x2, y2, z2);
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);
}
if (shouldShiftUV)
putUV(mutable, vertex, getU(original, vertex) + uShift, getV(original, vertex) + vShift);
if (shouldLight) {
if (vertexLighter != null)
putLight(mutable, vertex,
vertexLighter.getPackedLight(x2 + lightOffsetX, y2 + lightOffsetY, z2 + lightOffsetZ));
else
putLight(mutable, vertex, packedLightCoords);
}
}
t.setIdentity();
shouldShiftUV = false;
shouldColor = false;
shouldLight = false;
return mutable;
}
public void renderInto(BufferBuilder buffer) {
buffer.putBulkData(build());
}
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) {
transforms.m03 += x;
transforms.m13 += y;
transforms.m23 += z;
return this;
}
public SuperByteBuffer rotate(Axis axis, float angle) {
if (angle == 0)
return this;
t.setIdentity();
if (axis == Axis.X)
t.rotX(angle);
else if (axis == Axis.Y)
t.rotY(angle);
else
t.rotZ(angle);
transforms.mul(t, transforms);
return this;
}
public SuperByteBuffer rotateCentered(Axis axis, float angle) {
return translate(-.5f, -.5f, -.5f).rotate(axis, angle).translate(.5f, .5f, .5f);
}
public SuperByteBuffer shiftUV(TextureAtlasSprite from, TextureAtlasSprite to) {
shouldShiftUV = true;
uShift = to.getMinU() - from.getMinU();
vShift = to.getMinV() - from.getMinV();
return this;
}
public SuperByteBuffer shiftUVtoSheet(TextureAtlasSprite from, TextureAtlasSprite to, int sheetX, int sheetY) {
shouldShiftUV = true;
uShift = to.getInterpolatedU(sheetX * 16f / to.getWidth()) - from.getMinU();
vShift = to.getInterpolatedV(sheetY * 16f / to.getHeight()) - from.getMinV();
return this;
}
public SuperByteBuffer dontShiftUV() {
shouldShiftUV = false;
uShift = 0;
vShift = 0;
return this;
}
public SuperByteBuffer light(int packedLightCoords) {
shouldLight = true;
vertexLighter = null;
this.packedLightCoords = packedLightCoords;
return this;
}
public SuperByteBuffer light(IVertexLighter lighter) {
shouldLight = true;
vertexLighter = lighter;
return this;
}
public SuperByteBuffer offsetLighting(double x, double y, double z) {
lightOffsetX = (float) x;
lightOffsetY = (float) y;
lightOffsetZ = (float) z;
return this;
}
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) {
buffer.putInt(getBufferPosition(index) + 24, packedLight);
}
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);
}
}