diff --git a/src/main/java/com/jozufozu/flywheel/api/instance/BlockEntityInstance.java b/src/main/java/com/jozufozu/flywheel/api/instance/BlockEntityInstance.java index 0ea0acd7e..0fb3a750e 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instance/BlockEntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/api/instance/BlockEntityInstance.java @@ -2,10 +2,10 @@ package com.jozufozu.flywheel.api.instance; import java.util.List; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import net.minecraft.world.level.block.entity.BlockEntity; public interface BlockEntityInstance extends Instance { - List getCrumblingParts(); + List getCrumblingParts(); } diff --git a/src/main/java/com/jozufozu/flywheel/api/instance/DynamicInstance.java b/src/main/java/com/jozufozu/flywheel/api/instance/DynamicInstance.java index 36c8088b8..4f9835cb3 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instance/DynamicInstance.java +++ b/src/main/java/com/jozufozu/flywheel/api/instance/DynamicInstance.java @@ -2,7 +2,7 @@ package com.jozufozu.flywheel.api.instance; import org.joml.FrustumIntersection; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; /** @@ -20,7 +20,7 @@ public interface DynamicInstance extends Instance { *
* DISPATCHED IN PARALLEL, don't attempt to mutate anything outside this instance. *
- * {@link Instancer}/{@link InstancedPart} creation/acquisition is safe here. + * {@link Instancer}/{@link InstancePart} creation/acquisition is safe here. */ void beginFrame(); diff --git a/src/main/java/com/jozufozu/flywheel/api/instance/TickableInstance.java b/src/main/java/com/jozufozu/flywheel/api/instance/TickableInstance.java index 3e8a24ba8..e0c8fd77d 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instance/TickableInstance.java +++ b/src/main/java/com/jozufozu/flywheel/api/instance/TickableInstance.java @@ -1,6 +1,6 @@ package com.jozufozu.flywheel.api.instance; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; /** @@ -25,7 +25,7 @@ public interface TickableInstance extends Instance { * Called every tick, and after initialization.

* DISPATCHED IN PARALLEL, don't attempt to mutate anything outside of this instance * without proper synchronization.

- * {@link Instancer}/{@link InstancedPart} creation/acquisition is safe here. + * {@link Instancer}/{@link InstancePart} creation/acquisition is safe here. */ void tick(); diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/Handle.java b/src/main/java/com/jozufozu/flywheel/api/instancer/Handle.java new file mode 100644 index 000000000..208c73673 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/api/instancer/Handle.java @@ -0,0 +1,8 @@ +package com.jozufozu.flywheel.api.instancer; + +public interface Handle { + + void setChanged(); + + void setDeleted(); +} diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancePart.java b/src/main/java/com/jozufozu/flywheel/api/instancer/InstancePart.java new file mode 100644 index 000000000..ba6144f49 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/api/instancer/InstancePart.java @@ -0,0 +1,10 @@ +package com.jozufozu.flywheel.api.instancer; + +import com.jozufozu.flywheel.api.struct.StructType; + +public interface InstancePart { + StructType type(); + + @Deprecated + InstancePart copy(Handle handle); +} diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancedPart.java b/src/main/java/com/jozufozu/flywheel/api/instancer/InstancedPart.java deleted file mode 100644 index e06799ba1..000000000 --- a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancedPart.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.jozufozu.flywheel.api.instancer; - -import com.jozufozu.flywheel.api.struct.StructType; - -public abstract class InstancedPart { - - public final StructType type; - private Instancer owner; - - private boolean dirty; - private boolean removed; - - protected InstancedPart(StructType type) { - this.type = type; - } - - public final void markDirty() { - dirty = true; - owner.notifyDirty(); - } - - public final void delete() { - removed = true; - owner.notifyRemoval(); - } - - public final boolean checkDirtyAndClear() { - boolean wasDirty = dirty; - dirty = false; - return wasDirty; - } - - public final boolean isRemoved() { - return removed; - } - - public Instancer getOwner() { - return owner; - } - - public void setOwner(Instancer owner) { - this.owner = owner; - } - - public abstract InstancedPart copy(); -} diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/Instancer.java b/src/main/java/com/jozufozu/flywheel/api/instancer/Instancer.java index 58ef8a8f7..9be9e5633 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instancer/Instancer.java +++ b/src/main/java/com/jozufozu/flywheel/api/instancer/Instancer.java @@ -16,45 +16,20 @@ package com.jozufozu.flywheel.api.instancer; * because it means the properties of your model don't have to be re-evaluated every frame. *

* - * @param the data that represents a copy of the instanced model. + * @param

