package blusunrize.immersiveengineering.client.models; import blusunrize.immersiveengineering.api.tool.ExcavatorHandler; import blusunrize.immersiveengineering.api.tool.ExcavatorHandler.MineralMix; import blusunrize.immersiveengineering.client.ClientUtils; import blusunrize.immersiveengineering.common.util.ItemNBTHelper; import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4; import com.google.common.collect.Lists; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; 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.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.model.IPerspectiveAwareModel; import net.minecraftforge.client.model.pipeline.LightUtil; import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; import net.minecraftforge.common.model.TRSRTransformation; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.util.vector.Vector2f; import org.lwjgl.util.vector.Vector3f; import javax.annotation.Nullable; import javax.vecmath.Matrix4f; import java.util.*; @SuppressWarnings("deprecation") public class ModelCoresample implements IBakedModel, IPerspectiveAwareModel { Set<BakedQuad> bakedQuads; static List<BakedQuad> emptyQuads = Lists.newArrayList(); MineralMix mineral; public ModelCoresample(MineralMix mineral) { this.mineral = mineral; } public ModelCoresample() { this(null); } static HashMap<String, ModelCoresample> modelCache = new HashMap(); // @Override // public List<BakedQuad> getFaceQuads(EnumFacing p_177551_1_) // { // return emptyQuads; // } @Override public List<BakedQuad> getQuads(@Nullable IBlockState blockState, @Nullable EnumFacing side, long rand) { if(bakedQuads == null) { try{ bakedQuads = Collections.synchronizedSet(new LinkedHashSet<BakedQuad>()); float width = .25f; float depth = .25f; float wOff = (1-width)/2; float dOff = (1-depth)/2; int pixelLength = 0; HashMap<TextureAtlasSprite, Integer> textureOre = new HashMap(); if(mineral!=null && mineral.oreOutput!=null) { for(int i=0; i<mineral.oreOutput.length; i++) if(mineral.oreOutput[i]!=null) { int weight = Math.max(2, Math.round(16*mineral.recalculatedChances[i])); Block b = Block.getBlockFromItem(mineral.oreOutput[i].getItem()); IBlockState state = b!=null?b.getStateFromMeta(mineral.oreOutput[i].getMetadata()): Blocks.STONE.getDefaultState(); IBakedModel model = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(state); if(model!=null && model.getParticleTexture()!=null) textureOre.put(model.getParticleTexture(), weight); pixelLength += weight; } } else pixelLength=16; TextureAtlasSprite textureStone = ClientUtils.getSprite(new ResourceLocation("blocks/stone")); Vector2f[] stoneUVs = { new Vector2f(textureStone.getInterpolatedU(16*wOff),textureStone.getInterpolatedV(16*dOff)), new Vector2f(textureStone.getInterpolatedU(16*wOff),textureStone.getInterpolatedV(16*(dOff+depth))), new Vector2f(textureStone.getInterpolatedU(16*(wOff+width)),textureStone.getInterpolatedV(16*(dOff+depth))), new Vector2f(textureStone.getInterpolatedU(16*(wOff+width)),textureStone.getInterpolatedV(16*dOff))}; putVertexData(new Vector3f(0, -1, 0), new Vector3f[]{new Vector3f(wOff, 0, dOff), new Vector3f(wOff + width, 0, dOff), new Vector3f(wOff + width, 0, dOff + depth), new Vector3f(wOff, 0, dOff + depth)}, stoneUVs, textureStone); putVertexData(new Vector3f(0, 1, 0), new Vector3f[]{new Vector3f(wOff, 1, dOff), new Vector3f(wOff, 1, dOff + depth), new Vector3f(wOff + width, 1, dOff + depth), new Vector3f(wOff + width, 1, dOff)}, stoneUVs, textureStone); if(textureOre.isEmpty()) { Vector2f[][] uvs = new Vector2f[4][]; for(int j=0; j<4; j++) uvs[j] = new Vector2f[]{ new Vector2f(textureStone.getInterpolatedU(j*4),textureStone.getInterpolatedV(0)), new Vector2f(textureStone.getInterpolatedU(j*4),textureStone.getInterpolatedV(16)), new Vector2f(textureStone.getInterpolatedU((j+1)*4),textureStone.getInterpolatedV(16)), new Vector2f(textureStone.getInterpolatedU((j+1)*4),textureStone.getInterpolatedV(0))}; putVertexData(new Vector3f(0, 0, -1), new Vector3f[]{new Vector3f(wOff, 0, dOff), new Vector3f(wOff, 1, dOff), new Vector3f(wOff + width, 1, dOff), new Vector3f(wOff + width, 0, dOff)}, uvs[0], textureStone); putVertexData(new Vector3f(0, 0, 1), new Vector3f[]{new Vector3f(wOff + width, 0, dOff + depth), new Vector3f(wOff + width, 1, dOff + depth), new Vector3f(wOff, 1, dOff + depth), new Vector3f(wOff, 0, dOff + depth)}, uvs[2], textureStone); putVertexData(new Vector3f(-1, 0, 0), new Vector3f[]{new Vector3f(wOff, 0, dOff + depth), new Vector3f(wOff, 1, dOff + depth), new Vector3f(wOff, 1, dOff), new Vector3f(wOff, 0, dOff)}, uvs[3], textureStone); putVertexData(new Vector3f(1, 0, 0), new Vector3f[]{new Vector3f(wOff + width, 0, dOff), new Vector3f(wOff + width, 1, dOff), new Vector3f(wOff + width, 1, dOff + depth), new Vector3f(wOff + width, 0, dOff + depth)}, uvs[1], textureStone); } else { float h=0; for(TextureAtlasSprite sprite : textureOre.keySet()) { int weight = textureOre.get(sprite); int v = weight>8?16-weight:8; Vector2f[][] uvs = new Vector2f[4][]; for(int j=0; j<4; j++) uvs[j] = new Vector2f[]{ new Vector2f(sprite.getInterpolatedU(j*4),sprite.getInterpolatedV(v)), new Vector2f(sprite.getInterpolatedU(j*4),sprite.getInterpolatedV(v+weight)), new Vector2f(sprite.getInterpolatedU((j+1)*4),sprite.getInterpolatedV(v+weight)), new Vector2f(sprite.getInterpolatedU((j+1)*4),sprite.getInterpolatedV(v))}; float h1 = weight/(float)pixelLength; putVertexData(new Vector3f(0, 0, -1), new Vector3f[]{new Vector3f(wOff, h, dOff), new Vector3f(wOff, h + h1, dOff), new Vector3f(wOff + width, h + h1, dOff), new Vector3f(wOff + width, h, dOff)}, uvs[0], sprite); putVertexData(new Vector3f(0, 0, 1), new Vector3f[]{new Vector3f(wOff + width, h, dOff + depth), new Vector3f(wOff + width, h + h1, dOff + depth), new Vector3f(wOff, h + h1, dOff + depth), new Vector3f(wOff, h, dOff + depth)}, uvs[2], sprite); putVertexData(new Vector3f(-1, 0, 0), new Vector3f[]{new Vector3f(wOff, h, dOff + depth), new Vector3f(wOff, h + h1, dOff + depth), new Vector3f(wOff, h + h1, dOff), new Vector3f(wOff, h, dOff)}, uvs[3], sprite); putVertexData(new Vector3f(1, 0, 0), new Vector3f[]{new Vector3f(wOff + width, h, dOff), new Vector3f(wOff + width, h + h1, dOff), new Vector3f(wOff + width, h + h1, dOff + depth), new Vector3f(wOff + width, h, dOff + depth)}, uvs[1], sprite); h += h1; } } }catch(Exception e) { e.printStackTrace(); } } if(bakedQuads!=null && !bakedQuads.isEmpty()) { List<BakedQuad> quadList = Collections.synchronizedList(Lists.newArrayList(bakedQuads)); return quadList; } return emptyQuads; } protected final void putVertexData(Vector3f normal, Vector3f[] vertices, Vector2f[] uvs, TextureAtlasSprite sprite) { UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(DefaultVertexFormats.ITEM); builder.setQuadOrientation(EnumFacing.getFacingFromVector(normal.x, normal.y, normal.z)); builder.setTexture(sprite); // builder.setQuadColored(); for(int i=0; i<vertices.length; i++) { builder.put(0, vertices[i].x, vertices[i].y, vertices[i].z, 1);//Pos float d = LightUtil.diffuseLight(normal.x, normal.y, normal.z); builder.put(1, d, d, d, 1);//Colour builder.put(2, uvs[i].x, uvs[i].y, 0, 1);//UV builder.put(3, normal.x, normal.y, normal.z, 0);//Normal builder.put(4);//padding } bakedQuads.add(builder.build()); } @Override public boolean isAmbientOcclusion() { return true; } @Override public boolean isGui3d() { return true; } @Override public boolean isBuiltInRenderer() { return false; } @Override public TextureAtlasSprite getParticleTexture() { return null; } @Override public ItemCameraTransforms getItemCameraTransforms() { return ItemCameraTransforms.DEFAULT; } @Override public ItemOverrideList getOverrides() { return overrideList; } ItemOverrideList overrideList = new ItemOverrideList(new ArrayList()) { @Override public IBakedModel handleItemState(IBakedModel originalModel, ItemStack stack, World world, EntityLivingBase entity) { if(ItemNBTHelper.hasKey(stack, "mineral")) { String name = ItemNBTHelper.getString(stack, "mineral"); if(name!=null && !name.isEmpty()) { if(!modelCache.containsKey(name)) for(MineralMix mix : ExcavatorHandler.mineralList.keySet()) if(name.equals(mix.name)) modelCache.put(name, new ModelCoresample(mix)); IBakedModel model = modelCache.get(name); if(model != null) return model; } } return originalModel; } }; // @Override // public IBakedModel handleItemState(ItemStack stack) // { // return this; // } // @Override // public VertexFormat getFormat() // { // return DefaultVertexFormats.ITEM; // } static HashMap<TransformType, Matrix4> transformationMap = new HashMap<TransformType, Matrix4>(); static{ transformationMap.put(TransformType.FIRST_PERSON_LEFT_HAND, new Matrix4().translate(0, .28, 0).rotate(Math.toRadians(180), 1, 0, 0).rotate(Math.toRadians(-90), 0, 1, 0)); transformationMap.put(TransformType.FIRST_PERSON_RIGHT_HAND, new Matrix4().translate(0, .28, 0).rotate(Math.toRadians(180), 1, 0, 0).rotate(Math.toRadians(-90), 0, 1, 0)); transformationMap.put(TransformType.THIRD_PERSON_LEFT_HAND, new Matrix4().translate(0, .0625, -.125).scale(.625, .625, .625).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(.625, .625, .625).rotate(Math.toRadians(30), 1, 0, 0).rotate(Math.toRadians(130), 0, 1, 0)); transformationMap.put(TransformType.GUI, new Matrix4().scale(1.25,1.25,1.25).rotate(Math.toRadians(180), 1,0,0).rotate(Math.toRadians(20), 0,1,0).rotate(Math.toRadians(-30), 0,0,1)); transformationMap.put(TransformType.FIXED, new Matrix4().scale(1.5,1.5,1.5).rotate(Math.toRadians(180), 1,0,0)); transformationMap.put(TransformType.GROUND, new Matrix4().scale(1.5,1.5,1.5).rotate(Math.toRadians(180), 1,0,0)); } @Override public Pair<? extends IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType) { // if(transformationMap==null) return Pair.of(this, TRSRTransformation.identity().getMatrix()); // Matrix4 matrix = transformationMap.containsKey(cameraTransformType)?transformationMap.get(cameraTransformType):new Matrix4(); // return Pair.of(this, matrix.toMatrix4f()); } }