Finally safe vertex formats

- true to false for Pepper
 - IBufferedModel -> BufferedModel
 - VertexFormat -> BufferLayout
 - Use ImmutableList in BufferLayout
 - LayoutItem naming consistency
 - Try to reduce usage of raw BufferLayouts
 - Move vertex interfaces to api package
 - #createWriter and #createReader in VertexType
 - Some documentation
This commit is contained in:
Jozufozu 2021-12-22 02:45:45 -08:00
parent 42365def02
commit ede2ba8776
50 changed files with 599 additions and 433 deletions

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.api.struct; package com.jozufozu.flywheel.api.struct;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.core.layout.BufferLayout;
/** /**
* A StructType contains metadata for a specific instance struct that Flywheel can interface with. * A StructType contains metadata for a specific instance struct that Flywheel can interface with.
@ -9,13 +9,13 @@ import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
public interface StructType<S> { public interface StructType<S> {
/** /**
* @return A new, zeroed instance of the struct. * @return A new, zeroed instance of S.
*/ */
S create(); S create();
/** /**
* @return The format descriptor of the struct type. * @return The layout of S when buffered.
*/ */
VertexFormat format(); BufferLayout getLayout();
} }

View file

@ -1,5 +1,14 @@
package com.jozufozu.flywheel.core.vertex; package com.jozufozu.flywheel.api.vertex;
/**
* A read only view of a vertex buffer.
*
* <p>
* VertexList assumes nothing about the layout of the vertices. Implementations should feel free to return constants
* for values that are unused in their layout.
* </p>
* TODO: more flexible elements?
*/
public interface VertexList { public interface VertexList {
float getX(int index); float getX(int index);

View file

@ -0,0 +1,42 @@
package com.jozufozu.flywheel.api.vertex;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.core.layout.BufferLayout;
/**
* A vertex type containing metadata about a specific vertex layout.
*/
public interface VertexType {
/**
* The layout of this type of vertex when buffered.
*/
BufferLayout getLayout();
/**
* Create a writer backed by the given ByteBuffer.
*
* <p>
* Implementors are encouraged to override the return type for ergonomics.
* </p>
*/
VertexWriter createWriter(ByteBuffer buffer);
/**
* Create a view of the given ByteBuffer as if it were already filled with vertices.
*
* <p>
* Implementors are encouraged to override the return type for ergonomics.
* </p>
*/
VertexList createReader(ByteBuffer buffer, int vertexCount);
default int getStride() {
return getLayout().getStride();
}
default int byteOffset(int vertexIndex) {
return getStride() * vertexIndex;
}
}

View file

@ -0,0 +1,15 @@
package com.jozufozu.flywheel.api.vertex;
public interface VertexWriter {
void writeVertex(VertexList list, int index);
void seekToVertex(int vertex);
VertexList intoReader();
default void writeVertexList(VertexList list) {
for (int i = 0; i < list.getVertexCount(); i++) {
this.writeVertex(list, i);
}
}
}

View file

@ -1,5 +1,5 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.backend.gl.attrib; package com.jozufozu.flywheel.api.vertex;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;

View file

@ -102,7 +102,7 @@ public class Backend {
} }
materialRegistry.put(name, spec); materialRegistry.put(name, spec);
log.debug("registered material '" + name + "' with instance size " + spec.format().getStride()); log.debug("registered material '" + name + "' with instance size " + spec.getLayout().getStride());
return spec; return spec;
} }

View file

@ -1,21 +0,0 @@
package com.jozufozu.flywheel.backend.gl.attrib;
import com.jozufozu.flywheel.backend.gl.GlNumericType;
public class CommonAttributes {
public static final VertexAttribSpec VEC4 = new VertexAttribSpec(GlNumericType.FLOAT, 4);
public static final VertexAttribSpec VEC3 = new VertexAttribSpec(GlNumericType.FLOAT, 3);
public static final VertexAttribSpec VEC2 = new VertexAttribSpec(GlNumericType.FLOAT, 2);
public static final VertexAttribSpec FLOAT = new VertexAttribSpec(GlNumericType.FLOAT, 1);
public static final VertexAttribSpec QUATERNION = new VertexAttribSpec(GlNumericType.FLOAT, 4);
public static final VertexAttribSpec NORMAL = new VertexAttribSpec(GlNumericType.BYTE, 3, true);
public static final VertexAttribSpec UV = new VertexAttribSpec(GlNumericType.FLOAT, 2);
public static final VertexAttribSpec RGBA = new VertexAttribSpec(GlNumericType.UBYTE, 4, true);
public static final VertexAttribSpec RGB = new VertexAttribSpec(GlNumericType.UBYTE, 3, true);
public static final VertexAttribSpec LIGHT = new VertexAttribSpec(GlNumericType.UBYTE, 2, true);
public static final VertexAttribSpec NORMALIZED_BYTE = new VertexAttribSpec(GlNumericType.BYTE, 1, true);
}

View file

@ -1,61 +0,0 @@
package com.jozufozu.flywheel.backend.gl.attrib;
import java.util.ArrayList;
import java.util.Collections;
public class VertexFormat {
private final ArrayList<IAttribSpec> allAttributes;
private final int numAttributes;
private final int stride;
public VertexFormat(ArrayList<IAttribSpec> allAttributes) {
this.allAttributes = allAttributes;
int numAttributes = 0, stride = 0;
for (IAttribSpec spec : allAttributes) {
numAttributes += spec.getAttributeCount();
stride += spec.getSize();
}
this.numAttributes = numAttributes;
this.stride = stride;
}
public int getAttributeCount() {
return numAttributes;
}
public int getStride() {
return stride;
}
public void vertexAttribPointers(int index) {
int offset = 0;
for (IAttribSpec spec : this.allAttributes) {
spec.vertexAttribPointer(stride, index, offset);
index += spec.getAttributeCount();
offset += spec.getSize();
}
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private final ArrayList<IAttribSpec> allAttributes = new ArrayList<>();
public Builder() {
}
public Builder addAttributes(IAttribSpec... attributes) {
Collections.addAll(allAttributes, attributes);
return this;
}
public VertexFormat build() {
return new VertexFormat(allAttributes);
}
}
}

View file

