package blusunrize.immersiveengineering.client.models; import blusunrize.immersiveengineering.ImmersiveEngineering; import blusunrize.immersiveengineering.api.IEProperties; import blusunrize.immersiveengineering.api.tool.ConveyorHandler; import blusunrize.immersiveengineering.api.tool.ConveyorHandler.ConveyorDirection; import blusunrize.immersiveengineering.api.tool.ConveyorHandler.IConveyorBelt; import blusunrize.immersiveengineering.client.ClientUtils; import blusunrize.immersiveengineering.common.blocks.metal.BlockConveyor; import blusunrize.immersiveengineering.common.util.ItemNBTHelper; import blusunrize.immersiveengineering.common.util.Utils; import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4; import com.google.common.collect.Lists; 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.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.model.IPerspectiveAwareModel; import net.minecraftforge.common.model.TRSRTransformation; import net.minecraftforge.common.property.IExtendedBlockState; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.util.vector.Vector3f; import javax.annotation.Nullable; import javax.vecmath.Matrix4f; import java.util.*; @SuppressWarnings("deprecation") public class ModelConveyor implements IBakedModel, IPerspectiveAwareModel { static List<BakedQuad> emptyQuads = Lists.newArrayList(); public static HashMap<String, List<BakedQuad>> modelCache = new HashMap<>(); public static ResourceLocation[] rl_casing = {new ResourceLocation(ImmersiveEngineering.MODID, "blocks/conveyor_casing_top"), new ResourceLocation(ImmersiveEngineering.MODID, "blocks/conveyor_casing_side"), new ResourceLocation(ImmersiveEngineering.MODID, "blocks/conveyor_casing_walls")}; Set<BakedQuad> quads; IConveyorBelt conveyor; public ModelConveyor(IConveyorBelt conveyor) { this.conveyor = conveyor; } public ModelConveyor() { this(null); } @Override public List<BakedQuad> getQuads(@Nullable IBlockState blockState, @Nullable EnumFacing side, long rand) { TileEntity tile = null; String key = "default"; EnumFacing facing = EnumFacing.NORTH; if(blockState == null) key = conveyor != null ? ConveyorHandler.reverseClassRegistry.get(conveyor.getClass()).toString() : "immersiveengineering:conveyor"; else { facing = blockState.getValue(IEProperties.FACING_ALL); if(blockState instanceof IExtendedBlockState) { IExtendedBlockState exState = (IExtendedBlockState) blockState; if(exState.getUnlistedNames().contains(BlockConveyor.ICONEYOR_PASSTHROUGH)) conveyor = ((IExtendedBlockState) blockState).getValue(BlockConveyor.ICONEYOR_PASSTHROUGH); if(exState.getUnlistedNames().contains(IEProperties.TILEENTITY_PASSTHROUGH)) tile = ((IExtendedBlockState) blockState).getValue(IEProperties.TILEENTITY_PASSTHROUGH); if(conveyor != null && tile != null) key = conveyor.getModelCacheKey(tile, facing); } } List<BakedQuad> cachedQuads = modelCache.get(key); if(cachedQuads != null) return Collections.synchronizedList(Lists.newArrayList(cachedQuads)); else { cachedQuads = Collections.synchronizedList(Lists.newArrayList()); Matrix4f facingMatrix = TRSRTransformation.getMatrix(facing); if(conveyor != null) facingMatrix = conveyor.modifyBaseRotationMatrix(facingMatrix, tile, facing); Matrix4 matrix = new Matrix4(facingMatrix); ConveyorDirection conDir = conveyor != null ? conveyor.getConveyorDirection() : ConveyorDirection.HORIZONTAL; boolean[] walls = conveyor != null && tile != null ? new boolean[]{conveyor.renderWall(tile, facing, 0), conveyor.renderWall(tile, facing, 1)} : new boolean[]{true, true}; TextureAtlasSprite tex_conveyor = ClientUtils.mc().getTextureMapBlocks().getMissingSprite(); TextureAtlasSprite tex_conveyor_colour = null; int colourStripes = -1; if(conveyor != null) { tex_conveyor = ClientUtils.getSprite(tile != null ? (conveyor.isActive(tile) ? conveyor.getActiveTexture() : conveyor.getInactiveTexture()) : conveyor.getActiveTexture()); if((colourStripes = conveyor.getDyeColour()) >= 0) tex_conveyor_colour = ClientUtils.getSprite(conveyor.getColouredStripesTexture()); } cachedQuads.addAll(getBaseConveyor(facing, 1, matrix, conDir, tex_conveyor, walls, new boolean[]{true, true}, tex_conveyor_colour, colourStripes)); if(conveyor != null) cachedQuads = conveyor.modifyQuads(cachedQuads, tile, facing); modelCache.put(key, cachedQuads); return Collections.synchronizedList(Lists.newArrayList(cachedQuads)); } } public static Set<BakedQuad> getBaseConveyor(EnumFacing facing, float length, Matrix4 matrix, ConveyorDirection conDir, TextureAtlasSprite tex_conveyor, boolean[] walls, boolean[] corners, TextureAtlasSprite tex_conveyor_colour, int stripeColour) { Set<BakedQuad> quads = new LinkedHashSet<BakedQuad>(); Vector3f[] vertices = {new Vector3f(.0625f, 0, 1 - length), new Vector3f(.0625f, 0, 1), new Vector3f(.9375f, 0, 1), new Vector3f(.9375f, 0, 1 - length)}; TextureAtlasSprite tex_casing0 = ClientUtils.getSprite(rl_casing[0]); TextureAtlasSprite tex_casing1 = ClientUtils.getSprite(rl_casing[1]); TextureAtlasSprite tex_casing2 = ClientUtils.getSprite(rl_casing[2]); float[] colour = {1, 1, 1, 1}; float[] colourStripes = {(stripeColour >> 16 & 255) / 255f, (stripeColour >> 8 & 255) / 255f, (stripeColour & 255) / 255f, 1}; /** * Bottom & Top */ //Shift if up/down for(int i = 0; i < 4; i++) if((i == 0 || i == 3) ? conDir == ConveyorDirection.UP : conDir == ConveyorDirection.DOWN) vertices[i].translate(0, length, 0); //Draw bottom quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.DOWN,facing), tex_conveyor, new double[]{1, 0, 15, length * 16}, colour, true)); //Expand verts to side for(Vector3f v : vertices) v.setX(v.getX() < .5f ? 0 : 1); //Draw bottom casing quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.DOWN,facing), tex_casing2, new double[]{0, 0, 16, length * 16}, colour, true)); //Shift verts to top for(Vector3f v : vertices) v.translate(0, .125f, 0); //Draw top quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.UP,facing), tex_conveyor, new double[]{0, length * 16, 16, 0}, colour, false)); if(corners[0]) { vertices = new Vector3f[]{new Vector3f(0, .1875f, .9375f), new Vector3f(0, .1875f, 1), new Vector3f(1, .1875f, 1), new Vector3f(1, .1875f, .9375f)}; //Shift if up/down for(int i = 0; i < 4; i++) vertices[i].translate(0, i == 0 || i == 3 ? (conDir == ConveyorDirection.UP ? .0625f : conDir == ConveyorDirection.DOWN ? length - .0625f : 0) : (conDir == ConveyorDirection.DOWN ? length : 0), 0); //Draw top casing back quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.UP,facing), tex_casing0, new double[]{0, 1, 16, 0}, colour, false)); } if(corners[1]) { vertices = new Vector3f[]{new Vector3f(0, .1875f, 1 - length), new Vector3f(0, .1875f, 1.0625f - length), new Vector3f(1, .1875f, 1.0625f - length), new Vector3f(1, .1875f, 1 - length)}; //Shift if up/down for(int i = 0; i < 4; i++) vertices[i].translate(0, i == 1 || i == 2 ? (conDir == ConveyorDirection.UP ? length - .0625f : conDir == ConveyorDirection.DOWN ? .0625f : 0) : (conDir == ConveyorDirection.UP ? length : 0), 0); //Draw top casing front quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.UP,facing), tex_casing0, new double[]{0, 1, 16, 0}, colour, false)); } /** * Sides */ vertices = new Vector3f[]{new Vector3f(0, 0, 1 - length), new Vector3f(0, 0, 1), new Vector3f(0, .125f, 1), new Vector3f(0, .125f, 1 - length)}; for(int i = 0; i < 4; i++) if((i == 0 || i == 3) ? conDir == ConveyorDirection.UP : conDir == ConveyorDirection.DOWN) vertices[i].translate(0, length, 0); //Draw left side quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.WEST,facing), tex_casing1, new double[]{0, 0, 2, length * 16}, colour, false)); //Shift upwards for(int i = 0; i < 4; i++) vertices[i].setY(vertices[i].getY() + ((i == 0 || i == 1) ? .125f : .0625f)); //Shift back down and to the other side for(int i = 0; i < 4; i++) vertices[i].set(1, vertices[i].getY() - ((i == 0 || i == 1) ? .125f : .0625f)); //Draw right side quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.EAST,facing), tex_casing1, new double[]{0, 0, 2, length * 16}, colour, true)); //Shift upwards for(int i = 0; i < 4; i++) vertices[i].setY(vertices[i].getY() + ((i == 0 || i == 1) ? .125f : .0625f)); /** * Corners */ if(corners[0]) { vertices = new Vector3f[]{new Vector3f(0, .125f, .9375f), new Vector3f(0, .125f, 1), new Vector3f(0, .1875f, 1), new Vector3f(0, .1875f, .9375f)}; if(conDir != ConveyorDirection.HORIZONTAL) for(int i = 0; i < 4; i++) vertices[i].translate(0, i == 0 || i == 3 ? (conDir == ConveyorDirection.UP ? .0625f : conDir == ConveyorDirection.DOWN ? length - .0625f : 0) : (conDir == ConveyorDirection.DOWN ? length : 0), 0); //Back left quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.WEST,facing), tex_casing0, new double[]{0, 0, 1, 1}, colour, false)); for(Vector3f v : vertices) v.translate(.0625f, 0, 0); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.EAST,facing), tex_casing0, new double[]{0, 0, 1, 1}, colour, true)); //Shift right for(Vector3f v : vertices) v.setX(1); //Back right quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.EAST,facing), tex_casing0, new double[]{0, 0, 1, 1}, colour, true)); for(Vector3f v : vertices) v.translate(-.0625f, 0, 0); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.WEST,facing), tex_casing0, new double[]{0, 0, 1, 1}, colour, false)); } if(corners[1]) { vertices = new Vector3f[]{new Vector3f(0, .125f, 1 - length), new Vector3f(0, .125f, 1.0625f - length), new Vector3f(0, .1875f, 1.0625f - length), new Vector3f(0, .1875f, 1 - length)}; if(conDir != ConveyorDirection.HORIZONTAL) for(int i = 0; i < 4; i++) vertices[i].translate(0, i == 1 || i == 2 ? (conDir == ConveyorDirection.UP ? length - .0625f : conDir == ConveyorDirection.DOWN ? .0625f : 0) : (conDir == ConveyorDirection.UP ? length : 0), 0); //Front left quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.WEST,facing), tex_casing0, new double[]{0, 15, 1, 16}, colour, false)); for(Vector3f v : vertices) v.translate(.0625f, 0, 0); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.EAST,facing), tex_casing0, new double[]{0, 15, 1, 16}, colour, true)); //Shift right for(Vector3f v : vertices) v.setX(1); //Front right quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.EAST,facing), tex_casing0, new double[]{0, 15, 1, 16}, colour, true)); for(Vector3f v : vertices) v.translate(-.0625f, 0, 0); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.WEST,facing), tex_casing0, new double[]{0, 15, 1, 16}, colour, false)); } /** * Front & Back */ vertices = new Vector3f[]{new Vector3f(.0625f, 0, 1 - length), new Vector3f(.0625f, .125f, 1 - length), new Vector3f(.9375f, .125f, 1 - length), new Vector3f(.9375f, 0, 1 - length)}; //Shift if up/down if(conDir == ConveyorDirection.UP) for(Vector3f v : vertices) v.translate(0, length, 0); //Draw front double frontUMax = (1 - length) * 16; quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), facing, tex_conveyor, new double[]{1, frontUMax + 2, 15, frontUMax}, colour, false)); //Expand to side and up for(int i = 0; i < 4; i++) vertices[i].set(vertices[i].getX() < .5f ? 0 : 1, vertices[i].getY() + (i == 1 || i == 2 ? .0625f : 0)); //Draw front casing quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), facing, tex_casing2, new double[]{0, 3, 16, 0}, colour, false)); for(Vector3f v : vertices) v.translate(0, (conDir == ConveyorDirection.UP ? -.0625f : conDir == ConveyorDirection.DOWN ? .0625f : 0), .0625f); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), facing, tex_casing2, new double[]{0, 3, 16, 0}, colour, true)); //Undo expand, shift if up/down, shift to back for(int i = 0; i < 4; i++) { Vector3f v = vertices[i]; v.setX(v.getX() < .5f ? .0625f : .9375f); v.setY(v.getY() - (i == 1 || i == 2 ? .0625f : 0)); if(conDir == ConveyorDirection.UP) v.translate(0, -(length - .0625f), 0); if(conDir == ConveyorDirection.DOWN) v.translate(0, (length - .0625f), 0); v.translate(0, 0, length - .0625f); } //Draw back quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), facing.getOpposite(), tex_conveyor, new double[]{1, 0, 15, 2}, colour, true)); //Expand to side and up for(int i = 0; i < 4; i++) vertices[i].set(vertices[i].getX() < .5f ? 0 : 1, vertices[i].getY() + (i == 1 || i == 2 ? .0625f : 0)); //Draw back casing quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), facing.getOpposite(), tex_casing2, new double[]{0, 0, 16, 3}, colour, true)); for(Vector3f v : vertices) v.translate(0, conDir == ConveyorDirection.UP ? .0625f : conDir == ConveyorDirection.DOWN ? -.0625f : 0, -.0625f); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), facing.getOpposite(), tex_casing2, new double[]{0, 0, 16, 3}, colour, false)); /** * Walls */ float wallLength = length - .125f; vertices = new Vector3f[]{new Vector3f(0, .1875f, .9375f - wallLength), new Vector3f(0, .1875f, .9375f), new Vector3f(.0625f, .1875f, .9375f), new Vector3f(.0625f, .1875f, .9375f - wallLength)}; Vector3f[] vertices2 = new Vector3f[]{new Vector3f(0, .125f, .9375f - wallLength), new Vector3f(0, .125f, .9375f), new Vector3f(0, .1875f, .9375f), new Vector3f(0, .1875f, .9375f - wallLength)}; Vector3f[] vertices3 = new Vector3f[]{new Vector3f(.0625f, .125f, .9375f - wallLength), new Vector3f(.0625f, .125f, .9375f), new Vector3f(.0625f, .1875f, .9375f), new Vector3f(.0625f, .1875f, .9375f - wallLength)}; Vector3f[] verticesColour = new Vector3f[]{new Vector3f(0, .1876f, corners[1] ? (1 - length) : (.9375f - wallLength)), new Vector3f(0, .1876f, corners[0] ? 1 : .9375f), new Vector3f(.0625f, .1876f, corners[0] ? 1 : .9375f), new Vector3f(.0625f, .1876f, corners[1] ? (1 - length) : (.9375f - wallLength))}; for(int i = 0; i < 4; i++) if(conDir != ConveyorDirection.HORIZONTAL) { float f = (i == 0 || i == 3) ? (conDir == ConveyorDirection.UP ? length - .0625f : .0625f) : (conDir == ConveyorDirection.UP ? .0625f : length - .0625f); vertices[i].translate(0, f, 0); vertices2[i].translate(0, f, 0); vertices3[i].translate(0, f, 0); verticesColour[i].translate(0, f, 0); } //Draw left walls if(walls[0]) { quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.UP,facing), tex_casing2, new double[]{0, wallLength * 16, 1, 1}, colour, false)); if(tex_conveyor_colour != null && stripeColour >= 0) quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, verticesColour), Utils.rotateFacingTowardsDir(EnumFacing.UP,facing), tex_conveyor_colour, new double[]{0, wallLength * 16, 1, 1}, colourStripes, false)); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices2), Utils.rotateFacingTowardsDir(EnumFacing.WEST,facing), tex_casing1, new double[]{2, wallLength * 16, 3, 1}, colour, false)); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices3), Utils.rotateFacingTowardsDir(EnumFacing.EAST,facing), tex_casing1, new double[]{2, wallLength * 16, 3, 1}, colour, true)); } for(int i = 0; i < 4; i++) { vertices[i].translate(.9375f, 0, 0); vertices2[i].translate(.9375f, 0, 0); vertices3[i].translate(.9375f, 0, 0); verticesColour[i].translate(.9375f, 0, 0); } //Draw right walls if(walls[1]) { quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices), Utils.rotateFacingTowardsDir(EnumFacing.UP,facing), tex_casing2, new double[]{15, wallLength * 16, 16, 1}, colour, false)); if(tex_conveyor_colour != null && stripeColour >= 0) quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, verticesColour), Utils.rotateFacingTowardsDir(EnumFacing.UP,facing), tex_conveyor_colour, new double[]{15, wallLength * 16, 16, 1}, colourStripes, false)); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices2), Utils.rotateFacingTowardsDir(EnumFacing.WEST,facing), tex_casing1, new double[]{2, wallLength * 16, 3, 1}, colour, false)); quads.add(ClientUtils.createBakedQuad(DefaultVertexFormats.ITEM, ClientUtils.applyMatrixToVertices(matrix, vertices3), Utils.rotateFacingTowardsDir(EnumFacing.EAST,facing), tex_casing1, new double[]{2, wallLength * 16, 3, 1}, colour, true)); } return quads; } @Override public boolean isAmbientOcclusion() { return true; } @Override public boolean isGui3d() { return true; } @Override public boolean isBuiltInRenderer() { return false; } TextureAtlasSprite tex_particle; @Override public TextureAtlasSprite getParticleTexture() { if(tex_particle == null) tex_particle = ClientUtils.getSprite(conveyor != null ? conveyor.getInactiveTexture() : new ResourceLocation(ImmersiveEngineering.MODID, "blocks/conveyor_off")); return tex_particle; } @Override public ItemCameraTransforms getItemCameraTransforms() { return ItemCameraTransforms.DEFAULT; } @Override public ItemOverrideList getOverrides() { return overrideList; } static HashMap<String, IBakedModel> itemModelCache = new HashMap<String, IBakedModel>(); ItemOverrideList overrideList = new ItemOverrideList(new ArrayList()) { @Override public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity) { String key = ItemNBTHelper.getString(stack, "conveyorType"); IBakedModel model = itemModelCache.get(key); if(model == null) { model = new ModelConveyor(ConveyorHandler.getConveyor(new ResourceLocation(key), null)); itemModelCache.put(key, model); } return model; } }; static HashMap<TransformType, Matrix4> transformationMap = new HashMap<TransformType, Matrix4>(); static { transformationMap.put(TransformType.FIRST_PERSON_LEFT_HAND, new Matrix4().scale(.5, .5, .5).translate(0, .25, 0).rotate(Math.toRadians(-45), 0, 1, 0)); transformationMap.put(TransformType.FIRST_PERSON_RIGHT_HAND, new Matrix4().scale(.5, .5, .5).translate(0, .25, 0).rotate(Math.toRadians(-45), 0, 1, 0)); transformationMap.put(TransformType.THIRD_PERSON_LEFT_HAND, new Matrix4().translate(0, .0625, -.125).scale(.3125, .3125, .3125).rotate(Math.toRadians(30), 1, 0, 0).rotate(Math.toRadians(130), 0, 1, 0)); transformationMap.put(TransformType.THIRD_PERSON_RIGHT_HAND, new Matrix4().translate(0, .0625, -.125).scale(.3125, .3125, .3125).rotate(Math.toRadians(30), 1, 0, 0).rotate(Math.toRadians(130), 0, 1, 0)); transformationMap.put(TransformType.GUI, new Matrix4().scale(.625, .625, .625).rotate(Math.toRadians(-45), 0, 1, 0).rotate(Math.toRadians(-20), 0, 0, 1).rotate(Math.toRadians(20), 1, 0, 0)); transformationMap.put(TransformType.FIXED, new Matrix4().scale(.625, .625, .625).rotate(Math.PI, 0, 1, 0).translate(0, 0, .3125)); transformationMap.put(TransformType.GROUND, new Matrix4().scale(.25, .25, .25)); } @Override public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType) { Matrix4 matrix = transformationMap.containsKey(cameraTransformType) ? transformationMap.get(cameraTransformType) : new Matrix4(); return Pair.of(this, matrix.toMatrix4f()); } }