mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-07 12:56:31 +01:00
The bakery
- Port model baking infrastructure. - VirtualEmptyModelData seems like it isn't needed anymore, but I left some stubs in.
This commit is contained in:
parent
7bc6a7559a
commit
aae0200d93
7 changed files with 104 additions and 100 deletions
|
@ -17,6 +17,7 @@ import com.jozufozu.flywheel.api.vertex.VertexListProviderRegistry;
|
||||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||||
import com.jozufozu.flywheel.lib.material.Materials;
|
import com.jozufozu.flywheel.lib.material.Materials;
|
||||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||||
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||||
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
import com.mojang.blaze3d.vertex.BufferBuilder.DrawState;
|
||||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
@ -56,17 +57,17 @@ public final class ModelUtil {
|
||||||
return dispatcher;
|
return dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isVanillaBufferEmpty(Pair<DrawState, ByteBuffer> pair) {
|
public static boolean isVanillaBufferEmpty(BufferBuilder.RenderedBuffer renderedBuffer) {
|
||||||
return pair.getFirst().vertexCount() == 0;
|
return renderedBuffer.drawState().vertexCount() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MemoryBlock convertVanillaBuffer(Pair<DrawState, ByteBuffer> pair, VertexType vertexType) {
|
public static MemoryBlock convertVanillaBuffer(BufferBuilder.RenderedBuffer renderedBuffer, VertexType vertexType) {
|
||||||
DrawState drawState = pair.getFirst();
|
DrawState drawState = renderedBuffer.drawState();
|
||||||
int vertexCount = drawState.vertexCount();
|
int vertexCount = drawState.vertexCount();
|
||||||
VertexFormat srcFormat = drawState.format();
|
VertexFormat srcFormat = drawState.format();
|
||||||
|
|
||||||
ByteBuffer src = pair.getSecond();
|
ByteBuffer src = renderedBuffer.vertexBuffer();
|
||||||
MemoryBlock dst = MemoryBlock.malloc(vertexCount * vertexType.getLayout().getStride());
|
MemoryBlock dst = MemoryBlock.malloc((long) vertexCount * vertexType.getLayout().getStride());
|
||||||
long srcPtr = MemoryUtil.memAddress(src);
|
long srcPtr = MemoryUtil.memAddress(src);
|
||||||
long dstPtr = dst.ptr();
|
long dstPtr = dst.ptr();
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,14 @@ 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.client.resources.model.BakedModel;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
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;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||||
|
import net.minecraftforge.client.ChunkRenderTypeSet;
|
||||||
import net.minecraftforge.client.ForgeHooksClient;
|
import net.minecraftforge.client.ForgeHooksClient;
|
||||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
import net.minecraftforge.client.model.data.ModelData;
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
|
||||||
|
|
||||||
public final class BakedModelBufferer {
|
public final class BakedModelBufferer {
|
||||||
private static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new);
|
private static final RenderType[] CHUNK_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new);
|
||||||
|
@ -38,52 +39,52 @@ public final class BakedModelBufferer {
|
||||||
private BakedModelBufferer() {
|
private BakedModelBufferer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bufferSingle(ModelBlockRenderer blockRenderer, BlockAndTintGetter renderWorld, BakedModel model, BlockState state, @Nullable PoseStack poseStack, IModelData modelData, ResultConsumer resultConsumer) {
|
public static void bufferSingle(ModelBlockRenderer blockRenderer, BlockAndTintGetter renderWorld, BakedModel model, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer resultConsumer) {
|
||||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
if (poseStack == null) {
|
if (poseStack == null) {
|
||||||
poseStack = objects.identityPoseStack;
|
poseStack = objects.identityPoseStack;
|
||||||
}
|
}
|
||||||
Random random = objects.random;
|
var random = objects.random;
|
||||||
BufferBuilder[] buffers = objects.shadedBuffers;
|
BufferBuilder[] buffers = objects.shadedBuffers;
|
||||||
|
|
||||||
|
var renderTypes = model.getRenderTypes(state, random, modelData);
|
||||||
|
|
||||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||||
|
|
||||||
if (!ItemBlockRenderTypes.canRenderInLayer(state, renderType)) {
|
if (!renderTypes.contains(renderType)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferBuilder buffer = buffers[layerIndex];
|
BufferBuilder buffer = buffers[layerIndex];
|
||||||
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(renderType);
|
|
||||||
|
|
||||||
poseStack.pushPose();
|
poseStack.pushPose();
|
||||||
blockRenderer.tesselateBlock(renderWorld, model, state, BlockPos.ZERO, poseStack, buffer, false, random, 42L, OverlayTexture.NO_OVERLAY, modelData);
|
blockRenderer.tesselateBlock(renderWorld, model, state, BlockPos.ZERO, poseStack, buffer, false, random, 42L, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
||||||
poseStack.popPose();
|
poseStack.popPose();
|
||||||
|
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Pair<DrawState, ByteBuffer> data = buffer.popNextBuffer();
|
var data = buffer.end();
|
||||||
resultConsumer.accept(renderType, data);
|
resultConsumer.accept(renderType, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bufferSingleShadeSeparated(ModelBlockRenderer blockRenderer, BlockAndTintGetter renderWorld, BakedModel model, BlockState state, @Nullable PoseStack poseStack, IModelData modelData, ShadeSeparatedResultConsumer resultConsumer) {
|
public static void bufferSingleShadeSeparated(ModelBlockRenderer blockRenderer, BlockAndTintGetter renderWorld, BakedModel model, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ShadeSeparatedResultConsumer resultConsumer) {
|
||||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
if (poseStack == null) {
|
if (poseStack == null) {
|
||||||
poseStack = objects.identityPoseStack;
|
poseStack = objects.identityPoseStack;
|
||||||
}
|
}
|
||||||
Random random = objects.random;
|
var random = objects.random;
|
||||||
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
|
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
|
||||||
BufferBuilder[] shadedBuffers = objects.shadedBuffers;
|
BufferBuilder[] shadedBuffers = objects.shadedBuffers;
|
||||||
BufferBuilder[] unshadedBuffers = objects.unshadedBuffers;
|
BufferBuilder[] unshadedBuffers = objects.unshadedBuffers;
|
||||||
|
|
||||||
|
var renderTypes = model.getRenderTypes(state, random, modelData);
|
||||||
|
|
||||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||||
|
|
||||||
if (!ItemBlockRenderTypes.canRenderInLayer(state, renderType)) {
|
if (!renderTypes.contains(renderType)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,26 +94,22 @@ public final class BakedModelBufferer {
|
||||||
shadedBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
shadedBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
unshadedBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
unshadedBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(renderType);
|
|
||||||
|
|
||||||
poseStack.pushPose();
|
poseStack.pushPose();
|
||||||
blockRenderer.tesselateBlock(renderWorld, model, state, BlockPos.ZERO, poseStack, shadeSeparatingWrapper, false, random, 42L, OverlayTexture.NO_OVERLAY, modelData);
|
blockRenderer.tesselateBlock(renderWorld, model, state, BlockPos.ZERO, poseStack, shadeSeparatingWrapper, false, random, 42L, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
||||||
poseStack.popPose();
|
poseStack.popPose();
|
||||||
|
|
||||||
shadedBuffer.end();
|
shadedBuffer.end();
|
||||||
unshadedBuffer.end();
|
unshadedBuffer.end();
|
||||||
Pair<DrawState, ByteBuffer> shadedData = shadedBuffer.popNextBuffer();
|
var shadedData = shadedBuffer.end();
|
||||||
Pair<DrawState, ByteBuffer> unshadedData = unshadedBuffer.popNextBuffer();
|
var unshadedData = unshadedBuffer.end();
|
||||||
resultConsumer.accept(renderType, true, shadedData);
|
resultConsumer.accept(renderType, true, shadedData);
|
||||||
resultConsumer.accept(renderType, false, unshadedData);
|
resultConsumer.accept(renderType, false, unshadedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(null);
|
|
||||||
|
|
||||||
shadeSeparatingWrapper.clear();
|
shadeSeparatingWrapper.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bufferBlock(BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, BlockState state, @Nullable PoseStack poseStack, IModelData modelData, ResultConsumer resultConsumer) {
|
public static void bufferBlock(BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ResultConsumer resultConsumer) {
|
||||||
if (state.getRenderShape() != RenderShape.MODEL) {
|
if (state.getRenderShape() != RenderShape.MODEL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +117,7 @@ public final class BakedModelBufferer {
|
||||||
bufferSingle(renderDispatcher.getModelRenderer(), renderWorld, renderDispatcher.getBlockModel(state), state, poseStack, modelData, resultConsumer);
|
bufferSingle(renderDispatcher.getModelRenderer(), renderWorld, renderDispatcher.getBlockModel(state), state, poseStack, modelData, resultConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bufferBlockShadeSeparated(BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, BlockState state, @Nullable PoseStack poseStack, IModelData modelData, ShadeSeparatedResultConsumer resultConsumer) {
|
public static void bufferBlockShadeSeparated(BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, BlockState state, @Nullable PoseStack poseStack, ModelData modelData, ShadeSeparatedResultConsumer resultConsumer) {
|
||||||
if (state.getRenderShape() != RenderShape.MODEL) {
|
if (state.getRenderShape() != RenderShape.MODEL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -128,12 +125,12 @@ public final class BakedModelBufferer {
|
||||||
bufferSingleShadeSeparated(renderDispatcher.getModelRenderer(), renderWorld, renderDispatcher.getBlockModel(state), state, poseStack, modelData, resultConsumer);
|
bufferSingleShadeSeparated(renderDispatcher.getModelRenderer(), renderWorld, renderDispatcher.getBlockModel(state), state, poseStack, modelData, resultConsumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bufferMultiBlock(Collection<StructureTemplate.StructureBlockInfo> blocks, BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, @Nullable PoseStack poseStack, Map<BlockPos, IModelData> modelDataMap, ResultConsumer resultConsumer) {
|
public static void bufferMultiBlock(Collection<StructureTemplate.StructureBlockInfo> blocks, BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, @Nullable PoseStack poseStack, Map<BlockPos, ModelData> modelDataMap, ResultConsumer resultConsumer) {
|
||||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
if (poseStack == null) {
|
if (poseStack == null) {
|
||||||
poseStack = objects.identityPoseStack;
|
poseStack = objects.identityPoseStack;
|
||||||
}
|
}
|
||||||
Random random = objects.random;
|
var random = objects.random;
|
||||||
|
|
||||||
BufferBuilder[] buffers = objects.shadedBuffers;
|
BufferBuilder[] buffers = objects.shadedBuffers;
|
||||||
for (BufferBuilder buffer : buffers) {
|
for (BufferBuilder buffer : buffers) {
|
||||||
|
@ -144,53 +141,52 @@ public final class BakedModelBufferer {
|
||||||
ModelBlockRenderer.enableCaching();
|
ModelBlockRenderer.enableCaching();
|
||||||
|
|
||||||
for (StructureTemplate.StructureBlockInfo blockInfo : blocks) {
|
for (StructureTemplate.StructureBlockInfo blockInfo : blocks) {
|
||||||
BlockState state = blockInfo.state;
|
BlockState state = blockInfo.state();
|
||||||
|
|
||||||
if (state.getRenderShape() != RenderShape.MODEL) {
|
if (state.getRenderShape() != RenderShape.MODEL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BakedModel model = renderDispatcher.getBlockModel(state);
|
BakedModel model = renderDispatcher.getBlockModel(state);
|
||||||
BlockPos pos = blockInfo.pos;
|
BlockPos pos = blockInfo.pos();
|
||||||
long seed = state.getSeed(pos);
|
long seed = state.getSeed(pos);
|
||||||
IModelData modelData = modelDataMap.getOrDefault(pos, EmptyModelData.INSTANCE);
|
ModelData modelData = modelDataMap.getOrDefault(pos, ModelData.EMPTY);
|
||||||
|
|
||||||
|
var renderTypes = model.getRenderTypes(state, random, modelData);
|
||||||
|
|
||||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||||
|
|
||||||
if (!ItemBlockRenderTypes.canRenderInLayer(state, renderType)) {
|
if (!renderTypes.contains(renderType)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferBuilder buffer = buffers[layerIndex];
|
BufferBuilder buffer = buffers[layerIndex];
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(renderType);
|
|
||||||
|
|
||||||
poseStack.pushPose();
|
poseStack.pushPose();
|
||||||
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
||||||
blockRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, buffer, true, random, seed, OverlayTexture.NO_OVERLAY, modelData);
|
blockRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, buffer, true, random, seed, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
||||||
poseStack.popPose();
|
poseStack.popPose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(null);
|
|
||||||
ModelBlockRenderer.clearCache();
|
ModelBlockRenderer.clearCache();
|
||||||
|
|
||||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||||
BufferBuilder buffer = buffers[layerIndex];
|
BufferBuilder buffer = buffers[layerIndex];
|
||||||
buffer.end();
|
buffer.end();
|
||||||
Pair<DrawState, ByteBuffer> data = buffer.popNextBuffer();
|
var data = buffer.end();
|
||||||
resultConsumer.accept(renderType, data);
|
resultConsumer.accept(renderType, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bufferMultiBlockShadeSeparated(Collection<StructureTemplate.StructureBlockInfo> blocks, BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, @Nullable PoseStack poseStack, Map<BlockPos, IModelData> modelDataMap, ShadeSeparatedResultConsumer resultConsumer) {
|
public static void bufferMultiBlockShadeSeparated(Collection<StructureTemplate.StructureBlockInfo> blocks, BlockRenderDispatcher renderDispatcher, BlockAndTintGetter renderWorld, @Nullable PoseStack poseStack, Map<BlockPos, ModelData> modelDataMap, ShadeSeparatedResultConsumer resultConsumer) {
|
||||||
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
ThreadLocalObjects objects = THREAD_LOCAL_OBJECTS.get();
|
||||||
if (poseStack == null) {
|
if (poseStack == null) {
|
||||||
poseStack = objects.identityPoseStack;
|
poseStack = objects.identityPoseStack;
|
||||||
}
|
}
|
||||||
Random random = objects.random;
|
var random = objects.random;
|
||||||
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
|
ShadeSeparatingVertexConsumer shadeSeparatingWrapper = objects.shadeSeparatingWrapper;
|
||||||
|
|
||||||
BufferBuilder[] shadedBuffers = objects.shadedBuffers;
|
BufferBuilder[] shadedBuffers = objects.shadedBuffers;
|
||||||
|
@ -206,36 +202,35 @@ public final class BakedModelBufferer {
|
||||||
ModelBlockRenderer.enableCaching();
|
ModelBlockRenderer.enableCaching();
|
||||||
|
|
||||||
for (StructureTemplate.StructureBlockInfo blockInfo : blocks) {
|
for (StructureTemplate.StructureBlockInfo blockInfo : blocks) {
|
||||||
BlockState state = blockInfo.state;
|
BlockState state = blockInfo.state();
|
||||||
|
|
||||||
if (state.getRenderShape() != RenderShape.MODEL) {
|
if (state.getRenderShape() != RenderShape.MODEL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BakedModel model = renderDispatcher.getBlockModel(state);
|
BakedModel model = renderDispatcher.getBlockModel(state);
|
||||||
BlockPos pos = blockInfo.pos;
|
BlockPos pos = blockInfo.pos();
|
||||||
long seed = state.getSeed(pos);
|
long seed = state.getSeed(pos);
|
||||||
IModelData modelData = modelDataMap.getOrDefault(pos, EmptyModelData.INSTANCE);
|
ModelData modelData = modelDataMap.getOrDefault(pos, ModelData.EMPTY);
|
||||||
|
|
||||||
|
var renderTypes = model.getRenderTypes(state, random, modelData);
|
||||||
|
|
||||||
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
for (int layerIndex = 0; layerIndex < CHUNK_LAYER_AMOUNT; layerIndex++) {
|
||||||
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
RenderType renderType = CHUNK_LAYERS[layerIndex];
|
||||||
|
|
||||||
if (!ItemBlockRenderTypes.canRenderInLayer(state, renderType)) {
|
if (!renderTypes.contains(renderType)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
shadeSeparatingWrapper.prepare(shadedBuffers[layerIndex], unshadedBuffers[layerIndex]);
|
shadeSeparatingWrapper.prepare(shadedBuffers[layerIndex], unshadedBuffers[layerIndex]);
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(renderType);
|
|
||||||
|
|
||||||
poseStack.pushPose();
|
poseStack.pushPose();
|
||||||
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
poseStack.translate(pos.getX(), pos.getY(), pos.getZ());
|
||||||
blockRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, shadeSeparatingWrapper, true, random, seed, OverlayTexture.NO_OVERLAY, modelData);
|
blockRenderer.tesselateBlock(renderWorld, model, state, pos, poseStack, shadeSeparatingWrapper, true, random, seed, OverlayTexture.NO_OVERLAY, modelData, renderType);
|
||||||
poseStack.popPose();
|
poseStack.popPose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ForgeHooksClient.setRenderType(null);
|
|
||||||
ModelBlockRenderer.clearCache();
|
ModelBlockRenderer.clearCache();
|
||||||
|
|
||||||
shadeSeparatingWrapper.clear();
|
shadeSeparatingWrapper.clear();
|
||||||
|
@ -246,24 +241,24 @@ public final class BakedModelBufferer {
|
||||||
BufferBuilder unshadedBuffer = unshadedBuffers[layerIndex];
|
BufferBuilder unshadedBuffer = unshadedBuffers[layerIndex];
|
||||||
shadedBuffer.end();
|
shadedBuffer.end();
|
||||||
unshadedBuffer.end();
|
unshadedBuffer.end();
|
||||||
Pair<DrawState, ByteBuffer> shadedData = shadedBuffer.popNextBuffer();
|
var shadedData = shadedBuffer.end();
|
||||||
Pair<DrawState, ByteBuffer> unshadedData = unshadedBuffer.popNextBuffer();
|
var unshadedData = unshadedBuffer.end();
|
||||||
resultConsumer.accept(renderType, true, shadedData);
|
resultConsumer.accept(renderType, true, shadedData);
|
||||||
resultConsumer.accept(renderType, false, unshadedData);
|
resultConsumer.accept(renderType, false, unshadedData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ResultConsumer {
|
public interface ResultConsumer {
|
||||||
void accept(RenderType renderType, Pair<DrawState, ByteBuffer> data);
|
void accept(RenderType renderType, BufferBuilder.RenderedBuffer data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ShadeSeparatedResultConsumer {
|
public interface ShadeSeparatedResultConsumer {
|
||||||
void accept(RenderType renderType, boolean shaded, Pair<DrawState, ByteBuffer> data);
|
void accept(RenderType renderType, boolean shaded, BufferBuilder.RenderedBuffer data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ThreadLocalObjects {
|
private static class ThreadLocalObjects {
|
||||||
public final PoseStack identityPoseStack = new PoseStack();
|
public final PoseStack identityPoseStack = new PoseStack();
|
||||||
public final Random random = new Random();
|
public final RandomSource random = RandomSource.create();
|
||||||
|
|
||||||
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
|
public final ShadeSeparatingVertexConsumer shadeSeparatingWrapper = new ShadeSeparatingVertexConsumer();
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import net.minecraft.client.resources.model.BakedModel;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.Blocks;
|
import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import net.minecraftforge.client.model.data.ModelData;
|
||||||
|
|
||||||
public class BakedModelBuilder {
|
public class BakedModelBuilder {
|
||||||
private final BakedModel bakedModel;
|
private final BakedModel bakedModel;
|
||||||
|
@ -26,7 +26,7 @@ public class BakedModelBuilder {
|
||||||
private BlockAndTintGetter renderWorld;
|
private BlockAndTintGetter renderWorld;
|
||||||
private BlockState blockState;
|
private BlockState blockState;
|
||||||
private PoseStack poseStack;
|
private PoseStack poseStack;
|
||||||
private IModelData modelData;
|
private ModelData modelData;
|
||||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
|
|
||||||
public BakedModelBuilder(BakedModel bakedModel) {
|
public BakedModelBuilder(BakedModel bakedModel) {
|
||||||
|
@ -53,7 +53,7 @@ public class BakedModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BakedModelBuilder modelData(IModelData modelData) {
|
public BakedModelBuilder modelData(ModelData modelData) {
|
||||||
this.modelData = modelData;
|
this.modelData = modelData;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ public class BakedModelBuilder {
|
||||||
blockState = Blocks.AIR.defaultBlockState();
|
blockState = Blocks.AIR.defaultBlockState();
|
||||||
}
|
}
|
||||||
if (modelData == null) {
|
if (modelData == null) {
|
||||||
modelData = VirtualEmptyModelData.INSTANCE;
|
modelData = ModelData.EMPTY;
|
||||||
}
|
}
|
||||||
if (materialFunc == null) {
|
if (materialFunc == null) {
|
||||||
materialFunc = ModelUtil::getMaterial;
|
materialFunc = ModelUtil::getMaterial;
|
||||||
|
|
|
@ -16,14 +16,14 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
import net.minecraft.client.renderer.RenderType;
|
import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import net.minecraftforge.client.model.data.ModelData;
|
||||||
|
|
||||||
public class BlockModelBuilder {
|
public class BlockModelBuilder {
|
||||||
private final BlockState state;
|
private final BlockState state;
|
||||||
private boolean shadeSeparated = true;
|
private boolean shadeSeparated = true;
|
||||||
private BlockAndTintGetter renderWorld;
|
private BlockAndTintGetter renderWorld;
|
||||||
private PoseStack poseStack;
|
private PoseStack poseStack;
|
||||||
private IModelData modelData;
|
private ModelData modelData = ModelData.EMPTY;
|
||||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
|
|
||||||
public BlockModelBuilder(BlockState state) {
|
public BlockModelBuilder(BlockState state) {
|
||||||
|
@ -45,7 +45,7 @@ public class BlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockModelBuilder modelData(IModelData modelData) {
|
public BlockModelBuilder modelData(ModelData modelData) {
|
||||||
this.modelData = modelData;
|
this.modelData = modelData;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public class BlockModelBuilder {
|
||||||
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
renderWorld = VirtualEmptyBlockGetter.INSTANCE;
|
||||||
}
|
}
|
||||||
if (modelData == null) {
|
if (modelData == null) {
|
||||||
modelData = VirtualEmptyModelData.INSTANCE;
|
modelData = ModelData.EMPTY;
|
||||||
}
|
}
|
||||||
if (materialFunc == null) {
|
if (materialFunc == null) {
|
||||||
materialFunc = ModelUtil::getMaterial;
|
materialFunc = ModelUtil::getMaterial;
|
||||||
|
|
|
@ -20,14 +20,14 @@ import net.minecraft.client.renderer.RenderType;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import net.minecraftforge.client.model.data.ModelData;
|
||||||
|
|
||||||
public class MultiBlockModelBuilder {
|
public class MultiBlockModelBuilder {
|
||||||
private final Collection<StructureTemplate.StructureBlockInfo> blocks;
|
private final Collection<StructureTemplate.StructureBlockInfo> blocks;
|
||||||
private boolean shadeSeparated = true;
|
private boolean shadeSeparated = true;
|
||||||
private BlockAndTintGetter renderWorld;
|
private BlockAndTintGetter renderWorld;
|
||||||
private PoseStack poseStack;
|
private PoseStack poseStack;
|
||||||
private Map<BlockPos, IModelData> modelDataMap;
|
private Map<BlockPos, ModelData> modelDataMap;
|
||||||
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
private BiFunction<RenderType, Boolean, Material> materialFunc;
|
||||||
|
|
||||||
public MultiBlockModelBuilder(Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
public MultiBlockModelBuilder(Collection<StructureTemplate.StructureBlockInfo> blocks) {
|
||||||
|
@ -49,7 +49,7 @@ public class MultiBlockModelBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiBlockModelBuilder modelDataMap(Map<BlockPos, IModelData> modelDataMap) {
|
public MultiBlockModelBuilder modelDataMap(Map<BlockPos, ModelData> modelDataMap) {
|
||||||
this.modelDataMap = modelDataMap;
|
this.modelDataMap = modelDataMap;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package com.jozufozu.flywheel.lib.model.baked;
|
package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
import net.minecraft.core.SectionPos;
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.world.level.BlockAndTintGetter;
|
import net.minecraft.world.level.BlockAndTintGetter;
|
||||||
import net.minecraft.world.level.BlockGetter;
|
import net.minecraft.world.level.BlockGetter;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
@ -16,13 +20,15 @@ import net.minecraft.world.level.block.Blocks;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraft.world.level.chunk.DataLayer;
|
import net.minecraft.world.level.chunk.DataLayer;
|
||||||
|
import net.minecraft.world.level.chunk.LightChunk;
|
||||||
import net.minecraft.world.level.chunk.LightChunkGetter;
|
import net.minecraft.world.level.chunk.LightChunkGetter;
|
||||||
|
import net.minecraft.world.level.lighting.ChunkSkyLightSources;
|
||||||
import net.minecraft.world.level.lighting.LayerLightEventListener;
|
import net.minecraft.world.level.lighting.LayerLightEventListener;
|
||||||
import net.minecraft.world.level.lighting.LevelLightEngine;
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
import net.minecraft.world.level.material.FluidState;
|
import net.minecraft.world.level.material.FluidState;
|
||||||
import net.minecraft.world.level.material.Fluids;
|
import net.minecraft.world.level.material.Fluids;
|
||||||
|
|
||||||
public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
public interface VirtualEmptyBlockGetter extends BlockAndTintGetter, LightChunk {
|
||||||
public static final VirtualEmptyBlockGetter INSTANCE = new StaticLightImpl(0, 15);
|
public static final VirtualEmptyBlockGetter INSTANCE = new StaticLightImpl(0, 15);
|
||||||
public static final VirtualEmptyBlockGetter FULL_BRIGHT = new StaticLightImpl(15, 15);
|
public static final VirtualEmptyBlockGetter FULL_BRIGHT = new StaticLightImpl(15, 15);
|
||||||
public static final VirtualEmptyBlockGetter FULL_DARK = new StaticLightImpl(0, 0);
|
public static final VirtualEmptyBlockGetter FULL_DARK = new StaticLightImpl(0, 0);
|
||||||
|
@ -63,17 +69,24 @@ public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default int getBlockTint(BlockPos pos, ColorResolver resolver) {
|
default int getBlockTint(BlockPos pos, ColorResolver resolver) {
|
||||||
Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY).getOrThrow(Biomes.PLAINS);
|
Biome plainsBiome = Minecraft.getInstance().getConnection().registryAccess().registryOrThrow(Registries.BIOME).getOrThrow(Biomes.PLAINS);
|
||||||
return resolver.getColor(plainsBiome, pos.getX(), pos.getZ());
|
return resolver.getColor(plainsBiome, pos.getX(), pos.getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void findBlockLightSources(BiConsumer<BlockPos, BlockState> pOutput) {
|
||||||
|
}
|
||||||
|
|
||||||
public static class StaticLightImpl implements VirtualEmptyBlockGetter {
|
public static class StaticLightImpl implements VirtualEmptyBlockGetter {
|
||||||
private final LevelLightEngine lightEngine;
|
private final LevelLightEngine lightEngine;
|
||||||
|
private final ChunkSkyLightSources lightSources;
|
||||||
|
|
||||||
public StaticLightImpl(int blockLight, int skyLight) {
|
public StaticLightImpl(int blockLight, int skyLight) {
|
||||||
lightEngine = new LevelLightEngine(new LightChunkGetter() {
|
lightEngine = new LevelLightEngine(new LightChunkGetter() {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockGetter getChunkForLighting(int p_63023_, int p_63024_) {
|
public LightChunk getChunkForLighting(int p_63023_, int p_63024_) {
|
||||||
return StaticLightImpl.this;
|
return StaticLightImpl.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +103,8 @@ public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
||||||
return layer == LightLayer.BLOCK ? blockListener : skyListener;
|
return layer == LightLayer.BLOCK ? blockListener : skyListener;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
lightSources = new ChunkSkyLightSources(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LayerLightEventListener createStaticListener(int light) {
|
private static LayerLightEventListener createStaticListener(int light) {
|
||||||
|
@ -99,7 +114,18 @@ public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockEmissionIncrease(BlockPos pos, int emissionLevel) {
|
public int runLightUpdates() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLightEnabled(ChunkPos pChunkPos, boolean pLightEnabled) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void propagateLightSources(ChunkPos pChunkPos) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,19 +133,10 @@ public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int runUpdates(int pos, boolean isQueueEmpty, boolean updateBlockLight) {
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateSectionStatus(SectionPos pos, boolean isQueueEmpty) {
|
public void updateSectionStatus(SectionPos pos, boolean isQueueEmpty) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enableLightSources(ChunkPos pos, boolean isQueueEmpty) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataLayer getDataLayerData(SectionPos pos) {
|
public DataLayer getDataLayerData(SectionPos pos) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -136,5 +153,10 @@ public interface VirtualEmptyBlockGetter extends BlockAndTintGetter {
|
||||||
public LevelLightEngine getLightEngine() {
|
public LevelLightEngine getLightEngine() {
|
||||||
return lightEngine;
|
return lightEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkSkyLightSources getSkyLightSources() {
|
||||||
|
return lightSources;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ package com.jozufozu.flywheel.lib.model.baked;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import net.minecraftforge.client.model.data.IModelData;
|
import com.jozufozu.flywheel.api.model.Model;
|
||||||
|
|
||||||
|
import net.minecraftforge.client.model.data.ModelData;
|
||||||
import net.minecraftforge.client.model.data.ModelProperty;
|
import net.minecraftforge.client.model.data.ModelProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,27 +12,11 @@ import net.minecraftforge.client.model.data.ModelProperty;
|
||||||
* available in-world context. BakedModel#getModelData can react accordingly
|
* available in-world context. BakedModel#getModelData can react accordingly
|
||||||
* and avoid looking for model data itself.
|
* and avoid looking for model data itself.
|
||||||
**/
|
**/
|
||||||
public enum VirtualEmptyModelData implements IModelData {
|
public class VirtualEmptyModelData {
|
||||||
INSTANCE;
|
// TODO: Remove? Doesn't seem necessary anymore
|
||||||
|
public static final ModelData INSTANCE = ModelData.EMPTY;
|
||||||
|
|
||||||
public static boolean is(IModelData data) {
|
public static boolean is(ModelData data) {
|
||||||
return data == INSTANCE;
|
return data == INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasProperty(ModelProperty<?> prop) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public <T> T getData(ModelProperty<T> prop) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public <T> T setData(ModelProperty<T> prop, T data) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue