IndustrialWires/src/main/java/malte0811/industrialwires/client/render/TileRenderMechMB.java
2018-09-03 20:35:23 +02:00

154 lines
6.3 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.render;
import blusunrize.immersiveengineering.api.IEApi;
import blusunrize.immersiveengineering.client.ClientUtils;
import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4;
import malte0811.industrialwires.blocks.converter.TileEntityMechMB;
import malte0811.industrialwires.client.ClientUtilsIW;
import malte0811.industrialwires.client.RawQuad;
import malte0811.industrialwires.mech_mb.MechMBPart;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector3f;
import javax.annotation.Nonnull;
import java.util.*;
import static malte0811.industrialwires.blocks.converter.TileEntityMechMB.TICK_ANGLE_PER_SPEED;
import static malte0811.industrialwires.mech_mb.MechMBPart.SHAFT_KEY;
public class TileRenderMechMB extends TileEntitySpecialRenderer<TileEntityMechMB> implements IResourceManagerReloadListener {
public static final Map<ResourceLocation, IBakedModel> BASE_MODELS = new HashMap<>();
private static final Set<TileEntityMechMB> TES_WITH_MODELS = Collections.newSetFromMap(new WeakHashMap<>());
static {
IEApi.renderCacheClearers.add(TileRenderMechMB::clearCache);
}
@Override
public void render(TileEntityMechMB te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
if (te.mechanical != null) {
if (te.rotatingModel == null) {
generateModel(te);
}
GlStateManager.enableBlend();
GlStateManager.blendFunc(770, 771);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
GlStateManager.pushMatrix();
GlStateManager.translate(.5F + x, .5F + y, .5F + z);
GlStateManager.rotate(180 - te.facing.getHorizontalAngle(), 0, 1, 0);
GlStateManager.rotate((float) (te.angle + te.energyState.getSpeed() * TICK_ANGLE_PER_SPEED * partialTicks),
0, 0, 1);
GlStateManager.translate(-.5, -.5, -.5);
Tessellator tes = Tessellator.getInstance();
BufferBuilder bb = tes.getBuffer();
bb.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
ClientUtils.renderModelTESRFast(te.rotatingModel, bb, te.getWorld(), te.getPos());
tes.draw();
GlStateManager.popMatrix();
RenderHelper.enableStandardItemLighting();
}
}
@Override
public void onResourceManagerReload(@Nonnull IResourceManager resourceManager) {
clearCache();
}
private static void clearCache() {
for (TileEntityMechMB te : TES_WITH_MODELS)
te.rotatingModel = null;
TES_WITH_MODELS.clear();
}
private void generateModel(TileEntityMechMB te) {
te.rotatingModel = new ArrayList<>();
int offset = 1;
for (MechMBPart part : te.mechanical) {
addQuadsForPart(part, offset, te.rotatingModel);
offset += part.getLength();
}
//Add shaft model in the end blocks
List<BakedQuad> shaftQuads = MechMBPart.INSTANCES.get(SHAFT_KEY).getRotatingQuads();
Vector3f tmp = new Vector3f();
Matrix4 id = new Matrix4();
Matrix4 translate = new Matrix4();
translate.translate(0, 0, offset);
for (BakedQuad q : shaftQuads) {
RawQuad raw = RawQuad.unbake(q);
Vector3f.add(raw.vertices[0], raw.vertices[1], tmp);
tmp.scale(.5F);
Vector3f middle01 = new Vector3f(tmp);
Vector3f.add(raw.vertices[2], raw.vertices[3], tmp);
tmp.scale(.5F);
Vector3f middle23 = new Vector3f(tmp);
RawQuad start = new RawQuad(raw.vertices[0], middle01, middle23, raw.vertices[3],
raw.facing, raw.tex, raw.colorA, raw.normal, new float[][]{
raw.uvs[0], {raw.uvs[1][0], 8}, {raw.uvs[2][0], 8}, raw.uvs[3]
}, -1);
te.rotatingModel.add(ClientUtilsIW.bakeQuad(start, id, id));
RawQuad end = new RawQuad(middle01, raw.vertices[1], raw.vertices[2], middle23,
raw.facing, raw.tex, raw.colorA, raw.normal, new float[][]{
{raw.uvs[0][0], 8}, raw.uvs[1], raw.uvs[2], {raw.uvs[3][0], 8}
}, -1);
te.rotatingModel.add(ClientUtilsIW.bakeQuad(end, translate, id));
}
TES_WITH_MODELS.add(te);
}
private void addQuadsForPart(MechMBPart part, int offset, List<BakedQuad> out) {
List<BakedQuad> quadsForPart = part.getRotatingQuads();
if (offset != 0) {
for (BakedQuad b : quadsForPart) {
out.add(translateQuadZ(b, offset));
}
} else {
out.addAll(quadsForPart);
}
}
private BakedQuad translateQuadZ(BakedQuad b, float offset) {
int[] data = Arrays.copyOf(b.getVertexData(), b.getVertexData().length);
int pos = 0;
for (VertexFormatElement ele : b.getFormat().getElements()) {
if (ele.getUsage() == VertexFormatElement.EnumUsage.POSITION) {
for (int i = 0; i < 4; i++) {
data[i * b.getFormat().getIntegerSize() + pos + 2] = Float.floatToRawIntBits(
Float.intBitsToFloat(data[i * b.getFormat().getIntegerSize() + pos + 2]) + offset);
}
break;
}
pos += ele.getSize() / 4;
}
return new BakedQuad(data, b.getTintIndex(), b.getFace(),
b.getSprite(), b.shouldApplyDiffuseLighting(), b.getFormat());
}
}