Fix breaking overlay flickering on campfires by using vanilla method to calculate block normals. (#9664)

This commit is contained in:
Kovak authored and GitHub committed 2023-07-17 18:10:12 -07:00
1 parent ebb316a15c
commit 30f255d76c
5 files changed
+57 -18

No files matched your search

@@ -496,21 +496,30 @@ public class ForgeHooksClient
return new Material(TextureAtlas.LOCATION_BLOCKS, loc);
}
public static void fillNormal(int[] faceData, Direction facing)
{
fillNormal(faceData, facing, false);
}
/**
* internal, relies on fixed format of FaceBakery
*/
// TODO Do we need this?
public static void fillNormal(int[] faceData, Direction facing)
public static void fillNormal(int[] faceData, Direction facing, boolean calculateNormals)
{
Vector3f v1 = getVertexPos(faceData, 3);
Vector3f t1 = getVertexPos(faceData, 1);
Vector3f v2 = getVertexPos(faceData, 2);
Vector3f t2 = getVertexPos(faceData, 0);
v1.sub(t1);
v2.sub(t2);
v2.cross(v1);
v2.normalize();
Vector3f v2;
if (calculateNormals) {
Vector3f v1 = getVertexPos(faceData, 3);
Vector3f t1 = getVertexPos(faceData, 1);
v2 = getVertexPos(faceData, 2);
Vector3f t2 = getVertexPos(faceData, 0);
v1.sub(t1);
v2.sub(t2);
v2.cross(v1);
v2.normalize();
} else {
v2 = new Vector3f(facing.getNormal().getX(), facing.getNormal().getY(), facing.getNormal().getZ());
}
int x = ((byte) Math.round(v2.x() * 127)) & 0xFF;
int y = ((byte) Math.round(v2.y() * 127)) & 0xFF;
int z = ((byte) Math.round(v2.z() * 127)) & 0xFF;
@@ -28,11 +28,16 @@ import net.minecraft.util.ExtraCodecs;
* @param blockLight Block Light for this face from 0-15 (inclusive)
* @param skyLight Sky Light for this face from 0-15 (inclusive)
* @param ambientOcclusion If this face has AO
* @param calculateNormals If we should manually calculate the normals for this block or inherit facing normals like vanilla
*/
public record ForgeFaceData(int color, int blockLight, int skyLight, boolean ambientOcclusion)
public record ForgeFaceData(int color, int blockLight, int skyLight, boolean ambientOcclusion, boolean calculateNormals)
{
public ForgeFaceData(int color, int blockLight, int skyLight, boolean ambientOcclusion)
{
this(color, blockLight, skyLight, ambientOcclusion, false);
}
public static final ForgeFaceData DEFAULT = new ForgeFaceData(0xFFFFFFFF, 0, 0, true);
public static final ForgeFaceData DEFAULT = new ForgeFaceData(0xFFFFFFFF, 0, 0, true, false);
public static final Codec<Integer> COLOR = new ExtraCodecs.EitherCodec<>(Codec.INT, Codec.STRING).xmap(
either -> either.map(Function.identity(), str -> (int) Long.parseLong(str, 16)),
@@ -42,7 +47,8 @@ public record ForgeFaceData(int color, int blockLight, int skyLight, boolean amb
COLOR.optionalFieldOf("color", 0xFFFFFFFF).forGetter(ForgeFaceData::color),
Codec.intRange(0, 15).optionalFieldOf("block_light", 0).forGetter(ForgeFaceData::blockLight),
Codec.intRange(0, 15).optionalFieldOf("sky_light", 0).forGetter(ForgeFaceData::skyLight),
Codec.BOOL.optionalFieldOf("ambient_occlusion", true).forGetter(ForgeFaceData::ambientOcclusion))
Codec.BOOL.optionalFieldOf("ambient_occlusion", true).forGetter(ForgeFaceData::ambientOcclusion),
Codec.BOOL.optionalFieldOf("calculate_normals", false).forGetter(ForgeFaceData::calculateNormals))
.apply(builder, ForgeFaceData::new));
/**
@@ -388,6 +388,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
private int color = 0xFFFFFFFF;
private int blockLight = 0, skyLight = 0;
private boolean hasAmbientOcclusion = true;
private boolean calculateNormals = false;
private void validateCoordinate(float coord, char name) {
Preconditions.checkArgument(!(coord < -16.0F) && !(coord > 32.0F), "Position " + name + " out of range, must be within [-16, 32]. Found: %d", coord);
@@ -556,6 +557,17 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
return this;
}
/**
* Sets whether we should calculate actual normals for the faces of this model or inherit them from facing the
* way vanilla does
* @param calc whether to calculate normals
* @return this builder
*/
public ElementBuilder calculateNormals(boolean calc) {
this.calculateNormals = calc;
return this;
}
private BiConsumer<Direction, FaceBuilder> addTexture(String texture) {
return ($, f) -> f.texture(texture);
}
@@ -563,7 +575,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
BlockElement build() {
Map<Direction, BlockElementFace> faces = this.faces.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().build(), (k1, k2) -> { throw new IllegalArgumentException(); }, LinkedHashMap::new));
return new BlockElement(from, to, faces, rotation == null ? null : rotation.build(), shade, new ForgeFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion));
return new BlockElement(from, to, faces, rotation == null ? null : rotation.build(), shade, new ForgeFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion, this.calculateNormals));
}
public T end() { return self(); }
@@ -578,6 +590,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
private int color = 0xFFFFFFFF;
private int blockLight = 0, skyLight = 0;
private boolean hasAmbientOcclusion = true;
private boolean calculateNormals = false;
FaceBuilder(Direction dir) {
// param unused for functional match
@@ -660,11 +673,22 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
return this;
}
/**
* Sets whether we should calculate actual normals for this face or inherit them from facing the
* way vanilla does
* @param calc whether to calculate normals
* @return this builder
*/
public FaceBuilder calculateNormals(boolean calc) {
this.calculateNormals = calc;
return this;
}
BlockElementFace build() {
if (this.texture == null) {
throw new IllegalStateException("A model face must have a texture");
}
return new BlockElementFace(cullface, tintindex, texture, new BlockFaceUV(uvs, rotation.rotation), new ForgeFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion));
return new BlockElementFace(cullface, tintindex, texture, new BlockFaceUV(uvs, rotation.rotation), new ForgeFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion, this.calculateNormals));
}
public ElementBuilder end() { return ElementBuilder.this; }
@@ -60,7 +60,7 @@ public class ItemLayerModelBuilder<T extends ModelBuilder<T>> extends CustomLoad
{
faceData.compute(i, (key, value) -> {
ForgeFaceData fallback = value == null ? ForgeFaceData.DEFAULT : value;
return new ForgeFaceData(fallback.color(), blockLight, skyLight, fallback.ambientOcclusion());
return new ForgeFaceData(fallback.color(), blockLight, skyLight, fallback.ambientOcclusion(), fallback.calculateNormals());
});
}
return this;
@@ -85,7 +85,7 @@ public class ItemLayerModelBuilder<T extends ModelBuilder<T>> extends CustomLoad
{
faceData.compute(i, (key, value) -> {
ForgeFaceData fallback = value == null ? ForgeFaceData.DEFAULT : value;
return new ForgeFaceData(color, fallback.blockLight(), fallback.skyLight(), fallback.ambientOcclusion());
return new ForgeFaceData(color, fallback.blockLight(), fallback.skyLight(), fallback.ambientOcclusion(), fallback.calculateNormals());
});
}
return this;