More Rendering fixes

This commit is contained in:
Sebastian Hartte
2020-06-08 18:35:27 +02:00
parent 679ea1c332
commit b2afa0398c
44 changed files with 427 additions and 276 deletions
@@ -0,0 +1,67 @@
package appeng.client.render.model;
import com.google.common.base.Preconditions;
import net.minecraft.util.Direction;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* This implementation of IModelData allows us to know precisely which data is part of the
* model data. This is relevant for {@link AutoRotatingBakedModel} and {@link AutoRotatingCacheKey}.
*/
public class AEModelData implements IModelData {
private final Direction up;
private final Direction forward;
public AEModelData(Direction up, Direction forward) {
this.up = Preconditions.checkNotNull(up);
this.forward = Preconditions.checkNotNull(forward);
}
public Direction getUp() {
return up;
}
public Direction getForward() {
return forward;
}
public boolean isCacheable() {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AEModelData that = (AEModelData) o;
return up == that.up &&
forward == that.forward;
}
@Override
public int hashCode() {
return Objects.hash(up, forward);
}
@Override
public boolean hasProperty(ModelProperty<?> prop) {
return false;
}
@Nullable
@Override
public <T> T getData(ModelProperty<T> prop) {
throw new IllegalStateException();
}
@Nullable
@Override
public <T> T setData(ModelProperty<T> prop, T data) {
throw new IllegalStateException();
}
}
@@ -19,7 +19,6 @@
package appeng.client.render.model;
import appeng.block.AEBaseTileBlock;
import appeng.client.render.FacingToRotation;
import com.google.common.base.Objects;
import com.google.common.cache.CacheBuilder;
@@ -36,7 +35,9 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.ILightReader;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
@@ -63,17 +64,17 @@ public class AutoRotatingBakedModel implements IBakedModel
this.quadCache = CacheBuilder.newBuilder().maximumSize( 252 ).build( new CacheLoader<AutoRotatingCacheKey, List<BakedQuad>>()
{
@Override
public List<BakedQuad> load( AutoRotatingCacheKey key ) throws Exception
public List<BakedQuad> load( AutoRotatingCacheKey key )
{
return AutoRotatingBakedModel.this.getRotatedModel( key.getBlockState(), key.getSide(), key.getForward(), key.getUp() );
return AutoRotatingBakedModel.this.getRotatedModel( key.getBlockState(), key.getSide(), new Random(0), key.getModelData() );
}
} );
}
private List<BakedQuad> getRotatedModel( BlockState state, Direction side, Direction forward, Direction up )
private List<BakedQuad> getRotatedModel(BlockState state, Direction side, Random rand, AEModelData modelData)
{
FacingToRotation f2r = FacingToRotation.get( forward, up );
List<BakedQuad> original = AutoRotatingBakedModel.this.parent.getQuads( state, f2r.resultingRotate( side ), new Random(0) );
FacingToRotation f2r = FacingToRotation.get( modelData.getForward(), modelData.getUp() );
List<BakedQuad> original = AutoRotatingBakedModel.this.parent.getQuads( state, f2r.resultingRotate( side ), rand, modelData );
List<BakedQuad> rotated = new ArrayList<>( original.size() );
for( BakedQuad quad : original )
{
@@ -155,21 +156,23 @@ public class AutoRotatingBakedModel implements IBakedModel
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData) {
Direction forward = extraData.getData(AEBaseTileBlock.FORWARD);
Direction up = extraData.getData(AEBaseTileBlock.UP);
if( forward == null || up == null )
{
if (!(extraData instanceof AEModelData)) {
return this.parent.getQuads( state, side, rand, extraData );
}
// The model has other properties than just forward/up, so it would cause our cache to inadvertendly also cache
// these
// additional states, possibly leading to huge issues if the other extended state properties do not implement
// equals/hashCode correctly
// FIXME: IModelData does not expose a way for us to check if it only has the two properties and no other
return this.getRotatedModel( state, side, forward, up );
AEModelData aeModelData = (AEModelData) extraData;
if (aeModelData.isCacheable()) {
return quadCache.getUnchecked(new AutoRotatingCacheKey(state, aeModelData, side));
} else {
return this.getRotatedModel(state, side, rand, aeModelData);
}
}
@Nonnull
@Override
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData) {
return this.parent.getModelData(world, pos, state, tileData);
}
public static class VertexRotator extends QuadGatheringTransformer
@@ -29,15 +29,13 @@ import net.minecraft.util.Direction;
final class AutoRotatingCacheKey
{
private final BlockState blockState;
private final Direction forward;
private final Direction up;
private final AEModelData modelData;
private final Direction side;
AutoRotatingCacheKey( BlockState blockState, Direction forward, Direction up, Direction side )
AutoRotatingCacheKey( BlockState blockState, AEModelData modelData, Direction side )
{
this.blockState = blockState;
this.forward = forward;
this.up = up;
this.modelData = modelData;
this.side = side;
}
@@ -46,14 +44,8 @@ final class AutoRotatingCacheKey
return this.blockState;
}
public Direction getForward()
{
return this.forward;
}
public Direction getUp()
{
return this.up;
public AEModelData getModelData() {
return modelData;
}
public Direction getSide()
@@ -74,15 +66,14 @@ final class AutoRotatingCacheKey
}
AutoRotatingCacheKey cacheKey = (AutoRotatingCacheKey) o;
return this.blockState.equals( cacheKey.blockState ) && this.forward == cacheKey.forward && this.up == cacheKey.up && this.side == cacheKey.side;
return this.blockState.equals( cacheKey.blockState ) && this.modelData.equals(cacheKey.modelData) && this.side == cacheKey.side;
}
@Override
public int hashCode()
{
int result = this.blockState.hashCode();
result = 31 * result + this.forward.hashCode();
result = 31 * result + this.up.hashCode();
result = 31 * result + this.modelData.hashCode();
result = 31 * result + ( this.side != null ? this.side.hashCode() : 0 );
return result;
}
@@ -57,7 +57,12 @@ public class DriveBakedModel extends DelegateBakedModel
List<BakedQuad> result = new ArrayList<>(this.bakedBase.getQuads(state, side, rand, extraData));
DriveSlotsState slotsState = extraData.getData( TileDrive.SLOTS_STATE );
if (!(extraData instanceof DriveModelData)) {
return result;
}
DriveModelData driveModelData = (DriveModelData) extraData;
DriveSlotsState slotsState = driveModelData.getSlotsState();
if( side == null && slotsState != null )
{
@@ -20,7 +20,9 @@ package appeng.client.render.model;
import appeng.block.storage.DriveSlotState;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@@ -43,6 +45,11 @@ public class DriveModel implements IModelGeometry<DriveModel>
DriveSlotState.TYPES_FULL, new ResourceLocation( "appliedenergistics2:block/drive_cell_types_full" ),
DriveSlotState.FULL, new ResourceLocation( "appliedenergistics2:block/drive_cell_full" ) );
public static final Set<ResourceLocation> DEPENDENCIES = ImmutableSet.<ResourceLocation>builder()
.addAll(MODELS_CELLS.values())
.add(MODEL_BASE)
.build();
@Override
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
EnumMap<DriveSlotState, IBakedModel> cellModels = new EnumMap<>( DriveSlotState.class );
@@ -0,0 +1,44 @@
package appeng.client.render.model;
import appeng.block.storage.DriveSlotsState;
import com.google.common.base.Preconditions;
import net.minecraft.util.Direction;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import javax.annotation.Nullable;
import java.util.Objects;
public class DriveModelData extends AEModelData {
private final DriveSlotsState slotsState;
public DriveModelData(Direction up, Direction forward, DriveSlotsState slotsState) {
super(up, forward);
this.slotsState = slotsState;
}
@Override
public boolean isCacheable() {
return false; // Too many combinations
}
public DriveSlotsState getSlotsState() {
return slotsState;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
DriveModelData that = (DriveModelData) o;
return slotsState.equals(that.slotsState);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), slotsState);
}
}