mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-07 02:34:58 +01:00
Merge branch '1.18/next' into 1.18/culling
# Conflicts: # src/main/java/com/jozufozu/flywheel/api/struct/StructType.java # src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java # src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/MeshPool.java # src/main/java/com/jozufozu/flywheel/core/hardcoded/ModelPart.java # src/main/java/com/jozufozu/flywheel/core/model/Mesh.java # src/main/java/com/jozufozu/flywheel/core/model/ModelUtil.java # src/main/java/com/jozufozu/flywheel/core/model/SimpleMesh.java # src/main/java/com/jozufozu/flywheel/core/structs/model/TransformedWriterUnsafe.java # src/main/java/com/jozufozu/flywheel/core/structs/oriented/OrientedType.java # src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedStorageWriter.java # src/main/java/com/jozufozu/flywheel/core/structs/transformed/TransformedType.java # src/main/java/com/jozufozu/flywheel/core/uniform/ViewProvider.java
This commit is contained in:
commit
de09331e9b
90 changed files with 1717 additions and 1802 deletions
|
@ -22,7 +22,7 @@ public interface Material {
|
|||
|
||||
VertexTransformer getVertexTransformer();
|
||||
|
||||
public interface VertexTransformer {
|
||||
interface VertexTransformer {
|
||||
void transform(MutableVertexList vertexList, ClientLevel level);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.jozufozu.flywheel.api.struct;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
|
@ -25,22 +23,17 @@ public interface StructType<S extends InstancedPart> {
|
|||
*/
|
||||
BufferLayout getLayout();
|
||||
|
||||
/**
|
||||
* Create a {@link StructWriter} that will consume instances of S and write them to the given buffer.
|
||||
*
|
||||
* @param backing The buffer that the StructWriter will write to.
|
||||
*/
|
||||
StructWriter<S> getWriter(ByteBuffer backing);
|
||||
StructWriter<S> getWriter();
|
||||
|
||||
FileResolution getInstanceShader();
|
||||
|
||||
VertexTransformer<? extends S> getVertexTransformer();
|
||||
VertexTransformer<S> getVertexTransformer();
|
||||
|
||||
StorageBufferWriter<S> getStorageBufferWriter();
|
||||
|
||||
FileResolution getIndirectShader();
|
||||
|
||||
public interface VertexTransformer<S extends InstancedPart> {
|
||||
interface VertexTransformer<S extends InstancedPart> {
|
||||
void transform(MutableVertexList vertexList, S struct, ClientLevel level);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
package com.jozufozu.flywheel.api.struct;
|
||||
|
||||
/**
|
||||
* StructWriters can quickly consume many instances of S and write them to some backing buffer.
|
||||
*/
|
||||
public interface StructWriter<S> {
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
|
||||
/**
|
||||
* Write the given struct to the backing array.
|
||||
* StructWriters can quickly consume many instances of S and write them to some memory address.
|
||||
*/
|
||||
void write(S struct);
|
||||
|
||||
public interface StructWriter<S extends InstancedPart> {
|
||||
/**
|
||||
* Seek to the given position. The next write will occur there.
|
||||
* Write the given struct to the given memory address.
|
||||
*/
|
||||
void seek(int pos);
|
||||
void write(long ptr, S struct);
|
||||
}
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
package com.jozufozu.flywheel.api.uniform;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
|
||||
public abstract class UniformProvider {
|
||||
|
||||
protected ByteBuffer buffer;
|
||||
protected long ptr;
|
||||
protected Notifier notifier;
|
||||
|
||||
public abstract int getActualByteSize();
|
||||
|
||||
public void updatePtr(ByteBuffer backing, Notifier notifier) {
|
||||
this.buffer = backing;
|
||||
public void updatePtr(long ptr, Notifier notifier) {
|
||||
this.ptr = ptr;
|
||||
this.notifier = notifier;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -44,6 +44,37 @@ public interface VertexList extends PointSet {
|
|||
|
||||
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();
|
||||
|
||||
default boolean isEmpty() {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package com.jozufozu.flywheel.api.vertex;
|
||||
|
||||
public interface VertexListProvider {
|
||||
ReusableVertexList createVertexList();
|
||||
}
|
|
@ -1,38 +1,18 @@
|
|||
package com.jozufozu.flywheel.api.vertex;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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();
|
||||
|
||||
default int getStride() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
public class FlywheelMemory {
|
||||
|
||||
public static final Cleaner CLEANER = Cleaner.create();
|
||||
|
||||
private static int gpuMemory = 0;
|
||||
private static int cpuMemory = 0;
|
||||
|
||||
public static void _freeCPUMemory(long size) {
|
||||
cpuMemory -= size;
|
||||
}
|
||||
|
||||
public static void _allocCPUMemory(long size) {
|
||||
cpuMemory += size;
|
||||
}
|
||||
|
||||
public static void _freeGPUMemory(long size) {
|
||||
gpuMemory -= size;
|
||||
}
|
||||
|
||||
public static void _allocGPUMemory(long size) {
|
||||
gpuMemory += size;
|
||||
}
|
||||
|
||||
public static int getGPUMemory() {
|
||||
return gpuMemory;
|
||||
}
|
||||
|
||||
public static int getCPUMemory() {
|
||||
return cpuMemory;
|
||||
}
|
||||
|
||||
public static Cleaner.Cleanable track(Object owner, ByteBuffer buffer) {
|
||||
return CLEANER.register(owner, new Tracked(buffer));
|
||||
}
|
||||
|
||||
public static class Tracked implements Runnable {
|
||||
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
public Tracked(ByteBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
_allocCPUMemory(buffer.capacity());
|
||||
}
|
||||
|
||||
public void run() {
|
||||
_freeCPUMemory(buffer.capacity());
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,49 +1,111 @@
|
|||
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import static org.lwjgl.opengl.GL15.glBufferData;
|
||||
import static org.lwjgl.opengl.GL15.glDeleteBuffers;
|
||||
import static org.lwjgl.opengl.GL15.glGenBuffers;
|
||||
import static org.lwjgl.opengl.GL15.nglBufferData;
|
||||
import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_BIT;
|
||||
import static org.lwjgl.opengl.GL30.nglMapBufferRange;
|
||||
import static org.lwjgl.opengl.GL31.glCopyBufferSubData;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.GlObject;
|
||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
|
||||
public abstract class GlBuffer extends GlObject {
|
||||
|
||||
/**
|
||||
* Request a Persistent mapped buffer.
|
||||
*
|
||||
* <p>
|
||||
* If Persistent buffers are supported, this will provide one. Otherwise it will fall back to a classic mapped
|
||||
* buffer.
|
||||
* </p>
|
||||
*
|
||||
* @param type The type of buffer you want.
|
||||
* @return A buffer that will be persistent if the driver supports it.
|
||||
*/
|
||||
public static GlBuffer requestPersistent(GlBufferType type) {
|
||||
if (GlCompat.getInstance()
|
||||
.bufferStorageSupported()) {
|
||||
return new PersistentGlBuffer(type);
|
||||
} else {
|
||||
return new MappedGlBuffer(type);
|
||||
}
|
||||
}
|
||||
public class GlBuffer extends GlObject {
|
||||
|
||||
public final GlBufferType type;
|
||||
|
||||
protected final GlBufferUsage usage;
|
||||
/**
|
||||
* The size (in bytes) of the buffer on the GPU.
|
||||
*/
|
||||
protected long size;
|
||||
|
||||
/**
|
||||
* How much extra room to give the buffer when we reallocate.
|
||||
*/
|
||||
protected int growthMargin;
|
||||
|
||||
public GlBuffer(GlBufferType type) {
|
||||
setHandle(GL20.glGenBuffers());
|
||||
this(type, GlBufferUsage.STATIC_DRAW);
|
||||
}
|
||||
|
||||
public GlBuffer(GlBufferType type, GlBufferUsage usage) {
|
||||
setHandle(glGenBuffers());
|
||||
this.type = type;
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
public boolean ensureCapacity(long size) {
|
||||
if (size < 0) {
|
||||
throw new IllegalArgumentException("Size " + size + " < 0");
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.size == 0) {
|
||||
this.size = size;
|
||||
bind();
|
||||
glBufferData(type.glEnum, size, usage.glEnum);
|
||||
FlwMemoryTracker._allocGPUMemory(size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (size > this.size) {
|
||||
var oldSize = this.size;
|
||||
this.size = size + growthMargin;
|
||||
|
||||
realloc(oldSize, this.size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void realloc(long oldSize, long newSize) {
|
||||
FlwMemoryTracker._freeGPUMemory(oldSize);
|
||||
FlwMemoryTracker._allocGPUMemory(newSize);
|
||||
var oldHandle = handle();
|
||||
var newHandle = glGenBuffers();
|
||||
|
||||
GlBufferType.COPY_READ_BUFFER.bind(oldHandle);
|
||||
type.bind(newHandle);
|
||||
|
||||
glBufferData(type.glEnum, newSize, usage.glEnum);
|
||||
glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize);
|
||||
|
||||
glDeleteBuffers(oldHandle);
|
||||
setHandle(newHandle);
|
||||
}
|
||||
|
||||
public void upload(MemoryBlock directBuffer) {
|
||||
bind();
|
||||
FlwMemoryTracker._freeGPUMemory(size);
|
||||
nglBufferData(type.glEnum, directBuffer.size(), directBuffer.ptr(), usage.glEnum);
|
||||
this.size = directBuffer.size();
|
||||
FlwMemoryTracker._allocGPUMemory(size);
|
||||
}
|
||||
|
||||
public MappedBuffer map() {
|
||||
bind();
|
||||
long ptr = nglMapBufferRange(type.glEnum, 0, size, GL_MAP_WRITE_BIT);
|
||||
|
||||
if (ptr == MemoryUtil.NULL) {
|
||||
throw new GlException(GlError.poll(), "Could not map buffer");
|
||||
}
|
||||
|
||||
return new MappedBuffer(this, ptr, 0, size);
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setGrowthMargin(int growthMargin) {
|
||||
|
@ -66,24 +128,8 @@ public abstract class GlBuffer extends GlObject {
|
|||
type.unbind();
|
||||
}
|
||||
|
||||
public abstract void upload(ByteBuffer directBuffer);
|
||||
|
||||
public abstract MappedBuffer map();
|
||||
|
||||
/**
|
||||
* Ensure that the buffer has at least enough room to store {@code size} bytes.
|
||||
*
|
||||
* @return {@code true} if the buffer moved.
|
||||
*/
|
||||
public abstract boolean ensureCapacity(long size);
|
||||
|
||||
protected void deleteInternal(int handle) {
|
||||
GL20.glDeleteBuffers(handle);
|
||||
glDeleteBuffers(handle);
|
||||
FlwMemoryTracker._freeGPUMemory(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this buffer need not be #flush()'d for its contents to sync.
|
||||
* @return true if this buffer is persistently mapped.
|
||||
*/
|
||||
public abstract boolean isPersistent();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import static org.lwjgl.system.MemoryUtil.NULL;
|
||||
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
@ -11,10 +11,10 @@ public class MappedBuffer implements AutoCloseable {
|
|||
private final long length;
|
||||
private final GlBuffer owner;
|
||||
private final boolean persistent;
|
||||
private ByteBuffer internal;
|
||||
private long ptr;
|
||||
|
||||
public MappedBuffer(GlBuffer owner, ByteBuffer internal, long offset, long length) {
|
||||
this.internal = internal;
|
||||
public MappedBuffer(GlBuffer owner, long ptr, long offset, long length) {
|
||||
this.ptr = ptr;
|
||||
this.owner = owner;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
|
@ -27,19 +27,11 @@ public class MappedBuffer implements AutoCloseable {
|
|||
public void flush() {
|
||||
if (persistent) return;
|
||||
|
||||
if (internal == null) return;
|
||||
if (ptr == NULL) return;
|
||||
|
||||
owner.bind();
|
||||
GL15.glUnmapBuffer(owner.getType().glEnum);
|
||||
internal = null;
|
||||
}
|
||||
|
||||
public MappedBuffer position(int p) {
|
||||
if (p < offset || p >= offset + length) {
|
||||
throw new IndexOutOfBoundsException("Index " + p + " is not mapped");
|
||||
}
|
||||
internal.position(p - (int) offset);
|
||||
return this;
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,12 +39,8 @@ public class MappedBuffer implements AutoCloseable {
|
|||
flush();
|
||||
}
|
||||
|
||||
public ByteBuffer unwrap() {
|
||||
return internal;
|
||||
}
|
||||
|
||||
public long getMemAddress() {
|
||||
return MemoryUtil.memAddress(internal);
|
||||
public long getPtr() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
public void clear(long clearStart, long clearLength) {
|
||||
|
@ -64,7 +52,7 @@ public class MappedBuffer implements AutoCloseable {
|
|||
throw new IndexOutOfBoundsException("Clear range [" + clearStart + "," + (clearStart + clearLength) + "] is not mapped");
|
||||
}
|
||||
|
||||
long addr = MemoryUtil.memAddress(unwrap()) + clearStart;
|
||||
long addr = ptr + clearStart;
|
||||
|
||||
MemoryUtil.memSet(addr, 0, clearLength);
|
||||
}
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||
|
||||
public class MappedGlBuffer extends GlBuffer {
|
||||
|
||||
protected final GlBufferUsage usage;
|
||||
|
||||
public MappedGlBuffer(GlBufferType type) {
|
||||
this(type, GlBufferUsage.STATIC_DRAW);
|
||||
}
|
||||
|
||||
public MappedGlBuffer(GlBufferType type, GlBufferUsage usage) {
|
||||
super(type);
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ensureCapacity(long size) {
|
||||
if (size < 0) {
|
||||
throw new IllegalArgumentException("Size " + size + " < 0");
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.size == 0) {
|
||||
this.size = size;
|
||||
bind();
|
||||
GL32.glBufferData(type.glEnum, size, usage.glEnum);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (size > this.size) {
|
||||
var oldSize = this.size;
|
||||
this.size = size + growthMargin;
|
||||
|
||||
realloc(oldSize, this.size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void realloc(long oldSize, long newSize) {
|
||||
var oldHandle = handle();
|
||||
var newHandle = GL32.glGenBuffers();
|
||||
|
||||
GlBufferType.COPY_READ_BUFFER.bind(oldHandle);
|
||||
type.bind(newHandle);
|
||||
|
||||
GL32.glBufferData(type.glEnum, newSize, usage.glEnum);
|
||||
GL32.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize);
|
||||
|
||||
delete();
|
||||
setHandle(newHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upload(ByteBuffer directBuffer) {
|
||||
bind();
|
||||
GL32.glBufferData(type.glEnum, directBuffer, usage.glEnum);
|
||||
this.size = directBuffer.capacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedBuffer map() {
|
||||
bind();
|
||||
ByteBuffer byteBuffer = GL30.glMapBufferRange(type.glEnum, 0, size, GL30.GL_MAP_WRITE_BIT);
|
||||
|
||||
if (byteBuffer == null) {
|
||||
throw new GlException(GlError.poll(), "Could not map buffer");
|
||||
}
|
||||
|
||||
return new MappedBuffer(this, byteBuffer, 0, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.gl.buffer;
|
||||
|
||||
import static org.lwjgl.opengl.GL30.GL_MAP_WRITE_BIT;
|
||||
import static org.lwjgl.opengl.GL44.GL_MAP_COHERENT_BIT;
|
||||
import static org.lwjgl.opengl.GL44.GL_MAP_PERSISTENT_BIT;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlError;
|
||||
import com.jozufozu.flywheel.backend.gl.error.GlException;
|
||||
import com.jozufozu.flywheel.backend.gl.versioned.GlCompat;
|
||||
|
||||
public class PersistentGlBuffer extends GlBuffer {
|
||||
|
||||
@Nullable
|
||||
private MappedBuffer access;
|
||||
private final int storageFlags;
|
||||
|
||||
public PersistentGlBuffer(GlBufferType type) {
|
||||
super(type);
|
||||
|
||||
storageFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ensureCapacity(long size) {
|
||||
if (size < 0) {
|
||||
throw new IllegalArgumentException("Size " + size + " < 0");
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.size == 0) {
|
||||
this.size = size;
|
||||
bind();
|
||||
GlCompat.getInstance().bufferStorage.bufferStorage(type, this.size, storageFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (size > this.size) {
|
||||
var oldSize = this.size;
|
||||
this.size = size + growthMargin;
|
||||
|
||||
realloc(this.size, oldSize);
|
||||
|
||||
access = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upload(ByteBuffer directBuffer) {
|
||||
ensureCapacity(directBuffer.capacity());
|
||||
|
||||
var access = getWriteAccess();
|
||||
|
||||
ByteBuffer ourBuffer = access.unwrap();
|
||||
|
||||
ourBuffer.reset();
|
||||
|
||||
MemoryUtil.memCopy(directBuffer, ourBuffer);
|
||||
|
||||
int uploadSize = directBuffer.remaining();
|
||||
int ourSize = ourBuffer.capacity();
|
||||
|
||||
if (uploadSize < ourSize) {
|
||||
long clearFrom = access.getMemAddress() + uploadSize;
|
||||
MemoryUtil.memSet(clearFrom, 0, ourSize - uploadSize);
|
||||
}
|
||||
}
|
||||
|
||||
private void mapToClientMemory() {
|
||||
bind();
|
||||
ByteBuffer byteBuffer = GL32.glMapBufferRange(type.glEnum, 0, size, storageFlags);
|
||||
|
||||
if (byteBuffer == null) {
|
||||
throw new GlException(GlError.poll(), "Could not map buffer");
|
||||
}
|
||||
|
||||
access = new MappedBuffer(this, byteBuffer, 0, size);
|
||||
}
|
||||
|
||||
private void realloc(long newSize, long oldSize) {
|
||||
int oldHandle = handle();
|
||||
int newHandle = GL32.glGenBuffers();
|
||||
|
||||
GlBufferType.COPY_READ_BUFFER.bind(oldHandle);
|
||||
type.bind(newHandle);
|
||||
|
||||
GlCompat.getInstance().bufferStorage.bufferStorage(type, newSize, storageFlags);
|
||||
|
||||
GL32.glCopyBufferSubData(GlBufferType.COPY_READ_BUFFER.glEnum, type.glEnum, 0, 0, oldSize);
|
||||
|
||||
delete();
|
||||
setHandle(newHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedBuffer map() {
|
||||
return getWriteAccess()
|
||||
.position(0);
|
||||
}
|
||||
|
||||
private MappedBuffer getWriteAccess() {
|
||||
if (access == null) {
|
||||
mapToClientMemory();
|
||||
}
|
||||
|
||||
return access;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ import org.lwjgl.opengl.GL;
|
|||
import org.lwjgl.opengl.GL20C;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import net.minecraft.Util;
|
||||
|
||||
|
@ -78,7 +77,7 @@ public class GlCompat {
|
|||
}
|
||||
|
||||
/**
|
||||
* Copied from:
|
||||
* Modified from:
|
||||
* <br> <a href="https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96">canvas</a>
|
||||
*
|
||||
* <p>Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but
|
||||
|
@ -90,18 +89,11 @@ public class GlCompat {
|
|||
* <p>Hat tip to fewizz for the find and the fix.
|
||||
*/
|
||||
public static void safeShaderSource(int glId, CharSequence source) {
|
||||
final MemoryStack stack = MemoryStack.stackGet();
|
||||
final int stackPointer = stack.getPointer();
|
||||
|
||||
try {
|
||||
final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true);
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
final ByteBuffer sourceBuffer = stack.UTF8(source, true);
|
||||
final PointerBuffer pointers = stack.mallocPointer(1);
|
||||
pointers.put(sourceBuffer);
|
||||
|
||||
GL20C.nglShaderSource(glId, 1, pointers.address0(), 0);
|
||||
org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1);
|
||||
} finally {
|
||||
stack.setPointer(stackPointer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import java.util.List;
|
|||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
|
||||
public abstract class AbstractInstancer<D extends InstancedPart> implements Instancer<D> {
|
||||
|
||||
|
@ -114,22 +113,6 @@ public abstract class AbstractInstancer<D extends InstancedPart> implements Inst
|
|||
return instanceData;
|
||||
}
|
||||
|
||||
protected void writeChangedUnchecked(StructWriter<D> writer) {
|
||||
boolean sequential = true;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
final D element = data.get(i);
|
||||
if (element.checkDirtyAndClear()) {
|
||||
if (!sequential) {
|
||||
writer.seek(i);
|
||||
}
|
||||
writer.write(element);
|
||||
sequential = true;
|
||||
} else {
|
||||
sequential = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void delete();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,7 +28,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
|||
* The instancer manager is shared between the different instance managers.
|
||||
* </p>
|
||||
*/
|
||||
public class InstanceWorld {
|
||||
public class InstanceWorld implements AutoCloseable {
|
||||
protected final Engine engine;
|
||||
protected final InstanceManager<Entity> entities;
|
||||
protected final InstanceManager<BlockEntity> blockEntities;
|
||||
|
@ -148,4 +148,8 @@ public class InstanceWorld {
|
|||
.forEach(entities::add);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,7 @@ import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
|||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||
import com.jozufozu.flywheel.core.RenderContext;
|
||||
import com.jozufozu.flywheel.util.FlwUtil;
|
||||
import com.mojang.blaze3d.platform.Lighting;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
@ -68,19 +66,11 @@ public class BatchingEngine implements Engine {
|
|||
@Override
|
||||
public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) {
|
||||
// FIXME: properly support material stages
|
||||
// This also breaks block outlines on batched block entities
|
||||
if (stage != RenderStage.AFTER_FINAL_END_BATCH) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: this probably breaks some vanilla stuff but it works much better for flywheel
|
||||
Matrix4f mat = new Matrix4f();
|
||||
mat.setIdentity();
|
||||
if (context.level().effects().constantAmbientLight()) {
|
||||
Lighting.setupNetherLevel(mat);
|
||||
} else {
|
||||
Lighting.setupLevel(mat);
|
||||
}
|
||||
|
||||
batchTracker.endBatch();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,28 +2,35 @@ package com.jozufozu.flywheel.backend.instancing.batching;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexListProvider;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
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.
|
||||
*/
|
||||
public class DrawBuffer {
|
||||
private final RenderType parent;
|
||||
private final VertexFormatInfo formatInfo;
|
||||
private final VertexFormat format;
|
||||
private final int stride;
|
||||
private final VertexListProvider provider;
|
||||
|
||||
private MemoryBlock memory;
|
||||
private ByteBuffer buffer;
|
||||
|
||||
private ByteBuffer backingBuffer;
|
||||
private int expectedVertices;
|
||||
private long ptr;
|
||||
|
||||
public DrawBuffer(RenderType parent) {
|
||||
this.parent = parent;
|
||||
formatInfo = new VertexFormatInfo(parent.format());
|
||||
format = parent.format();
|
||||
stride = format.getVertexSize();
|
||||
provider = VertexListProviderRegistry.getOrInfer(format);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,29 +40,32 @@ public class DrawBuffer {
|
|||
*/
|
||||
public void prepare(int vertexCount) {
|
||||
if (expectedVertices != 0) {
|
||||
throw new IllegalStateException("Already drawing");
|
||||
throw new IllegalStateException("Already drawing!");
|
||||
}
|
||||
|
||||
this.expectedVertices = vertexCount;
|
||||
|
||||
// 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.
|
||||
int byteSize = formatInfo.stride * (vertexCount + 1);
|
||||
int byteSize = stride * (vertexCount + 1);
|
||||
|
||||
if (backingBuffer == null) {
|
||||
backingBuffer = MemoryTracker.create(byteSize);
|
||||
} else if (byteSize > backingBuffer.capacity()) {
|
||||
backingBuffer = MemoryTracker.resize(backingBuffer, byteSize);
|
||||
if (memory == null) {
|
||||
memory = MemoryBlock.malloc(byteSize);
|
||||
buffer = memory.asBuffer();
|
||||
} else if (byteSize > memory.size()) {
|
||||
memory = memory.realloc(byteSize);
|
||||
buffer = memory.asBuffer();
|
||||
}
|
||||
|
||||
backingBuffer.clear();
|
||||
ptr = MemoryUtil.memAddress(backingBuffer);
|
||||
MemoryUtil.memSet(ptr, 0, byteSize);
|
||||
memory.clear();
|
||||
}
|
||||
|
||||
public MutableVertexListImpl slice(int startVertex, int vertexCount) {
|
||||
return new MutableVertexListImpl(ptr + startVertex * formatInfo.stride, formatInfo, vertexCount);
|
||||
public ReusableVertexList slice(int startVertex, int vertexCount) {
|
||||
ReusableVertexList vertexList = provider.createVertexList();
|
||||
vertexList.ptr(memory.ptr() + startVertex * stride);
|
||||
vertexList.setVertexCount(vertexCount);
|
||||
return vertexList;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,7 +73,8 @@ public class DrawBuffer {
|
|||
* @param bufferBuilder The buffer builder to inject into.
|
||||
*/
|
||||
public void inject(BufferBuilderExtension bufferBuilder) {
|
||||
bufferBuilder.flywheel$injectForRender(backingBuffer, formatInfo.format, expectedVertices);
|
||||
buffer.clear();
|
||||
bufferBuilder.flywheel$injectForRender(buffer, format, expectedVertices);
|
||||
}
|
||||
|
||||
public int getVertexCount() {
|
||||
|
@ -78,11 +89,16 @@ public class DrawBuffer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Reset the draw buffer to have no vertices.
|
||||
* Reset the draw buffer to have no vertices.<p>
|
||||
*
|
||||
* Does not clear the backing buffer.
|
||||
*/
|
||||
public void reset() {
|
||||
this.expectedVertices = 0;
|
||||
}
|
||||
|
||||
public void free() {
|
||||
buffer = null;
|
||||
memory.free();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -5,9 +5,8 @@ import java.util.List;
|
|||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructType.VertexTransformer;
|
||||
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.core.model.Mesh;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
@ -49,80 +48,50 @@ public class TransformSet<D extends InstancedPart> {
|
|||
int start = Math.max(instances, 0);
|
||||
|
||||
int vertexCount = mesh.getVertexCount() * (end - start);
|
||||
MutableVertexListImpl sub = buffer.slice(startVertex, vertexCount);
|
||||
ReusableVertexList sub = buffer.slice(startVertex, vertexCount);
|
||||
startVertex += vertexCount;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void drawAll(MutableVertexListImpl vertexList, PoseStack stack, ClientLevel level) {
|
||||
void drawAll(ReusableVertexList vertexList, PoseStack stack, ClientLevel level) {
|
||||
drawList(vertexList, instancer.getAll(), stack, level);
|
||||
}
|
||||
|
||||
private void drawList(MutableVertexListImpl vertexList, List<D> list, PoseStack stack, ClientLevel level) {
|
||||
int startVertex = 0;
|
||||
int meshVertexCount = mesh.getVertexCount();
|
||||
private void drawList(ReusableVertexList vertexList, List<D> list, PoseStack stack, ClientLevel level) {
|
||||
long anchorPtr = vertexList.ptr();
|
||||
int totalVertexCount = vertexList.getVertexCount();
|
||||
|
||||
VertexList meshReader = mesh.getReader();
|
||||
@SuppressWarnings("unchecked")
|
||||
StructType.VertexTransformer<D> structVertexTransformer = (VertexTransformer<D>) instancer.type.getVertexTransformer();
|
||||
int meshVertexCount = mesh.getVertexCount();
|
||||
vertexList.setVertexCount(meshVertexCount);
|
||||
|
||||
StructType.VertexTransformer<D> structVertexTransformer = instancer.type.getVertexTransformer();
|
||||
|
||||
for (D d : list) {
|
||||
vertexList.setRange(startVertex, meshVertexCount);
|
||||
|
||||
writeMesh(vertexList, meshReader);
|
||||
mesh.write(vertexList);
|
||||
|
||||
structVertexTransformer.transform(vertexList, d, level);
|
||||
|
||||
startVertex += meshVertexCount;
|
||||
vertexList.shiftPtr(meshVertexCount);
|
||||
}
|
||||
|
||||
vertexList.setFullRange();
|
||||
vertexList.ptr(anchorPtr);
|
||||
vertexList.setVertexCount(totalVertexCount);
|
||||
material.getVertexTransformer().transform(vertexList, level);
|
||||
applyPoseStack(vertexList, stack, false);
|
||||
applyPoseStack(vertexList, stack);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
Vector4f pos = new Vector4f();
|
||||
Vector3f normal = new Vector3f();
|
||||
|
||||
Matrix4f modelMatrix = stack.last().pose();
|
||||
Matrix3f normalMatrix;
|
||||
if (applyNormalMatrix) {
|
||||
normalMatrix = stack.last().normal();
|
||||
} else {
|
||||
normalMatrix = null;
|
||||
}
|
||||
Matrix3f normalMatrix = stack.last().normal();
|
||||
|
||||
for (int i = 0; i < vertexList.getVertexCount(); i++) {
|
||||
pos.set(
|
||||
|
@ -136,7 +105,6 @@ public class TransformSet<D extends InstancedPart> {
|
|||
vertexList.y(i, pos.y());
|
||||
vertexList.z(i, pos.z());
|
||||
|
||||
if (applyNormalMatrix) {
|
||||
normal.set(
|
||||
vertexList.normalX(i),
|
||||
vertexList.normalY(i),
|
||||
|
@ -149,7 +117,6 @@ public class TransformSet<D extends InstancedPart> {
|
|||
vertexList.normalZ(i, normal.z());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getTotalVertexCount() {
|
||||
return mesh.getVertexCount() * instancer.getInstanceCount();
|
||||
|
|
|
@ -10,8 +10,8 @@ import com.jozufozu.flywheel.api.instancer.InstancerFactory;
|
|||
import com.jozufozu.flywheel.api.instancer.InstancerManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
|
||||
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
|
||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||
import com.jozufozu.flywheel.util.joml.FrustumIntersection;
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.lwjgl.system.MemoryUtil;
|
|||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.model.Mesh;
|
||||
|
||||
public class IndirectMeshPool {
|
||||
|
@ -23,7 +24,7 @@ public class IndirectMeshPool {
|
|||
final VertexType vertexType;
|
||||
|
||||
final int vbo;
|
||||
private final ByteBuffer clientStorage;
|
||||
private final MemoryBlock clientStorage;
|
||||
|
||||
private boolean dirty;
|
||||
|
||||
|
@ -35,7 +36,7 @@ public class IndirectMeshPool {
|
|||
vbo = glCreateBuffers();
|
||||
var byteCapacity = type.byteOffset(vertexCapacity);
|
||||
glNamedBufferStorage(vbo, byteCapacity, GL_DYNAMIC_STORAGE_BIT);
|
||||
clientStorage = MemoryUtil.memAlloc(byteCapacity);
|
||||
clientStorage = MemoryBlock.malloc(byteCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,24 +66,25 @@ public class IndirectMeshPool {
|
|||
}
|
||||
dirty = false;
|
||||
|
||||
final long ptr = clientStorage.ptr();
|
||||
|
||||
int byteIndex = 0;
|
||||
int baseVertex = 0;
|
||||
for (BufferedMesh model : meshList) {
|
||||
model.byteIndex = byteIndex;
|
||||
model.baseVertex = baseVertex;
|
||||
|
||||
model.buffer(clientStorage);
|
||||
model.buffer(ptr);
|
||||
|
||||
byteIndex += model.getByteSize();
|
||||
baseVertex += model.mesh.getVertexCount();
|
||||
}
|
||||
|
||||
clientStorage.rewind();
|
||||
|
||||
glNamedBufferSubData(vbo, 0, clientStorage);
|
||||
nglNamedBufferSubData(vbo, 0, byteIndex, ptr);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
clientStorage.free();
|
||||
glDeleteBuffers(vbo);
|
||||
meshes.clear();
|
||||
meshList.clear();
|
||||
|
@ -101,10 +103,8 @@ public class IndirectMeshPool {
|
|||
vertexCount = mesh.getVertexCount();
|
||||
}
|
||||
|
||||
private void buffer(ByteBuffer buffer) {
|
||||
var writer = IndirectMeshPool.this.vertexType.createWriter(buffer);
|
||||
writer.seek(this.byteIndex);
|
||||
writer.writeVertexList(this.mesh.getReader());
|
||||
private void buffer(long ptr) {
|
||||
this.mesh.write(ptr + byteIndex);
|
||||
}
|
||||
|
||||
public int getByteSize() {
|
||||
|
|
|
@ -6,12 +6,12 @@ import java.util.Set;
|
|||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
|
|||
public void init() {
|
||||
if (vbo != null) return;
|
||||
|
||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW);
|
||||
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER, GlBufferUsage.DYNAMIC_DRAW);
|
||||
vbo.setGrowthMargin(instanceFormat.getStride() * 16);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,16 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
|
|||
buf.clear(clearStart, clearLength);
|
||||
|
||||
if (size > 0) {
|
||||
writeChangedUnchecked(structType.getWriter(buf.unwrap()));
|
||||
final long ptr = buf.getPtr();
|
||||
final long stride = structType.getLayout().getStride();
|
||||
final StructWriter<D> writer = structType.getWriter();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
final D element = data.get(i);
|
||||
if (element.checkDirtyAndClear()) {
|
||||
writer.write(ptr + i * stride, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error("Error updating GPUInstancer:", e);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.jozufozu.flywheel.backend.instancing.instancing;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -18,7 +17,7 @@ import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
|||
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.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.model.Mesh;
|
||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
|
@ -27,7 +26,7 @@ public class MeshPool {
|
|||
|
||||
private static MeshPool allocator;
|
||||
|
||||
static MeshPool getInstance() {
|
||||
public static MeshPool getInstance() {
|
||||
if (allocator == null) {
|
||||
allocator = new MeshPool();
|
||||
}
|
||||
|
@ -58,7 +57,7 @@ public class MeshPool {
|
|||
* Create a new mesh pool.
|
||||
*/
|
||||
public MeshPool() {
|
||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
|
||||
vbo.setGrowthMargin(2048);
|
||||
}
|
||||
|
@ -71,9 +70,8 @@ public class MeshPool {
|
|||
*/
|
||||
public BufferedMesh alloc(Mesh mesh) {
|
||||
return meshes.computeIfAbsent(mesh, m -> {
|
||||
// FIXME: culling experiments fixing everything to Formats.BLOCK
|
||||
BufferedMesh bufferedModel = new BufferedMesh(Formats.BLOCK, m, byteSize, vertexCount);
|
||||
byteSize += bufferedModel.getByteSize();
|
||||
BufferedMesh bufferedModel = new BufferedMesh(m, byteSize, vertexCount);
|
||||
byteSize += m.size();
|
||||
vertexCount += bufferedModel.mesh.getVertexCount();
|
||||
allBuffered.add(bufferedModel);
|
||||
pendingUpload.add(bufferedModel);
|
||||
|
@ -147,7 +145,7 @@ public class MeshPool {
|
|||
|
||||
private void uploadAll() {
|
||||
try (MappedBuffer mapped = vbo.map()) {
|
||||
ByteBuffer buffer = mapped.unwrap();
|
||||
long ptr = mapped.getPtr();
|
||||
|
||||
int byteIndex = 0;
|
||||
int baseVertex = 0;
|
||||
|
@ -155,26 +153,26 @@ public class MeshPool {
|
|||
model.byteIndex = byteIndex;
|
||||
model.baseVertex = baseVertex;
|
||||
|
||||
model.buffer(buffer);
|
||||
model.buffer(ptr);
|
||||
|
||||
byteIndex += model.getByteSize();
|
||||
baseVertex += model.mesh.getVertexCount();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error("Error uploading pooled models:", e);
|
||||
Flywheel.LOGGER.error("Error uploading pooled meshes:", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void uploadPending() {
|
||||
try (MappedBuffer mapped = vbo.map()) {
|
||||
ByteBuffer buffer = mapped.unwrap();
|
||||
long buffer = mapped.getPtr();
|
||||
for (BufferedMesh model : pendingUpload) {
|
||||
model.buffer(buffer);
|
||||
}
|
||||
pendingUpload.clear();
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error("Error uploading pooled models:", e);
|
||||
Flywheel.LOGGER.error("Error uploading pooled meshes:", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,14 +205,6 @@ public class MeshPool {
|
|||
this.type = mesh.getVertexType();
|
||||
}
|
||||
|
||||
public BufferedMesh(VertexType type, Mesh mesh, long byteIndex, int baseVertex) {
|
||||
this.mesh = mesh;
|
||||
this.byteIndex = byteIndex;
|
||||
this.baseVertex = baseVertex;
|
||||
this.ebo = mesh.createEBO();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void drawCall(GlVertexArray vao) {
|
||||
drawInstances(vao, 1);
|
||||
}
|
||||
|
@ -228,7 +218,7 @@ public class MeshPool {
|
|||
}
|
||||
|
||||
private boolean hasAnythingToRender() {
|
||||
return mesh.getVertexCount() <= 0 || isDeleted();
|
||||
return mesh.isEmpty() || isDeleted();
|
||||
}
|
||||
|
||||
private void draw(int instanceCount) {
|
||||
|
@ -258,10 +248,8 @@ public class MeshPool {
|
|||
this.deleted = true;
|
||||
}
|
||||
|
||||
private void buffer(ByteBuffer buffer) {
|
||||
var writer = type.createWriter(buffer);
|
||||
writer.seek(this.byteIndex);
|
||||
writer.writeVertexList(this.mesh.getReader());
|
||||
private void buffer(long ptr) {
|
||||
this.mesh.write(ptr + byteIndex);
|
||||
|
||||
this.boundTo.clear();
|
||||
this.gpuResident = true;
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package com.jozufozu.flywheel.backend.memory;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
public class FlwMemoryTracker {
|
||||
static final Cleaner CLEANER = Cleaner.create();
|
||||
|
||||
private static long cpuMemory = 0;
|
||||
private static long gpuMemory = 0;
|
||||
|
||||
public static long malloc(long size) {
|
||||
long ptr = MemoryUtil.nmemAlloc(size);
|
||||
if (ptr == MemoryUtil.NULL) {
|
||||
throw new OutOfMemoryError("Failed to allocate " + size + " bytes");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link MemoryBlock#malloc(long)} or {@link MemoryBlock#mallocTracked(long)} and
|
||||
* {@link MemoryBlock#asBuffer()} instead. This method should only be used if specifically a {@linkplain ByteBuffer} is needed and it is
|
||||
* short-lived.
|
||||
*/
|
||||
@Deprecated
|
||||
public static ByteBuffer mallocBuffer(int size) {
|
||||
ByteBuffer buffer = MemoryUtil.memByteBuffer(malloc(size), size);
|
||||
_allocCPUMemory(buffer.capacity());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static long calloc(long num, long size) {
|
||||
long ptr = MemoryUtil.nmemCalloc(num, size);
|
||||
if (ptr == MemoryUtil.NULL) {
|
||||
throw new OutOfMemoryError("Failed to allocate " + num + " elements of size " + size + " bytes");
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link MemoryBlock#calloc(long, long)} or {@link MemoryBlock#callocTracked(long, long)} and
|
||||
* {@link MemoryBlock#asBuffer()} instead. This method should only be used if specifically a {@linkplain ByteBuffer} is needed and it is
|
||||
* short-lived.
|
||||
*/
|
||||
@Deprecated
|
||||
public static ByteBuffer callocBuffer(int num, int size) {
|
||||
ByteBuffer buffer = MemoryUtil.memByteBuffer(calloc(num, size), num * size);
|
||||
_allocCPUMemory(buffer.capacity());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static long realloc(long ptr, long size) {
|
||||
ptr = MemoryUtil.nmemRealloc(ptr, size);
|
||||
if (ptr == MemoryUtil.NULL) {
|
||||
throw new OutOfMemoryError("Failed to reallocate " + size + " bytes for address 0x" + Long.toHexString(ptr));
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link MemoryBlock#realloc(long)} or {@link MemoryBlock#reallocTracked(long)} instead. This method
|
||||
* should only be used if specifically a {@linkplain ByteBuffer} is needed and it is short-lived.
|
||||
*/
|
||||
@Deprecated
|
||||
public static ByteBuffer reallocBuffer(ByteBuffer buffer, int size) {
|
||||
ByteBuffer newBuffer = MemoryUtil.memByteBuffer(realloc(MemoryUtil.memAddress(buffer), size), size);
|
||||
_freeCPUMemory(buffer.capacity());
|
||||
_allocCPUMemory(newBuffer.capacity());
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
public static void free(long ptr) {
|
||||
MemoryUtil.nmemFree(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link MemoryBlock#free} instead. This method should only be used if specifically a {@linkplain ByteBuffer} is needed and
|
||||
* it is short-lived.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void freeBuffer(ByteBuffer buffer) {
|
||||
free(MemoryUtil.memAddress(buffer));
|
||||
_freeCPUMemory(buffer.capacity());
|
||||
}
|
||||
|
||||
public static void _allocCPUMemory(long size) {
|
||||
cpuMemory += size;
|
||||
}
|
||||
|
||||
public static void _freeCPUMemory(long size) {
|
||||
cpuMemory -= size;
|
||||
}
|
||||
|
||||
public static void _allocGPUMemory(long size) {
|
||||
gpuMemory += size;
|
||||
}
|
||||
|
||||
public static void _freeGPUMemory(long size) {
|
||||
gpuMemory -= size;
|
||||
}
|
||||
|
||||
public static long getCPUMemory() {
|
||||
return cpuMemory;
|
||||
}
|
||||
|
||||
public static long getGPUMemory() {
|
||||
return gpuMemory;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.jozufozu.flywheel.backend.memory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public sealed interface MemoryBlock permits MemoryBlockImpl {
|
||||
long ptr();
|
||||
|
||||
long size();
|
||||
|
||||
boolean isFreed();
|
||||
|
||||
boolean isTracked();
|
||||
|
||||
void copyTo(long ptr, long bytes);
|
||||
|
||||
void copyTo(long ptr);
|
||||
|
||||
void clear();
|
||||
|
||||
ByteBuffer asBuffer();
|
||||
|
||||
MemoryBlock realloc(long size);
|
||||
|
||||
MemoryBlock reallocTracked(long size);
|
||||
|
||||
void free();
|
||||
|
||||
static MemoryBlock malloc(long size) {
|
||||
return MemoryBlockImpl.mallocBlock(size);
|
||||
}
|
||||
|
||||
static MemoryBlock mallocTracked(long size) {
|
||||
return TrackedMemoryBlockImpl.mallocBlockTracked(size);
|
||||
}
|
||||
|
||||
static MemoryBlock calloc(long num, long size) {
|
||||
return MemoryBlockImpl.callocBlock(num, size);
|
||||
}
|
||||
|
||||
static MemoryBlock callocTracked(long num, long size) {
|
||||
return TrackedMemoryBlockImpl.callocBlockTracked(num, size);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package com.jozufozu.flywheel.backend.memory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
sealed class MemoryBlockImpl implements MemoryBlock permits TrackedMemoryBlockImpl {
|
||||
final long ptr;
|
||||
final long size;
|
||||
|
||||
boolean freed;
|
||||
|
||||
MemoryBlockImpl(long ptr, long size) {
|
||||
this.ptr = ptr;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ptr() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFreed() {
|
||||
return freed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTracked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(long ptr, long bytes) {
|
||||
MemoryUtil.memCopy(this.ptr, ptr, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(long ptr) {
|
||||
copyTo(ptr, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
MemoryUtil.memSet(ptr, 0, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer asBuffer() {
|
||||
int intSize = (int) size;
|
||||
if (intSize != size) {
|
||||
throw new UnsupportedOperationException("Cannot create buffer with long capacity!");
|
||||
}
|
||||
return MemoryUtil.memByteBuffer(ptr, intSize);
|
||||
}
|
||||
|
||||
void freeInner() {
|
||||
FlwMemoryTracker._freeCPUMemory(size);
|
||||
freed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock realloc(long size) {
|
||||
MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
freeInner();
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBlock reallocTracked(long size) {
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.realloc(ptr, size), size, FlwMemoryTracker.CLEANER);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
freeInner();
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
FlwMemoryTracker.free(ptr);
|
||||
freeInner();
|
||||
}
|
||||
|
||||
static MemoryBlock mallocBlock(long size) {
|
||||
MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.malloc(size), size);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
return block;
|
||||
}
|
||||
|
||||
static MemoryBlock callocBlock(long num, long size) {
|
||||
MemoryBlock block = new MemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
return block;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package com.jozufozu.flywheel.backend.memory;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
|
||||
final class TrackedMemoryBlockImpl extends MemoryBlockImpl {
|
||||
final CleaningAction cleaningAction;
|
||||
final Cleaner.Cleanable cleanable;
|
||||
|
||||
TrackedMemoryBlockImpl(long ptr, long size, Cleaner cleaner) {
|
||||
super(ptr, size);
|
||||
cleaningAction = new CleaningAction(ptr, size);
|
||||
cleanable = cleaner.register(this, cleaningAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTracked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void freeInner() {
|
||||
super.freeInner();
|
||||
cleaningAction.freed = true;
|
||||
cleanable.clean();
|
||||
}
|
||||
|
||||
static MemoryBlock mallocBlockTracked(long size) {
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.malloc(size), size, FlwMemoryTracker.CLEANER);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
return block;
|
||||
}
|
||||
|
||||
static MemoryBlock callocBlockTracked(long num, long size) {
|
||||
MemoryBlock block = new TrackedMemoryBlockImpl(FlwMemoryTracker.calloc(num, size), num * size, FlwMemoryTracker.CLEANER);
|
||||
FlwMemoryTracker._allocCPUMemory(block.size());
|
||||
return block;
|
||||
}
|
||||
|
||||
static class CleaningAction implements Runnable {
|
||||
final long ptr;
|
||||
final long size;
|
||||
|
||||
boolean freed;
|
||||
|
||||
CleaningAction(long ptr, long size) {
|
||||
this.ptr = ptr;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!freed) {
|
||||
FlwMemoryTracker.free(ptr);
|
||||
FlwMemoryTracker._freeCPUMemory(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.struct;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
|
||||
public abstract class BufferWriter<S extends InstancedPart> implements StructWriter<S> {
|
||||
protected final ByteBuffer backingBuffer;
|
||||
|
||||
protected final int stride;
|
||||
|
||||
protected BufferWriter(StructType<S> structType, ByteBuffer byteBuffer) {
|
||||
this.backingBuffer = byteBuffer;
|
||||
|
||||
this.stride = structType.getLayout().getStride();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void write(S struct) {
|
||||
writeInternal(struct);
|
||||
advance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the write pointer forward by the stride of one vertex.
|
||||
* This will always be called after a struct is written, implementors need not call it themselves.
|
||||
*
|
||||
* @see #write
|
||||
*/
|
||||
protected abstract void advance();
|
||||
|
||||
protected abstract void writeInternal(S s);
|
||||
|
||||
@Override
|
||||
public void seek(int pos) {
|
||||
backingBuffer.position(pos * stride);
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.struct;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
|
||||
/**
|
||||
* This class copied/adapted from jellysquid's
|
||||
*
|
||||
* An unsafe {@link BufferWriter} implementation which uses direct memory operations to enable fast blitting of
|
||||
* data into memory buffers. Only available on JVMs which support {@link sun.misc.Unsafe}, but generally produces much
|
||||
* better optimized code than other implementations. The implementation does not check for invalid memory accesses,
|
||||
* meaning that errors can corrupt process memory.
|
||||
*/
|
||||
public abstract class UnsafeBufferWriter<S extends InstancedPart> extends BufferWriter<S> {
|
||||
/**
|
||||
* The write pointer into the buffer storage. This is advanced by the stride every time
|
||||
* {@link UnsafeBufferWriter#advance()} is called.
|
||||
*/
|
||||
protected long writePointer;
|
||||
|
||||
protected UnsafeBufferWriter(StructType<S> structType, ByteBuffer byteBuffer) {
|
||||
super(structType, byteBuffer);
|
||||
|
||||
acquireWritePointer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(int pos) {
|
||||
super.seek(pos);
|
||||
acquireWritePointer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void advance() {
|
||||
this.writePointer += this.stride;
|
||||
}
|
||||
|
||||
private void acquireWritePointer() {
|
||||
this.writePointer = MemoryUtil.memAddress(this.backingBuffer, this.backingBuffer.position());
|
||||
}
|
||||
}
|
|
@ -3,13 +3,14 @@ package com.jozufozu.flywheel.core;
|
|||
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
|
||||
import static org.lwjgl.opengl.GL11.glDrawArrays;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
||||
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.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||
import com.jozufozu.flywheel.util.Lazy;
|
||||
|
@ -34,13 +35,14 @@ public class FullscreenQuad {
|
|||
|
||||
private FullscreenQuad() {
|
||||
try (var restoreState = GlStateTracker.getRestoreState()) {
|
||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
vbo.ensureCapacity(bufferSize);
|
||||
try (MappedBuffer buffer = vbo.map()) {
|
||||
var ptr = buffer.getPtr();
|
||||
|
||||
buffer.unwrap()
|
||||
.asFloatBuffer()
|
||||
.put(vertices);
|
||||
for (var i = 0; i < vertices.length; i++) {
|
||||
MemoryUtil.memPutFloat(ptr + i * Float.BYTES, vertices[i]);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package com.jozufozu.flywheel.core;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||
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.backend.instancing.instancing.ElementBuffer;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
|
||||
|
@ -34,11 +32,11 @@ public class QuadConverter {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
private final MappedGlBuffer ebo;
|
||||
private final GlBuffer ebo;
|
||||
private int quadCapacity;
|
||||
|
||||
public QuadConverter() {
|
||||
this.ebo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
||||
this.ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
||||
this.quadCapacity = 0;
|
||||
}
|
||||
|
||||
|
@ -49,9 +47,7 @@ public class QuadConverter {
|
|||
ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth());
|
||||
|
||||
try (MappedBuffer map = ebo.map()) {
|
||||
ByteBuffer indices = map.unwrap();
|
||||
|
||||
fillBuffer(indices, quads);
|
||||
fillBuffer(map.getPtr(), quads);
|
||||
}
|
||||
ebo.unbind();
|
||||
|
||||
|
@ -66,32 +62,18 @@ public class QuadConverter {
|
|||
this.quadCapacity = 0;
|
||||
}
|
||||
|
||||
private void fillBuffer(ByteBuffer indices, int quads) {
|
||||
long addr = MemoryUtil.memAddress(indices);
|
||||
private void fillBuffer(long addr, int quads) {
|
||||
int numVertices = 4 * quads;
|
||||
int baseVertex = 0;
|
||||
while (baseVertex < numVertices) {
|
||||
// writeQuadIndices(indices, baseVertex);
|
||||
writeQuadIndicesUnsafe(addr, baseVertex);
|
||||
writeQuadIndices(addr, baseVertex);
|
||||
|
||||
baseVertex += 4;
|
||||
addr += 6 * 4;
|
||||
}
|
||||
// ((Buffer) indices).flip();
|
||||
}
|
||||
|
||||
private void writeQuadIndices(ByteBuffer indices, int baseVertex) {
|
||||
// triangle a
|
||||
indices.putInt(baseVertex);
|
||||
indices.putInt(baseVertex + 1);
|
||||
indices.putInt(baseVertex + 2);
|
||||
// triangle b
|
||||
indices.putInt(baseVertex);
|
||||
indices.putInt(baseVertex + 2);
|
||||
indices.putInt(baseVertex + 3);
|
||||
}
|
||||
|
||||
private void writeQuadIndicesUnsafe(long addr, int baseVertex) {
|
||||
private void writeQuadIndices(long addr, int baseVertex) {
|
||||
// triangle a
|
||||
MemoryUtil.memPutInt(addr, baseVertex);
|
||||
MemoryUtil.memPutInt(addr + 4, baseVertex + 1);
|
||||
|
@ -102,7 +84,7 @@ public class QuadConverter {
|
|||
MemoryUtil.memPutInt(addr + 20, baseVertex + 3);
|
||||
}
|
||||
|
||||
// make sure this gets reset first so it has a chance to repopulate
|
||||
// make sure this gets reset first, so it has a chance to repopulate
|
||||
public static void onRendererReload(ReloadRenderersEvent event) {
|
||||
if (INSTANCE != null) {
|
||||
INSTANCE.delete();
|
||||
|
|
|
@ -2,74 +2,86 @@ package com.jozufozu.flywheel.core.hardcoded;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
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.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.model.Mesh;
|
||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex;
|
||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||
|
||||
public class ModelPart implements Mesh {
|
||||
|
||||
private final int vertices;
|
||||
private final int vertexCount;
|
||||
private final MemoryBlock contents;
|
||||
private final ReusableVertexList vertexList;
|
||||
private final String name;
|
||||
private final VertexList reader;
|
||||
private final @NotNull Vector4f boundingSphere;
|
||||
private final Vector4f boundingSphere;
|
||||
|
||||
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) {
|
||||
this.name = name;
|
||||
|
||||
{
|
||||
int vertices = 0;
|
||||
this.vertexCount = countVertices(cuboids);
|
||||
|
||||
contents = MemoryBlock.malloc(size());
|
||||
long ptr = contents.ptr();
|
||||
VertexWriter writer = new VertexWriterImpl(ptr);
|
||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||
vertices += cuboid.vertices();
|
||||
}
|
||||
this.vertices = vertices;
|
||||
cuboid.write(writer);
|
||||
}
|
||||
|
||||
try (var stack = MemoryStack.stackPush()) {
|
||||
PosTexNormalWriterUnsafe writer = getVertexType().createWriter(stack.malloc(size()));
|
||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||
cuboid.buffer(writer);
|
||||
}
|
||||
vertexList = getVertexType().createVertexList();
|
||||
vertexList.ptr(ptr);
|
||||
vertexList.setVertexCount(vertexCount);
|
||||
|
||||
reader = writer.intoReader(this.vertices);
|
||||
}
|
||||
|
||||
boundingSphere = ModelUtil.computeBoundingSphere(reader);
|
||||
boundingSphere = ModelUtil.computeBoundingSphere(vertexList);
|
||||
}
|
||||
|
||||
public static PartBuilder builder(String name, int sizeU, int sizeV) {
|
||||
return new PartBuilder(name, sizeU, sizeV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVertexCount() {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexList getReader() {
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PosTexNormalVertex getVertexType() {
|
||||
return Formats.POS_TEX_NORMAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVertexCount() {
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(long ptr) {
|
||||
contents.copyTo(ptr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(MutableVertexList dst) {
|
||||
vertexList.writeAll(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
contents.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector4fc getBoundingSphere() {
|
||||
return boundingSphere;
|
||||
}
|
||||
|
||||
private static int countVertices(List<PartBuilder.CuboidBuilder> cuboids) {
|
||||
int vertices = 0;
|
||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||
vertices += cuboid.vertices();
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.EnumSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
||||
import com.mojang.math.Matrix3f;
|
||||
import com.mojang.math.Quaternion;
|
||||
import com.mojang.math.Vector3f;
|
||||
|
@ -160,8 +159,7 @@ public class PartBuilder {
|
|||
return visibleFaces.size() * 4;
|
||||
}
|
||||
|
||||
public void buffer(PosTexNormalWriterUnsafe buffer) {
|
||||
|
||||
public void write(VertexWriter writer) {
|
||||
float sizeX = posX2 - posX1;
|
||||
float sizeY = posY2 - posY1;
|
||||
float sizeZ = posZ2 - posZ1;
|
||||
|
@ -219,28 +217,27 @@ public class PartBuilder {
|
|||
float f12 = getV((float)textureOffsetV + sizeZ + sizeY);
|
||||
|
||||
if (invertYZ) {
|
||||
quad(buffer, 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(buffer, 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(buffer, 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[]{hlh, llh, lll, hll}, f6, f11, f7, f10, down);
|
||||
quad(writer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, up);
|
||||
quad(writer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, west);
|
||||
quad(writer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, north);
|
||||
quad(writer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, east);
|
||||
quad(writer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, south);
|
||||
} else {
|
||||
quad(buffer, 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(buffer, 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(buffer, 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[]{hlh, llh, lll, hll}, f5, f10, f6, f11, down);
|
||||
quad(writer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, up);
|
||||
quad(writer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, west);
|
||||
quad(writer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, north);
|
||||
quad(writer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, east);
|
||||
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) {
|
||||
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[2].x(), vertices[2].y(), vertices[2].z(), normal.x(), normal.y(), normal.z(), minU, maxV);
|
||||
buffer.putVertex(vertices[3].x(), vertices[3].y(), vertices[3].z(), normal.x(), normal.y(), normal.z(), maxU, maxV);
|
||||
|
||||
public void quad(VertexWriter writer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) {
|
||||
writer.putVertex(vertices[0].x(), vertices[0].y(), vertices[0].z(), maxU, minV, normal.x(), normal.y(), normal.z());
|
||||
writer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), minU, minV, normal.x(), normal.y(), normal.z());
|
||||
writer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), minU, maxV, normal.x(), normal.y(), normal.z());
|
||||
writer.putVertex(vertices[3].x(), vertices[3].y(), vertices[3].z(), maxU, maxV, normal.x(), normal.y(), normal.z());
|
||||
}
|
||||
|
||||
public float getU(float u) {
|
||||
|
@ -258,5 +255,4 @@ public class PartBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,26 +1,39 @@
|
|||
package com.jozufozu.flywheel.core.layout;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeF;
|
||||
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeI;
|
||||
|
||||
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 VEC4 = primitiveF(GlNumericType.FLOAT, 4);
|
||||
public static final PrimitiveItem VEC3 = primitiveF(GlNumericType.FLOAT, 3);
|
||||
public static final PrimitiveItem VEC2 = primitiveF(GlNumericType.FLOAT, 2);
|
||||
public static final PrimitiveItem FLOAT = primitiveF(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 QUATERNION = primitiveF(GlNumericType.FLOAT, 4);
|
||||
public static final PrimitiveItem NORMAL = primitiveF(GlNumericType.BYTE, 3, true);
|
||||
public static final PrimitiveItem UV = primitiveF(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(new VertexAttributeI(GlNumericType.UBYTE, 2));
|
||||
public static final PrimitiveItem LIGHT_SHORT = new PrimitiveItem(new VertexAttributeI(GlNumericType.USHORT, 2));
|
||||
public static final PrimitiveItem RGBA = primitiveF(GlNumericType.UBYTE, 4, true);
|
||||
public static final PrimitiveItem RGB = primitiveF(GlNumericType.UBYTE, 3, true);
|
||||
public static final PrimitiveItem LIGHT = primitiveI(GlNumericType.UBYTE, 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 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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,22 +2,12 @@ package com.jozufozu.flywheel.core.layout;
|
|||
|
||||
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.VertexAttributeF;
|
||||
|
||||
public class PrimitiveItem implements LayoutItem {
|
||||
|
||||
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) {
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
|
|
@ -1,71 +1,56 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
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.VertexWriter;
|
||||
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||
import com.jozufozu.flywheel.core.QuadConverter;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||
|
||||
/**
|
||||
* A mesh that can be rendered by flywheel.
|
||||
*
|
||||
* <p>
|
||||
* It is expected that the following assertion will not fail:
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* Mesh mesh = ...;
|
||||
* VecBuffer into = ...;
|
||||
*
|
||||
* int initial = VecBuffer.unwrap().position();
|
||||
*
|
||||
* mesh.buffer(into);
|
||||
*
|
||||
* int final = VecBuffer.unwrap().position();
|
||||
*
|
||||
* assert mesh.size() == final - initial;
|
||||
* }</pre>
|
||||
* A holder for arbitrary vertex data that can be written to memory or a vertex list.
|
||||
*/
|
||||
public interface Mesh {
|
||||
|
||||
/**
|
||||
* A name uniquely identifying this model.
|
||||
*/
|
||||
String name();
|
||||
|
||||
VertexType getVertexType();
|
||||
|
||||
VertexList getReader();
|
||||
|
||||
Vector4fc getBoundingSphere();
|
||||
|
||||
/**
|
||||
* @return The number of vertices the model has.
|
||||
* @return The number of vertices this mesh has.
|
||||
*/
|
||||
default int getVertexCount() {
|
||||
return getReader().getVertexCount();
|
||||
}
|
||||
int getVertexCount();
|
||||
|
||||
/**
|
||||
* Is there nothing to render?
|
||||
* @return true if there are no vertices.
|
||||
*/
|
||||
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() {
|
||||
return getVertexType().byteOffset(getVertexCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an element buffer object that indexes the vertices of this model.
|
||||
* Write this mesh into memory. The written data will use the format defined by {@link #getVertexType()} and the amount of
|
||||
* bytes written will be the same as the return value of {@link #size()}.
|
||||
* @param ptr The address to which data is written to.
|
||||
*/
|
||||
void write(long ptr);
|
||||
|
||||
/**
|
||||
* Write this mesh into a vertex list. Vertices with index {@literal <}0 or {@literal >=}{@link #getVertexCount()} will not be
|
||||
* modified.
|
||||
* @param vertexList The vertex list to which data is written to.
|
||||
*/
|
||||
void write(MutableVertexList vertexList);
|
||||
|
||||
/**
|
||||
* Create an element buffer object that indexes the vertices of this mesh.
|
||||
*
|
||||
* <p>
|
||||
* Very often models in minecraft are made up of sequential quads, which is a very predictable pattern.
|
||||
|
@ -79,9 +64,10 @@ public interface Mesh {
|
|||
.quads2Tris(getVertexCount() / 4);
|
||||
}
|
||||
|
||||
default void writeInto(ByteBuffer buffer, long byteIndex) {
|
||||
VertexWriter writer = getVertexType().createWriter(buffer);
|
||||
writer.seek(byteIndex);
|
||||
writer.writeVertexList(getReader());
|
||||
}
|
||||
void close();
|
||||
|
||||
/**
|
||||
* A name uniquely identifying this mesh.
|
||||
*/
|
||||
String name();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import com.jozufozu.flywheel.api.material.Material;
|
|||
public interface Model {
|
||||
Map<Material, Mesh> getMeshes();
|
||||
|
||||
void delete();
|
||||
|
||||
default int getVertexCount() {
|
||||
int size = 0;
|
||||
for (Mesh mesh : getMeshes().values()) {
|
||||
|
|
|
@ -5,16 +5,23 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.dreizak.miniball.highdim.Miniball;
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.Materials;
|
||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.jozufozu.flywheel.core.vertex.VertexListProviderRegistry;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -46,15 +53,27 @@ public class ModelUtil {
|
|||
return dispatcher;
|
||||
}
|
||||
|
||||
public static VertexList createVertexList(BufferBuilder bufferBuilder) {
|
||||
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
|
||||
BufferBuilder.DrawState drawState = pair.getFirst();
|
||||
public static Pair<VertexType, MemoryBlock> convertBlockBuffer(Pair<DrawState, ByteBuffer> pair) {
|
||||
DrawState drawState = pair.getFirst();
|
||||
int vertexCount = drawState.vertexCount();
|
||||
VertexFormat srcFormat = drawState.format();
|
||||
VertexType dstVertexType = Formats.BLOCK;
|
||||
|
||||
if (drawState.format() != DefaultVertexFormat.BLOCK) {
|
||||
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format());
|
||||
}
|
||||
ByteBuffer src = pair.getSecond();
|
||||
MemoryBlock dst = MemoryBlock.malloc(src.capacity());
|
||||
long srcPtr = MemoryUtil.memAddress(src);
|
||||
long dstPtr = dst.ptr();
|
||||
|
||||
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
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -41,8 +42,16 @@ public class Models {
|
|||
}
|
||||
|
||||
public static void onReload(ReloadRenderersEvent event) {
|
||||
deleteAll(BLOCK_STATE.values());
|
||||
deleteAll(PARTIAL.values());
|
||||
deleteAll(PARTIAL_DIR.values());
|
||||
|
||||
BLOCK_STATE.clear();
|
||||
PARTIAL.clear();
|
||||
PARTIAL_DIR.clear();
|
||||
}
|
||||
|
||||
private static void deleteAll(Collection<Model> values) {
|
||||
values.forEach(Model::delete);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ public class SimpleLazyModel implements Model {
|
|||
return ImmutableMap.of(material, supplier.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
supplier.ifPresent(Mesh::close);
|
||||
}
|
||||
|
||||
public int getVertexCount() {
|
||||
return supplier.map(Mesh::getVertexCount)
|
||||
.orElse(0);
|
||||
|
|
|
@ -1,27 +1,37 @@
|
|||
package com.jozufozu.flywheel.core.model;
|
||||
|
||||
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.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||
|
||||
public class SimpleMesh implements Mesh {
|
||||
private final VertexList reader;
|
||||
private final VertexType vertexType;
|
||||
private final int vertexCount;
|
||||
private final MemoryBlock contents;
|
||||
private final ReusableVertexList vertexList;
|
||||
private final String name;
|
||||
private final Vector4f boundingSphere;
|
||||
|
||||
public SimpleMesh(VertexList reader, VertexType vertexType, String name) {
|
||||
this.reader = reader;
|
||||
public SimpleMesh(VertexType vertexType, MemoryBlock contents, String name) {
|
||||
this.vertexType = vertexType;
|
||||
this.contents = contents;
|
||||
this.name = name;
|
||||
|
||||
boundingSphere = ModelUtil.computeBoundingSphere(reader);
|
||||
int bytes = (int) contents.size();
|
||||
int stride = vertexType.getStride();
|
||||
if (bytes % stride != 0) {
|
||||
throw new IllegalArgumentException("MemoryBlock contains non-whole amount of vertices!");
|
||||
}
|
||||
vertexCount = bytes / stride;
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
vertexList = getVertexType().createVertexList();
|
||||
vertexList.ptr(contents.ptr());
|
||||
vertexList.setVertexCount(vertexCount);
|
||||
|
||||
boundingSphere = ModelUtil.computeBoundingSphere(vertexList);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,8 +40,28 @@ public class SimpleMesh implements Mesh {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VertexList getReader() {
|
||||
return reader;
|
||||
public int getVertexCount() {
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(long ptr) {
|
||||
contents.copyTo(ptr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(MutableVertexList dst) {
|
||||
vertexList.writeAll(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
contents.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,6 +19,12 @@ public class TessellatedModel implements Model {
|
|||
return meshes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
meshes.values()
|
||||
.forEach(Mesh::close);
|
||||
}
|
||||
|
||||
public boolean isShadeSeparated() {
|
||||
return shadeSeparated;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import java.util.function.BiFunction;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.model.Mesh;
|
||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||
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.ShadeSeparatedBufferFactory;
|
||||
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.VirtualEmptyModelData;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
|
@ -28,9 +30,10 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
public class BakedModelBuilder {
|
||||
private static final int STARTING_CAPACITY = 64;
|
||||
|
||||
private final BakedModel bakedModel;
|
||||
private boolean shadeSeparated = true;
|
||||
private VertexFormat vertexFormat;
|
||||
private BlockAndTintGetter renderWorld;
|
||||
private BlockState blockState;
|
||||
private PoseStack poseStack;
|
||||
|
@ -46,11 +49,6 @@ public class BakedModelBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public BakedModelBuilder vertexFormat(VertexFormat vertexFormat) {
|
||||
this.vertexFormat = vertexFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BakedModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
||||
this.renderWorld = renderWorld;
|
||||
return this;
|
||||
|
@ -80,9 +78,6 @@ public class BakedModelBuilder {
|
|||
public TessellatedModel build() {
|
||||
ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get();
|
||||
|
||||
if (vertexFormat == null) {
|
||||
vertexFormat = DefaultVertexFormat.BLOCK;
|
||||
}
|
||||
if (renderWorld == null) {
|
||||
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
||||
}
|
||||
|
@ -103,29 +98,31 @@ public class BakedModelBuilder {
|
|||
|
||||
if (shadeSeparated) {
|
||||
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
||||
BufferBuilder buffer = new BufferBuilder(64);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
||||
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
return buffer;
|
||||
};
|
||||
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
||||
buffer.end();
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
|
||||
Pair<VertexType, MemoryBlock> 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);
|
||||
} else {
|
||||
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
||||
BufferBuilder buffer = new BufferBuilder(64);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
||||
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
return buffer;
|
||||
};
|
||||
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
||||
buffer.end();
|
||||
Material material = materialFunc.apply(renderType, false);
|
||||
if (material != null) {
|
||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString()));
|
||||
Pair<VertexType, MemoryBlock> 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);
|
||||
|
|
|
@ -4,6 +4,8 @@ import java.util.function.BiFunction;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.model.Mesh;
|
||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||
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.ShadeSeparatedBufferFactory;
|
||||
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.VirtualEmptyModelData;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
|
@ -26,9 +28,10 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
public class BlockModelBuilder {
|
||||
private static final int STARTING_CAPACITY = 64;
|
||||
|
||||
private final BlockState state;
|
||||
private boolean shadeSeparated = true;
|
||||
private VertexFormat vertexFormat;
|
||||
private BlockAndTintGetter renderWorld;
|
||||
private PoseStack poseStack;
|
||||
private IModelData modelData;
|
||||
|
@ -43,11 +46,6 @@ public class BlockModelBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public BlockModelBuilder vertexFormat(VertexFormat vertexFormat) {
|
||||
this.vertexFormat = vertexFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
||||
this.renderWorld = renderWorld;
|
||||
return this;
|
||||
|
@ -72,9 +70,6 @@ public class BlockModelBuilder {
|
|||
public TessellatedModel build() {
|
||||
ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get();
|
||||
|
||||
if (vertexFormat == null) {
|
||||
vertexFormat = DefaultVertexFormat.BLOCK;
|
||||
}
|
||||
if (renderWorld == null) {
|
||||
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
||||
}
|
||||
|
@ -92,29 +87,31 @@ public class BlockModelBuilder {
|
|||
|
||||
if (shadeSeparated) {
|
||||
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
||||
BufferBuilder buffer = new BufferBuilder(64);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
||||
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
return buffer;
|
||||
};
|
||||
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
||||
buffer.end();
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
|
||||
Pair<VertexType, MemoryBlock> 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);
|
||||
} else {
|
||||
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
||||
BufferBuilder buffer = new BufferBuilder(64);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
||||
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
return buffer;
|
||||
};
|
||||
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
||||
buffer.end();
|
||||
Material material = materialFunc.apply(renderType, false);
|
||||
if (material != null) {
|
||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "state=" + state.toString() + ",renderType=" + renderType.toString()));
|
||||
Pair<VertexType, MemoryBlock> 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);
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.function.BiFunction;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.model.Mesh;
|
||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||
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.ShadeSeparatedBufferFactory;
|
||||
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.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -29,6 +31,8 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
|||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
public class MultiBlockModelBuilder {
|
||||
private static final int STARTING_CAPACITY = 1024;
|
||||
|
||||
private final Collection<StructureTemplate.StructureBlockInfo> blocks;
|
||||
private boolean shadeSeparated = true;
|
||||
private VertexFormat vertexFormat;
|
||||
|
@ -46,11 +50,6 @@ public class MultiBlockModelBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public MultiBlockModelBuilder vertexFormat(VertexFormat vertexFormat) {
|
||||
this.vertexFormat = vertexFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MultiBlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
||||
this.renderWorld = renderWorld;
|
||||
return this;
|
||||
|
@ -95,29 +94,31 @@ public class MultiBlockModelBuilder {
|
|||
|
||||
if (shadeSeparated) {
|
||||
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
||||
BufferBuilder buffer = new BufferBuilder(1024);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
||||
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
return buffer;
|
||||
};
|
||||
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
||||
buffer.end();
|
||||
Material material = materialFunc.apply(renderType, shaded);
|
||||
if (material != null) {
|
||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "renderType=" + renderType.toString() + ",shaded=" + shaded));
|
||||
Pair<VertexType, MemoryBlock> 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);
|
||||
} else {
|
||||
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
||||
BufferBuilder buffer = new BufferBuilder(1024);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
||||
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||
return buffer;
|
||||
};
|
||||
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
||||
buffer.end();
|
||||
Material material = materialFunc.apply(renderType, false);
|
||||
if (material != null) {
|
||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "renderType=" + renderType.toString()));
|
||||
Pair<VertexType, MemoryBlock> 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);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package com.jozufozu.flywheel.core.structs;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
|
||||
public abstract class ColoredLitWriter<D extends ColoredLitPart> implements StructWriter<D> {
|
||||
@Override
|
||||
public void write(long ptr, D d) {
|
||||
MemoryUtil.memPutByte(ptr, d.blockLight);
|
||||
MemoryUtil.memPutByte(ptr + 1, d.skyLight);
|
||||
MemoryUtil.memPutByte(ptr + 2, d.r);
|
||||
MemoryUtil.memPutByte(ptr + 3, d.g);
|
||||
MemoryUtil.memPutByte(ptr + 4, d.b);
|
||||
MemoryUtil.memPutByte(ptr + 5, d.a);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.structs;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.backend.struct.UnsafeBufferWriter;
|
||||
|
||||
public abstract class ColoredLitWriterUnsafe<D extends ColoredLitPart> extends UnsafeBufferWriter<D> {
|
||||
|
||||
public ColoredLitWriterUnsafe(StructType<D> structType, ByteBuffer byteBuffer) {
|
||||
super(structType, byteBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInternal(D d) {
|
||||
long ptr = writePointer;
|
||||
MemoryUtil.memPutByte(ptr, d.blockLight);
|
||||
MemoryUtil.memPutByte(ptr + 1, d.skyLight);
|
||||
MemoryUtil.memPutByte(ptr + 2, d.r);
|
||||
MemoryUtil.memPutByte(ptr + 3, d.g);
|
||||
MemoryUtil.memPutByte(ptr + 4, d.b);
|
||||
MemoryUtil.memPutByte(ptr + 5, d.a);
|
||||
}
|
||||
}
|
|
@ -2,10 +2,10 @@ package com.jozufozu.flywheel.core.structs;
|
|||
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedType;
|
||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
|
||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedType;
|
||||
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.transformed.TransformedType;
|
||||
|
||||
public class StructTypes {
|
||||
public static final StructType<TransformedPart> TRANSFORMED = ComponentRegistry.register(new TransformedType());
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package com.jozufozu.flywheel.core.structs.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.core.structs.ColoredLitWriterUnsafe;
|
||||
import com.jozufozu.flywheel.util.extension.MatrixExtension;
|
||||
|
||||
public class TransformedWriterUnsafe extends ColoredLitWriterUnsafe<TransformedPart> {
|
||||
|
||||
public TransformedWriterUnsafe(StructType<TransformedPart> structType, ByteBuffer byteBuffer) {
|
||||
super(structType, byteBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInternal(TransformedPart d) {
|
||||
super.writeInternal(d);
|
||||
long ptr = writePointer + 6;
|
||||
|
||||
((MatrixExtension) (Object) d.model).flywheel$writeUnsafe(ptr);
|
||||
((MatrixExtension) (Object) d.normal).flywheel$writeUnsafe(ptr + 4 * 16);
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.core.structs.model;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
@ -1,8 +1,5 @@
|
|||
package com.jozufozu.flywheel.core.structs.oriented;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
|
@ -33,8 +30,8 @@ public class OrientedType implements StructType<OrientedPart> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public StructWriter<OrientedPart> getWriter(ByteBuffer backing) {
|
||||
return new OrientedWriterUnsafe(this, backing);
|
||||
public StructWriter<OrientedPart> getWriter() {
|
||||
return OrientedWriter.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,7 +50,7 @@ public class OrientedType implements StructType<OrientedPart> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VertexTransformer<? extends OrientedPart> getVertexTransformer() {
|
||||
public VertexTransformer<OrientedPart> getVertexTransformer() {
|
||||
return (vertexList, struct, level) -> {
|
||||
Vector4f pos = new Vector4f();
|
||||
Vector3f normal = new Vector3f();
|
||||
|
|
|
@ -1,21 +1,15 @@
|
|||
package com.jozufozu.flywheel.core.structs.oriented;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.core.structs.ColoredLitWriterUnsafe;
|
||||
import com.jozufozu.flywheel.core.structs.ColoredLitWriter;
|
||||
|
||||
public class OrientedWriterUnsafe extends ColoredLitWriterUnsafe<OrientedPart> {
|
||||
public OrientedWriterUnsafe(StructType<OrientedPart> structType, ByteBuffer byteBuffer) {
|
||||
super(structType, byteBuffer);
|
||||
}
|
||||
public class OrientedWriter extends ColoredLitWriter<OrientedPart> {
|
||||
public static final OrientedWriter INSTANCE = new OrientedWriter();
|
||||
|
||||
@Override
|
||||
protected void writeInternal(OrientedPart d) {
|
||||
long ptr = writePointer;
|
||||
super.writeInternal(d);
|
||||
public void write(long ptr, OrientedPart d) {
|
||||
super.write(ptr, d);
|
||||
|
||||
MemoryUtil.memPutFloat(ptr + 6, d.posX);
|
||||
MemoryUtil.memPutFloat(ptr + 10, d.posY);
|
|
@ -1,4 +1,4 @@
|
|||
package com.jozufozu.flywheel.core.structs.model;
|
||||
package com.jozufozu.flywheel.core.structs.transformed;
|
||||
|
||||
import com.jozufozu.flywheel.core.structs.ColoredLitPart;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
|
@ -1,4 +1,4 @@
|
|||
package com.jozufozu.flywheel.core.structs.model;
|
||||
package com.jozufozu.flywheel.core.structs.transformed;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
package com.jozufozu.flywheel.core.structs.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
package com.jozufozu.flywheel.core.structs.transformed;
|
||||
|
||||
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
|
@ -30,8 +28,8 @@ public class TransformedType implements StructType<TransformedPart> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public StructWriter<TransformedPart> getWriter(ByteBuffer backing) {
|
||||
return new TransformedWriterUnsafe(this, backing);
|
||||
public StructWriter<TransformedPart> getWriter() {
|
||||
return TransformedWriter.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,7 +48,7 @@ public class TransformedType implements StructType<TransformedPart> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public VertexTransformer<? extends TransformedPart> getVertexTransformer() {
|
||||
public VertexTransformer<TransformedPart> getVertexTransformer() {
|
||||
return (vertexList, struct, level) -> {
|
||||
Vector4f pos = new Vector4f();
|
||||
Vector3f normal = new Vector3f();
|
|
@ -0,0 +1,17 @@
|
|||
package com.jozufozu.flywheel.core.structs.transformed;
|
||||
|
||||
import com.jozufozu.flywheel.core.structs.ColoredLitWriter;
|
||||
import com.jozufozu.flywheel.util.extension.MatrixExtension;
|
||||
|
||||
public class TransformedWriter extends ColoredLitWriter<TransformedPart> {
|
||||
public static final TransformedWriter INSTANCE = new TransformedWriter();
|
||||
|
||||
@Override
|
||||
public void write(long ptr, TransformedPart d) {
|
||||
super.write(ptr, d);
|
||||
ptr += 6;
|
||||
|
||||
((MatrixExtension) (Object) d.model).flywheel$writeUnsafe(ptr);
|
||||
((MatrixExtension) (Object) d.normal).flywheel$writeUnsafe(ptr + 4 * 16);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.backend.struct;
|
||||
package com.jozufozu.flywheel.core.structs.transformed;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
|
@ -9,22 +9,18 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
|||
|
||||
public class FogProvider extends UniformProvider {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getActualByteSize() {
|
||||
return 16 + 8 + 4;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (buffer == null) {
|
||||
if (ptr == MemoryUtil.NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
var color = RenderSystem.getShaderFogColor();
|
||||
|
||||
long ptr = MemoryUtil.memAddress(buffer);
|
||||
|
||||
MemoryUtil.memPutFloat(ptr, color[0]);
|
||||
MemoryUtil.memPutFloat(ptr + 4, color[1]);
|
||||
MemoryUtil.memPutFloat(ptr + 8, color[2]);
|
||||
|
|
|
@ -37,7 +37,7 @@ public class FrustumProvider extends UniformProvider {
|
|||
}
|
||||
|
||||
public void update(RenderContext context) {
|
||||
if (buffer == null) {
|
||||
if (ptr == MemoryUtil.NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,6 @@ public class FrustumProvider extends UniformProvider {
|
|||
|
||||
var shiftedCuller = RenderContext.createCuller(context.viewProjection(), -camX, -camY, -camZ);
|
||||
|
||||
long ptr = MemoryUtil.memAddress(buffer);
|
||||
|
||||
shiftedCuller.getJozuPackedPlanes(ptr);
|
||||
|
||||
notifier.signalChanged();
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
package com.jozufozu.flywheel.core.uniform;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jozufozu.flywheel.api.uniform.UniformProvider;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
||||
import com.jozufozu.flywheel.util.RenderMath;
|
||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
||||
|
||||
public class UniformBuffer {
|
||||
|
||||
|
@ -33,13 +31,13 @@ public class UniformBuffer {
|
|||
return instance;
|
||||
}
|
||||
|
||||
private final MappedGlBuffer buffer;
|
||||
private final ByteBuffer data;
|
||||
private final GlBuffer buffer;
|
||||
private final MemoryBlock data;
|
||||
|
||||
private final BitSet changedBytes;
|
||||
|
||||
private UniformBuffer() {
|
||||
buffer = new MappedGlBuffer(GlBufferType.UNIFORM_BUFFER);
|
||||
buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER);
|
||||
|
||||
Collection<UniformProvider> providers = ComponentRegistry.getAllUniformProviders();
|
||||
|
||||
|
@ -57,7 +55,7 @@ public class UniformBuffer {
|
|||
|
||||
allocatedProviders = builder.build();
|
||||
|
||||
data = MemoryTracker.create(totalBytes);
|
||||
data = MemoryBlock.mallocTracked(totalBytes);
|
||||
changedBytes = new BitSet(totalBytes);
|
||||
|
||||
for (Allocated p : allocatedProviders) {
|
||||
|
@ -112,8 +110,8 @@ public class UniformBuffer {
|
|||
changedBytes.set(offset, offset + size);
|
||||
}
|
||||
|
||||
private void updatePtr(ByteBuffer bufferBase) {
|
||||
provider.updatePtr(MemoryUtil.memSlice(bufferBase, offset, size), this);
|
||||
private void updatePtr(MemoryBlock bufferBase) {
|
||||
provider.updatePtr(bufferBase.ptr() + offset, this);
|
||||
}
|
||||
|
||||
public UniformProvider provider() {
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ViewProvider extends UniformProvider {
|
|||
}
|
||||
|
||||
public void update(RenderContext context) {
|
||||
if (buffer == null) {
|
||||
if (ptr == MemoryUtil.NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,6 @@ public class ViewProvider extends UniformProvider {
|
|||
var vp = context.viewProjection().copy();
|
||||
vp.multiplyWithTranslation(-camX, -camY, -camZ);
|
||||
|
||||
long ptr = MemoryUtil.memAddress(buffer);
|
||||
|
||||
MatrixExtension.writeUnsafe(vp, ptr);
|
||||
MemoryUtil.memPutFloat(ptr + 64, camX);
|
||||
MemoryUtil.memPutFloat(ptr + 68, camY);
|
||||
|
|
|
@ -1,49 +1,28 @@
|
|||
package com.jozufozu.flywheel.core.vertex;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
||||
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);
|
||||
}
|
||||
public abstract class AbstractVertexList implements ReusableVertexList {
|
||||
protected long ptr;
|
||||
protected int vertexCount;
|
||||
|
||||
@Override
|
||||
public int getVertexCount() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.jozufozu.flywheel.core.vertex;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
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;
|
||||
|
||||
public class BlockVertex implements VertexType {
|
||||
|
||||
public static final BufferLayout FORMAT = BufferLayout.builder()
|
||||
.addItems(CommonItems.VEC3,
|
||||
CommonItems.RGBA,
|
||||
|
@ -24,18 +21,13 @@ public class BlockVertex implements VertexType {
|
|||
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
|
||||
public FileResolution getLayoutShader() {
|
||||
return Components.Files.BLOCK_LAYOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVertexList createVertexList() {
|
||||
return new BlockVertexList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,72 +1,61 @@
|
|||
package com.jozufozu.flywheel.core.vertex;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.util.RenderMath;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
|
||||
public class BlockVertexList extends AbstractVertexList {
|
||||
protected static final int STRIDE = 32;
|
||||
|
||||
private final int 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;
|
||||
protected long idxPtr(int index) {
|
||||
return ptr + index * STRIDE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float x(int index) {
|
||||
return contents.getFloat(vertIdx(index));
|
||||
return MemoryUtil.memGetFloat(idxPtr(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public float y(int index) {
|
||||
return contents.getFloat(vertIdx(index) + 4);
|
||||
return MemoryUtil.memGetFloat(idxPtr(index) + 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float z(int index) {
|
||||
return contents.getFloat(vertIdx(index) + 8);
|
||||
return MemoryUtil.memGetFloat(idxPtr(index) + 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte r(int index) {
|
||||
return contents.get(vertIdx(index) + 12);
|
||||
return MemoryUtil.memGetByte(idxPtr(index) + 12);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte g(int index) {
|
||||
return contents.get(vertIdx(index) + 13);
|
||||
return MemoryUtil.memGetByte(idxPtr(index) + 13);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte b(int index) {
|
||||
return contents.get(vertIdx(index) + 14);
|
||||
return MemoryUtil.memGetByte(idxPtr(index) + 14);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte a(int index) {
|
||||
return contents.get(vertIdx(index) + 15);
|
||||
return MemoryUtil.memGetByte(idxPtr(index) + 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float u(int index) {
|
||||
return contents.getFloat(vertIdx(index) + 16);
|
||||
return MemoryUtil.memGetFloat(idxPtr(index) + 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float v(int index) {
|
||||
return contents.getFloat(vertIdx(index) + 20);
|
||||
return MemoryUtil.memGetFloat(idxPtr(index) + 20);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,22 +65,95 @@ public class BlockVertexList extends AbstractVertexList {
|
|||
|
||||
@Override
|
||||
public int light(int index) {
|
||||
return contents.getInt(vertIdx(index) + 24);
|
||||
return MemoryUtil.memGetInt(idxPtr(index) + 24) << 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float normalX(int index) {
|
||||
return RenderMath.f(contents.get(vertIdx(index) + 28));
|
||||
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 28));
|
||||
}
|
||||
|
||||
@Override
|
||||
public float normalY(int index) {
|
||||
return RenderMath.f(contents.get(vertIdx(index) + 29));
|
||||
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 29));
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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.VertexFormatElement;
|
||||
|
||||
public class VertexFormatInfo {
|
||||
public class InferredVertexFormatInfo {
|
||||
public final VertexFormat format;
|
||||
public final int stride;
|
||||
|
||||
|
@ -14,7 +14,7 @@ public class VertexFormatInfo {
|
|||
public final int lightOffset;
|
||||
public final int normalOffset;
|
||||
|
||||
public VertexFormatInfo(VertexFormat format) {
|
||||
public InferredVertexFormatInfo(VertexFormat format) {
|
||||
this.format = format;
|
||||
stride = format.getVertexSize();
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class VertexFormatInfo {
|
|||
this.normalOffset = normalOffset;
|
||||
}
|
||||
|
||||
protected VertexFormatInfo(VertexFormatInfo formatInfo) {
|
||||
protected InferredVertexFormatInfo(InferredVertexFormatInfo formatInfo) {
|
||||
format = formatInfo.format;
|
||||
stride = formatInfo.stride;
|
||||
positionOffset = formatInfo.positionOffset;
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
package com.jozufozu.flywheel.core.vertex;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.core.Components;
|
||||
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;
|
||||
|
||||
public class PosTexNormalVertex implements VertexType {
|
||||
|
||||
public static final BufferLayout FORMAT = BufferLayout.builder()
|
||||
.addItems(CommonItems.VEC3, CommonItems.UV, CommonItems.NORMAL)
|
||||
.build();
|
||||
|
@ -19,18 +16,13 @@ public class PosTexNormalVertex implements VertexType {
|
|||
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
|
||||
public FileResolution getLayoutShader() {
|
||||
return Components.Files.POS_TEX_NORMAL_LAYOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PosTexNormalVertexList createVertexList() {
|
||||
return new PosTexNormalVertexList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -4,9 +4,10 @@ import java.util.ArrayList;
|
|||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.FlywheelMemory;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
||||
import com.jozufozu.flywheel.light.LightUpdater;
|
||||
import com.jozufozu.flywheel.util.StringUtil;
|
||||
import com.jozufozu.flywheel.util.WorldAttached;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -24,10 +25,7 @@ public class ForgeEvents {
|
|||
|
||||
InstancedRenderDispatcher.getDebugString(debug);
|
||||
|
||||
// TODO: compress into one line
|
||||
debug.add("Memory used:");
|
||||
debug.add("GPU: " + FlywheelMemory.getGPUMemory());
|
||||
debug.add("CPU: " + FlywheelMemory.getCPUMemory());
|
||||
debug.add("Memory Usage: CPU: " + StringUtil.formatBytes(FlwMemoryTracker.getCPUMemory()) + ", GPU: " + StringUtil.formatBytes(FlwMemoryTracker.getGPUMemory()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ public class GPULightVolume extends LightVolume {
|
|||
|
||||
public void bind() {
|
||||
// just in case something goes wrong, or we accidentally call this before this volume is properly disposed of.
|
||||
if (lightData == null || lightData.capacity() == 0) return;
|
||||
if (lightData == null || lightData.size() == 0) return;
|
||||
|
||||
textureUnit.makeActive();
|
||||
glTexture.bind();
|
||||
|
@ -93,7 +93,7 @@ public class GPULightVolume extends LightVolume {
|
|||
int sizeY = box.sizeY();
|
||||
int sizeZ = box.sizeZ();
|
||||
|
||||
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, sizeX, sizeY, sizeZ, GL30.GL_RG, GL_UNSIGNED_BYTE, lightData);
|
||||
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, sizeX, sizeY, sizeZ, GL30.GL_RG, GL_UNSIGNED_BYTE, lightData.ptr());
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4 is the default
|
||||
bufferDirty = false;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package com.jozufozu.flywheel.light;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||
|
||||
|
@ -15,13 +14,53 @@ public class LightVolume implements ImmutableBox, LightListener {
|
|||
|
||||
protected final BlockAndTintGetter level;
|
||||
protected final GridAlignedBB box = new GridAlignedBB();
|
||||
protected ByteBuffer lightData;
|
||||
protected MemoryBlock lightData;
|
||||
|
||||
public LightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) {
|
||||
this.level = level;
|
||||
this.setBox(sampleVolume);
|
||||
|
||||
this.lightData = MemoryUtil.memAlloc(this.box.volume() * 2);
|
||||
this.lightData = MemoryBlock.malloc(this.box.volume() * 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableBox getVolume() {
|
||||
return box;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinX() {
|
||||
return box.getMinX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return box.getMinY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinZ() {
|
||||
return box.getMinZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxX() {
|
||||
return box.getMaxX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY() {
|
||||
return box.getMaxY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxZ() {
|
||||
return box.getMaxZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerInvalid() {
|
||||
return lightData == null;
|
||||
}
|
||||
|
||||
protected void setBox(ImmutableBox box) {
|
||||
|
@ -30,47 +69,143 @@ public class LightVolume implements ImmutableBox, LightListener {
|
|||
|
||||
public short getPackedLight(int x, int y, int z) {
|
||||
if (box.contains(x, y, z)) {
|
||||
return lightData.getShort(worldPosToBufferIndex(x, y, z));
|
||||
return MemoryUtil.memGetShort(worldPosToPtr(x, y, z));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getMinX() {
|
||||
return box.getMinX();
|
||||
}
|
||||
|
||||
public int getMinY() {
|
||||
return box.getMinY();
|
||||
}
|
||||
|
||||
public int getMinZ() {
|
||||
return box.getMinZ();
|
||||
}
|
||||
|
||||
public int getMaxX() {
|
||||
return box.getMaxX();
|
||||
}
|
||||
|
||||
public int getMaxY() {
|
||||
return box.getMaxY();
|
||||
}
|
||||
|
||||
public int getMaxZ() {
|
||||
return box.getMaxZ();
|
||||
}
|
||||
|
||||
public void move(ImmutableBox newSampleVolume) {
|
||||
if (lightData == null) return;
|
||||
|
||||
setBox(newSampleVolume);
|
||||
int neededCapacity = box.volume() * 2;
|
||||
if (neededCapacity > lightData.capacity()) {
|
||||
lightData = MemoryUtil.memRealloc(lightData, neededCapacity);
|
||||
if (neededCapacity > lightData.size()) {
|
||||
lightData = lightData.realloc(neededCapacity);
|
||||
}
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely (re)populate this volume with block and sky lighting data.
|
||||
* This is expensive and should be avoided.
|
||||
*/
|
||||
public void initialize() {
|
||||
if (lightData == null) return;
|
||||
|
||||
copyLight(getVolume());
|
||||
markDirty();
|
||||
}
|
||||
|
||||
protected void markDirty() {
|
||||
// noop
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
lightData.free();
|
||||
lightData = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all light from the world into this volume.
|
||||
*
|
||||
* @param worldVolume the region in the world to copy data from.
|
||||
*/
|
||||
public void copyLight(ImmutableBox worldVolume) {
|
||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||
|
||||
int xShift = box.getMinX();
|
||||
int yShift = box.getMinY();
|
||||
int zShift = box.getMinZ();
|
||||
|
||||
worldVolume.forEachContained((x, y, z) -> {
|
||||
pos.set(x, y, z);
|
||||
|
||||
int block = this.level.getBrightness(LightLayer.BLOCK, pos);
|
||||
int sky = this.level.getBrightness(LightLayer.SKY, pos);
|
||||
|
||||
writeLight(x - xShift, y - yShift, z - zShift, block, sky);
|
||||
});
|
||||
}
|
||||
|
||||
protected void writeLight(int x, int y, int z, int block, int sky) {
|
||||
byte b = (byte) ((block & 0xF) << 4);
|
||||
byte s = (byte) ((sky & 0xF) << 4);
|
||||
|
||||
long ptr = boxPosToPtr(x, y, z);
|
||||
MemoryUtil.memPutByte(ptr, b);
|
||||
MemoryUtil.memPutByte(ptr + 1, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy block light from the world into this volume.
|
||||
*
|
||||
* @param worldVolume the region in the world to copy data from.
|
||||
*/
|
||||
public void copyBlock(ImmutableBox worldVolume) {
|
||||
var pos = new BlockPos.MutableBlockPos();
|
||||
|
||||
int xShift = box.getMinX();
|
||||
int yShift = box.getMinY();
|
||||
int zShift = box.getMinZ();
|
||||
|
||||
worldVolume.forEachContained((x, y, z) -> {
|
||||
int light = this.level.getBrightness(LightLayer.BLOCK, pos.set(x, y, z));
|
||||
|
||||
writeBlock(x - xShift, y - yShift, z - zShift, light);
|
||||
});
|
||||
}
|
||||
|
||||
protected void writeBlock(int x, int y, int z, int block) {
|
||||
byte b = (byte) ((block & 0xF) << 4);
|
||||
|
||||
MemoryUtil.memPutByte(boxPosToPtr(x, y, z), b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy sky light from the world into this volume.
|
||||
*
|
||||
* @param worldVolume the region in the world to copy data from.
|
||||
*/
|
||||
public void copySky(ImmutableBox worldVolume) {
|
||||
var pos = new BlockPos.MutableBlockPos();
|
||||
|
||||
int xShift = box.getMinX();
|
||||
int yShift = box.getMinY();
|
||||
int zShift = box.getMinZ();
|
||||
|
||||
worldVolume.forEachContained((x, y, z) -> {
|
||||
int light = this.level.getBrightness(LightLayer.SKY, pos.set(x, y, z));
|
||||
|
||||
writeSky(x - xShift, y - yShift, z - zShift, light);
|
||||
});
|
||||
}
|
||||
|
||||
protected void writeSky(int x, int y, int z, int sky) {
|
||||
byte s = (byte) ((sky & 0xF) << 4);
|
||||
|
||||
MemoryUtil.memPutByte(boxPosToPtr(x, y, z) + 1, s);
|
||||
}
|
||||
|
||||
protected long worldPosToPtr(int x, int y, int z) {
|
||||
return lightData.ptr() + worldPosToPtrOffset(x, y, z);
|
||||
}
|
||||
|
||||
protected long boxPosToPtr(int x, int y, int z) {
|
||||
return lightData.ptr() + boxPosToPtrOffset(x, y, z);
|
||||
}
|
||||
|
||||
protected int worldPosToPtrOffset(int x, int y, int z) {
|
||||
x -= box.getMinX();
|
||||
y -= box.getMinY();
|
||||
z -= box.getMinZ();
|
||||
return boxPosToPtrOffset(x, y, z);
|
||||
}
|
||||
|
||||
protected int boxPosToPtrOffset(int x, int y, int z) {
|
||||
return (x + box.sizeX() * (y + z * box.sizeY())) * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLightUpdate(LightLayer type, ImmutableBox changedVolume) {
|
||||
if (lightData == null) return;
|
||||
|
@ -96,126 +231,4 @@ public class LightVolume implements ImmutableBox, LightListener {
|
|||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely (re)populate this volume with block and sky lighting data.
|
||||
* This is expensive and should be avoided.
|
||||
*/
|
||||
public void initialize() {
|
||||
if (lightData == null) return;
|
||||
|
||||
copyLight(getVolume());
|
||||
markDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy block light from the world into this volume.
|
||||
*
|
||||
* @param worldVolume the region in the world to copy data from.
|
||||
*/
|
||||
public void copyBlock(ImmutableBox worldVolume) {
|
||||
var pos = new BlockPos.MutableBlockPos();
|
||||
|
||||
int xShift = box.getMinX();
|
||||
int yShift = box.getMinY();
|
||||
int zShift = box.getMinZ();
|
||||
|
||||
worldVolume.forEachContained((x, y, z) -> {
|
||||
int light = this.level.getBrightness(LightLayer.BLOCK, pos.set(x, y, z));
|
||||
|
||||
writeBlock(x - xShift, y - yShift, z - zShift, light);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy sky light from the world into this volume.
|
||||
*
|
||||
* @param worldVolume the region in the world to copy data from.
|
||||
*/
|
||||
public void copySky(ImmutableBox worldVolume) {
|
||||
var pos = new BlockPos.MutableBlockPos();
|
||||
|
||||
int xShift = box.getMinX();
|
||||
int yShift = box.getMinY();
|
||||
int zShift = box.getMinZ();
|
||||
|
||||
worldVolume.forEachContained((x, y, z) -> {
|
||||
int light = this.level.getBrightness(LightLayer.SKY, pos.set(x, y, z));
|
||||
|
||||
writeSky(x - xShift, y - yShift, z - zShift, light);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all light from the world into this volume.
|
||||
*
|
||||
* @param worldVolume the region in the world to copy data from.
|
||||
*/
|
||||
public void copyLight(ImmutableBox worldVolume) {
|
||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||
|
||||
int xShift = box.getMinX();
|
||||
int yShift = box.getMinY();
|
||||
int zShift = box.getMinZ();
|
||||
|
||||
worldVolume.forEachContained((x, y, z) -> {
|
||||
pos.set(x, y, z);
|
||||
|
||||
int block = this.level.getBrightness(LightLayer.BLOCK, pos);
|
||||
int sky = this.level.getBrightness(LightLayer.SKY, pos);
|
||||
|
||||
writeLight(x - xShift, y - yShift, z - zShift, block, sky);
|
||||
});
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
MemoryUtil.memFree(lightData);
|
||||
lightData = null;
|
||||
}
|
||||
|
||||
protected void markDirty() {
|
||||
// noop
|
||||
}
|
||||
|
||||
protected void writeLight(int x, int y, int z, int block, int sky) {
|
||||
byte b = (byte) ((block & 0xF) << 4);
|
||||
byte s = (byte) ((sky & 0xF) << 4);
|
||||
|
||||
int i = boxPosToBufferIndex(x, y, z);
|
||||
lightData.put(i, b);
|
||||
lightData.put(i + 1, s);
|
||||
}
|
||||
|
||||
protected void writeBlock(int x, int y, int z, int block) {
|
||||
byte b = (byte) ((block & 0xF) << 4);
|
||||
|
||||
lightData.put(boxPosToBufferIndex(x, y, z), b);
|
||||
}
|
||||
|
||||
protected void writeSky(int x, int y, int z, int sky) {
|
||||
byte b = (byte) ((sky & 0xF) << 4);
|
||||
|
||||
lightData.put(boxPosToBufferIndex(x, y, z) + 1, b);
|
||||
}
|
||||
|
||||
protected int worldPosToBufferIndex(int x, int y, int z) {
|
||||
x -= box.getMinX();
|
||||
y -= box.getMinY();
|
||||
z -= box.getMinZ();
|
||||
return boxPosToBufferIndex(x, y, z);
|
||||
}
|
||||
|
||||
protected int boxPosToBufferIndex(int x, int y, int z) {
|
||||
return (x + box.sizeX() * (y + z * box.sizeY())) * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableBox getVolume() {
|
||||
return box;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isListenerInvalid() {
|
||||
return lightData == null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,19 +15,33 @@ import java.util.stream.Collectors;
|
|||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
||||
|
||||
public class StringUtil {
|
||||
|
||||
private static final NumberFormat timeFormat = new DecimalFormat("#0.000");
|
||||
private static final NumberFormat THREE_DECIMAL_PLACES = new DecimalFormat("#0.000");
|
||||
|
||||
public static String formatBytes(long bytes) {
|
||||
if (bytes < 1024) {
|
||||
return bytes + " B";
|
||||
} else if (bytes < 1024 * 1024) {
|
||||
return THREE_DECIMAL_PLACES.format(bytes / 1024f) + " KiB";
|
||||
} else if (bytes < 1024 * 1024 * 1024) {
|
||||
return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f) + " MiB";
|
||||
} else {
|
||||
return THREE_DECIMAL_PLACES.format(bytes / 1024f / 1024f / 1024f) + " GiB";
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatTime(long ns) {
|
||||
if (ns < 1000) {
|
||||
return ns + " ns";
|
||||
} else if (ns < 1000000) {
|
||||
return timeFormat.format(ns / 1000.) + " μs";
|
||||
return THREE_DECIMAL_PLACES.format(ns / 1000f) + " μs";
|
||||
} else if (ns < 1000000000) {
|
||||
return timeFormat.format(ns / 1000000.) + " ms";
|
||||
return THREE_DECIMAL_PLACES.format(ns / 1000000f) + " ms";
|
||||
} else {
|
||||
return timeFormat.format(ns / 1000000000.) + " s";
|
||||
return THREE_DECIMAL_PLACES.format(ns / 1000000000f) + " s";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,11 +70,11 @@ public class StringUtil {
|
|||
((Buffer) bytebuffer).rewind();
|
||||
return MemoryUtil.memASCII(bytebuffer, i);
|
||||
} catch (IOException ignored) {
|
||||
//
|
||||
} finally {
|
||||
if (bytebuffer != null) {
|
||||
MemoryUtil.memFree(bytebuffer);
|
||||
FlwMemoryTracker.freeBuffer(bytebuffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -75,12 +89,12 @@ public class StringUtil {
|
|||
}
|
||||
|
||||
private static ByteBuffer readInputStream(InputStream is) throws IOException {
|
||||
ByteBuffer bytebuffer = MemoryUtil.memAlloc(8192);
|
||||
ByteBuffer bytebuffer = FlwMemoryTracker.mallocBuffer(8192);
|
||||
ReadableByteChannel readablebytechannel = Channels.newChannel(is);
|
||||
|
||||
while (readablebytechannel.read(bytebuffer) != -1) {
|
||||
if (bytebuffer.remaining() == 0) {
|
||||
bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2);
|
||||
bytebuffer = FlwMemoryTracker.reallocBuffer(bytebuffer, bytebuffer.capacity() * 2);
|
||||
}
|
||||
}
|
||||
return bytebuffer;
|
||||
|
@ -88,7 +102,7 @@ public class StringUtil {
|
|||
|
||||
private static ByteBuffer readFileInputStream(FileInputStream fileinputstream) throws IOException {
|
||||
FileChannel filechannel = fileinputstream.getChannel();
|
||||
ByteBuffer bytebuffer = MemoryUtil.memAlloc((int) filechannel.size() + 1);
|
||||
ByteBuffer bytebuffer = FlwMemoryTracker.mallocBuffer((int) filechannel.size() + 1);
|
||||
|
||||
while (filechannel.read(bytebuffer) != -1) {
|
||||
}
|
||||
|
|
|
@ -36,7 +36,16 @@ public class WorldAttached<T> {
|
|||
i.remove();
|
||||
} else {
|
||||
// Prevent leaks
|
||||
map.remove(world);
|
||||
Object attached = map.remove(world);
|
||||
|
||||
// No, *really* prevent leaks
|
||||
if (attached instanceof AutoCloseable closeable) {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (Exception ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ import com.jozufozu.flywheel.core.Materials;
|
|||
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
|
||||
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedPart;
|
||||
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
import com.mojang.math.Quaternion;
|
||||
import com.mojang.math.Vector3f;
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.jozufozu.flywheel.core.model.Mesh;
|
|||
import com.jozufozu.flywheel.core.model.Models;
|
||||
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.jozufozu.flywheel.core.Materials;
|
|||
import com.jozufozu.flywheel.core.hardcoded.ModelPart;
|
||||
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
|
|
@ -13,7 +13,7 @@ import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
|||
import com.jozufozu.flywheel.backend.instancing.effect.Effect;
|
||||
import com.jozufozu.flywheel.core.model.Models;
|
||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
||||
import com.jozufozu.flywheel.core.structs.model.TransformedPart;
|
||||
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||
|
|
Loading…
Reference in a new issue