diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index 80cb2facb..da33797b9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -26,7 +26,7 @@ import net.minecraft.world.World; public class Backend { public static final Logger log = LogManager.getLogger(Backend.class); - public static Backend INSTANCE; + protected static final Backend INSTANCE = new Backend(); public static Backend getInstance() { return INSTANCE; @@ -46,7 +46,7 @@ public class Backend { private final Map> materialRegistry = new HashMap<>(); private final Map programSpecRegistry = new HashMap<>(); - public Backend() { + protected Backend() { // Can be null when running datagenerators due to the unfortunate time we call this minecraft = Minecraft.getInstance(); if (minecraft == null) return; 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 599950823..fa424ffa6 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/IInstance.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/IInstance.java @@ -11,4 +11,12 @@ import net.minecraft.util.math.BlockPos; public interface IInstance { BlockPos getWorldPosition(); + + void updateLight(); + + void remove(); + + boolean shouldReset(); + + void update(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java new file mode 100644 index 000000000..250880e61 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceManager.java @@ -0,0 +1,245 @@ +package com.jozufozu.flywheel.backend.instancing; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.backend.Backend; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3f; + +public abstract class InstanceManager 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 InstanceManager(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(); + }); + } + } + + public void add(T obj) { + if (!Backend.getInstance().canUseInstancing()) return; + + if (obj instanceof IInstanceRendered) { + addInternal(obj); + } + } + + public synchronized void queueAdd(T obj) { + if (!Backend.getInstance().canUseInstancing()) return; + + queuedAdditions.add(obj); + } + + public void update(T obj) { + if (!Backend.getInstance().canUseInstancing()) return; + + if (obj instanceof IInstanceRendered) { + IInstance instance = getInstance(obj, false); + + if (instance != null) { + + if (instance.shouldReset()) { + removeInternal(obj, instance); + + createInternal(obj); + } else { + instance.update(); + } + } + } + } + + public synchronized void queueUpdate(T obj) { + if (!Backend.getInstance().canUseInstancing()) return; + + queuedUpdates.add(obj); + } + + public void onLightUpdate(T obj) { + if (!Backend.getInstance().canUseInstancing()) return; + + if (obj instanceof IInstanceRendered) { + IInstance instance = getInstance(obj, false); + + if (instance != null) + instance.updateLight(); + } + } + + public void remove(T obj) { + if (!Backend.getInstance().canUseInstancing()) return; + + if (obj instanceof IInstanceRendered) { + IInstance instance = getInstance(obj, false); + if (instance != null) + removeInternal(obj, instance); + } + } + + public void invalidate() { + instances.clear(); + dynamicInstances.clear(); + tickableInstances.clear(); + } + + @SuppressWarnings("unchecked") + @Nullable + protected IInstance getInstance(I obj, boolean create) { + if (!Backend.getInstance().canUseInstancing()) return null; + + IInstance instance = instances.get(obj); + + if (instance != null) { + return instance; + } else if (create && canCreateInstance(obj)) { + return createInternal(obj); + } else { + return null; + } + } + + 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; + } + + protected void addInternal(T tile) { + getInstance(tile, true); + } + + protected void removeInternal(T obj, IInstance instance) { + instance.remove(); + instances.remove(obj); + dynamicInstances.remove(obj); + tickableInstances.remove(obj); + } + + protected IInstance createInternal(T obj) { + IInstance renderer = createRaw(obj); + + if (renderer != null) { + renderer.updateLight(); + instances.put(obj, renderer); + + if (renderer instanceof IDynamicInstance) + dynamicInstances.put(obj, (IDynamicInstance) renderer); + + if (renderer instanceof ITickableInstance) + tickableInstances.put(obj, ((ITickableInstance) renderer)); + } + + return renderer; + } + + @Override + public void onOriginShift() { + ArrayList instancedTiles = new ArrayList<>(instances.keySet()); + invalidate(); + instancedTiles.forEach(this::add); + } + + protected abstract IInstance createRaw(T obj); + + protected abstract boolean canCreateInstance(T entity); +} 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 381a47778..1fbf6f5a8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderRegistry.java @@ -35,7 +35,6 @@ public class InstancedRenderRegistry { this.entities.put(type, rendererFactory); } - static { INSTANCE.register(AllEntityTypes.SUPER_GLUE.get(), GlueInstance::new); } 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 index 59c68b1f4..24934c8ab 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/entity/EntityInstanceManager.java @@ -1,259 +1,29 @@ package com.jozufozu.flywheel.backend.instancing.entity; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -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.IInstance; +import com.jozufozu.flywheel.backend.instancing.InstanceManager; 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 class EntityInstanceManager extends InstanceManager { 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(); - }); - } + super(materialManager); } @Override - public void onOriginShift() { - ArrayList instancedTiles = new ArrayList<>(instances.keySet()); - invalidate(); - instancedTiles.forEach(this::add); + protected IInstance createRaw(Entity obj) { + return InstancedRenderRegistry.getInstance().create(materialManager, obj); } - @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) { + @Override + protected boolean canCreateInstance(Entity entity) { if (!entity.isAlive()) return false; World world = entity.world; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java index a4b1f8140..1359ceafd 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/tile/TileInstanceManager.java @@ -1,259 +1,29 @@ package com.jozufozu.flywheel.backend.instancing.tile; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -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.IInstance; +import com.jozufozu.flywheel.backend.instancing.InstanceManager; 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.tileentity.TileEntity; 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 TileInstanceManager 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 class TileInstanceManager extends InstanceManager { public TileInstanceManager(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(); - }); - } + super(materialManager); } @Override - public void onOriginShift() { - ArrayList instancedTiles = new ArrayList<>(instances.keySet()); - invalidate(); - instancedTiles.forEach(this::add); + protected IInstance createRaw(TileEntity obj) { + return InstancedRenderRegistry.getInstance().create(materialManager, obj); } - @SuppressWarnings("unchecked") - @Nullable - public TileEntityInstance getInstance(T tile, boolean create) { - if (!Backend.getInstance().canUseInstancing()) return null; - - TileEntityInstance instance = instances.get(tile); - - if (instance != null) { - return (TileEntityInstance) instance; - } else if (create && canCreateInstance(tile)) { - return createInternal(tile); - } else { - return null; - } - } - - public void onLightUpdate(T tile) { - if (!Backend.getInstance().canUseInstancing()) return; - - if (tile instanceof IInstanceRendered) { - TileEntityInstance instance = getInstance(tile, false); - - if (instance != null) - instance.updateLight(); - } - } - - public void add(T tile) { - if (!Backend.getInstance().canUseInstancing()) return; - - if (tile instanceof IInstanceRendered) { - addInternal(tile); - } - } - - public void update(T tile) { - if (!Backend.getInstance().canUseInstancing()) return; - - if (tile instanceof IInstanceRendered) { - TileEntityInstance instance = getInstance(tile, false); - - if (instance != null) { - - if (instance.shouldReset()) { - removeInternal(tile, instance); - - createInternal(tile); - } else { - instance.update(); - } - } - } - } - - public void remove(T tile) { - if (!Backend.getInstance().canUseInstancing()) return; - - if (tile instanceof IInstanceRendered) { - removeInternal(tile); - } - } - - 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(TileEntity tile) { - getInstance(tile, true); - } - - private void removeInternal(T tile) { - TileEntityInstance instance = getInstance(tile, false); - - if (instance != null) { - removeInternal(tile, instance); - } - } - - private void removeInternal(TileEntity tile, TileEntityInstance instance) { - instance.remove(); - instances.remove(tile); - dynamicInstances.remove(tile); - tickableInstances.remove(tile); - } - - private TileEntityInstance createInternal(T tile) { - TileEntityInstance 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(TileEntity tile) { + @Override + protected boolean canCreateInstance(TileEntity tile) { if (tile.isRemoved()) return false; World world = tile.getWorld(); diff --git a/src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java b/src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java index bd22d54c9..ef71f9366 100644 --- a/src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java +++ b/src/main/java/com/jozufozu/flywheel/core/AtlasStitcher.java @@ -6,22 +6,17 @@ import java.util.List; import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.TextureStitchEvent; -import net.minecraftforge.eventbus.api.IEventBus; /** * This is primarily for hacking entity textures into the block atlas. */ public class AtlasStitcher { - public static AtlasStitcher INSTANCE; + protected static final AtlasStitcher INSTANCE = new AtlasStitcher(); public static AtlasStitcher getInstance() { return INSTANCE; } - public AtlasStitcher(IEventBus modEventBus) { - modEventBus.addListener(this::onTextureStitch); - } - private final List sprites = new ArrayList<>(); public StitchedSprite get(ResourceLocation loc) { diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 5d5ce5a4f..ad6a105b0 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -78,8 +78,8 @@ public class CreateClient { modEventBus.addListener(AllParticleTypes::registerFactories); modEventBus.addListener(ClientEvents::loadCompleted); - Backend.INSTANCE = new Backend(); - AtlasStitcher.INSTANCE = new AtlasStitcher(modEventBus); + Backend.getInstance(); + modEventBus.addListener(AtlasStitcher.getInstance()::onTextureStitch); } public static void clientInit(FMLClientSetupEvent event) { diff --git a/src/main/resources/assets/flywheel/flywheel/shaders/smooth_oriented.glsl b/src/main/resources/assets/flywheel/flywheel/shaders/smooth_oriented.glsl new file mode 100644 index 000000000..4b6aac8ce --- /dev/null +++ b/src/main/resources/assets/flywheel/flywheel/shaders/smooth_oriented.glsl @@ -0,0 +1,55 @@ +#flwbuiltins +#flwinclude <"flywheel:core/matutils.glsl"> +#flwinclude <"flywheel:core/quaternion.glsl"> +#flwinclude <"flywheel:core/diffuse.glsl"> + +#[InstanceData] +struct Oriented { +// each vec 4 is 2 light coords packed +// x z + vec4 lightA;// lo, lo + vec4 lightB;// hi, lo + vec4 lightC;// hi, hi + vec4 lightD;// lo, hi + + vec3 loCorner; + vec3 size; + + vec4 color; + vec3 pos; + vec3 pivot; + vec4 rotation; +}; + +#flwinclude <"flywheel:data/modelvertex.glsl"> +#flwinclude <"flywheel:data/blockfragment.glsl"> + +BlockFrag FLWMain(Vertex v, Oriented o) { + vec4 worldPos = vec4(rotateVertexByQuat(v.pos - o.pivot, o.rotation) + o.pivot + o.pos, 1.); + + vec3 norm = rotateVertexByQuat(v.normal, o.rotation); + + FLWFinalizeWorldPos(worldPos); + FLWFinalizeNormal(norm); + + // manual trilinear interpolation + vec3 lightPos = (worldPos.xyz - o.loCorner) / o.size; + + vec4 lightLoZ = mix(lightA, lightB, lightPos.x);// lo z + vec4 lightHiZ = mix(lightD, lightC, lightPos.x);// hi z + + vec4 lightE = mix(lightLoZ, lightHiZ, lightPos.z);// + + vec2 lightCoord = mix(lightE.xy, lightE.zw, lightPos.y); + + BlockFrag b; + b.diffuse = diffuse(norm); + b.texCoords = v.texCoords; + b.light = lightCoord; + #if defined(DEBUG_NORMAL) + b.color = vec4(norm, 1.); + #else + b.color = o.color; + #endif + return b; +}