mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-30 14:55:01 +01:00
TemplateBuffer is no more
- Instead, BufferBuilderReader can decode parts of a BufferBuilder. - BufferedModel and its subclasses are now created directly with a ByteBuffer. - ContraptionModel renamed to IndexedModel. - InstancedModel and IndexedModel both now take model formats as arguments. - All of this allows for better abstraction, composition, and control of models rendered with Flywheel.
This commit is contained in:
parent
9ff193946c
commit
6227e81066
11 changed files with 340 additions and 312 deletions
|
@ -1,33 +1,35 @@
|
||||||
package com.jozufozu.flywheel.backend;
|
package com.jozufozu.flywheel.backend.core;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL15;
|
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.RenderWork;
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.simibubi.create.foundation.render.TemplateBuffer;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
public abstract class BufferedModel {
|
||||||
|
|
||||||
public abstract class BufferedModel extends TemplateBuffer {
|
|
||||||
|
|
||||||
|
protected final ByteBuffer data;
|
||||||
protected final VertexFormat modelFormat;
|
protected final VertexFormat modelFormat;
|
||||||
|
protected final int vertexCount;
|
||||||
protected GlBuffer modelVBO;
|
protected GlBuffer modelVBO;
|
||||||
private boolean initialized; // lazy init
|
private boolean initialized; // lazy init
|
||||||
private boolean removed;
|
private boolean removed;
|
||||||
|
|
||||||
protected BufferedModel(VertexFormat modelFormat, BufferBuilder buf) {
|
protected BufferedModel(VertexFormat modelFormat, ByteBuffer data, int vertices) {
|
||||||
super(buf);
|
this.data = data;
|
||||||
this.modelFormat = modelFormat;
|
this.modelFormat = modelFormat;
|
||||||
|
this.vertexCount = vertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders this model, checking first if there is anything to render.
|
* Renders this model, checking first if there is anything to render.
|
||||||
*/
|
*/
|
||||||
public final void render() {
|
public final void render() {
|
||||||
if (vertexCount == 0 || removed) return;
|
if (vertexCount <= 0 || removed) return;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
// Lazily acquire resources in order to get around initialization order, as #getTotalShaderAttributeCount
|
// Lazily acquire resources in order to get around initialization order, as #getTotalShaderAttributeCount
|
||||||
|
@ -60,22 +62,15 @@ public abstract class BufferedModel extends TemplateBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initModel() {
|
protected void initModel() {
|
||||||
int stride = modelFormat.getStride();
|
|
||||||
int invariantSize = vertexCount * stride;
|
|
||||||
|
|
||||||
// allocate the buffer on the gpu
|
// allocate the buffer on the gpu
|
||||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW);
|
modelVBO.alloc(data.capacity());
|
||||||
|
|
||||||
// mirror it in system memory so we can write to it
|
// mirror it in system memory so we can write to it
|
||||||
MappedBuffer buffer = modelVBO.getBuffer(0, invariantSize);
|
MappedBuffer buffer = modelVBO.getBuffer(0, data.capacity());
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
buffer.put(data);
|
||||||
copyVertex(buffer, i);
|
|
||||||
}
|
|
||||||
buffer.flush();
|
buffer.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void copyVertex(MappedBuffer to, int index);
|
|
||||||
|
|
||||||
protected int getTotalShaderAttributeCount() {
|
protected int getTotalShaderAttributeCount() {
|
||||||
return modelFormat.getShaderAttributeCount();
|
return modelFormat.getShaderAttributeCount();
|
||||||
}
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.jozufozu.flywheel.backend.core;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL20;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlPrimitiveType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
|
|
||||||
|
public class IndexedModel extends BufferedModel {
|
||||||
|
|
||||||
|
protected GlPrimitiveType eboIndexType;
|
||||||
|
protected GlBuffer ebo;
|
||||||
|
|
||||||
|
public IndexedModel(VertexFormat modelFormat, ByteBuffer buf, int vertices) {
|
||||||
|
super(modelFormat, buf, vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
|
||||||
|
createEBO();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doRender() {
|
||||||
|
modelVBO.bind();
|
||||||
|
ebo.bind();
|
||||||
|
|
||||||
|
setupAttributes();
|
||||||
|
GL20.glDrawElements(GL20.GL_QUADS, vertexCount, eboIndexType.getGlConstant(), 0);
|
||||||
|
|
||||||
|
int numAttributes = getTotalShaderAttributeCount();
|
||||||
|
for (int i = 0; i <= numAttributes; i++) {
|
||||||
|
GL20.glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ebo.unbind();
|
||||||
|
modelVBO.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void createEBO() {
|
||||||
|
ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
||||||
|
eboIndexType = GlPrimitiveType.UINT; // TODO: choose this based on the number of vertices
|
||||||
|
|
||||||
|
int indicesSize = vertexCount * eboIndexType.getSize();
|
||||||
|
|
||||||
|
ebo.bind();
|
||||||
|
|
||||||
|
ebo.alloc(indicesSize);
|
||||||
|
MappedBuffer indices = ebo.getBuffer(0, indicesSize);
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
indices.putInt(i);
|
||||||
|
}
|
||||||
|
indices.flush();
|
||||||
|
|
||||||
|
ebo.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void deleteInternal() {
|
||||||
|
super.deleteInternal();
|
||||||
|
ebo.delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ public class GlBuffer extends GlObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MappedBuffer getBuffer(int offset, int length) {
|
public MappedBuffer getBuffer(int offset, int length) {
|
||||||
if (Backend.compat.mapBufferRange == MapBufferRange.UNSUPPORTED) {
|
if (Backend.compat.mapBufferRange != MapBufferRange.UNSUPPORTED) {
|
||||||
return new MappedBufferRange(this, offset, length, GL30.GL_MAP_WRITE_BIT);
|
return new MappedBufferRange(this, offset, length, GL30.GL_MAP_WRITE_BIT);
|
||||||
} else {
|
} else {
|
||||||
MappedFullBuffer fullBuffer = new MappedFullBuffer(this, MappedBufferUsage.WRITE_ONLY);
|
MappedFullBuffer fullBuffer = new MappedFullBuffer(this, MappedBufferUsage.WRITE_ONLY);
|
||||||
|
|
|
@ -80,6 +80,12 @@ public abstract class MappedBuffer implements AutoCloseable {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MappedBuffer put(ByteBuffer b) {
|
||||||
|
checkAndMap();
|
||||||
|
internal.put(b);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public MappedBuffer putVec4(float x, float y, float z, float w) {
|
public MappedBuffer putVec4(float x, float y, float z, float w) {
|
||||||
checkAndMap();
|
checkAndMap();
|
||||||
internal.putFloat(x);
|
internal.putFloat(x);
|
||||||
|
|
|
@ -1,24 +1,21 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.BufferedModel;
|
import com.jozufozu.flywheel.backend.core.BufferedModel;
|
||||||
import com.jozufozu.flywheel.backend.core.materials.ModelAttributes;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class InstancedModel<D extends InstanceData> extends BufferedModel {
|
public class InstancedModel<D extends InstanceData> extends BufferedModel {
|
||||||
public static final VertexFormat FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build();
|
|
||||||
|
|
||||||
public final InstancedTileRenderer<?> renderer;
|
public final InstancedTileRenderer<?> renderer;
|
||||||
|
|
||||||
|
@ -34,8 +31,8 @@ public class InstancedModel<D extends InstanceData> extends BufferedModel {
|
||||||
boolean anyToRemove;
|
boolean anyToRemove;
|
||||||
boolean anyToUpdate;
|
boolean anyToUpdate;
|
||||||
|
|
||||||
public InstancedModel(InstancedTileRenderer<?> renderer, VertexFormat instanceFormat, InstanceFactory<D> factory, BufferBuilder buf) {
|
public InstancedModel(VertexFormat modelFormat, ByteBuffer buf, int vertices, InstancedTileRenderer<?> renderer, VertexFormat instanceFormat, InstanceFactory<D> factory) {
|
||||||
super(FORMAT, buf);
|
super(modelFormat, buf, vertices);
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.instanceFormat = instanceFormat;
|
this.instanceFormat = instanceFormat;
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
|
@ -225,20 +222,6 @@ public class InstancedModel<D extends InstanceData> extends BufferedModel {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void copyVertex(MappedBuffer constant, int i) {
|
|
||||||
constant.putFloat(getX(template, i));
|
|
||||||
constant.putFloat(getY(template, i));
|
|
||||||
constant.putFloat(getZ(template, i));
|
|
||||||
|
|
||||||
constant.put(getNX(template, i));
|
|
||||||
constant.put(getNY(template, i));
|
|
||||||
constant.put(getNZ(template, i));
|
|
||||||
|
|
||||||
constant.putFloat(getU(template, i));
|
|
||||||
constant.putFloat(getV(template, i));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getTotalShaderAttributeCount() {
|
protected int getTotalShaderAttributeCount() {
|
||||||
return instanceFormat.getShaderAttributeCount() + super.getTotalShaderAttributeCount();
|
return instanceFormat.getShaderAttributeCount() + super.getTotalShaderAttributeCount();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing;
|
package com.jozufozu.flywheel.backend.instancing;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -12,7 +14,10 @@ import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.jozufozu.flywheel.backend.core.BasicProgram;
|
import com.jozufozu.flywheel.backend.core.BasicProgram;
|
||||||
import com.jozufozu.flywheel.backend.core.PartialModel;
|
import com.jozufozu.flywheel.backend.core.PartialModel;
|
||||||
|
import com.jozufozu.flywheel.backend.core.materials.ModelAttributes;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback;
|
import com.jozufozu.flywheel.backend.gl.shader.ShaderCallback;
|
||||||
|
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||||
import com.jozufozu.flywheel.util.RenderUtil;
|
import com.jozufozu.flywheel.util.RenderUtil;
|
||||||
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
@ -31,6 +36,7 @@ import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.vector.Matrix4f;
|
import net.minecraft.util.math.vector.Matrix4f;
|
||||||
|
|
||||||
public class RenderMaterial<P extends BasicProgram, D extends InstanceData> {
|
public class RenderMaterial<P extends BasicProgram, D extends InstanceData> {
|
||||||
|
public static final VertexFormat MODEL_FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build();
|
||||||
|
|
||||||
protected final InstancedTileRenderer<P> renderer;
|
protected final InstancedTileRenderer<P> renderer;
|
||||||
protected final Cache<Object, InstancedModel<D>> models;
|
protected final Cache<Object, InstancedModel<D>> models;
|
||||||
|
@ -113,9 +119,30 @@ public class RenderMaterial<P extends BasicProgram, D extends InstanceData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstancedModel<D> buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
private InstancedModel<D> buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) {
|
||||||
BufferBuilder builder = getBufferBuilder(model, referenceState, ms);
|
BufferBuilderReader reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms));
|
||||||
|
|
||||||
return new InstancedModel<>(renderer, spec.getInstanceFormat(), spec.getInstanceFactory(), builder);
|
VertexFormat format = MODEL_FORMAT;
|
||||||
|
int vertexCount = reader.getVertexCount();
|
||||||
|
|
||||||
|
ByteBuffer to = ByteBuffer.allocate(vertexCount * format.getStride());
|
||||||
|
to.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
to.putFloat(reader.getX(i));
|
||||||
|
to.putFloat(reader.getY(i));
|
||||||
|
to.putFloat(reader.getZ(i));
|
||||||
|
|
||||||
|
to.put(reader.getNX(i));
|
||||||
|
to.put(reader.getNY(i));
|
||||||
|
to.put(reader.getNZ(i));
|
||||||
|
|
||||||
|
to.putFloat(reader.getU(i));
|
||||||
|
to.putFloat(reader.getV(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
to.rewind();
|
||||||
|
|
||||||
|
return new InstancedModel<>(format, to, vertexCount, renderer, spec.getInstanceFormat(), spec.getInstanceFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Direction[] dirs;
|
private static final Direction[] dirs;
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package com.jozufozu.flywheel.util;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||||
|
|
||||||
|
public class BufferBuilderReader {
|
||||||
|
|
||||||
|
private final ByteBuffer buffer;
|
||||||
|
private final int vertexCount;
|
||||||
|
private final int formatSize;
|
||||||
|
private final int size;
|
||||||
|
|
||||||
|
public BufferBuilderReader(BufferBuilder builder) {
|
||||||
|
VertexFormat vertexFormat = builder.getVertexFormat();
|
||||||
|
Pair<BufferBuilder.DrawState, ByteBuffer> data = builder.popData();
|
||||||
|
buffer = data.getSecond();
|
||||||
|
|
||||||
|
formatSize = vertexFormat.getSize();
|
||||||
|
|
||||||
|
vertexCount = data.getFirst()
|
||||||
|
.getCount();
|
||||||
|
|
||||||
|
size = vertexCount * formatSize;
|
||||||
|
|
||||||
|
// TODO: adjust the getters based on the input format
|
||||||
|
// ImmutableList<VertexFormatElement> elements = vertexFormat.getElements();
|
||||||
|
// for (int i = 0, size = elements.size(); i < size; i++) {
|
||||||
|
// VertexFormatElement element = elements.get(i);
|
||||||
|
// int offset = vertexFormat.getOffset(i);
|
||||||
|
//
|
||||||
|
// element.getUsage()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return vertexCount == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int vertIdx(int vertexIndex) {
|
||||||
|
return vertexIndex * formatSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getX(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index) + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getZ(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index) + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getR(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getG(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getB(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getA(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getU(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index) + 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getV(int index) {
|
||||||
|
return buffer.getFloat(vertIdx(index) + 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLight(int index) {
|
||||||
|
return buffer.getInt(vertIdx(index) + 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getNX(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 28);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getNY(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 29);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getNZ(int index) {
|
||||||
|
return buffer.get(vertIdx(index) + 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVertexCount() {
|
||||||
|
return vertexCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,101 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL20;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.BufferedModel;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlPrimitiveType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
|
||||||
|
|
||||||
public class ContraptionModel extends BufferedModel {
|
|
||||||
public static final VertexFormat FORMAT = VertexFormat.builder()
|
|
||||||
.addAttributes(ContraptionAttributes.class)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
protected GlPrimitiveType eboIndexType;
|
|
||||||
protected GlBuffer ebo;
|
|
||||||
|
|
||||||
public ContraptionModel(BufferBuilder buf) {
|
|
||||||
super(FORMAT, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void init() {
|
|
||||||
super.init();
|
|
||||||
|
|
||||||
createEBO();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doRender() {
|
|
||||||
modelVBO.bind();
|
|
||||||
ebo.bind();
|
|
||||||
|
|
||||||
setupAttributes();
|
|
||||||
GL20.glDrawElements(GL20.GL_QUADS, vertexCount, eboIndexType.getGlConstant(), 0);
|
|
||||||
|
|
||||||
int numAttributes = getTotalShaderAttributeCount();
|
|
||||||
for (int i = 0; i <= numAttributes; i++) {
|
|
||||||
GL20.glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
ebo.unbind();
|
|
||||||
modelVBO.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void createEBO() {
|
|
||||||
ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
|
||||||
eboIndexType = GlPrimitiveType.UINT; // TODO: choose this based on the number of vertices
|
|
||||||
|
|
||||||
int indicesSize = vertexCount * eboIndexType.getSize();
|
|
||||||
|
|
||||||
ebo.bind();
|
|
||||||
|
|
||||||
ebo.alloc(indicesSize);
|
|
||||||
MappedBuffer indices = ebo.getBuffer(0, indicesSize);
|
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
|
||||||
indices.putInt(i);
|
|
||||||
}
|
|
||||||
indices.flush();
|
|
||||||
|
|
||||||
ebo.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void copyVertex(MappedBuffer to, int vertex) {
|
|
||||||
to.putFloat(getX(template, vertex));
|
|
||||||
to.putFloat(getY(template, vertex));
|
|
||||||
to.putFloat(getZ(template, vertex));
|
|
||||||
|
|
||||||
to.put(getNX(template, vertex));
|
|
||||||
to.put(getNY(template, vertex));
|
|
||||||
to.put(getNZ(template, vertex));
|
|
||||||
|
|
||||||
to.putFloat(getU(template, vertex));
|
|
||||||
to.putFloat(getV(template, vertex));
|
|
||||||
|
|
||||||
to.put(getR(template, vertex));
|
|
||||||
to.put(getG(template, vertex));
|
|
||||||
to.put(getB(template, vertex));
|
|
||||||
to.put(getA(template, vertex));
|
|
||||||
|
|
||||||
int light = getLight(template, vertex);
|
|
||||||
|
|
||||||
byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4);
|
|
||||||
byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4);
|
|
||||||
|
|
||||||
to.put(block);
|
|
||||||
to.put(sky);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void deleteInternal() {
|
|
||||||
super.deleteInternal();
|
|
||||||
ebo.delete();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +1,23 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.core.IndexedModel;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
|
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
|
||||||
import com.jozufozu.flywheel.backend.light.GridAlignedBB;
|
import com.jozufozu.flywheel.backend.light.GridAlignedBB;
|
||||||
|
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
|
@ -25,6 +32,7 @@ import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||||
import net.minecraft.client.renderer.BlockModelShapes;
|
import net.minecraft.client.renderer.BlockModelShapes;
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
import net.minecraft.client.renderer.BufferBuilder;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.RenderTypeLookup;
|
import net.minecraft.client.renderer.RenderTypeLookup;
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
@ -40,17 +48,21 @@ import net.minecraftforge.client.ForgeHooksClient;
|
||||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||||
|
|
||||||
public class RenderedContraption {
|
public class RenderedContraption {
|
||||||
private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors());
|
public static final VertexFormat FORMAT = VertexFormat.builder()
|
||||||
private static final BlockModelShapes BLOCK_MODELS = Minecraft.getInstance().getModelManager().getBlockModelShapes();
|
.addAttributes(ContraptionAttributes.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
public Contraption contraption;
|
private static final BlockModelRenderer MODEL_RENDERER = new BlockModelRenderer(Minecraft.getInstance().getBlockColors());
|
||||||
private final ContraptionLighter<?> lighter;
|
private static final BlockModelShapes BLOCK_MODELS = Minecraft.getInstance().getModelManager().getBlockModelShapes();
|
||||||
public final ContraptionKineticRenderer kinetics;
|
|
||||||
public final PlacementSimulationWorld renderWorld;
|
|
||||||
|
|
||||||
private final Map<RenderType, ContraptionModel> renderLayers = new HashMap<>();
|
public Contraption contraption;
|
||||||
|
private final ContraptionLighter<?> lighter;
|
||||||
|
public final ContraptionKineticRenderer kinetics;
|
||||||
|
public final PlacementSimulationWorld renderWorld;
|
||||||
|
|
||||||
private Matrix4f model;
|
private final Map<RenderType, IndexedModel> renderLayers = new HashMap<>();
|
||||||
|
|
||||||
|
private Matrix4f model;
|
||||||
private AxisAlignedBB lightBox;
|
private AxisAlignedBB lightBox;
|
||||||
|
|
||||||
public RenderedContraption(World world, Contraption contraption) {
|
public RenderedContraption(World world, Contraption contraption) {
|
||||||
|
@ -79,7 +91,7 @@ public class RenderedContraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doRenderLayer(RenderType layer, ContraptionProgram shader) {
|
public void doRenderLayer(RenderType layer, ContraptionProgram shader) {
|
||||||
ContraptionModel structure = renderLayers.get(layer);
|
IndexedModel structure = renderLayers.get(layer);
|
||||||
if (structure != null) {
|
if (structure != null) {
|
||||||
setup(shader);
|
setup(shader);
|
||||||
structure.render();
|
structure.render();
|
||||||
|
@ -120,9 +132,9 @@ public class RenderedContraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
void invalidate() {
|
void invalidate() {
|
||||||
for (ContraptionModel buffer : renderLayers.values()) {
|
for (IndexedModel buffer : renderLayers.values()) {
|
||||||
buffer.delete();
|
buffer.delete();
|
||||||
}
|
}
|
||||||
renderLayers.clear();
|
renderLayers.clear();
|
||||||
|
|
||||||
lighter.lightVolume.delete();
|
lighter.lightVolume.delete();
|
||||||
|
@ -131,17 +143,18 @@ public class RenderedContraption {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildLayers() {
|
private void buildLayers() {
|
||||||
for (ContraptionModel buffer : renderLayers.values()) {
|
for (IndexedModel buffer : renderLayers.values()) {
|
||||||
buffer.delete();
|
buffer.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderLayers.clear();
|
renderLayers.clear();
|
||||||
|
|
||||||
List<RenderType> blockLayers = RenderType.getBlockLayers();
|
List<RenderType> blockLayers = RenderType.getBlockLayers();
|
||||||
|
|
||||||
for (RenderType layer : blockLayers) {
|
for (RenderType layer : blockLayers) {
|
||||||
renderLayers.put(layer, buildStructureModel(renderWorld, contraption, layer));
|
IndexedModel layerModel = buildStructureModel(renderWorld, contraption, layer);
|
||||||
}
|
if (layerModel != null) renderLayers.put(layer, layerModel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildInstancedTiles() {
|
private void buildInstancedTiles() {
|
||||||
|
@ -153,29 +166,67 @@ public class RenderedContraption {
|
||||||
BlockPos pos = te.getPos();
|
BlockPos pos = te.getPos();
|
||||||
te.setLocation(renderWorld, pos);
|
te.setLocation(renderWorld, pos);
|
||||||
kinetics.add(te);
|
kinetics.add(te);
|
||||||
te.setLocation(world, pos);
|
te.setLocation(world, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildActors() {
|
private void buildActors() {
|
||||||
contraption.getActors().forEach(kinetics::createActor);
|
contraption.getActors().forEach(kinetics::createActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
|
@Nullable
|
||||||
BufferBuilder builder = buildStructure(renderWorld, c, layer);
|
private static IndexedModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
|
||||||
return new ContraptionModel(builder);
|
BufferBuilderReader reader = new BufferBuilderReader(buildStructure(renderWorld, c, layer));
|
||||||
}
|
|
||||||
|
|
||||||
private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) {
|
int vertexCount = reader.getVertexCount();
|
||||||
PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world);
|
if (vertexCount == 0) return null;
|
||||||
|
|
||||||
renderWorld.setTileEntities(c.presentTileEntities.values());
|
VertexFormat format = FORMAT;
|
||||||
|
|
||||||
for (Template.BlockInfo info : c.getBlocks()
|
ByteBuffer to = ByteBuffer.allocate(format.getStride() * vertexCount);
|
||||||
.values())
|
to.order(ByteOrder.nativeOrder());
|
||||||
// Skip individual lighting updates to prevent lag with large contraptions
|
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
to.putFloat(reader.getX(i));
|
||||||
|
to.putFloat(reader.getY(i));
|
||||||
|
to.putFloat(reader.getZ(i));
|
||||||
|
|
||||||
|
to.put(reader.getNX(i));
|
||||||
|
to.put(reader.getNY(i));
|
||||||
|
to.put(reader.getNZ(i));
|
||||||
|
|
||||||
|
to.putFloat(reader.getU(i));
|
||||||
|
to.putFloat(reader.getV(i));
|
||||||
|
|
||||||
|
to.put(reader.getR(i));
|
||||||
|
to.put(reader.getG(i));
|
||||||
|
to.put(reader.getB(i));
|
||||||
|
to.put(reader.getA(i));
|
||||||
|
|
||||||
|
int light = reader.getLight(i);
|
||||||
|
|
||||||
|
byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4);
|
||||||
|
byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4);
|
||||||
|
|
||||||
|
to.put(block);
|
||||||
|
to.put(sky);
|
||||||
|
}
|
||||||
|
|
||||||
|
to.rewind();
|
||||||
|
|
||||||
|
return new IndexedModel(format, to, vertexCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) {
|
||||||
|
PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world);
|
||||||
|
|
||||||
|
renderWorld.setTileEntities(c.presentTileEntities.values());
|
||||||
|
|
||||||
|
for (Template.BlockInfo info : c.getBlocks()
|
||||||
|
.values())
|
||||||
|
// Skip individual lighting updates to prevent lag with large contraptions
|
||||||
renderWorld.setBlockState(info.pos, info.state, 128);
|
renderWorld.setBlockState(info.pos, info.state, 128);
|
||||||
|
|
||||||
renderWorld.updateLightSources();
|
renderWorld.updateLightSources();
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package com.simibubi.create.foundation.render;
|
package com.simibubi.create.foundation.render;
|
||||||
|
|
||||||
import java.nio.Buffer;
|
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher;
|
||||||
|
@ -26,12 +24,9 @@ import net.minecraft.world.LightType;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.client.model.pipeline.LightUtil;
|
import net.minecraftforge.client.model.pipeline.LightUtil;
|
||||||
|
|
||||||
public class SuperByteBuffer extends TemplateBuffer {
|
public class SuperByteBuffer {
|
||||||
|
|
||||||
public interface IVertexLighter {
|
|
||||||
public int getPackedLight(float x, float y, float z);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private final BufferBuilderReader template;
|
||||||
// Vertex Position
|
// Vertex Position
|
||||||
private MatrixStack transforms;
|
private MatrixStack transforms;
|
||||||
|
|
||||||
|
@ -49,7 +44,7 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
private int r, g, b, a;
|
private int r, g, b, a;
|
||||||
|
|
||||||
public SuperByteBuffer(BufferBuilder buf) {
|
public SuperByteBuffer(BufferBuilder buf) {
|
||||||
super(buf);
|
template = new BufferBuilderReader(buf);
|
||||||
transforms = new MatrixStack();
|
transforms = new MatrixStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,22 +65,20 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
Vector4f lightPos = new Vector4f();
|
Vector4f lightPos = new Vector4f();
|
||||||
|
|
||||||
public void renderInto(MatrixStack input, IVertexBuilder builder) {
|
public void renderInto(MatrixStack input, IVertexBuilder builder) {
|
||||||
ByteBuffer buffer = template;
|
if (isEmpty())
|
||||||
if (((Buffer) buffer).limit() == 0)
|
|
||||||
return;
|
return;
|
||||||
((Buffer) buffer).rewind();
|
|
||||||
|
|
||||||
Matrix3f normalMat = transforms.peek()
|
Matrix3f normalMat = transforms.peek()
|
||||||
.getNormal()
|
.getNormal()
|
||||||
.copy();
|
.copy();
|
||||||
// normalMat.multiply(transforms.peek().getNormal());
|
// normalMat.multiply(transforms.peek().getNormal());
|
||||||
|
|
||||||
Matrix4f modelMat = input.peek()
|
Matrix4f modelMat = input.peek()
|
||||||
.getModel()
|
.getModel()
|
||||||
.copy();
|
.copy();
|
||||||
|
|
||||||
Matrix4f localTransforms = transforms.peek()
|
Matrix4f localTransforms = transforms.peek()
|
||||||
.getModel();
|
.getModel();
|
||||||
modelMat.multiply(localTransforms);
|
modelMat.multiply(localTransforms);
|
||||||
|
|
||||||
if (shouldLight && lightTransform != null) {
|
if (shouldLight && lightTransform != null) {
|
||||||
|
@ -94,18 +87,18 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
float f = .5f;
|
float f = .5f;
|
||||||
int vertexCount = vertexCount(buffer);
|
int vertexCount = template.getVertexCount();
|
||||||
for (int i = 0; i < vertexCount; i++) {
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
float x = getX(buffer, i);
|
float x = template.getX(i);
|
||||||
float y = getY(buffer, i);
|
float y = template.getY(i);
|
||||||
float z = getZ(buffer, i);
|
float z = template.getZ(i);
|
||||||
byte r = getR(buffer, i);
|
byte r = template.getR(i);
|
||||||
byte g = getG(buffer, i);
|
byte g = template.getG(i);
|
||||||
byte b = getB(buffer, i);
|
byte b = template.getB(i);
|
||||||
byte a = getA(buffer, i);
|
byte a = template.getA(i);
|
||||||
float normalX = getNX(buffer, i) / 127f;
|
float normalX = template.getNX(i) / 127f;
|
||||||
float normalY = getNY(buffer, i) / 127f;
|
float normalY = template.getNY(i) / 127f;
|
||||||
float normalZ = getNZ(buffer, i) / 127f;
|
float normalZ = template.getNZ(i) / 127f;
|
||||||
|
|
||||||
float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ);
|
float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ);
|
||||||
normal.set(normalX, normalY, normalZ);
|
normal.set(normalX, normalY, normalZ);
|
||||||
|
@ -134,8 +127,8 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
builder.color(colorR, colorG, colorB, a);
|
builder.color(colorR, colorG, colorB, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
float u = getU(buffer, i);
|
float u = template.getU(i);
|
||||||
float v = getV(buffer, i);
|
float v = template.getV(i);
|
||||||
|
|
||||||
if (spriteShiftFunc != null) {
|
if (spriteShiftFunc != null) {
|
||||||
spriteShiftFunc.shift(builder, u, v);
|
spriteShiftFunc.shift(builder, u, v);
|
||||||
|
@ -156,7 +149,7 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
}
|
}
|
||||||
builder.light(light);
|
builder.light(light);
|
||||||
} else
|
} else
|
||||||
builder.light(getLight(buffer, i));
|
builder.light(template.getLight(i));
|
||||||
|
|
||||||
builder.normal(nx, ny, nz)
|
builder.normal(nx, ny, nz)
|
||||||
.endVertex();
|
.endVertex();
|
||||||
|
@ -297,7 +290,7 @@ public class SuperByteBuffer extends TemplateBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return ((Buffer) template).limit() == 0;
|
return template.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
package com.simibubi.create.foundation.render;
|
|
||||||
|
|
||||||
import java.nio.Buffer;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
import com.mojang.datafixers.util.Pair;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.BufferBuilder;
|
|
||||||
|
|
||||||
public class TemplateBuffer {
|
|
||||||
protected ByteBuffer template;
|
|
||||||
protected int formatSize;
|
|
||||||
protected int vertexCount;
|
|
||||||
|
|
||||||
public TemplateBuffer() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public TemplateBuffer(BufferBuilder buf) {
|
|
||||||
Pair<BufferBuilder.DrawState, ByteBuffer> state = buf.popData();
|
|
||||||
ByteBuffer rendered = state.getSecond();
|
|
||||||
rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers
|
|
||||||
|
|
||||||
formatSize = buf.getVertexFormat()
|
|
||||||
.getSize();
|
|
||||||
vertexCount = state.getFirst()
|
|
||||||
.getCount();
|
|
||||||
int size = vertexCount * formatSize;
|
|
||||||
|
|
||||||
template = ByteBuffer.allocate(size);
|
|
||||||
template.order(rendered.order());
|
|
||||||
((Buffer) template).limit(((Buffer) rendered).limit());
|
|
||||||
template.put(rendered);
|
|
||||||
((Buffer) template).rewind();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return ((Buffer) template).limit() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int vertexCount(ByteBuffer buffer) {
|
|
||||||
return ((Buffer) buffer).limit() / formatSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getBufferPosition(int vertexIndex) {
|
|
||||||
return vertexIndex * formatSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 int getLight(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.getInt(getBufferPosition(index) + 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getNX(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 28);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getNY(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 29);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected byte getNZ(ByteBuffer buffer, int index) {
|
|
||||||
return buffer.get(getBufferPosition(index) + 30);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue