package blusunrize.immersiveengineering.client.render;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.client.renderer.vertex.VertexFormatElement.EnumType;
import net.minecraft.client.renderer.vertex.VertexFormatElement.EnumUsage;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.pipeline.LightUtil;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
/**
* @author amadornes
* Blatantly stolen from Ama, since his stuff is good =3
*/
public class BakedModelTransformer
{
public static IBakedModel transform(IBakedModel model, IVertexTransformer transformer, IBlockState state, long rand)
{
return transform(model, transformer, state, rand, f -> f);
}
public static IBakedModel transform(IBakedModel model, IVertexTransformer transformer, IBlockState state, long rand, Function<VertexFormat, VertexFormat> formatRemapper)
{
List<BakedQuad>[] quads = new List[7];
for(int i = 0; i < quads.length; i++)
{
quads[i] = new ArrayList<BakedQuad>();
for(BakedQuad quad : model.getQuads(state, (i == 6 ? null : EnumFacing.getFront(i)), rand))
quads[i].add(transform(quad, transformer, formatRemapper));
}
return new TransformedModel(model, quads);
}
private static BakedQuad transform(BakedQuad quad, IVertexTransformer transformer, Function<VertexFormat, VertexFormat> formatRemapper)
{
VertexFormat format = quad.getFormat();
VertexFormat newFormat = formatRemapper.apply(format);
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(newFormat);
if(quad.hasTintIndex()) builder.setQuadTint(quad.getTintIndex());
builder.setQuadOrientation(quad.getFace());
LightUtil.putBakedQuad(builder, quad);
UnpackedBakedQuad unpackedQuad = builder.build();
try
{
float[][][] unpackedData = getUnpackedData(unpackedQuad);
int count = newFormat.getElementCount();
for(int v = 0; v < 4; v++)
{
for(int e = 0; e < count; e++)
{
VertexFormatElement element = newFormat.getElement(e);
unpackedData[v][e] = transformer.transform(quad, element.getType(), element.getUsage(), unpackedData[v][e]);
}
}
} catch(Exception e)
{
e.printStackTrace();
}
return unpackedQuad;
}
static Field f_unpackedData;
static float[][][] getUnpackedData(UnpackedBakedQuad unpackedQuad) throws Exception
{
if(f_unpackedData == null)
{
f_unpackedData = ReflectionHelper.findField(UnpackedBakedQuad.class, "unpackedData");
f_unpackedData.setAccessible(true);
}
return (float[][][]) f_unpackedData.get(unpackedQuad);
}
private static final class TransformedModel implements IBakedModel
{
private final IBakedModel parent;
private final List<BakedQuad>[] quads;
public TransformedModel(IBakedModel parent, List<BakedQuad>[] quads)
{
this.parent = parent;
this.quads = quads;
}
@Override
public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand)
{
return quads[side == null ? 6 : side.ordinal()];
}
@Override
public boolean isAmbientOcclusion()
{
return parent.isAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
return parent.isGui3d();
}
@Override
public boolean isBuiltInRenderer()
{
return parent.isBuiltInRenderer();
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return parent.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return parent.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides()
{
return parent.getOverrides();
}
}
public interface IVertexTransformer
{
float[] transform(BakedQuad quad, EnumType type, EnumUsage usage, float... data);
}
}