Vertex format refactor

- Use memCopy for instanced mesh buffering
- Remove VertexWriter
- Add VertexListProvider
- Add VertexListProviderRegistry to allow vanilla VertexFormats to
create VertexLists
- Add ReusableVertexList that allows setting the pointer and vertex
count
This commit is contained in:
PepperCode1 2022-08-09 11:25:26 -07:00
parent ed3aca8bfc
commit 6913a34443
37 changed files with 877 additions and 889 deletions

View file

@ -0,0 +1,11 @@
package com.jozufozu.flywheel.api.vertex;
public interface ReusableVertexList extends MutableVertexList {
long ptr();
void ptr(long ptr);
void shiftPtr(int vertices);
void setVertexCount(int vertexCount);
}

View file

@ -42,6 +42,37 @@ public interface VertexList {
float normalZ(int index); float normalZ(int index);
default void write(MutableVertexList dst, int srcIndex, int dstIndex) {
dst.x(dstIndex, x(srcIndex));
dst.y(dstIndex, y(srcIndex));
dst.z(dstIndex, z(srcIndex));
dst.r(dstIndex, r(srcIndex));
dst.g(dstIndex, g(srcIndex));
dst.b(dstIndex, b(srcIndex));
dst.a(dstIndex, a(srcIndex));
dst.u(dstIndex, u(srcIndex));
dst.v(dstIndex, v(srcIndex));
dst.overlay(dstIndex, overlay(srcIndex));
dst.light(dstIndex, light(srcIndex));
dst.normalX(dstIndex, normalX(srcIndex));
dst.normalY(dstIndex, normalY(srcIndex));
dst.normalZ(dstIndex, normalZ(srcIndex));
}
default void write(MutableVertexList dst, int srcStartIndex, int dstStartIndex, int vertexCount) {
for (int i = 0; i < vertexCount; i++) {
write(dst, srcStartIndex + i, dstStartIndex + i);
}
}
default void writeAll(MutableVertexList dst) {
write(dst, 0, 0, getVertexCount());
}
int getVertexCount(); int getVertexCount();
default boolean isEmpty() { default boolean isEmpty() {

View file

@ -0,0 +1,5 @@
package com.jozufozu.flywheel.api.vertex;
public interface VertexListProvider {
ReusableVertexList createVertexList();
}

View file

@ -1,38 +1,18 @@
package com.jozufozu.flywheel.api.vertex; package com.jozufozu.flywheel.api.vertex;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.BufferLayout;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;
/** /**
* A vertex type containing metadata about a specific vertex layout. * A vertex type containing metadata about a specific vertex layout.
*/ */
public interface VertexType { public interface VertexType extends VertexListProvider {
/** /**
* The layout of this type of vertex when buffered. * The layout of this type of vertex when buffered.
*/ */
BufferLayout getLayout(); 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);
FileResolution getLayoutShader(); FileResolution getLayoutShader();
default int getStride() { default int getStride() {

View file

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

View file

@ -68,6 +68,7 @@ public class BatchingEngine implements Engine {
@Override @Override
public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) { public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) {
// FIXME: properly support material stages // FIXME: properly support material stages
// This also breaks block outlines on batched block entities
if (stage != RenderStage.AFTER_FINAL_END_BATCH) { if (stage != RenderStage.AFTER_FINAL_END_BATCH) {
return; return;
} }

View file

@ -4,18 +4,24 @@ import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexListProvider;
import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry;
import com.mojang.blaze3d.platform.MemoryTracker; import com.mojang.blaze3d.platform.MemoryTracker;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
/** /**
* A byte buffer that can be used to draw vertices through multiple {@link MutableVertexListImpl}s. * A byte buffer that can be used to draw vertices through multiple {@link ReusableVertexList}s.
* *
* The number of vertices needs to be known ahead of time. * The number of vertices needs to be known ahead of time.
*/ */
public class DrawBuffer { public class DrawBuffer {
private final RenderType parent; private final RenderType parent;
private final VertexFormatInfo formatInfo; private final VertexFormat format;
private final int stride;
private final VertexListProvider provider;
private ByteBuffer backingBuffer; private ByteBuffer backingBuffer;
private int expectedVertices; private int expectedVertices;
@ -23,7 +29,9 @@ public class DrawBuffer {
public DrawBuffer(RenderType parent) { public DrawBuffer(RenderType parent) {
this.parent = parent; this.parent = parent;
formatInfo = new VertexFormatInfo(parent.format()); format = parent.format();
stride = format.getVertexSize();
provider = VertexListProviderRegistry.getOrInfer(format);
} }
/** /**
@ -39,9 +47,9 @@ public class DrawBuffer {
this.expectedVertices = vertexCount; this.expectedVertices = vertexCount;
// Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least // Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least
// enough buffer space for one more vertex. Sodium checks for this extra space when popNextBuffer // enough buffer space for one more vertex. Rubidium checks for this extra space when popNextBuffer
// is called and reallocates the buffer if there is not space for one more vertex. // is called and reallocates the buffer if there is not space for one more vertex.
int byteSize = formatInfo.stride * (vertexCount + 1); int byteSize = stride * (vertexCount + 1);
if (backingBuffer == null) { if (backingBuffer == null) {
backingBuffer = MemoryTracker.create(byteSize); backingBuffer = MemoryTracker.create(byteSize);
@ -54,8 +62,11 @@ public class DrawBuffer {
MemoryUtil.memSet(ptr, 0, byteSize); MemoryUtil.memSet(ptr, 0, byteSize);
} }
public MutableVertexListImpl slice(int startVertex, int vertexCount) { public ReusableVertexList slice(int startVertex, int vertexCount) {
return new MutableVertexListImpl(ptr + startVertex * formatInfo.stride, formatInfo, vertexCount); ReusableVertexList vertexList = provider.createVertexList();
vertexList.ptr(ptr + startVertex * stride);
vertexList.setVertexCount(vertexCount);
return vertexList;
} }
/** /**
@ -63,7 +74,7 @@ public class DrawBuffer {
* @param bufferBuilder The buffer builder to inject into. * @param bufferBuilder The buffer builder to inject into.
*/ */
public void inject(BufferBuilderExtension bufferBuilder) { public void inject(BufferBuilderExtension bufferBuilder) {
bufferBuilder.flywheel$injectForRender(backingBuffer, formatInfo.format, expectedVertices); bufferBuilder.flywheel$injectForRender(backingBuffer, format, expectedVertices);
} }
public int getVertexCount() { public int getVertexCount() {

View file

@ -1,206 +0,0 @@
package com.jozufozu.flywheel.backend.instancing.batching;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.util.RenderMath;
public class MutableVertexListImpl extends VertexFormatInfo implements MutableVertexList {
private final long anchorPtr;
private final int totalVertexCount;
private long ptr;
private int vertexCount;
public MutableVertexListImpl(long ptr, VertexFormatInfo formatInfo, int vertexCount) {
super(formatInfo);
anchorPtr = ptr;
totalVertexCount = vertexCount;
setFullRange();
}
public void setRange(int startVertex, int vertexCount) {
ptr = anchorPtr + startVertex * stride;
this.vertexCount = vertexCount;
}
public void setFullRange() {
ptr = anchorPtr;
vertexCount = totalVertexCount;
}
@Override
public float x(int index) {
if (positionOffset < 0) return 0;
return MemoryUtil.memGetFloat(ptr + index * stride + positionOffset);
}
@Override
public float y(int index) {
if (positionOffset < 0) return 0;
return MemoryUtil.memGetFloat(ptr + index * stride + positionOffset + 4);
}
@Override
public float z(int index) {
if (positionOffset < 0) return 0;
return MemoryUtil.memGetFloat(ptr + index * stride + positionOffset + 8);
}
@Override
public byte r(int index) {
if (colorOffset < 0) return 0;
return MemoryUtil.memGetByte(ptr + index * stride + colorOffset);
}
@Override
public byte g(int index) {
if (colorOffset < 0) return 0;
return MemoryUtil.memGetByte(ptr + index * stride + colorOffset + 1);
}
@Override
public byte b(int index) {
if (colorOffset < 0) return 0;
return MemoryUtil.memGetByte(ptr + index * stride + colorOffset + 2);
}
@Override
public byte a(int index) {
if (colorOffset < 0) return 0;
return MemoryUtil.memGetByte(ptr + index * stride + colorOffset + 3);
}
@Override
public float u(int index) {
if (textureOffset < 0) return 0;
return MemoryUtil.memGetFloat(ptr + index * stride + textureOffset);
}
@Override
public float v(int index) {
if (textureOffset < 0) return 0;
return MemoryUtil.memGetFloat(ptr + index * stride + textureOffset + 4);
}
@Override
public int overlay(int index) {
if (overlayOffset < 0) return 0;
return MemoryUtil.memGetInt(ptr + index * stride + overlayOffset);
}
@Override
public int light(int index) {
if (lightOffset < 0) return 0;
return MemoryUtil.memGetInt(ptr + index * stride + lightOffset);
}
@Override
public float normalX(int index) {
if (normalOffset < 0) return 0;
return RenderMath.f(MemoryUtil.memGetByte(ptr + index * stride + normalOffset));
}
@Override
public float normalY(int index) {
if (normalOffset < 0) return 0;
return RenderMath.f(MemoryUtil.memGetByte(ptr + index * stride + normalOffset + 1));
}
@Override
public float normalZ(int index) {
if (normalOffset < 0) return 0;
return RenderMath.f(MemoryUtil.memGetByte(ptr + index * stride + normalOffset + 2));
}
@Override
public int getVertexCount() {
return vertexCount;
}
@Override
public void x(int index, float x) {
if (positionOffset < 0) return;
MemoryUtil.memPutFloat(ptr + index * stride + positionOffset, x);
}
@Override
public void y(int index, float y) {
if (positionOffset < 0) return;
MemoryUtil.memPutFloat(ptr + index * stride + positionOffset + 4, y);
}
@Override
public void z(int index, float z) {
if (positionOffset < 0) return;
MemoryUtil.memPutFloat(ptr + index * stride + positionOffset + 8, z);
}
@Override
public void r(int index, byte r) {
if (colorOffset < 0) return;
MemoryUtil.memPutByte(ptr + index * stride + colorOffset, r);
}
@Override
public void g(int index, byte g) {
if (colorOffset < 0) return;
MemoryUtil.memPutByte(ptr + index * stride + colorOffset + 1, g);
}
@Override
public void b(int index, byte b) {
if (colorOffset < 0) return;
MemoryUtil.memPutByte(ptr + index * stride + colorOffset + 2, b);
}
@Override
public void a(int index, byte a) {
if (colorOffset < 0) return;
MemoryUtil.memPutByte(ptr + index * stride + colorOffset + 3, a);
}
@Override
public void u(int index, float u) {
if (textureOffset < 0) return;
MemoryUtil.memPutFloat(ptr + index * stride + textureOffset, u);
}
@Override
public void v(int index, float v) {
if (textureOffset < 0) return;
MemoryUtil.memPutFloat(ptr + index * stride + textureOffset + 4, v);
}
@Override
public void overlay(int index, int overlay) {
if (overlayOffset < 0) return;
MemoryUtil.memPutInt(ptr + index * stride + overlayOffset, overlay);
}
@Override
public void light(int index, int light) {
if (lightOffset < 0) return;
MemoryUtil.memPutInt(ptr + index * stride + lightOffset, light);
}
@Override
public void normalX(int index, float normalX) {
if (normalOffset < 0) return;
MemoryUtil.memPutByte(ptr + index * stride + normalOffset, RenderMath.nb(normalX));
}
@Override
public void normalY(int index, float normalY) {
if (normalOffset < 0) return;
MemoryUtil.memPutByte(ptr + index * stride + normalOffset + 1, RenderMath.nb(normalY));
}
@Override
public void normalZ(int index, float normalZ) {
if (normalOffset < 0) return;
MemoryUtil.memPutByte(ptr + index * stride + normalOffset + 2, RenderMath.nb(normalZ));
}
}

View file

@ -7,7 +7,7 @@ import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructType;
import com.jozufozu.flywheel.api.struct.StructType.VertexTransformer; import com.jozufozu.flywheel.api.struct.StructType.VertexTransformer;
import com.jozufozu.flywheel.api.vertex.MutableVertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.backend.instancing.TaskEngine; import com.jozufozu.flywheel.backend.instancing.TaskEngine;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
@ -49,69 +49,45 @@ public class TransformSet<D extends InstancedPart> {
int start = Math.max(instances, 0); int start = Math.max(instances, 0);
int vertexCount = mesh.getVertexCount() * (end - start); int vertexCount = mesh.getVertexCount() * (end - start);
MutableVertexListImpl sub = buffer.slice(startVertex, vertexCount); ReusableVertexList sub = buffer.slice(startVertex, vertexCount);
startVertex += vertexCount; startVertex += vertexCount;
pool.submit(() -> drawRange(sub, start, end, stack, level)); pool.submit(() -> drawRange(sub, start, end, stack, level));
} }
} }
private void drawRange(MutableVertexListImpl vertexList, int from, int to, PoseStack stack, ClientLevel level) { private void drawRange(ReusableVertexList vertexList, int from, int to, PoseStack stack, ClientLevel level) {
drawList(vertexList, instancer.getRange(from, to), stack, level); drawList(vertexList, instancer.getRange(from, to), stack, level);
} }
void drawAll(MutableVertexListImpl vertexList, PoseStack stack, ClientLevel level) { void drawAll(ReusableVertexList vertexList, PoseStack stack, ClientLevel level) {
drawList(vertexList, instancer.getAll(), stack, level); drawList(vertexList, instancer.getAll(), stack, level);
} }
private void drawList(MutableVertexListImpl vertexList, List<D> list, PoseStack stack, ClientLevel level) { private void drawList(ReusableVertexList vertexList, List<D> list, PoseStack stack, ClientLevel level) {
int startVertex = 0; long anchorPtr = vertexList.ptr();
int meshVertexCount = mesh.getVertexCount(); int totalVertexCount = vertexList.getVertexCount();
int meshVertexCount = mesh.getVertexCount();
vertexList.setVertexCount(meshVertexCount);
VertexList meshReader = mesh.getReader();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
StructType.VertexTransformer<D> structVertexTransformer = (VertexTransformer<D>) instancer.type.getVertexTransformer(); StructType.VertexTransformer<D> structVertexTransformer = (VertexTransformer<D>) instancer.type.getVertexTransformer();
for (D d : list) { for (D d : list) {
vertexList.setRange(startVertex, meshVertexCount); mesh.writeInto(vertexList);
writeMesh(vertexList, meshReader);
structVertexTransformer.transform(vertexList, d, level); structVertexTransformer.transform(vertexList, d, level);
startVertex += meshVertexCount; vertexList.shiftPtr(meshVertexCount);
} }
vertexList.setFullRange(); vertexList.ptr(anchorPtr);
vertexList.setVertexCount(totalVertexCount);
material.getVertexTransformer().transform(vertexList, level); material.getVertexTransformer().transform(vertexList, level);
applyPoseStack(vertexList, stack, false); applyPoseStack(vertexList, stack, false);
} }
// TODO: remove this
// The VertexWriter API and VertexFormat conversion needs to be rewritten to make this unnecessary
private static void writeMesh(MutableVertexList vertexList, VertexList meshReader) {
for (int i = 0; i < meshReader.getVertexCount(); i++) {
vertexList.x(i, meshReader.x(i));
vertexList.y(i, meshReader.y(i));
vertexList.z(i, meshReader.z(i));
vertexList.r(i, meshReader.r(i));
vertexList.g(i, meshReader.g(i));
vertexList.b(i, meshReader.b(i));
vertexList.a(i, meshReader.a(i));
vertexList.u(i, meshReader.u(i));
vertexList.v(i, meshReader.v(i));
vertexList.overlay(i, meshReader.overlay(i));
vertexList.light(i, meshReader.light(i));
vertexList.normalX(i, meshReader.normalX(i));
vertexList.normalY(i, meshReader.normalY(i));
vertexList.normalZ(i, meshReader.normalZ(i));
}
}
private static void applyPoseStack(MutableVertexList vertexList, PoseStack stack, boolean applyNormalMatrix) { private static void applyPoseStack(MutableVertexList vertexList, PoseStack stack, boolean applyNormalMatrix) {
Vector4f pos = new Vector4f(); Vector4f pos = new Vector4f();
Vector3f normal = new Vector3f(); Vector3f normal = new Vector3f();

View file

@ -152,7 +152,7 @@ public class MeshPool {
} }
} catch (Exception e) { } catch (Exception e) {
Flywheel.LOGGER.error("Error uploading pooled models:", e); Flywheel.LOGGER.error("Error uploading pooled meshes:", e);
} }
} }
@ -164,7 +164,7 @@ public class MeshPool {
} }
pendingUpload.clear(); pendingUpload.clear();
} catch (Exception e) { } catch (Exception e) {
Flywheel.LOGGER.error("Error uploading pooled models:", e); Flywheel.LOGGER.error("Error uploading pooled meshes:", e);
} }
} }
@ -209,7 +209,7 @@ public class MeshPool {
} }
private boolean hasAnythingToRender() { private boolean hasAnythingToRender() {
return mesh.getVertexCount() <= 0 || isDeleted(); return mesh.isEmpty() || isDeleted();
} }
private void draw(int instanceCount) { private void draw(int instanceCount) {

View file

@ -1,20 +1,22 @@
package com.jozufozu.flywheel.core.hardcoded; package com.jozufozu.flywheel.core.hardcoded;
import java.nio.ByteBuffer;
import java.util.List; import java.util.List;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.vertex.Formats;
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex; import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex;
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe; import com.mojang.blaze3d.platform.MemoryTracker;
public class ModelPart implements Mesh { public class ModelPart implements Mesh {
private final int vertexCount;
private final int vertices; private final ByteBuffer contents;
private final ReusableVertexList vertexList;
private final String name; private final String name;
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;
@ -24,17 +26,19 @@ public class ModelPart implements Mesh {
for (PartBuilder.CuboidBuilder cuboid : cuboids) { for (PartBuilder.CuboidBuilder cuboid : cuboids) {
vertices += cuboid.vertices(); vertices += cuboid.vertices();
} }
this.vertices = vertices; this.vertexCount = vertices;
} }
try (var stack = MemoryStack.stackPush()) { contents = MemoryTracker.create(size());
PosTexNormalWriterUnsafe writer = getVertexType().createWriter(stack.malloc(size())); long ptr = MemoryUtil.memAddress(contents);
VertexWriter writer = new VertexWriterImpl(ptr);
for (PartBuilder.CuboidBuilder cuboid : cuboids) { for (PartBuilder.CuboidBuilder cuboid : cuboids) {
cuboid.buffer(writer); cuboid.write(writer);
} }
reader = writer.intoReader(this.vertices); vertexList = getVertexType().createVertexList();
} vertexList.ptr(ptr);
vertexList.setVertexCount(vertexCount);
} }
public static PartBuilder builder(String name, int sizeU, int sizeV) { public static PartBuilder builder(String name, int sizeU, int sizeV) {
@ -42,22 +46,33 @@ public class ModelPart implements Mesh {
} }
@Override @Override
public String name() { public PosTexNormalVertex getVertexType() {
return name; return Formats.POS_TEX_NORMAL;
} }
@Override @Override
public int getVertexCount() { public int getVertexCount() {
return vertices; return vertexCount;
} }
@Override @Override
public VertexList getReader() { public void writeInto(ByteBuffer buffer, long byteIndex) {
return reader; buffer.position((int) byteIndex);
MemoryUtil.memCopy(contents, buffer);
} }
@Override @Override
public PosTexNormalVertex getVertexType() { public void writeInto(MutableVertexList dst) {
return Formats.POS_TEX_NORMAL; vertexList.writeAll(dst);
}
@Override
public void close() {
MemoryUtil.memFree(contents);
}
@Override
public String name() {
return name;
} }
} }

