/* * 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 . */ package malte0811.industrialwires.client.render; import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4; import malte0811.industrialwires.blocks.IWProperties; import malte0811.industrialwires.blocks.hv.TileEntityMarx; import malte0811.industrialwires.blocks.hv.TileEntityMarx.Discharge; import malte0811.industrialwires.client.ClientEventHandler; import malte0811.industrialwires.util.MiscUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; import org.lwjgl.opengl.GL11; import static malte0811.industrialwires.blocks.hv.TileEntityMarx.FiringState.FIRE; public class TileRenderMarx extends TileEntitySpecialRenderer { public static boolean screenShot = false; @Override public void render(TileEntityMarx te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) { final boolean debug = false; //noinspection ConstantConditions,PointlessBooleanExpression if (te.type == IWProperties.MarxType.BOTTOM && (debug || te.state == FIRE) && te.dischargeData!=null) { Vec3d player = Minecraft.getMinecraft().player.getPositionEyes(partialTicks); Tessellator tes = Tessellator.getInstance(); BufferBuilder vb = tes.getBuffer(); Matrix4 mat = prepare(x, y, z, te, player); if (te.dischargeData.energy>0) { drawDischarge(te.dischargeData, vb, tes, mat); } GlStateManager.popMatrix(); //draw firing spark gaps Vec3i facing = te.facing.getDirectionVec(); Vec3d offset = new Vec3d(MiscUtils.offset(BlockPos.ORIGIN, te.facing, te.mirrored, 1, 1, 0)); offset = offset.add(-.5 * oneSgn(offset.x), 0, -.5 * oneSgn(offset.z)); final float pos = .3125F; Vec3d gapDir = new Vec3d(facing.getZ()*(te.mirrored?-1:1), 1, facing.getX()*(te.mirrored?1:-1)); Vec3d up = new Vec3d(gapDir.x, -1, gapDir.z); Vec3d bottomGap = new Vec3d(offset.x+facing.getX()*pos+.5, offset.y+.75, offset.z+facing.getZ() * pos+.5); GlStateManager.pushMatrix(); GlStateManager.translate(x + bottomGap.x, y + bottomGap.y, z + bottomGap.z); bottomGap = bottomGap.add(te.getPos().getX(), te.getPos().getY(), te.getPos().getZ()); for (int i = 0; i < te.getStageCount() - 1; i++) { renderGap(i, facing, vb, tes, player, gapDir, up, bottomGap, te.mirrored); } cleanUp(); te.state = TileEntityMarx.FiringState.CHARGING; if (screenShot) { ClientEventHandler.shouldScreenshot = true; screenShot = false; } } } private double oneSgn(double in) { double ret = Math.signum(in); return ret==0?1:ret; } private void renderGap(int i, Vec3i facing, BufferBuilder vb, Tessellator tes, Vec3d player, Vec3d gapDir, Vec3d up, Vec3d bottomGap, boolean mirrored) { GlStateManager.pushMatrix(); GlStateManager.translate(0, i, 0); GlStateManager.rotate((mirrored?45:135), facing.getX(), facing.getY(), facing.getZ()); player = player.subtract(bottomGap.x, bottomGap.y+i, bottomGap.z); double t = player.dotProduct(gapDir)/2; Vec3d lineToPlayer = gapDir.scale(t).subtract(player); double angleRad = Math.acos(up.dotProduct(lineToPlayer) / (up.length() * lineToPlayer.length())); angleRad *= Math.signum(lineToPlayer.dotProduct(new Vec3d(facing))); float angle = (float) (Math.toDegrees(angleRad)); if (facing.getZ()<0) { angle = 270+angle; } else if (facing.getZ()>0) { angle = 90+angle; } else if (facing.getX()>0) { angle = 180+angle; } GlStateManager.rotate(angle, 0, 1, 0); vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); drawDischargeSection(new Vec3d(0, -.2F, 0), new Vec3d(0, .2F, 0), .25F, .4F, .45F, vb); tes.draw(); GlStateManager.popMatrix(); } private Matrix4 prepare(double x, double y, double z, TileEntityMarx te, Vec3d player) { setLightmapDisabled(true); GlStateManager.pushMatrix(); Vec3i offset = MiscUtils.offset(BlockPos.ORIGIN, te.facing, te.mirrored, 1, 4, 1); Vec3d bottom = new Vec3d(offset.getX()+.5, offset.getY(), offset.getZ()+.5); GlStateManager.translate(x+bottom.x, y+bottom.y, z+bottom.z); GlStateManager.disableTexture2D(); GlStateManager.disableLighting(); GlStateManager.shadeModel(GL11.GL_SMOOTH); GlStateManager.color(1, 1, 1, 1); GlStateManager.enableBlend(); GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); player = player.subtract(bottom.add(new Vec3d(te.getPos()))); double angle = Math.atan2(player.x, player.z); Matrix4 ret = new Matrix4(); ret.rotate(-angle, 0, 1, 0); GlStateManager.rotate((float) Math.toDegrees(angle), 0, 1, 0); Shaders.useShader(Shaders.MARX); return ret; } private void cleanUp() { setLightmapDisabled(false); GlStateManager.popMatrix(); GlStateManager.enableTexture2D(); GlStateManager.enableLighting(); GlStateManager.shadeModel(GL11.GL_FLAT); GlStateManager.disableBlend(); Shaders.stopUsingShaders(); } private void drawDischarge(Discharge d, BufferBuilder vb, Tessellator tes, Matrix4 mat) { if (d!=null&&d.vertices!=null) { vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); for (int i = 0;i