mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-10 03:53:12 +01:00
DRY contraption rendering
- Different subclasses for flywheel rendering and sbb rendering - Select which to use on renderer reload, gather context, and when create buffers are invalidated
This commit is contained in:
parent
cd9f18a8c9
commit
7c202ed491
9 changed files with 295 additions and 275 deletions
|
@ -86,7 +86,7 @@ public class CreateClient {
|
||||||
modEventBus.addListener(ClientEvents::loadCompleted);
|
modEventBus.addListener(ClientEvents::loadCompleted);
|
||||||
modEventBus.addListener(CreateContexts::flwInit);
|
modEventBus.addListener(CreateContexts::flwInit);
|
||||||
modEventBus.addListener(AllMaterialSpecs::flwInit);
|
modEventBus.addListener(AllMaterialSpecs::flwInit);
|
||||||
modEventBus.addListener(ContraptionRenderDispatcher::invalidateOnGatherContext);
|
modEventBus.addListener(ContraptionRenderDispatcher::gatherContext);
|
||||||
|
|
||||||
ZAPPER_RENDER_HANDLER.register(forgeEventBus);
|
ZAPPER_RENDER_HANDLER.register(forgeEventBus);
|
||||||
POTATO_CANNON_RENDER_HANDLER.register(forgeEventBus);
|
POTATO_CANNON_RENDER_HANDLER.register(forgeEventBus);
|
||||||
|
@ -207,7 +207,7 @@ public class CreateClient {
|
||||||
public static void invalidateRenderers() {
|
public static void invalidateRenderers() {
|
||||||
BUFFER_CACHE.invalidate();
|
BUFFER_CACHE.invalidate();
|
||||||
|
|
||||||
ContraptionRenderDispatcher.invalidateAll();
|
ContraptionRenderDispatcher.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkGraphicsFanciness() {
|
public static void checkGraphicsFanciness() {
|
||||||
|
|
|
@ -11,7 +11,10 @@ import net.minecraft.util.math.vector.Matrix4f;
|
||||||
|
|
||||||
public class ContraptionMatrices {
|
public class ContraptionMatrices {
|
||||||
|
|
||||||
public static final ContraptionMatrices IDENTITY = new ContraptionMatrices();
|
/**
|
||||||
|
* The results from using this are undefined.
|
||||||
|
*/
|
||||||
|
public static final ContraptionMatrices EMPTY = new ContraptionMatrices();
|
||||||
|
|
||||||
public final MatrixStack entityStack;
|
public final MatrixStack entityStack;
|
||||||
public final MatrixStack contraptionStack;
|
public final MatrixStack contraptionStack;
|
||||||
|
@ -20,9 +23,7 @@ public class ContraptionMatrices {
|
||||||
public final Matrix4f lightMatrix;
|
public final Matrix4f lightMatrix;
|
||||||
|
|
||||||
private ContraptionMatrices() {
|
private ContraptionMatrices() {
|
||||||
this.entityStack = new MatrixStack();
|
this.entityStack = this.contraptionStack = this.finalStack = new MatrixStack();
|
||||||
this.contraptionStack = new MatrixStack();
|
|
||||||
this.finalStack = new MatrixStack();
|
|
||||||
this.entityMatrix = new Matrix4f();
|
this.entityMatrix = new Matrix4f();
|
||||||
this.lightMatrix = new Matrix4f();
|
this.lightMatrix = new Matrix4f();
|
||||||
}
|
}
|
||||||
|
@ -81,4 +82,9 @@ public class ContraptionMatrices {
|
||||||
|
|
||||||
return cms;
|
return cms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Matrix4f contraptionPose() {
|
||||||
|
return contraptionStack.last()
|
||||||
|
.pose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.util.Random;
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||||
import com.jozufozu.flywheel.event.GatherContextEvent;
|
import com.jozufozu.flywheel.event.GatherContextEvent;
|
||||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||||
|
@ -54,7 +55,7 @@ public class ContraptionRenderDispatcher {
|
||||||
private static final Lazy<BlockModelRenderer> MODEL_RENDERER = Lazy.of(() -> new BlockModelRenderer(Minecraft.getInstance().getBlockColors()));
|
private static final Lazy<BlockModelRenderer> MODEL_RENDERER = Lazy.of(() -> new BlockModelRenderer(Minecraft.getInstance().getBlockColors()));
|
||||||
private static final Lazy<BlockModelShapes> BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShaper());
|
private static final Lazy<BlockModelShapes> BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShaper());
|
||||||
|
|
||||||
private static final WorldAttached<WorldContraptions> WORLDS = new WorldAttached<>(WorldContraptions::new);
|
private static WorldAttached<ContraptionRenderManager<?>> WORLDS = new WorldAttached<>(SBBContraptionManager::new);
|
||||||
|
|
||||||
public static final Compartment<Pair<Contraption, RenderType>> CONTRAPTION = new Compartment<>();
|
public static final Compartment<Pair<Contraption, RenderType>> CONTRAPTION = new Compartment<>();
|
||||||
|
|
||||||
|
@ -76,11 +77,11 @@ public class ContraptionRenderDispatcher {
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onRendererReload(ReloadRenderersEvent event) {
|
public static void onRendererReload(ReloadRenderersEvent event) {
|
||||||
invalidateAll();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void invalidateOnGatherContext(GatherContextEvent e) {
|
public static void gatherContext(GatherContextEvent e) {
|
||||||
invalidateAll();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void render(AbstractContraptionEntity entity, Contraption contraption, IRenderTypeBuffer buffers) {
|
public static void render(AbstractContraptionEntity entity, Contraption contraption, IRenderTypeBuffer buffers) {
|
||||||
|
@ -202,7 +203,13 @@ public class ContraptionRenderDispatcher {
|
||||||
return WorldRenderer.getLightColor(renderWorld, context.localPos);
|
return WorldRenderer.getLightColor(renderWorld, context.localPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void invalidateAll() {
|
public static void reset() {
|
||||||
WORLDS.empty(WorldContraptions::invalidate);
|
WORLDS.empty(ContraptionRenderManager::delete);
|
||||||
|
|
||||||
|
if (Backend.getInstance().available()) {
|
||||||
|
WORLDS = new WorldAttached<>(FlwContraptionManager::new);
|
||||||
|
} else {
|
||||||
|
WORLDS = new WorldAttached<>(SBBContraptionManager::new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.culling.ClippingHelper;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
|
|
||||||
public class ContraptionRenderInfo {
|
public class ContraptionRenderInfo {
|
||||||
public final Contraption contraption;
|
public final Contraption contraption;
|
||||||
public final PlacementSimulationWorld renderWorld;
|
public final PlacementSimulationWorld renderWorld;
|
||||||
|
|
||||||
private ContraptionMatrices matrices = ContraptionMatrices.IDENTITY;
|
private ContraptionMatrices matrices = ContraptionMatrices.EMPTY;
|
||||||
private boolean visible;
|
private boolean visible;
|
||||||
|
|
||||||
public ContraptionRenderInfo(Contraption contraption, PlacementSimulationWorld renderWorld) {
|
public ContraptionRenderInfo(Contraption contraption, PlacementSimulationWorld renderWorld) {
|
||||||
|
@ -29,22 +29,24 @@ public class ContraptionRenderInfo {
|
||||||
return !contraption.entity.isAlive();
|
return !contraption.entity.isAlive();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginFrame(ClippingHelper clippingHelper, MatrixStack mainStack, double camX, double camY, double camZ) {
|
public void beginFrame(BeginFrameEvent event) {
|
||||||
AbstractContraptionEntity entity = contraption.entity;
|
AbstractContraptionEntity entity = contraption.entity;
|
||||||
|
|
||||||
visible = clippingHelper.isVisible(entity.getBoundingBoxForCulling().inflate(2));
|
visible = event.getClippingHelper().isVisible(entity.getBoundingBoxForCulling().inflate(2));
|
||||||
|
|
||||||
mainStack.pushPose();
|
event.getStack().pushPose();
|
||||||
|
|
||||||
double x = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.xOld, entity.getX()) - camX;
|
Vector3d cameraPos = event.getInfo()
|
||||||
double y = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.yOld, entity.getY()) - camY;
|
.getPosition();
|
||||||
double z = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.zOld, entity.getZ()) - camZ;
|
double x = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.xOld, entity.getX()) - cameraPos.x;
|
||||||
|
double y = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.yOld, entity.getY()) - cameraPos.y;
|
||||||
|
double z = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.zOld, entity.getZ()) - cameraPos.z;
|
||||||
|
|
||||||
mainStack.translate(x, y, z);
|
event.getStack().translate(x, y, z);
|
||||||
|
|
||||||
matrices = new ContraptionMatrices(mainStack, entity);
|
matrices = new ContraptionMatrices(event.getStack(), entity);
|
||||||
|
|
||||||
mainStack.popPose();
|
event.getStack().popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVisible() {
|
public boolean isVisible() {
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||||
|
|
||||||
|
import java.lang.ref.Reference;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||||
|
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public abstract class ContraptionRenderManager<C extends ContraptionRenderInfo> {
|
||||||
|
protected final World world;
|
||||||
|
|
||||||
|
private int removalTimer;
|
||||||
|
|
||||||
|
protected final Int2ObjectMap<C> renderInfos = new Int2ObjectOpenHashMap<>();
|
||||||
|
protected final List<C> visible = new ObjectArrayList<>();
|
||||||
|
|
||||||
|
public ContraptionRenderManager(IWorld world) {
|
||||||
|
this.world = (World) world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void renderLayer(RenderLayerEvent event);
|
||||||
|
|
||||||
|
protected abstract C create(Contraption c);
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
removalTimer++;
|
||||||
|
if (removalTimer >= 20) {
|
||||||
|
removeDeadRenderers();
|
||||||
|
removalTimer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContraptionHandler.loadedContraptions.get(world)
|
||||||
|
.values()
|
||||||
|
.stream()
|
||||||
|
.map(Reference::get)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(AbstractContraptionEntity::getContraption)
|
||||||
|
.forEach(this::getRenderInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void beginFrame(BeginFrameEvent event) {
|
||||||
|
visible.clear();
|
||||||
|
|
||||||
|
renderInfos.int2ObjectEntrySet()
|
||||||
|
.stream()
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.forEach(renderInfo -> renderInfo.beginFrame(event));
|
||||||
|
|
||||||
|
renderInfos.int2ObjectEntrySet()
|
||||||
|
.stream()
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.filter(ContraptionRenderInfo::isVisible)
|
||||||
|
.forEach(visible::add);
|
||||||
|
}
|
||||||
|
|
||||||
|
public C getRenderInfo(Contraption c) {
|
||||||
|
int entityId = c.entity.getId();
|
||||||
|
C renderInfo = renderInfos.get(entityId);
|
||||||
|
|
||||||
|
if (renderInfo == null) {
|
||||||
|
renderInfo = create(c);
|
||||||
|
renderInfos.put(entityId, renderInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() {
|
||||||
|
renderInfos.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeDeadRenderers() {
|
||||||
|
renderInfos.values().removeIf(ContraptionRenderInfo::isDead);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL11.glBindTexture;
|
||||||
|
import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
|
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
||||||
|
import com.jozufozu.flywheel.backend.state.RenderLayer;
|
||||||
|
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
|
||||||
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
import com.simibubi.create.foundation.render.AllProgramSpecs;
|
||||||
|
import com.simibubi.create.foundation.render.CreateContexts;
|
||||||
|
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
|
|
||||||
|
public class FlwContraptionManager extends ContraptionRenderManager<RenderedContraption> {
|
||||||
|
|
||||||
|
public FlwContraptionManager(IWorld world) {
|
||||||
|
super(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
|
||||||
|
for (RenderedContraption contraption : visible) {
|
||||||
|
ContraptionLighter<?> lighter = contraption.getLighter();
|
||||||
|
if (lighter.getBounds().volume() < AllConfigs.CLIENT.maxContraptionLightVolume.get())
|
||||||
|
lighter.tick(contraption);
|
||||||
|
|
||||||
|
contraption.kinetics.tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderLayer(RenderLayerEvent event) {
|
||||||
|
if (visible.isEmpty()) return;
|
||||||
|
|
||||||
|
RenderType layer = event.getType();
|
||||||
|
|
||||||
|
layer.setupRenderState();
|
||||||
|
GlTextureUnit.T4.makeActive(); // the shaders expect light volumes to be in texture 4
|
||||||
|
|
||||||
|
ContraptionProgram structureShader = CreateContexts.STRUCTURE.getProgram(AllProgramSpecs.STRUCTURE);
|
||||||
|
|
||||||
|
structureShader.bind();
|
||||||
|
structureShader.uploadViewProjection(event.viewProjection);
|
||||||
|
structureShader.uploadCameraPos(event.camX, event.camY, event.camZ);
|
||||||
|
|
||||||
|
for (RenderedContraption renderedContraption : visible) {
|
||||||
|
renderedContraption.doRenderLayer(layer, structureShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Backend.getInstance().canUseInstancing()) {
|
||||||
|
RenderLayer renderLayer = event.getLayer();
|
||||||
|
if (renderLayer != null) {
|
||||||
|
for (RenderedContraption renderer : visible) {
|
||||||
|
renderer.materialManager.render(renderLayer, event.viewProjection, event.camX, event.camY, event.camZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the light volume state
|
||||||
|
GlTextureUnit.T4.makeActive();
|
||||||
|
glBindTexture(GL_TEXTURE_3D, 0);
|
||||||
|
|
||||||
|
layer.clearRenderState();
|
||||||
|
GlTextureUnit.T0.makeActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RenderedContraption create(Contraption c) {
|
||||||
|
PlacementSimulationWorld renderWorld = ContraptionRenderDispatcher.setupRenderWorld(world, c);
|
||||||
|
return new RenderedContraption(c, renderWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeDeadRenderers() {
|
||||||
|
renderInfos.values().removeIf(renderer -> {
|
||||||
|
if (renderer.isDead()) {
|
||||||
|
renderer.invalidate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
for (RenderedContraption renderer : renderInfos.values()) {
|
||||||
|
renderer.invalidate();
|
||||||
|
}
|
||||||
|
renderInfos.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,9 +18,9 @@ import com.jozufozu.flywheel.backend.model.ArrayModelRenderer;
|
||||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||||
import com.jozufozu.flywheel.backend.model.IndexedModel;
|
import com.jozufozu.flywheel.backend.model.IndexedModel;
|
||||||
import com.jozufozu.flywheel.backend.model.ModelRenderer;
|
import com.jozufozu.flywheel.backend.model.ModelRenderer;
|
||||||
|
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||||
import com.jozufozu.flywheel.light.GridAlignedBB;
|
import com.jozufozu.flywheel.light.GridAlignedBB;
|
||||||
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
|
||||||
|
@ -28,7 +28,6 @@ import com.simibubi.create.foundation.render.CreateContexts;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
|
||||||
import net.minecraft.client.renderer.LightTexture;
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
@ -36,6 +35,7 @@ import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.vector.Matrix4f;
|
import net.minecraft.util.math.vector.Matrix4f;
|
||||||
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class RenderedContraption extends ContraptionRenderInfo {
|
public class RenderedContraption extends ContraptionRenderInfo {
|
||||||
|
@ -85,26 +85,28 @@ public class RenderedContraption extends ContraptionRenderInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) {
|
public void beginFrame(BeginFrameEvent event) {
|
||||||
kinetics.beginFrame(info);
|
super.beginFrame(event);
|
||||||
|
|
||||||
|
if (!isVisible()) return;
|
||||||
|
|
||||||
|
kinetics.beginFrame(event.getInfo());
|
||||||
|
|
||||||
AbstractContraptionEntity entity = contraption.entity;
|
AbstractContraptionEntity entity = contraption.entity;
|
||||||
float pt = AnimationTickHolder.getPartialTicks();
|
float pt = AnimationTickHolder.getPartialTicks();
|
||||||
|
|
||||||
MatrixStack stack = new MatrixStack();
|
|
||||||
|
|
||||||
double x = MathHelper.lerp(pt, entity.xOld, entity.getX()) - camX;
|
|
||||||
double y = MathHelper.lerp(pt, entity.yOld, entity.getY()) - camY;
|
|
||||||
double z = MathHelper.lerp(pt, entity.zOld, entity.getZ()) - camZ;
|
|
||||||
stack.translate(x, y, z);
|
|
||||||
|
|
||||||
entity.doLocalTransforms(pt, new MatrixStack[] { stack });
|
|
||||||
|
|
||||||
model = stack.last().pose();
|
|
||||||
|
|
||||||
AxisAlignedBB lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume());
|
AxisAlignedBB lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume());
|
||||||
|
|
||||||
this.lightBox = lightBox.move(-camX, -camY, -camZ);
|
Vector3d cameraPos = event.getInfo()
|
||||||
|
.getPosition();
|
||||||
|
|
||||||
|
float x = (float) (MathHelper.lerp(pt, entity.xOld, entity.getX()) - cameraPos.x);
|
||||||
|
float y = (float) (MathHelper.lerp(pt, entity.yOld, entity.getY()) - cameraPos.y);
|
||||||
|
float z = (float) (MathHelper.lerp(pt, entity.zOld, entity.getZ()) - cameraPos.z);
|
||||||
|
model = Matrix4f.createTranslateMatrix(x, y, z);
|
||||||
|
|
||||||
|
model.multiply(getMatrices().contraptionPose());
|
||||||
|
|
||||||
|
this.lightBox = lightBox.move(-cameraPos.x, -cameraPos.y, -cameraPos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup(ContraptionProgram shader) {
|
void setup(ContraptionProgram shader) {
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher.CONTRAPTION;
|
||||||
|
import static com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher.buildStructureBuffer;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||||
|
import com.simibubi.create.CreateClient;
|
||||||
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||||
|
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||||
|
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
|
|
||||||
|
public class SBBContraptionManager extends ContraptionRenderManager<ContraptionRenderInfo> {
|
||||||
|
public SBBContraptionManager(IWorld world) {
|
||||||
|
super(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderLayer(RenderLayerEvent event) {
|
||||||
|
visible.forEach(info -> renderContraptionLayerSBB(event, info));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ContraptionRenderInfo create(Contraption c) {
|
||||||
|
PlacementSimulationWorld renderWorld = ContraptionRenderDispatcher.setupRenderWorld(world, c);
|
||||||
|
return new ContraptionRenderInfo(c, renderWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderContraptionLayerSBB(RenderLayerEvent event, ContraptionRenderInfo renderInfo) {
|
||||||
|
RenderType layer = event.getType();
|
||||||
|
|
||||||
|
if (!renderInfo.isVisible()) return;
|
||||||
|
|
||||||
|
SuperByteBuffer contraptionBuffer = CreateClient.BUFFER_CACHE.get(CONTRAPTION, Pair.of(renderInfo.contraption, layer), () -> buildStructureBuffer(renderInfo.renderWorld, renderInfo.contraption, layer));
|
||||||
|
|
||||||
|
if (!contraptionBuffer.isEmpty()) {
|
||||||
|
|
||||||
|
ContraptionMatrices matrices = renderInfo.getMatrices();
|
||||||
|
contraptionBuffer.transform(matrices.contraptionStack)
|
||||||
|
.light(matrices.entityMatrix)
|
||||||
|
.hybridLight()
|
||||||
|
.renderInto(matrices.entityStack, event.buffers.bufferSource()
|
||||||
|
.getBuffer(layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,234 +0,0 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
|
||||||
|
|
||||||
import static com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher.CONTRAPTION;
|
|
||||||
import static com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher.buildStructureBuffer;
|
|
||||||
import static org.lwjgl.opengl.GL11.glBindTexture;
|
|
||||||
import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D;
|
|
||||||
|
|
||||||
import java.lang.ref.Reference;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.Backend;
|
|
||||||
import com.jozufozu.flywheel.backend.gl.GlTextureUnit;
|
|
||||||
import com.jozufozu.flywheel.backend.state.RenderLayer;
|
|
||||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
|
||||||
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
|
||||||
import com.simibubi.create.CreateClient;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
|
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
|
||||||
import com.simibubi.create.foundation.render.AllProgramSpecs;
|
|
||||||
import com.simibubi.create.foundation.render.CreateContexts;
|
|
||||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
|
||||||
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|
||||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
|
||||||
import net.minecraft.client.renderer.RenderType;
|
|
||||||
import net.minecraft.world.IWorld;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
public class WorldContraptions {
|
|
||||||
private final World world;
|
|
||||||
|
|
||||||
private int worldHolderRefreshCounter;
|
|
||||||
|
|
||||||
public final Int2ObjectMap<RenderedContraption> flwRenderers = new Int2ObjectOpenHashMap<>();
|
|
||||||
public final Int2ObjectMap<ContraptionRenderInfo> renderInfos = new Int2ObjectOpenHashMap<>();
|
|
||||||
private final List<ContraptionRenderInfo> visible = new ObjectArrayList<>();
|
|
||||||
private final List<RenderedContraption> flwVisible = new ObjectArrayList<>();
|
|
||||||
|
|
||||||
public WorldContraptions(IWorld world) {
|
|
||||||
this.world = (World) world;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tick() {
|
|
||||||
for (RenderedContraption contraption : flwRenderers.values()) {
|
|
||||||
ContraptionLighter<?> lighter = contraption.getLighter();
|
|
||||||
if (lighter.getBounds().volume() < AllConfigs.CLIENT.maxContraptionLightVolume.get())
|
|
||||||
lighter.tick(contraption);
|
|
||||||
|
|
||||||
contraption.kinetics.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
worldHolderRefreshCounter++;
|
|
||||||
if (worldHolderRefreshCounter >= 20) {
|
|
||||||
removeDeadHolders();
|
|
||||||
removeDeadContraptions();
|
|
||||||
worldHolderRefreshCounter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Consumer<Contraption> setup;
|
|
||||||
if (Backend.getInstance().available()) {
|
|
||||||
setup = this::createRenderer;
|
|
||||||
} else {
|
|
||||||
setup = this::getRenderInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
ContraptionHandler.loadedContraptions.get(world)
|
|
||||||
.values()
|
|
||||||
.stream()
|
|
||||||
.map(Reference::get)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.map(AbstractContraptionEntity::getContraption)
|
|
||||||
.forEach(setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void beginFrame(BeginFrameEvent event) {
|
|
||||||
ActiveRenderInfo info = event.getInfo();
|
|
||||||
double camX = info.getPosition().x;
|
|
||||||
double camY = info.getPosition().y;
|
|
||||||
double camZ = info.getPosition().z;
|
|
||||||
|
|
||||||
visible.clear();
|
|
||||||
flwVisible.clear();
|
|
||||||
|
|
||||||
renderInfos.int2ObjectEntrySet()
|
|
||||||
.stream()
|
|
||||||
.map(Map.Entry::getValue)
|
|
||||||
.forEach(renderInfo -> {
|
|
||||||
renderInfo.beginFrame(event.getClippingHelper(), event.getStack(), camX, camY, camZ);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Backend.getInstance()
|
|
||||||
.available()) {
|
|
||||||
flwRenderers.int2ObjectEntrySet()
|
|
||||||
.stream()
|
|
||||||
.map(Map.Entry::getValue)
|
|
||||||
.forEach(flwVisible::add);
|
|
||||||
|
|
||||||
for (RenderedContraption renderer : flwVisible) {
|
|
||||||
renderer.beginFrame(info, camX, camY, camZ);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
renderInfos.int2ObjectEntrySet()
|
|
||||||
.stream()
|
|
||||||
.map(Map.Entry::getValue)
|
|
||||||
.forEach(visible::add);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renderLayer(RenderLayerEvent event) {
|
|
||||||
if (Backend.getInstance().available()) {
|
|
||||||
renderLayerFlywheel(event);
|
|
||||||
} else {
|
|
||||||
renderLayerSBB(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderLayerFlywheel(RenderLayerEvent event) {
|
|
||||||
if (flwVisible.isEmpty()) return;
|
|
||||||
|
|
||||||
RenderType layer = event.getType();
|
|
||||||
|
|
||||||
layer.setupRenderState();
|
|
||||||
GlTextureUnit.T4.makeActive(); // the shaders expect light volumes to be in texture 4
|
|
||||||
|
|
||||||
ContraptionProgram structureShader = CreateContexts.STRUCTURE.getProgram(AllProgramSpecs.STRUCTURE);
|
|
||||||
|
|
||||||
structureShader.bind();
|
|
||||||
structureShader.uploadViewProjection(event.viewProjection);
|
|
||||||
structureShader.uploadCameraPos(event.camX, event.camY, event.camZ);
|
|
||||||
|
|
||||||
for (RenderedContraption renderedContraption : flwVisible) {
|
|
||||||
renderedContraption.doRenderLayer(layer, structureShader);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Backend.getInstance().canUseInstancing()) {
|
|
||||||
RenderLayer renderLayer = event.getLayer();
|
|
||||||
if (renderLayer != null) {
|
|
||||||
for (RenderedContraption renderer : flwVisible) {
|
|
||||||
renderer.materialManager.render(renderLayer, event.viewProjection, event.camX, event.camY, event.camZ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear the light volume state
|
|
||||||
GlTextureUnit.T4.makeActive();
|
|
||||||
glBindTexture(GL_TEXTURE_3D, 0);
|
|
||||||
|
|
||||||
layer.clearRenderState();
|
|
||||||
GlTextureUnit.T0.makeActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderLayerSBB(RenderLayerEvent event) {
|
|
||||||
visible.forEach(info -> renderContraptionLayerSBB(event, info));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderContraptionLayerSBB(RenderLayerEvent event, ContraptionRenderInfo renderInfo) {
|
|
||||||
RenderType layer = event.getType();
|
|
||||||
|
|
||||||
if (!renderInfo.isVisible()) return;
|
|
||||||
|
|
||||||
SuperByteBuffer contraptionBuffer = CreateClient.BUFFER_CACHE.get(CONTRAPTION, Pair.of(renderInfo.contraption, layer),
|
|
||||||
() -> buildStructureBuffer(renderInfo.renderWorld, renderInfo.contraption, layer));
|
|
||||||
|
|
||||||
if (!contraptionBuffer.isEmpty()) {
|
|
||||||
|
|
||||||
ContraptionMatrices matrices = renderInfo.getMatrices();
|
|
||||||
contraptionBuffer.transform(matrices.contraptionStack)
|
|
||||||
.light(matrices.entityMatrix)
|
|
||||||
.hybridLight()
|
|
||||||
.renderInto(matrices.entityStack, event.buffers.bufferSource().getBuffer(layer));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createRenderer(Contraption c) {
|
|
||||||
int entityId = c.entity.getId();
|
|
||||||
RenderedContraption contraption = flwRenderers.get(entityId);
|
|
||||||
|
|
||||||
if (contraption == null) {
|
|
||||||
PlacementSimulationWorld renderWorld = ContraptionRenderDispatcher.setupRenderWorld(world, c);
|
|
||||||
contraption = new RenderedContraption(c, renderWorld);
|
|
||||||
flwRenderers.put(entityId, contraption);
|
|
||||||
renderInfos.put(entityId, contraption);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContraptionRenderInfo getRenderInfo(Contraption c) {
|
|
||||||
int entityId = c.entity.getId();
|
|
||||||
ContraptionRenderInfo renderInfo = renderInfos.get(entityId);
|
|
||||||
|
|
||||||
if (renderInfo == null) {
|
|
||||||
PlacementSimulationWorld renderWorld = ContraptionRenderDispatcher.setupRenderWorld(world, c);
|
|
||||||
renderInfo = new ContraptionRenderInfo(c, renderWorld);
|
|
||||||
renderInfos.put(entityId, renderInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return renderInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void invalidate() {
|
|
||||||
for (RenderedContraption renderer : flwRenderers.values()) {
|
|
||||||
renderer.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
flwRenderers.clear();
|
|
||||||
renderInfos.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeDeadContraptions() {
|
|
||||||
flwRenderers.values().removeIf(renderer -> {
|
|
||||||
if (renderer.isDead()) {
|
|
||||||
renderer.invalidate();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeDeadHolders() {
|
|
||||||
renderInfos.values().removeIf(ContraptionRenderInfo::isDead);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue