249 lines
11 KiB
Java
249 lines
11 KiB
Java
package electroblob.wizardry.client.renderer.effect;
|
|
|
|
import electroblob.wizardry.Wizardry;
|
|
import electroblob.wizardry.potion.PotionContainment;
|
|
import electroblob.wizardry.registry.WizardryPotions;
|
|
import electroblob.wizardry.util.GeometryUtils;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.renderer.BufferBuilder;
|
|
import net.minecraft.client.renderer.GlStateManager;
|
|
import net.minecraft.client.renderer.OpenGlHelper;
|
|
import net.minecraft.client.renderer.Tessellator;
|
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
import net.minecraft.nbt.NBTUtil;
|
|
import net.minecraft.util.ResourceLocation;
|
|
import net.minecraft.util.math.MathHelper;
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
|
import net.minecraftforge.fml.common.Mod;
|
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
|
import net.minecraftforge.fml.relauncher.Side;
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
@Mod.EventBusSubscriber(Side.CLIENT)
|
|
public class RenderContainmentField {
|
|
|
|
private static final ResourceLocation[] TEXTURES = new ResourceLocation[8];
|
|
|
|
private static final float ANIMATION_SPEED = 0.004f;
|
|
private static final float FADE_DISTANCE_SQUARED = 15;
|
|
|
|
static {
|
|
for(int i = 0; i< TEXTURES.length; i++){
|
|
TEXTURES[i] = new ResourceLocation(Wizardry.MODID, "textures/environment/containment_field_" + i + ".png");
|
|
}
|
|
}
|
|
|
|
@SubscribeEvent
|
|
public static void onRenderWorldLastEvent(RenderWorldLastEvent event){
|
|
|
|
EntityPlayer player = Minecraft.getMinecraft().player;
|
|
|
|
if(player.isPotionActive(WizardryPotions.containment)){
|
|
|
|
Vec3d centre = GeometryUtils.getCentre(NBTUtil.getPosFromTag(player.getEntityData().getCompoundTag(PotionContainment.ENTITY_TAG)));
|
|
float r = PotionContainment.getContainmentDistance(player.getActivePotionEffect(WizardryPotions.containment).getAmplifier());
|
|
|
|
GlStateManager.pushMatrix();
|
|
GlStateManager.enableBlend();
|
|
GlStateManager.shadeModel(GL11.GL_SMOOTH); // Allows the vertex colours to produce a gradient
|
|
GlStateManager.disableLighting();
|
|
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
|
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
// Enables tiling (Also used for guardian beam, beacon beam and ender crystal beam)
|
|
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
|
|
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
|
|
|
|
// Translate the texture in the 2D space (like the creeper charge layer)
|
|
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
|
GlStateManager.loadIdentity();
|
|
float distance = (player.ticksExisted + event.getPartialTicks()) * ANIMATION_SPEED;
|
|
GlStateManager.translate(distance, distance, 0);
|
|
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
|
|
|
GlStateManager.color(1, 1, 1, 1);
|
|
|
|
Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURES[(player.ticksExisted % (TEXTURES.length * 2))/2]);
|
|
|
|
Tessellator tessellator = Tessellator.getInstance();
|
|
|
|
// The aim here is to have only the bits of the containment field near the player be visible (if any).
|
|
// There's probably a really neat, advanced way of doing this with OpenGL (stencil buffer...?) but in the
|
|
// absence of OpenGL skills, I've devised a cheat which kinda achieves the effect we want:
|
|
|
|
// - Split each face of the cube into four, where the split point is taken orthogonal to the player (the
|
|
// player is taken as (0, 0, 0) for simplicity, unlike most render classes where the entire thing is
|
|
// translated first)
|
|
// - Then have the alpha value for each vertex change based on its distance from the player
|
|
// - N.B. OpenGL renders quads as two triangles, with the 1st and 3rd vertices forming the line between them.
|
|
// This causes weirdness in the interpolation since the interpolation isn't taking the whole square into
|
|
// account. The order of the vertices below ensures that the seams between the triangles form an X shape
|
|
// on each of the faces, meaning that you always see a square shape appear rather than a random polygon.
|
|
|
|
Vec3d relative = centre.subtract(player.getPositionEyes(event.getPartialTicks())).add(0, player.getEyeHeight(), 0);
|
|
|
|
double x1 = relative.x - r;
|
|
double y1 = relative.y - r;
|
|
double z1 = relative.z - r;
|
|
double x2 = relative.x + r;
|
|
double y2 = relative.y + r;
|
|
double z2 = relative.z + r;
|
|
|
|
float alpha = Math.min(1, player.getActivePotionEffect(WizardryPotions.containment).getDuration() / 40f);
|
|
|
|
BufferBuilder buffer = tessellator.getBuffer();
|
|
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
|
|
|
|
// The following code is mostly an incomprehensible mess of numbers, but unfortunately without a lot of
|
|
// fancy vector stuff it has to be like this, and besides, this is faster!
|
|
|
|
// Bottom
|
|
drawVertex(buffer, x1, y1, z1, 0, 0, alpha);
|
|
drawVertex(buffer, x1, y1, 0, 0, -(float)z1, alpha);
|
|
drawVertex(buffer, 0, y1, 0, -(float)x1, -(float)z1, alpha);
|
|
drawVertex(buffer, 0, y1, z1, -(float)x1, 0, alpha);
|
|
|
|
drawVertex(buffer, 0, y1, 0, -(float)x1, -(float)z1, alpha);
|
|
drawVertex(buffer, x2, y1, 0, 2*r, -(float)z1, alpha);
|
|
drawVertex(buffer, x2, y1, z1, 2*r, 0, alpha);
|
|
drawVertex(buffer, 0, y1, z1, -(float)x1, 0, alpha);
|
|
|
|
drawVertex(buffer, x1, y1, z2, 0, 2*r, alpha);
|
|
drawVertex(buffer, 0, y1, z2, -(float)x1, 2*r, alpha);
|
|
drawVertex(buffer, 0, y1, 0, -(float)x1, -(float)z1, alpha);
|
|
drawVertex(buffer, x1, y1, 0, 0, -(float)z1, alpha);
|
|
|
|
drawVertex(buffer, 0, y1, 0, -(float)x1, -(float)z1, alpha);
|
|
drawVertex(buffer, 0, y1, z2, -(float)x1, 2*r, alpha);
|
|
drawVertex(buffer, x2, y1, z2, 2*r, 2*r, alpha);
|
|
drawVertex(buffer, x2, y1, 0, 2*r, -(float)z1, alpha);
|
|
|
|
// Top
|
|
drawVertex(buffer, x1, y2, z1, 0, 0, alpha);
|
|
drawVertex(buffer, 0, y2, z1, -(float)x1, 0, alpha);
|
|
drawVertex(buffer, 0, y2, 0, -(float)x1, -(float)z1, alpha);
|
|
drawVertex(buffer, x1, y2, 0, 0, -(float)z1, alpha);
|
|
|
|
drawVertex(buffer, x2, y2, z1, 2*r, 0, alpha);
|
|
drawVertex(buffer, x2, y2, 0, 2*r, -(float)z1, alpha);
|
|
drawVertex(buffer, 0, y2, 0, -(float)x1, -(float)z1, alpha);
|
|
drawVertex(buffer, 0, y2, z1, -(float)x1, 0, alpha);
|
|
|
|
drawVertex(buffer, 0, y2, 0, -(float)x1, -(float)z1, alpha);
|
|
drawVertex(buffer, 0, y2, z2, -(float)x1, 2*r, alpha);
|
|
drawVertex(buffer, x1, y2, z2, 0, 2*r, alpha);
|
|
drawVertex(buffer, x1, y2, 0, 0, -(float)z1, alpha);
|
|
|
|
drawVertex(buffer, 0, y2, 0, -(float)x1, -(float)z1, alpha);
|
|
drawVertex(buffer, x2, y2, 0, 2*r, -(float)z1, alpha);
|
|
drawVertex(buffer, x2, y2, z2, 2*r, 2*r, alpha);
|
|
drawVertex(buffer, 0, y2, z2, -(float)x1, 2*r, alpha);
|
|
|
|
// North
|
|
drawVertex(buffer, x1, y1, z1, 0, 0, alpha);
|
|
drawVertex(buffer, 0, y1, z1, -(float)x1, 0, alpha);
|
|
drawVertex(buffer, 0, 0, z1, -(float)x1, -(float)y1, alpha);
|
|
drawVertex(buffer, x1, 0, z1, 0, -(float)y1, alpha);
|
|
|
|
drawVertex(buffer, x2, y1, z1, 2*r, 0, alpha);
|
|
drawVertex(buffer, x2, 0, z1, 2*r, -(float)y1, alpha);
|
|
drawVertex(buffer, 0, 0, z1, -(float)x1, -(float)y1, alpha);
|
|
drawVertex(buffer, 0, y1, z1, -(float)x1, 0, alpha);
|
|
|
|
drawVertex(buffer, 0, 0, z1, -(float)x1, -(float)y1, alpha);
|
|
drawVertex(buffer, 0, y2, z1, -(float)x1, 2*r, alpha);
|
|
drawVertex(buffer, x1, y2, z1, 0, 2*r, alpha);
|
|
drawVertex(buffer, x1, 0, z1, 0, -(float)y1, alpha);
|
|
|
|
drawVertex(buffer, 0, 0, z1, -(float)x1, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, 0, z1, 2*r, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, y2, z1, 2*r, 2*r, alpha);
|
|
drawVertex(buffer, 0, y2, z1, -(float)x1, 2*r, alpha);
|
|
|
|
// South
|
|
drawVertex(buffer, x1, y1, z2, 0, 0, alpha);
|
|
drawVertex(buffer, x1, 0, z2, 0, -(float)y1, alpha);
|
|
drawVertex(buffer, 0, 0, z2, -(float)x1, -(float)y1, alpha);
|
|
drawVertex(buffer, 0, y1, z2, -(float)x1, 0, alpha);
|
|
|
|
drawVertex(buffer, 0, 0, z2, -(float)x1, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, 0, z2, 2*r, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, y1, z2, 2*r, 0, alpha);
|
|
drawVertex(buffer, 0, y1, z2, -(float)x1, 0, alpha);
|
|
|
|
drawVertex(buffer, x1, y2, z2, 0, 2*r, alpha);
|
|
drawVertex(buffer, 0, y2, z2, -(float)x1, 2*r, alpha);
|
|
drawVertex(buffer, 0, 0, z2, -(float)x1, -(float)y1, alpha);
|
|
drawVertex(buffer, x1, 0, z2, 0, -(float)y1, alpha);
|
|
|
|
drawVertex(buffer, 0, 0, z2, -(float)x1, -(float)y1, alpha);
|
|
drawVertex(buffer, 0, y2, z2, -(float)x1, 2*r, alpha);
|
|
drawVertex(buffer, x2, y2, z2, 2*r, 2*r, alpha);
|
|
drawVertex(buffer, x2, 0, z2, 2*r, -(float)y1, alpha);
|
|
|
|
// West
|
|
drawVertex(buffer, x1, y1, z1, 0, 0, alpha);
|
|
drawVertex(buffer, x1, 0, z1, 0, -(float)y1, alpha);
|
|
drawVertex(buffer, x1, 0, 0, -(float)z1, -(float)y1, alpha);
|
|
drawVertex(buffer, x1, y1, 0, -(float)z1, 0, alpha);
|
|
|
|
drawVertex(buffer, x1, 0, 0, -(float)z1, -(float)y1, alpha);
|
|
drawVertex(buffer, x1, 0, z2, 2*r, -(float)y1, alpha);
|
|
drawVertex(buffer, x1, y1, z2, 2*r, 0, alpha);
|
|
drawVertex(buffer, x1, y1, 0, -(float)z1, 0, alpha);
|
|
|
|
drawVertex(buffer, x1, y2, z1, 0, 2*r, alpha);
|
|
drawVertex(buffer, x1, y2, 0, -(float)z1, 2*r, alpha);
|
|
drawVertex(buffer, x1, 0, 0, -(float)z1, -(float)y1, alpha);
|
|
drawVertex(buffer, x1, 0, z1, 0, -(float)y1, alpha);
|
|
|
|
drawVertex(buffer, x1, 0, 0, -(float)z1, -(float)y1, alpha);
|
|
drawVertex(buffer, x1, y2, 0, -(float)z1, 2*r, alpha);
|
|
drawVertex(buffer, x1, y2, z2, 2*r, 2*r, alpha);
|
|
drawVertex(buffer, x1, 0, z2, 2*r, -(float)y1, alpha);
|
|
|
|
// East
|
|
drawVertex(buffer, x2, y1, z1, 0, 0, alpha);
|
|
drawVertex(buffer, x2, y1, 0, -(float)z1, 0, alpha);
|
|
drawVertex(buffer, x2, 0, 0, -(float)z1, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, 0, z1, 0, -(float)y1, alpha);
|
|
|
|
drawVertex(buffer, x2, y1, z2, 2*r, 0, alpha);
|
|
drawVertex(buffer, x2, 0, z2, 2*r, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, 0, 0, -(float)z1, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, y1, 0, -(float)z1, 0, alpha);
|
|
|
|
drawVertex(buffer, x2, 0, 0, -(float)z1, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, y2, 0, -(float)z1, 2*r, alpha);
|
|
drawVertex(buffer, x2, y2, z1, 0, 2*r, alpha);
|
|
drawVertex(buffer, x2, 0, z1, 0, -(float)y1, alpha);
|
|
|
|
drawVertex(buffer, x2, 0, 0, -(float)z1, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, 0, z2, 2*r, -(float)y1, alpha);
|
|
drawVertex(buffer, x2, y2, z2, 2*r, 2*r, alpha);
|
|
drawVertex(buffer, x2, y2, 0, -(float)z1, 2*r, alpha);
|
|
|
|
tessellator.draw();
|
|
|
|
// Undoes the texture translation
|
|
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
|
GlStateManager.loadIdentity();
|
|
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
|
|
|
GlStateManager.disableBlend();
|
|
GlStateManager.enableTexture2D();
|
|
GlStateManager.enableLighting();
|
|
GlStateManager.disableRescaleNormal();
|
|
GlStateManager.popMatrix();
|
|
}
|
|
}
|
|
|
|
private static void drawVertex(BufferBuilder buffer, double x, double y, double z, float u, float v, float alpha){
|
|
float f = MathHelper.clamp(1 - (float)(x*x + y*y + z*z) / FADE_DISTANCE_SQUARED, 0, 1);
|
|
buffer.pos(x, y, z).tex(u, v).color(1, 1, 1, f * alpha).endVertex();
|
|
}
|
|
|
|
}
|