View file

@ -5,7 +5,6 @@ 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.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,8 +159,7 @@ public class PartBuilder {
return visibleFaces.size() * 4; return visibleFaces.size() * 4;
} }
public void buffer(PosTexNormalWriterUnsafe buffer) { public void write(VertexWriter writer) {
float sizeX = posX2 - posX1; float sizeX = posX2 - posX1;
float sizeY = posY2 - posY1; float sizeY = posY2 - posY1;
float sizeZ = posZ2 - posZ1; float sizeZ = posZ2 - posZ1;
@ -219,28 +217,27 @@ public class PartBuilder {
float f12 = getV((float)textureOffsetV + sizeZ + sizeY); float f12 = getV((float)textureOffsetV + sizeZ + sizeY);
if (invertYZ) { if (invertYZ) {
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, down); quad(writer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, down);
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, up); quad(writer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, up);
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, west); quad(writer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, west);
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, north); quad(writer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, north);
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, east); quad(writer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, east);
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, south); quad(writer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, south);
} else { } else {
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, down); quad(writer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, down);
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, up); quad(writer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, up);
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, west); quad(writer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, west);
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, north); quad(writer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, north);
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, east); quad(writer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, east);
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, south); quad(writer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, south);
} }
} }
public void quad(PosTexNormalWriterUnsafe buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) { public void quad(VertexWriter writer, 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); writer.putVertex(vertices[0].x(), vertices[0].y(), vertices[0].z(), maxU, minV, normal.x(), normal.y(), normal.z());
buffer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), normal.x(), normal.y(), normal.z(), minU, minV); writer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), minU, minV, normal.x(), normal.y(), normal.z());
buffer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), normal.x(), normal.y(), normal.z(), minU, maxV); writer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), minU, maxV, normal.x(), normal.y(), normal.z());
buffer.putVertex(vertices[3].x(), vertices[3].y(), vertices[3].z(), normal.x(), normal.y(), normal.z(), maxU, maxV); writer.putVertex(vertices[3].x(), vertices[3].y(), vertices[3].z(), maxU, maxV, normal.x(), normal.y(), normal.z());
} }
public float getU(float u) { public float getU(float u) {
@ -258,5 +255,4 @@ public class PartBuilder {
} }
} }
} }

