diff --git a/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java b/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java index 8a418247e..37b72652f 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java +++ b/src/main/java/com/jozufozu/flywheel/backend/RenderWork.java @@ -3,12 +3,13 @@ package com.jozufozu.flywheel.backend; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -@Mod.EventBusSubscriber +@Mod.EventBusSubscriber(value = Dist.CLIENT) public class RenderWork { private static final Queue runs = new ConcurrentLinkedQueue<>(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/IInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/IInstance.java index 3b3c6d304..599950823 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/IInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/IInstance.java @@ -1,5 +1,7 @@ package com.jozufozu.flywheel.backend.instancing; +import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; + import net.minecraft.util.math.BlockPos; /** diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 235814484..2a67adac9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -13,9 +13,10 @@ import java.util.Vector; import javax.annotation.Nonnull; import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import com.jozufozu.flywheel.core.Contexts; import com.jozufozu.flywheel.core.CrumblingInstanceManager; -import com.jozufozu.flywheel.core.shader.WorldProgram; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.ReloadRenderersEvent; import com.jozufozu.flywheel.event.RenderLayerEvent; @@ -38,15 +39,16 @@ import net.minecraft.util.LazyValue; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.world.IWorld; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -@Mod.EventBusSubscriber +@Mod.EventBusSubscriber(value = Dist.CLIENT) public class InstancedRenderDispatcher { - private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); - + private static final WorldAttached entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(Contexts.WORLD.getMaterialManager(world))); private static final WorldAttached tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(Contexts.WORLD.getMaterialManager(world))); + private static final LazyValue> blockBreaking = new LazyValue<>(() -> { Vector renderers = new Vector<>(10); for (int i = 0; i < 10; i++) { @@ -56,41 +58,49 @@ public class InstancedRenderDispatcher { }); @Nonnull - public static TileInstanceManager get(IWorld world) { + public static TileInstanceManager getTiles(IWorld world) { return tileInstanceManager.get(world); } + @Nonnull + public static EntityInstanceManager getEntities(IWorld world) { + return entityInstanceManager.get(world); + } + public static void tick() { Minecraft mc = Minecraft.getInstance(); ClientWorld world = mc.world; - TileInstanceManager instancer = get(world); - Entity renderViewEntity = mc.renderViewEntity; - instancer.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); + + if (renderViewEntity == null) return; + + getTiles(world).tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); + getEntities(world).tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); } public static void enqueueUpdate(TileEntity te) { - get(te.getWorld()).queueUpdate(te); + getTiles(te.getWorld()).queueUpdate(te); } @SubscribeEvent public static void onBeginFrame(BeginFrameEvent event) { Contexts.WORLD.getMaterialManager(event.getWorld()) .checkAndShiftOrigin(event.getInfo()); - get(event.getWorld()) - .beginFrame(event.getInfo()); + + getTiles(event.getWorld()).beginFrame(event.getInfo()); + getEntities(event.getWorld()).beginFrame(event.getInfo()); } @SubscribeEvent public static void renderLayer(RenderLayerEvent event) { ClientWorld world = event.getWorld(); if (!Backend.getInstance().canUseInstancing(world)) return; - MaterialManager materialManager = Contexts.WORLD.getMaterialManager(world); event.type.startDrawing(); - materialManager.render(event.type, event.viewProjection, event.camX, event.camY, event.camZ); + Contexts.WORLD.getMaterialManager(world) + .render(event.type, event.viewProjection, event.camX, event.camY, event.camZ); event.type.endDrawing(); } @@ -101,12 +111,18 @@ public class InstancedRenderDispatcher { if (Backend.getInstance().canUseInstancing() && world != null) { Contexts.WORLD.getMaterialManager(world).delete(); - TileInstanceManager tileRenderer = get(world); - tileRenderer.invalidate(); - world.loadedTileEntityList.forEach(tileRenderer::add); + TileInstanceManager tiles = getTiles(world); + tiles.invalidate(); + world.loadedTileEntityList.forEach(tiles::add); + + EntityInstanceManager entities = getEntities(world); + entities.invalidate(); + world.getAllEntities().forEach(entities::add); } } + private static final RenderType crumblingLayer = ModelBakery.BLOCK_DESTRUCTION_RENDER_LAYERS.get(0); + public static void renderBreaking(ClientWorld world, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { if (!Backend.getInstance().canUseInstancing(world)) return; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java index f88250fc9..381a47778 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java @@ -5,9 +5,15 @@ import java.util.Map; import javax.annotation.Nullable; import com.google.common.collect.Maps; +import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; +import com.jozufozu.flywheel.backend.instancing.entity.IEntityInstanceFactory; import com.jozufozu.flywheel.backend.instancing.tile.ITileInstanceFactory; import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueInstance; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; @@ -18,17 +24,38 @@ public class InstancedRenderRegistry { return INSTANCE; } - private final Map, ITileInstanceFactory> renderers = Maps.newHashMap(); + private final Map, ITileInstanceFactory> tiles = Maps.newHashMap(); + private final Map, IEntityInstanceFactory> entities = Maps.newHashMap(); public void register(TileEntityType type, ITileInstanceFactory rendererFactory) { - this.renderers.put(type, rendererFactory); + this.tiles.put(type, rendererFactory); + } + + public void register(EntityType type, IEntityInstanceFactory rendererFactory) { + this.entities.put(type, rendererFactory); + } + + + static { + INSTANCE.register(AllEntityTypes.SUPER_GLUE.get(), GlueInstance::new); } @SuppressWarnings("unchecked") @Nullable public TileEntityInstance create(MaterialManager manager, T tile) { TileEntityType type = tile.getType(); - ITileInstanceFactory factory = (ITileInstanceFactory) this.renderers.get(type); + ITileInstanceFactory factory = (ITileInstanceFactory) this.tiles.get(type); + + if (factory == null) return null; + else return factory.create(manager, tile); + } + + + @SuppressWarnings("unchecked") + @Nullable + public EntityInstance create(MaterialManager manager, T tile) { + EntityType type = tile.getType(); + IEntityInstanceFactory factory = (IEntityInstanceFactory) this.entities.get(type); if (factory == null) return null; else return factory.create(manager, tile); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java index a872d3a94..80c438853 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstance.java @@ -8,7 +8,7 @@ import com.jozufozu.flywheel.backend.instancing.IInstance; import com.jozufozu.flywheel.backend.instancing.ITickableInstance; import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; import com.jozufozu.flywheel.backend.instancing.MaterialManager; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import com.jozufozu.flywheel.core.materials.IFlatLight; import com.jozufozu.flywheel.core.materials.ModelData; import com.jozufozu.flywheel.core.materials.OrientedData; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java new file mode 100644 index 000000000..6345053d9 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java @@ -0,0 +1,272 @@ +package com.jozufozu.flywheel.backend.instancing.entity; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.ITickableInstance; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.World; + +public class EntityInstanceManager implements MaterialManager.OriginShiftListener { + + public final MaterialManager materialManager; + + protected final ArrayList queuedAdditions; + //protected final ConcurrentHashMap.KeySetView queuedUpdates; + + protected final Map> instances; + protected final Object2ObjectOpenHashMap tickableInstances; + protected final Object2ObjectOpenHashMap dynamicInstances; + + protected int frame; + protected int tick; + + public EntityInstanceManager(MaterialManager materialManager) { + this.materialManager = materialManager; + //this.queuedUpdates = ConcurrentHashMap.newKeySet(64); + this.queuedAdditions = new ArrayList<>(64); + this.instances = new HashMap<>(); + + this.dynamicInstances = new Object2ObjectOpenHashMap<>(); + this.tickableInstances = new Object2ObjectOpenHashMap<>(); + + materialManager.onOriginShift(this); + } + + public void tick(double cameraX, double cameraY, double cameraZ) { + tick++; + + // integer camera pos + int cX = (int) cameraX; + int cY = (int) cameraY; + int cZ = (int) cameraZ; + + if (tickableInstances.size() > 0) { + for (ITickableInstance instance : tickableInstances.values()) { + if (!instance.decreaseTickRateWithDistance()) { + instance.tick(); + continue; + } + + BlockPos pos = instance.getWorldPosition(); + + int dX = pos.getX() - cX; + int dY = pos.getY() - cY; + int dZ = pos.getZ() - cZ; + + if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) + instance.tick(); + } + } +// +// queuedUpdates.forEach(te -> { +// queuedUpdates.remove(te); +// +// update(te); +// }); + } + + public void beginFrame(ActiveRenderInfo info) { + frame++; + processQueuedAdditions(); + + Vector3f look = info.getHorizontalPlane(); + float lookX = look.getX(); + float lookY = look.getY(); + float lookZ = look.getZ(); + + // integer camera pos + int cX = (int) info.getProjectedView().x; + int cY = (int) info.getProjectedView().y; + int cZ = (int) info.getProjectedView().z; + + if (dynamicInstances.size() > 0) { + dynamicInstances.object2ObjectEntrySet().fastForEach(e -> { + IDynamicInstance dyn = e.getValue(); + if (!dyn.decreaseFramerateWithDistance() || shouldFrameUpdate(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ)) + dyn.beginFrame(); + }); + } + } + + @Override + public void onOriginShift() { + ArrayList instancedTiles = new ArrayList<>(instances.keySet()); + invalidate(); + instancedTiles.forEach(this::add); + } + + @SuppressWarnings("unchecked") + @Nullable + public EntityInstance getInstance(T entity, boolean create) { + if (!Backend.getInstance().canUseInstancing()) return null; + + EntityInstance instance = instances.get(entity); + + if (instance != null) { + return (EntityInstance) instance; + } else if (create && canCreateInstance(entity)) { + return createInternal(entity); + } else { + return null; + } + } + +// public void onLightUpdate(T tile) { +// if (!Backend.getInstance().canUseInstancing()) return; +// +// if (tile instanceof IInstanceRendered) { +// EntityInstance instance = getInstance(tile, false); +// +// if (instance != null) +// instance.updateLight(); +// } +// } + + public void add(T entity) { + if (!Backend.getInstance().canUseInstancing()) return; + + if (entity instanceof IInstanceRendered) { + addInternal(entity); + } + } + +// public void update(T tile) { +// if (!Backend.getInstance().canUseInstancing()) return; +// +// if (tile instanceof IInstanceRendered) { +// EntityInstance instance = getInstance(tile, false); +// +// if (instance != null) { +// +// if (instance.shouldReset()) { +// removeInternal(tile, instance); +// +// createInternal(tile); +// } else { +// instance.update(); +// } +// } +// } +// } + + public void remove(T entity) { + if (!Backend.getInstance().canUseInstancing()) return; + + if (entity instanceof IInstanceRendered) { + removeInternal(entity); + } + } + + public synchronized void queueAdd(T tile) { + if (!Backend.getInstance().canUseInstancing()) return; + + queuedAdditions.add(tile); + } + +// public synchronized void queueUpdate(T tile) { +// if (!Backend.getInstance().canUseInstancing()) return; +// +// queuedUpdates.add(tile); +// } + + protected synchronized void processQueuedAdditions() { + if (queuedAdditions.size() > 0) { + queuedAdditions.forEach(this::addInternal); + queuedAdditions.clear(); + } + } + + protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { + int dX = worldPos.getX() - cX; + int dY = worldPos.getY() - cY; + int dZ = worldPos.getZ() - cZ; + + // is it more than 2 blocks behind the camera? + int dist = 2; + float dot = (dX + lookX * dist) * lookX + (dY + lookY * dist) * lookY + (dZ + lookZ * dist) * lookZ; + if (dot < 0) return false; + + return (frame % getUpdateDivisor(dX, dY, dZ)) == 0; + } + + protected int getUpdateDivisor(int dX, int dY, int dZ) { + int dSq = dX * dX + dY * dY + dZ * dZ; + + return (dSq / 1024) + 1; + } + + private void addInternal(Entity tile) { + getInstance(tile, true); + } + + private void removeInternal(T tile) { + EntityInstance instance = getInstance(tile, false); + + if (instance != null) { + removeInternal(tile, instance); + } + } + + private void removeInternal(Entity tile, EntityInstance instance) { + instance.remove(); + instances.remove(tile); + dynamicInstances.remove(tile); + tickableInstances.remove(tile); + } + + private EntityInstance createInternal(T tile) { + EntityInstance renderer = InstancedRenderRegistry.getInstance().create(materialManager, tile); + + if (renderer != null) { + //renderer.updateLight(); + instances.put(tile, renderer); + + if (renderer instanceof IDynamicInstance) + dynamicInstances.put(tile, (IDynamicInstance) renderer); + + if (renderer instanceof ITickableInstance) + tickableInstances.put(tile, ((ITickableInstance) renderer)); + } + + return renderer; + } + + public void invalidate() { + instances.clear(); + dynamicInstances.clear(); + tickableInstances.clear(); + } + + public boolean canCreateInstance(Entity entity) { + if (!entity.isAlive()) return false; + + World world = entity.world; + + if (world == null) return false; + + if (Backend.isFlywheelWorld(world)) { + BlockPos pos = entity.getBlockPos(); + + IBlockReader existingChunk = world.getExistingChunk(pos.getX() >> 4, pos.getZ() >> 4); + + return existingChunk != null; + } + + return false; + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileEntityInstance.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileEntityInstance.java index 7ad2d8bfd..e3929101c 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileEntityInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileEntityInstance.java @@ -8,7 +8,6 @@ import com.jozufozu.flywheel.backend.instancing.IInstance; import com.jozufozu.flywheel.backend.instancing.ITickableInstance; import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; import com.jozufozu.flywheel.backend.instancing.MaterialManager; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; import com.jozufozu.flywheel.core.materials.IFlatLight; import com.jozufozu.flywheel.core.materials.ModelData; import com.jozufozu.flywheel.core.materials.OrientedData; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/TileInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java similarity index 94% rename from src/main/java/com/jozufozu/flywheel/backend/instancing/TileInstanceManager.java rename to src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java index 510b83dcf..a4b1f8140 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/TileInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java @@ -1,4 +1,4 @@ -package com.jozufozu.flywheel.backend.instancing; +package com.jozufozu.flywheel.backend.instancing.tile; import java.util.ArrayList; import java.util.HashMap; @@ -8,7 +8,11 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nullable; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.ITickableInstance; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.renderer.ActiveRenderInfo; diff --git a/src/main/java/com/jozufozu/flywheel/core/Contexts.java b/src/main/java/com/jozufozu/flywheel/core/Contexts.java index b14917d0f..18433bf76 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Contexts.java +++ b/src/main/java/com/jozufozu/flywheel/core/Contexts.java @@ -11,10 +11,11 @@ import com.jozufozu.flywheel.core.shader.gamestate.NormalDebugStateProvider; import com.jozufozu.flywheel.event.GatherContextEvent; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) public class Contexts { public static WorldContext WORLD; diff --git a/src/main/java/com/jozufozu/flywheel/core/CrumblingInstanceManager.java b/src/main/java/com/jozufozu/flywheel/core/CrumblingInstanceManager.java index 7a50f1671..bbea00ada 100644 --- a/src/main/java/com/jozufozu/flywheel/core/CrumblingInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/core/CrumblingInstanceManager.java @@ -1,7 +1,7 @@ package com.jozufozu.flywheel.core; import com.jozufozu.flywheel.backend.instancing.MaterialManager; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/com/jozufozu/flywheel/core/Materials.java b/src/main/java/com/jozufozu/flywheel/core/Materials.java index 0d7ee40e2..0a9cc8f47 100644 --- a/src/main/java/com/jozufozu/flywheel/core/Materials.java +++ b/src/main/java/com/jozufozu/flywheel/core/Materials.java @@ -9,10 +9,11 @@ import com.jozufozu.flywheel.event.GatherContextEvent; import com.simibubi.create.foundation.render.AllMaterialSpecs; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) public class Materials { public static final MaterialSpec ORIENTED = AllMaterialSpecs.register(new MaterialSpec<>(Locations.ORIENTED, Programs.ORIENTED, Formats.UNLIT_MODEL, Formats.ORIENTED, OrientedData::new)); public static final MaterialSpec TRANSFORMED = AllMaterialSpecs.register(new MaterialSpec<>(Locations.MODEL, Programs.TRANSFORMED, Formats.UNLIT_MODEL, Formats.TRANSFORMED, ModelData::new)); diff --git a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java index a00f339e6..6fa635f59 100644 --- a/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java +++ b/src/main/java/com/jozufozu/flywheel/core/QuadConverter.java @@ -17,6 +17,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.backend.model.ElementBuffer; import com.jozufozu.flywheel.event.ReloadRenderersEvent; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -24,7 +25,7 @@ import net.minecraftforge.fml.common.Mod; /** * A class to manage EBOs that index quads as triangles. */ -@Mod.EventBusSubscriber +@Mod.EventBusSubscriber(value = Dist.CLIENT) public class QuadConverter { public static final int STARTING_CAPACITY = 42; diff --git a/src/main/java/com/jozufozu/flywheel/core/instancing/ConditionalInstance.java b/src/main/java/com/jozufozu/flywheel/core/instancing/ConditionalInstance.java index 26bcc9d19..251b00db6 100644 --- a/src/main/java/com/jozufozu/flywheel/core/instancing/ConditionalInstance.java +++ b/src/main/java/com/jozufozu/flywheel/core/instancing/ConditionalInstance.java @@ -21,8 +21,6 @@ public class ConditionalInstance { public ConditionalInstance(Instancer model) { this.model = model; this.condition = () -> true; - - update(); } public ConditionalInstance withSetupFunc(Consumer setupFunc) { diff --git a/src/main/java/com/jozufozu/flywheel/event/EntityWorldHandler.java b/src/main/java/com/jozufozu/flywheel/event/EntityWorldHandler.java new file mode 100644 index 000000000..8c668503e --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/event/EntityWorldHandler.java @@ -0,0 +1,27 @@ +package com.jozufozu.flywheel.event; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.entity.EntityLeaveWorldEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(Dist.CLIENT) +public class EntityWorldHandler { + + @SubscribeEvent + public static void onEntityJoinWorld(EntityJoinWorldEvent event) { + if (event.getWorld().isRemote) + InstancedRenderDispatcher.getEntities(event.getWorld()) + .queueAdd(event.getEntity()); + } + + @SubscribeEvent + public static void onEntityLeaveWorld(EntityLeaveWorldEvent event) { + if (event.getWorld().isRemote) + InstancedRenderDispatcher.getEntities(event.getWorld()) + .remove(event.getEntity()); + } +} diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 759524d38..e89ccd26d 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -4,17 +4,19 @@ import java.util.ArrayList; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; +import com.jozufozu.flywheel.backend.instancing.entity.EntityInstanceManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import net.minecraft.client.Minecraft; import net.minecraft.client.world.ClientWorld; import net.minecraft.world.IWorld; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -@Mod.EventBusSubscriber +@Mod.EventBusSubscriber(value = Dist.CLIENT) public class ForgeEvents { @SubscribeEvent @@ -40,9 +42,15 @@ public class ForgeEvents { IWorld world = event.getWorld(); if (Backend.isFlywheelWorld(world)) { - TileInstanceManager renderer = InstancedRenderDispatcher.get(world); - renderer.invalidate(); - ((ClientWorld) world).loadedTileEntityList.forEach(renderer::add); + ClientWorld clientWorld = (ClientWorld) world; + + TileInstanceManager tiles = InstancedRenderDispatcher.getTiles(world); + tiles.invalidate(); + clientWorld.loadedTileEntityList.forEach(tiles::add); + + EntityInstanceManager entities = InstancedRenderDispatcher.getEntities(world); + entities.invalidate(); + clientWorld.getAllEntities().forEach(entities::add); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueInstance.java index 5b9f755df..2c8b9e65e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueInstance.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.glue; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import com.jozufozu.flywheel.backend.instancing.ITickableInstance; import com.jozufozu.flywheel.backend.instancing.Instancer; @@ -29,17 +30,16 @@ public class GlueInstance extends EntityInstance implements ITi public GlueInstance(MaterialManager renderer, SuperGlueEntity entity) { super(renderer, entity); - Instancer instancer = renderer.getMaterial(Materials.ORIENTED) .get(entity.getType(), GlueInstance::supplyModel); + + Direction face = entity.getFacingDirection(); + rotation = new Quaternion(AngleHelper.verticalAngle(face), AngleHelper.horizontalAngleNew(face), 0, true); + model = new ConditionalInstance<>(instancer) .withCondition(this::shouldShow) .withSetupFunc(this::positionModel) .update(); - - Direction face = entity.getFacingDirection(); - - rotation = new Quaternion(AngleHelper.verticalAngle(face), AngleHelper.horizontalAngleNew(face), 0, true); } @Override @@ -93,22 +93,23 @@ public class GlueInstance extends EntityInstance implements ITi Vector3d a4 = plane.add(start); Vector3d b4 = plane.add(end); - float[] quads = new float[] { - // x, y, z,nx, ny,nz, u, v - // inside quad - (float) a1.x, (float) a1.y, (float) a1.z, 0, -1, 0, 1, 0, - (float) a2.x, (float) a2.y, (float) a2.z, 0, -1, 0, 1, 1, - (float) a3.x, (float) a3.y, (float) a3.z, 0, -1, 0, 0, 1, - (float) a4.x, (float) a4.y, (float) a4.z, 0, -1, 0, 0, 0, - // outside quad - (float) b4.x, (float) b4.y, (float) b4.z, 0, 1, 0, 0, 0, - (float) b3.x, (float) b3.y, (float) b3.z, 0, 1, 0, 0, 1, - (float) b2.x, (float) b2.y, (float) b2.z, 0, 1, 0, 1, 1, - (float) b1.x, (float) b1.y, (float) b1.z, 0, 1, 0, 1, 0, - }; + ByteBuffer buffer = ByteBuffer.allocate(Formats.UNLIT_MODEL.getStride() * 8); + buffer.order(ByteOrder.nativeOrder()); + + // x, y, z,nx, ny,nz, u, v + // inside quad + buffer.putFloat((float) a1.x).putFloat((float) a1.y).putFloat((float) a1.z).put((byte) 0).put((byte) 127).put((byte) 0).putFloat(1f).putFloat(0f); + buffer.putFloat((float) a2.x).putFloat((float) a2.y).putFloat((float) a2.z).put((byte) 0).put((byte) 127).put((byte) 0).putFloat(1f).putFloat(1f); + buffer.putFloat((float) a3.x).putFloat((float) a3.y).putFloat((float) a3.z).put((byte) 0).put((byte) 127).put((byte) 0).putFloat(0f).putFloat(1f); + buffer.putFloat((float) a4.x).putFloat((float) a4.y).putFloat((float) a4.z).put((byte) 0).put((byte) 127).put((byte) 0).putFloat(0f).putFloat(0f); + // outside quad + buffer.putFloat((float) b4.x).putFloat((float) b4.y).putFloat((float) b4.z).put((byte) 0).put((byte) -127).put((byte) 0).putFloat(0f).putFloat(0f); + buffer.putFloat((float) b3.x).putFloat((float) b3.y).putFloat((float) b3.z).put((byte) 0).put((byte) -127).put((byte) 0).putFloat(0f).putFloat(1f); + buffer.putFloat((float) b2.x).putFloat((float) b2.y).putFloat((float) b2.z).put((byte) 0).put((byte) -127).put((byte) 0).putFloat(1f).putFloat(1f); + buffer.putFloat((float) b1.x).putFloat((float) b1.y).putFloat((float) b1.z).put((byte) 0).put((byte) -127).put((byte) 0).putFloat(1f).putFloat(0f); + + buffer.rewind(); - ByteBuffer buffer = ByteBuffer.allocate(quads.length * 4); - buffer.asFloatBuffer().put(quads); return IndexedModel.fromSequentialQuads(Formats.UNLIT_MODEL, buffer, 8); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java index 54a768860..1cf73852d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java @@ -8,7 +8,7 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; import com.jozufozu.flywheel.backend.instancing.MaterialManager; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/CancelEntityRenderMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/CancelEntityRenderMixin.java index bdb3e5576..00300abab 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/CancelEntityRenderMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/CancelEntityRenderMixin.java @@ -4,28 +4,37 @@ import java.util.ArrayList; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.Redirect; import com.google.common.collect.Lists; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; -@Mixin(ClientWorld.class) +@Mixin(WorldRenderer.class) public class CancelEntityRenderMixin { - @Inject(at = @At("RETURN"), method = "getAllEntities", cancellable = true) - private void filterEntities(CallbackInfoReturnable> cir) { +// @Inject(at = @At("HEAD"), method = "shouldRender", cancellable = true) +// private void dontRenderFlywheelEntities(E entity, ClippingHelper p_229086_2_, double p_229086_3_, double p_229086_5_, double p_229086_7_, CallbackInfoReturnable cir) { +// if (Backend.getInstance().canUseInstancing()) { +// if (entity instanceof IInstanceRendered && !((IInstanceRendered) entity).shouldRenderNormally()) +// cir.setReturnValue(false); +// } +// } + + @Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;getAllEntities()Ljava/lang/Iterable;")) + private Iterable filterEntities(ClientWorld world) { + Iterable entities = world.getAllEntities(); if (Backend.getInstance().canUseInstancing()) { - Iterable entities = cir.getReturnValue(); - ArrayList list = Lists.newArrayList(entities); - list.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderNormally()); + ArrayList filtered = Lists.newArrayList(entities); + filtered.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderNormally()); - cir.setReturnValue(list); + return filtered; } + return entities; } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/RenderHooksMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/RenderHooksMixin.java index 0c345df3f..b729d38cc 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/RenderHooksMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/RenderHooksMixin.java @@ -97,7 +97,7 @@ public class RenderHooksMixin { @Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded") private void checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) { - InstancedRenderDispatcher.get(world) + InstancedRenderDispatcher.getTiles(world) .update(world.getTileEntity(pos)); } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileRemoveMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileRemoveMixin.java index b433bd3be..2e506add4 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileRemoveMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileRemoveMixin.java @@ -24,7 +24,7 @@ public class TileRemoveMixin { @Inject(at = @At("TAIL"), method = "remove") private void onRemove(CallbackInfo ci) { if (world instanceof ClientWorld) - InstancedRenderDispatcher.get(this.world) + InstancedRenderDispatcher.getTiles(this.world) .remove((TileEntity) (Object) this); } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileWorldHookMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileWorldHookMixin.java index 0b622ae58..58d3c8dad 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileWorldHookMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/TileWorldHookMixin.java @@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.backend.instancing.TileInstanceManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; @@ -35,7 +35,7 @@ public class TileWorldHookMixin { @Inject(at = @At("TAIL"), method = "addTileEntity") private void onAddTile(TileEntity te, CallbackInfoReturnable cir) { if (isRemote) { - InstancedRenderDispatcher.get(self) + InstancedRenderDispatcher.getTiles(self) .queueAdd(te); } } @@ -46,7 +46,7 @@ public class TileWorldHookMixin { @Inject(at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", ordinal = 0), method = "tickBlockEntities") private void onChunkUnload(CallbackInfo ci) { if (isRemote) { - TileInstanceManager kineticRenderer = InstancedRenderDispatcher.get(self); + TileInstanceManager kineticRenderer = InstancedRenderDispatcher.getTiles(self); for (TileEntity tile : tileEntitiesToBeRemoved) { kineticRenderer.remove(tile); } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/LightUpdateMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/LightUpdateMixin.java index bbd9c970e..1ee536982 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/LightUpdateMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/LightUpdateMixin.java @@ -46,7 +46,7 @@ public abstract class LightUpdateMixin extends AbstractChunkProvider { .getY()) == sectionY) .map(Map.Entry::getValue) .forEach(tile -> { - InstancedRenderDispatcher.get(world) + InstancedRenderDispatcher.getTiles(world) .onLightUpdate(tile); }); } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/NetworkLightUpdateMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/NetworkLightUpdateMixin.java index fc8f6fb08..fe706092a 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/NetworkLightUpdateMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/flywheel/light/NetworkLightUpdateMixin.java @@ -36,7 +36,7 @@ public class NetworkLightUpdateMixin { chunk.getTileEntityMap() .values() .forEach(tile -> { - InstancedRenderDispatcher.get(world) + InstancedRenderDispatcher.getTiles(world) .onLightUpdate(tile); }); }