Rudebidium

- Misc. workarounds to make copycat blocks render correctly with sodiums optimization strategies
This commit is contained in:
simibubi 2023-04-18 13:43:13 +02:00
parent 641e0f000a
commit 1432c46c47
8 changed files with 68 additions and 17 deletions

View file

@ -278,6 +278,10 @@ public abstract class CopycatBlock extends Block implements IBE<CopycatBlockEnti
public boolean canFaceBeOccluded(BlockState state, Direction face) {
return false;
}
public boolean shouldFaceAlwaysRender(BlockState state, Direction face) {
return false;
}
// Wrapped properties

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.curiosities.frames;
import java.util.Collections;
import java.util.List;
import java.util.Random;
@ -48,11 +49,7 @@ public abstract class CopycatModel extends BakedModelWrapperWithData {
OcclusionData occlusionData = new OcclusionData();
if (state.getBlock() instanceof CopycatBlock copycatBlock) {
MutableBlockPos mutablePos = new MutableBlockPos();
for (Direction face : Iterate.directions)
if (copycatBlock.canFaceBeOccluded(state, face))
if (!Block.shouldRenderFace(material, world, pos, face, mutablePos.setWithOffset(pos, face)))
occlusionData.occlude(face);
gatherOcclusionData(world, pos, state, material, occlusionData, copycatBlock);
builder.withInitial(OCCLUSION_PROPERTY, occlusionData);
}
@ -60,8 +57,35 @@ public abstract class CopycatModel extends BakedModelWrapperWithData {
builder.withInitial(WRAPPED_DATA_PROPERTY, wrappedData);
}
private void gatherOcclusionData(BlockAndTintGetter world, BlockPos pos, BlockState state, BlockState material,
OcclusionData occlusionData, CopycatBlock copycatBlock) {
MutableBlockPos mutablePos = new MutableBlockPos();
for (Direction face : Iterate.directions) {
// Rubidium: Run an additional IForgeBlock.hidesNeighborFace check because it
// seems to be missing in Block.shouldRenderFace
MutableBlockPos neighbourPos = mutablePos.setWithOffset(pos, face);
BlockState neighbourState = world.getBlockState(neighbourPos);
if (state.supportsExternalFaceHiding()
&& neighbourState.hidesNeighborFace(world, neighbourPos, state, face.getOpposite())) {
occlusionData.occlude(face);
continue;
}
if (!copycatBlock.canFaceBeOccluded(state, face))
continue;
if (!Block.shouldRenderFace(material, world, pos, face, neighbourPos))
occlusionData.occlude(face);
}
}
@Override
public List<BakedQuad> getQuads(BlockState state, Direction side, Random rand, IModelData data) {
// Rubidium: see below
if (side != null && state.getBlock() instanceof CopycatBlock ccb && ccb.shouldFaceAlwaysRender(state, side))
return Collections.emptyList();
BlockState material = getMaterial(data);
if (material == null)
@ -79,7 +103,16 @@ public abstract class CopycatModel extends BakedModelWrapperWithData {
if (wrappedData == null)
wrappedData = EmptyModelData.INSTANCE;
return getCroppedQuads(state, side, rand, material, wrappedData);
List<BakedQuad> croppedQuads = getCroppedQuads(state, side, rand, material, wrappedData);
// Rubidium: render side!=null versions of the base material during side==null,
// to avoid getting culled away
if (side == null && state.getBlock() instanceof CopycatBlock ccb)
for (Direction nonOcclusionSide : Iterate.directions)
if (ccb.shouldFaceAlwaysRender(state, nonOcclusionSide))
croppedQuads.addAll(getCroppedQuads(state, nonOcclusionSide, rand, material, wrappedData));
return croppedQuads;
}
protected abstract List<BakedQuad> getCroppedQuads(BlockState state, Direction side, Random rand,

View file

@ -118,6 +118,11 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock {
.getOpposite() == face;
}
@Override
public boolean shouldFaceAlwaysRender(BlockState state, Direction face) {
return canFaceBeOccluded(state, face.getOpposite());
}
@Override
public BlockState getConnectiveMaterial(BlockAndTintGetter reader, BlockState otherState, Direction face,
BlockPos fromPos, BlockPos toPos) {

View file

@ -77,9 +77,8 @@ public class CopycatPanelModel extends CopycatModel {
if (!front && direction == facing.getOpposite())
continue;
BakedQuad newQuad = BakedQuadHelper.clone(quad);
BakedModelHelper.cropAndMove(newQuad, bb, normalScaledN13);
quads.add(newQuad);
quads.add(BakedQuadHelper.cloneWithCustomGeometry(quad,
BakedModelHelper.cropAndMove(quad.getVertices(), quad.getSprite(), bb, normalScaledN13)));
}
}

View file

@ -138,6 +138,11 @@ public class CopycatStepBlock extends WaterloggedCopycatBlock {
return (state.getValue(HALF) == Half.TOP) == (face == Direction.UP);
return state.getValue(FACING) == face;
}
@Override
public boolean shouldFaceAlwaysRender(BlockState state, Direction face) {
return canFaceBeOccluded(state, face.getOpposite());
}
@Override
public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) {

View file

@ -77,9 +77,8 @@ public class CopycatStepModel extends CopycatModel {
if (top && direction == Direction.DOWN)
continue;
BakedQuad newQuad = BakedQuadHelper.clone(quad);
BakedModelHelper.cropAndMove(newQuad, bb1, offset);
quads.add(newQuad);
quads.add(BakedQuadHelper.cloneWithCustomGeometry(quad,
BakedModelHelper.cropAndMove(quad.getVertices(), quad.getSprite(), bb1, offset)));
}
}

View file

@ -4,6 +4,7 @@ import static com.simibubi.create.foundation.block.render.SpriteShiftEntry.getUn
import static com.simibubi.create.foundation.block.render.SpriteShiftEntry.getUnInterpolatedV;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
@ -24,9 +25,10 @@ import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.model.data.EmptyModelData;
public class BakedModelHelper {
public static void cropAndMove(BakedQuad quad, AABB crop, Vec3 move) {
int[] vertexData = quad.getVertices();
public static int[] cropAndMove(int[] vertexData, TextureAtlasSprite sprite, AABB crop, Vec3 move) {
vertexData = Arrays.copyOf(vertexData, vertexData.length);
Vec3 xyz0 = BakedQuadHelper.getXYZ(vertexData, 0);
Vec3 xyz1 = BakedQuadHelper.getXYZ(vertexData, 1);
Vec3 xyz2 = BakedQuadHelper.getXYZ(vertexData, 2);
@ -46,8 +48,6 @@ public class BakedModelHelper {
float v0 = BakedQuadHelper.getV(vertexData, 0);
float v1 = BakedQuadHelper.getV(vertexData, 1);
TextureAtlasSprite sprite = quad.getSprite();
float uScale = (float) Math
.round((getUnInterpolatedU(sprite, u3) - getUnInterpolatedU(sprite, u0)) / xyz3.distanceTo(xyz0));
float vScale = (float) Math
@ -91,6 +91,8 @@ public class BakedModelHelper {
BakedQuadHelper.setXYZ(vertexData, vertex, newXyz.add(move));
}
return vertexData;
}
public static BakedModel generateModel(BakedModel template, UnaryOperator<TextureAtlasSprite> spriteSwapper) {

View file

@ -29,6 +29,10 @@ public final class BakedQuadHelper {
quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade());
}
public static BakedQuad cloneWithCustomGeometry(BakedQuad quad, int[] vertexData) {
return new BakedQuad(vertexData, quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade());
}
public static Vec3 getXYZ(int[] vertexData, int vertex) {
float x = Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + X_OFFSET]);
float y = Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + Y_OFFSET]);