View file

@ -0,0 +1,5 @@
package com.jozufozu.flywheel.core.hardcoded;
public interface VertexWriter {
void putVertex(float x, float y, float z, float u, float v, float nX, float nY, float nZ);
}

View file

@ -0,0 +1,27 @@
package com.jozufozu.flywheel.core.hardcoded;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.RenderMath;
public class VertexWriterImpl implements VertexWriter {
private long ptr;
public VertexWriterImpl(long ptr) {
this.ptr = ptr;
}
@Override
public void putVertex(float x, float y, float z, float u, float v, float nX, float nY, float nZ) {
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;
}
}

View file

@ -1,26 +1,39 @@
package com.jozufozu.flywheel.core.layout; package com.jozufozu.flywheel.core.layout;
import com.jozufozu.flywheel.backend.gl.GlNumericType; import com.jozufozu.flywheel.backend.gl.GlNumericType;
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeF;
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeI; import com.jozufozu.flywheel.backend.gl.array.VertexAttributeI;
public class CommonItems { public class CommonItems {
public static final PrimitiveItem VEC4 = new PrimitiveItem(GlNumericType.FLOAT, 4); public static final PrimitiveItem VEC4 = primitiveF(GlNumericType.FLOAT, 4);
public static final PrimitiveItem VEC3 = new PrimitiveItem(GlNumericType.FLOAT, 3); public static final PrimitiveItem VEC3 = primitiveF(GlNumericType.FLOAT, 3);
public static final PrimitiveItem VEC2 = new PrimitiveItem(GlNumericType.FLOAT, 2); public static final PrimitiveItem VEC2 = primitiveF(GlNumericType.FLOAT, 2);
public static final PrimitiveItem FLOAT = new PrimitiveItem(GlNumericType.FLOAT, 1); public static final PrimitiveItem FLOAT = primitiveF(GlNumericType.FLOAT, 1);
public static final PrimitiveItem QUATERNION = new PrimitiveItem(GlNumericType.FLOAT, 4); public static final PrimitiveItem QUATERNION = primitiveF(GlNumericType.FLOAT, 4);
public static final PrimitiveItem NORMAL = new PrimitiveItem(GlNumericType.BYTE, 3, true); public static final PrimitiveItem NORMAL = primitiveF(GlNumericType.BYTE, 3, true);
public static final PrimitiveItem UV = new PrimitiveItem(GlNumericType.FLOAT, 2); public static final PrimitiveItem UV = primitiveF(GlNumericType.FLOAT, 2);
public static final PrimitiveItem RGBA = new PrimitiveItem(GlNumericType.UBYTE, 4, true); public static final PrimitiveItem RGBA = primitiveF(GlNumericType.UBYTE, 4, true);
public static final PrimitiveItem RGB = new PrimitiveItem(GlNumericType.UBYTE, 3, true); public static final PrimitiveItem RGB = primitiveF(GlNumericType.UBYTE, 3, true);
public static final PrimitiveItem LIGHT = new PrimitiveItem(new VertexAttributeI(GlNumericType.UBYTE, 2)); public static final PrimitiveItem LIGHT = primitiveI(GlNumericType.UBYTE, 2);
public static final PrimitiveItem LIGHT_SHORT = new PrimitiveItem(new VertexAttributeI(GlNumericType.USHORT, 2)); public static final PrimitiveItem LIGHT_SHORT = primitiveI(GlNumericType.USHORT, 2);
public static final PrimitiveItem NORMALIZED_BYTE = new PrimitiveItem(GlNumericType.BYTE, 1, true); public static final PrimitiveItem NORMALIZED_BYTE = primitiveF(GlNumericType.BYTE, 1, true);
public static final MatrixItem MAT3 = new MatrixItem(3, 3); public static final MatrixItem MAT3 = new MatrixItem(3, 3);
public static final MatrixItem MAT4 = new MatrixItem(4, 4); public static final MatrixItem MAT4 = new MatrixItem(4, 4);
private static PrimitiveItem primitiveF(GlNumericType type, int count, boolean normalized) {
return new PrimitiveItem(new VertexAttributeF(type, count, normalized));
}
private static PrimitiveItem primitiveF(GlNumericType type, int count) {
return primitiveF(type, count, false);
}
private static PrimitiveItem primitiveI(GlNumericType type, int count) {
return new PrimitiveItem(new VertexAttributeI(type, count));
}
} }

View file

@ -2,22 +2,12 @@ package com.jozufozu.flywheel.core.layout;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.jozufozu.flywheel.backend.gl.GlNumericType;
import com.jozufozu.flywheel.backend.gl.array.VertexAttribute; import com.jozufozu.flywheel.backend.gl.array.VertexAttribute;
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeF;
public class PrimitiveItem implements LayoutItem { public class PrimitiveItem implements LayoutItem {
private final VertexAttribute attribute; private final VertexAttribute attribute;
public PrimitiveItem(GlNumericType type, int count) {
this(type, count, false);
}
public PrimitiveItem(GlNumericType type, int count, boolean normalized) {
this(new VertexAttributeF(type, count, normalized));
}
public PrimitiveItem(VertexAttribute attribute) { public PrimitiveItem(VertexAttribute attribute) {
this.attribute = attribute; this.attribute = attribute;
} }

View file

@ -2,9 +2,8 @@ package com.jozufozu.flywheel.core.model;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.api.vertex.VertexWriter;
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer; import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
import com.jozufozu.flywheel.core.QuadConverter; import com.jozufozu.flywheel.core.QuadConverter;
@ -30,39 +29,34 @@ import com.jozufozu.flywheel.core.QuadConverter;
*/ */
public interface Mesh { public interface Mesh {
/**
* A name uniquely identifying this model.
*/
String name();
VertexType getVertexType(); VertexType getVertexType();
VertexList getReader();
/** /**
* @return The number of vertices the model has. * @return The number of vertices this mesh has.
*/ */
default int getVertexCount() { int getVertexCount();
return getReader().getVertexCount();
}
/** /**
* Is there nothing to render? * Is there nothing to render?
* @return true if there are no vertices. * @return true if there are no vertices.
*/ */
default boolean isEmpty() { default boolean isEmpty() {
return getReader().isEmpty(); return getVertexCount() == 0;
} }
/** /**
* The size in bytes that this model's data takes up. * The size in bytes that this mesh's data takes up.
*/ */
default int size() { default int size() {
return getVertexType().byteOffset(getVertexCount()); return getVertexType().byteOffset(getVertexCount());
} }
void writeInto(ByteBuffer buffer, long byteIndex);
void writeInto(MutableVertexList vertexList);
/** /**
* Create an element buffer object that indexes the vertices of this model. * Create an element buffer object that indexes the vertices of this mesh.
* *
* <p> * <p>
* Very often models in minecraft are made up of sequential quads, which is a very predictable pattern. * Very often models in minecraft are made up of sequential quads, which is a very predictable pattern.
@ -76,9 +70,10 @@ public interface Mesh {
.quads2Tris(getVertexCount() / 4); .quads2Tris(getVertexCount() / 4);
} }
default void writeInto(ByteBuffer buffer, long byteIndex) { void close();
VertexWriter writer = getVertexType().createWriter(buffer);
writer.seek(byteIndex); /**
writer.writeVertexList(getReader()); * A name uniquely identifying this mesh.
} */
String name();
} }

View file

@ -4,14 +4,18 @@ import java.lang.reflect.Field;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.Flywheel; import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.VertexList; import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.vertex.Formats; import com.jozufozu.flywheel.core.vertex.Formats;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.platform.MemoryTracker;
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -43,15 +47,27 @@ public class ModelUtil {
return dispatcher; return dispatcher;
} }
public static VertexList createVertexList(BufferBuilder bufferBuilder) { public static Pair<VertexType, ByteBuffer> convertBlockBuffer(Pair<DrawState, ByteBuffer> pair) {
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer(); DrawState drawState = pair.getFirst();
BufferBuilder.DrawState drawState = pair.getFirst(); int vertexCount = drawState.vertexCount();
VertexFormat srcFormat = drawState.format();
VertexType dstVertexType = Formats.BLOCK;
if (drawState.format() != DefaultVertexFormat.BLOCK) { ByteBuffer src = pair.getSecond();
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format()); ByteBuffer dst = MemoryTracker.create(src.capacity());
} long srcPtr = MemoryUtil.memAddress(src);
long dstPtr = MemoryUtil.memAddress(dst);
return Formats.BLOCK.createReader(pair.getSecond(), drawState.vertexCount()); ReusableVertexList srcList = VertexListProviderRegistry.getOrInfer(srcFormat).createVertexList();
ReusableVertexList dstList = dstVertexType.createVertexList();
srcList.ptr(srcPtr);
dstList.ptr(dstPtr);
srcList.setVertexCount(vertexCount);
dstList.setVertexCount(vertexCount);
srcList.writeAll(dstList);
return Pair.of(dstVertexType, dst);
} }
@Nullable @Nullable

View file

@ -1,22 +1,36 @@
package com.jozufozu.flywheel.core.model; package com.jozufozu.flywheel.core.model;
import com.jozufozu.flywheel.api.vertex.VertexList; import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
public class SimpleMesh implements Mesh { public class SimpleMesh implements Mesh {
private final VertexList reader;
private final VertexType vertexType; private final VertexType vertexType;
private final int vertexCount;
private final ByteBuffer contents;
private final ReusableVertexList vertexList;
private final String name; private final String name;
public SimpleMesh(VertexList reader, VertexType vertexType, String name) { public SimpleMesh(VertexType vertexType, ByteBuffer contents, String name) {
this.reader = reader;
this.vertexType = vertexType; this.vertexType = vertexType;
this.contents = contents;
this.name = name; this.name = name;
}
@Override contents.clear();
public String name() { int bytes = contents.remaining();
return name; int stride = vertexType.getStride();
if (bytes % stride != 0) {
throw new IllegalArgumentException("Buffer contains non-whole amount of vertices!");
}
vertexCount = bytes / stride;
vertexList = getVertexType().createVertexList();
vertexList.ptr(MemoryUtil.memAddress(contents));
vertexList.setVertexCount(vertexCount);
} }
@Override @Override
@ -25,8 +39,29 @@ public class SimpleMesh implements Mesh {
} }
@Override @Override
public VertexList getReader() { public int getVertexCount() {
return reader; return vertexCount;
}
@Override
public void writeInto(ByteBuffer buffer, long byteIndex) {
buffer.position((int) byteIndex);
MemoryUtil.memCopy(contents, buffer);
}
@Override
public void writeInto(MutableVertexList dst) {
vertexList.writeAll(dst);
}
@Override
public void close() {
MemoryUtil.memFree(contents);
}
@Override
public String name() {
return name;
} }
@Override @Override

View file

@ -1,9 +1,11 @@
package com.jozufozu.flywheel.core.model.buffering; package com.jozufozu.flywheel.core.model.buffering;
import java.nio.ByteBuffer;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.core.model.SimpleMesh; import com.jozufozu.flywheel.core.model.SimpleMesh;
@ -12,13 +14,13 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
import com.jozufozu.flywheel.core.vertex.Formats;
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter; import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData; import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BakedModel;
@ -30,7 +32,6 @@ import net.minecraftforge.client.model.data.IModelData;
public class BakedModelBuilder { public class BakedModelBuilder {
private final BakedModel bakedModel; private final BakedModel bakedModel;
private boolean shadeSeparated = true; private boolean shadeSeparated = true;
private VertexFormat vertexFormat;
private BlockAndTintGetter renderWorld; private BlockAndTintGetter renderWorld;
private BlockState blockState; private BlockState blockState;
private PoseStack poseStack; private PoseStack poseStack;
@ -46,11 +47,6 @@ public class BakedModelBuilder {
return this; return this;
} }
public BakedModelBuilder vertexFormat(VertexFormat vertexFormat) {
this.vertexFormat = vertexFormat;
return this;
}
public BakedModelBuilder renderWorld(BlockAndTintGetter renderWorld) { public BakedModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
this.renderWorld = renderWorld; this.renderWorld = renderWorld;
return this; return this;
@ -80,9 +76,6 @@ public class BakedModelBuilder {
public TessellatedModel build() { public TessellatedModel build() {
ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get(); ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get();
if (vertexFormat == null) {
vertexFormat = DefaultVertexFormat.BLOCK;
}
if (renderWorld == null) { if (renderWorld == null) {
renderWorld = VirtualEmptyBlockGetter.INSTANCE; renderWorld = VirtualEmptyBlockGetter.INSTANCE;
} }
@ -104,28 +97,30 @@ public class BakedModelBuilder {
if (shadeSeparated) { if (shadeSeparated) {
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> { ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
BufferBuilder buffer = new BufferBuilder(64); BufferBuilder buffer = new BufferBuilder(64);
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
return buffer; return buffer;
}; };
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> { ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, shaded); Material material = materialFunc.apply(renderType, shaded);
if (material != null) { if (material != null) {
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
} }
}; };
ModelBufferingUtil.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer); ModelBufferingUtil.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer);
} else { } else {
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> { BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
BufferBuilder buffer = new BufferBuilder(64); BufferBuilder buffer = new BufferBuilder(64);
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
return buffer; return buffer;
}; };
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> { ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, false); Material material = materialFunc.apply(renderType, false);
if (material != null) { if (material != null) {
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString())); Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString()));
} }
}; };
ModelBufferingUtil.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer); ModelBufferingUtil.bufferSingle(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer);

