mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-09 11:32:06 +01:00
WorldAttached contraption rendering
- ContraptionRenderDispatcher's meat was moved to WorldContraptions - Rename ContraptionWorldHolder to ContraptionRenderInfo - One ContraptionMatrices per contraption per frame - Cull contraptions - Bump flywheel version
This commit is contained in:
parent
ce2e2be2c2
commit
cd9f18a8c9
11 changed files with 365 additions and 245 deletions
|
@ -16,7 +16,7 @@ cursegradle_version = 1.4.0
|
|||
|
||||
# dependency versions
|
||||
registrate_version = 1.0.4
|
||||
flywheel_version = 1.16-0.2.0.31
|
||||
flywheel_version = 1.16-0.2.0.32
|
||||
jei_version = 7.7.1.110
|
||||
|
||||
# curseforge information
|
||||
|
|
|
@ -37,10 +37,9 @@ public class ContraptionEntityRenderer<C extends AbstractContraptionEntity> exte
|
|||
int overlay) {
|
||||
super.render(entity, yaw, partialTicks, ms, buffers, overlay);
|
||||
|
||||
ContraptionMatrices matrices = new ContraptionMatrices(ms, entity);
|
||||
Contraption contraption = entity.getContraption();
|
||||
if (contraption != null) {
|
||||
ContraptionRenderDispatcher.render(entity, contraption, matrices, buffers);
|
||||
ContraptionRenderDispatcher.render(entity, contraption, buffers);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,41 +10,52 @@ import net.minecraft.util.math.vector.Matrix3f;
|
|||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
|
||||
public class ContraptionMatrices {
|
||||
|
||||
public static final ContraptionMatrices IDENTITY = new ContraptionMatrices();
|
||||
|
||||
public final MatrixStack entityStack;
|
||||
public final MatrixStack contraptionStack;
|
||||
public final MatrixStack finalStack;
|
||||
public final Matrix4f entityMatrix;
|
||||
public final Matrix4f lightMatrix;
|
||||
|
||||
private ContraptionMatrices() {
|
||||
this.entityStack = new MatrixStack();
|
||||
this.contraptionStack = new MatrixStack();
|
||||
this.finalStack = new MatrixStack();
|
||||
this.entityMatrix = new Matrix4f();
|
||||
this.lightMatrix = new Matrix4f();
|
||||
}
|
||||
|
||||
public ContraptionMatrices(MatrixStack entityStack, AbstractContraptionEntity entity) {
|
||||
this.entityStack = entityStack;
|
||||
this.entityStack = copyStack(entityStack);
|
||||
this.contraptionStack = new MatrixStack();
|
||||
float partialTicks = AnimationTickHolder.getPartialTicks();
|
||||
entity.doLocalTransforms(partialTicks, new MatrixStack[] { this.contraptionStack });
|
||||
|
||||
entityMatrix = translateTo(entity, partialTicks);
|
||||
|
||||
lightMatrix = entityMatrix.copy();
|
||||
lightMatrix.multiply(contraptionStack.last().pose());
|
||||
|
||||
finalStack = copyStack(entityStack);
|
||||
transform(finalStack, contraptionStack);
|
||||
}
|
||||
|
||||
public MatrixStack getFinalStack() {
|
||||
MatrixStack finalStack = new MatrixStack();
|
||||
transform(finalStack, entityStack);
|
||||
transform(finalStack, contraptionStack);
|
||||
return finalStack;
|
||||
}
|
||||
|
||||
public Matrix4f getFinalModel() {
|
||||
Matrix4f finalModel = entityStack.last().pose().copy();
|
||||
finalModel.multiply(contraptionStack.last().pose());
|
||||
return finalModel;
|
||||
return finalStack.last().pose();
|
||||
}
|
||||
|
||||
public Matrix3f getFinalNormal() {
|
||||
Matrix3f finalNormal = entityStack.last().normal().copy();
|
||||
finalNormal.mul(contraptionStack.last().normal());
|
||||
return finalNormal;
|
||||
return finalStack.last().normal();
|
||||
}
|
||||
|
||||
public Matrix4f getFinalLight() {
|
||||
Matrix4f lightTransform = entityMatrix.copy();
|
||||
lightTransform.multiply(contraptionStack.last().pose());
|
||||
return lightTransform;
|
||||
return lightMatrix;
|
||||
}
|
||||
|
||||
public static Matrix4f translateTo(Entity entity, float partialTicks) {
|
||||
|
@ -62,4 +73,12 @@ public class ContraptionMatrices {
|
|||
.mul(transform.last()
|
||||
.normal());
|
||||
}
|
||||
|
||||
public static MatrixStack copyStack(MatrixStack ms) {
|
||||
MatrixStack cms = new MatrixStack();
|
||||
|
||||
transform(cms, ms);
|
||||
|
||||
return cms;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,31 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_QUADS;
|
||||
import static org.lwjgl.opengl.GL11.glBindTexture;
|
||||
import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
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.GatherContextEvent;
|
||||
import com.jozufozu.flywheel.event.ReloadRenderersEvent;
|
||||
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||
import com.jozufozu.flywheel.util.WorldAttached;
|
||||
import com.jozufozu.flywheel.util.transform.MatrixTransformStack;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.AllMovementBehaviours;
|
||||
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.content.contraptions.components.structureMovement.MovementBehaviour;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.render.AllProgramSpecs;
|
||||
import com.simibubi.create.foundation.render.Compartment;
|
||||
import com.simibubi.create.foundation.render.CreateContexts;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.render.TileEntityRenderHelper;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.BlockModelRenderer;
|
||||
import net.minecraft.client.renderer.BlockModelShapes;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
|
@ -53,7 +37,6 @@ import net.minecraft.client.renderer.WorldRenderer;
|
|||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.LightType;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.Template;
|
||||
|
@ -70,123 +53,25 @@ import net.minecraftforge.fml.common.Mod;
|
|||
public class ContraptionRenderDispatcher {
|
||||
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 int worldHolderRefreshCounter;
|
||||
|
||||
public static final Int2ObjectMap<RenderedContraption> RENDERERS = new Int2ObjectOpenHashMap<>();
|
||||
public static final Int2ObjectMap<ContraptionWorldHolder> WORLD_HOLDERS = new Int2ObjectOpenHashMap<>();
|
||||
private static final WorldAttached<WorldContraptions> WORLDS = new WorldAttached<>(WorldContraptions::new);
|
||||
|
||||
public static final Compartment<Pair<Contraption, RenderType>> CONTRAPTION = new Compartment<>();
|
||||
|
||||
public static void tick() {
|
||||
public static void tick(World world) {
|
||||
if (Minecraft.getInstance().isPaused()) return;
|
||||
|
||||
for (RenderedContraption contraption : RENDERERS.values()) {
|
||||
ContraptionLighter<?> lighter = contraption.getLighter();
|
||||
if (lighter.getBounds().volume() < AllConfigs.CLIENT.maxContraptionLightVolume.get())
|
||||
lighter.tick(contraption);
|
||||
|
||||
contraption.kinetics.tick();
|
||||
}
|
||||
|
||||
worldHolderRefreshCounter++;
|
||||
if (worldHolderRefreshCounter >= 20) {
|
||||
removeDeadHolders();
|
||||
worldHolderRefreshCounter = 0;
|
||||
}
|
||||
WORLDS.get(world).tick();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void beginFrame(BeginFrameEvent event) {
|
||||
ActiveRenderInfo info = event.getInfo();
|
||||
double camX = info.getPosition().x;
|
||||
double camY = info.getPosition().y;
|
||||
double camZ = info.getPosition().z;
|
||||
for (RenderedContraption renderer : RENDERERS.values()) {
|
||||
renderer.beginFrame(info, camX, camY, camZ);
|
||||
}
|
||||
WORLDS.get(event.getWorld()).beginFrame(event);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void renderLayer(RenderLayerEvent event) {
|
||||
if (Backend.getInstance().available()) {
|
||||
renderLayerFlywheel(event);
|
||||
} else {
|
||||
renderLayerSBB(event);
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderLayerFlywheel(RenderLayerEvent event) {
|
||||
removeDeadContraptions();
|
||||
|
||||
if (RENDERERS.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 renderer : RENDERERS.values()) {
|
||||
renderer.doRenderLayer(layer, structureShader);
|
||||
}
|
||||
|
||||
if (Backend.getInstance().canUseInstancing()) {
|
||||
RenderLayer renderLayer = event.getLayer();
|
||||
if (renderLayer != null) {
|
||||
for (RenderedContraption renderer : RENDERERS.values()) {
|
||||
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 static void renderLayerSBB(RenderLayerEvent event) {
|
||||
ContraptionHandler.loadedContraptions.get(event.getWorld())
|
||||
.values()
|
||||
.stream()
|
||||
.map(Reference::get)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(entity -> renderContraptionLayerSBB(event, entity));
|
||||
}
|
||||
|
||||
private static void renderContraptionLayerSBB(RenderLayerEvent event, AbstractContraptionEntity entity) {
|
||||
RenderType layer = event.getType();
|
||||
|
||||
Contraption contraption = entity.getContraption();
|
||||
Pair<Contraption, RenderType> key = Pair.of(contraption, layer);
|
||||
|
||||
SuperByteBuffer contraptionBuffer = CreateClient.BUFFER_CACHE.get(CONTRAPTION, key, () -> buildStructureBuffer(getWorldHolder(entity.level, contraption).renderWorld, contraption, layer));
|
||||
|
||||
if (!contraptionBuffer.isEmpty()) {
|
||||
MatrixStack stack = event.stack;
|
||||
|
||||
stack.pushPose();
|
||||
|
||||
double x = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.xOld, entity.getX()) - event.camX;
|
||||
double y = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.yOld, entity.getY()) - event.camY;
|
||||
double z = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.zOld, entity.getZ()) - event.camZ;
|
||||
|
||||
stack.translate(x, y, z);
|
||||
ContraptionMatrices matrices = new ContraptionMatrices(stack, entity);
|
||||
contraptionBuffer.transform(matrices.contraptionStack)
|
||||
.light(matrices.entityMatrix)
|
||||
.hybridLight()
|
||||
.renderInto(matrices.entityStack, event.buffers.bufferSource().getBuffer(layer));
|
||||
|
||||
stack.popPose();
|
||||
}
|
||||
|
||||
WORLDS.get(event.getWorld()).renderLayer(event);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
@ -198,44 +83,13 @@ public class ContraptionRenderDispatcher {
|
|||
invalidateAll();
|
||||
}
|
||||
|
||||
public static void render(AbstractContraptionEntity entity, Contraption contraption,
|
||||
ContraptionMatrices matrices, IRenderTypeBuffer buffers) {
|
||||
public static void render(AbstractContraptionEntity entity, Contraption contraption, IRenderTypeBuffer buffers) {
|
||||
World world = entity.level;
|
||||
|
||||
if (Backend.getInstance().available()) {
|
||||
getRenderer(world, contraption); // hack to create the RenderedContraption when using Flywheel
|
||||
}
|
||||
ContraptionRenderInfo renderInfo = WORLDS.get(world)
|
||||
.getRenderInfo(contraption);
|
||||
|
||||
PlacementSimulationWorld renderWorld = getWorldHolder(world, contraption).renderWorld;
|
||||
|
||||
ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, matrices, buffers);
|
||||
}
|
||||
|
||||
private static RenderedContraption getRenderer(World world, Contraption c) {
|
||||
int entityId = c.entity.getId();
|
||||
RenderedContraption contraption = RENDERERS.get(entityId);
|
||||
|
||||
if (contraption == null) {
|
||||
PlacementSimulationWorld renderWorld = setupRenderWorld(world, c);
|
||||
contraption = new RenderedContraption(c, renderWorld);
|
||||
RENDERERS.put(entityId, contraption);
|
||||
WORLD_HOLDERS.put(entityId, contraption);
|
||||
}
|
||||
|
||||
return contraption;
|
||||
}
|
||||
|
||||
private static ContraptionWorldHolder getWorldHolder(World world, Contraption c) {
|
||||
int entityId = c.entity.getId();
|
||||
ContraptionWorldHolder holder = WORLD_HOLDERS.get(entityId);
|
||||
|
||||
if (holder == null) {
|
||||
PlacementSimulationWorld renderWorld = setupRenderWorld(world, c);
|
||||
holder = new ContraptionWorldHolder(c, renderWorld);
|
||||
WORLD_HOLDERS.put(entityId, holder);
|
||||
}
|
||||
|
||||
return holder;
|
||||
renderDynamic(world, renderInfo.renderWorld, contraption, renderInfo.getMatrices(), buffers);
|
||||
}
|
||||
|
||||
public static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) {
|
||||
|
@ -291,7 +145,7 @@ public class ContraptionRenderDispatcher {
|
|||
}
|
||||
}
|
||||
|
||||
private static SuperByteBuffer buildStructureBuffer(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
|
||||
public static SuperByteBuffer buildStructureBuffer(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) {
|
||||
BufferBuilder builder = buildStructure(renderWorld, c, layer);
|
||||
return new SuperByteBuffer(builder);
|
||||
}
|
||||
|
@ -349,26 +203,6 @@ public class ContraptionRenderDispatcher {
|
|||
}
|
||||
|
||||
public static void invalidateAll() {
|
||||
for (RenderedContraption renderer : RENDERERS.values()) {
|
||||
renderer.invalidate();
|
||||
}
|
||||
|
||||
RENDERERS.clear();
|
||||
WORLD_HOLDERS.clear();
|
||||
WORLDS.empty(WorldContraptions::invalidate);
|
||||
}
|
||||
|
||||
public static void removeDeadContraptions() {
|
||||
RENDERERS.values().removeIf(renderer -> {
|
||||
if (renderer.isDead()) {
|
||||
renderer.invalidate();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public static void removeDeadHolders() {
|
||||
WORLD_HOLDERS.values().removeIf(ContraptionWorldHolder::isDead);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
||||
|
||||
import net.minecraft.client.renderer.culling.ClippingHelper;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public class ContraptionRenderInfo {
|
||||
public final Contraption contraption;
|
||||
public final PlacementSimulationWorld renderWorld;
|
||||
|
||||
private ContraptionMatrices matrices = ContraptionMatrices.IDENTITY;
|
||||
private boolean visible;
|
||||
|
||||
public ContraptionRenderInfo(Contraption contraption, PlacementSimulationWorld renderWorld) {
|
||||
this.contraption = contraption;
|
||||
this.renderWorld = renderWorld;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return contraption.entity.getId();
|
||||
}
|
||||
|
||||
public boolean isDead() {
|
||||
return !contraption.entity.isAlive();
|
||||
}
|
||||
|
||||
public void beginFrame(ClippingHelper clippingHelper, MatrixStack mainStack, double camX, double camY, double camZ) {
|
||||
AbstractContraptionEntity entity = contraption.entity;
|
||||
|
||||
visible = clippingHelper.isVisible(entity.getBoundingBoxForCulling().inflate(2));
|
||||
|
||||
mainStack.pushPose();
|
||||
|
||||
double x = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.xOld, entity.getX()) - camX;
|
||||
double y = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.yOld, entity.getY()) - camY;
|
||||
double z = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), entity.zOld, entity.getZ()) - camZ;
|
||||
|
||||
mainStack.translate(x, y, z);
|
||||
|
||||
matrices = new ContraptionMatrices(mainStack, entity);
|
||||
|
||||
mainStack.popPose();
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return visible && contraption.entity.isAlive();
|
||||
}
|
||||
|
||||
public ContraptionMatrices getMatrices() {
|
||||
return matrices;
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement.render;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
|
||||
import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld;
|
||||
|
||||
public class ContraptionWorldHolder {
|
||||
public final Contraption contraption;
|
||||
public final PlacementSimulationWorld renderWorld;
|
||||
|
||||
public ContraptionWorldHolder(Contraption contraption, PlacementSimulationWorld renderWorld) {
|
||||
this.contraption = contraption;
|
||||
this.renderWorld = renderWorld;
|
||||
}
|
||||
|
||||
public int getEntityId() {
|
||||
return contraption.entity.getId();
|
||||
}
|
||||
|
||||
public boolean isDead() {
|
||||
return !contraption.entity.isAlive();
|
||||
}
|
||||
}
|
|
@ -11,25 +11,25 @@ import com.simibubi.create.foundation.utility.outliner.AABBOutline;
|
|||
|
||||
public class LightVolumeDebugger {
|
||||
public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) {
|
||||
ContraptionRenderDispatcher.RENDERERS.values()
|
||||
.stream()
|
||||
.flatMap(r -> {
|
||||
GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume();
|
||||
GridAlignedBB sample = r.getLighter().lightVolume.getSampleVolume();
|
||||
|
||||
ArrayList<Pair<GridAlignedBB, Integer>> pairs = new ArrayList<>(2);
|
||||
|
||||
pairs.add(Pair.of(texture, 0xFFFFFF));
|
||||
pairs.add(Pair.of(sample, 0xFFFF00));
|
||||
|
||||
return pairs.stream();
|
||||
})
|
||||
.map(pair -> {
|
||||
AABBOutline outline = new AABBOutline(GridAlignedBB.toAABB(pair.getFirst()));
|
||||
|
||||
outline.getParams().colored(pair.getSecond());
|
||||
return outline;
|
||||
})
|
||||
.forEach(outline -> outline.render(ms, buffer, AnimationTickHolder.getPartialTicks()));
|
||||
// ContraptionRenderDispatcher.RENDERERS.values()
|
||||
// .stream()
|
||||
// .flatMap(r -> {
|
||||
// GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume();
|
||||
// GridAlignedBB sample = r.getLighter().lightVolume.getSampleVolume();
|
||||
//
|
||||
// ArrayList<Pair<GridAlignedBB, Integer>> pairs = new ArrayList<>(2);
|
||||
//
|
||||
// pairs.add(Pair.of(texture, 0xFFFFFF));
|
||||
// pairs.add(Pair.of(sample, 0xFFFF00));
|
||||
//
|
||||
// return pairs.stream();
|
||||
// })
|
||||
// .map(pair -> {
|
||||
// AABBOutline outline = new AABBOutline(GridAlignedBB.toAABB(pair.getFirst()));
|
||||
//
|
||||
// outline.getParams().colored(pair.getSecond());
|
||||
// return outline;
|
||||
// })
|
||||
// .forEach(outline -> outline.render(ms, buffer, AnimationTickHolder.getPartialTicks()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,7 @@ import javax.annotation.Nullable;
|
|||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes;
|
||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||
import com.jozufozu.flywheel.backend.instancing.IInstanceRendered;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialGroup;
|
||||
import com.jozufozu.flywheel.backend.material.MaterialManager;
|
||||
import com.jozufozu.flywheel.backend.model.ArrayModelRenderer;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
|
@ -41,7 +38,7 @@ import net.minecraft.util.math.MathHelper;
|
|||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class RenderedContraption extends ContraptionWorldHolder {
|
||||
public class RenderedContraption extends ContraptionRenderInfo {
|
||||
public static final VertexFormat FORMAT = VertexFormat.builder()
|
||||
.addAttributes(CommonAttributes.VEC3,
|
||||
CommonAttributes.NORMAL,
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -141,7 +141,7 @@ public class ClientEvents {
|
|||
PlacementHelpers.tick();
|
||||
CreateClient.OUTLINER.tickOutlines();
|
||||
CreateClient.GHOST_BLOCKS.tickGhosts();
|
||||
ContraptionRenderDispatcher.tick();
|
||||
ContraptionRenderDispatcher.tick(world);
|
||||
BlueprintOverlayRenderer.tick();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,17 +6,19 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraftforge.common.util.NonNullFunction;
|
||||
|
||||
public class WorldAttached<T> {
|
||||
|
||||
static List<Map<IWorld, ?>> allMaps = new ArrayList<>();
|
||||
Map<IWorld, T> attached;
|
||||
private Function<IWorld, T> factory;
|
||||
private final NonNullFunction<IWorld, T> factory;
|
||||
|
||||
public WorldAttached(Function<IWorld, T> factory) {
|
||||
public WorldAttached(NonNullFunction<IWorld, T> factory) {
|
||||
this.factory = factory;
|
||||
attached = new HashMap<>();
|
||||
allMaps.add(attached);
|
||||
|
@ -26,7 +28,7 @@ public class WorldAttached<T> {
|
|||
allMaps.forEach(m -> m.remove(world));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
public T get(IWorld world) {
|
||||
T t = attached.get(world);
|
||||
if (t != null)
|
||||
|
|
Loading…
Reference in a new issue