2016-06-23 03:49:47 +00:00
|
|
|
/*
|
|
|
|
* Minecraft Forge
|
2018-07-01 21:17:28 +00:00
|
|
|
* Copyright (c) 2016-2018.
|
2016-06-23 03:49:47 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation version 2.1
|
|
|
|
* of the License.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
2015-06-18 11:14:46 +00:00
|
|
|
package net.minecraftforge.client.model;
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
import java.util.function.Function;
|
2015-06-18 11:14:46 +00:00
|
|
|
import java.util.Collection;
|
2018-09-08 20:34:59 +00:00
|
|
|
import java.util.Collections;
|
2015-06-18 11:14:46 +00:00
|
|
|
import java.util.EnumMap;
|
|
|
|
import java.util.List;
|
2018-07-18 03:37:20 +00:00
|
|
|
import java.util.Optional;
|
2018-09-08 20:34:59 +00:00
|
|
|
import java.util.Random;
|
|
|
|
import java.util.Set;
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2017-06-25 01:08:20 +00:00
|
|
|
import javax.annotation.Nullable;
|
2016-01-04 10:54:45 +00:00
|
|
|
import javax.vecmath.Matrix4f;
|
2015-12-03 19:38:08 +00:00
|
|
|
import javax.vecmath.Vector4f;
|
|
|
|
|
2015-06-18 11:14:46 +00:00
|
|
|
import net.minecraft.block.state.IBlockState;
|
|
|
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
2016-03-23 14:34:48 +00:00
|
|
|
import net.minecraft.client.renderer.block.model.IBakedModel;
|
2018-09-08 20:34:59 +00:00
|
|
|
import net.minecraft.client.renderer.block.model.IUnbakedModel;
|
2015-12-03 19:38:08 +00:00
|
|
|
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
|
2016-03-01 20:19:38 +00:00
|
|
|
import net.minecraft.client.renderer.block.model.ItemOverrideList;
|
2015-06-18 11:14:46 +00:00
|
|
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
|
|
|
import net.minecraft.client.renderer.vertex.VertexFormat;
|
2018-09-06 13:27:24 +00:00
|
|
|
import net.minecraft.resources.IResourceManager;
|
2015-06-18 11:14:46 +00:00
|
|
|
import net.minecraft.util.EnumFacing;
|
|
|
|
import net.minecraft.util.ResourceLocation;
|
2016-03-01 20:19:38 +00:00
|
|
|
import net.minecraft.util.math.MathHelper;
|
2015-06-28 22:19:10 +00:00
|
|
|
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
|
2018-10-04 23:28:45 +00:00
|
|
|
import net.minecraftforge.versions.forge.ForgeVersion;
|
2016-03-21 07:01:30 +00:00
|
|
|
import net.minecraftforge.common.model.IModelState;
|
|
|
|
import net.minecraftforge.common.model.TRSRTransformation;
|
2015-06-18 11:14:46 +00:00
|
|
|
import net.minecraftforge.common.property.IExtendedBlockState;
|
|
|
|
import net.minecraftforge.fluids.Fluid;
|
|
|
|
|
2016-01-04 10:54:45 +00:00
|
|
|
import org.apache.commons.lang3.tuple.Pair;
|
2018-09-06 13:27:24 +00:00
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
|
|
import org.apache.logging.log4j.Logger;
|
2016-01-04 10:54:45 +00:00
|
|
|
|
2015-12-30 10:31:36 +00:00
|
|
|
import com.google.common.cache.CacheBuilder;
|
|
|
|
import com.google.common.cache.CacheLoader;
|
|
|
|
import com.google.common.cache.LoadingCache;
|
2015-06-18 11:14:46 +00:00
|
|
|
import com.google.common.collect.ImmutableList;
|
|
|
|
import com.google.common.collect.ImmutableMap;
|
|
|
|
import com.google.common.collect.ImmutableSet;
|
|
|
|
import com.google.gson.JsonElement;
|
|
|
|
import com.google.gson.JsonParser;
|
|
|
|
|
2018-09-08 20:34:59 +00:00
|
|
|
public final class ModelFluid implements IUnbakedModel
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2018-09-06 13:27:24 +00:00
|
|
|
private static final Logger LOGGER = LogManager.getLogger();
|
2018-09-18 04:04:02 +00:00
|
|
|
public static final ModelFluid WATER = null; // TODO fluids new ModelFluid(FluidRegistry.WATER);
|
|
|
|
public static final ModelFluid LAVA = null; // TODO fluids new ModelFluid(FluidRegistry.LAVA);
|
2018-07-18 03:37:20 +00:00
|
|
|
|
2015-06-18 11:14:46 +00:00
|
|
|
private final Fluid fluid;
|
|
|
|
|
|
|
|
public ModelFluid(Fluid fluid)
|
|
|
|
{
|
|
|
|
this.fluid = fluid;
|
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
@Override
|
2018-09-22 10:40:22 +00:00
|
|
|
public Collection<ResourceLocation> getTextures(Function<ResourceLocation, IUnbakedModel> modelGetter, Set<String> missingTextureErrors)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
return fluid.getOverlay() != null
|
|
|
|
? ImmutableSet.of(fluid.getStill(), fluid.getFlowing(), fluid.getOverlay())
|
|
|
|
: ImmutableSet.of(fluid.getStill(), fluid.getFlowing());
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
2018-09-22 10:40:22 +00:00
|
|
|
|
2018-09-08 20:34:59 +00:00
|
|
|
@Override
|
|
|
|
public Collection<ResourceLocation> getOverrideLocations() {
|
|
|
|
return Collections.emptyList();
|
|
|
|
}
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2018-09-08 20:34:59 +00:00
|
|
|
public IBakedModel bake(Function<ResourceLocation, IUnbakedModel> modelGetter, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter, IModelState state, boolean uvlock, VertexFormat format)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
return new CachingBakedFluid(
|
|
|
|
state.apply(Optional.empty()),
|
|
|
|
PerspectiveMapWrapper.getTransforms(state),
|
|
|
|
format,
|
|
|
|
fluid.getColor(),
|
|
|
|
bakedTextureGetter.apply(fluid.getStill()),
|
|
|
|
bakedTextureGetter.apply(fluid.getFlowing()),
|
|
|
|
Optional.ofNullable(fluid.getOverlay()).map(bakedTextureGetter),
|
|
|
|
fluid.isLighterThanAir(),
|
|
|
|
Optional.empty()
|
|
|
|
);
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
public enum FluidLoader implements ICustomModelLoader
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2016-03-21 07:23:27 +00:00
|
|
|
INSTANCE;
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2018-09-22 10:40:22 +00:00
|
|
|
public void onResourceManagerReload(IResourceManager resourceManager) {}
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2015-06-18 11:14:46 +00:00
|
|
|
public boolean accepts(ResourceLocation modelLocation)
|
|
|
|
{
|
2018-09-06 13:27:24 +00:00
|
|
|
return modelLocation.getNamespace().equals(ForgeVersion.MOD_ID) && (
|
|
|
|
modelLocation.getPath().equals("fluid") ||
|
|
|
|
modelLocation.getPath().equals("models/block/fluid") ||
|
|
|
|
modelLocation.getPath().equals("models/item/fluid"));
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2018-09-08 20:34:59 +00:00
|
|
|
public IUnbakedModel loadModel(ResourceLocation modelLocation)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2016-03-21 07:23:27 +00:00
|
|
|
return WATER;
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
private static final class CachingBakedFluid extends BakedFluid
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2015-12-30 10:31:36 +00:00
|
|
|
private final LoadingCache<Long, BakedFluid> modelCache = CacheBuilder.newBuilder().maximumSize(200).build(new CacheLoader<Long, BakedFluid>()
|
|
|
|
{
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2018-07-18 03:37:20 +00:00
|
|
|
public BakedFluid load(Long key)
|
2015-12-30 10:31:36 +00:00
|
|
|
{
|
|
|
|
boolean statePresent = (key & 1) != 0;
|
|
|
|
key >>>= 1;
|
|
|
|
int[] cornerRound = new int[4];
|
2018-07-18 03:37:20 +00:00
|
|
|
for (int i = 0; i < 4; i++)
|
2015-12-30 10:31:36 +00:00
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
cornerRound[i] = (int) (key & 0x3FF);
|
2015-12-30 10:31:36 +00:00
|
|
|
key >>>= 10;
|
|
|
|
}
|
2018-07-18 03:37:20 +00:00
|
|
|
int flowRound = (int) (key & 0x7FF) - 1024;
|
|
|
|
key >>>= 11;
|
|
|
|
boolean[] overlaySides = new boolean[4];
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
overlaySides[i] = (key & 1) != 0;
|
|
|
|
key >>>= 1;
|
|
|
|
}
|
|
|
|
return new BakedFluid(transformation, transforms, format, color, still, flowing, overlay, gas, statePresent, cornerRound, flowRound, overlaySides);
|
2015-12-30 10:31:36 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
public CachingBakedFluid(Optional<TRSRTransformation> transformation, ImmutableMap<TransformType, TRSRTransformation> transforms, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, Optional<TextureAtlasSprite> overlay, boolean gas, Optional<IExtendedBlockState> stateOption)
|
2016-01-04 10:54:45 +00:00
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
super(transformation, transforms, format, color, still, flowing, overlay, gas, stateOption.isPresent(), getCorners(stateOption), getFlow(stateOption), getOverlay(stateOption));
|
2015-12-30 10:31:36 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
/**
|
|
|
|
* Gets the quantized fluid levels for each corner.
|
|
|
|
*
|
|
|
|
* Each value is packed into 10 bits of the model key, so max range is [0,1024).
|
|
|
|
* The value is currently stored/interpreted as the closest multiple of 1/864.
|
|
|
|
* The divisor is chosen here to allows likely flow values to be exactly representable
|
|
|
|
* while also providing good use of the available value range.
|
|
|
|
* (For fluids with default quanta, this evenly divides the per-block intervals of 1/9 by 96)
|
|
|
|
*/
|
2015-12-30 10:31:36 +00:00
|
|
|
private static int[] getCorners(Optional<IExtendedBlockState> stateOption)
|
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
int[] cornerRound = {0, 0, 0, 0};
|
|
|
|
if (stateOption.isPresent())
|
2015-12-30 10:31:36 +00:00
|
|
|
{
|
|
|
|
IExtendedBlockState state = stateOption.get();
|
2018-07-18 03:37:20 +00:00
|
|
|
for (int i = 0; i < 4; i++)
|
2015-12-30 10:31:36 +00:00
|
|
|
{
|
2018-09-18 04:04:02 +00:00
|
|
|
Float level = null; // TODO fluids state.getValue(BlockFluidBase.LEVEL_CORNERS[i]);
|
2018-07-18 03:37:20 +00:00
|
|
|
cornerRound[i] = Math.round((level == null ? 8f / 9f : level) * 864);
|
2015-12-30 10:31:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return cornerRound;
|
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
/**
|
|
|
|
* Gets the quantized flow direction of the fluid.
|
|
|
|
*
|
|
|
|
* This value comprises 11 bits of the model key, and is signed, so the max range is [-1024,1024).
|
|
|
|
* The value is currently stored as the angle rounded to the nearest degree.
|
|
|
|
* A value of -1000 is used to signify no flow.
|
|
|
|
*/
|
2015-12-30 10:31:36 +00:00
|
|
|
private static int getFlow(Optional<IExtendedBlockState> stateOption)
|
|
|
|
{
|
2016-02-16 11:13:19 +00:00
|
|
|
Float flow = -1000f;
|
2018-07-18 03:37:20 +00:00
|
|
|
if (stateOption.isPresent())
|
2015-12-30 10:31:36 +00:00
|
|
|
{
|
2018-09-18 04:04:02 +00:00
|
|
|
flow = null; // TODO fluids stateOption.get().getValue(BlockFluidBase.FLOW_DIRECTION);
|
2018-07-18 03:37:20 +00:00
|
|
|
if (flow == null) flow = -1000f;
|
2015-12-30 10:31:36 +00:00
|
|
|
}
|
2018-07-18 03:37:20 +00:00
|
|
|
int flowRound = (int) Math.round(Math.toDegrees(flow));
|
2016-12-21 23:52:30 +00:00
|
|
|
flowRound = MathHelper.clamp(flowRound, -1000, 1000);
|
2015-12-30 10:31:36 +00:00
|
|
|
return flowRound;
|
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
/**
|
|
|
|
* Gets the overlay texture flag for each side.
|
|
|
|
*
|
|
|
|
* This value determines if the fluid "overlay" texture should be used for that side,
|
|
|
|
* instead of the normal "flowing" texture (if applicable for that fluid).
|
|
|
|
* The sides are stored here by their regular horizontal index.
|
|
|
|
*/
|
|
|
|
private static boolean[] getOverlay(Optional<IExtendedBlockState> stateOption)
|
|
|
|
{
|
|
|
|
boolean[] overlaySides = new boolean[4];
|
|
|
|
if (stateOption.isPresent())
|
|
|
|
{
|
|
|
|
IExtendedBlockState state = stateOption.get();
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
2018-09-18 04:04:02 +00:00
|
|
|
Boolean overlay = null; // TODO fluids state.getValue(BlockFluidBase.SIDE_OVERLAYS[i]);
|
2018-07-18 03:37:20 +00:00
|
|
|
if (overlay != null) overlaySides[i] = overlay;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return overlaySides;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-09-22 10:40:22 +00:00
|
|
|
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, Random rand)
|
2018-07-18 03:37:20 +00:00
|
|
|
{
|
|
|
|
if (side != null && state instanceof IExtendedBlockState)
|
|
|
|
{
|
|
|
|
Optional<IExtendedBlockState> exState = Optional.of((IExtendedBlockState)state);
|
|
|
|
|
|
|
|
int[] cornerRound = getCorners(exState);
|
|
|
|
int flowRound = getFlow(exState);
|
|
|
|
boolean[] overlaySides = getOverlay(exState);
|
|
|
|
|
|
|
|
long key = 0L;
|
|
|
|
for (int i = 3; i >= 0; i--)
|
|
|
|
{
|
|
|
|
key <<= 1;
|
|
|
|
key |= overlaySides[i] ? 1 : 0;
|
|
|
|
}
|
|
|
|
key <<= 11;
|
|
|
|
key |= flowRound + 1024;
|
|
|
|
for (int i = 3; i >= 0; i--)
|
|
|
|
{
|
|
|
|
key <<= 10;
|
|
|
|
key |= cornerRound[i];
|
|
|
|
}
|
|
|
|
key <<= 1;
|
|
|
|
key |= 1;
|
|
|
|
|
2018-09-22 10:40:22 +00:00
|
|
|
return modelCache.getUnchecked(key).getQuads(state, side, rand);
|
2018-07-18 03:37:20 +00:00
|
|
|
}
|
|
|
|
|
2018-09-22 10:40:22 +00:00
|
|
|
return super.getQuads(state, side, rand);
|
2018-07-18 03:37:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class BakedFluid implements IBakedModel
|
|
|
|
{
|
|
|
|
private static final int x[] = { 0, 0, 1, 1 };
|
|
|
|
private static final int z[] = { 0, 1, 1, 0 };
|
|
|
|
private static final float eps = 1e-3f;
|
|
|
|
|
|
|
|
protected final Optional<TRSRTransformation> transformation;
|
|
|
|
protected final ImmutableMap<TransformType, TRSRTransformation> transforms;
|
|
|
|
protected final VertexFormat format;
|
|
|
|
protected final int color;
|
|
|
|
protected final TextureAtlasSprite still, flowing;
|
|
|
|
protected final Optional<TextureAtlasSprite> overlay;
|
|
|
|
protected final boolean gas;
|
|
|
|
protected final ImmutableMap<EnumFacing, ImmutableList<BakedQuad>> faceQuads;
|
|
|
|
|
|
|
|
public BakedFluid(Optional<TRSRTransformation> transformation, ImmutableMap<TransformType, TRSRTransformation> transforms, VertexFormat format, int color, TextureAtlasSprite still, TextureAtlasSprite flowing, Optional<TextureAtlasSprite> overlay, boolean gas, boolean statePresent, int[] cornerRound, int flowRound, boolean[] sideOverlays)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
|
|
|
this.transformation = transformation;
|
2016-01-04 10:54:45 +00:00
|
|
|
this.transforms = transforms;
|
2015-06-18 11:14:46 +00:00
|
|
|
this.format = format;
|
|
|
|
this.color = color;
|
|
|
|
this.still = still;
|
|
|
|
this.flowing = flowing;
|
2018-07-18 03:37:20 +00:00
|
|
|
this.overlay = overlay;
|
2015-06-18 11:14:46 +00:00
|
|
|
this.gas = gas;
|
2018-07-18 03:37:20 +00:00
|
|
|
this.faceQuads = buildQuads(statePresent, cornerRound, flowRound, sideOverlays);
|
|
|
|
}
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
private ImmutableMap<EnumFacing, ImmutableList<BakedQuad>> buildQuads(boolean statePresent, int[] cornerRound, int flowRound, boolean[] sideOverlays)
|
|
|
|
{
|
|
|
|
EnumMap<EnumFacing, ImmutableList<BakedQuad>> faceQuads = new EnumMap<>(EnumFacing.class);
|
|
|
|
for (EnumFacing side : EnumFacing.values())
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2017-06-25 01:08:20 +00:00
|
|
|
faceQuads.put(side, ImmutableList.of());
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
if (statePresent)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
// y levels
|
2015-06-18 11:14:46 +00:00
|
|
|
float[] y = new float[4];
|
2018-07-18 03:37:20 +00:00
|
|
|
boolean fullVolume = true;
|
|
|
|
for (int i = 0; i < 4; i++)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
float value = cornerRound[i] / 864f;
|
|
|
|
if (value < 1f) fullVolume = false;
|
|
|
|
y[i] = gas ? 1f - value : value;
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
// flow
|
|
|
|
boolean isFlowing = flowRound > -1000;
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
float flow = isFlowing ? (float) Math.toRadians(flowRound) : 0f;
|
|
|
|
TextureAtlasSprite topSprite = isFlowing ? flowing : still;
|
|
|
|
float scale = isFlowing ? 4f : 8f;
|
2015-06-18 11:14:46 +00:00
|
|
|
|
|
|
|
float c = MathHelper.cos(flow) * scale;
|
|
|
|
float s = MathHelper.sin(flow) * scale;
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
// top
|
|
|
|
EnumFacing top = gas ? EnumFacing.DOWN : EnumFacing.UP;
|
|
|
|
|
|
|
|
// base uv offset for flow direction
|
|
|
|
VertexParameter uv = i -> c * (x[i] * 2 - 1) + s * (z[i] * 2 - 1);
|
|
|
|
|
|
|
|
VertexParameter topX = i -> x[i];
|
|
|
|
VertexParameter topY = i -> y[i];
|
|
|
|
VertexParameter topZ = i -> z[i];
|
|
|
|
VertexParameter topU = i -> 8 + uv.get(i);
|
|
|
|
VertexParameter topV = i -> 8 + uv.get((i + 1) % 4);
|
|
|
|
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
|
|
|
|
|
|
|
builder.add(buildQuad(top, topSprite, gas, false, topX, topY, topZ, topU, topV));
|
|
|
|
if (!fullVolume) builder.add(buildQuad(top, topSprite, !gas, true, topX, topY, topZ, topU, topV));
|
|
|
|
|
|
|
|
faceQuads.put(top, builder.build());
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// bottom
|
2018-07-18 03:37:20 +00:00
|
|
|
EnumFacing bottom = top.getOpposite();
|
|
|
|
faceQuads.put(bottom, ImmutableList.of(
|
|
|
|
buildQuad(bottom, still, gas, false,
|
|
|
|
i -> z[i],
|
|
|
|
i -> gas ? 1 : 0,
|
|
|
|
i -> x[i],
|
|
|
|
i -> z[i] * 16,
|
|
|
|
i -> x[i] * 16
|
|
|
|
)
|
|
|
|
));
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
// sides
|
|
|
|
for (int i = 0; i < 4; i++)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2018-09-06 13:27:24 +00:00
|
|
|
EnumFacing side = EnumFacing.byHorizontalIndex((5 - i) % 4); // [W, S, E, N]
|
2018-07-18 03:37:20 +00:00
|
|
|
boolean useOverlay = overlay.isPresent() && sideOverlays[side.getHorizontalIndex()];
|
|
|
|
int si = i; // local var for lambda capture
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
VertexParameter sideX = j -> x[(si + x[j]) % 4];
|
|
|
|
VertexParameter sideY = j -> z[j] == 0 ? (gas ? 1 : 0) : y[(si + x[j]) % 4];
|
|
|
|
VertexParameter sideZ = j -> z[(si + x[j]) % 4];
|
|
|
|
VertexParameter sideU = j -> x[j] * 8;
|
|
|
|
VertexParameter sideV = j -> (gas ? sideY.get(j) : 1 - sideY.get(j)) * 8;
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
|
2015-06-18 11:14:46 +00:00
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
if (!useOverlay) builder.add(buildQuad(side, flowing, gas, true, sideX, sideY, sideZ, sideU, sideV));
|
|
|
|
builder.add(buildQuad(side, useOverlay ? overlay.get() : flowing, !gas, false, sideX, sideY, sideZ, sideU, sideV));
|
|
|
|
|
|
|
|
faceQuads.put(side, builder.build());
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
// inventory
|
|
|
|
faceQuads.put(EnumFacing.SOUTH, ImmutableList.of(
|
|
|
|
buildQuad(EnumFacing.UP, still, false, false,
|
|
|
|
i -> z[i],
|
|
|
|
i -> x[i],
|
|
|
|
i -> 0,
|
|
|
|
i -> z[i] * 16,
|
|
|
|
i -> x[i] * 16
|
|
|
|
)
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
return ImmutableMap.copyOf(faceQuads);
|
|
|
|
}
|
|
|
|
|
|
|
|
// maps vertex index to parameter value
|
|
|
|
private interface VertexParameter
|
|
|
|
{
|
|
|
|
float get(int index);
|
|
|
|
}
|
|
|
|
|
|
|
|
private BakedQuad buildQuad(EnumFacing side, TextureAtlasSprite texture, boolean flip, boolean offset, VertexParameter x, VertexParameter y, VertexParameter z, VertexParameter u, VertexParameter v)
|
|
|
|
{
|
|
|
|
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(format);
|
|
|
|
builder.setQuadOrientation(side);
|
|
|
|
builder.setTexture(texture);
|
|
|
|
builder.setQuadTint(0);
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
int vertex = flip ? 3 - i : i;
|
|
|
|
putVertex(
|
|
|
|
builder, side, offset,
|
|
|
|
x.get(vertex), y.get(vertex), z.get(vertex),
|
|
|
|
texture.getInterpolatedU(u.get(vertex)),
|
|
|
|
texture.getInterpolatedV(v.get(vertex))
|
|
|
|
);
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
2018-07-18 03:37:20 +00:00
|
|
|
|
|
|
|
return builder.build();
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
|
2018-07-18 03:37:20 +00:00
|
|
|
private void putVertex(UnpackedBakedQuad.Builder builder, EnumFacing side, boolean offset, float x, float y, float z, float u, float v)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2015-06-28 22:19:10 +00:00
|
|
|
for(int e = 0; e < format.getElementCount(); e++)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2015-06-28 22:19:10 +00:00
|
|
|
switch(format.getElement(e).getUsage())
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
|
|
|
case POSITION:
|
2018-07-18 03:37:20 +00:00
|
|
|
float dx = offset ? side.getDirectionVec().getX() * eps : 0f;
|
|
|
|
float dy = offset ? side.getDirectionVec().getY() * eps : 0f;
|
|
|
|
float dz = offset ? side.getDirectionVec().getZ() * eps : 0f;
|
|
|
|
float[] data = { x - dx, y - dy, z - dz, 1f };
|
2018-04-01 07:24:37 +00:00
|
|
|
if(transformation.isPresent() && !transformation.get().isIdentity())
|
2015-12-03 19:38:08 +00:00
|
|
|
{
|
|
|
|
Vector4f vec = new Vector4f(data);
|
2018-09-22 10:40:22 +00:00
|
|
|
transformation.get().getMatrixVec().transform(vec);
|
2015-12-03 19:38:08 +00:00
|
|
|
vec.get(data);
|
|
|
|
}
|
|
|
|
builder.put(e, data);
|
2015-06-18 11:14:46 +00:00
|
|
|
break;
|
|
|
|
case COLOR:
|
2015-06-28 22:19:10 +00:00
|
|
|
builder.put(e,
|
2016-03-17 04:28:19 +00:00
|
|
|
((color >> 16) & 0xFF) / 255f,
|
|
|
|
((color >> 8) & 0xFF) / 255f,
|
|
|
|
(color & 0xFF) / 255f,
|
2015-06-18 11:14:46 +00:00
|
|
|
((color >> 24) & 0xFF) / 255f);
|
|
|
|
break;
|
2015-06-28 22:19:10 +00:00
|
|
|
case UV: if(format.getElement(e).getIndex() == 0)
|
|
|
|
{
|
|
|
|
builder.put(e, u, v, 0f, 1f);
|
2015-06-18 11:14:46 +00:00
|
|
|
break;
|
2015-06-28 22:19:10 +00:00
|
|
|
}
|
2015-06-18 11:14:46 +00:00
|
|
|
case NORMAL:
|
2018-09-08 20:34:59 +00:00
|
|
|
builder.put(e, (float)side.getXOffset(), (float)side.getYOffset(), (float)side.getZOffset(), 0f);
|
2015-06-18 11:14:46 +00:00
|
|
|
break;
|
|
|
|
default:
|
2015-06-28 22:19:10 +00:00
|
|
|
builder.put(e);
|
2015-06-18 11:14:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2015-06-18 11:14:46 +00:00
|
|
|
public boolean isAmbientOcclusion()
|
|
|
|
{
|
2016-04-06 13:13:51 +00:00
|
|
|
return true;
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2015-06-18 11:14:46 +00:00
|
|
|
public boolean isGui3d()
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2016-03-13 01:40:03 +00:00
|
|
|
public boolean isBuiltInRenderer()
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2015-12-30 04:15:03 +00:00
|
|
|
public TextureAtlasSprite getParticleTexture()
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
|
|
|
return still;
|
|
|
|
}
|
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2018-09-22 10:40:22 +00:00
|
|
|
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, Random rand)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
2018-07-18 03:37:20 +00:00
|
|
|
return side == null ? ImmutableList.of() : faceQuads.get(side);
|
2016-03-01 20:19:38 +00:00
|
|
|
}
|
|
|
|
|
2017-06-18 01:24:17 +00:00
|
|
|
@Override
|
2016-03-13 01:40:03 +00:00
|
|
|
public ItemOverrideList getOverrides()
|
2016-03-01 20:19:38 +00:00
|
|
|
{
|
2018-09-22 10:40:22 +00:00
|
|
|
return ItemOverrideList.EMPTY;
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
2016-01-04 10:54:45 +00:00
|
|
|
|
|
|
|
@Override
|
2016-03-01 20:19:38 +00:00
|
|
|
public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType type)
|
2016-01-04 10:54:45 +00:00
|
|
|
{
|
2017-06-25 01:08:20 +00:00
|
|
|
return PerspectiveMapWrapper.handlePerspective(this, transforms, type);
|
2016-01-04 10:54:45 +00:00
|
|
|
}
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2016-03-02 17:00:32 +00:00
|
|
|
public ModelFluid process(ImmutableMap<String, String> customData)
|
2015-06-18 11:14:46 +00:00
|
|
|
{
|
|
|
|
if(!customData.containsKey("fluid")) return this;
|
|
|
|
|
|
|
|
String fluidStr = customData.get("fluid");
|
|
|
|
JsonElement e = new JsonParser().parse(fluidStr);
|
2018-09-18 04:04:02 +00:00
|
|
|
String fluid = e.getAsString();/* TODO fluids
|
2015-06-18 11:14:46 +00:00
|
|
|
if(!FluidRegistry.isFluidRegistered(fluid))
|
|
|
|
{
|
2018-09-06 13:27:24 +00:00
|
|
|
LOGGER.fatal("fluid '{}' not found", fluid);
|
2016-03-21 07:23:27 +00:00
|
|
|
return WATER;
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
2018-09-18 04:04:02 +00:00
|
|
|
return new ModelFluid(FluidRegistry.getFluid(fluid));*/
|
|
|
|
return this;
|
2015-06-18 11:14:46 +00:00
|
|
|
}
|
|
|
|
}
|