mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-10 12:34:11 +01:00
Instance Refactor I
This commit is contained in:
parent
4ac0adf703
commit
b65cb7eb7f
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -59,7 +59,6 @@ body:
|
||||
label: Mod Version
|
||||
description: The version of the mod you were using when the bug occured
|
||||
options:
|
||||
- "0.7.0"
|
||||
- "0.6.8.a"
|
||||
- "0.6.8"
|
||||
- "0.6.7"
|
||||
|
@ -2,7 +2,7 @@ org.gradle.jvmargs = -Xmx3G
|
||||
org.gradle.daemon = false
|
||||
|
||||
# mod version info
|
||||
mod_version = 0.7.0
|
||||
mod_version = 1.0.0-alpha
|
||||
artifact_minecraft_version = 1.18.2
|
||||
|
||||
minecraft_version = 1.18.2
|
||||
|
@ -17,7 +17,7 @@ import com.jozufozu.flywheel.impl.RegistryImpl;
|
||||
import com.jozufozu.flywheel.lib.backend.Backends;
|
||||
import com.jozufozu.flywheel.lib.context.Contexts;
|
||||
import com.jozufozu.flywheel.lib.format.Formats;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndices;
|
||||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.Models;
|
||||
import com.jozufozu.flywheel.lib.model.PartialModel;
|
||||
@ -111,7 +111,7 @@ public class Flywheel {
|
||||
Contexts.init();
|
||||
Pipelines.init();
|
||||
|
||||
MaterialIndicies.init();
|
||||
MaterialIndices.init();
|
||||
|
||||
VanillaInstances.init();
|
||||
|
||||
@ -126,10 +126,10 @@ public class Flywheel {
|
||||
}
|
||||
|
||||
private static void setup(final FMLCommonSetupEvent event) {
|
||||
ArgumentTypes.register(rl("backend").toString(), BackendArgument.class, new EmptyArgumentSerializer<>(BackendArgument::getInstance));
|
||||
|
||||
RegistryImpl.freezeAll();
|
||||
IdRegistryImpl.freezeAll();
|
||||
|
||||
ArgumentTypes.register(rl("backend").toString(), BackendArgument.class, new EmptyArgumentSerializer<>(BackendArgument::getInstance));
|
||||
}
|
||||
|
||||
public static ArtifactVersion getVersion() {
|
||||
|
@ -3,7 +3,7 @@ package com.jozufozu.flywheel.api.backend;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.InstanceManager;
|
||||
|
||||
public interface Engine extends RenderDispatcher, InstancerProvider {
|
||||
void attachManagers(InstanceManager<?>... listener);
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.jozufozu.flywheel.api.instance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
public interface BlockEntityInstance<T extends BlockEntity> extends Instance {
|
||||
List<InstancedPart> getCrumblingParts();
|
||||
}
|
@ -2,11 +2,10 @@ package com.jozufozu.flywheel.api.instance;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
|
||||
/**
|
||||
* An interface giving {@link BlockEntityInstance}s a hook to have a function called at
|
||||
* the start of a frame. By implementing {@link DynamicInstance}, a {@link BlockEntityInstance}
|
||||
* An interface giving {@link Instance}s a hook to have a function called at
|
||||
* the start of a frame. By implementing {@link DynamicInstance}, an {@link Instance}
|
||||
* can animate its models in ways that could not be easily achieved by shader attribute
|
||||
* parameterization.
|
||||
*
|
||||
|
@ -0,0 +1,6 @@
|
||||
package com.jozufozu.flywheel.api.instance;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
public interface EntityInstance<E extends Entity> extends Instance {
|
||||
}
|
@ -4,9 +4,38 @@ import org.joml.FrustumIntersection;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
/**
|
||||
* A general interface providing information about any type of thing that could use Flywheel's instanced rendering.
|
||||
*/
|
||||
public interface Instance {
|
||||
BlockPos getWorldPosition();
|
||||
|
||||
/**
|
||||
* Initialize parts here.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Update instance data here. Good for when data doesn't change very often and when animations are GPU based.
|
||||
*
|
||||
* <br><br> If your animations are complex or more CPU driven, see {@link DynamicInstance} or {@link TickableInstance}.
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* When an instance is reset, the instance is deleted and re-created.
|
||||
*
|
||||
* <p>
|
||||
* Just before {@link #update()} would be called, {@code shouldReset()} is checked.
|
||||
* If this function returns {@code true}, then this instance will be {@link #delete deleted},
|
||||
* and another instance will be constructed to replace it. This allows for more sane resource
|
||||
* acquisition compared to trying to update everything within the lifetime of an instance.
|
||||
* </p>
|
||||
*
|
||||
* @return {@code true} if this instance should be discarded and refreshed.
|
||||
*/
|
||||
boolean shouldReset();
|
||||
|
||||
/**
|
||||
* Check this instance against a frustum.<p>
|
||||
* An implementor may choose to return a constant to skip the frustum check.
|
||||
@ -15,5 +44,12 @@ public interface Instance {
|
||||
*/
|
||||
boolean checkFrustum(FrustumIntersection frustum);
|
||||
|
||||
boolean isRemoved();
|
||||
/**
|
||||
* Free any acquired resources.
|
||||
*/
|
||||
void delete();
|
||||
|
||||
// TODO
|
||||
@Deprecated
|
||||
void removeNow();
|
||||
}
|
||||
|
@ -2,11 +2,10 @@ package com.jozufozu.flywheel.api.instance;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
|
||||
/**
|
||||
* An interface giving {@link BlockEntityInstance}s a hook to have a function called at
|
||||
* the end of every tick. By implementing {@link TickableInstance}, a {@link BlockEntityInstance}
|
||||
* An interface giving {@link Instance}s a hook to have a function called at
|
||||
* the end of every tick. By implementing {@link TickableInstance}, an {@link Instance}
|
||||
* can update frequently, but not every frame.
|
||||
* <br> There are a few cases in which this should be considered over {@link DynamicInstance}:
|
||||
* <ul>
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.jozufozu.flywheel.api.instance.blockentity;
|
||||
package com.jozufozu.flywheel.api.instance.controller;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.jozufozu.flywheel.api.instance.entity;
|
||||
package com.jozufozu.flywheel.api.instance.controller;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.EntityInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
@ -0,0 +1,60 @@
|
||||
package com.jozufozu.flywheel.api.instance.controller;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.impl.instance.InstancingControllerRegistryImpl;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
||||
/**
|
||||
* A utility class for registering and retrieving {@code InstancingController}s.
|
||||
*/
|
||||
public final class InstancingControllerRegistry {
|
||||
/**
|
||||
* Gets the instancing controller for the given block entity type, if one exists.
|
||||
* @param type The block entity type to get the instancing controller for.
|
||||
* @param <T> The type of the block entity.
|
||||
* @return The instancing controller for the given block entity type, or {@code null} if none exists.
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends BlockEntity> BlockEntityInstancingController<? super T> getController(BlockEntityType<T> type) {
|
||||
return InstancingControllerRegistryImpl.getController(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instancing controller for the given entity type, if one exists.
|
||||
* @param type The entity type to get the instancing controller for.
|
||||
* @param <T> The type of the entity.
|
||||
* @return The instancing controller for the given entity type, or {@code null} if none exists.
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends Entity> EntityInstancingController<? super T> getController(EntityType<T> type) {
|
||||
return InstancingControllerRegistryImpl.getController(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the instancing controller for the given block entity type.
|
||||
* @param type The block entity type to set the instancing controller for.
|
||||
* @param instancingController The instancing controller to set.
|
||||
* @param <T> The type of the block entity.
|
||||
*/
|
||||
public static <T extends BlockEntity> void setController(BlockEntityType<T> type, BlockEntityInstancingController<? super T> instancingController) {
|
||||
InstancingControllerRegistryImpl.setController(type, instancingController);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the instancing controller for the given entity type.
|
||||
* @param type The entity type to set the instancing controller for.
|
||||
* @param instancingController The instancing controller to set.
|
||||
* @param <T> The type of the entity.
|
||||
*/
|
||||
public static <T extends Entity> void setController(EntityType<T> type, EntityInstancingController<? super T> instancingController) {
|
||||
InstancingControllerRegistryImpl.setController(type, instancingController);
|
||||
}
|
||||
|
||||
private InstancingControllerRegistry() {
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.jozufozu.flywheel.api.instance.effect;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
|
||||
public interface Effect {
|
||||
Collection<Instance> createInstances(InstancerProvider instancerManager);
|
||||
}
|
@ -14,6 +14,6 @@ public interface InstancerProvider {
|
||||
*/
|
||||
<D extends InstancedPart> Instancer<D> getInstancer(StructType<D> type, Model model, RenderStage stage);
|
||||
|
||||
// TODO: this method does not belong in the interface
|
||||
// TODO: this method does not belong in this interface
|
||||
Vec3i getOriginCoordinate();
|
||||
}
|
||||
|
@ -21,6 +21,10 @@ public interface IdRegistry<T> extends Iterable<T> {
|
||||
@Nullable
|
||||
ResourceLocation getId(T object);
|
||||
|
||||
T getOrThrow(ResourceLocation id);
|
||||
|
||||
ResourceLocation getIdOrThrow(T object);
|
||||
|
||||
@Unmodifiable
|
||||
Set<ResourceLocation> getAllIds();
|
||||
|
||||
|
@ -9,7 +9,7 @@ import com.jozufozu.flywheel.api.struct.StructType;
|
||||
public class CullingContextSet {
|
||||
static CullingContextSet create() {
|
||||
var builder = new CullingContextSet();
|
||||
for (StructType<?> structType : StructType.REGISTRY.getAll()) {
|
||||
for (StructType<?> structType : StructType.REGISTRY) {
|
||||
builder.add(structType);
|
||||
}
|
||||
return builder;
|
||||
|
@ -26,7 +26,7 @@ import com.jozufozu.flywheel.glsl.ShaderSources;
|
||||
import com.jozufozu.flywheel.glsl.SourceComponent;
|
||||
import com.jozufozu.flywheel.glsl.generate.FnSignature;
|
||||
import com.jozufozu.flywheel.glsl.generate.GlslExpr;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndices;
|
||||
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
|
||||
import com.jozufozu.flywheel.util.StringUtil;
|
||||
|
||||
@ -55,12 +55,12 @@ public class FlwCompiler {
|
||||
|
||||
this.sources = sources;
|
||||
this.vertexMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("vertex_material_adapter"))
|
||||
.materialSources(MaterialIndicies.getAllVertexShaders())
|
||||
.materialSources(MaterialIndices.getAllVertexShaders())
|
||||
.adapt(FnSignature.ofVoid("flw_materialVertex"))
|
||||
.switchOn(GlslExpr.variable("flw_materialVertexID"))
|
||||
.build(sources);
|
||||
this.fragmentMaterialComponent = MaterialAdapterComponent.builder(Flywheel.rl("fragment_material_adapter"))
|
||||
.materialSources(MaterialIndicies.getAllFragmentShaders())
|
||||
.materialSources(MaterialIndices.getAllFragmentShaders())
|
||||
.adapt(FnSignature.ofVoid("flw_materialFragment"))
|
||||
.adapt(FnSignature.create()
|
||||
.returnType("bool")
|
||||
|
@ -24,8 +24,8 @@ public class PipelineContextSet {
|
||||
static PipelineContextSet create() {
|
||||
var builder = new PipelineContextSet();
|
||||
for (Pipeline pipelineShader : availablePipelineShaders()) {
|
||||
for (StructType<?> structType : StructType.REGISTRY.getAll()) {
|
||||
for (VertexType vertexType : VertexType.REGISTRY.getAll()) {
|
||||
for (StructType<?> structType : StructType.REGISTRY) {
|
||||
for (VertexType vertexType : VertexType.REGISTRY) {
|
||||
builder.add(vertexType, structType, Contexts.WORLD, pipelineShader);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.jozufozu.flywheel.backend.instancing;
|
||||
package com.jozufozu.flywheel.backend.engine;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
@ -1,4 +1,4 @@
|
||||
package com.jozufozu.flywheel.backend.instancing;
|
||||
package com.jozufozu.flywheel.backend.engine;
|
||||
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
@ -1,4 +1,4 @@
|
||||
package com.jozufozu.flywheel.backend.uniform;
|
||||
package com.jozufozu.flywheel.backend.engine;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
@ -10,7 +10,7 @@ import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.InstanceManager;
|
||||
import com.jozufozu.flywheel.util.FlwUtil;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
|
@ -20,7 +20,7 @@ import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancerKey;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerKey;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
@ -2,7 +2,7 @@ package com.jozufozu.flywheel.backend.engine.batching;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
||||
|
||||
public class CPUInstancer<D extends InstancedPart> extends AbstractInstancer<D> {
|
||||
|
||||
|
@ -16,7 +16,7 @@ import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
|
||||
import com.jozufozu.flywheel.backend.uniform.UniformBuffer;
|
||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||
import com.jozufozu.flywheel.gl.shader.GlProgram;
|
||||
import com.jozufozu.flywheel.lib.context.Contexts;
|
||||
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
|
||||
|
@ -5,7 +5,7 @@ import org.lwjgl.system.MemoryUtil;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndices;
|
||||
|
||||
public final class IndirectDraw<T extends InstancedPart> {
|
||||
private final IndirectInstancer<T> instancer;
|
||||
@ -25,8 +25,8 @@ public final class IndirectDraw<T extends InstancedPart> {
|
||||
this.stage = stage;
|
||||
this.mesh = mesh;
|
||||
|
||||
this.vertexMaterialID = MaterialIndicies.getVertexShaderIndex(material.vertexShader());
|
||||
this.fragmentMaterialID = MaterialIndicies.getFragmentShaderIndex(material.fragmentShader());
|
||||
this.vertexMaterialID = MaterialIndices.getVertexShaderIndex(material);
|
||||
this.fragmentMaterialID = MaterialIndices.getFragmentShaderIndex(material);
|
||||
}
|
||||
|
||||
public void prepare(int baseInstance) {
|
||||
|
@ -11,7 +11,7 @@ import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancerKey;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerKey;
|
||||
import com.jozufozu.flywheel.util.Pair;
|
||||
|
||||
public class IndirectDrawManager {
|
||||
|
@ -13,7 +13,7 @@ import java.util.Map;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndices;
|
||||
import com.jozufozu.flywheel.util.Textures;
|
||||
|
||||
public class IndirectDrawSet<T extends InstancedPart> {
|
||||
@ -50,7 +50,7 @@ public class IndirectDrawSet<T extends InstancedPart> {
|
||||
multiDraws.clear();
|
||||
// sort by stage, then material
|
||||
indirectDraws.sort(Comparator.comparing(IndirectDraw<T>::stage)
|
||||
.thenComparing(draw -> MaterialIndicies.getMaterialIndex(draw.material())));
|
||||
.thenComparing(draw -> MaterialIndices.getMaterialIndex(draw.material())));
|
||||
|
||||
for (int start = 0, i = 0; i < indirectDraws.size(); i++) {
|
||||
var draw = indirectDraws.get(i);
|
||||
|
@ -15,7 +15,7 @@ import com.jozufozu.flywheel.api.instancer.Instancer;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.InstanceManager;
|
||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
||||
import com.jozufozu.flywheel.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.util.FlwUtil;
|
||||
|
@ -5,7 +5,7 @@ import org.lwjgl.system.MemoryUtil;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
||||
|
||||
public class IndirectInstancer<D extends InstancedPart> extends AbstractInstancer<D> {
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
package com.jozufozu.flywheel.backend.engine.indirect;
|
||||
|
||||
import com.jozufozu.flywheel.api.material.Material;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
|
||||
public record ShaderState(Material material, VertexType vertex, StructType<?> instance) {
|
||||
}
|
@ -8,7 +8,7 @@ import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.gl.array.GlVertexArray;
|
||||
import com.jozufozu.flywheel.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.gl.buffer.GlBufferType;
|
||||
|
@ -20,7 +20,7 @@ import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancerKey;
|
||||
import com.jozufozu.flywheel.backend.engine.InstancerKey;
|
||||
|
||||
public class InstancingDrawManager {
|
||||
|
||||
|
@ -16,11 +16,11 @@ import com.jozufozu.flywheel.api.model.Model;
|
||||
import com.jozufozu.flywheel.api.struct.StructType;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.backend.compile.FlwCompiler;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.uniform.UniformBuffer;
|
||||
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.InstanceManager;
|
||||
import com.jozufozu.flywheel.gl.GlStateTracker;
|
||||
import com.jozufozu.flywheel.gl.GlTextureUnit;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndicies;
|
||||
import com.jozufozu.flywheel.lib.material.MaterialIndices;
|
||||
import com.jozufozu.flywheel.lib.pipeline.Pipelines;
|
||||
import com.jozufozu.flywheel.util.FlwUtil;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
@ -121,8 +121,8 @@ public class InstancingEngine implements Engine {
|
||||
UniformBuffer.syncAndBind(program);
|
||||
|
||||
var uniformLocation = program.getUniformLocation("_flw_materialID_instancing");
|
||||
var vertexID = MaterialIndicies.getVertexShaderIndex(material.vertexShader());
|
||||
var fragmentID = MaterialIndicies.getFragmentShaderIndex(material.fragmentShader());
|
||||
var vertexID = MaterialIndices.getVertexShaderIndex(material);
|
||||
var fragmentID = MaterialIndices.getFragmentShaderIndex(material);
|
||||
GL32.glUniform2ui(uniformLocation, vertexID, fragmentID);
|
||||
}
|
||||
|
||||
|
@ -7,11 +7,12 @@ import com.jozufozu.flywheel.api.event.RenderContext;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instance.effect.Effect;
|
||||
import com.jozufozu.flywheel.backend.BackendUtil;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.effect.Effect;
|
||||
import com.jozufozu.flywheel.backend.instancing.effect.EffectInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.BlockEntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.EffectInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.EntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.task.ParallelTaskExecutor;
|
||||
import com.jozufozu.flywheel.extension.ClientLevelExtension;
|
||||
|
||||
|
@ -6,8 +6,10 @@ import com.jozufozu.flywheel.api.backend.BackendManager;
|
||||
import com.jozufozu.flywheel.api.event.BeginFrameEvent;
|
||||
import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.RenderStageEvent;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.effect.Effect;
|
||||
import com.jozufozu.flywheel.backend.BackendUtil;
|
||||
import com.jozufozu.flywheel.backend.instancing.effect.Effect;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.InstanceManager;
|
||||
import com.jozufozu.flywheel.config.FlwCommands;
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
import com.jozufozu.flywheel.util.AnimationTickHolder;
|
||||
@ -26,7 +28,7 @@ public class InstancedRenderDispatcher {
|
||||
private static final WorldAttached<InstanceWorld> instanceWorlds = new WorldAttached<>(InstanceWorld::create);
|
||||
|
||||
/**
|
||||
* Call this when you want to manually run {@link AbstractInstance#update()}.
|
||||
* Call this when you want to manually run {@link Instance#update()}.
|
||||
* @param blockEntity The block entity whose instance you want to update.
|
||||
*/
|
||||
public static void enqueueUpdate(BlockEntity blockEntity) {
|
||||
@ -38,7 +40,7 @@ public class InstancedRenderDispatcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this when you want to manually run {@link AbstractInstance#update()}.
|
||||
* Call this when you want to manually run {@link Instance#update()}.
|
||||
* @param entity The entity whose instance you want to update.
|
||||
*/
|
||||
public static void enqueueUpdate(Entity entity) {
|
||||
@ -118,7 +120,7 @@ public class InstancedRenderDispatcher {
|
||||
InstanceWorld instanceWorld = instanceWorlds.get(Minecraft.getInstance().level);
|
||||
|
||||
debug.add("Update limiting: " + FlwCommands.boolToText(FlwConfig.get().limitUpdates()).getString());
|
||||
debug.add("B: " + instanceWorld.blockEntities.getObjectCount() + ", E: " + instanceWorld.entities.getObjectCount());
|
||||
debug.add("B: " + instanceWorld.blockEntities.getInstanceCount() + ", E: " + instanceWorld.entities.getInstanceCount());
|
||||
instanceWorld.engine.addDebugInfo(debug);
|
||||
} else {
|
||||
debug.add("Disabled");
|
||||
|
@ -1,11 +0,0 @@
|
||||
package com.jozufozu.flywheel.backend.instancing.effect;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
|
||||
public interface Effect {
|
||||
|
||||
Collection<AbstractInstance> createInstances(InstancerProvider instancerManager);
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package com.jozufozu.flywheel.backend.instancing.entity;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.BackendUtil;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class EntityInstanceManager extends InstanceManager<Entity> {
|
||||
|
||||
private final One2OneStorage<Entity> storage;
|
||||
|
||||
public EntityInstanceManager(InstancerProvider instancerManager) {
|
||||
storage = new One2OneStorage<>(instancerManager) {
|
||||
@Override
|
||||
protected @Nullable AbstractInstance createRaw(Entity obj) {
|
||||
return InstancedRenderRegistry.createInstance(this.instancerManager, obj);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public One2OneStorage<Entity> getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canCreateInstance(Entity entity) {
|
||||
if (!entity.isAlive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InstancedRenderRegistry.canInstance(entity.getType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Level level = entity.level;
|
||||
|
||||
return BackendUtil.isFlywheelLevel(level);
|
||||
}
|
||||
}
|
@ -1,14 +1,16 @@
|
||||
package com.jozufozu.flywheel.backend.instancing.blockentity;
|
||||
package com.jozufozu.flywheel.backend.instancing.manager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.BackendUtil;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
|
||||
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
|
||||
import com.jozufozu.flywheel.lib.instance.InstancingControllerHelper;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
@ -18,7 +20,6 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
|
||||
|
||||
private final BlockEntityStorage storage;
|
||||
|
||||
public BlockEntityInstanceManager(InstancerProvider instancerManager) {
|
||||
@ -26,7 +27,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Storage<BlockEntity> getStorage() {
|
||||
protected Storage<BlockEntity> getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
@ -43,7 +44,7 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InstancedRenderRegistry.canInstance(blockEntity.getType())) {
|
||||
if (!InstancingControllerHelper.canInstance(blockEntity.getType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -68,18 +69,17 @@ public class BlockEntityInstanceManager extends InstanceManager<BlockEntity> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class BlockEntityStorage extends One2OneStorage<BlockEntity> {
|
||||
private static class BlockEntityStorage extends One2OneStorage<BlockEntity> {
|
||||
private final Long2ObjectMap<BlockEntityInstance<?>> posLookup = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
final Long2ObjectMap<BlockEntityInstance<?>> posLookup = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
|
||||
public BlockEntityStorage(InstancerProvider manager) {
|
||||
super(manager);
|
||||
public BlockEntityStorage(InstancerProvider instancerManager) {
|
||||
super(instancerManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractInstance createRaw(BlockEntity obj) {
|
||||
var instance = InstancedRenderRegistry.createInstance(instancerManager, obj);
|
||||
@Nullable
|
||||
protected Instance createRaw(BlockEntity obj) {
|
||||
BlockEntityInstance<?> instance = InstancingControllerHelper.createInstance(instancerManager, obj);
|
||||
|
||||
if (instance != null) {
|
||||
BlockPos blockPos = obj.getBlockPos();
|
@ -1,18 +1,16 @@
|
||||
package com.jozufozu.flywheel.backend.instancing.effect;
|
||||
package com.jozufozu.flywheel.backend.instancing.manager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.effect.Effect;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.storage.AbstractStorage;
|
||||
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
|
||||
import com.jozufozu.flywheel.lib.light.LightUpdater;
|
||||
|
||||
public class EffectInstanceManager extends InstanceManager<Effect> {
|
||||
|
||||
private final EffectStorage<Effect> storage;
|
||||
|
||||
public EffectInstanceManager(InstancerProvider instancerManager) {
|
||||
@ -20,7 +18,7 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Storage<Effect> getStorage() {
|
||||
protected Storage<Effect> getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
@ -29,9 +27,8 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class EffectStorage<T extends Effect> extends AbstractStorage<T> {
|
||||
|
||||
private final Multimap<T, AbstractInstance> instances;
|
||||
private static class EffectStorage<T extends Effect> extends AbstractStorage<T> {
|
||||
private final Multimap<T, Instance> instances;
|
||||
|
||||
public EffectStorage(InstancerProvider manager) {
|
||||
super(manager);
|
||||
@ -39,21 +36,13 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getObjectCount() {
|
||||
return instances.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AbstractInstance> allInstances() {
|
||||
public Iterable<Instance> getAllInstances() {
|
||||
return instances.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
instances.values().forEach(AbstractInstance::removeAndMark);
|
||||
instances.clear();
|
||||
tickableInstances.clear();
|
||||
dynamicInstances.clear();
|
||||
public int getInstanceCount() {
|
||||
return instances.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -75,9 +64,8 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
|
||||
|
||||
this.tickableInstances.removeAll(instances);
|
||||
this.dynamicInstances.removeAll(instances);
|
||||
for (AbstractInstance instance : instances) {
|
||||
LightUpdater.get(instance.level)
|
||||
.removeListener(instance);
|
||||
for (Instance instance : instances) {
|
||||
instance.removeNow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,20 +77,28 @@ public class EffectInstanceManager extends InstanceManager<Effect> {
|
||||
return;
|
||||
}
|
||||
|
||||
instances.forEach(AbstractInstance::update);
|
||||
instances.forEach(Instance::update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recreateAll() {
|
||||
this.dynamicInstances.clear();
|
||||
this.tickableInstances.clear();
|
||||
this.instances.values().forEach(AbstractInstance::removeAndMark);
|
||||
tickableInstances.clear();
|
||||
dynamicInstances.clear();
|
||||
instances.values().forEach(Instance::delete);
|
||||
|
||||
var backup = new ArrayList<>(this.instances.keySet());
|
||||
this.instances.clear();
|
||||
var backup = new ArrayList<>(instances.keySet());
|
||||
instances.clear();
|
||||
backup.forEach(this::create);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
instances.values().forEach(Instance::delete);
|
||||
instances.clear();
|
||||
tickableInstances.clear();
|
||||
dynamicInstances.clear();
|
||||
}
|
||||
|
||||
private void create(T obj) {
|
||||
var instances = obj.createInstances(instancerManager);
|
||||
|
@ -0,0 +1,53 @@
|
||||
package com.jozufozu.flywheel.backend.instancing.manager;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.BackendUtil;
|
||||
import com.jozufozu.flywheel.backend.instancing.storage.One2OneStorage;
|
||||
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
|
||||
import com.jozufozu.flywheel.lib.instance.InstancingControllerHelper;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
public class EntityInstanceManager extends InstanceManager<Entity> {
|
||||
private final EntityStorage storage;
|
||||
|
||||
public EntityInstanceManager(InstancerProvider instancerManager) {
|
||||
storage = new EntityStorage(instancerManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Storage<Entity> getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canCreateInstance(Entity entity) {
|
||||
if (!entity.isAlive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InstancingControllerHelper.canInstance(entity.getType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Level level = entity.level;
|
||||
|
||||
return BackendUtil.isFlywheelLevel(level);
|
||||
}
|
||||
|
||||
private static class EntityStorage extends One2OneStorage<Entity> {
|
||||
public EntityStorage(InstancerProvider instancerManager) {
|
||||
super(instancerManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected Instance createRaw(Entity obj) {
|
||||
return InstancingControllerHelper.createInstance(instancerManager, obj);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.jozufozu.flywheel.backend.instancing;
|
||||
package com.jozufozu.flywheel.backend.instancing.manager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -12,6 +12,7 @@ import org.joml.FrustumIntersection;
|
||||
import com.jozufozu.flywheel.api.backend.BackendManager;
|
||||
import com.jozufozu.flywheel.api.event.RenderContext;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.task.TaskExecutor;
|
||||
import com.jozufozu.flywheel.backend.instancing.ratelimit.BandedPrimeLimiter;
|
||||
@ -19,33 +20,28 @@ import com.jozufozu.flywheel.backend.instancing.ratelimit.DistanceUpdateLimiter;
|
||||
import com.jozufozu.flywheel.backend.instancing.ratelimit.NonLimiter;
|
||||
import com.jozufozu.flywheel.backend.instancing.storage.Storage;
|
||||
import com.jozufozu.flywheel.config.FlwConfig;
|
||||
import com.jozufozu.flywheel.lib.light.LightUpdater;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
public abstract class InstanceManager<T> {
|
||||
private final Set<T> queuedAdditions = new HashSet<>(64);
|
||||
private final Set<T> queuedUpdates = new HashSet<>(64);
|
||||
|
||||
private final Set<T> queuedAdditions;
|
||||
private final Set<T> queuedUpdates;
|
||||
|
||||
protected DistanceUpdateLimiter frame;
|
||||
protected DistanceUpdateLimiter tick;
|
||||
protected DistanceUpdateLimiter frameLimiter;
|
||||
protected DistanceUpdateLimiter tickLimiter;
|
||||
|
||||
public InstanceManager() {
|
||||
this.queuedUpdates = new HashSet<>(64);
|
||||
this.queuedAdditions = new HashSet<>(64);
|
||||
|
||||
frame = createUpdateLimiter();
|
||||
tick = createUpdateLimiter();
|
||||
frameLimiter = createUpdateLimiter();
|
||||
tickLimiter = createUpdateLimiter();
|
||||
}
|
||||
|
||||
public abstract Storage<T> getStorage();
|
||||
protected abstract Storage<T> getStorage();
|
||||
|
||||
/**
|
||||
* Is the given object currently capable of being instanced?
|
||||
*
|
||||
* <p>
|
||||
* This won't be the case for TEs or entities that are outside of loaded chunks.
|
||||
* This won't be the case for block entities or entities that are outside of loaded chunks.
|
||||
* </p>
|
||||
*
|
||||
* @return true if the object is currently capable of being instanced.
|
||||
@ -65,102 +61,8 @@ public abstract class InstanceManager<T> {
|
||||
*
|
||||
* @return The object count.
|
||||
*/
|
||||
public int getObjectCount() {
|
||||
return getStorage().getObjectCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ticks the InstanceManager.
|
||||
*
|
||||
* <p>
|
||||
* {@link TickableInstance}s get ticked.
|
||||
* <br>
|
||||
* Queued updates are processed.
|
||||
* </p>
|
||||
*/
|
||||
public void tick(TaskExecutor executor, double cameraX, double cameraY, double cameraZ) {
|
||||
tick.tick();
|
||||
processQueuedUpdates();
|
||||
|
||||
// integer camera pos as a micro-optimization
|
||||
int cX = (int) cameraX;
|
||||
int cY = (int) cameraY;
|
||||
int cZ = (int) cameraZ;
|
||||
|
||||
var instances = getStorage().getInstancesForTicking();
|
||||
distributeWork(executor, instances, instance -> tickInstance(instance, cX, cY, cZ));
|
||||
}
|
||||
|
||||
protected void tickInstance(TickableInstance instance, int cX, int cY, int cZ) {
|
||||
if (!instance.decreaseTickRateWithDistance()) {
|
||||
instance.tick();
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos pos = instance.getWorldPosition();
|
||||
|
||||
int dX = pos.getX() - cX;
|
||||
int dY = pos.getY() - cY;
|
||||
int dZ = pos.getZ() - cZ;
|
||||
|
||||
if (!tick.shouldUpdate(dX, dY, dZ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
instance.tick();
|
||||
}
|
||||
|
||||
public void beginFrame(TaskExecutor executor, RenderContext context) {
|
||||
frame.tick();
|
||||
processQueuedAdditions();
|
||||
|
||||
// integer camera pos
|
||||
BlockPos cameraIntPos = context.camera().getBlockPosition();
|
||||
int cX = cameraIntPos.getX();
|
||||
int cY = cameraIntPos.getY();
|
||||
int cZ = cameraIntPos.getZ();
|
||||
FrustumIntersection culler = context.culler();
|
||||
|
||||
var instances = getStorage().getInstancesForUpdate();
|
||||
distributeWork(executor, instances, instance -> updateInstance(instance, culler, cX, cY, cZ));
|
||||
}
|
||||
|
||||
private static <I> void distributeWork(TaskExecutor executor, List<I> instances, Consumer<I> action) {
|
||||
final int size = instances.size();
|
||||
final int threadCount = executor.getThreadCount();
|
||||
|
||||
if (threadCount == 1) {
|
||||
executor.execute(() -> instances.forEach(action));
|
||||
} else {
|
||||
final int stride = Math.max(size / (threadCount * 2), 1);
|
||||
for (int start = 0; start < size; start += stride) {
|
||||
int end = Math.min(start + stride, size);
|
||||
|
||||
var sub = instances.subList(start, end);
|
||||
executor.execute(() -> sub.forEach(action));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateInstance(DynamicInstance dyn, FrustumIntersection test, int cX, int cY, int cZ) {
|
||||
if (!dyn.decreaseFramerateWithDistance()) {
|
||||
dyn.beginFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos worldPos = dyn.getWorldPosition();
|
||||
int dX = worldPos.getX() - cX;
|
||||
int dY = worldPos.getY() - cY;
|
||||
int dZ = worldPos.getZ() - cZ;
|
||||
|
||||
if (!frame.shouldUpdate(dX, dY, dZ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dyn.checkFrustum(test)) {
|
||||
dyn.beginFrame();
|
||||
}
|
||||
|
||||
public int getInstanceCount() {
|
||||
return getStorage().getInstanceCount();
|
||||
}
|
||||
|
||||
public void add(T obj) {
|
||||
@ -185,15 +87,13 @@ public abstract class InstanceManager<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void queueUpdate(T obj) {
|
||||
if (!BackendManager.isOn()) return;
|
||||
|
||||
if (!canCreateInstance(obj)) {
|
||||
public void queueAddAll(Collection<? extends T> objects) {
|
||||
if (!BackendManager.isOn() || objects.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (queuedUpdates) {
|
||||
queuedUpdates.add(obj);
|
||||
synchronized (queuedAdditions) {
|
||||
queuedAdditions.addAll(objects);
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,16 +116,38 @@ public abstract class InstanceManager<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void queueUpdate(T obj) {
|
||||
if (!BackendManager.isOn()) return;
|
||||
|
||||
if (!canCreateInstance(obj)) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (queuedUpdates) {
|
||||
queuedUpdates.add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(T obj) {
|
||||
if (!BackendManager.isOn()) return;
|
||||
|
||||
getStorage().remove(obj);
|
||||
}
|
||||
|
||||
public void onOriginShift() {
|
||||
getStorage().recreateAll();
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
getStorage().invalidate();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
for (Instance instance : getStorage().getAllInstances()) {
|
||||
instance.removeNow();
|
||||
}
|
||||
}
|
||||
|
||||
protected void processQueuedAdditions() {
|
||||
if (queuedAdditions.isEmpty()) {
|
||||
return;
|
||||
@ -256,23 +178,96 @@ public abstract class InstanceManager<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void onOriginShift() {
|
||||
getStorage().recreateAll();
|
||||
/**
|
||||
* Ticks the InstanceManager.
|
||||
*
|
||||
* <p>
|
||||
* {@link TickableInstance}s get ticked.
|
||||
* <br>
|
||||
* Queued updates are processed.
|
||||
* </p>
|
||||
*/
|
||||
public void tick(TaskExecutor executor, double cameraX, double cameraY, double cameraZ) {
|
||||
tickLimiter.tick();
|
||||
processQueuedUpdates();
|
||||
|
||||
// integer camera pos as a micro-optimization
|
||||
int cX = (int) cameraX;
|
||||
int cY = (int) cameraY;
|
||||
int cZ = (int) cameraZ;
|
||||
|
||||
var instances = getStorage().getInstancesForTicking();
|
||||
distributeWork(executor, instances, instance -> tickInstance(instance, cX, cY, cZ));
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
for (AbstractInstance value : getStorage().allInstances()) {
|
||||
LightUpdater.get(value.level).removeListener(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void queueAddAll(Collection<? extends T> objects) {
|
||||
if (!BackendManager.isOn() || objects.isEmpty()) {
|
||||
protected void tickInstance(TickableInstance instance, int cX, int cY, int cZ) {
|
||||
if (!instance.decreaseTickRateWithDistance()) {
|
||||
instance.tick();
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (queuedAdditions) {
|
||||
queuedAdditions.addAll(objects);
|
||||
BlockPos pos = instance.getWorldPosition();
|
||||
|
||||
int dX = pos.getX() - cX;
|
||||
int dY = pos.getY() - cY;
|
||||
int dZ = pos.getZ() - cZ;
|
||||
|
||||
if (!tickLimiter.shouldUpdate(dX, dY, dZ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
instance.tick();
|
||||
}
|
||||
|
||||
public void beginFrame(TaskExecutor executor, RenderContext context) {
|
||||
frameLimiter.tick();
|
||||
processQueuedAdditions();
|
||||
|
||||
// integer camera pos
|
||||
BlockPos cameraIntPos = context.camera().getBlockPosition();
|
||||
int cX = cameraIntPos.getX();
|
||||
int cY = cameraIntPos.getY();
|
||||
int cZ = cameraIntPos.getZ();
|
||||
FrustumIntersection culler = context.culler();
|
||||
|
||||
var instances = getStorage().getInstancesForUpdate();
|
||||
distributeWork(executor, instances, instance -> updateInstance(instance, culler, cX, cY, cZ));
|
||||
}
|
||||
|
||||
private static <I> void distributeWork(TaskExecutor executor, List<I> instances, Consumer<I> action) {
|
||||
final int size = instances.size();
|
||||
final int threadCount = executor.getThreadCount();
|
||||
|
||||
if (threadCount == 1) {
|
||||
executor.execute(() -> instances.forEach(action));
|
||||
} else {
|
||||
final int stride = Math.max(size / (threadCount * 2), 1);
|
||||
for (int start = 0; start < size; start += stride) {
|
||||
int end = Math.min(start + stride, size);
|
||||
|
||||
var sub = instances.subList(start, end);
|
||||
executor.execute(() -> sub.forEach(action));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateInstance(DynamicInstance instance, FrustumIntersection frustum, int cX, int cY, int cZ) {
|
||||
if (!instance.decreaseFramerateWithDistance()) {
|
||||
instance.beginFrame();
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos worldPos = instance.getWorldPosition();
|
||||
int dX = worldPos.getX() - cX;
|
||||
int dY = worldPos.getY() - cY;
|
||||
int dZ = worldPos.getZ() - cZ;
|
||||
|
||||
if (!frameLimiter.shouldUpdate(dX, dY, dZ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance.checkFrustum(frustum)) {
|
||||
instance.beginFrame();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import net.minecraft.util.Mth;
|
||||
|
||||
public class BandedPrimeLimiter implements DistanceUpdateLimiter {
|
||||
// 1 followed by the prime numbers
|
||||
private static final int[] divisorSequence = new int[] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
|
||||
private static final int[] DIVISOR_SEQUENCE = new int[] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 };
|
||||
|
||||
private int tickCount = 0;
|
||||
|
||||
@ -23,6 +23,6 @@ public class BandedPrimeLimiter implements DistanceUpdateLimiter {
|
||||
|
||||
int i = (dSq / 2048);
|
||||
|
||||
return divisorSequence[Mth.clamp(i, 0, divisorSequence.length - 1)];
|
||||
return DIVISOR_SEQUENCE[Mth.clamp(i, 0, DIVISOR_SEQUENCE.length - 1)];
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package com.jozufozu.flywheel.backend.instancing.ratelimit;
|
||||
public class NonLimiter implements DistanceUpdateLimiter {
|
||||
@Override
|
||||
public void tick() {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,21 +4,17 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.lib.light.LightUpdater;
|
||||
|
||||
public abstract class AbstractStorage<T> implements Storage<T> {
|
||||
protected final List<TickableInstance> tickableInstances;
|
||||
protected final List<DynamicInstance> dynamicInstances;
|
||||
protected final InstancerProvider instancerManager;
|
||||
protected final List<TickableInstance> tickableInstances = new ArrayList<>();
|
||||
protected final List<DynamicInstance> dynamicInstances = new ArrayList<>();
|
||||
|
||||
protected AbstractStorage(InstancerProvider instancerManager) {
|
||||
this.instancerManager = instancerManager;
|
||||
|
||||
this.dynamicInstances = new ArrayList<>();
|
||||
this.tickableInstances = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -31,19 +27,17 @@ public abstract class AbstractStorage<T> implements Storage<T> {
|
||||
return dynamicInstances;
|
||||
}
|
||||
|
||||
protected void setup(AbstractInstance renderer) {
|
||||
renderer.init();
|
||||
renderer.updateLight();
|
||||
LightUpdater.get(renderer.level)
|
||||
.addListener(renderer);
|
||||
if (renderer instanceof TickableInstance r) {
|
||||
tickableInstances.add(r);
|
||||
r.tick();
|
||||
protected void setup(Instance instance) {
|
||||
instance.init();
|
||||
|
||||
if (instance instanceof TickableInstance tickable) {
|
||||
tickableInstances.add(tickable);
|
||||
tickable.tick();
|
||||
}
|
||||
|
||||
if (renderer instanceof DynamicInstance r) {
|
||||
dynamicInstances.add(r);
|
||||
r.beginFrame();
|
||||
if (instance instanceof DynamicInstance dynamic) {
|
||||
dynamicInstances.add(dynamic);
|
||||
dynamic.beginFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,11 @@ import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.lib.light.LightUpdater;
|
||||
|
||||
public abstract class One2OneStorage<T> extends AbstractStorage<T> {
|
||||
private final Map<T, AbstractInstance> instances;
|
||||
private final Map<T, Instance> instances;
|
||||
|
||||
public One2OneStorage(InstancerProvider instancerManager) {
|
||||
super(instancerManager);
|
||||
@ -18,26 +17,18 @@ public abstract class One2OneStorage<T> extends AbstractStorage<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getObjectCount() {
|
||||
return instances.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AbstractInstance> allInstances() {
|
||||
public Iterable<Instance> getAllInstances() {
|
||||
return instances.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
instances.values().forEach(AbstractInstance::remove);
|
||||
instances.clear();
|
||||
dynamicInstances.clear();
|
||||
tickableInstances.clear();
|
||||
public int getInstanceCount() {
|
||||
return instances.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(T obj) {
|
||||
AbstractInstance instance = instances.get(obj);
|
||||
Instance instance = instances.get(obj);
|
||||
|
||||
if (instance == null) {
|
||||
create(obj);
|
||||
@ -46,22 +37,21 @@ public abstract class One2OneStorage<T> extends AbstractStorage<T> {
|
||||
|
||||
@Override
|
||||
public void remove(T obj) {
|
||||
var instance = instances.remove(obj);
|
||||
Instance instance = instances.remove(obj);
|
||||
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
instance.remove();
|
||||
instance.delete();
|
||||
dynamicInstances.remove(instance);
|
||||
tickableInstances.remove(instance);
|
||||
LightUpdater.get(instance.level)
|
||||
.removeListener(instance);
|
||||
instance.removeNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(T obj) {
|
||||
AbstractInstance instance = instances.get(obj);
|
||||
Instance instance = instances.get(obj);
|
||||
|
||||
if (instance == null) {
|
||||
return;
|
||||
@ -83,9 +73,9 @@ public abstract class One2OneStorage<T> extends AbstractStorage<T> {
|
||||
dynamicInstances.clear();
|
||||
tickableInstances.clear();
|
||||
instances.replaceAll((obj, instance) -> {
|
||||
instance.remove();
|
||||
instance.delete();
|
||||
|
||||
AbstractInstance out = createRaw(obj);
|
||||
Instance out = createRaw(obj);
|
||||
|
||||
if (out != null) {
|
||||
setup(out);
|
||||
@ -95,16 +85,23 @@ public abstract class One2OneStorage<T> extends AbstractStorage<T> {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
instances.values().forEach(Instance::delete);
|
||||
instances.clear();
|
||||
tickableInstances.clear();
|
||||
dynamicInstances.clear();
|
||||
}
|
||||
|
||||
private void create(T obj) {
|
||||
AbstractInstance renderer = createRaw(obj);
|
||||
Instance instance = createRaw(obj);
|
||||
|
||||
if (renderer != null) {
|
||||
setup(renderer);
|
||||
instances.put(obj, renderer);
|
||||
if (instance != null) {
|
||||
setup(instance);
|
||||
instances.put(obj, instance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract AbstractInstance createRaw(T obj);
|
||||
protected abstract Instance createRaw(T obj);
|
||||
}
|
||||
|
@ -3,20 +3,18 @@ package com.jozufozu.flywheel.backend.instancing.storage;
|
||||
import java.util.List;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
|
||||
public interface Storage<T> {
|
||||
int getObjectCount();
|
||||
Iterable<Instance> getAllInstances();
|
||||
|
||||
Iterable<AbstractInstance> allInstances();
|
||||
int getInstanceCount();
|
||||
|
||||
List<TickableInstance> getInstancesForTicking();
|
||||
|
||||
List<DynamicInstance> getInstancesForUpdate();
|
||||
|
||||
void invalidate();
|
||||
|
||||
void add(T obj);
|
||||
|
||||
void remove(T obj);
|
||||
@ -24,4 +22,6 @@ public interface Storage<T> {
|
||||
void update(T obj);
|
||||
|
||||
void recreateAll();
|
||||
|
||||
void invalidate();
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ public class SerialTaskExecutor implements TaskExecutor {
|
||||
|
||||
@Override
|
||||
public void syncPoint() {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,7 +63,7 @@ public class FlwCommands {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (player != null) {
|
||||
Backend backend = context.getArgument("id", Backend.class);
|
||||
value.set(Backend.REGISTRY.getId(backend).toString());
|
||||
value.set(Backend.REGISTRY.getIdOrThrow(backend).toString());
|
||||
|
||||
Component message = backend.getEngineMessage();
|
||||
player.displayClientMessage(message, false);
|
||||
|
@ -24,10 +24,9 @@ public class FlwConfig {
|
||||
private final ForgeConfigSpec clientSpec;
|
||||
|
||||
public FlwConfig() {
|
||||
Pair<ClientConfig, ForgeConfigSpec> client = new ForgeConfigSpec.Builder().configure(ClientConfig::new);
|
||||
|
||||
this.client = client.getLeft();
|
||||
clientSpec = client.getRight();
|
||||
Pair<ClientConfig, ForgeConfigSpec> clientPair = new ForgeConfigSpec.Builder().configure(ClientConfig::new);
|
||||
this.client = clientPair.getLeft();
|
||||
clientSpec = clientPair.getRight();
|
||||
}
|
||||
|
||||
public static FlwConfig get() {
|
||||
@ -38,7 +37,7 @@ public class FlwConfig {
|
||||
Backend backend = parseBackend(client.backend.get());
|
||||
if (backend == null) {
|
||||
backend = BackendManager.getDefaultBackend();
|
||||
client.backend.set(Backend.REGISTRY.getId(backend).toString());
|
||||
client.backend.set(Backend.REGISTRY.getIdOrThrow(backend).toString());
|
||||
}
|
||||
|
||||
return backend;
|
||||
@ -77,7 +76,7 @@ public class FlwConfig {
|
||||
|
||||
public ClientConfig(ForgeConfigSpec.Builder builder) {
|
||||
backend = builder.comment("Select the backend to use.")
|
||||
.define("backend", Backend.REGISTRY.getId(BackendManager.getDefaultBackend()).toString());
|
||||
.define("backend", Backend.REGISTRY.getIdOrThrow(BackendManager.getDefaultBackend()).toString());
|
||||
|
||||
limitUpdates = builder.comment("Enable or disable instance update limiting with distance.")
|
||||
.define("limitUpdates", true);
|
||||
|
@ -2,7 +2,7 @@ package com.jozufozu.flywheel.extension;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.BlockEntityInstancingController;
|
||||
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
||||
|
@ -2,7 +2,7 @@ package com.jozufozu.flywheel.extension;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.EntityInstancingController;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
|
@ -39,7 +39,7 @@ public final class BackendManagerImpl {
|
||||
var actual = preferred.findFallback();
|
||||
|
||||
if (preferred != actual) {
|
||||
LOGGER.warn("Flywheel backend fell back from '{}' to '{}'", Backend.REGISTRY.getId(preferred), Backend.REGISTRY.getId(actual));
|
||||
LOGGER.warn("Flywheel backend fell back from '{}' to '{}'", Backend.REGISTRY.getIdOrThrow(preferred), Backend.REGISTRY.getIdOrThrow(actual));
|
||||
}
|
||||
|
||||
return actual;
|
||||
|
@ -72,6 +72,24 @@ public class IdRegistryImpl<T> implements IdRegistry<T> {
|
||||
return reverseMap.get(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getOrThrow(ResourceLocation id) {
|
||||
T object = get(id);
|
||||
if (object == null) {
|
||||
throw new IllegalArgumentException("Could not find object for ID '" + id + "'!");
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getIdOrThrow(T object) {
|
||||
ResourceLocation id = getId(object);
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("Could not find ID for object!");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Unmodifiable
|
||||
public Set<ResourceLocation> getAllIds() {
|
||||
@ -107,6 +125,7 @@ public class IdRegistryImpl<T> implements IdRegistry<T> {
|
||||
for (Runnable runnable : freezeCallbacks) {
|
||||
runnable.run();
|
||||
}
|
||||
freezeCallbacks.clear();
|
||||
}
|
||||
|
||||
public static void freezeAll() {
|
||||
|
@ -91,6 +91,7 @@ public class RegistryImpl<T> implements Registry<T> {
|
||||
for (Runnable runnable : freezeCallbacks) {
|
||||
runnable.run();
|
||||
}
|
||||
freezeCallbacks.clear();
|
||||
}
|
||||
|
||||
public static void freezeAll() {
|
||||
|
@ -0,0 +1,37 @@
|
||||
package com.jozufozu.flywheel.impl.instance;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.controller.BlockEntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.EntityInstancingController;
|
||||
import com.jozufozu.flywheel.extension.BlockEntityTypeExtension;
|
||||
import com.jozufozu.flywheel.extension.EntityTypeExtension;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class InstancingControllerRegistryImpl {
|
||||
@Nullable
|
||||
public static <T extends BlockEntity> BlockEntityInstancingController<? super T> getController(BlockEntityType<T> type) {
|
||||
return ((BlockEntityTypeExtension<T>) type).flywheel$getInstancingController();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T extends Entity> EntityInstancingController<? super T> getController(EntityType<T> type) {
|
||||
return ((EntityTypeExtension<T>) type).flywheel$getInstancingController();
|
||||
}
|
||||
|
||||
public static <T extends BlockEntity> void setController(BlockEntityType<T> type, BlockEntityInstancingController<? super T> instancingController) {
|
||||
((BlockEntityTypeExtension<T>) type).flywheel$setInstancingController(instancingController);
|
||||
}
|
||||
|
||||
public static <T extends Entity> void setController(EntityType<T> type, EntityInstancingController<? super T> instancingController) {
|
||||
((EntityTypeExtension<T>) type).flywheel$setInstancingController(instancingController);
|
||||
}
|
||||
|
||||
private InstancingControllerRegistryImpl() {
|
||||
}
|
||||
}
|
@ -1,15 +1,16 @@
|
||||
package com.jozufozu.flywheel.backend.instancing.blockentity;
|
||||
package com.jozufozu.flywheel.lib.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.FrustumIntersection;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.BlockEntityInstanceManager;
|
||||
import com.jozufozu.flywheel.lib.box.ImmutableBox;
|
||||
import com.jozufozu.flywheel.lib.box.MutableBox;
|
||||
|
||||
@ -29,19 +30,19 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
* </ul>
|
||||
* See the interfaces' documentation for more information about each one.
|
||||
*
|
||||
* <br> Implementing one or more of these will give a {@link BlockEntityInstance} access
|
||||
* <br> Implementing one or more of these will give a {@link AbstractBlockEntityInstance} access
|
||||
* to more interesting and regular points within a tick or a frame.
|
||||
*
|
||||
* @param <T> The type of {@link BlockEntity} your class is an instance of.
|
||||
*/
|
||||
public abstract class BlockEntityInstance<T extends BlockEntity> extends AbstractInstance {
|
||||
public abstract class AbstractBlockEntityInstance<T extends BlockEntity> extends AbstractInstance implements BlockEntityInstance<T> {
|
||||
|
||||
protected final T blockEntity;
|
||||
protected final BlockPos pos;
|
||||
protected final BlockPos instancePos;
|
||||
protected final BlockState blockState;
|
||||
|
||||
public BlockEntityInstance(InstancerProvider instancerManager, T blockEntity) {
|
||||
public AbstractBlockEntityInstance(InstancerProvider instancerManager, T blockEntity) {
|
||||
super(instancerManager, blockEntity.getLevel());
|
||||
this.blockEntity = blockEntity;
|
||||
this.pos = blockEntity.getBlockPos();
|
||||
@ -49,6 +50,7 @@ public abstract class BlockEntityInstance<T extends BlockEntity> extends Abstrac
|
||||
this.instancePos = pos.subtract(instancerManager.getOriginCoordinate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InstancedPart> getCrumblingParts() {
|
||||
var out = new ArrayList<InstancedPart>();
|
||||
addCrumblingParts(out);
|
@ -1,14 +1,13 @@
|
||||
package com.jozufozu.flywheel.backend.instancing.entity;
|
||||
package com.jozufozu.flywheel.lib.instance;
|
||||
|
||||
import org.joml.FrustumIntersection;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.EntityInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
||||
import com.jozufozu.flywheel.backend.instancing.manager.BlockEntityInstanceManager;
|
||||
import com.jozufozu.flywheel.lib.box.MutableBox;
|
||||
import com.jozufozu.flywheel.lib.light.LightListener;
|
||||
import com.jozufozu.flywheel.lib.light.TickingLightListener;
|
||||
import com.mojang.math.Vector3f;
|
||||
|
||||
@ -30,17 +29,17 @@ import net.minecraft.world.phys.Vec3;
|
||||
* </ul>
|
||||
* See the interfaces' documentation for more information about each one.
|
||||
*
|
||||
* <br> Implementing one or more of these will give a {@link EntityInstance} access
|
||||
* <br> Implementing one or more of these will give a {@link AbstractEntityInstance} access
|
||||
* to more interesting and regular points within a tick or a frame.
|
||||
*
|
||||
* @param <E> The type of {@link Entity} your class is an instance of.
|
||||
*/
|
||||
public abstract class EntityInstance<E extends Entity> extends AbstractInstance implements LightListener, TickingLightListener {
|
||||
public abstract class AbstractEntityInstance<E extends Entity> extends AbstractInstance implements EntityInstance<E>, TickingLightListener {
|
||||
|
||||
protected final E entity;
|
||||
protected final MutableBox bounds;
|
||||
|
||||
public EntityInstance(InstancerProvider instancerManager, E entity) {
|
||||
public AbstractEntityInstance(InstancerProvider instancerManager, E entity) {
|
||||
super(instancerManager, entity.level);
|
||||
this.entity = entity;
|
||||
bounds = MutableBox.from(entity.getBoundingBox());
|
@ -1,66 +1,44 @@
|
||||
package com.jozufozu.flywheel.backend.instancing;
|
||||
package com.jozufozu.flywheel.lib.instance;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.Instance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.FlatLit;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager;
|
||||
import com.jozufozu.flywheel.lib.light.LightListener;
|
||||
import com.jozufozu.flywheel.lib.light.LightUpdater;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
|
||||
/**
|
||||
* A general interface providing information about any type of thing that could use Flywheel's instanced rendering.
|
||||
* Right now, that's only {@link BlockEntityInstanceManager}, but there could be an entity equivalent in the future.
|
||||
*/
|
||||
public abstract class AbstractInstance implements Instance, LightListener {
|
||||
|
||||
protected final InstancerProvider instancerManager;
|
||||
public final Level level;
|
||||
protected boolean removed = false;
|
||||
protected boolean deleted = false;
|
||||
|
||||
public AbstractInstance(InstancerProvider instancerManager, Level level) {
|
||||
this.instancerManager = instancerManager;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize models here.
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
updateLight();
|
||||
LightUpdater.get(level).addListener(this);
|
||||
}
|
||||
|
||||
public final void removeAndMark() {
|
||||
if (removed) {
|
||||
return;
|
||||
}
|
||||
|
||||
remove();
|
||||
removed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free any acquired resources.
|
||||
*/
|
||||
public abstract void remove();
|
||||
|
||||
/**
|
||||
* Update instance data here. Good for when data doesn't change very often and when animations are GPU based.
|
||||
* Don't query lighting data here, that's handled separately in {@link #updateLight()}.
|
||||
*
|
||||
* <br><br> If your animations are complex or more CPU driven, see {@link DynamicInstance} or {@link TickableInstance}.
|
||||
*/
|
||||
@Override
|
||||
public void update() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldReset() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after construction and when a light update occurs in the world.
|
||||
*
|
||||
@ -69,30 +47,21 @@ public abstract class AbstractInstance implements Instance, LightListener {
|
||||
public void updateLight() {
|
||||
}
|
||||
|
||||
/**
|
||||
* When an instance is reset, the instance is deleted and re-created.
|
||||
*
|
||||
* <p>
|
||||
* Just before {@link #update()} would be called, {@code shouldReset()} is checked.
|
||||
* If this function returns {@code true}, then this instance will be {@link #remove removed},
|
||||
* and another instance will be constructed to replace it. This allows for more sane resource
|
||||
* acquisition compared to trying to update everything within the lifetime of an instance.
|
||||
* </p>
|
||||
*
|
||||
* @return {@code true} if this instance should be discarded and refreshed.
|
||||
*/
|
||||
public boolean shouldReset() {
|
||||
return false;
|
||||
protected abstract void _delete();
|
||||
|
||||
@Override
|
||||
public final void delete() {
|
||||
if (deleted) {
|
||||
return;
|
||||
}
|
||||
|
||||
_delete();
|
||||
deleted = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalid() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoved() {
|
||||
return removed;
|
||||
return deleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -117,4 +86,8 @@ public abstract class AbstractInstance implements Instance, LightListener {
|
||||
.setSkyLight(sky));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void removeNow() {
|
||||
LightUpdater.get(level).removeListener(this);
|
||||
}
|
||||
}
|
@ -1,25 +1,20 @@
|
||||
package com.jozufozu.flywheel.api.instance;
|
||||
package com.jozufozu.flywheel.lib.instance;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.api.instance.EntityInstance;
|
||||
import com.jozufozu.flywheel.api.instance.controller.BlockEntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.EntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.InstancingControllerRegistry;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
|
||||
import com.jozufozu.flywheel.extension.BlockEntityTypeExtension;
|
||||
import com.jozufozu.flywheel.extension.EntityTypeExtension;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
|
||||
/**
|
||||
* A utility class for registering and retrieving {@code InstancingController}s.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class InstancedRenderRegistry {
|
||||
public final class InstancingControllerHelper {
|
||||
/**
|
||||
* Checks if the given block entity type can be instanced.
|
||||
* @param type The block entity type to check.
|
||||
@ -27,7 +22,7 @@ public class InstancedRenderRegistry {
|
||||
* @return {@code true} if the block entity type can be instanced.
|
||||
*/
|
||||
public static <T extends BlockEntity> boolean canInstance(BlockEntityType<? extends T> type) {
|
||||
return getController(type) != null;
|
||||
return InstancingControllerRegistry.getController(type) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,7 +32,7 @@ public class InstancedRenderRegistry {
|
||||
* @return {@code true} if the entity type can be instanced.
|
||||
*/
|
||||
public static <T extends Entity> boolean canInstance(EntityType<? extends T> type) {
|
||||
return getController(type) != null;
|
||||
return InstancingControllerRegistry.getController(type) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,7 +44,7 @@ public class InstancedRenderRegistry {
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends BlockEntity> BlockEntityInstance<? super T> createInstance(InstancerProvider instancerManager, T blockEntity) {
|
||||
BlockEntityInstancingController<? super T> controller = getController(getType(blockEntity));
|
||||
BlockEntityInstancingController<? super T> controller = InstancingControllerRegistry.getController(getType(blockEntity));
|
||||
if (controller == null) {
|
||||
return null;
|
||||
}
|
||||
@ -65,7 +60,7 @@ public class InstancedRenderRegistry {
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends Entity> EntityInstance<? super T> createInstance(InstancerProvider instancerManager, T entity) {
|
||||
EntityInstancingController<? super T> controller = getController(getType(entity));
|
||||
EntityInstancingController<? super T> controller = InstancingControllerRegistry.getController(getType(entity));
|
||||
if (controller == null) {
|
||||
return null;
|
||||
}
|
||||
@ -79,7 +74,7 @@ public class InstancedRenderRegistry {
|
||||
* @return {@code true} if the block entity is instanced and should not be rendered normally.
|
||||
*/
|
||||
public static <T extends BlockEntity> boolean shouldSkipRender(T blockEntity) {
|
||||
BlockEntityInstancingController<? super T> controller = getController(getType(blockEntity));
|
||||
BlockEntityInstancingController<? super T> controller = InstancingControllerRegistry.getController(getType(blockEntity));
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
@ -93,61 +88,20 @@ public class InstancedRenderRegistry {
|
||||
* @return {@code true} if the entity is instanced and should not be rendered normally.
|
||||
*/
|
||||
public static <T extends Entity> boolean shouldSkipRender(T entity) {
|
||||
EntityInstancingController<? super T> controller = getController(getType(entity));
|
||||
EntityInstancingController<? super T> controller = InstancingControllerRegistry.getController(getType(entity));
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return controller.shouldSkipRender(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instancing controller for the given block entity type, if one exists.
|
||||
* @param type The block entity type to get the instancing controller for.
|
||||
* @param <T> The type of the block entity.
|
||||
* @return The instancing controller for the given block entity type, or {@code null} if none exists.
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends BlockEntity> BlockEntityInstancingController<? super T> getController(BlockEntityType<T> type) {
|
||||
return ((BlockEntityTypeExtension<T>) type).flywheel$getInstancingController();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instancing controller for the given entity type, if one exists.
|
||||
* @param type The entity type to get the instancing controller for.
|
||||
* @param <T> The type of the entity.
|
||||
* @return The instancing controller for the given entity type, or {@code null} if none exists.
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends Entity> EntityInstancingController<? super T> getController(EntityType<T> type) {
|
||||
return ((EntityTypeExtension<T>) type).flywheel$getInstancingController();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the instancing controller for the given block entity type.
|
||||
* @param type The block entity type to set the instancing controller for.
|
||||
* @param instancingController The instancing controller to set.
|
||||
* @param <T> The type of the block entity.
|
||||
*/
|
||||
public static <T extends BlockEntity> void setController(BlockEntityType<T> type, BlockEntityInstancingController<? super T> instancingController) {
|
||||
((BlockEntityTypeExtension<T>) type).flywheel$setInstancingController(instancingController);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the instancing controller for the given entity type.
|
||||
* @param type The entity type to set the instancing controller for.
|
||||
* @param instancingController The instancing controller to set.
|
||||
* @param <T> The type of the entity.
|
||||
*/
|
||||
public static <T extends Entity> void setController(EntityType<T> type, EntityInstancingController<? super T> instancingController) {
|
||||
((EntityTypeExtension<T>) type).flywheel$setInstancingController(instancingController);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the given block entity.
|
||||
* @param blockEntity The block entity to get the type of.
|
||||
* @param <T> The type of the block entity.
|
||||
* @return The {@link BlockEntityType} associated with the given block entity.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends BlockEntity> BlockEntityType<? super T> getType(T blockEntity) {
|
||||
return (BlockEntityType<? super T>) blockEntity.getType();
|
||||
}
|
||||
@ -158,7 +112,11 @@ public class InstancedRenderRegistry {
|
||||
* @param <T> The type of the entity.
|
||||
* @return The {@link EntityType} associated with the given entity.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Entity> EntityType<? super T> getType(T entity) {
|
||||
return (EntityType<? super T>) entity.getType();
|
||||
}
|
||||
|
||||
private InstancingControllerHelper() {
|
||||
}
|
||||
}
|
@ -4,10 +4,10 @@ import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.api.instance.controller.BlockEntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.InstancingControllerRegistry;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
@ -93,7 +93,7 @@ public class SimpleBlockEntityInstancingController<T extends BlockEntity> implem
|
||||
skipRender = be -> false;
|
||||
}
|
||||
SimpleBlockEntityInstancingController<T> controller = new SimpleBlockEntityInstancingController<>(instanceFactory, skipRender);
|
||||
InstancedRenderRegistry.setController(type, controller);
|
||||
InstancingControllerRegistry.setController(type, controller);
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,10 @@ import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.EntityInstance;
|
||||
import com.jozufozu.flywheel.api.instance.controller.EntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.InstancingControllerRegistry;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
@ -93,7 +93,7 @@ public class SimpleEntityInstancingController<T extends Entity> implements Entit
|
||||
skipRender = entity -> false;
|
||||
}
|
||||
SimpleEntityInstancingController<T> controller = new SimpleEntityInstancingController<>(instanceFactory, skipRender);
|
||||
InstancedRenderRegistry.setController(type, controller);
|
||||
InstancingControllerRegistry.setController(type, controller);
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
// TODO: add messages to exceptions
|
||||
public class MaterialIndicies {
|
||||
private static Reference2IntMap<Material> materialIndicies;
|
||||
private static Object2IntMap<ResourceLocation> vertexShaderIndicies;
|
||||
private static Object2IntMap<ResourceLocation> fragmentShaderIndicies;
|
||||
public class MaterialIndices {
|
||||
private static Reference2IntMap<Material> materialIndices;
|
||||
private static Object2IntMap<ResourceLocation> vertexShaderIndices;
|
||||
private static Object2IntMap<ResourceLocation> fragmentShaderIndices;
|
||||
private static ObjectList<Material> materialsByIndex;
|
||||
private static ObjectList<ResourceLocation> vertexShadersByIndex;
|
||||
private static ObjectList<ResourceLocation> fragmentShadersByIndex;
|
||||
@ -34,21 +34,29 @@ public class MaterialIndicies {
|
||||
if (!initialized) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return materialIndicies.getInt(material);
|
||||
return materialIndices.getInt(material);
|
||||
}
|
||||
|
||||
public static int getVertexShaderIndex(ResourceLocation vertexShader) {
|
||||
if (!initialized) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return vertexShaderIndicies.getInt(vertexShader);
|
||||
return vertexShaderIndices.getInt(vertexShader);
|
||||
}
|
||||
|
||||
public static int getFragmentShaderIndex(ResourceLocation fragmentShader) {
|
||||
if (!initialized) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return fragmentShaderIndicies.getInt(fragmentShader);
|
||||
return fragmentShaderIndices.getInt(fragmentShader);
|
||||
}
|
||||
|
||||
public static int getVertexShaderIndex(Material material) {
|
||||
return getVertexShaderIndex(material.vertexShader());
|
||||
}
|
||||
|
||||
public static int getFragmentShaderIndex(Material material) {
|
||||
return getFragmentShaderIndex(material.fragmentShader());
|
||||
}
|
||||
|
||||
public static Material getMaterial(int index) {
|
||||
@ -99,9 +107,9 @@ public class MaterialIndicies {
|
||||
private static void initInner() {
|
||||
int amount = Material.REGISTRY.getAll().size();
|
||||
|
||||
Reference2IntMap<Material> materialIndicies = new Reference2IntOpenHashMap<>();
|
||||
Object2IntMap<ResourceLocation> vertexShaderIndicies = new Object2IntOpenHashMap<>();
|
||||
Object2IntMap<ResourceLocation> fragmentShaderIndicies = new Object2IntOpenHashMap<>();
|
||||
Reference2IntMap<Material> materialIndices = new Reference2IntOpenHashMap<>();
|
||||
Object2IntMap<ResourceLocation> vertexShaderIndices = new Object2IntOpenHashMap<>();
|
||||
Object2IntMap<ResourceLocation> fragmentShaderIndices = new Object2IntOpenHashMap<>();
|
||||
ObjectList<Material> materialsByIndex = new ObjectArrayList<>(amount);
|
||||
ObjectList<ResourceLocation> vertexShadersByIndex = new ObjectArrayList<>(amount);
|
||||
ObjectList<ResourceLocation> fragmentShadersByIndex = new ObjectArrayList<>(amount);
|
||||
@ -113,35 +121,35 @@ public class MaterialIndicies {
|
||||
int vertexShaderIndex = 0;
|
||||
int fragmentShaderIndex = 0;
|
||||
for (Material material : Material.REGISTRY) {
|
||||
materialIndicies.put(material, materialIndex);
|
||||
materialIndices.put(material, materialIndex);
|
||||
materialsByIndex.add(material);
|
||||
materialIndex++;
|
||||
ResourceLocation vertexShader = material.vertexShader();
|
||||
if (allVertexShaders.add(vertexShader)) {
|
||||
vertexShaderIndicies.put(vertexShader, vertexShaderIndex);
|
||||
vertexShaderIndices.put(vertexShader, vertexShaderIndex);
|
||||
vertexShadersByIndex.add(vertexShader);
|
||||
vertexShaderIndex++;
|
||||
}
|
||||
ResourceLocation fragmentShader = material.fragmentShader();
|
||||
if (allFragmentShaders.add(fragmentShader)) {
|
||||
fragmentShaderIndicies.put(fragmentShader, fragmentShaderIndex);
|
||||
fragmentShaderIndices.put(fragmentShader, fragmentShaderIndex);
|
||||
fragmentShadersByIndex.add(fragmentShader);
|
||||
fragmentShaderIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
MaterialIndicies.materialIndicies = Reference2IntMaps.unmodifiable(materialIndicies);
|
||||
MaterialIndicies.vertexShaderIndicies = Object2IntMaps.unmodifiable(vertexShaderIndicies);
|
||||
MaterialIndicies.fragmentShaderIndicies = Object2IntMaps.unmodifiable(fragmentShaderIndicies);
|
||||
MaterialIndicies.materialsByIndex = ObjectLists.unmodifiable(materialsByIndex);
|
||||
MaterialIndicies.vertexShadersByIndex = ObjectLists.unmodifiable(vertexShadersByIndex);
|
||||
MaterialIndicies.fragmentShadersByIndex = ObjectLists.unmodifiable(fragmentShadersByIndex);
|
||||
MaterialIndices.materialIndices = Reference2IntMaps.unmodifiable(materialIndices);
|
||||
MaterialIndices.vertexShaderIndices = Object2IntMaps.unmodifiable(vertexShaderIndices);
|
||||
MaterialIndices.fragmentShaderIndices = Object2IntMaps.unmodifiable(fragmentShaderIndices);
|
||||
MaterialIndices.materialsByIndex = ObjectLists.unmodifiable(materialsByIndex);
|
||||
MaterialIndices.vertexShadersByIndex = ObjectLists.unmodifiable(vertexShadersByIndex);
|
||||
MaterialIndices.fragmentShadersByIndex = ObjectLists.unmodifiable(fragmentShadersByIndex);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void init() {
|
||||
Material.REGISTRY.addFreezeCallback(MaterialIndicies::initInner);
|
||||
Material.REGISTRY.addFreezeCallback(MaterialIndices::initInner);
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.blockentity.BlockEntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.BlockEntityInstancingController;
|
||||
import com.jozufozu.flywheel.extension.BlockEntityTypeExtension;
|
||||
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
|
@ -10,8 +10,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jozufozu.flywheel.api.backend.BackendManager;
|
||||
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.extension.ClientLevelExtension;
|
||||
import com.jozufozu.flywheel.lib.instance.InstancingControllerHelper;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@ -33,7 +33,7 @@ public abstract class ClientLevelMixin implements ClientLevelExtension {
|
||||
Iterable<Entity> entities = cir.getReturnValue();
|
||||
ArrayList<Entity> filtered = Lists.newArrayList(entities);
|
||||
|
||||
filtered.removeIf(InstancedRenderRegistry::shouldSkipRender);
|
||||
filtered.removeIf(InstancingControllerHelper::shouldSkipRender);
|
||||
|
||||
cir.setReturnValue(filtered);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.entity.EntityInstancingController;
|
||||
import com.jozufozu.flywheel.api.instance.controller.EntityInstancingController;
|
||||
import com.jozufozu.flywheel.extension.EntityTypeExtension;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
@ -7,9 +7,9 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.jozufozu.flywheel.api.instance.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.backend.BackendUtil;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.lib.instance.InstancingControllerHelper;
|
||||
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
@ -19,10 +19,10 @@ public class ChunkRebuildHooksMixin {
|
||||
@Inject(method = "handleBlockEntity", at = @At("HEAD"), cancellable = true)
|
||||
private <E extends BlockEntity> void flywheel$addAndFilterBEs(ChunkRenderDispatcher.CompiledChunk compiledChunk, Set<BlockEntity> set, E be, CallbackInfo ci) {
|
||||
if (BackendUtil.canUseInstancing(be.getLevel())) {
|
||||
if (InstancedRenderRegistry.canInstance(be.getType()))
|
||||
if (InstancingControllerHelper.canInstance(be.getType()))
|
||||
InstancedRenderDispatcher.getBlockEntities(be.getLevel()).queueAdd(be);
|
||||
|
||||
if (InstancedRenderRegistry.shouldSkipRender(be))
|
||||
if (InstancingControllerHelper.shouldSkipRender(be))
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance;
|
||||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleLazyModel;
|
||||
import com.jozufozu.flywheel.lib.modelpart.ModelPart;
|
||||
@ -23,7 +23,7 @@ import net.minecraft.client.renderer.blockentity.BellRenderer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.block.entity.BellBlockEntity;
|
||||
|
||||
public class BellInstance extends BlockEntityInstance<BellBlockEntity> implements DynamicInstance {
|
||||
public class BellInstance extends AbstractBlockEntityInstance<BellBlockEntity> implements DynamicInstance {
|
||||
|
||||
private static final SimpleLazyModel MODEL = new SimpleLazyModel(BellInstance::createBellModel, Materials.BELL);
|
||||
|
||||
@ -68,7 +68,7 @@ public class BellInstance extends BlockEntityInstance<BellBlockEntity> implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
protected void _delete() {
|
||||
bell.delete();
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance;
|
||||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleLazyModel;
|
||||
import com.jozufozu.flywheel.lib.modelpart.ModelPart;
|
||||
@ -35,7 +35,7 @@ import net.minecraft.world.level.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.LidBlockEntity;
|
||||
import net.minecraft.world.level.block.state.properties.ChestType;
|
||||
|
||||
public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends BlockEntityInstance<T> implements DynamicInstance {
|
||||
public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends AbstractBlockEntityInstance<T> implements DynamicInstance {
|
||||
|
||||
private static final BiFunction<ChestType, TextureAtlasSprite, SimpleLazyModel> LID = Util.memoize((type, mat) -> new SimpleLazyModel(() -> createLidModel(type, mat), Materials.CHEST));
|
||||
private static final BiFunction<ChestType, TextureAtlasSprite, SimpleLazyModel> BASE = Util.memoize((type, mat) -> new SimpleLazyModel(() -> createBaseModel(type, mat), Materials.CHEST));
|
||||
@ -117,7 +117,7 @@ public class ChestInstance<T extends BlockEntity & LidBlockEntity> extends Block
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
protected void _delete() {
|
||||
body.delete();
|
||||
lid.delete();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.api.model.Mesh;
|
||||
import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance;
|
||||
import com.jozufozu.flywheel.lib.instance.AbstractEntityInstance;
|
||||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.Models;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleLazyModel;
|
||||
@ -26,7 +26,7 @@ import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance<T> implements DynamicInstance, TickableInstance {
|
||||
public class MinecartInstance<T extends AbstractMinecart> extends AbstractEntityInstance<T> implements DynamicInstance, TickableInstance {
|
||||
|
||||
private static final SimpleLazyModel MODEL = new SimpleLazyModel(MinecartInstance::getBodyModel, Materials.MINECART);
|
||||
|
||||
@ -150,7 +150,7 @@ public class MinecartInstance<T extends AbstractMinecart> extends EntityInstance
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
protected void _delete() {
|
||||
body.delete();
|
||||
if (contents != null) contents.delete();
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancedPart;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance;
|
||||
import com.jozufozu.flywheel.lib.instance.AbstractBlockEntityInstance;
|
||||
import com.jozufozu.flywheel.lib.material.Materials;
|
||||
import com.jozufozu.flywheel.lib.model.SimpleLazyModel;
|
||||
import com.jozufozu.flywheel.lib.modelpart.ModelPart;
|
||||
@ -28,7 +28,7 @@ import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.level.block.ShulkerBoxBlock;
|
||||
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
|
||||
|
||||
public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntity> implements DynamicInstance {
|
||||
public class ShulkerBoxInstance extends AbstractBlockEntityInstance<ShulkerBoxBlockEntity> implements DynamicInstance {
|
||||
|
||||
private static final Function<TextureAtlasSprite, SimpleLazyModel> BASE = Util.memoize(it -> new SimpleLazyModel(() -> makeBaseModel(it), Materials.SHULKER));
|
||||
private static final Function<TextureAtlasSprite, SimpleLazyModel> LID = Util.memoize(it -> new SimpleLazyModel(() -> makeLidModel(it), Materials.SHULKER));
|
||||
@ -95,7 +95,7 @@ public class ShulkerBoxInstance extends BlockEntityInstance<ShulkerBoxBlockEntit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
protected void _delete() {
|
||||
base.delete();
|
||||
lid.delete();
|
||||
}
|
||||
|
@ -12,12 +12,12 @@ import com.jozufozu.flywheel.api.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.api.event.RenderStage;
|
||||
import com.jozufozu.flywheel.api.instance.DynamicInstance;
|
||||
import com.jozufozu.flywheel.api.instance.TickableInstance;
|
||||
import com.jozufozu.flywheel.api.instance.effect.Effect;
|
||||
import com.jozufozu.flywheel.api.instancer.InstancerProvider;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstance;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.backend.instancing.effect.Effect;
|
||||
import com.jozufozu.flywheel.lib.box.ImmutableBox;
|
||||
import com.jozufozu.flywheel.lib.box.MutableBox;
|
||||
import com.jozufozu.flywheel.lib.instance.AbstractInstance;
|
||||
import com.jozufozu.flywheel.lib.model.Models;
|
||||
import com.jozufozu.flywheel.lib.struct.StructTypes;
|
||||
import com.jozufozu.flywheel.lib.struct.TransformedPart;
|
||||
@ -109,7 +109,7 @@ public class ExampleEffect implements Effect {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AbstractInstance> createInstances(InstancerProvider instancerManager) {
|
||||
public Collection<com.jozufozu.flywheel.api.instance.Instance> createInstances(InstancerProvider instancerManager) {
|
||||
effects.clear();
|
||||
boids.clear();
|
||||
for (int i = 0; i < INSTANCE_COUNT; i++) {
|
||||
@ -262,7 +262,7 @@ public class ExampleEffect implements Effect {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
protected void _delete() {
|
||||
instance.delete();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user