Instanced entities stage 0

This commit is contained in:
JozsefA 2021-06-07 02:43:36 -07:00
parent d47f898c76
commit 285b8f98cf
23 changed files with 439 additions and 72 deletions

View file

@ -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<Runnable> runs = new ConcurrentLinkedQueue<>();

View file

@ -1,5 +1,7 @@
package com.jozufozu.flywheel.backend.instancing;
import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager;
import net.minecraft.util.math.BlockPos;
/**

View file

@ -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> entityInstanceManager = new WorldAttached<>(world -> new EntityInstanceManager(Contexts.WORLD.getMaterialManager(world)));
private static final WorldAttached<TileInstanceManager> tileInstanceManager = new WorldAttached<>(world -> new TileInstanceManager(Contexts.WORLD.getMaterialManager(world)));
private static final LazyValue<Vector<CrumblingInstanceManager>> blockBreaking = new LazyValue<>(() -> {
Vector<CrumblingInstanceManager> 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<WorldProgram> 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;

View file

@ -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<TileEntityType<?>, ITileInstanceFactory<?>> renderers = Maps.newHashMap();
private final Map<TileEntityType<?>, ITileInstanceFactory<?>> tiles = Maps.newHashMap();
private final Map<EntityType<?>, IEntityInstanceFactory<?>> entities = Maps.newHashMap();
public <T extends TileEntity> void register(TileEntityType<? extends T> type, ITileInstanceFactory<? super T> rendererFactory) {
this.renderers.put(type, rendererFactory);
this.tiles.put(type, rendererFactory);
}
public <T extends Entity> void register(EntityType<? extends T> type, IEntityInstanceFactory<? super T> rendererFactory) {
this.entities.put(type, rendererFactory);
}
static {
INSTANCE.register(AllEntityTypes.SUPER_GLUE.get(), GlueInstance::new);
}
@SuppressWarnings("unchecked")
@Nullable
public <T extends TileEntity> TileEntityInstance<? super T> create(MaterialManager<?> manager, T tile) {
TileEntityType<?> type = tile.getType();
ITileInstanceFactory<? super T> factory = (ITileInstanceFactory<? super T>) this.renderers.get(type);
ITileInstanceFactory<? super T> factory = (ITileInstanceFactory<? super T>) this.tiles.get(type);
if (factory == null) return null;
else return factory.create(manager, tile);
}
@SuppressWarnings("unchecked")
@Nullable
public <T extends Entity> EntityInstance<? super T> create(MaterialManager<?> manager, T tile) {
EntityType<?> type = tile.getType();
IEntityInstanceFactory<? super T> factory = (IEntityInstanceFactory<? super T>) this.entities.get(type);
if (factory == null) return null;
else return factory.create(manager, tile);

View file

@ -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;

View file

@ -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<Entity> queuedAdditions;
//protected final ConcurrentHashMap.KeySetView<Entity, Boolean> queuedUpdates;
protected final Map<Entity, EntityInstance<?>> instances;
protected final Object2ObjectOpenHashMap<Entity, ITickableInstance> tickableInstances;
protected final Object2ObjectOpenHashMap<Entity, IDynamicInstance> 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<Entity> instancedTiles = new ArrayList<>(instances.keySet());
invalidate();
instancedTiles.forEach(this::add);
}
@SuppressWarnings("unchecked")
@Nullable
public <T extends Entity> EntityInstance<? super T> getInstance(T entity, boolean create) {
if (!Backend.getInstance().canUseInstancing()) return null;
EntityInstance<?> instance = instances.get(entity);
if (instance != null) {
return (EntityInstance<? super T>) instance;
} else if (create && canCreateInstance(entity)) {
return createInternal(entity);
} else {
return null;
}
}
// public <T extends Entity> void onLightUpdate(T tile) {
// if (!Backend.getInstance().canUseInstancing()) return;
//
// if (tile instanceof IInstanceRendered) {
// EntityInstance<? super T> instance = getInstance(tile, false);
//
// if (instance != null)
// instance.updateLight();
// }
// }
public <T extends Entity> void add(T entity) {
if (!Backend.getInstance().canUseInstancing()) return;
if (entity instanceof IInstanceRendered) {
addInternal(entity);
}
}
// public <T extends Entity> void update(T tile) {
// if (!Backend.getInstance().canUseInstancing()) return;
//
// if (tile instanceof IInstanceRendered) {
// EntityInstance<? super T> instance = getInstance(tile, false);
//
// if (instance != null) {
//
// if (instance.shouldReset()) {
// removeInternal(tile, instance);
//
// createInternal(tile);
// } else {
// instance.update();
// }
// }
// }
// }
public <T extends Entity> void remove(T entity) {
if (!Backend.getInstance().canUseInstancing()) return;
if (entity instanceof IInstanceRendered) {
removeInternal(entity);
}
}
public synchronized <T extends Entity> void queueAdd(T tile) {
if (!Backend.getInstance().canUseInstancing()) return;
queuedAdditions.add(tile);
}
// public synchronized <T extends Entity> 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 <T extends Entity> void removeInternal(T tile) {
EntityInstance<? super T> 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 <T extends Entity> EntityInstance<? super T> createInternal(T tile) {
EntityInstance<? super T> 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;
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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<WorldProgram> WORLD;

View file

@ -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;

View file

@ -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<OrientedData> ORIENTED = AllMaterialSpecs.register(new MaterialSpec<>(Locations.ORIENTED, Programs.ORIENTED, Formats.UNLIT_MODEL, Formats.ORIENTED, OrientedData::new));
public static final MaterialSpec<ModelData> TRANSFORMED = AllMaterialSpecs.register(new MaterialSpec<>(Locations.MODEL, Programs.TRANSFORMED, Formats.UNLIT_MODEL, Formats.TRANSFORMED, ModelData::new));

View file

@ -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;

View file

@ -21,8 +21,6 @@ public class ConditionalInstance<D extends InstanceData> {
public ConditionalInstance(Instancer<D> model) {
this.model = model;
this.condition = () -> true;
update();
}
public ConditionalInstance<D> withSetupFunc(Consumer<D> setupFunc) {

View file

@ -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());
}
}

View file

@ -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);
}
}
}

View file

@ -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<SuperGlueEntity> implements ITi
public GlueInstance(MaterialManager<?> renderer, SuperGlueEntity entity) {
super(renderer, entity);
Instancer<OrientedData> 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<SuperGlueEntity> implements ITi
Vector3d a4 = plane.add(start);
Vector3d b4 = plane.add(end);
float[] quads = new float[] {
ByteBuffer buffer = ByteBuffer.allocate(Formats.UNLIT_MODEL.getStride() * 8);
buffer.order(ByteOrder.nativeOrder());
// 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,
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
(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,
};
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);
}

View file

@ -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;

View file

@ -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<Iterable<Entity>> cir) {
// @Inject(at = @At("HEAD"), method = "shouldRender", cancellable = true)
// private <E extends Entity> void dontRenderFlywheelEntities(E entity, ClippingHelper p_229086_2_, double p_229086_3_, double p_229086_5_, double p_229086_7_, CallbackInfoReturnable<Boolean> 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<Entity> filterEntities(ClientWorld world) {
Iterable<Entity> entities = world.getAllEntities();
if (Backend.getInstance().canUseInstancing()) {
Iterable<Entity> entities = cir.getReturnValue();
ArrayList<Entity> list = Lists.newArrayList(entities);
list.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderNormally());
ArrayList<Entity> filtered = Lists.newArrayList(entities);
filtered.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderNormally());
cir.setReturnValue(list);
}
return filtered;
}
return entities;
}
}

View file

@ -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));
}
}

View file

@ -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);
}
}

View file

@ -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<Boolean> 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);
}

View file

@ -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);
});
}

View file

@ -36,7 +36,7 @@ public class NetworkLightUpdateMixin {
chunk.getTileEntityMap()
.values()
.forEach(tile -> {
InstancedRenderDispatcher.get(world)
InstancedRenderDispatcher.getTiles(world)
.onLightUpdate(tile);
});
}