package com.zpig333.runesofwizardry.client.render;
import java.awt.Color;
import java.util.Random;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.tileentity.TileEntityBeaconRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import org.lwjgl.opengl.GL11;
import com.zpig333.runesofwizardry.core.References;
import com.zpig333.runesofwizardry.core.WizardryLogger;
import com.zpig333.runesofwizardry.tileentity.TileEntityDustActive;
import com.zpig333.runesofwizardry.tileentity.TileEntityDustActive.BeamData;
import com.zpig333.runesofwizardry.tileentity.TileEntityDustPlaced;
public class RenderDustActive extends RenderDustPlaced {
/* (non-Javadoc)
* @see com.zpig333.runesofwizardry.client.render.RenderDustPlaced#renderTileEntityAt(com.zpig333.runesofwizardry.tileentity.TileEntityDustPlaced, double, double, double, float, int)
*/
@Override
public void renderTileEntityAt(TileEntityDustPlaced tileEntity, double relativeX, double relativeY, double relativeZ,float partialTicks, int blockDamageProgress) {
super.renderTileEntityAt(tileEntity, relativeX, relativeY, relativeZ,partialTicks, blockDamageProgress);
if(!(tileEntity instanceof TileEntityDustActive)){
WizardryLogger.logError("TileEntity was not active dust for rendering by RenderDustActive");
return;
}
//save GL state
GL11.glPushMatrix();
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
//move the reference point from the player to the position of the block
GlStateManager.translate(relativeX, relativeY, relativeZ);
TileEntityDustActive te = (TileEntityDustActive)tileEntity;
if(te.stardata!=null && te.stardata.doRender)renderStar(te);
if(te.beamdata!=null && te.beamdata.doRender)drawBeam(te, partialTicks);
GL11.glPopAttrib();
GL11.glPopMatrix();
}
private static final int BIRTHLENGTH = 20*5;
/**
* Draws a bicolor star as defined per the TE
* @author billythegoat101, tweaks by Xilef11
*/
private void renderStar(TileEntityDustActive te)
{
//the star disappears sometimes (especially if it's *far* from the dust) - this is because the TE is not in the view. can't do much about it.
Tessellator tes = Tessellator.getInstance();
VertexBuffer vb = tes.getBuffer();
Vec3d off = te.stardata.offset;
RenderHelper.disableStandardItemLighting();
int ticks = (int) (te.ticksExisted() % 200);
if (ticks >= 100)
{
ticks = 200 - ticks - 1;
}
float f1 = (ticks) / 200F;
float f2 = 0.0F;
if (f1 > 0.7F)
{
f2 = (f1 - 0.7F) / 0.2F;
}
float yOffset = 0;
float scale = te.stardata.scale;
if(te.ticksExisted() < BIRTHLENGTH){
double offset = off.yCoord +0.5;
double offsetPerc = offset/(1-0.1875);
double perc = ((double)ticks / (double) BIRTHLENGTH);
scale *= Math.min(perc+0.2,1);
yOffset = (float)perc*(float)offsetPerc-(float)offset;
}
Random random = new Random(432L);
GL11.glPushAttrib(GL11.GL_LIGHTING_BIT | GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
GL11.glDisable(GL11.GL_ALPHA_TEST);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glDepthMask(false);
GL11.glPushMatrix();
//center 1 block above TE by default
GlStateManager.translate(0.5+off.xCoord, 1+off.yCoord+yOffset, 0.5+off.zCoord);
GL11.glScalef(0.02F, 0.02F, 0.02F);
GL11.glScalef(scale,scale,scale);
GL11.glScalef(1F, te.stardata.yscale, 1F);
for (int i = 0; i < ((f1 + f1 * f1) / 2F) * 90F + 30F; i++)
{
GL11.glRotatef(random.nextFloat() * 360F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(random.nextFloat() * 360F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(random.nextFloat() * 360F, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(random.nextFloat() * 360F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(random.nextFloat() * 360F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(random.nextFloat() * 360F + f1 * 90F, 0.0F, 0.0F, 1.0F);
vb.begin(GL11.GL_TRIANGLE_FAN, DefaultVertexFormats.POSITION_COLOR);
float f3 = random.nextFloat() * 20F + 5F + f2 * 10F;
float f4 = random.nextFloat() * 2.0F + 1.0F + f2 * 2.0F;
Color col = new Color(te.stardata.innercolor);
vb.pos(0, 0, 0).color(col.getRed(), col.getGreen(), col.getBlue(), (int)(255F * (1.0F - f2))).endVertex();
col = new Color(te.stardata.outercolor);
vb.pos(-0.86599999999999999D * f4, f3, -0.5F * f4).color(col.getRed(), col.getGreen(), col.getBlue(), 0).endVertex();
vb.pos(0.86599999999999999D * f4, f3, -0.5F * f4).color(col.getRed(), col.getGreen(), col.getBlue(), 0).endVertex();
vb.pos(0, f3, 1.0F * f4).color(col.getRed(), col.getGreen(), col.getBlue(), 0).endVertex();
vb.pos(-0.86599999999999999D * f4, f3, -0.5F * f4).color(col.getRed(), col.getGreen(), col.getBlue(), 0).endVertex();
tes.draw();
}
GL11.glPopMatrix();
GL11.glDepthMask(true);
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_BLEND);
GL11.glShadeModel(GL11.GL_FLAT);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glPopAttrib();
RenderHelper.enableStandardItemLighting();
}
private static final ResourceLocation TEXTURE_SPIRAL_BEAM = new ResourceLocation(References.modid, "textures/renderer/beam_spiral.png");
private static final ResourceLocation TEXTURE_RING_BEAM = new ResourceLocation(References.modid, "textures/renderer/beam_rings.png");
private static final ResourceLocation MISSING_TEXTURE=new ResourceLocation("minecraft:missing_block_texture");
private void drawBeam(TileEntityDustActive te,float partialTicks) {
GlStateManager.alphaFunc(GL11.GL_GEQUAL, 0.1F);
//looks like the GL flags get reset by the renderBeamSegment thing, so we are stuck with the solid beam if we want to just call instead of copy
this.bindTexture(getBeamTexture(te.beamdata));
GlStateManager.disableFog();
Color beamColor = new Color(te.beamdata.color);
Vec3d off = te.beamdata.offset;
float[] colors = new float[]{beamColor.getRed()/255F,beamColor.getGreen()/255F,beamColor.getBlue()/255F};
//renderBeamSegment(double x, double y, double z, double partialTicks, double shouldBeamrender, double totalWorldTime, int verticalOffset, int height, float[] colors, double beamRadius, double glowRadius)
//looks like shouldBeamRender affects the scale/speed of the texture animation
TileEntityBeaconRenderer.renderBeamSegment(off.xCoord, off.yCoord, off.zCoord, partialTicks, getTextureScale(te.beamdata), te.beamdata.doesRotate?(double)te.getWorld().getTotalWorldTime() : partialTicks, 0, te.beamdata.height, colors, te.beamdata.beamRadius,te.beamdata.glowRadius);
GlStateManager.enableFog();
}
private static ResourceLocation getBeamTexture(BeamData data){
switch(data.type){
case BEACON:return TileEntityBeaconRenderer.TEXTURE_BEACON_BEAM;
case SPIRAL:return TEXTURE_SPIRAL_BEAM;
case RINGS: return TEXTURE_RING_BEAM;
case CUSTOM: if(data.customTexture!=null)return data.customTexture;
//$FALL-THROUGH$
default:return MISSING_TEXTURE;
}
}
private static double getTextureScale(BeamData data){
switch(data.type){
case BEACON:return 1.0;
case SPIRAL: return 0.5;
case RINGS: return 1.0;
case CUSTOM: return data.customTexScale;
default: return 1.0;
}
}
/* (non-Javadoc)
* @see net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer#isGlobalRenderer(net.minecraft.tileentity.TileEntity)
*/
@Override
public boolean isGlobalRenderer(TileEntityDustPlaced te) {
if(te instanceof TileEntityDustActive){
TileEntityDustActive tea = (TileEntityDustActive)te;
return (tea.stardata!=null && tea.stardata.doRender)||(tea.beamdata!=null && tea.beamdata.doRender);
}
return false;
}
}