From 33b1f8f30fcdf53109e8d28aeba010ddd33198d1 Mon Sep 17 00:00:00 2001 From: RainWarrior Date: Wed, 30 Dec 2015 13:31:36 +0300 Subject: [PATCH] Caching of fluid models. Fixes #2145. --- .../client/model/ModelFluid.java | 81 ++++++++++++++++--- 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/minecraftforge/client/model/ModelFluid.java b/src/main/java/net/minecraftforge/client/model/ModelFluid.java index 1fc7d10f0c..dd4fb11b5a 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelFluid.java +++ b/src/main/java/net/minecraftforge/client/model/ModelFluid.java @@ -29,6 +29,9 @@ import net.minecraftforge.fml.common.FMLLog; import com.google.common.base.Function; import com.google.common.base.Optional; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -100,12 +103,28 @@ public class ModelFluid implements IModelCustomData private static final int z[] = { 0, 1, 1, 0 }; private static final float eps = 1e-3f; + private final LoadingCache modelCache = CacheBuilder.newBuilder().maximumSize(200).build(new CacheLoader() + { + public BakedFluid load(Long key) throws Exception + { + boolean statePresent = (key & 1) != 0; + key >>>= 1; + int[] cornerRound = new int[4]; + for(int i = 0; i < 4; i++) + { + cornerRound[i] = (int)(key & 0x3FF); + key >>>= 10; + } + int flowRound = (int)(key & 0x7FF) - 1024; + return new BakedFluid(transformation, format, color, still, flowing, gas, statePresent, cornerRound, flowRound); + } + }); + private final Optional transformation; private final VertexFormat format; private final int color; private final TextureAtlasSprite still, flowing; private final boolean gas; - private final Optional state; private final EnumMap> faceQuads; public BakedFluid(Optional transformation, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, boolean gas) @@ -114,6 +133,35 @@ public class ModelFluid implements IModelCustomData } public BakedFluid(Optional transformation, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, boolean gas, Optional stateOption) + { + this(transformation, format, color, still, flowing, gas, stateOption.isPresent(), getCorners(stateOption), getFlow(stateOption)); + } + + private static int[] getCorners(Optional stateOption) + { + int[] cornerRound = new int[]{0, 0, 0, 0}; + if(stateOption.isPresent()) + { + IExtendedBlockState state = stateOption.get(); + for(int i = 0; i < 4; i++) + { + cornerRound[i] = Math.round(state.getValue(BlockFluidBase.LEVEL_CORNERS[i]) * 768); + } + } + return cornerRound; + } + + private static int getFlow(Optional stateOption) + { + int flowRound = -1000; + if(stateOption.isPresent()) + { + flowRound = (int)Math.round(Math.toDegrees(stateOption.get().getValue(BlockFluidBase.FLOW_DIRECTION))); + } + return flowRound; + } + + public BakedFluid(Optional transformation, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, boolean gas, boolean statePresent, int[] cornerRound, int flowRound) { this.transformation = transformation; this.format = format; @@ -121,7 +169,6 @@ public class ModelFluid implements IModelCustomData this.still = still; this.flowing = flowing; this.gas = gas; - this.state = stateOption; faceQuads = Maps.newEnumMap(EnumFacing.class); for(EnumFacing side : EnumFacing.values()) @@ -129,23 +176,22 @@ public class ModelFluid implements IModelCustomData faceQuads.put(side, ImmutableList.of()); } - if(state.isPresent()) + if(statePresent) { - IExtendedBlockState state = this.state.get(); float[] y = new float[4]; for(int i = 0; i < 4; i++) { if(gas) { - y[i] = 1 - state.getValue(BlockFluidBase.LEVEL_CORNERS[i]); + y[i] = 1 - cornerRound[i] / 768f; } else { - y[i] = state.getValue(BlockFluidBase.LEVEL_CORNERS[i]); + y[i] = cornerRound[i] / 768f; } } - float flow = state.getValue(BlockFluidBase.FLOW_DIRECTION); + float flow = (float)Math.toRadians(flowRound); // top @@ -222,7 +268,6 @@ public class ModelFluid implements IModelCustomData else { // 1 quad for inventory - UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(format); builder.setQuadOrientation(EnumFacing.UP); builder.setQuadColored(); @@ -242,7 +287,6 @@ public class ModelFluid implements IModelCustomData { for(int e = 0; e < format.getElementCount(); e++) { - // TODO transformation switch(format.getElement(e).getUsage()) { case POSITION: @@ -280,7 +324,7 @@ public class ModelFluid implements IModelCustomData public boolean isAmbientOcclusion() { - return false; // FIXME + return false; } public boolean isGui3d() @@ -320,7 +364,22 @@ public class ModelFluid implements IModelCustomData public IBakedModel handleBlockState(IBlockState state) { - return new BakedFluid(transformation, format, color, still, flowing, gas, Optional.of((IExtendedBlockState)state)); + if(state instanceof IExtendedBlockState) + { + IExtendedBlockState exState = (IExtendedBlockState)state; + int[] cornerRound = getCorners(Optional.of(exState)); + int flowRound = getFlow(Optional.of(exState)); + long key = flowRound + 1024; + for(int i = 3; i >= 0; i--) + { + key <<= 10; + key |= cornerRound[i]; + } + key <<= 1; + key |= 1; + return modelCache.getUnchecked(key); + } + return this; } }