88c10cdb81
Update to new mappings
182 lines
6.4 KiB
Java
182 lines
6.4 KiB
Java
/*
|
|
* This file is part of Industrial Wires.
|
|
* Copyright (C) 2016-2018 malte0811
|
|
* Industrial Wires is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
* Industrial Wires 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 General Public License for more details.
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Industrial Wires. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package malte0811.industrialwires.client.multiblock_io_model;
|
|
|
|
import blusunrize.immersiveengineering.api.IEEnums.SideConfig;
|
|
import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4;
|
|
import com.google.common.cache.Cache;
|
|
import com.google.common.cache.CacheBuilder;
|
|
import com.google.common.collect.ImmutableList;
|
|
import malte0811.industrialwires.IndustrialWires;
|
|
import malte0811.industrialwires.blocks.IWProperties;
|
|
import malte0811.industrialwires.client.ClientUtilsIW;
|
|
import malte0811.industrialwires.client.RawQuad;
|
|
import malte0811.industrialwires.util.MBSideConfig;
|
|
import malte0811.industrialwires.util.MBSideConfig.BlockFace;
|
|
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.ItemOverrideList;
|
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
|
import net.minecraft.util.EnumFacing;
|
|
import net.minecraft.util.ResourceLocation;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraftforge.common.model.IModelState;
|
|
import net.minecraftforge.common.model.TRSRTransformation;
|
|
import net.minecraftforge.common.property.IExtendedBlockState;
|
|
import net.minecraftforge.fml.relauncher.Side;
|
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
|
import org.lwjgl.util.vector.Vector3f;
|
|
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Optional;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
@SideOnly(Side.CLIENT)
|
|
public class BakedMBIOModel implements IBakedModel {
|
|
private static final MBSideConfig NULL_CONFIG = new MBSideConfig(ImmutableList.of(new BlockFace(new BlockPos(0, 2, 0), EnumFacing.DOWN)));
|
|
private static final Matrix4 ID = new Matrix4();
|
|
|
|
static final ResourceLocation IO_LOC = new ResourceLocation(IndustrialWires.MODID, "blocks/io");
|
|
static TextureAtlasSprite IO_TEX = null;
|
|
|
|
private final IBakedModel base;
|
|
private final TRSRTransformation transform;
|
|
|
|
private final Cache<MBSideConfig, List<BakedQuad>> cache = CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.MINUTES)
|
|
.maximumSize(100).build();
|
|
|
|
BakedMBIOModel(IBakedModel base, IModelState transform) {
|
|
this.base = base;
|
|
this.transform = TRSRTransformation.blockCornerToCenter(transform.apply(Optional.empty()).orElse(TRSRTransformation.identity()));
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {
|
|
MBSideConfig config = NULL_CONFIG;
|
|
if (state instanceof IExtendedBlockState) {
|
|
MBSideConfig tmpConfig = ((IExtendedBlockState) state).getValue(IWProperties.MB_SIDES);
|
|
if (tmpConfig!=null) {
|
|
config = tmpConfig;
|
|
}
|
|
}
|
|
List<BakedQuad> ret = cache.getIfPresent(config);
|
|
if (ret==null) {
|
|
if (IO_TEX==null) {
|
|
IO_TEX = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(IO_LOC.toString());
|
|
}
|
|
Matrix4 mat = new Matrix4(transform.getMatrix());
|
|
ret = new ArrayList<>(base.getQuads(state, side, rand));
|
|
for (Map.Entry<BlockFace, SideConfig> f:config.sides.entrySet()) {
|
|
if (f.getKey().face==null) {
|
|
continue;
|
|
}
|
|
Vec3d transformedPos = mat.apply(new Vec3d(f.getKey().offset));
|
|
EnumFacing transformedFace = transform.rotate(f.getKey().face);
|
|
Vector3f[] verts = getVerticesFromFace(transformedPos, transformedFace);
|
|
RawQuad q = new RawQuad(verts[0], verts[1], verts[2], verts[3], transformedFace,
|
|
IO_TEX, new float[]{1, 1, 1, 1}, getNormal(transformedFace),
|
|
getUVsForConfig(f.getValue()));
|
|
ret.add(ClientUtilsIW.bakeQuad(q, ID, ID));
|
|
}
|
|
ret = ImmutableList.copyOf(ret);
|
|
cache.put(config.copy(), ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
private static final Vector3f[] NORMALS = new Vector3f[6];
|
|
private static final Vector3f[][] VERTICES = new Vector3f[6][4];
|
|
static {
|
|
final float innerSize = .5F;
|
|
final float offsetInner = 1-innerSize/2;
|
|
float[] vec = new float[3];
|
|
for (int i = 0; i < EnumFacing.VALUES.length; i++) {
|
|
EnumFacing f = EnumFacing.VALUES[i];
|
|
NORMALS[i] = new Vector3f(f.getXOffset(), f.getYOffset(), f.getZOffset());
|
|
int axis = f.getAxis().ordinal();
|
|
vec[axis] = f.getAxisDirection()==EnumFacing.AxisDirection.POSITIVE?1.001F:-.001F;
|
|
float x1 = f.getAxisDirection()==EnumFacing.AxisDirection.POSITIVE?offsetInner:1-offsetInner;
|
|
for (int j = 0;j<4;j++) {
|
|
vec[(axis+1)%3] = 0<j&&j<3?x1:1-x1;
|
|
vec[(axis+2)%3] = j<2?1-offsetInner:offsetInner;
|
|
VERTICES[i][j] = vecFromArray(vec);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static Vector3f vecFromArray(float[] in) {
|
|
return new Vector3f(in[0], in[1], in[2]);
|
|
}
|
|
|
|
private Vector3f[] getVerticesFromFace(Vec3d p, EnumFacing f) {
|
|
Vector3f[] orig = VERTICES[f.ordinal()];
|
|
Vector3f[] ret = new Vector3f[4];
|
|
Vector3f offset = new Vector3f((float) p.x, (float) p.y, (float) p.z);
|
|
for (int i = 0; i < 4; i++) {
|
|
ret[i] = Vector3f.add(orig[i], offset, null);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
private float[] getUVsForConfig(SideConfig sc) {
|
|
float u = (sc.ordinal()/2)*8, v = (sc.ordinal()%2)*8;
|
|
return new float[]{u, v, u+8, v+8};
|
|
}
|
|
|
|
private Vector3f getNormal(EnumFacing face) {
|
|
return NORMALS[face.ordinal()];
|
|
}
|
|
|
|
@Override
|
|
public boolean isAmbientOcclusion() {
|
|
return base.isAmbientOcclusion();
|
|
}
|
|
|
|
@Override
|
|
public boolean isGui3d() {
|
|
return base.isGui3d();
|
|
}
|
|
|
|
@Override
|
|
public boolean isBuiltInRenderer() {
|
|
return base.isBuiltInRenderer();
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public TextureAtlasSprite getParticleTexture() {
|
|
return base.getParticleTexture();
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public ItemOverrideList getOverrides() {
|
|
return base.getOverrides();
|
|
}
|
|
|
|
public void clearCache() {
|
|
cache.invalidateAll();
|
|
}
|
|
}
|