mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 07:26:48 +01:00
Improve virtual model rendering
- Use VirtualEmptyBlockGetter instead of mc.level - Move getBufferBuilder from BlockModel to ModelUtil - Add static .is method to VirtualEmptyModelData
This commit is contained in:
parent
26c35e31b6
commit
810cae681a
4 changed files with 181 additions and 46 deletions
|
@ -1,24 +1,14 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat;
|
||||||
import com.jozufozu.flywheel.core.Formats;
|
import com.jozufozu.flywheel.core.Formats;
|
||||||
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
import com.jozufozu.flywheel.util.BufferBuilderReader;
|
||||||
import com.jozufozu.flywheel.util.RenderMath;
|
import com.jozufozu.flywheel.util.RenderMath;
|
||||||
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
|
||||||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
|
||||||
import net.minecraft.client.resources.model.BakedModel;
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraft.core.Direction;
|
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +32,7 @@ public class BlockModel implements Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) {
|
public BlockModel(BakedModel model, BlockState referenceState, PoseStack ms) {
|
||||||
reader = new BufferBuilderReader(getBufferBuilder(model, referenceState, ms));
|
reader = new BufferBuilderReader(ModelUtil.getBufferBuilder(model, referenceState, ms));
|
||||||
name = referenceState.toString();
|
name = referenceState.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,32 +66,4 @@ public class BlockModel implements Model {
|
||||||
buffer.endVertex();
|
buffer.endVertex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) {
|
|
||||||
Minecraft mc = Minecraft.getInstance();
|
|
||||||
BlockRenderDispatcher dispatcher = mc.getBlockRenderer();
|
|
||||||
ModelBlockRenderer blockRenderer = dispatcher.getModelRenderer();
|
|
||||||
BufferBuilder builder = new BufferBuilder(512);
|
|
||||||
|
|
||||||
// BakedQuadWrapper quadReader = new BakedQuadWrapper();
|
|
||||||
//
|
|
||||||
// IModelData modelData = model.getModelData(mc.world, BlockPos.ZERO.up(255), referenceState, VirtualEmptyModelData.INSTANCE);
|
|
||||||
// List<BakedQuad> quads = Arrays.stream(dirs)
|
|
||||||
// .flatMap(dir -> model.getQuads(referenceState, dir, mc.world.rand, modelData).stream())
|
|
||||||
// .collect(Collectors.toList());
|
|
||||||
|
|
||||||
builder.begin(com.mojang.blaze3d.vertex.VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
|
||||||
blockRenderer.tesselateBlock(mc.level, model, referenceState, BlockPos.ZERO.above(255), ms, builder, true, mc.level.random, 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
|
|
||||||
builder.end();
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOWN, UP, NORTH, SOUTH, WEST, EAST, null
|
|
||||||
private static final Direction[] dirs;
|
|
||||||
|
|
||||||
static {
|
|
||||||
Direction[] directions = Direction.values();
|
|
||||||
|
|
||||||
dirs = Arrays.copyOf(directions, directions.length + 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
package com.jozufozu.flywheel.core.model;
|
package com.jozufozu.flywheel.core.model;
|
||||||
|
|
||||||
import static com.mojang.blaze3d.vertex.VertexFormat.Mode.QUADS;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.util.Lazy;
|
import com.jozufozu.flywheel.util.Lazy;
|
||||||
|
import com.jozufozu.flywheel.util.VirtualEmptyBlockGetter;
|
||||||
|
import com.jozufozu.flywheel.util.VirtualEmptyModelData;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||||
import com.mojang.blaze3d.vertex.PoseStack;
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
import net.minecraft.client.renderer.ItemBlockRenderTypes;
|
||||||
|
@ -16,7 +18,9 @@ import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.client.renderer.block.BlockModelShaper;
|
import net.minecraft.client.renderer.block.BlockModelShaper;
|
||||||
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
import net.minecraft.client.renderer.block.ModelBlockRenderer;
|
||||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||||
|
import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.RenderShape;
|
import net.minecraft.world.level.block.RenderShape;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
@ -26,13 +30,42 @@ import net.minecraftforge.client.model.data.EmptyModelData;
|
||||||
|
|
||||||
public class ModelUtil {
|
public class ModelUtil {
|
||||||
private static final Lazy<ModelBlockRenderer> MODEL_RENDERER = Lazy.of(() -> new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()));
|
private static final Lazy<ModelBlockRenderer> MODEL_RENDERER = Lazy.of(() -> new ModelBlockRenderer(Minecraft.getInstance().getBlockColors()));
|
||||||
private static final Lazy<BlockModelShaper> BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShaper());
|
|
||||||
|
// DOWN, UP, NORTH, SOUTH, WEST, EAST, null
|
||||||
|
private static final Direction[] CULL_FACES;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Direction[] directions = Direction.values();
|
||||||
|
|
||||||
|
CULL_FACES = Arrays.copyOf(directions, directions.length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BufferBuilder getBufferBuilder(BakedModel model, BlockState referenceState, PoseStack ms) {
|
||||||
|
ModelBlockRenderer blockRenderer = Minecraft.getInstance().getBlockRenderer().getModelRenderer();
|
||||||
|
BufferBuilder builder = new BufferBuilder(512);
|
||||||
|
|
||||||
|
// BakedQuadWrapper quadReader = new BakedQuadWrapper();
|
||||||
|
//
|
||||||
|
// IModelData modelData = model.getModelData(VirtualEmptyBlockGetter.INSTANCE, BlockPos.ZERO, referenceState, VirtualEmptyModelData.INSTANCE);
|
||||||
|
// List<BakedQuad> quads = Arrays.stream(CULL_FACES)
|
||||||
|
// .flatMap(dir -> model.getQuads(referenceState, dir, new Random(), modelData).stream())
|
||||||
|
// .collect(Collectors.toList());
|
||||||
|
|
||||||
|
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
|
blockRenderer.tesselateBlock(VirtualEmptyBlockGetter.INSTANCE, model, referenceState, BlockPos.ZERO, ms, builder,
|
||||||
|
true, new Random(), 42, OverlayTexture.NO_OVERLAY, VirtualEmptyModelData.INSTANCE);
|
||||||
|
builder.end();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
public static BufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
public static BufferBuilder getBufferBuilderFromTemplate(BlockAndTintGetter renderWorld, RenderType layer, Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
||||||
|
ModelBlockRenderer modelRenderer = MODEL_RENDERER.get();
|
||||||
|
BlockModelShaper blockModels = Minecraft.getInstance().getModelManager().getBlockModelShaper();
|
||||||
|
|
||||||
PoseStack ms = new PoseStack();
|
PoseStack ms = new PoseStack();
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
BufferBuilder builder = new BufferBuilder(DefaultVertexFormat.BLOCK.getIntegerSize());
|
BufferBuilder builder = new BufferBuilder(512);
|
||||||
builder.begin(QUADS, DefaultVertexFormat.BLOCK);
|
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(layer);
|
ForgeHooksClient.setRenderType(layer);
|
||||||
ModelBlockRenderer.enableCaching();
|
ModelBlockRenderer.enableCaching();
|
||||||
|
@ -48,8 +81,8 @@ public class ModelUtil {
|
||||||
|
|
||||||
ms.pushPose();
|
ms.pushPose();
|
||||||
ms.translate(pos.getX(), pos.getY(), pos.getZ());
|
ms.translate(pos.getX(), pos.getY(), pos.getZ());
|
||||||
MODEL_RENDERER.get().tesselateBlock(renderWorld, BLOCK_MODELS.get().getBlockModel(state), state, pos, ms, builder, true,
|
modelRenderer.tesselateBlock(renderWorld, blockModels.getBlockModel(state), state, pos, ms, builder,
|
||||||
random, 42, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE);
|
true, random, 42, OverlayTexture.NO_OVERLAY, EmptyModelData.INSTANCE);
|
||||||
ms.popPose();
|
ms.popPose();
|
||||||
}
|
}
|
||||||
ModelBlockRenderer.clearCache();
|
ModelBlockRenderer.clearCache();
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
package com.jozufozu.flywheel.util;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.ColorResolver;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.biome.Biomes;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.chunk.DataLayer;
|
||||||
|
import net.minecraft.world.level.chunk.LightChunkGetter;
|
||||||
|
import net.minecraft.world.level.lighting.LayerLightEventListener;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.level.material.Fluids;
|
||||||
|
|
||||||
|
public enum VirtualEmptyBlockGetter implements BlockAndTintGetter {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
private final LevelLightEngine lightEngine = new LevelLightEngine(new LightChunkGetter() {
|
||||||
|
@Override
|
||||||
|
public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) {
|
||||||
|
return VirtualEmptyBlockGetter.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockGetter getLevel() {
|
||||||
|
return VirtualEmptyBlockGetter.this;
|
||||||
|
}
|
||||||
|
}, false, false) {
|
||||||
|
private static final LayerLightEventListener SKY_DUMMY_LISTENER = new LayerLightEventListener() {
|
||||||
|
@Override
|
||||||
|
public void checkBlock(BlockPos pos) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBlockEmissionIncrease(BlockPos pos, int p_164456_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasLightWork() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int runUpdates(int p_164449_, boolean p_164450_, boolean p_164451_) {
|
||||||
|
return p_164449_;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSectionStatus(SectionPos pos, boolean p_75838_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enableLightSources(ChunkPos pos, boolean p_164453_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataLayer getDataLayerData(SectionPos pos) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightValue(BlockPos pos) {
|
||||||
|
return 15;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayerLightEventListener getLayerListener(LightLayer layer) {
|
||||||
|
if (layer == LightLayer.BLOCK) {
|
||||||
|
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
|
||||||
|
} else {
|
||||||
|
return SKY_DUMMY_LISTENER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawBrightness(BlockPos pos, int skyDarken) {
|
||||||
|
return 15 - skyDarken;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static boolean is(BlockAndTintGetter blockGetter) {
|
||||||
|
return blockGetter == INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntity getBlockEntity(BlockPos pos) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(BlockPos pos) {
|
||||||
|
return Blocks.AIR.defaultBlockState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidState getFluidState(BlockPos pos) {
|
||||||
|
return Fluids.EMPTY.defaultFluidState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinBuildHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getShade(Direction direction, boolean bool) {
|
||||||
|
return Minecraft.getInstance().level.getShade(direction, bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelLightEngine getLightEngine() {
|
||||||
|
return lightEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockTint(BlockPos pos, ColorResolver resolver) {
|
||||||
|
Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getOrThrow(Biomes.PLAINS);
|
||||||
|
return resolver.getColor(plainsBiome, pos.getX(), pos.getZ());
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,10 @@ public enum VirtualEmptyModelData implements IModelData {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
|
public static boolean is(IModelData data) {
|
||||||
|
return data == INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasProperty(ModelProperty<?> prop) {
|
public boolean hasProperty(ModelProperty<?> prop) {
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue