986 lines
37 KiB
Java
986 lines
37 KiB
Java
package net.minecraft.client.renderer.block;
|
|
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
|
import it.unimi.dsi.fastutil.longs.Long2FloatLinkedOpenHashMap;
|
|
import it.unimi.dsi.fastutil.longs.Long2IntLinkedOpenHashMap;
|
|
import java.util.List;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.CrashReport;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.ReportedException;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.color.block.BlockColors;
|
|
import net.minecraft.client.renderer.LevelRenderer;
|
|
import net.minecraft.client.renderer.block.ModelBlockRenderer.Cache.1;
|
|
import net.minecraft.client.renderer.block.ModelBlockRenderer.Cache.2;
|
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
|
import net.minecraft.client.renderer.block.model.BlockModelPart;
|
|
import net.minecraft.client.renderer.block.model.BlockStateModel;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.util.ARGB;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.level.BlockAndTintGetter;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class ModelBlockRenderer {
|
|
private static final Direction[] DIRECTIONS = Direction.values();
|
|
private final BlockColors blockColors;
|
|
private static final int CACHE_SIZE = 100;
|
|
static final ThreadLocal<ModelBlockRenderer.Cache> CACHE = ThreadLocal.withInitial(ModelBlockRenderer.Cache::new);
|
|
|
|
public ModelBlockRenderer(BlockColors blockColors) {
|
|
this.blockColors = blockColors;
|
|
}
|
|
|
|
public void tesselateBlock(
|
|
BlockAndTintGetter level,
|
|
List<BlockModelPart> parts,
|
|
BlockState state,
|
|
BlockPos pos,
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
boolean checkSides,
|
|
int packedOverlay
|
|
) {
|
|
if (!parts.isEmpty()) {
|
|
boolean bl = Minecraft.useAmbientOcclusion() && state.getLightEmission() == 0 && ((BlockModelPart)parts.getFirst()).useAmbientOcclusion();
|
|
poseStack.translate(state.getOffset(pos));
|
|
|
|
try {
|
|
if (bl) {
|
|
this.tesselateWithAO(level, parts, state, pos, poseStack, consumer, checkSides, packedOverlay);
|
|
} else {
|
|
this.tesselateWithoutAO(level, parts, state, pos, poseStack, consumer, checkSides, packedOverlay);
|
|
}
|
|
} catch (Throwable var13) {
|
|
CrashReport crashReport = CrashReport.forThrowable(var13, "Tesselating block model");
|
|
CrashReportCategory crashReportCategory = crashReport.addCategory("Block model being tesselated");
|
|
CrashReportCategory.populateBlockDetails(crashReportCategory, level, pos, state);
|
|
crashReportCategory.setDetail("Using AO", bl);
|
|
throw new ReportedException(crashReport);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static boolean shouldRenderFace(BlockAndTintGetter level, BlockState state, boolean checkSides, Direction face, BlockPos pos) {
|
|
if (!checkSides) {
|
|
return true;
|
|
} else {
|
|
BlockState blockState = level.getBlockState(pos);
|
|
return Block.shouldRenderFace(state, blockState, face);
|
|
}
|
|
}
|
|
|
|
public void tesselateWithAO(
|
|
BlockAndTintGetter level,
|
|
List<BlockModelPart> parts,
|
|
BlockState state,
|
|
BlockPos pos,
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
boolean checkSides,
|
|
int packedOverlay
|
|
) {
|
|
ModelBlockRenderer.AmbientOcclusionRenderStorage ambientOcclusionRenderStorage = new ModelBlockRenderer.AmbientOcclusionRenderStorage();
|
|
int i = 0;
|
|
int j = 0;
|
|
|
|
for (BlockModelPart blockModelPart : parts) {
|
|
for (Direction direction : DIRECTIONS) {
|
|
int k = 1 << direction.ordinal();
|
|
boolean bl = (i & k) == 1;
|
|
boolean bl2 = (j & k) == 1;
|
|
if (!bl || bl2) {
|
|
List<BakedQuad> list = blockModelPart.getQuads(direction);
|
|
if (!list.isEmpty()) {
|
|
if (!bl) {
|
|
bl2 = shouldRenderFace(level, state, checkSides, direction, ambientOcclusionRenderStorage.scratchPos.setWithOffset(pos, direction));
|
|
i |= k;
|
|
if (bl2) {
|
|
j |= k;
|
|
}
|
|
}
|
|
|
|
if (bl2) {
|
|
this.renderModelFaceAO(level, state, pos, poseStack, consumer, list, ambientOcclusionRenderStorage, packedOverlay);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
List<BakedQuad> list2 = blockModelPart.getQuads(null);
|
|
if (!list2.isEmpty()) {
|
|
this.renderModelFaceAO(level, state, pos, poseStack, consumer, list2, ambientOcclusionRenderStorage, packedOverlay);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void tesselateWithoutAO(
|
|
BlockAndTintGetter level,
|
|
List<BlockModelPart> parts,
|
|
BlockState state,
|
|
BlockPos pos,
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
boolean checkSides,
|
|
int packedOverlay
|
|
) {
|
|
ModelBlockRenderer.CommonRenderStorage commonRenderStorage = new ModelBlockRenderer.CommonRenderStorage();
|
|
int i = 0;
|
|
int j = 0;
|
|
|
|
for (BlockModelPart blockModelPart : parts) {
|
|
for (Direction direction : DIRECTIONS) {
|
|
int k = 1 << direction.ordinal();
|
|
boolean bl = (i & k) == 1;
|
|
boolean bl2 = (j & k) == 1;
|
|
if (!bl || bl2) {
|
|
List<BakedQuad> list = blockModelPart.getQuads(direction);
|
|
if (!list.isEmpty()) {
|
|
BlockPos blockPos = commonRenderStorage.scratchPos.setWithOffset(pos, direction);
|
|
if (!bl) {
|
|
bl2 = shouldRenderFace(level, state, checkSides, direction, blockPos);
|
|
i |= k;
|
|
if (bl2) {
|
|
j |= k;
|
|
}
|
|
}
|
|
|
|
if (bl2) {
|
|
int l = commonRenderStorage.cache.getLightColor(state, level, blockPos);
|
|
this.renderModelFaceFlat(level, state, pos, l, packedOverlay, false, poseStack, consumer, list, commonRenderStorage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
List<BakedQuad> list2 = blockModelPart.getQuads(null);
|
|
if (!list2.isEmpty()) {
|
|
this.renderModelFaceFlat(level, state, pos, -1, packedOverlay, true, poseStack, consumer, list2, commonRenderStorage);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void renderModelFaceAO(
|
|
BlockAndTintGetter level,
|
|
BlockState state,
|
|
BlockPos pos,
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
List<BakedQuad> quads,
|
|
ModelBlockRenderer.AmbientOcclusionRenderStorage renderStorage,
|
|
int packedOverlay
|
|
) {
|
|
for (BakedQuad bakedQuad : quads) {
|
|
calculateShape(level, state, pos, bakedQuad.vertices(), bakedQuad.direction(), renderStorage);
|
|
renderStorage.calculate(level, state, pos, bakedQuad.direction(), bakedQuad.shade());
|
|
this.putQuadData(level, state, pos, consumer, poseStack.last(), bakedQuad, renderStorage, packedOverlay);
|
|
}
|
|
}
|
|
|
|
private void putQuadData(
|
|
BlockAndTintGetter level,
|
|
BlockState state,
|
|
BlockPos pos,
|
|
VertexConsumer consumer,
|
|
PoseStack.Pose pose,
|
|
BakedQuad quad,
|
|
ModelBlockRenderer.CommonRenderStorage renderStorage,
|
|
int packedOverlay
|
|
) {
|
|
int i = quad.tintIndex();
|
|
float f;
|
|
float g;
|
|
float h;
|
|
if (i != -1) {
|
|
int j;
|
|
if (renderStorage.tintCacheIndex == i) {
|
|
j = renderStorage.tintCacheValue;
|
|
} else {
|
|
j = this.blockColors.getColor(state, level, pos, i);
|
|
renderStorage.tintCacheIndex = i;
|
|
renderStorage.tintCacheValue = j;
|
|
}
|
|
|
|
f = ARGB.redFloat(j);
|
|
g = ARGB.greenFloat(j);
|
|
h = ARGB.blueFloat(j);
|
|
} else {
|
|
f = 1.0F;
|
|
g = 1.0F;
|
|
h = 1.0F;
|
|
}
|
|
|
|
consumer.putBulkData(pose, quad, renderStorage.brightness, f, g, h, 1.0F, renderStorage.lightmap, packedOverlay, true);
|
|
}
|
|
|
|
private static void calculateShape(
|
|
BlockAndTintGetter level, BlockState state, BlockPos pos, int[] verticies, Direction direction, ModelBlockRenderer.CommonRenderStorage renderStorage
|
|
) {
|
|
float f = 32.0F;
|
|
float g = 32.0F;
|
|
float h = 32.0F;
|
|
float i = -32.0F;
|
|
float j = -32.0F;
|
|
float k = -32.0F;
|
|
|
|
for (int l = 0; l < 4; l++) {
|
|
float m = Float.intBitsToFloat(verticies[l * 8]);
|
|
float n = Float.intBitsToFloat(verticies[l * 8 + 1]);
|
|
float o = Float.intBitsToFloat(verticies[l * 8 + 2]);
|
|
f = Math.min(f, m);
|
|
g = Math.min(g, n);
|
|
h = Math.min(h, o);
|
|
i = Math.max(i, m);
|
|
j = Math.max(j, n);
|
|
k = Math.max(k, o);
|
|
}
|
|
|
|
if (renderStorage instanceof ModelBlockRenderer.AmbientOcclusionRenderStorage ambientOcclusionRenderStorage) {
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.WEST.index] = f;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.EAST.index] = i;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.DOWN.index] = g;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.UP.index] = j;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.NORTH.index] = h;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.SOUTH.index] = k;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.FLIP_WEST.index] = 1.0F - f;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.FLIP_EAST.index] = 1.0F - i;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.FLIP_DOWN.index] = 1.0F - g;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.FLIP_UP.index] = 1.0F - j;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.FLIP_NORTH.index] = 1.0F - h;
|
|
ambientOcclusionRenderStorage.faceShape[ModelBlockRenderer.SizeInfo.FLIP_SOUTH.index] = 1.0F - k;
|
|
}
|
|
|
|
float p = 1.0E-4F;
|
|
float m = 0.9999F;
|
|
|
|
renderStorage.facePartial = switch (direction) {
|
|
case DOWN, UP -> f >= 1.0E-4F || h >= 1.0E-4F || i <= 0.9999F || k <= 0.9999F;
|
|
case NORTH, SOUTH -> f >= 1.0E-4F || g >= 1.0E-4F || i <= 0.9999F || j <= 0.9999F;
|
|
case WEST, EAST -> g >= 1.0E-4F || h >= 1.0E-4F || j <= 0.9999F || k <= 0.9999F;
|
|
};
|
|
|
|
renderStorage.faceCubic = switch (direction) {
|
|
case DOWN -> g == j && (g < 1.0E-4F || state.isCollisionShapeFullBlock(level, pos));
|
|
case UP -> g == j && (j > 0.9999F || state.isCollisionShapeFullBlock(level, pos));
|
|
case NORTH -> h == k && (h < 1.0E-4F || state.isCollisionShapeFullBlock(level, pos));
|
|
case SOUTH -> h == k && (k > 0.9999F || state.isCollisionShapeFullBlock(level, pos));
|
|
case WEST -> f == i && (f < 1.0E-4F || state.isCollisionShapeFullBlock(level, pos));
|
|
case EAST -> f == i && (i > 0.9999F || state.isCollisionShapeFullBlock(level, pos));
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param repackLight {@code true} if packed light should be re-calculated
|
|
*/
|
|
private void renderModelFaceFlat(
|
|
BlockAndTintGetter level,
|
|
BlockState state,
|
|
BlockPos pos,
|
|
int packedLight,
|
|
int packedOverlay,
|
|
boolean repackLight,
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
List<BakedQuad> quads,
|
|
ModelBlockRenderer.CommonRenderStorage renderStorage
|
|
) {
|
|
for (BakedQuad bakedQuad : quads) {
|
|
if (repackLight) {
|
|
calculateShape(level, state, pos, bakedQuad.vertices(), bakedQuad.direction(), renderStorage);
|
|
BlockPos blockPos = (BlockPos)(renderStorage.faceCubic ? renderStorage.scratchPos.setWithOffset(pos, bakedQuad.direction()) : pos);
|
|
packedLight = renderStorage.cache.getLightColor(state, level, blockPos);
|
|
}
|
|
|
|
float f = level.getShade(bakedQuad.direction(), bakedQuad.shade());
|
|
renderStorage.brightness[0] = f;
|
|
renderStorage.brightness[1] = f;
|
|
renderStorage.brightness[2] = f;
|
|
renderStorage.brightness[3] = f;
|
|
renderStorage.lightmap[0] = packedLight;
|
|
renderStorage.lightmap[1] = packedLight;
|
|
renderStorage.lightmap[2] = packedLight;
|
|
renderStorage.lightmap[3] = packedLight;
|
|
this.putQuadData(level, state, pos, consumer, poseStack.last(), bakedQuad, renderStorage, packedOverlay);
|
|
}
|
|
}
|
|
|
|
public static void renderModel(
|
|
PoseStack.Pose pose, VertexConsumer consumer, BlockStateModel model, float red, float green, float blue, int packedLight, int packedOverlay
|
|
) {
|
|
for (BlockModelPart blockModelPart : model.collectParts(RandomSource.create(42L))) {
|
|
for (Direction direction : DIRECTIONS) {
|
|
renderQuadList(pose, consumer, red, green, blue, blockModelPart.getQuads(direction), packedLight, packedOverlay);
|
|
}
|
|
|
|
renderQuadList(pose, consumer, red, green, blue, blockModelPart.getQuads(null), packedLight, packedOverlay);
|
|
}
|
|
}
|
|
|
|
private static void renderQuadList(
|
|
PoseStack.Pose pose, VertexConsumer consumer, float red, float green, float blue, List<BakedQuad> quads, int packedLight, int packedOverlay
|
|
) {
|
|
for (BakedQuad bakedQuad : quads) {
|
|
float f;
|
|
float g;
|
|
float h;
|
|
if (bakedQuad.isTinted()) {
|
|
f = Mth.clamp(red, 0.0F, 1.0F);
|
|
g = Mth.clamp(green, 0.0F, 1.0F);
|
|
h = Mth.clamp(blue, 0.0F, 1.0F);
|
|
} else {
|
|
f = 1.0F;
|
|
g = 1.0F;
|
|
h = 1.0F;
|
|
}
|
|
|
|
consumer.putBulkData(pose, bakedQuad, f, g, h, 1.0F, packedLight, packedOverlay);
|
|
}
|
|
}
|
|
|
|
public static void enableCaching() {
|
|
((ModelBlockRenderer.Cache)CACHE.get()).enable();
|
|
}
|
|
|
|
public static void clearCache() {
|
|
((ModelBlockRenderer.Cache)CACHE.get()).disable();
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
protected static enum AdjacencyInfo {
|
|
DOWN(
|
|
new Direction[]{Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH},
|
|
0.5F,
|
|
true,
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.SOUTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.NORTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.NORTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.SOUTH
|
|
}
|
|
),
|
|
UP(
|
|
new Direction[]{Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH},
|
|
1.0F,
|
|
true,
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.SOUTH,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.SOUTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.NORTH,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.NORTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.NORTH,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.NORTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.SOUTH,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.SOUTH
|
|
}
|
|
),
|
|
NORTH(
|
|
new Direction[]{Direction.UP, Direction.DOWN, Direction.EAST, Direction.WEST},
|
|
0.8F,
|
|
true,
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST
|
|
}
|
|
),
|
|
SOUTH(
|
|
new Direction[]{Direction.WEST, Direction.EAST, Direction.DOWN, Direction.UP},
|
|
0.8F,
|
|
true,
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.WEST
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_WEST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.WEST,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.WEST
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.EAST
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_EAST,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.EAST,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.EAST
|
|
}
|
|
),
|
|
WEST(
|
|
new Direction[]{Direction.UP, Direction.DOWN, Direction.NORTH, Direction.SOUTH},
|
|
0.6F,
|
|
true,
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.SOUTH,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.SOUTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.NORTH,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.NORTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.NORTH,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.NORTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.SOUTH,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.SOUTH
|
|
}
|
|
),
|
|
EAST(
|
|
new Direction[]{Direction.DOWN, Direction.UP, Direction.NORTH, Direction.SOUTH},
|
|
0.6F,
|
|
true,
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.SOUTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.DOWN,
|
|
ModelBlockRenderer.SizeInfo.NORTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.NORTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_NORTH,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.NORTH
|
|
},
|
|
new ModelBlockRenderer.SizeInfo[]{
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.SOUTH,
|
|
ModelBlockRenderer.SizeInfo.FLIP_UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.FLIP_SOUTH,
|
|
ModelBlockRenderer.SizeInfo.UP,
|
|
ModelBlockRenderer.SizeInfo.SOUTH
|
|
}
|
|
);
|
|
|
|
final Direction[] corners;
|
|
final boolean doNonCubicWeight;
|
|
final ModelBlockRenderer.SizeInfo[] vert0Weights;
|
|
final ModelBlockRenderer.SizeInfo[] vert1Weights;
|
|
final ModelBlockRenderer.SizeInfo[] vert2Weights;
|
|
final ModelBlockRenderer.SizeInfo[] vert3Weights;
|
|
private static final ModelBlockRenderer.AdjacencyInfo[] BY_FACING = Util.make(new ModelBlockRenderer.AdjacencyInfo[6], adjacencyInfos -> {
|
|
adjacencyInfos[Direction.DOWN.get3DDataValue()] = DOWN;
|
|
adjacencyInfos[Direction.UP.get3DDataValue()] = UP;
|
|
adjacencyInfos[Direction.NORTH.get3DDataValue()] = NORTH;
|
|
adjacencyInfos[Direction.SOUTH.get3DDataValue()] = SOUTH;
|
|
adjacencyInfos[Direction.WEST.get3DDataValue()] = WEST;
|
|
adjacencyInfos[Direction.EAST.get3DDataValue()] = EAST;
|
|
});
|
|
|
|
/**
|
|
* @param shadeBrightness the shade brightness for this direction
|
|
*/
|
|
private AdjacencyInfo(
|
|
final Direction[] corners,
|
|
final float shadeBrightness,
|
|
final boolean doNonCubicWeight,
|
|
final ModelBlockRenderer.SizeInfo[] vert0Weights,
|
|
final ModelBlockRenderer.SizeInfo[] vert1Weights,
|
|
final ModelBlockRenderer.SizeInfo[] vert2Weights,
|
|
final ModelBlockRenderer.SizeInfo[] vert3Weights
|
|
) {
|
|
this.corners = corners;
|
|
this.doNonCubicWeight = doNonCubicWeight;
|
|
this.vert0Weights = vert0Weights;
|
|
this.vert1Weights = vert1Weights;
|
|
this.vert2Weights = vert2Weights;
|
|
this.vert3Weights = vert3Weights;
|
|
}
|
|
|
|
public static ModelBlockRenderer.AdjacencyInfo fromFacing(Direction facing) {
|
|
return BY_FACING[facing.get3DDataValue()];
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
static class AmbientOcclusionRenderStorage extends ModelBlockRenderer.CommonRenderStorage {
|
|
final float[] faceShape = new float[ModelBlockRenderer.SizeInfo.COUNT];
|
|
|
|
public AmbientOcclusionRenderStorage() {
|
|
}
|
|
|
|
public void calculate(BlockAndTintGetter level, BlockState state, BlockPos pos, Direction direction, boolean shade) {
|
|
BlockPos blockPos = this.faceCubic ? pos.relative(direction) : pos;
|
|
ModelBlockRenderer.AdjacencyInfo adjacencyInfo = ModelBlockRenderer.AdjacencyInfo.fromFacing(direction);
|
|
BlockPos.MutableBlockPos mutableBlockPos = this.scratchPos;
|
|
mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[0]);
|
|
BlockState blockState = level.getBlockState(mutableBlockPos);
|
|
int i = this.cache.getLightColor(blockState, level, mutableBlockPos);
|
|
float f = this.cache.getShadeBrightness(blockState, level, mutableBlockPos);
|
|
mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[1]);
|
|
BlockState blockState2 = level.getBlockState(mutableBlockPos);
|
|
int j = this.cache.getLightColor(blockState2, level, mutableBlockPos);
|
|
float g = this.cache.getShadeBrightness(blockState2, level, mutableBlockPos);
|
|
mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[2]);
|
|
BlockState blockState3 = level.getBlockState(mutableBlockPos);
|
|
int k = this.cache.getLightColor(blockState3, level, mutableBlockPos);
|
|
float h = this.cache.getShadeBrightness(blockState3, level, mutableBlockPos);
|
|
mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[3]);
|
|
BlockState blockState4 = level.getBlockState(mutableBlockPos);
|
|
int l = this.cache.getLightColor(blockState4, level, mutableBlockPos);
|
|
float m = this.cache.getShadeBrightness(blockState4, level, mutableBlockPos);
|
|
BlockState blockState5 = level.getBlockState(mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[0]).move(direction));
|
|
boolean bl = !blockState5.isViewBlocking(level, mutableBlockPos) || blockState5.getLightBlock() == 0;
|
|
BlockState blockState6 = level.getBlockState(mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[1]).move(direction));
|
|
boolean bl2 = !blockState6.isViewBlocking(level, mutableBlockPos) || blockState6.getLightBlock() == 0;
|
|
BlockState blockState7 = level.getBlockState(mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[2]).move(direction));
|
|
boolean bl3 = !blockState7.isViewBlocking(level, mutableBlockPos) || blockState7.getLightBlock() == 0;
|
|
BlockState blockState8 = level.getBlockState(mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[3]).move(direction));
|
|
boolean bl4 = !blockState8.isViewBlocking(level, mutableBlockPos) || blockState8.getLightBlock() == 0;
|
|
float n;
|
|
int o;
|
|
if (!bl3 && !bl) {
|
|
n = f;
|
|
o = i;
|
|
} else {
|
|
mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[0]).move(adjacencyInfo.corners[2]);
|
|
BlockState blockState9 = level.getBlockState(mutableBlockPos);
|
|
n = this.cache.getShadeBrightness(blockState9, level, mutableBlockPos);
|
|
o = this.cache.getLightColor(blockState9, level, mutableBlockPos);
|
|
}
|
|
|
|
float p;
|
|
int q;
|
|
if (!bl4 && !bl) {
|
|
p = f;
|
|
q = i;
|
|
} else {
|
|
mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[0]).move(adjacencyInfo.corners[3]);
|
|
BlockState blockState9 = level.getBlockState(mutableBlockPos);
|
|
p = this.cache.getShadeBrightness(blockState9, level, mutableBlockPos);
|
|
q = this.cache.getLightColor(blockState9, level, mutableBlockPos);
|
|
}
|
|
|
|
float r;
|
|
int s;
|
|
if (!bl3 && !bl2) {
|
|
r = f;
|
|
s = i;
|
|
} else {
|
|
mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[1]).move(adjacencyInfo.corners[2]);
|
|
BlockState blockState9 = level.getBlockState(mutableBlockPos);
|
|
r = this.cache.getShadeBrightness(blockState9, level, mutableBlockPos);
|
|
s = this.cache.getLightColor(blockState9, level, mutableBlockPos);
|
|
}
|
|
|
|
float t;
|
|
int u;
|
|
if (!bl4 && !bl2) {
|
|
t = f;
|
|
u = i;
|
|
} else {
|
|
mutableBlockPos.setWithOffset(blockPos, adjacencyInfo.corners[1]).move(adjacencyInfo.corners[3]);
|
|
BlockState blockState9 = level.getBlockState(mutableBlockPos);
|
|
t = this.cache.getShadeBrightness(blockState9, level, mutableBlockPos);
|
|
u = this.cache.getLightColor(blockState9, level, mutableBlockPos);
|
|
}
|
|
|
|
int v = this.cache.getLightColor(state, level, pos);
|
|
mutableBlockPos.setWithOffset(pos, direction);
|
|
BlockState blockState10 = level.getBlockState(mutableBlockPos);
|
|
if (this.faceCubic || !blockState10.isSolidRender()) {
|
|
v = this.cache.getLightColor(blockState10, level, mutableBlockPos);
|
|
}
|
|
|
|
float w = this.faceCubic
|
|
? this.cache.getShadeBrightness(level.getBlockState(blockPos), level, blockPos)
|
|
: this.cache.getShadeBrightness(level.getBlockState(pos), level, pos);
|
|
ModelBlockRenderer.AmbientVertexRemap ambientVertexRemap = ModelBlockRenderer.AmbientVertexRemap.fromFacing(direction);
|
|
if (this.facePartial && adjacencyInfo.doNonCubicWeight) {
|
|
float x = (m + f + p + w) * 0.25F;
|
|
float y = (h + f + n + w) * 0.25F;
|
|
float z = (h + g + r + w) * 0.25F;
|
|
float aa = (m + g + t + w) * 0.25F;
|
|
float ab = this.faceShape[adjacencyInfo.vert0Weights[0].index] * this.faceShape[adjacencyInfo.vert0Weights[1].index];
|
|
float ac = this.faceShape[adjacencyInfo.vert0Weights[2].index] * this.faceShape[adjacencyInfo.vert0Weights[3].index];
|
|
float ad = this.faceShape[adjacencyInfo.vert0Weights[4].index] * this.faceShape[adjacencyInfo.vert0Weights[5].index];
|
|
float ae = this.faceShape[adjacencyInfo.vert0Weights[6].index] * this.faceShape[adjacencyInfo.vert0Weights[7].index];
|
|
float af = this.faceShape[adjacencyInfo.vert1Weights[0].index] * this.faceShape[adjacencyInfo.vert1Weights[1].index];
|
|
float ag = this.faceShape[adjacencyInfo.vert1Weights[2].index] * this.faceShape[adjacencyInfo.vert1Weights[3].index];
|
|
float ah = this.faceShape[adjacencyInfo.vert1Weights[4].index] * this.faceShape[adjacencyInfo.vert1Weights[5].index];
|
|
float ai = this.faceShape[adjacencyInfo.vert1Weights[6].index] * this.faceShape[adjacencyInfo.vert1Weights[7].index];
|
|
float aj = this.faceShape[adjacencyInfo.vert2Weights[0].index] * this.faceShape[adjacencyInfo.vert2Weights[1].index];
|
|
float ak = this.faceShape[adjacencyInfo.vert2Weights[2].index] * this.faceShape[adjacencyInfo.vert2Weights[3].index];
|
|
float al = this.faceShape[adjacencyInfo.vert2Weights[4].index] * this.faceShape[adjacencyInfo.vert2Weights[5].index];
|
|
float am = this.faceShape[adjacencyInfo.vert2Weights[6].index] * this.faceShape[adjacencyInfo.vert2Weights[7].index];
|
|
float an = this.faceShape[adjacencyInfo.vert3Weights[0].index] * this.faceShape[adjacencyInfo.vert3Weights[1].index];
|
|
float ao = this.faceShape[adjacencyInfo.vert3Weights[2].index] * this.faceShape[adjacencyInfo.vert3Weights[3].index];
|
|
float ap = this.faceShape[adjacencyInfo.vert3Weights[4].index] * this.faceShape[adjacencyInfo.vert3Weights[5].index];
|
|
float aq = this.faceShape[adjacencyInfo.vert3Weights[6].index] * this.faceShape[adjacencyInfo.vert3Weights[7].index];
|
|
this.brightness[ambientVertexRemap.vert0] = Math.clamp(x * ab + y * ac + z * ad + aa * ae, 0.0F, 1.0F);
|
|
this.brightness[ambientVertexRemap.vert1] = Math.clamp(x * af + y * ag + z * ah + aa * ai, 0.0F, 1.0F);
|
|
this.brightness[ambientVertexRemap.vert2] = Math.clamp(x * aj + y * ak + z * al + aa * am, 0.0F, 1.0F);
|
|
this.brightness[ambientVertexRemap.vert3] = Math.clamp(x * an + y * ao + z * ap + aa * aq, 0.0F, 1.0F);
|
|
int ar = blend(l, i, q, v);
|
|
int as = blend(k, i, o, v);
|
|
int at = blend(k, j, s, v);
|
|
int au = blend(l, j, u, v);
|
|
this.lightmap[ambientVertexRemap.vert0] = blend(ar, as, at, au, ab, ac, ad, ae);
|
|
this.lightmap[ambientVertexRemap.vert1] = blend(ar, as, at, au, af, ag, ah, ai);
|
|
this.lightmap[ambientVertexRemap.vert2] = blend(ar, as, at, au, aj, ak, al, am);
|
|
this.lightmap[ambientVertexRemap.vert3] = blend(ar, as, at, au, an, ao, ap, aq);
|
|
} else {
|
|
float x = (m + f + p + w) * 0.25F;
|
|
float y = (h + f + n + w) * 0.25F;
|
|
float z = (h + g + r + w) * 0.25F;
|
|
float aa = (m + g + t + w) * 0.25F;
|
|
this.lightmap[ambientVertexRemap.vert0] = blend(l, i, q, v);
|
|
this.lightmap[ambientVertexRemap.vert1] = blend(k, i, o, v);
|
|
this.lightmap[ambientVertexRemap.vert2] = blend(k, j, s, v);
|
|
this.lightmap[ambientVertexRemap.vert3] = blend(l, j, u, v);
|
|
this.brightness[ambientVertexRemap.vert0] = x;
|
|
this.brightness[ambientVertexRemap.vert1] = y;
|
|
this.brightness[ambientVertexRemap.vert2] = z;
|
|
this.brightness[ambientVertexRemap.vert3] = aa;
|
|
}
|
|
|
|
float x = level.getShade(direction, shade);
|
|
|
|
for (int av = 0; av < this.brightness.length; av++) {
|
|
this.brightness[av] = this.brightness[av] * x;
|
|
}
|
|
}
|
|
|
|
private static int blend(int color1, int color2, int color3, int currentBlockColor) {
|
|
if (color1 == 0) {
|
|
color1 = currentBlockColor;
|
|
}
|
|
|
|
if (color2 == 0) {
|
|
color2 = currentBlockColor;
|
|
}
|
|
|
|
if (color3 == 0) {
|
|
color3 = currentBlockColor;
|
|
}
|
|
|
|
return color1 + color2 + color3 + currentBlockColor >> 2 & 16711935;
|
|
}
|
|
|
|
private static int blend(
|
|
int color1, int color2, int color3, int blockLight, float color1Weight, float color2Weight, float color3Weight, float blockLightWeight
|
|
) {
|
|
int i = (int)(
|
|
(color1 >> 16 & 0xFF) * color1Weight
|
|
+ (color2 >> 16 & 0xFF) * color2Weight
|
|
+ (color3 >> 16 & 0xFF) * color3Weight
|
|
+ (blockLight >> 16 & 0xFF) * blockLightWeight
|
|
)
|
|
& 0xFF;
|
|
int j = (int)((color1 & 0xFF) * color1Weight + (color2 & 0xFF) * color2Weight + (color3 & 0xFF) * color3Weight + (blockLight & 0xFF) * blockLightWeight)
|
|
& 0xFF;
|
|
return i << 16 | j;
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
static enum AmbientVertexRemap {
|
|
DOWN(0, 1, 2, 3),
|
|
UP(2, 3, 0, 1),
|
|
NORTH(3, 0, 1, 2),
|
|
SOUTH(0, 1, 2, 3),
|
|
WEST(3, 0, 1, 2),
|
|
EAST(1, 2, 3, 0);
|
|
|
|
final int vert0;
|
|
final int vert1;
|
|
final int vert2;
|
|
final int vert3;
|
|
private static final ModelBlockRenderer.AmbientVertexRemap[] BY_FACING = Util.make(new ModelBlockRenderer.AmbientVertexRemap[6], ambientVertexRemaps -> {
|
|
ambientVertexRemaps[Direction.DOWN.get3DDataValue()] = DOWN;
|
|
ambientVertexRemaps[Direction.UP.get3DDataValue()] = UP;
|
|
ambientVertexRemaps[Direction.NORTH.get3DDataValue()] = NORTH;
|
|
ambientVertexRemaps[Direction.SOUTH.get3DDataValue()] = SOUTH;
|
|
ambientVertexRemaps[Direction.WEST.get3DDataValue()] = WEST;
|
|
ambientVertexRemaps[Direction.EAST.get3DDataValue()] = EAST;
|
|
});
|
|
|
|
private AmbientVertexRemap(final int vert0, final int vert1, final int vert2, final int vert3) {
|
|
this.vert0 = vert0;
|
|
this.vert1 = vert1;
|
|
this.vert2 = vert2;
|
|
this.vert3 = vert3;
|
|
}
|
|
|
|
public static ModelBlockRenderer.AmbientVertexRemap fromFacing(Direction facing) {
|
|
return BY_FACING[facing.get3DDataValue()];
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
static class Cache {
|
|
private boolean enabled;
|
|
private final Long2IntLinkedOpenHashMap colorCache = Util.make(() -> {
|
|
Long2IntLinkedOpenHashMap long2IntLinkedOpenHashMap = new 1(this, 100, 0.25F);
|
|
long2IntLinkedOpenHashMap.defaultReturnValue(Integer.MAX_VALUE);
|
|
return long2IntLinkedOpenHashMap;
|
|
});
|
|
private final Long2FloatLinkedOpenHashMap brightnessCache = Util.make(() -> {
|
|
Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = new 2(this, 100, 0.25F);
|
|
long2FloatLinkedOpenHashMap.defaultReturnValue(Float.NaN);
|
|
return long2FloatLinkedOpenHashMap;
|
|
});
|
|
private final LevelRenderer.BrightnessGetter cachedBrightnessGetter = (blockAndTintGetter, blockPos) -> {
|
|
long l = blockPos.asLong();
|
|
int i = this.colorCache.get(l);
|
|
if (i != Integer.MAX_VALUE) {
|
|
return i;
|
|
} else {
|
|
int j = LevelRenderer.BrightnessGetter.DEFAULT.packedBrightness(blockAndTintGetter, blockPos);
|
|
if (this.colorCache.size() == 100) {
|
|
this.colorCache.removeFirstInt();
|
|
}
|
|
|
|
this.colorCache.put(l, j);
|
|
return j;
|
|
}
|
|
};
|
|
|
|
private Cache() {
|
|
}
|
|
|
|
public void enable() {
|
|
this.enabled = true;
|
|
}
|
|
|
|
public void disable() {
|
|
this.enabled = false;
|
|
this.colorCache.clear();
|
|
this.brightnessCache.clear();
|
|
}
|
|
|
|
public int getLightColor(BlockState state, BlockAndTintGetter level, BlockPos pos) {
|
|
return LevelRenderer.getLightColor(this.enabled ? this.cachedBrightnessGetter : LevelRenderer.BrightnessGetter.DEFAULT, level, state, pos);
|
|
}
|
|
|
|
public float getShadeBrightness(BlockState state, BlockAndTintGetter level, BlockPos pos) {
|
|
long l = pos.asLong();
|
|
if (this.enabled) {
|
|
float f = this.brightnessCache.get(l);
|
|
if (!Float.isNaN(f)) {
|
|
return f;
|
|
}
|
|
}
|
|
|
|
float f = state.getShadeBrightness(level, pos);
|
|
if (this.enabled) {
|
|
if (this.brightnessCache.size() == 100) {
|
|
this.brightnessCache.removeFirstFloat();
|
|
}
|
|
|
|
this.brightnessCache.put(l, f);
|
|
}
|
|
|
|
return f;
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
static class CommonRenderStorage {
|
|
public final BlockPos.MutableBlockPos scratchPos = new BlockPos.MutableBlockPos();
|
|
public boolean faceCubic;
|
|
public boolean facePartial;
|
|
public final float[] brightness = new float[4];
|
|
public final int[] lightmap = new int[4];
|
|
public int tintCacheIndex = -1;
|
|
public int tintCacheValue;
|
|
public final ModelBlockRenderer.Cache cache = (ModelBlockRenderer.Cache)ModelBlockRenderer.CACHE.get();
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
protected static enum SizeInfo {
|
|
DOWN(0),
|
|
UP(1),
|
|
NORTH(2),
|
|
SOUTH(3),
|
|
WEST(4),
|
|
EAST(5),
|
|
FLIP_DOWN(6),
|
|
FLIP_UP(7),
|
|
FLIP_NORTH(8),
|
|
FLIP_SOUTH(9),
|
|
FLIP_WEST(10),
|
|
FLIP_EAST(11);
|
|
|
|
public static final int COUNT = values().length;
|
|
final int index;
|
|
|
|
private SizeInfo(final int index) {
|
|
this.index = index;
|
|
}
|
|
}
|
|
}
|