View file

@ -1,9 +1,11 @@
package com.jozufozu.flywheel.core.model.buffering; package com.jozufozu.flywheel.core.model.buffering;
import java.nio.ByteBuffer;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.core.model.SimpleMesh; import com.jozufozu.flywheel.core.model.SimpleMesh;
@ -12,13 +14,13 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
import com.jozufozu.flywheel.core.vertex.Formats;
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter; import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData; import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.BlockAndTintGetter;
@ -28,7 +30,6 @@ import net.minecraftforge.client.model.data.IModelData;
public class BlockModelBuilder { public class BlockModelBuilder {
private final BlockState state; private final BlockState state;
private boolean shadeSeparated = true; private boolean shadeSeparated = true;
private VertexFormat vertexFormat;
private BlockAndTintGetter renderWorld; private BlockAndTintGetter renderWorld;
private PoseStack poseStack; private PoseStack poseStack;
private IModelData modelData; private IModelData modelData;
@ -43,11 +44,6 @@ public class BlockModelBuilder {
return this; return this;
} }
public BlockModelBuilder vertexFormat(VertexFormat vertexFormat) {
this.vertexFormat = vertexFormat;
return this;
}
public BlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) { public BlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
this.renderWorld = renderWorld; this.renderWorld = renderWorld;
return this; return this;
@ -72,9 +68,6 @@ public class BlockModelBuilder {
public TessellatedModel build() { public TessellatedModel build() {
ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get(); ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get();
if (vertexFormat == null) {
vertexFormat = DefaultVertexFormat.BLOCK;
}
if (renderWorld == null) { if (renderWorld == null) {
renderWorld = VirtualEmptyBlockGetter.INSTANCE; renderWorld = VirtualEmptyBlockGetter.INSTANCE;
} }
@ -93,28 +86,30 @@ public class BlockModelBuilder {
if (shadeSeparated) { if (shadeSeparated) {
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> { ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
BufferBuilder buffer = new BufferBuilder(64); BufferBuilder buffer = new BufferBuilder(64);
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
return buffer; return buffer;
}; };
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> { ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, shaded); Material material = materialFunc.apply(renderType, shaded);
if (material != null) { if (material != null) {
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded)); Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
} }
}; };
ModelBufferingUtil.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer); ModelBufferingUtil.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer);
} else { } else {
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> { BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
BufferBuilder buffer = new BufferBuilder(64); BufferBuilder buffer = new BufferBuilder(64);
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
return buffer; return buffer;
}; };
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> { ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, false); Material material = materialFunc.apply(renderType, false);
if (material != null) { if (material != null) {
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "state=" + state.toString() + ",renderType=" + renderType.toString())); Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "state=" + state.toString() + ",renderType=" + renderType.toString()));
} }
}; };
ModelBufferingUtil.bufferBlock(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer); ModelBufferingUtil.bufferBlock(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelData, resultConsumer);

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.core.model.buffering; package com.jozufozu.flywheel.core.model.buffering;
import java.nio.ByteBuffer;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
@ -7,6 +8,7 @@ import java.util.function.BiFunction;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.model.Mesh; import com.jozufozu.flywheel.core.model.Mesh;
import com.jozufozu.flywheel.core.model.ModelUtil; import com.jozufozu.flywheel.core.model.ModelUtil;
import com.jozufozu.flywheel.core.model.SimpleMesh; import com.jozufozu.flywheel.core.model.SimpleMesh;
@ -15,12 +17,12 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer; import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
import com.jozufozu.flywheel.core.vertex.Formats;
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter; import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -46,11 +48,6 @@ public class MultiBlockModelBuilder {
return this; return this;
} }
public MultiBlockModelBuilder vertexFormat(VertexFormat vertexFormat) {
this.vertexFormat = vertexFormat;
return this;
}
public MultiBlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) { public MultiBlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
this.renderWorld = renderWorld; this.renderWorld = renderWorld;
return this; return this;
@ -96,28 +93,30 @@ public class MultiBlockModelBuilder {
if (shadeSeparated) { if (shadeSeparated) {
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> { ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
BufferBuilder buffer = new BufferBuilder(1024); BufferBuilder buffer = new BufferBuilder(1024);
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
return buffer; return buffer;
}; };
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> { ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, shaded); Material material = materialFunc.apply(renderType, shaded);
if (material != null) { if (material != null) {
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "renderType=" + renderType.toString() + ",shaded=" + shaded)); Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString() + ",shaded=" + shaded));
} }
}; };
ModelBufferingUtil.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelDataMap, resultConsumer); ModelBufferingUtil.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelDataMap, resultConsumer);
} else { } else {
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> { BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
BufferBuilder buffer = new BufferBuilder(1024); BufferBuilder buffer = new BufferBuilder(1024);
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat); buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
return buffer; return buffer;
}; };
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> { ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
buffer.end(); buffer.end();
Material material = materialFunc.apply(renderType, false); Material material = materialFunc.apply(renderType, false);
if (material != null) { if (material != null) {
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "renderType=" + renderType.toString())); Pair<VertexType, ByteBuffer> pair = ModelUtil.convertBlockBuffer(buffer.popNextBuffer());
meshMapBuilder.put(material, new SimpleMesh(pair.getFirst(), pair.getSecond(), "renderType=" + renderType.toString()));
} }
}; };
ModelBufferingUtil.bufferMultiBlock(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelDataMap, resultConsumer); ModelBufferingUtil.bufferMultiBlock(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.bufferWrapper, objects.random, modelDataMap, resultConsumer);

View file

@ -1,49 +1,28 @@
package com.jozufozu.flywheel.core.vertex; package com.jozufozu.flywheel.core.vertex;
import java.nio.Buffer; import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil; public abstract class AbstractVertexList implements ReusableVertexList {
protected long ptr;
import com.jozufozu.flywheel.api.vertex.VertexList; protected int vertexCount;
import com.mojang.blaze3d.platform.MemoryTracker;
import com.mojang.blaze3d.vertex.BufferBuilder;
public abstract class AbstractVertexList implements VertexList, AutoCloseable {
protected final ByteBuffer contents;
protected final long base;
protected final int vertexCount;
protected AbstractVertexList(ByteBuffer copyFrom, int vertexCount) {
this.contents = MemoryTracker.create(copyFrom.capacity());
this.vertexCount = vertexCount;
this.base = MemoryUtil.memAddress(this.contents);
init(copyFrom);
}
public AbstractVertexList(BufferBuilder builder) {
var pair = builder.popNextBuffer();
ByteBuffer copyFrom = pair.getSecond();
this.contents = MemoryTracker.create(copyFrom.capacity());
this.vertexCount = pair.getFirst().vertexCount();
this.base = MemoryUtil.memAddress(this.contents);
init(copyFrom);
}
private void init(ByteBuffer copyFrom) {
this.contents.order(copyFrom.order());
this.contents.put(copyFrom);
((Buffer) this.contents).flip();
}
@Override
public void close() {
MemoryUtil.memFree(contents);
}
@Override @Override
public int getVertexCount() { public int getVertexCount() {
return vertexCount; return vertexCount;
} }
@Override
public void setVertexCount(int vertexCount) {
this.vertexCount = vertexCount;
}
@Override
public long ptr() {
return ptr;
}
@Override
public void ptr(long ptr) {
this.ptr = ptr;
}
} }

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.core.vertex; package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.Components; import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.BufferLayout;
@ -9,7 +7,6 @@ import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;
public class BlockVertex implements VertexType { public class BlockVertex implements VertexType {
public static final BufferLayout FORMAT = BufferLayout.builder() public static final BufferLayout FORMAT = BufferLayout.builder()
.addItems(CommonItems.VEC3, .addItems(CommonItems.VEC3,
CommonItems.RGBA, CommonItems.RGBA,
@ -24,18 +21,13 @@ public class BlockVertex implements VertexType {
return FORMAT; return FORMAT;
} }
@Override
public BlockWriterUnsafe createWriter(ByteBuffer buffer) {
return new BlockWriterUnsafe(this, buffer);
}
@Override
public BlockVertexListUnsafe createReader(ByteBuffer buffer, int vertexCount) {
return new BlockVertexListUnsafe(buffer, vertexCount);
}
@Override @Override
public FileResolution getLayoutShader() { public FileResolution getLayoutShader() {
return Components.Files.BLOCK_LAYOUT; return Components.Files.BLOCK_LAYOUT;
} }
@Override
public BlockVertexList createVertexList() {
return new BlockVertexList();
}
} }

View file

@ -1,72 +1,61 @@
package com.jozufozu.flywheel.core.vertex; package com.jozufozu.flywheel.core.vertex;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.RenderMath; import com.jozufozu.flywheel.util.RenderMath;
import com.mojang.blaze3d.vertex.BufferBuilder;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
public class BlockVertexList extends AbstractVertexList { public class BlockVertexList extends AbstractVertexList {
protected static final int STRIDE = 32;
private final int stride; protected long idxPtr(int index) {
return ptr + index * STRIDE;
public BlockVertexList(BufferBuilder builder) {
super(builder);
this.stride = builder.getVertexFormat()
.getVertexSize();
}
@Override
public boolean isEmpty() {
return vertexCount == 0;
}
private int vertIdx(int vertexIndex) {
return vertexIndex * stride;
} }
@Override @Override
public float x(int index) { public float x(int index) {
return contents.getFloat(vertIdx(index)); return MemoryUtil.memGetFloat(idxPtr(index));
} }
@Override @Override
public float y(int index) { public float y(int index) {
return contents.getFloat(vertIdx(index) + 4); return MemoryUtil.memGetFloat(idxPtr(index) + 4);
} }
@Override @Override
public float z(int index) { public float z(int index) {
return contents.getFloat(vertIdx(index) + 8); return MemoryUtil.memGetFloat(idxPtr(index) + 8);
} }
@Override @Override
public byte r(int index) { public byte r(int index) {
return contents.get(vertIdx(index) + 12); return MemoryUtil.memGetByte(idxPtr(index) + 12);
} }
@Override @Override
public byte g(int index) { public byte g(int index) {
return contents.get(vertIdx(index) + 13); return MemoryUtil.memGetByte(idxPtr(index) + 13);
} }
@Override @Override
public byte b(int index) { public byte b(int index) {
return contents.get(vertIdx(index) + 14); return MemoryUtil.memGetByte(idxPtr(index) + 14);
} }
@Override @Override
public byte a(int index) { public byte a(int index) {
return contents.get(vertIdx(index) + 15); return MemoryUtil.memGetByte(idxPtr(index) + 15);
} }
@Override @Override
public float u(int index) { public float u(int index) {
return contents.getFloat(vertIdx(index) + 16); return MemoryUtil.memGetFloat(idxPtr(index) + 16);
} }
@Override @Override
public float v(int index) { public float v(int index) {
return contents.getFloat(vertIdx(index) + 20); return MemoryUtil.memGetFloat(idxPtr(index) + 20);
} }
@Override @Override
@ -76,22 +65,95 @@ public class BlockVertexList extends AbstractVertexList {
@Override @Override
public int light(int index) { public int light(int index) {
return contents.getInt(vertIdx(index) + 24); return MemoryUtil.memGetInt(idxPtr(index) + 24) << 4;
} }
@Override @Override
public float normalX(int index) { public float normalX(int index) {
return RenderMath.f(contents.get(vertIdx(index) + 28)); return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 28));
} }
@Override @Override
public float normalY(int index) { public float normalY(int index) {
return RenderMath.f(contents.get(vertIdx(index) + 29)); return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 29));
} }
@Override @Override
public float normalZ(int index) { public float normalZ(int index) {
return RenderMath.f(contents.get(vertIdx(index) + 30)); return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 30));
} }
@Override
public void x(int index, float x) {
MemoryUtil.memPutFloat(idxPtr(index), x);
}
@Override
public void y(int index, float y) {
MemoryUtil.memPutFloat(idxPtr(index) + 4, y);
}
@Override
public void z(int index, float z) {
MemoryUtil.memPutFloat(idxPtr(index) + 8, z);
}
@Override
public void r(int index, byte r) {
MemoryUtil.memPutByte(idxPtr(index) + 12, r);
}
@Override
public void g(int index, byte g) {
MemoryUtil.memPutByte(idxPtr(index) + 13, g);
}
@Override
public void b(int index, byte b) {
MemoryUtil.memPutByte(idxPtr(index) + 14, b);
}
@Override
public void a(int index, byte a) {
MemoryUtil.memPutByte(idxPtr(index) + 15, a);
}
@Override
public void u(int index, float u) {
MemoryUtil.memPutFloat(idxPtr(index) + 16, u);
}
@Override
public void v(int index, float v) {
MemoryUtil.memPutFloat(idxPtr(index) + 20, v);
}
@Override
public void overlay(int index, int overlay) {
}
@Override
public void light(int index, int light) {
MemoryUtil.memPutInt(idxPtr(index) + 24, light >> 4);
}
@Override
public void normalX(int index, float normalX) {
MemoryUtil.memPutByte(idxPtr(index) + 28, RenderMath.nb(normalX));
}
@Override
public void normalY(int index, float normalY) {
MemoryUtil.memPutByte(idxPtr(index) + 29, RenderMath.nb(normalY));
}
@Override
public void normalZ(int index, float normalZ) {
MemoryUtil.memPutByte(idxPtr(index) + 30, RenderMath.nb(normalZ));
}
@Override
public void shiftPtr(int vertices) {
ptr += vertices * STRIDE;
}
} }

View file

@ -1,91 +0,0 @@
package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.RenderMath;
import net.minecraft.client.renderer.texture.OverlayTexture;
public class BlockVertexListUnsafe extends AbstractVertexList {
public BlockVertexListUnsafe(ByteBuffer copyFrom, int vertexCount) {
super(copyFrom, vertexCount);
}
private long ptr(long index) {
return base + index * 32;
}
@Override
public float x(int index) {
return MemoryUtil.memGetFloat(ptr(index));
}
@Override
public float y(int index) {
return MemoryUtil.memGetFloat(ptr(index) + 4);
}
@Override
public float z(int index) {
return MemoryUtil.memGetFloat(ptr(index) + 8);
}
@Override
public byte r(int index) {
return MemoryUtil.memGetByte(ptr(index) + 12);
}
@Override
public byte g(int index) {
return MemoryUtil.memGetByte(ptr(index) + 13);
}
@Override
public byte b(int index) {
return MemoryUtil.memGetByte(ptr(index) + 14);
}
@Override
public byte a(int index) {
return MemoryUtil.memGetByte(ptr(index) + 15);
}
@Override
public float u(int index) {
return MemoryUtil.memGetFloat(ptr(index) + 16);
}
@Override
public float v(int index) {
return MemoryUtil.memGetFloat(ptr(index) + 20);
}
@Override
public int overlay(int index) {
return OverlayTexture.NO_OVERLAY;
}
@Override
public int light(int index) {
return MemoryUtil.memGetInt(ptr(index) + 24);
}
@Override
public float normalX(int index) {
return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 28));
}
@Override
public float normalY(int index) {
return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 29));
}
@Override
public float normalZ(int index) {
return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 30));
}
}

View file