@ -11,14 +11,14 @@ import com.jozufozu.flywheel.core.model.Model;
public abstract class AbstractInstancer<D extends InstanceData> implements Instancer<D> { public abstract class AbstractInstancer<D extends InstanceData> implements Instancer<D> {
protected final Supplier<D> type; protected final Supplier<D> factory;
protected final Model modelData; protected final Model modelData;
protected final ArrayList<D> data = new ArrayList<>(); protected final ArrayList<D> data = new ArrayList<>();
protected boolean anyToRemove; protected boolean anyToRemove;
protected AbstractInstancer(Supplier<D> type, Model modelData) { protected AbstractInstancer(Supplier<D> factory, Model modelData) {
this.type = type; this.factory = factory;
this.modelData = modelData; this.modelData = modelData;
} }
@ -27,7 +27,7 @@ public abstract class AbstractInstancer<D extends InstanceData> implements Insta
*/ */
@Override @Override
public D createInstance() { public D createInstance() {
return _add(type.get()); return _add(factory.get());
} }
/** /**

View file

@ -1,21 +1,18 @@
package com.jozufozu.flywheel.backend.instancing.instancing; package com.jozufozu.flywheel.backend.instancing.instancing;
import java.util.BitSet;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.InstanceData;
import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
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.core.layout.BufferLayout;
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.jozufozu.flywheel.backend.gl.error.GlError; import com.jozufozu.flywheel.backend.gl.error.GlError;
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer; import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
import com.jozufozu.flywheel.backend.model.IBufferedModel; import com.jozufozu.flywheel.backend.model.BufferedModel;
import com.jozufozu.flywheel.backend.model.ModelAllocator; import com.jozufozu.flywheel.backend.model.ModelAllocator;
import com.jozufozu.flywheel.core.model.Model; import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.util.AttribUtil; import com.jozufozu.flywheel.util.AttribUtil;
@ -23,10 +20,10 @@ import com.jozufozu.flywheel.util.AttribUtil;
public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> { public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
private final ModelAllocator modelAllocator; private final ModelAllocator modelAllocator;
private final VertexFormat instanceFormat; private final BufferLayout instanceFormat;
private final Instanced<D> instancedType; private final Instanced<D> instancedType;
private IBufferedModel model; private BufferedModel model;
private GlVertexArray vao; private GlVertexArray vao;
private GlBuffer instanceVBO; private GlBuffer instanceVBO;
private int glBufferSize = -1; private int glBufferSize = -1;
@ -39,7 +36,7 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
public GPUInstancer(Instanced<D> type, Model model, ModelAllocator modelAllocator) { public GPUInstancer(Instanced<D> type, Model model, ModelAllocator modelAllocator) {
super(type::create, model); super(type::create, model);
this.modelAllocator = modelAllocator; this.modelAllocator = modelAllocator;
this.instanceFormat = type.format(); this.instanceFormat = type.getLayout();
instancedType = type; instancedType = type;
} }

View file

@ -1,90 +1,41 @@
package com.jozufozu.flywheel.backend.model; package com.jozufozu.flywheel.backend.model;
import static org.lwjgl.opengl.GL11.glDrawArrays; import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.api.vertex.VertexType;
import org.lwjgl.opengl.GL31; public interface BufferedModel {
import com.jozufozu.flywheel.Flywheel; VertexType getType();
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
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 com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.util.AttribUtil;
public class BufferedModel implements IBufferedModel { int getVertexCount();
protected final Model model;
protected final GlPrimitive primitiveMode;
protected GlBuffer vbo;
protected boolean deleted;
public BufferedModel(GlPrimitive primitiveMode, Model model) {
this.model = model;
this.primitiveMode = primitiveMode;
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
vbo.bind();
// allocate the buffer on the gpu
vbo.alloc(model.size());
// mirror it in system memory so we can write to it, and upload our model.
try (MappedBuffer buffer = vbo.getBuffer(0, model.size())) {
model.getType().copyInto(buffer.unwrap(), model.getReader());
} catch (Exception e) {
Flywheel.log.error(String.format("Error uploading model '%s':", model.name()), e);
}
vbo.unbind();
}
public boolean isDeleted() {
return deleted;
}
public VertexFormat getFormat() {
return model.format();
}
public int getVertexCount() {
return model.vertexCount();
}
/** /**
* The VBO/VAO should be bound externally. * The VBO/VAO should be bound externally.
*/ */
public void setupState() { void setupState();
vbo.bind();
AttribUtil.enableArrays(getAttributeCount());
getFormat().vertexAttribPointers(0);
}
public void clearState() { void clearState();
AttribUtil.disableArrays(getAttributeCount());
vbo.unbind();
}
public void drawCall() { void drawCall();
glDrawArrays(primitiveMode.glEnum, 0, getVertexCount());
}
/** /**
* Draws many instances of this model, assuming the appropriate state is already bound. * Draws many instances of this model, assuming the appropriate state is already bound.
*/ */
public void drawInstances(int instanceCount) { void drawInstances(int instanceCount);
if (!valid()) return;
GL31.glDrawArraysInstanced(primitiveMode.glEnum, 0, getVertexCount(), instanceCount); boolean isDeleted();
void delete();
default BufferLayout getFormat() {
return getType().getLayout();
} }
public void delete() { default boolean valid() {
if (deleted) return; return getVertexCount() > 0 && !isDeleted();
}
deleted = true; default int getAttributeCount() {
vbo.delete(); return getFormat().getAttributeCount();
} }
} }

View file

@ -1,36 +0,0 @@
package com.jozufozu.flywheel.backend.model;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
public interface IBufferedModel {
VertexFormat getFormat();
int getVertexCount();
/**
* The VBO/VAO should be bound externally.
*/
void setupState();
void clearState();
void drawCall();
/**
* Draws many instances of this model, assuming the appropriate state is already bound.
*/
void drawInstances(int instanceCount);
boolean isDeleted();
void delete();
default boolean valid() {
return getVertexCount() > 0 && !isDeleted();
}
default int getAttributeCount() {
return getFormat().getAttributeCount();
}
}

View file

