mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-02-07 10:45:00 +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();
|
VertexTransformer getVertexTransformer();
|
||||||
|
|
||||||
public interface VertexTransformer {
|
interface VertexTransformer {
|
||||||
void transform(MutableVertexList vertexList, ClientLevel level);
|
void transform(MutableVertexList vertexList, ClientLevel level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.jozufozu.flywheel.api.struct;
|
package com.jozufozu.flywheel.api.struct;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
|
@ -25,22 +23,17 @@ public interface StructType<S extends InstancedPart> {
|
||||||
*/
|
*/
|
||||||
BufferLayout getLayout();
|
BufferLayout getLayout();
|
||||||
|
|
||||||
/**
|
StructWriter<S> getWriter();
|
||||||
* 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);
|
|
||||||
|
|
||||||
FileResolution getInstanceShader();
|
FileResolution getInstanceShader();
|
||||||
|
|
||||||
VertexTransformer<? extends S> getVertexTransformer();
|
VertexTransformer<S> getVertexTransformer();
|
||||||
|
|
||||||
StorageBufferWriter<S> getStorageBufferWriter();
|
StorageBufferWriter<S> getStorageBufferWriter();
|
||||||
|
|
||||||
FileResolution getIndirectShader();
|
FileResolution getIndirectShader();
|
||||||
|
|
||||||
public interface VertexTransformer<S extends InstancedPart> {
|
interface VertexTransformer<S extends InstancedPart> {
|
||||||
void transform(MutableVertexList vertexList, S struct, ClientLevel level);
|
void transform(MutableVertexList vertexList, S struct, ClientLevel level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
package com.jozufozu.flywheel.api.struct;
|
package com.jozufozu.flywheel.api.struct;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StructWriters can quickly consume many instances of S and write them to some backing buffer.
|
* StructWriters can quickly consume many instances of S and write them to some memory address.
|
||||||
*/
|
*/
|
||||||
public interface StructWriter<S> {
|
public interface StructWriter<S extends InstancedPart> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the given struct to the backing array.
|
* Write the given struct to the given memory address.
|
||||||
*/
|
*/
|
||||||
void write(S struct);
|
void write(long ptr, S struct);
|
||||||
|
|
||||||
/**
|
|
||||||
* Seek to the given position. The next write will occur there.
|
|
||||||
*/
|
|
||||||
void seek(int pos);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
package com.jozufozu.flywheel.api.uniform;
|
package com.jozufozu.flywheel.api.uniform;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
|
||||||
public abstract class UniformProvider {
|
public abstract class UniformProvider {
|
||||||
|
|
||||||
protected ByteBuffer buffer;
|
protected long ptr;
|
||||||
protected Notifier notifier;
|
protected Notifier notifier;
|
||||||
|
|
||||||
public abstract int getActualByteSize();
|
public abstract int getActualByteSize();
|
||||||
|
|
||||||
public void updatePtr(ByteBuffer backing, Notifier notifier) {
|
public void updatePtr(long ptr, Notifier notifier) {
|
||||||
this.buffer = backing;
|
this.ptr = ptr;
|
||||||
this.notifier = notifier;
|
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);
|
float normalZ(int index);
|
||||||
|
|
||||||
|
default void write(MutableVertexList dst, int srcIndex, int dstIndex) {
|
||||||
|
dst.x(dstIndex, x(srcIndex));
|
||||||
|
dst.y(dstIndex, y(srcIndex));
|
||||||
|
dst.z(dstIndex, z(srcIndex));
|
||||||
|
|
||||||
|
dst.r(dstIndex, r(srcIndex));
|
||||||
|
dst.g(dstIndex, g(srcIndex));
|
||||||
|
dst.b(dstIndex, b(srcIndex));
|
||||||
|
dst.a(dstIndex, a(srcIndex));
|
||||||
|
|
||||||
|
dst.u(dstIndex, u(srcIndex));
|
||||||
|
dst.v(dstIndex, v(srcIndex));
|
||||||
|
|
||||||
|
dst.overlay(dstIndex, overlay(srcIndex));
|
||||||
|
dst.light(dstIndex, light(srcIndex));
|
||||||
|
|
||||||
|
dst.normalX(dstIndex, normalX(srcIndex));
|
||||||
|
dst.normalY(dstIndex, normalY(srcIndex));
|
||||||
|
dst.normalZ(dstIndex, normalZ(srcIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
default void write(MutableVertexList dst, int srcStartIndex, int dstStartIndex, int vertexCount) {
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
write(dst, srcStartIndex + i, dstStartIndex + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default void writeAll(MutableVertexList dst) {
|
||||||
|
write(dst, 0, 0, getVertexCount());
|
||||||
|
}
|
||||||
|
|
||||||
int getVertexCount();
|
int getVertexCount();
|
||||||
|
|
||||||
default boolean isEmpty() {
|
default boolean isEmpty() {
|
||||||
|
|
|
@ -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;
|
package com.jozufozu.flywheel.api.vertex;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A vertex type containing metadata about a specific vertex layout.
|
* A vertex type containing metadata about a specific vertex layout.
|
||||||
*/
|
*/
|
||||||
public interface VertexType {
|
public interface VertexType extends VertexListProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The layout of this type of vertex when buffered.
|
* The layout of this type of vertex when buffered.
|
||||||
*/
|
*/
|
||||||
BufferLayout getLayout();
|
BufferLayout getLayout();
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a writer backed by the given ByteBuffer.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Implementors are encouraged to override the return type for ergonomics.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
VertexWriter createWriter(ByteBuffer buffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a view of the given ByteBuffer as if it were already filled with vertices.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Implementors are encouraged to override the return type for ergonomics.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
VertexList createReader(ByteBuffer buffer, int vertexCount);
|
|
||||||
|
|
||||||
FileResolution getLayoutShader();
|
FileResolution getLayoutShader();
|
||||||
|
|
||||||
default int getStride() {
|
default int getStride() {
|
||||||
|
|
|
@ -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;
|
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.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 {
|
public 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 final GlBufferType type;
|
public final GlBufferType type;
|
||||||
|
protected final GlBufferUsage usage;
|
||||||
/**
|
/**
|
||||||
* The size (in bytes) of the buffer on the GPU.
|
* The size (in bytes) of the buffer on the GPU.
|
||||||
*/
|
*/
|
||||||
protected long size;
|
protected long size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How much extra room to give the buffer when we reallocate.
|
* How much extra room to give the buffer when we reallocate.
|
||||||
*/
|
*/
|
||||||
protected int growthMargin;
|
protected int growthMargin;
|
||||||
|
|
||||||
public GlBuffer(GlBufferType type) {
|
public GlBuffer(GlBufferType type) {
|
||||||
setHandle(GL20.glGenBuffers());
|
this(type, GlBufferUsage.STATIC_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlBuffer(GlBufferType type, GlBufferUsage usage) {
|
||||||
|
setHandle(glGenBuffers());
|
||||||
this.type = type;
|
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) {
|
public void setGrowthMargin(int growthMargin) {
|
||||||
|
@ -66,24 +128,8 @@ public abstract class GlBuffer extends GlObject {
|
||||||
type.unbind();
|
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) {
|
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;
|
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.opengl.GL15;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
@ -11,10 +11,10 @@ public class MappedBuffer implements AutoCloseable {
|
||||||
private final long length;
|
private final long length;
|
||||||
private final GlBuffer owner;
|
private final GlBuffer owner;
|
||||||
private final boolean persistent;
|
private final boolean persistent;
|
||||||
private ByteBuffer internal;
|
private long ptr;
|
||||||
|
|
||||||
public MappedBuffer(GlBuffer owner, ByteBuffer internal, long offset, long length) {
|
public MappedBuffer(GlBuffer owner, long ptr, long offset, long length) {
|
||||||
this.internal = internal;
|
this.ptr = ptr;
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
@ -27,19 +27,11 @@ public class MappedBuffer implements AutoCloseable {
|
||||||
public void flush() {
|
public void flush() {
|
||||||
if (persistent) return;
|
if (persistent) return;
|
||||||
|
|
||||||
if (internal == null) return;
|
if (ptr == NULL) return;
|
||||||
|
|
||||||
owner.bind();
|
owner.bind();
|
||||||
GL15.glUnmapBuffer(owner.getType().glEnum);
|
GL15.glUnmapBuffer(owner.getType().glEnum);
|
||||||
internal = null;
|
ptr = 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,12 +39,8 @@ public class MappedBuffer implements AutoCloseable {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer unwrap() {
|
public long getPtr() {
|
||||||
return internal;
|
return ptr;
|
||||||
}
|
|
||||||
|
|
||||||
public long getMemAddress() {
|
|
||||||
return MemoryUtil.memAddress(internal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear(long clearStart, long clearLength) {
|
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");
|
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);
|
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.GL20C;
|
||||||
import org.lwjgl.opengl.GLCapabilities;
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import org.lwjgl.system.MemoryStack;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
|
||||||
|
|
||||||
import net.minecraft.Util;
|
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>
|
* <br> <a href="https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96">canvas</a>
|
||||||
*
|
*
|
||||||
* <p>Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but
|
* <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.
|
* <p>Hat tip to fewizz for the find and the fix.
|
||||||
*/
|
*/
|
||||||
public static void safeShaderSource(int glId, CharSequence source) {
|
public static void safeShaderSource(int glId, CharSequence source) {
|
||||||
final MemoryStack stack = MemoryStack.stackGet();
|
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||||
final int stackPointer = stack.getPointer();
|
final ByteBuffer sourceBuffer = stack.UTF8(source, true);
|
||||||
|
|
||||||
try {
|
|
||||||
final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true);
|
|
||||||
final PointerBuffer pointers = stack.mallocPointer(1);
|
final PointerBuffer pointers = stack.mallocPointer(1);
|
||||||
pointers.put(sourceBuffer);
|
pointers.put(sourceBuffer);
|
||||||
|
|
||||||
GL20C.nglShaderSource(glId, 1, pointers.address0(), 0);
|
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.InstancedPart;
|
||||||
import com.jozufozu.flywheel.api.instancer.Instancer;
|
import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
|
||||||
|
|
||||||
public abstract class AbstractInstancer<D extends InstancedPart> implements Instancer<D> {
|
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;
|
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();
|
public abstract void delete();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -28,7 +28,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
* The instancer manager is shared between the different instance managers.
|
* The instancer manager is shared between the different instance managers.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class InstanceWorld {
|
public class InstanceWorld implements AutoCloseable {
|
||||||
protected final Engine engine;
|
protected final Engine engine;
|
||||||
protected final InstanceManager<Entity> entities;
|
protected final InstanceManager<Entity> entities;
|
||||||
protected final InstanceManager<BlockEntity> blockEntities;
|
protected final InstanceManager<BlockEntity> blockEntities;
|
||||||
|
@ -148,4 +148,8 @@ public class InstanceWorld {
|
||||||
.forEach(entities::add);
|
.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.backend.instancing.TaskEngine;
|
||||||
import com.jozufozu.flywheel.core.RenderContext;
|
import com.jozufozu.flywheel.core.RenderContext;
|
||||||
import com.jozufozu.flywheel.util.FlwUtil;
|
import com.jozufozu.flywheel.util.FlwUtil;
|
||||||
import com.mojang.blaze3d.platform.Lighting;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.math.Matrix4f;
|
|
||||||
|
|
||||||
import net.minecraft.client.Camera;
|
import net.minecraft.client.Camera;
|
||||||
import net.minecraft.client.multiplayer.ClientLevel;
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
@ -68,19 +66,11 @@ public class BatchingEngine implements Engine {
|
||||||
@Override
|
@Override
|
||||||
public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) {
|
public void renderStage(TaskEngine taskEngine, RenderContext context, RenderStage stage) {
|
||||||
// FIXME: properly support material stages
|
// FIXME: properly support material stages
|
||||||
|
// This also breaks block outlines on batched block entities
|
||||||
if (stage != RenderStage.AFTER_FINAL_END_BATCH) {
|
if (stage != RenderStage.AFTER_FINAL_END_BATCH) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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();
|
batchTracker.endBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,28 +2,35 @@ package com.jozufozu.flywheel.backend.instancing.batching;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexListProvider;
|
||||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
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;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A byte buffer that can be used to draw vertices through multiple {@link MutableVertexListImpl}s.
|
* A byte buffer that can be used to draw vertices through multiple {@link ReusableVertexList}s.
|
||||||
*
|
*
|
||||||
* The number of vertices needs to be known ahead of time.
|
* The number of vertices needs to be known ahead of time.
|
||||||
*/
|
*/
|
||||||
public class DrawBuffer {
|
public class DrawBuffer {
|
||||||
private final RenderType parent;
|
private final RenderType parent;
|
||||||
private final VertexFormatInfo formatInfo;
|
private final VertexFormat format;
|
||||||
|
private final int stride;
|
||||||
|
private final VertexListProvider provider;
|
||||||
|
|
||||||
|
private MemoryBlock memory;
|
||||||
|
private ByteBuffer buffer;
|
||||||
|
|
||||||
private ByteBuffer backingBuffer;
|
|
||||||
private int expectedVertices;
|
private int expectedVertices;
|
||||||
private long ptr;
|
|
||||||
|
|
||||||
public DrawBuffer(RenderType parent) {
|
public DrawBuffer(RenderType parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
formatInfo = new VertexFormatInfo(parent.format());
|
format = parent.format();
|
||||||
|
stride = format.getVertexSize();
|
||||||
|
provider = VertexListProviderRegistry.getOrInfer(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,29 +40,32 @@ public class DrawBuffer {
|
||||||
*/
|
*/
|
||||||
public void prepare(int vertexCount) {
|
public void prepare(int vertexCount) {
|
||||||
if (expectedVertices != 0) {
|
if (expectedVertices != 0) {
|
||||||
throw new IllegalStateException("Already drawing");
|
throw new IllegalStateException("Already drawing!");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.expectedVertices = vertexCount;
|
this.expectedVertices = vertexCount;
|
||||||
|
|
||||||
// Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least
|
// Add one extra vertex to uphold the vanilla assumption that BufferBuilders have at least
|
||||||
// enough buffer space for one more vertex. Sodium checks for this extra space when popNextBuffer
|
// enough buffer space for one more vertex. Rubidium checks for this extra space when popNextBuffer
|
||||||
// is called and reallocates the buffer if there is not space for one more vertex.
|
// is called and reallocates the buffer if there is not space for one more vertex.
|
||||||
int byteSize = formatInfo.stride * (vertexCount + 1);
|
int byteSize = stride * (vertexCount + 1);
|
||||||
|
|
||||||
if (backingBuffer == null) {
|
if (memory == null) {
|
||||||
backingBuffer = MemoryTracker.create(byteSize);
|
memory = MemoryBlock.malloc(byteSize);
|
||||||
} else if (byteSize > backingBuffer.capacity()) {
|
buffer = memory.asBuffer();
|
||||||
backingBuffer = MemoryTracker.resize(backingBuffer, byteSize);
|
} else if (byteSize > memory.size()) {
|
||||||
|
memory = memory.realloc(byteSize);
|
||||||
|
buffer = memory.asBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
backingBuffer.clear();
|
memory.clear();
|
||||||
ptr = MemoryUtil.memAddress(backingBuffer);
|
|
||||||
MemoryUtil.memSet(ptr, 0, byteSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableVertexListImpl slice(int startVertex, int vertexCount) {
|
public ReusableVertexList slice(int startVertex, int vertexCount) {
|
||||||
return new MutableVertexListImpl(ptr + startVertex * formatInfo.stride, formatInfo, vertexCount);
|
ReusableVertexList vertexList = provider.createVertexList();
|
||||||
|
vertexList.ptr(memory.ptr() + startVertex * stride);
|
||||||
|
vertexList.setVertexCount(vertexCount);
|
||||||
|
return vertexList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +73,8 @@ public class DrawBuffer {
|
||||||
* @param bufferBuilder The buffer builder to inject into.
|
* @param bufferBuilder The buffer builder to inject into.
|
||||||
*/
|
*/
|
||||||
public void inject(BufferBuilderExtension bufferBuilder) {
|
public void inject(BufferBuilderExtension bufferBuilder) {
|
||||||
bufferBuilder.flywheel$injectForRender(backingBuffer, formatInfo.format, expectedVertices);
|
buffer.clear();
|
||||||
|
bufferBuilder.flywheel$injectForRender(buffer, format, expectedVertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVertexCount() {
|
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.
|
* Does not clear the backing buffer.
|
||||||
*/
|
*/
|
||||||
public void reset() {
|
public void reset() {
|
||||||
this.expectedVertices = 0;
|
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.instancer.InstancedPart;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType.VertexTransformer;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||||
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
import com.jozufozu.flywheel.backend.instancing.TaskEngine;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
@ -49,80 +48,50 @@ public class TransformSet<D extends InstancedPart> {
|
||||||
int start = Math.max(instances, 0);
|
int start = Math.max(instances, 0);
|
||||||
|
|
||||||
int vertexCount = mesh.getVertexCount() * (end - start);
|
int vertexCount = mesh.getVertexCount() * (end - start);
|
||||||
MutableVertexListImpl sub = buffer.slice(startVertex, vertexCount);
|
ReusableVertexList sub = buffer.slice(startVertex, vertexCount);
|
||||||
startVertex += vertexCount;
|
startVertex += vertexCount;
|
||||||
|
|
||||||
pool.submit(() -> drawRange(sub, start, end, stack, level));
|
pool.submit(() -> drawRange(sub, start, end, stack, level));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawRange(MutableVertexListImpl vertexList, int from, int to, PoseStack stack, ClientLevel level) {
|
private void drawRange(ReusableVertexList vertexList, int from, int to, PoseStack stack, ClientLevel level) {
|
||||||
drawList(vertexList, instancer.getRange(from, to), stack, level);
|
drawList(vertexList, instancer.getRange(from, to), stack, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawAll(MutableVertexListImpl vertexList, PoseStack stack, ClientLevel level) {
|
void drawAll(ReusableVertexList vertexList, PoseStack stack, ClientLevel level) {
|
||||||
drawList(vertexList, instancer.getAll(), stack, level);
|
drawList(vertexList, instancer.getAll(), stack, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawList(MutableVertexListImpl vertexList, List<D> list, PoseStack stack, ClientLevel level) {
|
private void drawList(ReusableVertexList vertexList, List<D> list, PoseStack stack, ClientLevel level) {
|
||||||
int startVertex = 0;
|
long anchorPtr = vertexList.ptr();
|
||||||
int meshVertexCount = mesh.getVertexCount();
|
int totalVertexCount = vertexList.getVertexCount();
|
||||||
|
|
||||||
VertexList meshReader = mesh.getReader();
|
int meshVertexCount = mesh.getVertexCount();
|
||||||
@SuppressWarnings("unchecked")
|
vertexList.setVertexCount(meshVertexCount);
|
||||||
StructType.VertexTransformer<D> structVertexTransformer = (VertexTransformer<D>) instancer.type.getVertexTransformer();
|
|
||||||
|
StructType.VertexTransformer<D> structVertexTransformer = instancer.type.getVertexTransformer();
|
||||||
|
|
||||||
for (D d : list) {
|
for (D d : list) {
|
||||||
vertexList.setRange(startVertex, meshVertexCount);
|
mesh.write(vertexList);
|
||||||
|
|
||||||
writeMesh(vertexList, meshReader);
|
|
||||||
|
|
||||||
structVertexTransformer.transform(vertexList, d, level);
|
structVertexTransformer.transform(vertexList, d, level);
|
||||||
|
|
||||||
startVertex += meshVertexCount;
|
vertexList.shiftPtr(meshVertexCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
vertexList.setFullRange();
|
vertexList.ptr(anchorPtr);
|
||||||
|
vertexList.setVertexCount(totalVertexCount);
|
||||||
material.getVertexTransformer().transform(vertexList, level);
|
material.getVertexTransformer().transform(vertexList, level);
|
||||||
applyPoseStack(vertexList, stack, false);
|
applyPoseStack(vertexList, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove this
|
private static void applyPoseStack(MutableVertexList vertexList, PoseStack stack) {
|
||||||
// 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) {
|
|
||||||
Vector4f pos = new Vector4f();
|
Vector4f pos = new Vector4f();
|
||||||
Vector3f normal = new Vector3f();
|
Vector3f normal = new Vector3f();
|
||||||
|
|
||||||
Matrix4f modelMatrix = stack.last().pose();
|
Matrix4f modelMatrix = stack.last().pose();
|
||||||
Matrix3f normalMatrix;
|
Matrix3f normalMatrix = stack.last().normal();
|
||||||
if (applyNormalMatrix) {
|
|
||||||
normalMatrix = stack.last().normal();
|
|
||||||
} else {
|
|
||||||
normalMatrix = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < vertexList.getVertexCount(); i++) {
|
for (int i = 0; i < vertexList.getVertexCount(); i++) {
|
||||||
pos.set(
|
pos.set(
|
||||||
|
@ -136,7 +105,6 @@ public class TransformSet<D extends InstancedPart> {
|
||||||
vertexList.y(i, pos.y());
|
vertexList.y(i, pos.y());
|
||||||
vertexList.z(i, pos.z());
|
vertexList.z(i, pos.z());
|
||||||
|
|
||||||
if (applyNormalMatrix) {
|
|
||||||
normal.set(
|
normal.set(
|
||||||
vertexList.normalX(i),
|
vertexList.normalX(i),
|
||||||
vertexList.normalY(i),
|
vertexList.normalY(i),
|
||||||
|
@ -149,7 +117,6 @@ public class TransformSet<D extends InstancedPart> {
|
||||||
vertexList.normalZ(i, normal.z());
|
vertexList.normalZ(i, normal.z());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotalVertexCount() {
|
public int getTotalVertexCount() {
|
||||||
return mesh.getVertexCount() * instancer.getInstanceCount();
|
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.api.instancer.InstancerManager;
|
||||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
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.oriented.OrientedPart;
|
||||||
|
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
|
||||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||||
import com.jozufozu.flywheel.util.joml.FrustumIntersection;
|
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.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
|
|
||||||
public class IndirectMeshPool {
|
public class IndirectMeshPool {
|
||||||
|
@ -23,7 +24,7 @@ public class IndirectMeshPool {
|
||||||
final VertexType vertexType;
|
final VertexType vertexType;
|
||||||
|
|
||||||
final int vbo;
|
final int vbo;
|
||||||
private final ByteBuffer clientStorage;
|
private final MemoryBlock clientStorage;
|
||||||
|
|
||||||
private boolean dirty;
|
private boolean dirty;
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ public class IndirectMeshPool {
|
||||||
vbo = glCreateBuffers();
|
vbo = glCreateBuffers();
|
||||||
var byteCapacity = type.byteOffset(vertexCapacity);
|
var byteCapacity = type.byteOffset(vertexCapacity);
|
||||||
glNamedBufferStorage(vbo, byteCapacity, GL_DYNAMIC_STORAGE_BIT);
|
glNamedBufferStorage(vbo, byteCapacity, GL_DYNAMIC_STORAGE_BIT);
|
||||||
clientStorage = MemoryUtil.memAlloc(byteCapacity);
|
clientStorage = MemoryBlock.malloc(byteCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,24 +66,25 @@ public class IndirectMeshPool {
|
||||||
}
|
}
|
||||||
dirty = false;
|
dirty = false;
|
||||||
|
|
||||||
|
final long ptr = clientStorage.ptr();
|
||||||
|
|
||||||
int byteIndex = 0;
|
int byteIndex = 0;
|
||||||
int baseVertex = 0;
|
int baseVertex = 0;
|
||||||
for (BufferedMesh model : meshList) {
|
for (BufferedMesh model : meshList) {
|
||||||
model.byteIndex = byteIndex;
|
model.byteIndex = byteIndex;
|
||||||
model.baseVertex = baseVertex;
|
model.baseVertex = baseVertex;
|
||||||
|
|
||||||
model.buffer(clientStorage);
|
model.buffer(ptr);
|
||||||
|
|
||||||
byteIndex += model.getByteSize();
|
byteIndex += model.getByteSize();
|
||||||
baseVertex += model.mesh.getVertexCount();
|
baseVertex += model.mesh.getVertexCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
clientStorage.rewind();
|
nglNamedBufferSubData(vbo, 0, byteIndex, ptr);
|
||||||
|
|
||||||
glNamedBufferSubData(vbo, 0, clientStorage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
|
clientStorage.free();
|
||||||
glDeleteBuffers(vbo);
|
glDeleteBuffers(vbo);
|
||||||
meshes.clear();
|
meshes.clear();
|
||||||
meshList.clear();
|
meshList.clear();
|
||||||
|
@ -101,10 +103,8 @@ public class IndirectMeshPool {
|
||||||
vertexCount = mesh.getVertexCount();
|
vertexCount = mesh.getVertexCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buffer(ByteBuffer buffer) {
|
private void buffer(long ptr) {
|
||||||
var writer = IndirectMeshPool.this.vertexType.createWriter(buffer);
|
this.mesh.write(ptr + byteIndex);
|
||||||
writer.seek(this.byteIndex);
|
|
||||||
writer.writeVertexList(this.mesh.getReader());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getByteSize() {
|
public int getByteSize() {
|
||||||
|
|
|
@ -6,12 +6,12 @@ import java.util.Set;
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
|
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||||
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferUsage;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
|
||||||
public void init() {
|
public void init() {
|
||||||
if (vbo != null) return;
|
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);
|
vbo.setGrowthMargin(instanceFormat.getStride() * 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,16 @@ public class GPUInstancer<D extends InstancedPart> extends AbstractInstancer<D>
|
||||||
buf.clear(clearStart, clearLength);
|
buf.clear(clearStart, clearLength);
|
||||||
|
|
||||||
if (size > 0) {
|
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) {
|
} catch (Exception e) {
|
||||||
Flywheel.LOGGER.error("Error updating GPUInstancer:", e);
|
Flywheel.LOGGER.error("Error updating GPUInstancer:", e);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.backend.instancing.instancing;
|
package com.jozufozu.flywheel.backend.instancing.instancing;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
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.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
|
@ -27,7 +26,7 @@ public class MeshPool {
|
||||||
|
|
||||||
private static MeshPool allocator;
|
private static MeshPool allocator;
|
||||||
|
|
||||||
static MeshPool getInstance() {
|
public static MeshPool getInstance() {
|
||||||
if (allocator == null) {
|
if (allocator == null) {
|
||||||
allocator = new MeshPool();
|
allocator = new MeshPool();
|
||||||
}
|
}
|
||||||
|
@ -58,7 +57,7 @@ public class MeshPool {
|
||||||
* Create a new mesh pool.
|
* Create a new mesh pool.
|
||||||
*/
|
*/
|
||||||
public MeshPool() {
|
public MeshPool() {
|
||||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
|
|
||||||
vbo.setGrowthMargin(2048);
|
vbo.setGrowthMargin(2048);
|
||||||
}
|
}
|
||||||
|
@ -71,9 +70,8 @@ public class MeshPool {
|
||||||
*/
|
*/
|
||||||
public BufferedMesh alloc(Mesh mesh) {
|
public BufferedMesh alloc(Mesh mesh) {
|
||||||
return meshes.computeIfAbsent(mesh, m -> {
|
return meshes.computeIfAbsent(mesh, m -> {
|
||||||
// FIXME: culling experiments fixing everything to Formats.BLOCK
|
BufferedMesh bufferedModel = new BufferedMesh(m, byteSize, vertexCount);
|
||||||
BufferedMesh bufferedModel = new BufferedMesh(Formats.BLOCK, m, byteSize, vertexCount);
|
byteSize += m.size();
|
||||||
byteSize += bufferedModel.getByteSize();
|
|
||||||
vertexCount += bufferedModel.mesh.getVertexCount();
|
vertexCount += bufferedModel.mesh.getVertexCount();
|
||||||
allBuffered.add(bufferedModel);
|
allBuffered.add(bufferedModel);
|
||||||
pendingUpload.add(bufferedModel);
|
pendingUpload.add(bufferedModel);
|
||||||
|
@ -147,7 +145,7 @@ public class MeshPool {
|
||||||
|
|
||||||
private void uploadAll() {
|
private void uploadAll() {
|
||||||
try (MappedBuffer mapped = vbo.map()) {
|
try (MappedBuffer mapped = vbo.map()) {
|
||||||
ByteBuffer buffer = mapped.unwrap();
|
long ptr = mapped.getPtr();
|
||||||
|
|
||||||
int byteIndex = 0;
|
int byteIndex = 0;
|
||||||
int baseVertex = 0;
|
int baseVertex = 0;
|
||||||
|
@ -155,26 +153,26 @@ public class MeshPool {
|
||||||
model.byteIndex = byteIndex;
|
model.byteIndex = byteIndex;
|
||||||
model.baseVertex = baseVertex;
|
model.baseVertex = baseVertex;
|
||||||
|
|
||||||
model.buffer(buffer);
|
model.buffer(ptr);
|
||||||
|
|
||||||
byteIndex += model.getByteSize();
|
byteIndex += model.getByteSize();
|
||||||
baseVertex += model.mesh.getVertexCount();
|
baseVertex += model.mesh.getVertexCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.LOGGER.error("Error uploading pooled models:", e);
|
Flywheel.LOGGER.error("Error uploading pooled meshes:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void uploadPending() {
|
private void uploadPending() {
|
||||||
try (MappedBuffer mapped = vbo.map()) {
|
try (MappedBuffer mapped = vbo.map()) {
|
||||||
ByteBuffer buffer = mapped.unwrap();
|
long buffer = mapped.getPtr();
|
||||||
for (BufferedMesh model : pendingUpload) {
|
for (BufferedMesh model : pendingUpload) {
|
||||||
model.buffer(buffer);
|
model.buffer(buffer);
|
||||||
}
|
}
|
||||||
pendingUpload.clear();
|
pendingUpload.clear();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.LOGGER.error("Error uploading pooled models:", e);
|
Flywheel.LOGGER.error("Error uploading pooled meshes:", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,14 +205,6 @@ public class MeshPool {
|
||||||
this.type = mesh.getVertexType();
|
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) {
|
public void drawCall(GlVertexArray vao) {
|
||||||
drawInstances(vao, 1);
|
drawInstances(vao, 1);
|
||||||
}
|
}
|
||||||
|
@ -228,7 +218,7 @@ public class MeshPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasAnythingToRender() {
|
private boolean hasAnythingToRender() {
|
||||||
return mesh.getVertexCount() <= 0 || isDeleted();
|
return mesh.isEmpty() || isDeleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void draw(int instanceCount) {
|
private void draw(int instanceCount) {
|
||||||
|
@ -258,10 +248,8 @@ public class MeshPool {
|
||||||
this.deleted = true;
|
this.deleted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buffer(ByteBuffer buffer) {
|
private void buffer(long ptr) {
|
||||||
var writer = type.createWriter(buffer);
|
this.mesh.write(ptr + byteIndex);
|
||||||
writer.seek(this.byteIndex);
|
|
||||||
writer.writeVertexList(this.mesh.getReader());
|
|
||||||
|
|
||||||
this.boundTo.clear();
|
this.boundTo.clear();
|
||||||
this.gpuResident = true;
|
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.GL_TRIANGLES;
|
||||||
import static org.lwjgl.opengl.GL11.glDrawArrays;
|
import static org.lwjgl.opengl.GL11.glDrawArrays;
|
||||||
|
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||||
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
import com.jozufozu.flywheel.backend.gl.array.GlVertexArray;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
import com.jozufozu.flywheel.core.layout.CommonItems;
|
import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.util.Lazy;
|
import com.jozufozu.flywheel.util.Lazy;
|
||||||
|
@ -34,13 +35,14 @@ public class FullscreenQuad {
|
||||||
|
|
||||||
private FullscreenQuad() {
|
private FullscreenQuad() {
|
||||||
try (var restoreState = GlStateTracker.getRestoreState()) {
|
try (var restoreState = GlStateTracker.getRestoreState()) {
|
||||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
vbo = new GlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||||
vbo.ensureCapacity(bufferSize);
|
vbo.ensureCapacity(bufferSize);
|
||||||
try (MappedBuffer buffer = vbo.map()) {
|
try (MappedBuffer buffer = vbo.map()) {
|
||||||
|
var ptr = buffer.getPtr();
|
||||||
|
|
||||||
buffer.unwrap()
|
for (var i = 0; i < vertices.length; i++) {
|
||||||
.asFloatBuffer()
|
MemoryUtil.memPutFloat(ptr + i * Float.BYTES, vertices[i]);
|
||||||
.put(vertices);
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
|
Flywheel.LOGGER.error("Could not create fullscreen quad.", e);
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
package com.jozufozu.flywheel.core;
|
package com.jozufozu.flywheel.core;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
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.GlBufferType;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
|
|
||||||
|
@ -34,11 +32,11 @@ public class QuadConverter {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MappedGlBuffer ebo;
|
private final GlBuffer ebo;
|
||||||
private int quadCapacity;
|
private int quadCapacity;
|
||||||
|
|
||||||
public QuadConverter() {
|
public QuadConverter() {
|
||||||
this.ebo = new MappedGlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
this.ebo = new GlBuffer(GlBufferType.ELEMENT_ARRAY_BUFFER);
|
||||||
this.quadCapacity = 0;
|
this.quadCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +47,7 @@ public class QuadConverter {
|
||||||
ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth());
|
ebo.ensureCapacity((long) indexCount * GlNumericType.UINT.getByteWidth());
|
||||||
|
|
||||||
try (MappedBuffer map = ebo.map()) {
|
try (MappedBuffer map = ebo.map()) {
|
||||||
ByteBuffer indices = map.unwrap();
|
fillBuffer(map.getPtr(), quads);
|
||||||
|
|
||||||
fillBuffer(indices, quads);
|
|
||||||
}
|
}
|
||||||
ebo.unbind();
|
ebo.unbind();
|
||||||
|
|
||||||
|
@ -66,32 +62,18 @@ public class QuadConverter {
|
||||||
this.quadCapacity = 0;
|
this.quadCapacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillBuffer(ByteBuffer indices, int quads) {
|
private void fillBuffer(long addr, int quads) {
|
||||||
long addr = MemoryUtil.memAddress(indices);
|
|
||||||
int numVertices = 4 * quads;
|
int numVertices = 4 * quads;
|
||||||
int baseVertex = 0;
|
int baseVertex = 0;
|
||||||
while (baseVertex < numVertices) {
|
while (baseVertex < numVertices) {
|
||||||
// writeQuadIndices(indices, baseVertex);
|
writeQuadIndices(addr, baseVertex);
|
||||||
writeQuadIndicesUnsafe(addr, baseVertex);
|
|
||||||
|
|
||||||
baseVertex += 4;
|
baseVertex += 4;
|
||||||
addr += 6 * 4;
|
addr += 6 * 4;
|
||||||
}
|
}
|
||||||
// ((Buffer) indices).flip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeQuadIndices(ByteBuffer indices, int baseVertex) {
|
private void writeQuadIndices(long addr, 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) {
|
|
||||||
// triangle a
|
// triangle a
|
||||||
MemoryUtil.memPutInt(addr, baseVertex);
|
MemoryUtil.memPutInt(addr, baseVertex);
|
||||||
MemoryUtil.memPutInt(addr + 4, baseVertex + 1);
|
MemoryUtil.memPutInt(addr + 4, baseVertex + 1);
|
||||||
|
@ -102,7 +84,7 @@ public class QuadConverter {
|
||||||
MemoryUtil.memPutInt(addr + 20, baseVertex + 3);
|
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) {
|
public static void onRendererReload(ReloadRenderersEvent event) {
|
||||||
if (INSTANCE != null) {
|
if (INSTANCE != null) {
|
||||||
INSTANCE.delete();
|
INSTANCE.delete();
|
||||||
|
|
|
@ -2,74 +2,86 @@ package com.jozufozu.flywheel.core.hardcoded;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||||
import org.lwjgl.system.MemoryStack;
|
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex;
|
import com.jozufozu.flywheel.core.vertex.PosTexNormalVertex;
|
||||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
|
||||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||||
|
|
||||||
public class ModelPart implements Mesh {
|
public class ModelPart implements Mesh {
|
||||||
|
private final int vertexCount;
|
||||||
private final int vertices;
|
private final MemoryBlock contents;
|
||||||
|
private final ReusableVertexList vertexList;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final VertexList reader;
|
private final Vector4f boundingSphere;
|
||||||
private final @NotNull Vector4f boundingSphere;
|
|
||||||
|
|
||||||
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) {
|
public ModelPart(List<PartBuilder.CuboidBuilder> cuboids, String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
{
|
this.vertexCount = countVertices(cuboids);
|
||||||
int vertices = 0;
|
|
||||||
|
contents = MemoryBlock.malloc(size());
|
||||||
|
long ptr = contents.ptr();
|
||||||
|
VertexWriter writer = new VertexWriterImpl(ptr);
|
||||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
||||||
vertices += cuboid.vertices();
|
cuboid.write(writer);
|
||||||
}
|
|
||||||
this.vertices = vertices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try (var stack = MemoryStack.stackPush()) {
|
vertexList = getVertexType().createVertexList();
|
||||||
PosTexNormalWriterUnsafe writer = getVertexType().createWriter(stack.malloc(size()));
|
vertexList.ptr(ptr);
|
||||||
for (PartBuilder.CuboidBuilder cuboid : cuboids) {
|
vertexList.setVertexCount(vertexCount);
|
||||||
cuboid.buffer(writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
reader = writer.intoReader(this.vertices);
|
boundingSphere = ModelUtil.computeBoundingSphere(vertexList);
|
||||||
}
|
|
||||||
|
|
||||||
boundingSphere = ModelUtil.computeBoundingSphere(reader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PartBuilder builder(String name, int sizeU, int sizeV) {
|
public static PartBuilder builder(String name, int sizeU, int sizeV) {
|
||||||
return new PartBuilder(name, sizeU, 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
|
@Override
|
||||||
public PosTexNormalVertex getVertexType() {
|
public PosTexNormalVertex getVertexType() {
|
||||||
return Formats.POS_TEX_NORMAL;
|
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
|
@Override
|
||||||
public Vector4fc getBoundingSphere() {
|
public Vector4fc getBoundingSphere() {
|
||||||
return boundingSphere;
|
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.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.core.vertex.PosTexNormalWriterUnsafe;
|
|
||||||
import com.mojang.math.Matrix3f;
|
import com.mojang.math.Matrix3f;
|
||||||
import com.mojang.math.Quaternion;
|
import com.mojang.math.Quaternion;
|
||||||
import com.mojang.math.Vector3f;
|
import com.mojang.math.Vector3f;
|
||||||
|
@ -160,8 +159,7 @@ public class PartBuilder {
|
||||||
return visibleFaces.size() * 4;
|
return visibleFaces.size() * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buffer(PosTexNormalWriterUnsafe buffer) {
|
public void write(VertexWriter writer) {
|
||||||
|
|
||||||
float sizeX = posX2 - posX1;
|
float sizeX = posX2 - posX1;
|
||||||
float sizeY = posY2 - posY1;
|
float sizeY = posY2 - posY1;
|
||||||
float sizeZ = posZ2 - posZ1;
|
float sizeZ = posZ2 - posZ1;
|
||||||
|
@ -219,28 +217,27 @@ public class PartBuilder {
|
||||||
float f12 = getV((float)textureOffsetV + sizeZ + sizeY);
|
float f12 = getV((float)textureOffsetV + sizeZ + sizeY);
|
||||||
|
|
||||||
if (invertYZ) {
|
if (invertYZ) {
|
||||||
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, down);
|
quad(writer, new Vector3f[]{hlh, llh, lll, hll}, f6, f11, f7, f10, down);
|
||||||
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, up);
|
quad(writer, new Vector3f[]{hhl, lhl, lhh, hhh}, f5, f10, f6, f11, up);
|
||||||
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, west);
|
quad(writer, new Vector3f[]{lll, llh, lhh, lhl}, f5, f12, f4, f11, west);
|
||||||
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, north);
|
quad(writer, new Vector3f[]{hll, lll, lhl, hhl}, f9, f12, f8, f11, north);
|
||||||
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, east);
|
quad(writer, new Vector3f[]{hlh, hll, hhl, hhh}, f8, f12, f6, f11, east);
|
||||||
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, south);
|
quad(writer, new Vector3f[]{llh, hlh, hhh, lhh}, f6, f12, f5, f11, south);
|
||||||
} else {
|
} else {
|
||||||
quad(buffer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, down);
|
quad(writer, new Vector3f[]{hlh, llh, lll, hll}, f5, f10, f6, f11, down);
|
||||||
quad(buffer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, up);
|
quad(writer, new Vector3f[]{hhl, lhl, lhh, hhh}, f6, f11, f7, f10, up);
|
||||||
quad(buffer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, west);
|
quad(writer, new Vector3f[]{lll, llh, lhh, lhl}, f4, f11, f5, f12, west);
|
||||||
quad(buffer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, north);
|
quad(writer, new Vector3f[]{hll, lll, lhl, hhl}, f5, f11, f6, f12, north);
|
||||||
quad(buffer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, east);
|
quad(writer, new Vector3f[]{hlh, hll, hhl, hhh}, f6, f11, f8, f12, east);
|
||||||
quad(buffer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, south);
|
quad(writer, new Vector3f[]{llh, hlh, hhh, lhh}, f8, f11, f9, f12, south);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void quad(PosTexNormalWriterUnsafe buffer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) {
|
public void quad(VertexWriter writer, Vector3f[] vertices, float minU, float minV, float maxU, float maxV, Vector3f normal) {
|
||||||
buffer.putVertex(vertices[0].x(), vertices[0].y(), vertices[0].z(), normal.x(), normal.y(), normal.z(), maxU, minV);
|
writer.putVertex(vertices[0].x(), vertices[0].y(), vertices[0].z(), maxU, minV, normal.x(), normal.y(), normal.z());
|
||||||
buffer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), normal.x(), normal.y(), normal.z(), minU, minV);
|
writer.putVertex(vertices[1].x(), vertices[1].y(), vertices[1].z(), minU, minV, normal.x(), normal.y(), normal.z());
|
||||||
buffer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), normal.x(), normal.y(), normal.z(), minU, maxV);
|
writer.putVertex(vertices[2].x(), vertices[2].y(), vertices[2].z(), minU, maxV, normal.x(), normal.y(), normal.z());
|
||||||
buffer.putVertex(vertices[3].x(), vertices[3].y(), vertices[3].z(), normal.x(), normal.y(), normal.z(), maxU, maxV);
|
writer.putVertex(vertices[3].x(), vertices[3].y(), vertices[3].z(), maxU, maxV, normal.x(), normal.y(), normal.z());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getU(float u) {
|
public float getU(float u) {
|
||||||
|
@ -258,5 +255,4 @@ public class PartBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
package com.jozufozu.flywheel.core.layout;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeF;
|
||||||
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeI;
|
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeI;
|
||||||
|
|
||||||
public class CommonItems {
|
public class CommonItems {
|
||||||
|
|
||||||
public static final PrimitiveItem VEC4 = new PrimitiveItem(GlNumericType.FLOAT, 4);
|
public static final PrimitiveItem VEC4 = primitiveF(GlNumericType.FLOAT, 4);
|
||||||
public static final PrimitiveItem VEC3 = new PrimitiveItem(GlNumericType.FLOAT, 3);
|
public static final PrimitiveItem VEC3 = primitiveF(GlNumericType.FLOAT, 3);
|
||||||
public static final PrimitiveItem VEC2 = new PrimitiveItem(GlNumericType.FLOAT, 2);
|
public static final PrimitiveItem VEC2 = primitiveF(GlNumericType.FLOAT, 2);
|
||||||
public static final PrimitiveItem FLOAT = new PrimitiveItem(GlNumericType.FLOAT, 1);
|
public static final PrimitiveItem FLOAT = primitiveF(GlNumericType.FLOAT, 1);
|
||||||
|
|
||||||
public static final PrimitiveItem QUATERNION = new PrimitiveItem(GlNumericType.FLOAT, 4);
|
public static final PrimitiveItem QUATERNION = primitiveF(GlNumericType.FLOAT, 4);
|
||||||
public static final PrimitiveItem NORMAL = new PrimitiveItem(GlNumericType.BYTE, 3, true);
|
public static final PrimitiveItem NORMAL = primitiveF(GlNumericType.BYTE, 3, true);
|
||||||
public static final PrimitiveItem UV = new PrimitiveItem(GlNumericType.FLOAT, 2);
|
public static final PrimitiveItem UV = primitiveF(GlNumericType.FLOAT, 2);
|
||||||
|
|
||||||
public static final PrimitiveItem RGBA = new PrimitiveItem(GlNumericType.UBYTE, 4, true);
|
public static final PrimitiveItem RGBA = primitiveF(GlNumericType.UBYTE, 4, true);
|
||||||
public static final PrimitiveItem RGB = new PrimitiveItem(GlNumericType.UBYTE, 3, true);
|
public static final PrimitiveItem RGB = primitiveF(GlNumericType.UBYTE, 3, true);
|
||||||
public static final PrimitiveItem LIGHT = new PrimitiveItem(new VertexAttributeI(GlNumericType.UBYTE, 2));
|
public static final PrimitiveItem LIGHT = primitiveI(GlNumericType.UBYTE, 2);
|
||||||
public static final PrimitiveItem LIGHT_SHORT = new PrimitiveItem(new VertexAttributeI(GlNumericType.USHORT, 2));
|
public static final PrimitiveItem LIGHT_SHORT = primitiveI(GlNumericType.USHORT, 2);
|
||||||
|
|
||||||
public static final PrimitiveItem NORMALIZED_BYTE = new PrimitiveItem(GlNumericType.BYTE, 1, true);
|
public static final PrimitiveItem NORMALIZED_BYTE = primitiveF(GlNumericType.BYTE, 1, true);
|
||||||
|
|
||||||
public static final MatrixItem MAT3 = new MatrixItem(3, 3);
|
public static final MatrixItem MAT3 = new MatrixItem(3, 3);
|
||||||
public static final MatrixItem MAT4 = new MatrixItem(4, 4);
|
public static final MatrixItem MAT4 = new MatrixItem(4, 4);
|
||||||
|
|
||||||
|
private static PrimitiveItem primitiveF(GlNumericType type, int count, boolean normalized) {
|
||||||
|
return new PrimitiveItem(new VertexAttributeF(type, count, normalized));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PrimitiveItem primitiveF(GlNumericType type, int count) {
|
||||||
|
return primitiveF(type, count, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PrimitiveItem primitiveI(GlNumericType type, int count) {
|
||||||
|
return new PrimitiveItem(new VertexAttributeI(type, count));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,22 +2,12 @@ package com.jozufozu.flywheel.core.layout;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlNumericType;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.array.VertexAttribute;
|
import com.jozufozu.flywheel.backend.gl.array.VertexAttribute;
|
||||||
import com.jozufozu.flywheel.backend.gl.array.VertexAttributeF;
|
|
||||||
|
|
||||||
public class PrimitiveItem implements LayoutItem {
|
public class PrimitiveItem implements LayoutItem {
|
||||||
|
|
||||||
private final VertexAttribute attribute;
|
private final VertexAttribute attribute;
|
||||||
|
|
||||||
public PrimitiveItem(GlNumericType type, int count) {
|
|
||||||
this(type, count, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PrimitiveItem(GlNumericType type, int count, boolean normalized) {
|
|
||||||
this(new VertexAttributeF(type, count, normalized));
|
|
||||||
}
|
|
||||||
|
|
||||||
public PrimitiveItem(VertexAttribute attribute) {
|
public PrimitiveItem(VertexAttribute attribute) {
|
||||||
this.attribute = attribute;
|
this.attribute = attribute;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,71 +1,56 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexWriter;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
import com.jozufozu.flywheel.backend.instancing.instancing.ElementBuffer;
|
||||||
import com.jozufozu.flywheel.core.QuadConverter;
|
import com.jozufozu.flywheel.core.QuadConverter;
|
||||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mesh that can be rendered by flywheel.
|
* A holder for arbitrary vertex data that can be written to memory or a vertex list.
|
||||||
*
|
|
||||||
* <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>
|
|
||||||
*/
|
*/
|
||||||
public interface Mesh {
|
public interface Mesh {
|
||||||
|
|
||||||
/**
|
|
||||||
* A name uniquely identifying this model.
|
|
||||||
*/
|
|
||||||
String name();
|
|
||||||
|
|
||||||
VertexType getVertexType();
|
VertexType getVertexType();
|
||||||
|
|
||||||
VertexList getReader();
|
|
||||||
|
|
||||||
Vector4fc getBoundingSphere();
|
Vector4fc getBoundingSphere();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The number of vertices the model has.
|
* @return The number of vertices this mesh has.
|
||||||
*/
|
*/
|
||||||
default int getVertexCount() {
|
int getVertexCount();
|
||||||
return getReader().getVertexCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is there nothing to render?
|
* Is there nothing to render?
|
||||||
* @return true if there are no vertices.
|
* @return true if there are no vertices.
|
||||||
*/
|
*/
|
||||||
default boolean isEmpty() {
|
default boolean isEmpty() {
|
||||||
return getReader().isEmpty();
|
return getVertexCount() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size in bytes that this model's data takes up.
|
* The size in bytes that this mesh's data takes up.
|
||||||
*/
|
*/
|
||||||
default int size() {
|
default int size() {
|
||||||
return getVertexType().byteOffset(getVertexCount());
|
return getVertexType().byteOffset(getVertexCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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>
|
* <p>
|
||||||
* Very often models in minecraft are made up of sequential quads, which is a very predictable pattern.
|
* Very often models in minecraft are made up of sequential quads, which is a very predictable pattern.
|
||||||
|
@ -79,9 +64,10 @@ public interface Mesh {
|
||||||
.quads2Tris(getVertexCount() / 4);
|
.quads2Tris(getVertexCount() / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void writeInto(ByteBuffer buffer, long byteIndex) {
|
void close();
|
||||||
VertexWriter writer = getVertexType().createWriter(buffer);
|
|
||||||
writer.seek(byteIndex);
|
/**
|
||||||
writer.writeVertexList(getReader());
|
* A name uniquely identifying this mesh.
|
||||||
}
|
*/
|
||||||
|
String name();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ import com.jozufozu.flywheel.api.material.Material;
|
||||||
public interface Model {
|
public interface Model {
|
||||||
Map<Material, Mesh> getMeshes();
|
Map<Material, Mesh> getMeshes();
|
||||||
|
|
||||||
|
void delete();
|
||||||
|
|
||||||
default int getVertexCount() {
|
default int getVertexCount() {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
for (Mesh mesh : getMeshes().values()) {
|
for (Mesh mesh : getMeshes().values()) {
|
||||||
|
|
|
@ -5,16 +5,23 @@ import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.dreizak.miniball.highdim.Miniball;
|
import com.dreizak.miniball.highdim.Miniball;
|
||||||
import com.jozufozu.flywheel.Flywheel;
|
import com.jozufozu.flywheel.Flywheel;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
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.Materials;
|
||||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
import com.jozufozu.flywheel.core.vertex.Formats;
|
||||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
|
import com.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 com.mojang.datafixers.util.Pair;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -46,15 +53,27 @@ public class ModelUtil {
|
||||||
return dispatcher;
|
return dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VertexList createVertexList(BufferBuilder bufferBuilder) {
|
public static Pair<VertexType, MemoryBlock> convertBlockBuffer(Pair<DrawState, ByteBuffer> pair) {
|
||||||
Pair<BufferBuilder.DrawState, ByteBuffer> pair = bufferBuilder.popNextBuffer();
|
DrawState drawState = pair.getFirst();
|
||||||
BufferBuilder.DrawState drawState = pair.getFirst();
|
int vertexCount = drawState.vertexCount();
|
||||||
|
VertexFormat srcFormat = drawState.format();
|
||||||
|
VertexType dstVertexType = Formats.BLOCK;
|
||||||
|
|
||||||
if (drawState.format() != DefaultVertexFormat.BLOCK) {
|
ByteBuffer src = pair.getSecond();
|
||||||
throw new RuntimeException("Cannot use BufferBuilder with " + drawState.format());
|
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
|
@Nullable
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -41,8 +42,16 @@ public class Models {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onReload(ReloadRenderersEvent event) {
|
public static void onReload(ReloadRenderersEvent event) {
|
||||||
|
deleteAll(BLOCK_STATE.values());
|
||||||
|
deleteAll(PARTIAL.values());
|
||||||
|
deleteAll(PARTIAL_DIR.values());
|
||||||
|
|
||||||
BLOCK_STATE.clear();
|
BLOCK_STATE.clear();
|
||||||
PARTIAL.clear();
|
PARTIAL.clear();
|
||||||
PARTIAL_DIR.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());
|
return ImmutableMap.of(material, supplier.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
supplier.ifPresent(Mesh::close);
|
||||||
|
}
|
||||||
|
|
||||||
public int getVertexCount() {
|
public int getVertexCount() {
|
||||||
return supplier.map(Mesh::getVertexCount)
|
return supplier.map(Mesh::getVertexCount)
|
||||||
.orElse(0);
|
.orElse(0);
|
||||||
|
|
|
@ -1,27 +1,37 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
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.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.util.joml.Vector4f;
|
import com.jozufozu.flywheel.util.joml.Vector4f;
|
||||||
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
import com.jozufozu.flywheel.util.joml.Vector4fc;
|
||||||
|
|
||||||
public class SimpleMesh implements Mesh {
|
public class SimpleMesh implements Mesh {
|
||||||
private final VertexList reader;
|
|
||||||
private final VertexType vertexType;
|
private final VertexType vertexType;
|
||||||
|
private final int vertexCount;
|
||||||
|
private final MemoryBlock contents;
|
||||||
|
private final ReusableVertexList vertexList;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final Vector4f boundingSphere;
|
private final Vector4f boundingSphere;
|
||||||
|
|
||||||
public SimpleMesh(VertexList reader, VertexType vertexType, String name) {
|
public SimpleMesh(VertexType vertexType, MemoryBlock contents, String name) {
|
||||||
this.reader = reader;
|
|
||||||
this.vertexType = vertexType;
|
this.vertexType = vertexType;
|
||||||
|
this.contents = contents;
|
||||||
this.name = name;
|
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
|
vertexList = getVertexType().createVertexList();
|
||||||
public String name() {
|
vertexList.ptr(contents.ptr());
|
||||||
return name;
|
vertexList.setVertexCount(vertexCount);
|
||||||
|
|
||||||
|
boundingSphere = ModelUtil.computeBoundingSphere(vertexList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -30,8 +40,28 @@ public class SimpleMesh implements Mesh {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VertexList getReader() {
|
public int getVertexCount() {
|
||||||
return reader;
|
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
|
@Override
|
||||||
|
|
|
@ -19,6 +19,12 @@ public class TessellatedModel implements Model {
|
||||||
return meshes;
|
return meshes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
meshes.values()
|
||||||
|
.forEach(Mesh::close);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isShadeSeparated() {
|
public boolean isShadeSeparated() {
|
||||||
return shadeSeparated;
|
return shadeSeparated;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import java.util.function.BiFunction;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||||
import com.jozufozu.flywheel.core.model.SimpleMesh;
|
import com.jozufozu.flywheel.core.model.SimpleMesh;
|
||||||
|
@ -12,13 +14,13 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
|
||||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
|
||||||
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
||||||
import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData;
|
import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
|
@ -28,9 +30,10 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import net.minecraftforge.client.model.data.IModelData;
|
||||||
|
|
||||||
public class BakedModelBuilder {
|
public class BakedModelBuilder {
|
||||||
|
private static final int STARTING_CAPACITY = 64;
|
||||||
|
|
||||||
private final BakedModel bakedModel;
|
private final BakedModel bakedModel;
|
||||||
private boolean shadeSeparated = true;
|
private boolean shadeSeparated = true;
|
||||||
private VertexFormat vertexFormat;
|
|
||||||
private BlockAndTintGetter renderWorld;
|
private BlockAndTintGetter renderWorld;
|
||||||
private BlockState blockState;
|
private BlockState blockState;
|
||||||
private PoseStack poseStack;
|
private PoseStack poseStack;
|
||||||
|
@ -46,11 +49,6 @@ public class BakedModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BakedModelBuilder vertexFormat(VertexFormat vertexFormat) {
|
|
||||||
this.vertexFormat = vertexFormat;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BakedModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
public BakedModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
||||||
this.renderWorld = renderWorld;
|
this.renderWorld = renderWorld;
|
||||||
return this;
|
return this;
|
||||||
|
@ -80,9 +78,6 @@ public class BakedModelBuilder {
|
||||||
public TessellatedModel build() {
|
public TessellatedModel build() {
|
||||||
ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get();
|
ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get();
|
||||||
|
|
||||||
if (vertexFormat == null) {
|
|
||||||
vertexFormat = DefaultVertexFormat.BLOCK;
|
|
||||||
}
|
|
||||||
if (renderWorld == null) {
|
if (renderWorld == null) {
|
||||||
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
@ -103,29 +98,31 @@ public class BakedModelBuilder {
|
||||||
|
|
||||||
if (shadeSeparated) {
|
if (shadeSeparated) {
|
||||||
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
||||||
BufferBuilder buffer = new BufferBuilder(64);
|
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Material material = materialFunc.apply(renderType, shaded);
|
Material material = materialFunc.apply(renderType, shaded);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
|
Pair<VertexType, 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);
|
ModelBufferingUtil.bufferSingleShadeSeparated(ModelUtil.VANILLA_RENDERER.getModelRenderer(), renderWorld, bakedModel, blockState, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer);
|
||||||
} else {
|
} else {
|
||||||
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
||||||
BufferBuilder buffer = new BufferBuilder(64);
|
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Material material = materialFunc.apply(renderType, false);
|
Material material = materialFunc.apply(renderType, false);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "bakedModel=" + bakedModel.toString() + ",renderType=" + renderType.toString()));
|
Pair<VertexType, 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);
|
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.google.common.collect.ImmutableMap;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||||
import com.jozufozu.flywheel.core.model.SimpleMesh;
|
import com.jozufozu.flywheel.core.model.SimpleMesh;
|
||||||
|
@ -12,13 +14,13 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
|
||||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
|
||||||
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
||||||
import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData;
|
import com.jozufozu.flywheel.core.virtual.VirtualEmptyModelData;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
|
@ -26,9 +28,10 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import net.minecraftforge.client.model.data.IModelData;
|
||||||
|
|
||||||
public class BlockModelBuilder {
|
public class BlockModelBuilder {
|
||||||
|
private static final int STARTING_CAPACITY = 64;
|
||||||
|
|
||||||
private final BlockState state;
|
private final BlockState state;
|
||||||
private boolean shadeSeparated = true;
|
private boolean shadeSeparated = true;
|
||||||
private VertexFormat vertexFormat;
|
|
||||||
private BlockAndTintGetter renderWorld;
|
private BlockAndTintGetter renderWorld;
|
||||||
private PoseStack poseStack;
|
private PoseStack poseStack;
|
||||||
private IModelData modelData;
|
private IModelData modelData;
|
||||||
|
@ -43,11 +46,6 @@ public class BlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelBuilder vertexFormat(VertexFormat vertexFormat) {
|
|
||||||
this.vertexFormat = vertexFormat;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
public BlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
||||||
this.renderWorld = renderWorld;
|
this.renderWorld = renderWorld;
|
||||||
return this;
|
return this;
|
||||||
|
@ -72,9 +70,6 @@ public class BlockModelBuilder {
|
||||||
public TessellatedModel build() {
|
public TessellatedModel build() {
|
||||||
ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get();
|
ModelBufferingObjects objects = ModelBufferingObjects.THREAD_LOCAL.get();
|
||||||
|
|
||||||
if (vertexFormat == null) {
|
|
||||||
vertexFormat = DefaultVertexFormat.BLOCK;
|
|
||||||
}
|
|
||||||
if (renderWorld == null) {
|
if (renderWorld == null) {
|
||||||
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
@ -92,29 +87,31 @@ public class BlockModelBuilder {
|
||||||
|
|
||||||
if (shadeSeparated) {
|
if (shadeSeparated) {
|
||||||
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
||||||
BufferBuilder buffer = new BufferBuilder(64);
|
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Material material = materialFunc.apply(renderType, shaded);
|
Material material = materialFunc.apply(renderType, shaded);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "state=" + state.toString() + ",renderType=" + renderType.toString() + ",shaded=" + shaded));
|
Pair<VertexType, 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);
|
ModelBufferingUtil.bufferBlockShadeSeparated(ModelUtil.VANILLA_RENDERER, renderWorld, state, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelData, resultConsumer);
|
||||||
} else {
|
} else {
|
||||||
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
||||||
BufferBuilder buffer = new BufferBuilder(64);
|
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Material material = materialFunc.apply(renderType, false);
|
Material material = materialFunc.apply(renderType, false);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "state=" + state.toString() + ",renderType=" + renderType.toString()));
|
Pair<VertexType, 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);
|
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.google.common.collect.ImmutableMap;
|
||||||
import com.jozufozu.flywheel.api.material.Material;
|
import com.jozufozu.flywheel.api.material.Material;
|
||||||
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.MemoryBlock;
|
||||||
import com.jozufozu.flywheel.core.model.Mesh;
|
import com.jozufozu.flywheel.core.model.Mesh;
|
||||||
import com.jozufozu.flywheel.core.model.ModelUtil;
|
import com.jozufozu.flywheel.core.model.ModelUtil;
|
||||||
import com.jozufozu.flywheel.core.model.SimpleMesh;
|
import com.jozufozu.flywheel.core.model.SimpleMesh;
|
||||||
|
@ -15,12 +17,12 @@ import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.BufferFacto
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ResultConsumer;
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedBufferFactory;
|
||||||
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
|
import com.jozufozu.flywheel.core.model.buffering.ModelBufferingUtil.ShadeSeparatedResultConsumer;
|
||||||
import com.jozufozu.flywheel.core.vertex.Formats;
|
|
||||||
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
import com.jozufozu.flywheel.core.virtual.VirtualEmptyBlockGetter;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -29,6 +31,8 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import net.minecraftforge.client.model.data.IModelData;
|
||||||
|
|
||||||
public class MultiBlockModelBuilder {
|
public class MultiBlockModelBuilder {
|
||||||
|
private static final int STARTING_CAPACITY = 1024;
|
||||||
|
|
||||||
private final Collection<StructureTemplate.StructureBlockInfo> blocks;
|
private final Collection<StructureTemplate.StructureBlockInfo> blocks;
|
||||||
private boolean shadeSeparated = true;
|
private boolean shadeSeparated = true;
|
||||||
private VertexFormat vertexFormat;
|
private VertexFormat vertexFormat;
|
||||||
|
@ -46,11 +50,6 @@ public class MultiBlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiBlockModelBuilder vertexFormat(VertexFormat vertexFormat) {
|
|
||||||
this.vertexFormat = vertexFormat;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MultiBlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
public MultiBlockModelBuilder renderWorld(BlockAndTintGetter renderWorld) {
|
||||||
this.renderWorld = renderWorld;
|
this.renderWorld = renderWorld;
|
||||||
return this;
|
return this;
|
||||||
|
@ -95,29 +94,31 @@ public class MultiBlockModelBuilder {
|
||||||
|
|
||||||
if (shadeSeparated) {
|
if (shadeSeparated) {
|
||||||
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
ShadeSeparatedBufferFactory<BufferBuilder> bufferFactory = (renderType, shaded) -> {
|
||||||
BufferBuilder buffer = new BufferBuilder(1024);
|
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
ShadeSeparatedResultConsumer<BufferBuilder> resultConsumer = (renderType, shaded, buffer) -> {
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Material material = materialFunc.apply(renderType, shaded);
|
Material material = materialFunc.apply(renderType, shaded);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "renderType=" + renderType.toString() + ",shaded=" + shaded));
|
Pair<VertexType, 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);
|
ModelBufferingUtil.bufferMultiBlockShadeSeparated(blocks, ModelUtil.VANILLA_RENDERER, renderWorld, poseStack, bufferFactory, objects.shadeSeparatingBufferWrapper, objects.random, modelDataMap, resultConsumer);
|
||||||
} else {
|
} else {
|
||||||
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
BufferFactory<BufferBuilder> bufferFactory = (renderType) -> {
|
||||||
BufferBuilder buffer = new BufferBuilder(1024);
|
BufferBuilder buffer = new BufferBuilder(STARTING_CAPACITY);
|
||||||
buffer.begin(VertexFormat.Mode.QUADS, vertexFormat);
|
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
ResultConsumer<BufferBuilder> resultConsumer = (renderType, buffer) -> {
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Material material = materialFunc.apply(renderType, false);
|
Material material = materialFunc.apply(renderType, false);
|
||||||
if (material != null) {
|
if (material != null) {
|
||||||
meshMapBuilder.put(material, new SimpleMesh(ModelUtil.createVertexList(buffer), Formats.BLOCK, "renderType=" + renderType.toString()));
|
Pair<VertexType, 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);
|
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.api.struct.StructType;
|
||||||
import com.jozufozu.flywheel.core.ComponentRegistry;
|
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.OrientedPart;
|
||||||
import com.jozufozu.flywheel.core.structs.oriented.OrientedType;
|
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 class StructTypes {
|
||||||
public static final StructType<TransformedPart> TRANSFORMED = ComponentRegistry.register(new TransformedType());
|
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;
|
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.StructType;
|
||||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||||
import com.jozufozu.flywheel.core.Components;
|
import com.jozufozu.flywheel.core.Components;
|
||||||
|
@ -33,8 +30,8 @@ public class OrientedType implements StructType<OrientedPart> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StructWriter<OrientedPart> getWriter(ByteBuffer backing) {
|
public StructWriter<OrientedPart> getWriter() {
|
||||||
return new OrientedWriterUnsafe(this, backing);
|
return OrientedWriter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,7 +50,7 @@ public class OrientedType implements StructType<OrientedPart> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VertexTransformer<? extends OrientedPart> getVertexTransformer() {
|
public VertexTransformer<OrientedPart> getVertexTransformer() {
|
||||||
return (vertexList, struct, level) -> {
|
return (vertexList, struct, level) -> {
|
||||||
Vector4f pos = new Vector4f();
|
Vector4f pos = new Vector4f();
|
||||||
Vector3f normal = new Vector3f();
|
Vector3f normal = new Vector3f();
|
||||||
|
|
|
@ -1,21 +1,15 @@
|
||||||
package com.jozufozu.flywheel.core.structs.oriented;
|
package com.jozufozu.flywheel.core.structs.oriented;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.core.structs.ColoredLitWriter;
|
||||||
import com.jozufozu.flywheel.core.structs.ColoredLitWriterUnsafe;
|
|
||||||
|
|
||||||
public class OrientedWriterUnsafe extends ColoredLitWriterUnsafe<OrientedPart> {
|
public class OrientedWriter extends ColoredLitWriter<OrientedPart> {
|
||||||
public OrientedWriterUnsafe(StructType<OrientedPart> structType, ByteBuffer byteBuffer) {
|
public static final OrientedWriter INSTANCE = new OrientedWriter();
|
||||||
super(structType, byteBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeInternal(OrientedPart d) {
|
public void write(long ptr, OrientedPart d) {
|
||||||
long ptr = writePointer;
|
super.write(ptr, d);
|
||||||
super.writeInternal(d);
|
|
||||||
|
|
||||||
MemoryUtil.memPutFloat(ptr + 6, d.posX);
|
MemoryUtil.memPutFloat(ptr + 6, d.posX);
|
||||||
MemoryUtil.memPutFloat(ptr + 10, d.posY);
|
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.ColoredLitPart;
|
||||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
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;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
package com.jozufozu.flywheel.core.structs.model;
|
package com.jozufozu.flywheel.core.structs.transformed;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
|
import com.jozufozu.flywheel.api.struct.StorageBufferWriter;
|
||||||
import com.jozufozu.flywheel.api.struct.StructType;
|
import com.jozufozu.flywheel.api.struct.StructType;
|
||||||
|
@ -30,8 +28,8 @@ public class TransformedType implements StructType<TransformedPart> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StructWriter<TransformedPart> getWriter(ByteBuffer backing) {
|
public StructWriter<TransformedPart> getWriter() {
|
||||||
return new TransformedWriterUnsafe(this, backing);
|
return TransformedWriter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,7 +48,7 @@ public class TransformedType implements StructType<TransformedPart> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VertexTransformer<? extends TransformedPart> getVertexTransformer() {
|
public VertexTransformer<TransformedPart> getVertexTransformer() {
|
||||||
return (vertexList, struct, level) -> {
|
return (vertexList, struct, level) -> {
|
||||||
Vector4f pos = new Vector4f();
|
Vector4f pos = new Vector4f();
|
||||||
Vector3f normal = new Vector3f();
|
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
|
@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault
|
||||||
package com.jozufozu.flywheel.backend.struct;
|
package com.jozufozu.flywheel.core.structs.transformed;
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
|
@ -9,22 +9,18 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
|
||||||
public class FogProvider extends UniformProvider {
|
public class FogProvider extends UniformProvider {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getActualByteSize() {
|
public int getActualByteSize() {
|
||||||
return 16 + 8 + 4;
|
return 16 + 8 + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
if (buffer == null) {
|
if (ptr == MemoryUtil.NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var color = RenderSystem.getShaderFogColor();
|
var color = RenderSystem.getShaderFogColor();
|
||||||
|
|
||||||
long ptr = MemoryUtil.memAddress(buffer);
|
|
||||||
|
|
||||||
MemoryUtil.memPutFloat(ptr, color[0]);
|
MemoryUtil.memPutFloat(ptr, color[0]);
|
||||||
MemoryUtil.memPutFloat(ptr + 4, color[1]);
|
MemoryUtil.memPutFloat(ptr + 4, color[1]);
|
||||||
MemoryUtil.memPutFloat(ptr + 8, color[2]);
|
MemoryUtil.memPutFloat(ptr + 8, color[2]);
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class FrustumProvider extends UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(RenderContext context) {
|
public void update(RenderContext context) {
|
||||||
if (buffer == null) {
|
if (ptr == MemoryUtil.NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,6 @@ public class FrustumProvider extends UniformProvider {
|
||||||
|
|
||||||
var shiftedCuller = RenderContext.createCuller(context.viewProjection(), -camX, -camY, -camZ);
|
var shiftedCuller = RenderContext.createCuller(context.viewProjection(), -camX, -camY, -camZ);
|
||||||
|
|
||||||
long ptr = MemoryUtil.memAddress(buffer);
|
|
||||||
|
|
||||||
shiftedCuller.getJozuPackedPlanes(ptr);
|
shiftedCuller.getJozuPackedPlanes(ptr);
|
||||||
|
|
||||||
notifier.signalChanged();
|
notifier.signalChanged();
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
package com.jozufozu.flywheel.core.uniform;
|
package com.jozufozu.flywheel.core.uniform;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.jozufozu.flywheel.api.uniform.UniformProvider;
|
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.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.core.ComponentRegistry;
|
||||||
import com.jozufozu.flywheel.util.RenderMath;
|
import com.jozufozu.flywheel.util.RenderMath;
|
||||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
|
||||||
|
|
||||||
public class UniformBuffer {
|
public class UniformBuffer {
|
||||||
|
|
||||||
|
@ -33,13 +31,13 @@ public class UniformBuffer {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MappedGlBuffer buffer;
|
private final GlBuffer buffer;
|
||||||
private final ByteBuffer data;
|
private final MemoryBlock data;
|
||||||
|
|
||||||
private final BitSet changedBytes;
|
private final BitSet changedBytes;
|
||||||
|
|
||||||
private UniformBuffer() {
|
private UniformBuffer() {
|
||||||
buffer = new MappedGlBuffer(GlBufferType.UNIFORM_BUFFER);
|
buffer = new GlBuffer(GlBufferType.UNIFORM_BUFFER);
|
||||||
|
|
||||||
Collection<UniformProvider> providers = ComponentRegistry.getAllUniformProviders();
|
Collection<UniformProvider> providers = ComponentRegistry.getAllUniformProviders();
|
||||||
|
|
||||||
|
@ -57,7 +55,7 @@ public class UniformBuffer {
|
||||||
|
|
||||||
allocatedProviders = builder.build();
|
allocatedProviders = builder.build();
|
||||||
|
|
||||||
data = MemoryTracker.create(totalBytes);
|
data = MemoryBlock.mallocTracked(totalBytes);
|
||||||
changedBytes = new BitSet(totalBytes);
|
changedBytes = new BitSet(totalBytes);
|
||||||
|
|
||||||
for (Allocated p : allocatedProviders) {
|
for (Allocated p : allocatedProviders) {
|
||||||
|
@ -112,8 +110,8 @@ public class UniformBuffer {
|
||||||
changedBytes.set(offset, offset + size);
|
changedBytes.set(offset, offset + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePtr(ByteBuffer bufferBase) {
|
private void updatePtr(MemoryBlock bufferBase) {
|
||||||
provider.updatePtr(MemoryUtil.memSlice(bufferBase, offset, size), this);
|
provider.updatePtr(bufferBase.ptr() + offset, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniformProvider provider() {
|
public UniformProvider provider() {
|
||||||
|
|
|
@ -31,7 +31,7 @@ public class ViewProvider extends UniformProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(RenderContext context) {
|
public void update(RenderContext context) {
|
||||||
if (buffer == null) {
|
if (ptr == MemoryUtil.NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +52,6 @@ public class ViewProvider extends UniformProvider {
|
||||||
var vp = context.viewProjection().copy();
|
var vp = context.viewProjection().copy();
|
||||||
vp.multiplyWithTranslation(-camX, -camY, -camZ);
|
vp.multiplyWithTranslation(-camX, -camY, -camZ);
|
||||||
|
|
||||||
long ptr = MemoryUtil.memAddress(buffer);
|
|
||||||
|
|
||||||
MatrixExtension.writeUnsafe(vp, ptr);
|
MatrixExtension.writeUnsafe(vp, ptr);
|
||||||
MemoryUtil.memPutFloat(ptr + 64, camX);
|
MemoryUtil.memPutFloat(ptr + 64, camX);
|
||||||
MemoryUtil.memPutFloat(ptr + 68, camY);
|
MemoryUtil.memPutFloat(ptr + 68, camY);
|
||||||
|
|
|
@ -1,49 +1,28 @@
|
||||||
package com.jozufozu.flywheel.core.vertex;
|
package com.jozufozu.flywheel.core.vertex;
|
||||||
|
|
||||||
import java.nio.Buffer;
|
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
public abstract class AbstractVertexList implements ReusableVertexList {
|
||||||
|
protected long ptr;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexList;
|
protected int vertexCount;
|
||||||
import com.mojang.blaze3d.platform.MemoryTracker;
|
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
||||||
|
|
||||||
public abstract class AbstractVertexList implements VertexList, AutoCloseable {
|
|
||||||
|
|
||||||
protected final ByteBuffer contents;
|
|
||||||
protected final long base;
|
|
||||||
protected final int vertexCount;
|
|
||||||
|
|
||||||
protected AbstractVertexList(ByteBuffer copyFrom, int vertexCount) {
|
|
||||||
this.contents = MemoryTracker.create(copyFrom.capacity());
|
|
||||||
this.vertexCount = vertexCount;
|
|
||||||
this.base = MemoryUtil.memAddress(this.contents);
|
|
||||||
init(copyFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbstractVertexList(BufferBuilder builder) {
|
|
||||||
var pair = builder.popNextBuffer();
|
|
||||||
ByteBuffer copyFrom = pair.getSecond();
|
|
||||||
this.contents = MemoryTracker.create(copyFrom.capacity());
|
|
||||||
this.vertexCount = pair.getFirst().vertexCount();
|
|
||||||
this.base = MemoryUtil.memAddress(this.contents);
|
|
||||||
init(copyFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(ByteBuffer copyFrom) {
|
|
||||||
this.contents.order(copyFrom.order());
|
|
||||||
this.contents.put(copyFrom);
|
|
||||||
((Buffer) this.contents).flip();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
MemoryUtil.memFree(contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getVertexCount() {
|
public int getVertexCount() {
|
||||||
return vertexCount;
|
return vertexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVertexCount(int vertexCount) {
|
||||||
|
this.vertexCount = vertexCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long ptr() {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ptr(long ptr) {
|
||||||
|
this.ptr = ptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.jozufozu.flywheel.core.vertex;
|
package com.jozufozu.flywheel.core.vertex;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.core.Components;
|
import com.jozufozu.flywheel.core.Components;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
|
@ -9,7 +7,6 @@ import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
|
||||||
public class BlockVertex implements VertexType {
|
public class BlockVertex implements VertexType {
|
||||||
|
|
||||||
public static final BufferLayout FORMAT = BufferLayout.builder()
|
public static final BufferLayout FORMAT = BufferLayout.builder()
|
||||||
.addItems(CommonItems.VEC3,
|
.addItems(CommonItems.VEC3,
|
||||||
CommonItems.RGBA,
|
CommonItems.RGBA,
|
||||||
|
@ -24,18 +21,13 @@ public class BlockVertex implements VertexType {
|
||||||
return FORMAT;
|
return FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockWriterUnsafe createWriter(ByteBuffer buffer) {
|
|
||||||
return new BlockWriterUnsafe(this, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BlockVertexListUnsafe createReader(ByteBuffer buffer, int vertexCount) {
|
|
||||||
return new BlockVertexListUnsafe(buffer, vertexCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileResolution getLayoutShader() {
|
public FileResolution getLayoutShader() {
|
||||||
return Components.Files.BLOCK_LAYOUT;
|
return Components.Files.BLOCK_LAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockVertexList createVertexList() {
|
||||||
|
return new BlockVertexList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +1,61 @@
|
||||||
package com.jozufozu.flywheel.core.vertex;
|
package com.jozufozu.flywheel.core.vertex;
|
||||||
|
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.util.RenderMath;
|
import com.jozufozu.flywheel.util.RenderMath;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
|
||||||
public class BlockVertexList extends AbstractVertexList {
|
public class BlockVertexList extends AbstractVertexList {
|
||||||
|
protected static final int STRIDE = 32;
|
||||||
|
|
||||||
private final int stride;
|
protected long idxPtr(int index) {
|
||||||
|
return ptr + index * STRIDE;
|
||||||
public BlockVertexList(BufferBuilder builder) {
|
|
||||||
super(builder);
|
|
||||||
this.stride = builder.getVertexFormat()
|
|
||||||
.getVertexSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return vertexCount == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int vertIdx(int vertexIndex) {
|
|
||||||
return vertexIndex * stride;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float x(int index) {
|
public float x(int index) {
|
||||||
return contents.getFloat(vertIdx(index));
|
return MemoryUtil.memGetFloat(idxPtr(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float y(int index) {
|
public float y(int index) {
|
||||||
return contents.getFloat(vertIdx(index) + 4);
|
return MemoryUtil.memGetFloat(idxPtr(index) + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float z(int index) {
|
public float z(int index) {
|
||||||
return contents.getFloat(vertIdx(index) + 8);
|
return MemoryUtil.memGetFloat(idxPtr(index) + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte r(int index) {
|
public byte r(int index) {
|
||||||
return contents.get(vertIdx(index) + 12);
|
return MemoryUtil.memGetByte(idxPtr(index) + 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte g(int index) {
|
public byte g(int index) {
|
||||||
return contents.get(vertIdx(index) + 13);
|
return MemoryUtil.memGetByte(idxPtr(index) + 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte b(int index) {
|
public byte b(int index) {
|
||||||
return contents.get(vertIdx(index) + 14);
|
return MemoryUtil.memGetByte(idxPtr(index) + 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte a(int index) {
|
public byte a(int index) {
|
||||||
return contents.get(vertIdx(index) + 15);
|
return MemoryUtil.memGetByte(idxPtr(index) + 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float u(int index) {
|
public float u(int index) {
|
||||||
return contents.getFloat(vertIdx(index) + 16);
|
return MemoryUtil.memGetFloat(idxPtr(index) + 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float v(int index) {
|
public float v(int index) {
|
||||||
return contents.getFloat(vertIdx(index) + 20);
|
return MemoryUtil.memGetFloat(idxPtr(index) + 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,22 +65,95 @@ public class BlockVertexList extends AbstractVertexList {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int light(int index) {
|
public int light(int index) {
|
||||||
return contents.getInt(vertIdx(index) + 24);
|
return MemoryUtil.memGetInt(idxPtr(index) + 24) << 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float normalX(int index) {
|
public float normalX(int index) {
|
||||||
return RenderMath.f(contents.get(vertIdx(index) + 28));
|
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 28));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float normalY(int index) {
|
public float normalY(int index) {
|
||||||
return RenderMath.f(contents.get(vertIdx(index) + 29));
|
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 29));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float normalZ(int index) {
|
public float normalZ(int index) {
|
||||||
return RenderMath.f(contents.get(vertIdx(index) + 30));
|
return RenderMath.f(MemoryUtil.memGetByte(idxPtr(index) + 30));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void x(int index, float x) {
|
||||||
|
MemoryUtil.memPutFloat(idxPtr(index), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void y(int index, float y) {
|
||||||
|
MemoryUtil.memPutFloat(idxPtr(index) + 4, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void z(int index, float z) {
|
||||||
|
MemoryUtil.memPutFloat(idxPtr(index) + 8, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void r(int index, byte r) {
|
||||||
|
MemoryUtil.memPutByte(idxPtr(index) + 12, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void g(int index, byte g) {
|
||||||
|
MemoryUtil.memPutByte(idxPtr(index) + 13, g);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void b(int index, byte b) {
|
||||||
|
MemoryUtil.memPutByte(idxPtr(index) + 14, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void a(int index, byte a) {
|
||||||
|
MemoryUtil.memPutByte(idxPtr(index) + 15, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void u(int index, float u) {
|
||||||
|
MemoryUtil.memPutFloat(idxPtr(index) + 16, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void v(int index, float v) {
|
||||||
|
MemoryUtil.memPutFloat(idxPtr(index) + 20, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void overlay(int index, int overlay) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void light(int index, int light) {
|
||||||
|
MemoryUtil.memPutInt(idxPtr(index) + 24, light >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void normalX(int index, float normalX) {
|
||||||
|
MemoryUtil.memPutByte(idxPtr(index) + 28, RenderMath.nb(normalX));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void normalY(int index, float normalY) {
|
||||||
|
MemoryUtil.memPutByte(idxPtr(index) + 29, RenderMath.nb(normalY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void normalZ(int index, float normalZ) {
|
||||||
|
MemoryUtil.memPutByte(idxPtr(index) + 30, RenderMath.nb(normalZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shiftPtr(int vertices) {
|
||||||
|
ptr += vertices * STRIDE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.VertexFormat;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
||||||
|
|
||||||
public class VertexFormatInfo {
|
public class InferredVertexFormatInfo {
|
||||||
public final VertexFormat format;
|
public final VertexFormat format;
|
||||||
public final int stride;
|
public final int stride;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ public class VertexFormatInfo {
|
||||||
public final int lightOffset;
|
public final int lightOffset;
|
||||||
public final int normalOffset;
|
public final int normalOffset;
|
||||||
|
|
||||||
public VertexFormatInfo(VertexFormat format) {
|
public InferredVertexFormatInfo(VertexFormat format) {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
stride = format.getVertexSize();
|
stride = format.getVertexSize();
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ public class VertexFormatInfo {
|
||||||
this.normalOffset = normalOffset;
|
this.normalOffset = normalOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected VertexFormatInfo(VertexFormatInfo formatInfo) {
|
protected InferredVertexFormatInfo(InferredVertexFormatInfo formatInfo) {
|
||||||
format = formatInfo.format;
|
format = formatInfo.format;
|
||||||
stride = formatInfo.stride;
|
stride = formatInfo.stride;
|
||||||
positionOffset = formatInfo.positionOffset;
|
positionOffset = formatInfo.positionOffset;
|
|
@ -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;
|
package com.jozufozu.flywheel.core.vertex;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.core.Components;
|
import com.jozufozu.flywheel.core.Components;
|
||||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||||
|
@ -9,7 +7,6 @@ import com.jozufozu.flywheel.core.layout.CommonItems;
|
||||||
import com.jozufozu.flywheel.core.source.FileResolution;
|
import com.jozufozu.flywheel.core.source.FileResolution;
|
||||||
|
|
||||||
public class PosTexNormalVertex implements VertexType {
|
public class PosTexNormalVertex implements VertexType {
|
||||||
|
|
||||||
public static final BufferLayout FORMAT = BufferLayout.builder()
|
public static final BufferLayout FORMAT = BufferLayout.builder()
|
||||||
.addItems(CommonItems.VEC3, CommonItems.UV, CommonItems.NORMAL)
|
.addItems(CommonItems.VEC3, CommonItems.UV, CommonItems.NORMAL)
|
||||||
.build();
|
.build();
|
||||||
|
@ -19,18 +16,13 @@ public class PosTexNormalVertex implements VertexType {
|
||||||
return FORMAT;
|
return FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PosTexNormalWriterUnsafe createWriter(ByteBuffer buffer) {
|
|
||||||
return new PosTexNormalWriterUnsafe(this, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PosTexNormalVertexListUnsafe createReader(ByteBuffer buffer, int vertexCount) {
|
|
||||||
return new PosTexNormalVertexListUnsafe(buffer, vertexCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileResolution getLayoutShader() {
|
public FileResolution getLayoutShader() {
|
||||||
return Components.Files.POS_TEX_NORMAL_LAYOUT;
|
return Components.Files.POS_TEX_NORMAL_LAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PosTexNormalVertexList createVertexList() {
|
||||||
|
return new PosTexNormalVertexList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.Flywheel;
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.FlywheelMemory;
|
|
||||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||||
|
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
||||||
import com.jozufozu.flywheel.light.LightUpdater;
|
import com.jozufozu.flywheel.light.LightUpdater;
|
||||||
|
import com.jozufozu.flywheel.util.StringUtil;
|
||||||
import com.jozufozu.flywheel.util.WorldAttached;
|
import com.jozufozu.flywheel.util.WorldAttached;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
@ -24,10 +25,7 @@ public class ForgeEvents {
|
||||||
|
|
||||||
InstancedRenderDispatcher.getDebugString(debug);
|
InstancedRenderDispatcher.getDebugString(debug);
|
||||||
|
|
||||||
// TODO: compress into one line
|
debug.add("Memory Usage: CPU: " + StringUtil.formatBytes(FlwMemoryTracker.getCPUMemory()) + ", GPU: " + StringUtil.formatBytes(FlwMemoryTracker.getGPUMemory()));
|
||||||
debug.add("Memory used:");
|
|
||||||
debug.add("GPU: " + FlywheelMemory.getGPUMemory());
|
|
||||||
debug.add("CPU: " + FlywheelMemory.getCPUMemory());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class GPULightVolume extends LightVolume {
|
||||||
|
|
||||||
public void bind() {
|
public void bind() {
|
||||||
// just in case something goes wrong, or we accidentally call this before this volume is properly disposed of.
|
// 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();
|
textureUnit.makeActive();
|
||||||
glTexture.bind();
|
glTexture.bind();
|
||||||
|
@ -93,7 +93,7 @@ public class GPULightVolume extends LightVolume {
|
||||||
int sizeY = box.sizeY();
|
int sizeY = box.sizeY();
|
||||||
int sizeZ = box.sizeZ();
|
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
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4 is the default
|
||||||
bufferDirty = false;
|
bufferDirty = false;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package com.jozufozu.flywheel.light;
|
package com.jozufozu.flywheel.light;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import org.lwjgl.system.MemoryUtil;
|
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.GridAlignedBB;
|
||||||
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
import com.jozufozu.flywheel.util.box.ImmutableBox;
|
||||||
|
|
||||||
|
@ -15,13 +14,53 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
|
|
||||||
protected final BlockAndTintGetter level;
|
protected final BlockAndTintGetter level;
|
||||||
protected final GridAlignedBB box = new GridAlignedBB();
|
protected final GridAlignedBB box = new GridAlignedBB();
|
||||||
protected ByteBuffer lightData;
|
protected MemoryBlock lightData;
|
||||||
|
|
||||||
public LightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) {
|
public LightVolume(BlockAndTintGetter level, ImmutableBox sampleVolume) {
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.setBox(sampleVolume);
|
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) {
|
protected void setBox(ImmutableBox box) {
|
||||||
|
@ -30,47 +69,143 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
|
|
||||||
public short getPackedLight(int x, int y, int z) {
|
public short getPackedLight(int x, int y, int z) {
|
||||||
if (box.contains(x, y, z)) {
|
if (box.contains(x, y, z)) {
|
||||||
return lightData.getShort(worldPosToBufferIndex(x, y, z));
|
return MemoryUtil.memGetShort(worldPosToPtr(x, y, z));
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
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) {
|
public void move(ImmutableBox newSampleVolume) {
|
||||||
if (lightData == null) return;
|
if (lightData == null) return;
|
||||||
|
|
||||||
setBox(newSampleVolume);
|
setBox(newSampleVolume);
|
||||||
int neededCapacity = box.volume() * 2;
|
int neededCapacity = box.volume() * 2;
|
||||||
if (neededCapacity > lightData.capacity()) {
|
if (neededCapacity > lightData.size()) {
|
||||||
lightData = MemoryUtil.memRealloc(lightData, neededCapacity);
|
lightData = lightData.realloc(neededCapacity);
|
||||||
}
|
}
|
||||||
initialize();
|
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
|
@Override
|
||||||
public void onLightUpdate(LightLayer type, ImmutableBox changedVolume) {
|
public void onLightUpdate(LightLayer type, ImmutableBox changedVolume) {
|
||||||
if (lightData == null) return;
|
if (lightData == null) return;
|
||||||
|
@ -96,126 +231,4 @@ public class LightVolume implements ImmutableBox, LightListener {
|
||||||
markDirty();
|
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 org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.memory.FlwMemoryTracker;
|
||||||
|
|
||||||
public class StringUtil {
|
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) {
|
public static String formatTime(long ns) {
|
||||||
if (ns < 1000) {
|
if (ns < 1000) {
|
||||||
return ns + " ns";
|
return ns + " ns";
|
||||||
} else if (ns < 1000000) {
|
} else if (ns < 1000000) {
|
||||||
return timeFormat.format(ns / 1000.) + " μs";
|
return THREE_DECIMAL_PLACES.format(ns / 1000f) + " μs";
|
||||||
} else if (ns < 1000000000) {
|
} else if (ns < 1000000000) {
|
||||||
return timeFormat.format(ns / 1000000.) + " ms";
|
return THREE_DECIMAL_PLACES.format(ns / 1000000f) + " ms";
|
||||||
} else {
|
} 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();
|
((Buffer) bytebuffer).rewind();
|
||||||
return MemoryUtil.memASCII(bytebuffer, i);
|
return MemoryUtil.memASCII(bytebuffer, i);
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
|
//
|
||||||
} finally {
|
} finally {
|
||||||
if (bytebuffer != null) {
|
if (bytebuffer != null) {
|
||||||
MemoryUtil.memFree(bytebuffer);
|
FlwMemoryTracker.freeBuffer(bytebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -75,12 +89,12 @@ public class StringUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ByteBuffer readInputStream(InputStream is) throws IOException {
|
private static ByteBuffer readInputStream(InputStream is) throws IOException {
|
||||||
ByteBuffer bytebuffer = MemoryUtil.memAlloc(8192);
|
ByteBuffer bytebuffer = FlwMemoryTracker.mallocBuffer(8192);
|
||||||
ReadableByteChannel readablebytechannel = Channels.newChannel(is);
|
ReadableByteChannel readablebytechannel = Channels.newChannel(is);
|
||||||
|
|
||||||
while (readablebytechannel.read(bytebuffer) != -1) {
|
while (readablebytechannel.read(bytebuffer) != -1) {
|
||||||
if (bytebuffer.remaining() == 0) {
|
if (bytebuffer.remaining() == 0) {
|
||||||
bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2);
|
bytebuffer = FlwMemoryTracker.reallocBuffer(bytebuffer, bytebuffer.capacity() * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bytebuffer;
|
return bytebuffer;
|
||||||
|
@ -88,7 +102,7 @@ public class StringUtil {
|
||||||
|
|
||||||
private static ByteBuffer readFileInputStream(FileInputStream fileinputstream) throws IOException {
|
private static ByteBuffer readFileInputStream(FileInputStream fileinputstream) throws IOException {
|
||||||
FileChannel filechannel = fileinputstream.getChannel();
|
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) {
|
while (filechannel.read(bytebuffer) != -1) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,16 @@ public class WorldAttached<T> {
|
||||||
i.remove();
|
i.remove();
|
||||||
} else {
|
} else {
|
||||||
// Prevent leaks
|
// 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.hardcoded.ModelPart;
|
||||||
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
||||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
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.oriented.OrientedPart;
|
||||||
|
import com.jozufozu.flywheel.core.structs.transformed.TransformedPart;
|
||||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||||
import com.mojang.math.Quaternion;
|
import com.mojang.math.Quaternion;
|
||||||
import com.mojang.math.Vector3f;
|
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.Models;
|
||||||
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
||||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
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.AnimationTickHolder;
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
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.hardcoded.ModelPart;
|
||||||
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
import com.jozufozu.flywheel.core.model.SimpleLazyModel;
|
||||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
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.AnimationTickHolder;
|
||||||
import com.jozufozu.flywheel.util.transform.TransformStack;
|
import com.jozufozu.flywheel.util.transform.TransformStack;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
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.backend.instancing.effect.Effect;
|
||||||
import com.jozufozu.flywheel.core.model.Models;
|
import com.jozufozu.flywheel.core.model.Models;
|
||||||
import com.jozufozu.flywheel.core.structs.StructTypes;
|
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.event.ReloadRenderersEvent;
|
||||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||||
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
import com.jozufozu.flywheel.util.box.GridAlignedBB;
|
||||||
|
|
Loading…
Reference in a new issue