@ -1,56 +0,0 @@
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.x(i);
float y = list.y(i);
float z = list.z(i);
float xN = list.normalX(i);
float yN = list.normalY(i);
float zN = list.normalZ(i);
float u = list.u(i);
float v = list.v(i);
byte r = list.r(i);
byte g = list.g(i);
byte b = list.b(i);
byte a = list.a(i);
int light = list.light(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 >> 4) & 0xF000F);
MemoryUtil.memPutByte(ptr + 28, RenderMath.nb(nX));
MemoryUtil.memPutByte(ptr + 29, RenderMath.nb(nY));
MemoryUtil.memPutByte(ptr + 30, RenderMath.nb(nZ));
ptr += 32;
}
}

View file

@ -1,9 +1,9 @@
package com.jozufozu.flywheel.backend.instancing.batching; package com.jozufozu.flywheel.core.vertex;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormatElement; import com.mojang.blaze3d.vertex.VertexFormatElement;
public class VertexFormatInfo { public class InferredVertexFormatInfo {
public final VertexFormat format; public final VertexFormat format;
public final int stride; public final int stride;
@ -14,7 +14,7 @@ public class VertexFormatInfo {
public final int lightOffset; public final int lightOffset;
public final int normalOffset; public final int normalOffset;
public VertexFormatInfo(VertexFormat format) { public InferredVertexFormatInfo(VertexFormat format) {
this.format = format; this.format = format;
stride = format.getVertexSize(); stride = format.getVertexSize();
@ -51,7 +51,7 @@ public class VertexFormatInfo {
this.normalOffset = normalOffset; this.normalOffset = normalOffset;
} }
protected VertexFormatInfo(VertexFormatInfo formatInfo) { protected InferredVertexFormatInfo(InferredVertexFormatInfo formatInfo) {
format = formatInfo.format; format = formatInfo.format;
stride = formatInfo.stride; stride = formatInfo.stride;
positionOffset = formatInfo.positionOffset; positionOffset = formatInfo.positionOffset;

View file

@ -0,0 +1,214 @@
package com.jozufozu.flywheel.core.vertex;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.util.RenderMath;
import net.minecraft.client.renderer.texture.OverlayTexture;
public final class InferredVertexListImpl extends InferredVertexFormatInfo implements ReusableVertexList {
private long ptr;
private int vertexCount;
public InferredVertexListImpl(InferredVertexFormatInfo formatInfo) {
super(formatInfo);
}
private long idxPtr(int index) {
return ptr + index * stride;
}
@Override
public float x(int index) {
if (positionOffset < 0) return 0;
return MemoryUtil.memGetFloat(idxPtr(index) + positionOffset);
}
@Override
public float y(int index) {
if (positionOffset < 0) return 0;
return MemoryUtil.memGetFloat(idxPtr(index) + positionOffset + 4);
}
@Override
public float z(int index) {
if (positionOffset < 0) return 0;
return MemoryUtil.memGetFloat(idxPtr(index) + positionOffset + 8);
}
@Override
public byte r(int index) {
if (colorOffset < 0) return 0;
return MemoryUtil.memGetByte(idxPtr(index) + colorOffset);
}
@Override
public byte g(int index) {
if (colorOffset < 0) return 0;
return MemoryUtil.memGetByte(idxPtr(index) + colorOffset + 1);
}
@Override
public byte b(int index) {
if (colorOffset < 0) return 0;
return MemoryUtil.memGetByte(idxPtr(index) + colorOffset + 2);
}
@Override
public byte a(int index) {
if (colorOffset < 0) return 0;
return MemoryUtil.memGetByte(idxPtr(index) + colorOffset + 3);
}
@Override
public float u(int index) {
if (textureOffset < 0) return 0;
return MemoryUtil.memGetFloat(idxPtr(index) + textureOffset);
}
@Override
public float v(int index) {
if (textureOffset < 0) return 0;
return MemoryUtil.memGetFloat(idxPtr(index) + textureOffset + 4);
}
@Override
public int overlay(int index) {
if (overlayOffset < 0) return OverlayTexture.NO_OVERLAY;
return MemoryUtil.memGetInt(idxPtr(index) + overlayOffset);
}
@Override
public int light(int index) {
if (lightOffset < 0) return 0;
return MemoryUtil.memGetInt(idxPtr(index) + lightOffset);
}
@Override
public float normalX(int index) {
if (normalOffset < 0) return 0;
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + normalOffset));
}
@Override
public float normalY(int index) {
if (normalOffset < 0) return 0;
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + normalOffset + 1));
}
@Override
public float normalZ(int index) {
if (normalOffset < 0) return 0;
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + normalOffset + 2));
}
@Override
public void x(int index, float x) {
if (positionOffset < 0) return;
MemoryUtil.memPutFloat(idxPtr(index) + positionOffset, x);
}
@Override
public void y(int index, float y) {
if (positionOffset < 0) return;
MemoryUtil.memPutFloat(idxPtr(index) + positionOffset + 4, y);
}
@Override
public void z(int index, float z) {
if (positionOffset < 0) return;
MemoryUtil.memPutFloat(idxPtr(index) + positionOffset + 8, z);
}
@Override
public void r(int index, byte r) {
if (colorOffset < 0) return;
MemoryUtil.memPutByte(idxPtr(index) + colorOffset, r);
}
@Override
public void g(int index, byte g) {
if (colorOffset < 0) return;
MemoryUtil.memPutByte(idxPtr(index) + colorOffset + 1, g);
}
@Override
public void b(int index, byte b) {
if (colorOffset < 0) return;
MemoryUtil.memPutByte(idxPtr(index) + colorOffset + 2, b);
}
@Override
public void a(int index, byte a) {
if (colorOffset < 0) return;
MemoryUtil.memPutByte(idxPtr(index) + colorOffset + 3, a);
}
@Override
public void u(int index, float u) {
if (textureOffset < 0) return;
MemoryUtil.memPutFloat(idxPtr(index) + textureOffset, u);
}
@Override
public void v(int index, float v) {
if (textureOffset < 0) return;
MemoryUtil.memPutFloat(idxPtr(index) + textureOffset + 4, v);
}
@Override
public void overlay(int index, int overlay) {
if (overlayOffset < 0) return;
MemoryUtil.memPutInt(idxPtr(index) + overlayOffset, overlay);
}
@Override
public void light(int index, int light) {
if (lightOffset < 0) return;
MemoryUtil.memPutInt(idxPtr(index) + lightOffset, light);
}
@Override
public void normalX(int index, float normalX) {
if (normalOffset < 0) return;
MemoryUtil.memPutByte(idxPtr(index) + normalOffset, RenderMath.nb(normalX));
}
@Override
public void normalY(int index, float normalY) {
if (normalOffset < 0) return;
MemoryUtil.memPutByte(idxPtr(index) + normalOffset + 1, RenderMath.nb(normalY));
}
@Override
public void normalZ(int index, float normalZ) {
if (normalOffset < 0) return;
MemoryUtil.memPutByte(idxPtr(index) + normalOffset + 2, RenderMath.nb(normalZ));
}
@Override
public int getVertexCount() {
return vertexCount;
}
@Override
public long ptr() {
return ptr;
}
@Override
public void ptr(long ptr) {
this.ptr = ptr;
}
@Override
public void shiftPtr(int vertices) {
ptr += vertices * stride;
}
@Override
public void setVertexCount(int vertexCount) {
this.vertexCount = vertexCount;
}
}

View file

@ -0,0 +1,20 @@
package com.jozufozu.flywheel.core.vertex;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.api.vertex.VertexListProvider;
import com.mojang.blaze3d.vertex.VertexFormat;
public class InferredVertexListProviderImpl implements VertexListProvider {
private final VertexFormat format;
private final InferredVertexFormatInfo formatInfo;
public InferredVertexListProviderImpl(VertexFormat format) {
this.format = format;
formatInfo = new InferredVertexFormatInfo(format);
}
@Override
public ReusableVertexList createVertexList() {
return new InferredVertexListImpl(formatInfo);
}
}

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.core.vertex; package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.core.Components; import com.jozufozu.flywheel.core.Components;
import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.layout.BufferLayout;
@ -9,7 +7,6 @@ import com.jozufozu.flywheel.core.layout.CommonItems;
import com.jozufozu.flywheel.core.source.FileResolution; import com.jozufozu.flywheel.core.source.FileResolution;
public class PosTexNormalVertex implements VertexType { public class PosTexNormalVertex implements VertexType {
public static final BufferLayout FORMAT = BufferLayout.builder() public static final BufferLayout FORMAT = BufferLayout.builder()
.addItems(CommonItems.VEC3, CommonItems.UV, CommonItems.NORMAL) .addItems(CommonItems.VEC3, CommonItems.UV, CommonItems.NORMAL)
.build(); .build();
@ -19,18 +16,13 @@ public class PosTexNormalVertex implements VertexType {
return FORMAT; return FORMAT;
} }
@Override
public PosTexNormalWriterUnsafe createWriter(ByteBuffer buffer) {
return new PosTexNormalWriterUnsafe(this, buffer);
}
@Override
public PosTexNormalVertexListUnsafe createReader(ByteBuffer buffer, int vertexCount) {
return new PosTexNormalVertexListUnsafe(buffer, vertexCount);
}
@Override @Override
public FileResolution getLayoutShader() { public FileResolution getLayoutShader() {
return Components.Files.POS_TEX_NORMAL_LAYOUT; return Components.Files.POS_TEX_NORMAL_LAYOUT;
} }
@Override
public PosTexNormalVertexList createVertexList() {
return new PosTexNormalVertexList();
}
} }