@ -7,7 +7,7 @@ public class ImmediateAllocator implements ModelAllocator {
public static final ImmediateAllocator INSTANCE = new ImmediateAllocator(); public static final ImmediateAllocator INSTANCE = new ImmediateAllocator();
@Override @Override
public IBufferedModel alloc(Model model, Callback allocationCallback) { public BufferedModel alloc(Model model, Callback allocationCallback) {
IndexedModel out = new IndexedModel(model); IndexedModel out = new IndexedModel(model);
allocationCallback.onAlloc(out); allocationCallback.onAlloc(out);
return out; return out;

View file

@ -11,7 +11,7 @@ import com.jozufozu.flywheel.core.model.Model;
* *
* <br><em>This should be favored over a normal BufferedModel.</em> * <br><em>This should be favored over a normal BufferedModel.</em>
*/ */
public class IndexedModel extends BufferedModel { public class IndexedModel extends VBOModel {
protected ElementBuffer ebo; protected ElementBuffer ebo;

View file

@ -9,10 +9,10 @@ public interface ModelAllocator {
* @param model The model to allocate. * @param model The model to allocate.
* @return A handle to the allocated model. * @return A handle to the allocated model.
*/ */
IBufferedModel alloc(Model model, Callback allocationCallback); BufferedModel alloc(Model model, Callback allocationCallback);
@FunctionalInterface @FunctionalInterface
interface Callback { interface Callback {
void onAlloc(IBufferedModel arenaModel); void onAlloc(BufferedModel arenaModel);
} }
} }

View file

@ -1,6 +1,5 @@
package com.jozufozu.flywheel.backend.model; package com.jozufozu.flywheel.backend.model;
import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -8,13 +7,13 @@ import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.gl.GlPrimitive; import com.jozufozu.flywheel.backend.gl.GlPrimitive;
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.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.core.model.Model; import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.core.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.api.vertex.VertexWriter;
import com.jozufozu.flywheel.util.AttribUtil; import com.jozufozu.flywheel.util.AttribUtil;
public class ModelPool implements ModelAllocator { public class ModelPool implements ModelAllocator {
@ -118,13 +117,13 @@ public class ModelPool implements ModelAllocator {
private void uploadAll() { private void uploadAll() {
try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) { try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) {
ByteBuffer buf = buffer.unwrap(); VertexWriter writer = vertexType.createWriter(buffer.unwrap());
int vertices = 0; int vertices = 0;
for (PooledModel model : models) { for (PooledModel model : models) {
model.first = vertices; model.first = vertices;
buffer(buf, model); buffer(writer, model);
vertices += model.getVertexCount(); vertices += model.getVertexCount();
} }
@ -136,9 +135,9 @@ public class ModelPool implements ModelAllocator {
private void uploadPending() { private void uploadPending() {
try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) { try (MappedBuffer buffer = vbo.getBuffer(0, bufferSize)) {
ByteBuffer buf = buffer.unwrap(); VertexWriter writer = vertexType.createWriter(buffer.unwrap());
for (PooledModel model : pendingUpload) { for (PooledModel model : pendingUpload) {
buffer(buf, model); buffer(writer, model);
} }
pendingUpload.clear(); pendingUpload.clear();
} catch (Exception e) { } catch (Exception e) {
@ -146,10 +145,9 @@ public class ModelPool implements ModelAllocator {
} }
} }
private void buffer(ByteBuffer buf, PooledModel model) { private void buffer(VertexWriter writer, PooledModel model) {
int pos = model.first * vertexType.getStride(); writer.seekToVertex(model.first);
buf.position(pos); writer.writeVertexList(model.model.getReader());
vertexType.copyInto(buf, model.model.getReader());
if (model.callback != null) model.callback.onAlloc(model); if (model.callback != null) model.callback.onAlloc(model);
} }
@ -161,7 +159,7 @@ public class ModelPool implements ModelAllocator {
vbo.delete(); vbo.delete();
} }
public class PooledModel implements IBufferedModel { public class PooledModel implements BufferedModel {
private final ElementBuffer ebo; private final ElementBuffer ebo;
private Callback callback; private Callback callback;
@ -178,8 +176,8 @@ public class ModelPool implements ModelAllocator {
} }
@Override @Override
public VertexFormat getFormat() { public VertexType getType() {
return model.format(); return ModelPool.this.vertexType;
} }
@Override @Override
@ -192,7 +190,7 @@ public class ModelPool implements ModelAllocator {
vbo.bind(); vbo.bind();
ebo.bind(); ebo.bind();
AttribUtil.enableArrays(getAttributeCount()); AttribUtil.enableArrays(getAttributeCount());
getFormat().vertexAttribPointers(0); ModelPool.this.vertexType.getLayout().vertexAttribPointers(0);
} }
@Override @Override

View file

@ -7,7 +7,7 @@ import com.jozufozu.flywheel.core.model.Model;
public class ModelRenderer { public class ModelRenderer {
protected Supplier<Model> modelSupplier; protected Supplier<Model> modelSupplier;
protected IBufferedModel model; protected BufferedModel model;
protected boolean initialized; protected boolean initialized;

View file

@ -0,0 +1,91 @@
package com.jozufozu.flywheel.backend.model;
import static org.lwjgl.opengl.GL11.glDrawArrays;
import org.lwjgl.opengl.GL31;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
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 com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.util.AttribUtil;
public class VBOModel implements BufferedModel {
protected final Model model;
protected final GlPrimitive primitiveMode;
protected GlBuffer vbo;
protected boolean deleted;
public VBOModel(GlPrimitive primitiveMode, Model model) {
this.model = model;
this.primitiveMode = primitiveMode;
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
vbo.bind();
// allocate the buffer on the gpu
vbo.alloc(model.size());
// mirror it in system memory so we can write to it, and upload our model.
try (MappedBuffer buffer = vbo.getBuffer(0, model.size())) {
model.writeInto(buffer.unwrap());
} catch (Exception e) {
Flywheel.log.error(String.format("Error uploading model '%s':", model.name()), e);
}
vbo.unbind();
}
public boolean isDeleted() {
return deleted;
}
@Override
public VertexType getType() {
return model.getType();
}
public int getVertexCount() {
return model.vertexCount();
}
/**
* The VBO/VAO should be bound externally.
*/
public void setupState() {
vbo.bind();
AttribUtil.enableArrays(getAttributeCount());
getFormat().vertexAttribPointers(0);
}
public void clearState() {
AttribUtil.disableArrays(getAttributeCount());
vbo.unbind();
}
public void drawCall() {
glDrawArrays(primitiveMode.glEnum, 0, getVertexCount());
}
/**
* Draws many instances of this model, assuming the appropriate state is already bound.
*/
public void drawInstances(int instanceCount) {
if (!valid()) return;
GL31.glDrawArraysInstanced(primitiveMode.glEnum, 0, getVertexCount(), instanceCount);
}
public void delete() {
if (deleted) return;
deleted = true;
vbo.delete();
}
}

View file

@ -2,20 +2,17 @@ package com.jozufozu.flywheel.backend.struct;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
public abstract class BufferWriter<S> implements StructWriter<S> { public abstract class BufferWriter<S> implements StructWriter<S> {
protected final VecBuffer backingBuffer; protected final VecBuffer backingBuffer;
protected final VertexFormat format;
protected final int stride; protected final int stride;
protected BufferWriter(VecBuffer backingBuffer, StructType<S> vertexType) { protected BufferWriter(VecBuffer backingBuffer, StructType<S> vertexType) {
this.backingBuffer = backingBuffer; this.backingBuffer = backingBuffer;
this.format = vertexType.format(); this.stride = vertexType.getLayout().getStride();
this.stride = this.format.getStride();
} }
@Override @Override

View file

@ -2,17 +2,17 @@ package com.jozufozu.flywheel.core.hardcoded;
import java.util.List; import java.util.List;
import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.model.Model; import com.jozufozu.flywheel.core.model.Model;
import com.jozufozu.flywheel.core.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertexListUnsafe; import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriter;
import com.mojang.blaze3d.platform.MemoryTracker; import com.mojang.blaze3d.platform.MemoryTracker;
public class ModelPart implements Model { public class ModelPart implements Model {
private final int vertices; private final int vertices;
private final String name; private final String name;
private final PosTexNormalVertexListUnsafe reader; private final VertexList reader;
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) { public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) {
this.name = name; this.name = name;
@ -25,7 +25,7 @@ public class ModelPart implements Model {
this.vertices = vertices; this.vertices = vertices;
} }
PosTexNormalWriter writer = new PosTexNormalWriter(MemoryTracker.create(size())); PosTexNormalWriterUnsafe writer = Formats.POS_TEX_NORMAL.createWriter(MemoryTracker.create(size()));
for (PartBuilder.CuboidBuilder cuboid : cuboids) { for (PartBuilder.CuboidBuilder cuboid : cuboids) {
cuboid.buffer(writer); cuboid.buffer(writer);
} }

View file

@ -5,7 +5,7 @@ import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriter; import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
import com.mojang.math.Matrix3f; import com.mojang.math.Matrix3f;
import com.mojang.math.Quaternion; import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
@ -160,7 +160,7 @@ public class PartBuilder {
return visibleFaces.size() * 4; return visibleFaces.size() * 4;
} }
public void buffer(PosTexNormalWriter buffer) { public void buffer(PosTexNormalWriterUnsafe buffer) {
float sizeX = posX2 - posX1; float sizeX = posX2 - posX1;
float sizeY = posY2 - posY1; float sizeY = posY2 - posY1;
@ -235,7 +235,7 @@ public class PartBuilder {
} }
} }
public void quad(PosTexNormalWriter buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) { public void quad(PosTexNormalWriterUnsafe buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) {
buffer.putVertex(vertices[0].x(), vertices[0].y(), vertices[0].z(), normal.x(), normal.y(), normal.z(), maxU, minV); buffer.putVertex(vertices[0].x(), vertices[0].y(), vertices[0].z(), normal.x(), normal.y(), normal.z(), maxU, minV);
buffer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), normal.x(), normal.y(), normal.z(), minU, minV); buffer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), normal.x(), normal.y(), normal.z(), minU, minV);
buffer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), normal.x(), normal.y(), normal.z(), minU, maxV); buffer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), normal.x(), normal.y(), normal.z(), minU, maxV);

View file

@ -0,0 +1,6 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core.hardcoded;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;

View file

@ -0,0 +1,74 @@
package com.jozufozu.flywheel.core.layout;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.jozufozu.flywheel.api.vertex.VertexType;
/**
* Classic Vertex Format struct with a clever name.
*
* <p>
* Used for vertices and instance. Describes the layout of a datatype in a buffer object.
* </p>
*
* @see com.jozufozu.flywheel.api.struct.StructType
* @see VertexType
*/
public class BufferLayout {
private final List<LayoutItem> allAttributes;
private final int numAttributes;
private final int stride;
public BufferLayout(List<LayoutItem> allAttributes) {
this.allAttributes = allAttributes;
int numAttributes = 0, stride = 0;
for (LayoutItem spec : allAttributes) {
numAttributes += spec.getAttributeCount();
stride += spec.getSize();
}
this.numAttributes = numAttributes;
this.stride = stride;
}
public int getAttributeCount() {
return numAttributes;
}
public int getStride() {
return stride;
}
public void vertexAttribPointers(int index) {
int offset = 0;
for (LayoutItem spec : this.allAttributes) {
spec.vertexAttribPointer(stride, index, offset);
index += spec.getAttributeCount();
offset += spec.getSize();
}
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private final ImmutableList.Builder<LayoutItem> allItems;
public Builder() {
allItems = ImmutableList.builder();
}
public Builder addItems(LayoutItem... attributes) {
allItems.add(attributes);
return this;
}
public BufferLayout build() {
return new BufferLayout(allItems.build());
}
}
}

View file

@ -0,0 +1,24 @@
package com.jozufozu.flywheel.core.layout;
import com.jozufozu.flywheel.backend.gl.GlNumericType;
public class CommonItems {
public static final PrimitiveItem VEC4 = new PrimitiveItem(GlNumericType.FLOAT, 4);
public static final PrimitiveItem VEC3 = new PrimitiveItem(GlNumericType.FLOAT, 3);
public static final PrimitiveItem VEC2 = new PrimitiveItem(GlNumericType.FLOAT, 2);
public static final PrimitiveItem FLOAT = new PrimitiveItem(GlNumericType.FLOAT, 1);
public static final PrimitiveItem QUATERNION = new PrimitiveItem(GlNumericType.FLOAT, 4);
public static final PrimitiveItem NORMAL = new PrimitiveItem(GlNumericType.BYTE, 3, true);
public static final PrimitiveItem UV = new PrimitiveItem(GlNumericType.FLOAT, 2);
public static final PrimitiveItem RGBA = new PrimitiveItem(GlNumericType.UBYTE, 4, true);
public static final PrimitiveItem RGB = new PrimitiveItem(GlNumericType.UBYTE, 3, true);
public static final PrimitiveItem LIGHT = new PrimitiveItem(GlNumericType.UBYTE, 2, true);
public static final PrimitiveItem LIGHT_SHORT = new PrimitiveItem(GlNumericType.USHORT, 2, true);
public static final PrimitiveItem NORMALIZED_BYTE = new PrimitiveItem(GlNumericType.BYTE, 1, true);
public static final LayoutItem PADDING_BYTE = new PaddingItem(1);
}

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.backend.gl.attrib; package com.jozufozu.flywheel.core.layout;
public interface IAttribSpec { public interface LayoutItem {
void vertexAttribPointer(int stride, int index, int offset); void vertexAttribPointer(int stride, int index, int offset);

View file

@ -1,10 +1,10 @@
package com.jozufozu.flywheel.backend.gl.attrib; package com.jozufozu.flywheel.core.layout;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import com.jozufozu.flywheel.backend.gl.GlNumericType; import com.jozufozu.flywheel.backend.gl.GlNumericType;
public enum MatrixAttributes implements IAttribSpec { public enum MatrixItems implements LayoutItem {
MAT3(3, 3), MAT3(3, 3),
MAT4(4, 4), MAT4(4, 4),
; ;
@ -12,7 +12,7 @@ public enum MatrixAttributes implements IAttribSpec {
private final int rows; private final int rows;
private final int cols; private final int cols;
MatrixAttributes(int rows, int cols) { MatrixItems(int rows, int cols) {
this.rows = rows; this.rows = rows;
this.cols = cols; this.cols = cols;
} }

View file

@ -0,0 +1,19 @@
package com.jozufozu.flywheel.core.layout;
record PaddingItem(int bytes) implements LayoutItem {
@Override
public void vertexAttribPointer(int stride, int index, int offset) {
}
@Override
public int getSize() {
return bytes;
}
@Override
public int getAttributeCount() {
return 0;
}
}

View file

@ -1,10 +1,10 @@
package com.jozufozu.flywheel.backend.gl.attrib; package com.jozufozu.flywheel.core.layout;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
import com.jozufozu.flywheel.backend.gl.GlNumericType; import com.jozufozu.flywheel.backend.gl.GlNumericType;
public class VertexAttribSpec implements IAttribSpec { public class PrimitiveItem implements LayoutItem {
private final GlNumericType type; private final GlNumericType type;
private final int count; private final int count;
@ -12,11 +12,11 @@ public class VertexAttribSpec implements IAttribSpec {
private final int attributeCount; private final int attributeCount;
private final boolean normalized; private final boolean normalized;
public VertexAttribSpec(GlNumericType type, int count) { public PrimitiveItem(GlNumericType type, int count) {
this(type, count, false); this(type, count, false);
} }
public VertexAttribSpec(GlNumericType type, int count, boolean normalized) { public PrimitiveItem(GlNumericType type, int count, boolean normalized) {
this.type = type; this.type = type;
this.count = count; this.count = count;
this.size = type.getByteWidth() * count; this.size = type.getByteWidth() * count;

View file

@ -0,0 +1,6 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core.layout;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;

View file

@ -6,9 +6,9 @@ import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter; import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter;
public abstract class UnsafeBasicWriter<D extends BasicData> extends UnsafeBufferWriter<D> { public abstract class BasicWriterUnsafe<D extends BasicData> extends UnsafeBufferWriter<D> {
public UnsafeBasicWriter(VecBuffer backingBuffer, StructType<D> vertexType) { public BasicWriterUnsafe(VecBuffer backingBuffer, StructType<D> vertexType) {
super(backingBuffer, vertexType); super(backingBuffer, vertexType);
} }

View file

@ -3,9 +3,9 @@ package com.jozufozu.flywheel.core.materials.model;
import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes; import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.backend.gl.attrib.MatrixAttributes; import com.jozufozu.flywheel.core.layout.MatrixItems;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Programs; import com.jozufozu.flywheel.core.Programs;
import com.jozufozu.flywheel.core.model.ModelTransformer; import com.jozufozu.flywheel.core.model.ModelTransformer;
@ -14,9 +14,9 @@ import net.minecraft.resources.ResourceLocation;
public class ModelType implements Instanced<ModelData>, Batched<ModelData> { public class ModelType implements Instanced<ModelData>, Batched<ModelData> {
public static final VertexFormat FORMAT = VertexFormat.builder() public static final BufferLayout FORMAT = BufferLayout.builder()
.addAttributes(CommonAttributes.LIGHT, CommonAttributes.RGBA) .addItems(CommonItems.LIGHT, CommonItems.RGBA)
.addAttributes(MatrixAttributes.MAT4, MatrixAttributes.MAT3) .addItems(MatrixItems.MAT4, MatrixItems.MAT3)
.build(); .build();
@Override @Override
@ -25,13 +25,13 @@ public class ModelType implements Instanced<ModelData>, Batched<ModelData> {
} }
@Override @Override
public VertexFormat format() { public BufferLayout getLayout() {
return FORMAT; return FORMAT;
} }
@Override @Override
public StructWriter<ModelData> getWriter(VecBuffer backing) { public StructWriter<ModelData> getWriter(VecBuffer backing) {
return new UnsafeModelWriter(backing, this); return new ModelWriterUnsafe(backing, this);
} }
@Override @Override

View file

@ -2,12 +2,12 @@ package com.jozufozu.flywheel.core.materials.model;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.materials.UnsafeBasicWriter; import com.jozufozu.flywheel.core.materials.BasicWriterUnsafe;
import com.jozufozu.flywheel.util.WriteUnsafe; import com.jozufozu.flywheel.util.WriteUnsafe;
public class UnsafeModelWriter extends UnsafeBasicWriter<ModelData> { public class ModelWriterUnsafe extends BasicWriterUnsafe<ModelData> {
public UnsafeModelWriter(VecBuffer backingBuffer, StructType<ModelData> vertexType) { public ModelWriterUnsafe(VecBuffer backingBuffer, StructType<ModelData> vertexType) {
super(backingBuffer, vertexType); super(backingBuffer, vertexType);
} }

View file

@ -3,8 +3,8 @@ package com.jozufozu.flywheel.core.materials.oriented;
import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.Batched;
import com.jozufozu.flywheel.api.struct.Instanced; import com.jozufozu.flywheel.api.struct.Instanced;
import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.api.struct.StructWriter;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes; import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.core.Programs; import com.jozufozu.flywheel.core.Programs;
import com.jozufozu.flywheel.core.model.ModelTransformer; import com.jozufozu.flywheel.core.model.ModelTransformer;
@ -14,9 +14,9 @@ import net.minecraft.resources.ResourceLocation;
public class OrientedType implements Instanced<OrientedData>, Batched<OrientedData> { public class OrientedType implements Instanced<OrientedData>, Batched<OrientedData> {
public static final VertexFormat FORMAT = VertexFormat.builder() public static final BufferLayout FORMAT = BufferLayout.builder()
.addAttributes(CommonAttributes.LIGHT, CommonAttributes.RGBA) .addItems(CommonItems.LIGHT, CommonItems.RGBA)
.addAttributes(CommonAttributes.VEC3, CommonAttributes.VEC3, CommonAttributes.QUATERNION) .addItems(CommonItems.VEC3, CommonItems.VEC3, CommonItems.QUATERNION)
.build(); .build();
@Override @Override
@ -25,13 +25,13 @@ public class OrientedType implements Instanced<OrientedData>, Batched<OrientedDa
} }
@Override @Override
public VertexFormat format() { public BufferLayout getLayout() {
return FORMAT; return FORMAT;
} }
@Override @Override
public StructWriter<OrientedData> getWriter(VecBuffer backing) { public StructWriter<OrientedData> getWriter(VecBuffer backing) {
return new UnsafeOrientedWriter(backing, this); return new OrientedWriterUnsafe(backing, this);
} }
@Override @Override

View file

@ -4,10 +4,10 @@ import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.core.materials.UnsafeBasicWriter; import com.jozufozu.flywheel.core.materials.BasicWriterUnsafe;
public class UnsafeOrientedWriter extends UnsafeBasicWriter<OrientedData> { public class OrientedWriterUnsafe extends BasicWriterUnsafe<OrientedData> {
public UnsafeOrientedWriter(VecBuffer backingBuffer, StructType<OrientedData> vertexType) { public OrientedWriterUnsafe(VecBuffer backingBuffer, StructType<OrientedData> vertexType) {
super(backingBuffer, vertexType); super(backingBuffer, vertexType);
} }

View file

@ -1,7 +1,7 @@
package com.jozufozu.flywheel.core.model; package com.jozufozu.flywheel.core.model;
import com.jozufozu.flywheel.core.vertex.VertexList; import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.vertex.BlockVertexListUnsafe; import com.jozufozu.flywheel.api.vertex.VertexList;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -29,7 +29,7 @@ public class BlockModel implements Model {
} }
public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) { public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) {
reader = new BlockVertexListUnsafe(ModelUtil.getBufferBuilder(model, referenceState, ms)); reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilder(model, referenceState, ms));
name = referenceState.toString(); name = referenceState.toString();
} }

View file

@ -1,11 +1,12 @@
package com.jozufozu.flywheel.core.model; package com.jozufozu.flywheel.core.model;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import java.nio.ByteBuffer;
import com.jozufozu.flywheel.backend.model.ElementBuffer; import com.jozufozu.flywheel.backend.model.ElementBuffer;
import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.QuadConverter; import com.jozufozu.flywheel.core.QuadConverter;
import com.jozufozu.flywheel.core.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.core.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
/** /**
* A model that can be rendered by flywheel. * A model that can be rendered by flywheel.
@ -49,13 +50,6 @@ public interface Model {
return Formats.POS_TEX_NORMAL; return Formats.POS_TEX_NORMAL;
} }
/**
* @return The format of this model's vertices
*/
default VertexFormat format() {
return getType().getFormat();
}
/** /**
* Create an element buffer object that indexes the vertices of this model. * Create an element buffer object that indexes the vertices of this model.
* *
@ -75,7 +69,7 @@ public interface Model {
* The size in bytes that this model's data takes up. * The size in bytes that this model's data takes up.
*/ */
default int size() { default int size() {
return vertexCount() * format().getStride(); return getType().byteOffset(vertexCount());
} }
/** /**
@ -85,4 +79,8 @@ public interface Model {
default boolean empty() { default boolean empty() {
return vertexCount() == 0; return vertexCount() == 0;
} }
default void writeInto(ByteBuffer buffer) {
getType().createWriter(buffer).writeVertexList(getReader());
}
} }

View file

@ -1,6 +1,6 @@
package com.jozufozu.flywheel.core.model; package com.jozufozu.flywheel.core.model;
import com.jozufozu.flywheel.core.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.util.RenderMath; import com.jozufozu.flywheel.util.RenderMath;
import com.jozufozu.flywheel.util.transform.Transform; import com.jozufozu.flywheel.util.transform.Transform;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;

View file

@ -55,7 +55,7 @@ public class ModelUtil {
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK); builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder, blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder,
true, new Random(), 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE); false, new Random(), 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
builder.end(); builder.end();
return builder; return builder;
} }

View file

@ -3,9 +3,8 @@ package com.jozufozu.flywheel.core.model;
import java.util.Collection; import java.util.Collection;
import com.jozufozu.flywheel.core.Formats; import com.jozufozu.flywheel.core.Formats;
import com.jozufozu.flywheel.core.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.core.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.vertex.BlockVertexListUnsafe;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.BlockAndTintGetter;
@ -17,7 +16,7 @@ public class WorldModel implements Model {
private final String name; private final String name;
public WorldModel(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, String name) { public WorldModel(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks, String name) {
reader = new BlockVertexListUnsafe(ModelUtil.getBufferBuilderFromTemplate(renderWorld, layer, blocks)); reader = Formats.BLOCK.createReader(ModelUtil.getBufferBuilderFromTemplate(renderWorld, layer, blocks));
this.name = name; this.name = name;
} }

View file

@ -2,70 +2,49 @@ package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes; import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.util.RenderMath; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.client.renderer.LightTexture; import com.mojang.datafixers.util.Pair;
public class BlockVertex implements VertexType { public class BlockVertex implements VertexType {
public static final VertexFormat FORMAT = VertexFormat.builder() public static final BufferLayout FORMAT = BufferLayout.builder()
.addAttributes(CommonAttributes.VEC3, .addItems(CommonItems.VEC3,
CommonAttributes.UV, CommonItems.RGBA,
CommonAttributes.RGBA, CommonItems.UV,
CommonAttributes.LIGHT, CommonItems.LIGHT_SHORT,
CommonAttributes.NORMAL) CommonItems.NORMAL,
CommonItems.PADDING_BYTE)
.build(); .build();
@Override @Override
public VertexFormat getFormat() { public BufferLayout getLayout() {
return FORMAT; return FORMAT;
} }
@Override @Override
public void copyInto(ByteBuffer buffer, VertexList reader) { public BlockWriterUnsafe createWriter(ByteBuffer buffer) {
int stride = getStride(); return new BlockWriterUnsafe(this, buffer);
long addr = MemoryUtil.memAddress(buffer);
int vertexCount = reader.getVertexCount();
for (int i = 0; i < vertexCount; i++) {
float x = reader.getX(i);
float y = reader.getY(i);
float z = reader.getZ(i);
float xN = reader.getNX(i);
float yN = reader.getNY(i);
float zN = reader.getNZ(i);
float u = reader.getU(i);
float v = reader.getV(i);
byte r = reader.getR(i);
byte g = reader.getG(i);
byte b = reader.getB(i);
byte a = reader.getA(i);
int light = reader.getLight(i);
MemoryUtil.memPutFloat(addr, x);
MemoryUtil.memPutFloat(addr + 4, y);
MemoryUtil.memPutFloat(addr + 8, z);
MemoryUtil.memPutFloat(addr + 12, u);
MemoryUtil.memPutFloat(addr + 16, v);
MemoryUtil.memPutByte(addr + 20, r);
MemoryUtil.memPutByte(addr + 21, g);
MemoryUtil.memPutByte(addr + 22, b);
MemoryUtil.memPutByte(addr + 23, a);
MemoryUtil.memPutByte(addr + 24, (byte) (LightTexture.block(light) << 4));
MemoryUtil.memPutByte(addr + 25, (byte) (LightTexture.sky(light) << 4));
MemoryUtil.memPutByte(addr + 26, RenderMath.nb(xN));
MemoryUtil.memPutByte(addr + 27, RenderMath.nb(yN));
MemoryUtil.memPutByte(addr + 28, RenderMath.nb(zN));
addr += stride;
} }
@Override
public BlockVertexListUnsafe createReader(ByteBuffer buffer, int vertexCount) {
return new BlockVertexListUnsafe(buffer, vertexCount);
}
public VertexList createReader(BufferBuilder bufferBuilder) {
// TODO: try to avoid virtual model rendering
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
BufferBuilder.DrawState drawState = pair.getFirst();
if (drawState.format() != DefaultVertexFormat.BLOCK) {
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format());
}
return new BlockVertexListUnsafe(pair.getSecond(), drawState.vertexCount());
} }
} }

View file

@ -2,6 +2,7 @@ package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.util.RenderMath; import com.jozufozu.flywheel.util.RenderMath;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;

View file

@ -4,27 +4,23 @@ import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.util.RenderMath; import com.jozufozu.flywheel.util.RenderMath;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
public class BlockVertexListUnsafe implements VertexList { public class BlockVertexListUnsafe implements VertexList {
private final ByteBuffer buffer;
private final int vertexCount; private final int vertexCount;
private final int stride;
private final long base; private final long base;
public BlockVertexListUnsafe(BufferBuilder builder) { public BlockVertexListUnsafe(ByteBuffer buffer, int vertexCount) {
VertexFormat vertexFormat = builder.getVertexFormat(); this.buffer = buffer;
Pair<BufferBuilder.DrawState, ByteBuffer> data = builder.popNextBuffer(); this.base = MemoryUtil.memAddress(buffer);
this.base = MemoryUtil.memAddress(data.getSecond()); this.vertexCount = vertexCount;
this.vertexCount = data.getFirst().vertexCount();
this.stride = vertexFormat.getVertexSize();
} }
private long ptr(long index) { private long ptr(long index) {
return base + index * stride; return base + index * 32;
} }
@Override @Override

View file

@ -0,0 +1,57 @@
package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.util.RenderMath;
public class BlockWriterUnsafe extends VertexWriterUnsafe<BlockVertex> {
public BlockWriterUnsafe(BlockVertex type, ByteBuffer buffer) {
super(type, buffer);
}
@Override
public void writeVertex(VertexList list, int i) {
float x = list.getX(i);
float y = list.getY(i);
float z = list.getZ(i);
float xN = list.getNX(i);
float yN = list.getNY(i);
float zN = list.getNZ(i);
float u = list.getU(i);
float v = list.getV(i);
byte r = list.getR(i);
byte g = list.getG(i);
byte b = list.getB(i);
byte a = list.getA(i);
int light = list.getLight(i);
putVertex(x, y, z, u, v, r, g, b, a, light, xN, yN, zN);
}
public void putVertex(float x, float y, float z, float u, float v, byte r, byte g, byte b, byte a, int light, float nX, float nY, float nZ) {
MemoryUtil.memPutFloat(ptr, x);
MemoryUtil.memPutFloat(ptr + 4, y);
MemoryUtil.memPutFloat(ptr + 8, z);
MemoryUtil.memPutByte(ptr + 12, r);
MemoryUtil.memPutByte(ptr + 13, g);
MemoryUtil.memPutByte(ptr + 14, b);
MemoryUtil.memPutByte(ptr + 15, a);
MemoryUtil.memPutFloat(ptr + 16, u);
MemoryUtil.memPutFloat(ptr + 20, v);
MemoryUtil.memPutInt(ptr + 24, light);
MemoryUtil.memPutByte(ptr + 28, RenderMath.nb(nX));
MemoryUtil.memPutByte(ptr + 29, RenderMath.nb(nY));
MemoryUtil.memPutByte(ptr + 30, RenderMath.nb(nZ));
ptr += 32;
advance();
}
}

View file

@ -2,38 +2,28 @@ package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.layout.BufferLayout;
public class PosTexNormalVertex implements VertexType { public class PosTexNormalVertex implements VertexType {
public static final VertexFormat FORMAT = VertexFormat.builder() public static final BufferLayout FORMAT = BufferLayout.builder()
.addAttributes(CommonAttributes.VEC3, CommonAttributes.UV, CommonAttributes.NORMAL) .addItems(CommonItems.VEC3, CommonItems.UV, CommonItems.NORMAL)
.build(); .build();
@Override @Override
public VertexFormat getFormat() { public BufferLayout getLayout() {
return FORMAT; return FORMAT;
} }
@Override @Override
public void copyInto(ByteBuffer buffer, VertexList reader) { public PosTexNormalWriterUnsafe createWriter(ByteBuffer buffer) {
PosTexNormalWriter writer = new PosTexNormalWriter(buffer); return new PosTexNormalWriterUnsafe(this, buffer);
int vertexCount = reader.getVertexCount();
for (int i = 0; i < vertexCount; i++) {
float x = reader.getX(i);
float y = reader.getY(i);
float z = reader.getZ(i);
float u = reader.getU(i);
float v = reader.getV(i);
float xN = reader.getNX(i);
float yN = reader.getNY(i);
float zN = reader.getNZ(i);
writer.putVertex(x, y, z, xN, yN, zN, u, v);
} }
@Override
public PosTexNormalVertexListUnsafe createReader(ByteBuffer buffer, int vertexCount) {
return new PosTexNormalVertexListUnsafe(buffer, vertexCount);
} }
} }

View file

@ -4,6 +4,7 @@ import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.util.RenderMath; import com.jozufozu.flywheel.util.RenderMath;
public class PosTexNormalVertexListUnsafe implements VertexList { public class PosTexNormalVertexListUnsafe implements VertexList {

View file

@ -1,42 +0,0 @@
package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.RenderMath;
public class PosTexNormalWriter {
private final ByteBuffer buffer;
private long addr;
private int vertexCount;
public PosTexNormalWriter(ByteBuffer buffer) {
this.buffer = buffer;
addr = MemoryUtil.memAddress(buffer);
}
public void putVertex(float x, float y, float z, float nX, float nY, float nZ, float u, float v) {
MemoryUtil.memPutFloat(addr, x);
MemoryUtil.memPutFloat(addr + 4, y);
MemoryUtil.memPutFloat(addr + 8, z);
MemoryUtil.memPutFloat(addr + 12, u);
MemoryUtil.memPutFloat(addr + 16, v);
MemoryUtil.memPutByte(addr + 20, RenderMath.nb(nX));
MemoryUtil.memPutByte(addr + 21, RenderMath.nb(nY));
MemoryUtil.memPutByte(addr + 22, RenderMath.nb(nZ));
addr += 23;
vertexCount++;
}
public int getVertexCount() {
return vertexCount;
}
public PosTexNormalVertexListUnsafe intoReader() {
return new PosTexNormalVertexListUnsafe(buffer, vertexCount);
}
}

View file

@ -0,0 +1,45 @@
package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.util.RenderMath;
public class PosTexNormalWriterUnsafe extends VertexWriterUnsafe<PosTexNormalVertex> {
public PosTexNormalWriterUnsafe(PosTexNormalVertex type, ByteBuffer buffer) {
super(type, buffer);
}
@Override
public void writeVertex(VertexList list, int i) {
float x = list.getX(i);
float y = list.getY(i);
float z = list.getZ(i);
float u = list.getU(i);
float v = list.getV(i);
float xN = list.getNX(i);
float yN = list.getNY(i);
float zN = list.getNZ(i);
putVertex(x, y, z, xN, yN, zN, u, v);
}
public void putVertex(float x, float y, float z, float nX, float nY, float nZ, float u, float v) {
MemoryUtil.memPutFloat(ptr, x);
MemoryUtil.memPutFloat(ptr + 4, y);
MemoryUtil.memPutFloat(ptr + 8, z);
MemoryUtil.memPutFloat(ptr + 12, u);
MemoryUtil.memPutFloat(ptr + 16, v);
MemoryUtil.memPutByte(ptr + 20, RenderMath.nb(nX));
MemoryUtil.memPutByte(ptr + 21, RenderMath.nb(nY));
MemoryUtil.memPutByte(ptr + 22, RenderMath.nb(nZ));
ptr += 23;
advance();
}
}

View file

@ -1,16 +0,0 @@
package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
public interface VertexType {
VertexFormat getFormat();
void copyInto(ByteBuffer buffer, VertexList reader);
default int getStride() {
return getFormat().getStride();
}
}

View file

@ -0,0 +1,41 @@
package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.api.vertex.VertexWriter;
public abstract class VertexWriterUnsafe<V extends VertexType> implements VertexWriter {
public final V type;
protected final ByteBuffer buffer;
private int totalVertices;
private int writeVertex;
protected long ptr;
protected VertexWriterUnsafe(V type, ByteBuffer buffer) {
this.type = type;
this.buffer = buffer;
this.ptr = MemoryUtil.memAddress(buffer);
}
protected void advance() {
writeVertex++;
if (writeVertex > totalVertices) totalVertices = writeVertex;
}
@Override
public void seekToVertex(int vertex) {
buffer.position(type.byteOffset(vertex));
writeVertex = vertex;
ptr = MemoryUtil.memAddress(buffer);
}
@Override
public VertexList intoReader() {
return type.createReader(buffer, totalVertices);
}
}

View file

@ -0,0 +1,6 @@
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
package com.jozufozu.flywheel.core.vertex;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;