the data that represents a copy of the instanced model. */ -public interface Instancer { +public interface Instancer

{ /** * @return a handle to a new copy of this model. */ - D createInstance(); - - /** - * Copy a data from another Instancer to this. - * This has the effect of swapping out one model for another. - * @param inOther the data associated with a different model. - */ - void stealInstance(D inOther); - - /** - * Notify the Instancer that some of its data needs updating. - * - *

- * This might be ignored, depending on the implementation. For the GPUInstancer, this triggers a scan of all - * instances. - *

- */ - void notifyDirty(); - - /** - * Notify the Instances that some of its data should be removed. - * - *

- * By the time the next frame is drawn, the instanceData passed will no longer be considered for rendering. - *

- */ - void notifyRemoval(); + P createInstance(); /** * Populate arr with new instances of this model. + * * @param arr An array to fill. */ - default void createInstances(D[] arr) { + default void createInstances(P[] arr) { for (int i = 0; i < arr.length; i++) { arr[i] = createInstance(); } diff --git a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancerProvider.java b/src/main/java/com/jozufozu/flywheel/api/instancer/InstancerProvider.java index 74338c8fb..21ea65f18 100644 --- a/src/main/java/com/jozufozu/flywheel/api/instancer/InstancerProvider.java +++ b/src/main/java/com/jozufozu/flywheel/api/instancer/InstancerProvider.java @@ -10,5 +10,5 @@ public interface InstancerProvider { * * @return An instancer for the given struct type, model, and render stage. */ - Instancer instancer(StructType type, Model model, RenderStage stage); +

Instancer

instancer(StructType

type, Model model, RenderStage stage); } diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java index f867d4df2..c0a0bf002 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructType.java @@ -1,6 +1,7 @@ package com.jozufozu.flywheel.api.struct; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.Handle; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.registry.Registry; import com.jozufozu.flywheel.api.vertex.MutableVertexList; @@ -11,29 +12,31 @@ import net.minecraft.resources.ResourceLocation; /** * A StructType contains metadata for a specific instance struct that Flywheel can interface with. - * @param The java representation of the instance struct. + * + * @param

The java representation of the instance struct. */ -public interface StructType { +public interface StructType

{ static Registry> REGISTRY = RegistryImpl.create(); /** + * @param handle A handle that allows you to mark the instance as dirty or deleted. * @return A new, zeroed instance of S. */ - S create(); + P create(Handle handle); /** * @return The layout of S when buffered. */ BufferLayout getLayout(); - StructWriter getWriter(); + StructWriter

getWriter(); ResourceLocation instanceShader(); - VertexTransformer getVertexTransformer(); + VertexTransformer

getVertexTransformer(); - interface VertexTransformer { - void transform(MutableVertexList vertexList, S struct, ClientLevel level); + interface VertexTransformer

{ + void transform(MutableVertexList vertexList, P struct, ClientLevel level); } } diff --git a/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java b/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java index 21caf4adc..55468838f 100644 --- a/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java +++ b/src/main/java/com/jozufozu/flywheel/api/struct/StructWriter.java @@ -1,14 +1,14 @@ package com.jozufozu.flywheel.api.struct; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; /** * StructWriters can quickly consume many instances of S and write them to some memory address. */ -public interface StructWriter { +public interface StructWriter

{ /** * Write the given struct to the given memory address. */ - void write(final long ptr, final S struct); + void write(final long ptr, final P struct); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java index bc7f515b1..6ec625409 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/AbstractInstancer.java @@ -4,18 +4,24 @@ import java.util.ArrayList; import java.util.BitSet; import java.util.List; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.struct.StructType; -public abstract class AbstractInstancer implements Instancer { +public abstract class AbstractInstancer

implements Instancer

{ - public final StructType type; - protected final ArrayList data = new ArrayList<>(); + public final StructType

type; - protected boolean anyToRemove; + // Lock for all instance data, only needs to be used in methods that may run on the TaskExecutor. + protected final Object lock = new Object(); + protected final ArrayList

data = new ArrayList<>(); + protected final ArrayList handles = new ArrayList<>(); - protected AbstractInstancer(StructType type) { + // TODO: atomic bitset? + protected final BitSet changed = new BitSet(); + protected final BitSet deleted = new BitSet(); + + protected AbstractInstancer(StructType

type) { this.type = type; } @@ -23,100 +29,92 @@ public abstract class AbstractInstancer implements Inst * @return a handle to a new copy of this model. */ @Override - public D createInstance() { - return _add(type.create()); - } + public P createInstance() { + synchronized (lock) { + var i = data.size(); + var handle = new HandleImpl(this, i); + P instanceData = type.create(handle); - /** - * Copy a data from another Instancer to this. - *

- * This has the effect of swapping out one model for another. - * @param inOther the data associated with a different model. - */ - @Override - public void stealInstance(D inOther) { - if (inOther.getOwner() == this) return; - - // Changing the owner reference will delete it in the other instancer - inOther.getOwner() - .notifyRemoval(); - _add(inOther); - } - - @Override - public void notifyRemoval() { - anyToRemove = true; + data.add(instanceData); + handles.add(handle); + changed.set(i); + return instanceData; + } } /** * Clear all instance data without freeing resources. */ public void clear() { + handles.forEach(HandleImpl::clear); data.clear(); - anyToRemove = true; + handles.clear(); + changed.clear(); + deleted.clear(); } public int getInstanceCount() { return data.size(); } - public List getRange(int start, int end) { + public List

getRange(int start, int end) { return data.subList(start, end); } - public List getAll() { + public List

getAll() { return data; } protected void removeDeletedInstances() { // Figure out which elements are to be removed. final int oldSize = this.data.size(); - int removeCount = 0; - final BitSet removeSet = new BitSet(oldSize); - for (int i = 0; i < oldSize; i++) { - final D element = this.data.get(i); - if (element.isRemoved() || element.getOwner() != this) { - removeSet.set(i); - removeCount++; - } - } + int removeCount = deleted.cardinality(); final int newSize = oldSize - removeCount; // shift surviving elements left over the spaces left by removed elements for (int i = 0, j = 0; (i < oldSize) && (j < newSize); i++, j++) { - i = removeSet.nextClearBit(i); + i = deleted.nextClearBit(i); if (i != j) { - D element = data.get(i); + var handle = handles.get(i); + P element = data.get(i); + + handles.set(j, handle); data.set(j, element); - // Marking the data dirty marks us dirty too. - // Perhaps there will be some wasted cycles, but the JVM should be able to - // generate code that moves the repeated segment out of the loop. - element.markDirty(); + + handle.setIndex(j); + changed.set(j); } } + deleted.clear(); data.subList(newSize, oldSize) .clear(); - + handles.subList(newSize, oldSize) + .clear(); } - private D _add(D instanceData) { - instanceData.setOwner(this); - - instanceData.markDirty(); - synchronized (data) { - data.add(instanceData); - } - - return instanceData; - } - - public abstract void delete(); - @Override public String toString() { return "Instancer[" + getInstanceCount() + ']'; } + + public void notifyDirty(int index) { + if (index < 0 || index >= getInstanceCount()) { + return; + } + synchronized (lock) { + changed.set(index); + } + } + + public void notifyRemoval(int index) { + if (index < 0 || index >= getInstanceCount()) { + return; + } + synchronized (lock) { + deleted.set(index); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/HandleImpl.java b/src/main/java/com/jozufozu/flywheel/backend/engine/HandleImpl.java new file mode 100644 index 000000000..915ef8249 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/HandleImpl.java @@ -0,0 +1,32 @@ +package com.jozufozu.flywheel.backend.engine; + +import com.jozufozu.flywheel.api.instancer.Handle; + +public class HandleImpl implements Handle { + + private final AbstractInstancer instancer; + private int index; + + public HandleImpl(AbstractInstancer instancer, int index) { + this.instancer = instancer; + this.index = index; + } + + @Override + public void setChanged() { + instancer.notifyDirty(index); + } + + @Override + public void setDeleted() { + instancer.notifyRemoval(index); + } + + public void setIndex(int i) { + index = i; + } + + public void clear() { + index = -1; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java index 8be8b6116..39fa9840a 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/InstancerKey.java @@ -1,9 +1,9 @@ package com.jozufozu.flywheel.backend.engine; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.struct.StructType; -public record InstancerKey(StructType type, Model model, RenderStage stage) { +public record InstancerKey

(StructType

type, Model model, RenderStage stage) { } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java index bf55fbde6..3e62c61ff 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingEngine.java @@ -5,7 +5,7 @@ import java.util.List; import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.struct.StructType; @@ -24,7 +24,7 @@ public class BatchingEngine implements Engine { private final BatchingDrawTracker drawTracker = new BatchingDrawTracker(); @Override - public Instancer instancer(StructType type, Model model, RenderStage stage) { + public

Instancer

instancer(StructType

type, Model model, RenderStage stage) { return transformManager.getInstancer(type, model, stage); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingTransformManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingTransformManager.java index bc3240d27..b07d78952 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingTransformManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/BatchingTransformManager.java @@ -15,7 +15,7 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ListMultimap; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.model.Model; @@ -42,9 +42,9 @@ public class BatchingTransformManager { } @SuppressWarnings("unchecked") - public Instancer getInstancer(StructType type, Model model, RenderStage stage) { - InstancerKey key = new InstancerKey<>(type, model, stage); - CPUInstancer instancer = (CPUInstancer) instancers.get(key); + public

Instancer

getInstancer(StructType

type, Model model, RenderStage stage) { + InstancerKey

key = new InstancerKey<>(type, model, stage); + CPUInstancer

instancer = (CPUInstancer

) instancers.get(key); if (instancer == null) { instancer = new CPUInstancer<>(type); instancers.put(key, instancer); @@ -71,7 +71,6 @@ public class BatchingTransformManager { .forEach(BatchedMeshPool::delete); meshPools.clear(); - initializedInstancers.forEach(CPUInstancer::delete); initializedInstancers.clear(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/CPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/CPUInstancer.java index 29b17dc2f..99306a267 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/CPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/CPUInstancer.java @@ -1,29 +1,18 @@ package com.jozufozu.flywheel.backend.engine.batching; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.backend.engine.AbstractInstancer; -public class CPUInstancer extends AbstractInstancer { +public class CPUInstancer

extends AbstractInstancer

{ - public CPUInstancer(StructType type) { + public CPUInstancer(StructType

type) { super(type); } void update() { - if (anyToRemove) { - data.removeIf(InstancedPart::isRemoved); - anyToRemove = false; + if (!deleted.isEmpty()) { + removeDeletedInstances(); } } - - @Override - public void notifyDirty() { - // noop - } - - @Override - public void delete() { - // noop - } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java index 5aebed403..003337564 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/batching/TransformCall.java @@ -2,7 +2,7 @@ package com.jozufozu.flywheel.backend.engine.batching; import java.util.List; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.task.TaskExecutor; @@ -16,15 +16,15 @@ import com.mojang.math.Vector4f; import net.minecraft.client.multiplayer.ClientLevel; -public class TransformCall { - private final CPUInstancer instancer; +public class TransformCall

{ + private final CPUInstancer

instancer; private final Material material; private final BatchedMeshPool.BufferedMesh mesh; private final int meshVertexCount; private final int meshByteSize; - public TransformCall(CPUInstancer instancer, Material material, BatchedMeshPool.BufferedMesh mesh) { + public TransformCall(CPUInstancer

instancer, Material material, BatchedMeshPool.BufferedMesh mesh) { this.instancer = instancer; this.material = material; this.mesh = mesh; @@ -65,18 +65,18 @@ public class TransformCall { transformList(vertexList, instancer.getAll(), matrices, level); } - private void transformList(ReusableVertexList vertexList, List parts, PoseStack.Pose matrices, ClientLevel level) { + private void transformList(ReusableVertexList vertexList, List

parts, PoseStack.Pose matrices, ClientLevel level) { long anchorPtr = vertexList.ptr(); int totalVertexCount = vertexList.vertexCount(); vertexList.vertexCount(meshVertexCount); - StructType.VertexTransformer structVertexTransformer = instancer.type.getVertexTransformer(); + StructType.VertexTransformer

structVertexTransformer = instancer.type.getVertexTransformer(); - for (D d : parts) { + for (P p : parts) { mesh.copyTo(vertexList.ptr()); - structVertexTransformer.transform(vertexList, d, level); + structVertexTransformer.transform(vertexList, p, level); vertexList.ptr(vertexList.ptr() + meshByteSize); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java index f60427a53..b5f9bed66 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java @@ -12,7 +12,7 @@ import static org.lwjgl.opengl.GL45.glVertexArrayElementBuffer; import static org.lwjgl.opengl.GL45.glVertexArrayVertexBuffer; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.backend.compile.FlwCompiler; @@ -22,7 +22,7 @@ import com.jozufozu.flywheel.lib.context.Contexts; import com.jozufozu.flywheel.lib.pipeline.Pipelines; import com.jozufozu.flywheel.lib.util.QuadConverter; -public class IndirectCullingGroup { +public class IndirectCullingGroup

{ private static final int BARRIER_BITS = GL_SHADER_STORAGE_BARRIER_BIT | GL_COMMAND_BARRIER_BIT; @@ -38,13 +38,13 @@ public class IndirectCullingGroup { int vertexArray; - final IndirectDrawSet drawSet = new IndirectDrawSet<>(); + final IndirectDrawSet

drawSet = new IndirectDrawSet<>(); private boolean hasCulledThisFrame; private boolean needsMemoryBarrier; private int instanceCountThisFrame; - IndirectCullingGroup(StructType structType, VertexType vertexType) { + IndirectCullingGroup(StructType

structType, VertexType vertexType) { this.vertexType = vertexType; objectStride = structType.getLayout() diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDraw.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDraw.java index fa2bbed67..bbc352f4c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDraw.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDraw.java @@ -3,12 +3,12 @@ package com.jozufozu.flywheel.backend.engine.indirect; import org.lwjgl.system.MemoryUtil; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.lib.material.MaterialIndices; -public final class IndirectDraw { - private final IndirectInstancer instancer; +public final class IndirectDraw

{ + private final IndirectInstancer

instancer; private final IndirectMeshPool.BufferedMesh mesh; private final Material material; private final RenderStage stage; @@ -19,7 +19,7 @@ public final class IndirectDraw { boolean needsFullWrite = true; - IndirectDraw(IndirectInstancer instancer, Material material, RenderStage stage, IndirectMeshPool.BufferedMesh mesh) { + IndirectDraw(IndirectInstancer

instancer, Material material, RenderStage stage, IndirectMeshPool.BufferedMesh mesh) { this.instancer = instancer; this.material = material; this.stage = stage; @@ -42,10 +42,9 @@ public final class IndirectDraw { void writeObjects(long objectPtr, long batchIDPtr, int batchID) { if (needsFullWrite) { instancer.writeFull(objectPtr, batchIDPtr, batchID); - } else if (instancer.anyToUpdate) { + } else { instancer.writeSparse(objectPtr, batchIDPtr, batchID); } - instancer.anyToUpdate = false; } public void writeIndirectCommand(long ptr) { @@ -63,7 +62,7 @@ public final class IndirectDraw { } - public IndirectInstancer instancer() { + public IndirectInstancer

instancer() { return instancer; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java index 316335d83..73eb23973 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.Map; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.struct.StructType; @@ -22,9 +22,9 @@ public class IndirectDrawManager { public final Map, VertexType>, IndirectCullingGroup> renderLists = new HashMap<>(); @SuppressWarnings("unchecked") - public Instancer getInstancer(StructType type, Model model, RenderStage stage) { - InstancerKey key = new InstancerKey<>(type, model, stage); - IndirectInstancer instancer = (IndirectInstancer) instancers.get(key); + public

Instancer

getInstancer(StructType

type, Model model, RenderStage stage) { + InstancerKey

key = new InstancerKey<>(type, model, stage); + IndirectInstancer

instancer = (IndirectInstancer

) instancers.get(key); if (instancer == null) { instancer = new IndirectInstancer<>(type); instancers.put(key, instancer); @@ -51,7 +51,6 @@ public class IndirectDrawManager { .forEach(IndirectCullingGroup::delete); renderLists.clear(); - initializedInstancers.forEach(IndirectInstancer::delete); initializedInstancers.clear(); } @@ -60,13 +59,13 @@ public class IndirectDrawManager { } @SuppressWarnings("unchecked") - private void add(IndirectInstancer instancer, Model model, RenderStage stage) { + private

void add(IndirectInstancer

instancer, Model model, RenderStage stage) { var meshes = model.getMeshes(); for (var entry : meshes.entrySet()) { var material = entry.getKey(); var mesh = entry.getValue(); - var indirectList = (IndirectCullingGroup) renderLists.computeIfAbsent(Pair.of(instancer.type, mesh.getVertexType()), p -> new IndirectCullingGroup<>(p.first(), p.second())); + var indirectList = (IndirectCullingGroup

) renderLists.computeIfAbsent(Pair.of(instancer.type, mesh.getVertexType()), p -> new IndirectCullingGroup<>(p.first(), p.second())); indirectList.drawSet.add(instancer, material, stage, indirectList.meshPool.alloc(mesh)); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawSet.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawSet.java index dd80b96e2..8fe598553 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawSet.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawSet.java @@ -11,14 +11,14 @@ import java.util.List; import java.util.Map; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.lib.material.MaterialIndices; import com.jozufozu.flywheel.util.Textures; -public class IndirectDrawSet { +public class IndirectDrawSet

{ - final List> indirectDraws = new ArrayList<>(); + final List> indirectDraws = new ArrayList<>(); final Map> multiDraws = new EnumMap<>(RenderStage.class); @@ -30,7 +30,7 @@ public class IndirectDrawSet { return indirectDraws.size(); } - public void add(IndirectInstancer instancer, Material material, RenderStage stage, IndirectMeshPool.BufferedMesh bufferedMesh) { + public void add(IndirectInstancer

instancer, Material material, RenderStage stage, IndirectMeshPool.BufferedMesh bufferedMesh) { indirectDraws.add(new IndirectDraw<>(instancer, material, stage, bufferedMesh)); determineMultiDraws(); } @@ -49,7 +49,7 @@ public class IndirectDrawSet { // TODO: Better material equality. Really we only need to bin by the results of the setup method. multiDraws.clear(); // sort by stage, then material - indirectDraws.sort(Comparator.comparing(IndirectDraw::stage) + indirectDraws.sort(Comparator.comparing(IndirectDraw

::stage) .thenComparing(draw -> MaterialIndices.getMaterialIndex(draw.material()))); for (int start = 0, i = 0; i < indirectDraws.size(); i++) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java index 207766137..be3e9bb30 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java @@ -7,7 +7,7 @@ import org.lwjgl.opengl.GL32; import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.struct.StructType; @@ -34,7 +34,7 @@ public class IndirectEngine implements Engine { } @Override - public Instancer instancer(StructType type, Model model, RenderStage stage) { + public

Instancer

instancer(StructType

type, Model model, RenderStage stage) { return drawManager.getInstancer(type, model, stage); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java index b21bb0c89..4d50bafc5 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectInstancer.java @@ -2,54 +2,45 @@ package com.jozufozu.flywheel.backend.engine.indirect; import org.lwjgl.system.MemoryUtil; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; import com.jozufozu.flywheel.backend.engine.AbstractInstancer; -public class IndirectInstancer extends AbstractInstancer { +public class IndirectInstancer

extends AbstractInstancer

{ private final long objectStride; - private final StructWriter writer; + private final StructWriter

writer; int instanceCount = 0; - boolean anyToUpdate; - - public IndirectInstancer(StructType type) { + public IndirectInstancer(StructType

type) { super(type); this.objectStride = type.getLayout() .getStride(); writer = type.getWriter(); } - @Override - public void notifyDirty() { - anyToUpdate = true; - } - public boolean isEmpty() { - return !anyToUpdate && !anyToRemove && instanceCount == 0; + return changed.isEmpty() && deleted.isEmpty() && instanceCount == 0; } void update() { - if (anyToRemove) { + if (!deleted.isEmpty()) { removeDeletedInstances(); } instanceCount = data.size(); - - anyToRemove = false; } public void writeSparse(long objectPtr, long batchIDPtr, int batchID) { - for (int i = 0, size = data.size(); i < size; i++) { - final var element = data.get(i); - if (element.checkDirtyAndClear()) { - writer.write(objectPtr + i * objectStride, element); + final int size = data.size(); - MemoryUtil.memPutInt(batchIDPtr + i * IndirectBuffers.INT_SIZE, batchID); - } + for (int i = changed.nextSetBit(0); i >= 0 && i < size; i = changed.nextSetBit(i + 1)) { + writer.write(objectPtr + i * objectStride, data.get(i)); + + MemoryUtil.memPutInt(batchIDPtr + i * IndirectBuffers.INT_SIZE, batchID); } + changed.clear(); } public void writeFull(long objectPtr, long batchIDPtr, int batchID) { @@ -62,10 +53,6 @@ public class IndirectInstancer extends AbstractInstance MemoryUtil.memPutInt(batchIDPtr, batchID); batchIDPtr += IndirectBuffers.INT_SIZE; } - } - - @Override - public void delete() { - // noop + changed.clear(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java index ce7058c5b..55b48a75c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/GPUInstancer.java @@ -4,7 +4,7 @@ import java.util.HashSet; import java.util.Set; import com.jozufozu.flywheel.Flywheel; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; @@ -15,25 +15,18 @@ import com.jozufozu.flywheel.gl.buffer.GlBufferType; import com.jozufozu.flywheel.gl.buffer.GlBufferUsage; import com.jozufozu.flywheel.gl.buffer.MappedBuffer; -public class GPUInstancer extends AbstractInstancer { +public class GPUInstancer

extends AbstractInstancer

{ final BufferLayout instanceFormat; - final StructType structType; final Set boundTo = new HashSet<>(); GlBuffer vbo; int glInstanceCount = 0; boolean anyToUpdate; - public GPUInstancer(StructType type) { + public GPUInstancer(StructType

type) { super(type); this.instanceFormat = type.getLayout(); - this.structType = type; - } - - @Override - public void notifyDirty() { - anyToUpdate = true; } public void init() { @@ -46,11 +39,11 @@ public class GPUInstancer extends AbstractInstancer } public boolean isEmpty() { - return !anyToUpdate && !anyToRemove && glInstanceCount == 0; + return deleted.isEmpty() && changed.isEmpty() && glInstanceCount == 0; } void update() { - if (anyToRemove) { + if (!deleted.isEmpty()) { removeDeletedInstances(); } @@ -59,13 +52,11 @@ public class GPUInstancer extends AbstractInstancer boundTo.clear(); } - if (anyToUpdate) { + if (!changed.isEmpty()) { clearAndUpdateBuffer(); } glInstanceCount = data.size(); - - anyToRemove = anyToUpdate = false; } private void clearAndUpdateBuffer() { @@ -78,15 +69,14 @@ public class GPUInstancer extends AbstractInstancer if (size > 0) { final long ptr = buf.getPtr(); - final long stride = structType.getLayout().getStride(); - final StructWriter writer = structType.getWriter(); + final long stride = type.getLayout() + .getStride(); + final StructWriter

writer = type.getWriter(); - for (int i = 0; i < size; i++) { - final D element = data.get(i); - if (element.checkDirtyAndClear()) { - writer.write(ptr + i * stride, element); - } + for (int i = changed.nextSetBit(0); i >= 0 && i < size; i = changed.nextSetBit(i + 1)) { + writer.write(ptr + i * stride, data.get(i)); } + changed.clear(); } } catch (Exception e) { Flywheel.LOGGER.error("Error updating GPUInstancer:", e); @@ -104,7 +94,6 @@ public class GPUInstancer extends AbstractInstancer return vbo.ensureCapacity(requiredSize); } - @Override public void delete() { vbo.delete(); vbo = null; diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingDrawManager.java index 89cf04c4c..10c3fd563 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingDrawManager.java @@ -14,7 +14,7 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ListMultimap; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Mesh; import com.jozufozu.flywheel.api.model.Model; @@ -35,9 +35,9 @@ public class InstancingDrawManager { } @SuppressWarnings("unchecked") - public Instancer getInstancer(StructType type, Model model, RenderStage stage) { - InstancerKey key = new InstancerKey<>(type, model, stage); - GPUInstancer instancer = (GPUInstancer) instancers.get(key); + public

Instancer

getInstancer(StructType

type, Model model, RenderStage stage) { + InstancerKey

key = new InstancerKey<>(type, model, stage); + GPUInstancer

instancer = (GPUInstancer

) instancers.get(key); if (instancer == null) { instancer = new GPUInstancer<>(type); instancers.put(key, instancer); diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java index 639d3e771..8cfbb174b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java @@ -8,7 +8,7 @@ import com.jozufozu.flywheel.api.backend.Engine; import com.jozufozu.flywheel.api.context.Context; import com.jozufozu.flywheel.api.event.RenderContext; import com.jozufozu.flywheel.api.event.RenderStage; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.api.instancer.Instancer; import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.api.struct.StructType; @@ -41,7 +41,7 @@ public class InstancingEngine implements Engine { } @Override - public Instancer instancer(StructType type, Model model, RenderStage stage) { + public

Instancer

instancer(StructType

type, Model model, RenderStage stage) { return drawManager.getInstancer(type, model, stage); } diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/BlockEntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/BlockEntityInstanceManager.java index 254fd4358..e43961527 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/BlockEntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/BlockEntityInstanceManager.java @@ -39,37 +39,6 @@ public class BlockEntityInstanceManager extends InstanceManager { } } - @Override - protected boolean canCreateInstance(BlockEntity blockEntity) { - if (blockEntity.isRemoved()) { - return false; - } - - if (!InstancingControllerHelper.canInstance(blockEntity)) { - return false; - } - - Level level = blockEntity.getLevel(); - - if (level == null) { - return false; - } - - if (level.isEmptyBlock(blockEntity.getBlockPos())) { - return false; - } - - if (BackendUtil.isFlywheelLevel(level)) { - BlockPos pos = blockEntity.getBlockPos(); - - BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); - - return existingChunk != null; - } - - return false; - } - private static class BlockEntityStorage extends One2OneStorage { private final Long2ObjectMap> posLookup = new Long2ObjectOpenHashMap<>(); @@ -77,6 +46,37 @@ public class BlockEntityInstanceManager extends InstanceManager { super(engine); } + @Override + public boolean willAccept(BlockEntity blockEntity) { + if (blockEntity.isRemoved()) { + return false; + } + + if (!InstancingControllerHelper.canInstance(blockEntity)) { + return false; + } + + Level level = blockEntity.getLevel(); + + if (level == null) { + return false; + } + + if (level.isEmptyBlock(blockEntity.getBlockPos())) { + return false; + } + + if (BackendUtil.isFlywheelLevel(level)) { + BlockPos pos = blockEntity.getBlockPos(); + + BlockGetter existingChunk = level.getChunkForCollisions(pos.getX() >> 4, pos.getZ() >> 4); + + return existingChunk != null; + } + + return false; + } + @Override @Nullable protected Instance createRaw(BlockEntity obj) { diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EffectInstanceManager.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EffectInstanceManager.java index 185e4edaa..c30187f05 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EffectInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EffectInstanceManager.java @@ -21,11 +21,6 @@ public class EffectInstanceManager extends InstanceManager { return storage; } - @Override - protected boolean canCreateInstance(Effect obj) { - return true; - } - private static class EffectStorage extends One2ManyStorage { public EffectStorage(Engine engine) { super(engine); @@ -35,5 +30,10 @@ public class EffectInstanceManager extends InstanceManager { protected Collection createRaw(Effect obj) { return obj.createInstances(new InstanceContext(engine, engine.renderOrigin())); } + + @Override + public boolean willAccept(Effect obj) { + return true; + } } } diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EntityInstanceManager.java index 326527acd..b76c1966d 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/EntityInstanceManager.java @@ -25,21 +25,6 @@ public class EntityInstanceManager extends InstanceManager { return storage; } - @Override - protected boolean canCreateInstance(Entity entity) { - if (!entity.isAlive()) { - return false; - } - - if (!InstancingControllerHelper.canInstance(entity)) { - return false; - } - - Level level = entity.level; - - return BackendUtil.isFlywheelLevel(level); - } - private static class EntityStorage extends One2OneStorage { public EntityStorage(Engine engine) { super(engine); @@ -55,5 +40,20 @@ public class EntityInstanceManager extends InstanceManager { return controller.createInstance(new InstanceContext(engine, engine.renderOrigin()), obj); } + + @Override + public boolean willAccept(Entity entity) { + if (!entity.isAlive()) { + return false; + } + + if (!InstancingControllerHelper.canInstance(entity)) { + return false; + } + + Level level = entity.level; + + return BackendUtil.isFlywheelLevel(level); + } } } diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java index f164dfe43..e2976e4a8 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/manager/InstanceManager.java @@ -31,17 +31,6 @@ public abstract class InstanceManager { protected abstract Storage getStorage(); - /** - * Is the given object currently capable of being instanced? - * - *

- * This won't be the case for block entities or entities that are outside of loaded chunks. - *

- * - * @return true if the object is currently capable of being instanced. - */ - protected abstract boolean canCreateInstance(T obj); - protected DistanceUpdateLimiter createUpdateLimiter() { if (FlwConfig.get().limitUpdates()) { return new BandedPrimeLimiter(); @@ -60,7 +49,7 @@ public abstract class InstanceManager { } public void add(T obj) { - if (!canCreateInstance(obj)) { + if (!getStorage().willAccept(obj)) { return; } @@ -68,7 +57,7 @@ public abstract class InstanceManager { } public void queueAdd(T obj) { - if (!canCreateInstance(obj)) { + if (!getStorage().willAccept(obj)) { return; } @@ -89,7 +78,7 @@ public abstract class InstanceManager { * @param obj the object to update. */ public void update(T obj) { - if (!canCreateInstance(obj)) { + if (!getStorage().willAccept(obj)) { return; } @@ -97,7 +86,7 @@ public abstract class InstanceManager { } public void queueUpdate(T obj) { - if (!canCreateInstance(obj)) { + if (!getStorage().willAccept(obj)) { return; } diff --git a/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Storage.java b/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Storage.java index 9052cb59b..78c3a474e 100644 --- a/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Storage.java +++ b/src/main/java/com/jozufozu/flywheel/impl/instancing/storage/Storage.java @@ -14,6 +14,13 @@ public interface Storage { List getDynamicInstances(); + /** + * Is the given object currently capable of being added? + * + * @return true if the object is currently capable of being instanced. + */ + boolean willAccept(T obj); + void add(T obj); void remove(T obj); diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/AbstractInstancePart.java b/src/main/java/com/jozufozu/flywheel/lib/struct/AbstractInstancePart.java new file mode 100644 index 000000000..71b55fc4d --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/AbstractInstancePart.java @@ -0,0 +1,29 @@ +package com.jozufozu.flywheel.lib.struct; + +import com.jozufozu.flywheel.api.instancer.Handle; +import com.jozufozu.flywheel.api.instancer.InstancePart; +import com.jozufozu.flywheel.api.struct.StructType; + +public abstract class AbstractInstancePart implements InstancePart { + + public final StructType type; + protected final Handle handle; + + protected AbstractInstancePart(StructType type, Handle handle) { + this.type = type; + this.handle = handle; + } + + @Override + public StructType type() { + return type; + } + + public final void setChanged() { + handle.setChanged(); + } + + public final void delete() { + handle.setDeleted(); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/ColoredLitPart.java b/src/main/java/com/jozufozu/flywheel/lib/struct/ColoredLitPart.java index 1b952ee9f..a6339f577 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/ColoredLitPart.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/ColoredLitPart.java @@ -1,11 +1,11 @@ package com.jozufozu.flywheel.lib.struct; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.Handle; import com.jozufozu.flywheel.api.struct.StructType; import net.minecraft.client.renderer.LightTexture; -public abstract class ColoredLitPart extends InstancedPart implements FlatLit { +public abstract class ColoredLitPart extends AbstractInstancePart implements FlatLit { public byte blockLight; public byte skyLight; @@ -15,21 +15,21 @@ public abstract class ColoredLitPart extends InstancedPart implements FlatLit type) { - super(type); + public ColoredLitPart(StructType type, Handle handle) { + super(type, handle); } @Override public ColoredLitPart setBlockLight(int blockLight) { this.blockLight = (byte) blockLight; - markDirty(); + setChanged(); return this; } @Override public ColoredLitPart setSkyLight(int skyLight) { this.skyLight = (byte) skyLight; - markDirty(); + setChanged(); return this; } @@ -63,7 +63,7 @@ public abstract class ColoredLitPart extends InstancedPart implements FlatLit * This only covers flat lighting, smooth lighting is still TODO. * - * @param The name of the class that implements this interface. + * @param

The name of the class that implements this interface. */ -public interface FlatLit> { +public interface FlatLit

> { /** * @param blockLight An integer in the range [0, 15] representing the * amount of block light this instance should receive. * @return {@code this} */ - D setBlockLight(int blockLight); + P setBlockLight(int blockLight); /** * @param skyLight An integer in the range [0, 15] representing the * amount of sky light this instance should receive. * @return {@code this} */ - D setSkyLight(int skyLight); + P setSkyLight(int skyLight); - default D setLight(int blockLight, int skyLight) { - return setBlockLight(blockLight) - .setSkyLight(skyLight); + default P setLight(int blockLight, int skyLight) { + return setBlockLight(blockLight).setSkyLight(skyLight); } - default D updateLight(BlockAndTintGetter level, BlockPos pos) { + default P updateLight(BlockAndTintGetter level, BlockPos pos) { return setLight(level.getBrightness(LightLayer.BLOCK, pos), level.getBrightness(LightLayer.SKY, pos)); } diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedPart.java b/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedPart.java index c6559f92f..2f00ab4f2 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedPart.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedPart.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.lib.struct; +import com.jozufozu.flywheel.api.instancer.Handle; import com.mojang.math.Quaternion; import com.mojang.math.Vector3f; @@ -18,8 +19,8 @@ public class OrientedPart extends ColoredLitPart { public float qZ; public float qW = 1; - public OrientedPart() { - super(StructTypes.ORIENTED); + public OrientedPart(Handle handle) { + super(StructTypes.ORIENTED, handle); } public OrientedPart setPosition(BlockPos pos) { @@ -34,7 +35,7 @@ public class OrientedPart extends ColoredLitPart { this.posX = x; this.posY = y; this.posZ = z; - markDirty(); + setChanged(); return this; } @@ -42,7 +43,7 @@ public class OrientedPart extends ColoredLitPart { this.posX += x; this.posY += y; this.posZ += z; - markDirty(); + setChanged(); return this; } @@ -58,7 +59,7 @@ public class OrientedPart extends ColoredLitPart { this.pivotX = x; this.pivotY = y; this.pivotZ = z; - markDirty(); + setChanged(); return this; } @@ -71,7 +72,7 @@ public class OrientedPart extends ColoredLitPart { this.qY = y; this.qZ = z; this.qW = w; - markDirty(); + setChanged(); return this; } @@ -80,13 +81,13 @@ public class OrientedPart extends ColoredLitPart { this.qY = 0; this.qZ = 0; this.qW = 1; - markDirty(); + setChanged(); return this; } @Override - public OrientedPart copy() { - var out = new OrientedPart(); + public OrientedPart copy(Handle handle) { + var out = new OrientedPart(handle); out.posX = this.posX; out.posY = this.posY; out.posZ = this.posZ; diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedType.java b/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedType.java index 1010220d6..6185819d6 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedType.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/OrientedType.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.lib.struct; +import com.jozufozu.flywheel.api.instancer.Handle; import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.api.struct.StructWriter; @@ -24,8 +25,8 @@ public class OrientedType implements StructType { .build(); @Override - public OrientedPart create() { - return new OrientedPart(); + public OrientedPart create(Handle handle) { + return new OrientedPart(handle); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedPart.java b/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedPart.java index 195ad2da9..16a19233d 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedPart.java +++ b/src/main/java/com/jozufozu/flywheel/lib/struct/TransformedPart.java @@ -1,5 +1,6 @@ package com.jozufozu.flywheel.lib.struct; +import com.jozufozu.flywheel.api.instancer.Handle; import com.jozufozu.flywheel.lib.transform.Transform; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix3f; @@ -15,15 +16,17 @@ public class TransformedPart extends ColoredLitPart implements Transform */ public TransformedPart setEmptyTransform() { - markDirty(); + setChanged(); this.model.load(EMPTY_MATRIX_4f); this.normal.load(EMPTY_MATRIX_3f); @@ -43,7 +46,7 @@ public class TransformedPart extends ColoredLitPart implements Transform { .build(); @Override - public TransformedPart create() { - return new TransformedPart(); + public TransformedPart create(Handle handle) { + return new TransformedPart(handle); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java index 949cc71b4..971f24d1c 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/BellInstance.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.controller.InstanceContext; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance; import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.model.SimpleLazyModel; @@ -68,7 +68,7 @@ public class BellInstance extends AbstractBlockEntityInstance i } @Override - public List getCrumblingParts() { + public List getCrumblingParts() { return List.of(bell); } diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java index 83fc3ad6c..4b95610ca 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java @@ -7,7 +7,7 @@ import java.util.function.BiFunction; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.controller.InstanceContext; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance; import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.model.SimpleLazyModel; @@ -111,7 +111,7 @@ public class ChestInstance extends Abstr } @Override - public List getCrumblingParts() { + public List getCrumblingParts() { return List.of(body, lid); } diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java index 4b32d9c8e..3cee8063a 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ShulkerBoxInstance.java @@ -6,7 +6,7 @@ import java.util.function.Function; import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.api.instance.controller.InstanceContext; -import com.jozufozu.flywheel.api.instancer.InstancedPart; +import com.jozufozu.flywheel.api.instancer.InstancePart; import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance; import com.jozufozu.flywheel.lib.material.Materials; import com.jozufozu.flywheel.lib.model.SimpleLazyModel; @@ -95,7 +95,7 @@ public class ShulkerBoxInstance extends AbstractBlockEntityInstance getCrumblingParts() { + public List getCrumblingParts() { return List.of(base, lid); }