View file

@ -0,0 +1,154 @@
package com.jozufozu.flywheel.core.vertex;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.RenderMath;
import net.minecraft.client.renderer.texture.OverlayTexture;
public class PosTexNormalVertexList extends AbstractVertexList {
protected static final int STRIDE = 23;
protected long idxPtr(long idx) {
return ptr + idx * STRIDE;
}
@Override
public float x(int index) {
return MemoryUtil.memGetFloat(idxPtr(index));
}
@Override
public float y(int index) {
return MemoryUtil.memGetFloat(idxPtr(index) + 4);
}
@Override
public float z(int index) {
return MemoryUtil.memGetFloat(idxPtr(index) + 8);
}
@Override
public byte r(int index) {
return (byte) 0xFF;
}
@Override
public byte g(int index) {
return (byte) 0xFF;
}
@Override
public byte b(int index) {
return (byte) 0xFF;
}
@Override
public byte a(int index) {
return (byte) 0xFF;
}
@Override
public float u(int index) {
return MemoryUtil.memGetFloat(idxPtr(index) + 12);
}
@Override
public float v(int index) {
return MemoryUtil.memGetFloat(idxPtr(index) + 16);
}
@Override
public int overlay(int index) {
return OverlayTexture.NO_OVERLAY;
}
@Override
public int light(int index) {
return 0;
}
@Override
public float normalX(int index) {
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 20));
}
@Override
public float normalY(int index) {
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 21));
}
@Override
public float normalZ(int index) {
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 22));
}
@Override
public void x(int index, float x) {
MemoryUtil.memPutFloat(idxPtr(index), x);
}
@Override
public void y(int index, float y) {
MemoryUtil.memPutFloat(idxPtr(index) + 4, y);
}
@Override
public void z(int index, float z) {
MemoryUtil.memPutFloat(idxPtr(index) + 8, z);
}
@Override
public void r(int index, byte r) {
}
@Override
public void g(int index, byte g) {
}
@Override
public void b(int index, byte b) {
}
@Override
public void a(int index, byte a) {
}
@Override
public void u(int index, float u) {
MemoryUtil.memPutFloat(idxPtr(index) + 12, u);
}
@Override
public void v(int index, float v) {
MemoryUtil.memPutFloat(idxPtr(index) + 16, v);
}
@Override
public void overlay(int index, int overlay) {
}
@Override
public void light(int index, int light) {
}
@Override
public void normalX(int index, float normalX) {
MemoryUtil.memPutByte(idxPtr(index) + 20, RenderMath.nb(normalX));
}
@Override
public void normalY(int index, float normalY) {
MemoryUtil.memPutByte(idxPtr(index) + 21, RenderMath.nb(normalY));
}
@Override
public void normalZ(int index, float normalZ) {
MemoryUtil.memPutByte(idxPtr(index) + 22, RenderMath.nb(normalZ));
}
@Override
public void shiftPtr(int vertices) {
ptr += vertices * STRIDE;
}
}

View file

@ -1,90 +0,0 @@
package com.jozufozu.flywheel.core.vertex;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.util.RenderMath;
import net.minecraft.client.renderer.texture.OverlayTexture;
public class PosTexNormalVertexListUnsafe extends AbstractVertexList {
public PosTexNormalVertexListUnsafe(ByteBuffer copyFrom, int vertexCount) {
super(copyFrom, vertexCount);
}
private long ptr(long idx) {
return base + idx * 23;
}
@Override
public float x(int index) {
return MemoryUtil.memGetFloat(ptr(index));
}
@Override
public float y(int index) {
return MemoryUtil.memGetFloat(ptr(index) + 4);
}
@Override
public float z(int index) {
return MemoryUtil.memGetFloat(ptr(index) + 8);
}
@Override
public byte r(int index) {
return (byte) 0xFF;
}
@Override
public byte g(int index) {
return (byte) 0xFF;
}
@Override
public byte b(int index) {
return (byte) 0xFF;
}
@Override
public byte a(int index) {
return (byte) 0xFF;
}
@Override
public float u(int index) {
return MemoryUtil.memGetFloat(ptr(index) + 12);
}
@Override
public float v(int index) {
return MemoryUtil.memGetFloat(ptr(index) + 16);
}
@Override
public int overlay(int index) {
return OverlayTexture.NO_OVERLAY;
}
@Override
public int light(int index) {
return 0;
}
@Override
public float normalX(int index) {
return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 20));
}
@Override
public float normalY(int index) {
return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 21));
}
@Override
public float normalZ(int index) {
return RenderMath.f(MemoryUtil.memGetByte(ptr(index) + 22));
}
}

View file

@ -1,44 +0,0 @@
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.x(i);
float y = list.y(i);
float z = list.z(i);
float u = list.u(i);
float v = list.v(i);
float xN = list.normalX(i);
float yN = list.normalY(i);
float zN = list.normalZ(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;
}
}

View file

@ -1,41 +0,0 @@
package com.jozufozu.flywheel.core.vertex;
import java.lang.ref.Cleaner;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.vertex.VertexList;
import com.jozufozu.flywheel.backend.FlywheelMemory;
import com.mojang.blaze3d.platform.MemoryTracker;
public abstract class TrackedVertexList implements VertexList, AutoCloseable {
protected final ByteBuffer contents;
protected final long base;
protected final int vertexCount;
private final Cleaner.Cleanable cleanable;
protected TrackedVertexList(ByteBuffer copyFrom, int vertexCount) {
this.contents = MemoryTracker.create(copyFrom.capacity());
this.contents.order(copyFrom.order());
this.contents.put(copyFrom);
((Buffer) this.contents).flip();
this.cleanable = FlywheelMemory.track(this, this.contents);
this.base = MemoryUtil.memAddress(this.contents);
this.vertexCount = vertexCount;
}
@Override
public void close() {
cleanable.clean();
}
@Override
public int getVertexCount() {
return vertexCount;
}
}

View file

@ -0,0 +1,55 @@
package com.jozufozu.flywheel.core.vertex;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jetbrains.annotations.Nullable;
import com.jozufozu.flywheel.api.vertex.VertexListProvider;
import com.mojang.blaze3d.vertex.VertexFormat;
public class VertexListProviderRegistry {
private static final Map<VertexFormat, Holder> HOLDERS = new ConcurrentHashMap<>();
private static Holder getOrCreateHolder(VertexFormat format) {
return HOLDERS.computeIfAbsent(format, Holder::new);
}
public static void register(VertexFormat format, VertexListProvider provider) {
getOrCreateHolder(format).registeredProvider = provider;
}
@Nullable
public static VertexListProvider get(VertexFormat format) {
return getOrCreateHolder(format).get();
}
public static VertexListProvider getOrInfer(VertexFormat format) {
return getOrCreateHolder(format).getOrInfer();
}
private static class Holder {
public final VertexFormat format;
public VertexListProvider registeredProvider;
public VertexListProvider inferredProvider;
public Holder(VertexFormat format) {
this.format = format;
}
@Nullable
public VertexListProvider get() {
return registeredProvider;
}
public VertexListProvider getOrInfer() {
if (registeredProvider != null) {
return registeredProvider;
}
if (inferredProvider == null) {
inferredProvider = new InferredVertexListProviderImpl(format);
}
return inferredProvider;
}
}
}

View file

@ -1,33 +0,0 @@
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;
protected long ptr;
protected VertexWriterUnsafe(V type, ByteBuffer buffer) {
this.type = type;
this.buffer = buffer;
this.ptr = MemoryUtil.memAddress(buffer);
}
@Override
public void seek(long offset) {
buffer.position((int) offset);
ptr = MemoryUtil.memAddress(buffer);
}
@Override
public VertexList intoReader(int vertices) {
return type.createReader(buffer, vertices);
}
}