Created
July 18, 2018 01:18
-
-
Save Galaxtone/390060cf0099730d7583c45305d654b4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.galaxtone.noneuclideanportals.graphics; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Map.Entry; | |
import org.lwjgl.opengl.GL11; | |
import org.lwjgl.util.glu.Project; | |
import com.galaxtone.noneuclideanportals.Portal; | |
import com.galaxtone.noneuclideanportals.utils.Selection; | |
import net.minecraft.block.material.Material; | |
import net.minecraft.client.Minecraft; | |
import net.minecraft.client.renderer.ActiveRenderInfo; | |
import net.minecraft.client.renderer.EntityRenderer; | |
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.culling.ClippingHelperImpl; | |
import net.minecraft.client.renderer.culling.Frustum; | |
import net.minecraft.client.renderer.culling.ICamera; | |
import net.minecraft.client.renderer.texture.TextureManager; | |
import net.minecraft.client.renderer.texture.TextureMap; | |
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; | |
import net.minecraft.entity.Entity; | |
import net.minecraft.entity.player.EntityPlayer; | |
import net.minecraft.util.BlockRenderLayer; | |
import net.minecraft.util.EnumFacing.Axis; | |
import net.minecraft.util.math.AxisAlignedBB; | |
import net.minecraft.util.math.BlockPos; | |
import net.minecraft.util.math.MathHelper; | |
import net.minecraft.util.math.Vec3d; | |
import net.minecraftforge.fml.relauncher.Side; | |
import net.minecraftforge.fml.relauncher.SideOnly; | |
@SideOnly(Side.CLIENT) | |
public class RenderHandler { | |
/* List of client list portal ordered by maximum axis-aligned distance across the X and Z axis */ | |
public static List<Portal> orderedPortalList = new ArrayList<Portal>(); | |
/* Useful for rendering */ | |
private static final Tessellator tessellator = Tessellator.getInstance(); | |
private static final VertexBuffer buffer = tessellator.getBuffer(); | |
/* Used for interpolation for smooth motion */ | |
public static float partialTicks; | |
/* Entity that the player is spectating or the player themselves if their not, and the interpolation for smooth rendering */ | |
public static Entity entity; | |
public static Vec3d offset; | |
/* Used to skip the Render event when redrawing the world */ | |
public static boolean skipEvent = false; | |
/* Used for interpolating things */ | |
private static double interpolate(double oldValue, double newValue) { | |
return oldValue + (newValue - oldValue) * partialTicks; | |
} | |
private static Vec3d interpolate(double oldX, double oldY, double oldZ, double newX, double newY, double newZ) { | |
return new Vec3d( | |
interpolate(oldX, newX), | |
interpolate(oldY, newY), | |
interpolate(oldZ, newZ)); | |
} | |
/* Called every frame to update everything for rendering the current frame */ | |
public static void update(float newPartialTicks) { | |
partialTicks = newPartialTicks; | |
entity = Minecraft.getMinecraft().getRenderViewEntity(); | |
offset = interpolate(entity.prevPosX, entity.prevPosY, entity.prevPosZ, entity.posX, entity.posY, entity.posZ); | |
Map<Portal, Double> distance = new HashMap<Portal, Double>(Portal.clientList.size()); | |
for (Portal portal : Portal.clientList) | |
distance.put(portal, Math.max(portal.position.getX() + 0.5D - entity.posX, portal.position.getY() + 0.5D - entity.posZ)); | |
List<Entry<Portal, Double>> entries = new ArrayList<Entry<Portal, Double>>(distance.entrySet()); | |
entries.sort(Entry.comparingByValue()); | |
int length = 0; | |
for (Entry<Portal, Double> entry : entries) | |
if (entity.worldObj.isBlockLoaded(entry.getKey().position)) | |
length++; | |
else | |
break; | |
orderedPortalList = new ArrayList<Portal>(Portal.clientList.size()); | |
int index = 0; | |
for (Entry<Portal, Double> entry : entries) { | |
if (++index > length) | |
break; | |
orderedPortalList.add(entry.getKey()); | |
} | |
} | |
/* Draws a square */ | |
private static void drawQuad(Axis axis, AxisAlignedBB plane) { | |
plane = plane.offset(-offset.xCoord, -offset.yCoord, -offset.zCoord); | |
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); | |
switch (axis) { | |
case X: | |
buffer.pos(plane.minX, plane.minY, plane.minZ).endVertex(); | |
buffer.pos(plane.minX, plane.minY, plane.maxZ).endVertex(); | |
buffer.pos(plane.minX, plane.maxY, plane.maxZ).endVertex(); | |
buffer.pos(plane.minX, plane.maxY, plane.minZ).endVertex(); | |
break; | |
case Z: | |
buffer.pos(plane.minX, plane.minY, plane.minZ).endVertex(); | |
buffer.pos(plane.maxX, plane.minY, plane.minZ).endVertex(); | |
buffer.pos(plane.maxX, plane.maxY, plane.minZ).endVertex(); | |
buffer.pos(plane.minX, plane.maxY, plane.minZ).endVertex(); | |
break; | |
case Y: | |
buffer.pos(plane.minX, plane.minY, plane.minZ).endVertex(); | |
buffer.pos(plane.maxX, plane.minY, plane.minZ).endVertex(); | |
buffer.pos(plane.maxX, plane.minY, plane.maxZ).endVertex(); | |
buffer.pos(plane.minX, plane.minY, plane.maxZ).endVertex(); | |
break; | |
} | |
tessellator.draw(); | |
} | |
/* Draws a square centered within the blocks */ | |
private static void drawCenteredQuad(Axis axis, AxisAlignedBB plane) { | |
switch (axis) { | |
case X: | |
plane = plane.offset(0.5, 0, 0); | |
break; | |
case Z: | |
plane = plane.offset(0, 0, 0.5); | |
break; | |
case Y: | |
plane = plane.offset(0, 0.5, 0); | |
break; | |
} | |
drawQuad(axis, plane); | |
} | |
/* Draws an outline of an area */ | |
private static void drawBoxOutline(AxisAlignedBB box) { | |
box = box.offset(-offset.xCoord, -offset.yCoord, -offset.zCoord); | |
buffer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION); | |
buffer.pos(box.minX, box.minY, box.minZ).endVertex(); | |
buffer.pos(box.maxX, box.minY, box.minZ).endVertex(); | |
buffer.pos(box.maxX, box.minY, box.maxZ).endVertex(); | |
buffer.pos(box.minX, box.minY, box.maxZ).endVertex(); | |
buffer.pos(box.minX, box.minY, box.minZ).endVertex(); | |
tessellator.draw(); | |
buffer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); | |
buffer.pos(box.minX, box.minY, box.minZ).endVertex(); | |
buffer.pos(box.minX, box.maxY, box.minZ).endVertex(); | |
buffer.pos(box.maxX, box.minY, box.minZ).endVertex(); | |
buffer.pos(box.maxX, box.maxY, box.minZ).endVertex(); | |
buffer.pos(box.maxX, box.minY, box.maxZ).endVertex(); | |
buffer.pos(box.maxX, box.maxY, box.maxZ).endVertex(); | |
buffer.pos(box.minX, box.minY, box.maxZ).endVertex(); | |
buffer.pos(box.minX, box.maxY, box.maxZ).endVertex(); | |
tessellator.draw(); | |
buffer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION); | |
buffer.pos(box.minX, box.maxY, box.minZ).endVertex(); | |
buffer.pos(box.maxX, box.maxY, box.minZ).endVertex(); | |
buffer.pos(box.maxX, box.maxY, box.maxZ).endVertex(); | |
buffer.pos(box.minX, box.maxY, box.maxZ).endVertex(); | |
buffer.pos(box.minX, box.maxY, box.minZ).endVertex(); | |
tessellator.draw(); | |
} | |
/* Renders current selection area for new portal creation */ | |
public static void renderSelection() { | |
GlStateManager.enableBlend(); | |
GlStateManager.disableDepth(); | |
GlStateManager.disableCull(); | |
GlStateManager.disableTexture2D(); | |
GlStateManager.color(0.8F, 0.0F, 0.8F, 0.3F); | |
drawCenteredQuad(Selection.axis, Selection.plane); | |
drawBoxOutline(Selection.plane); | |
GlStateManager.disableBlend(); | |
GlStateManager.enableDepth(); | |
GlStateManager.enableCull(); | |
GlStateManager.enableTexture2D(); | |
} | |
/* Renders all the portals */ | |
public static void renderPortals() { | |
Vec3d position = ActiveRenderInfo.projectViewFromEntity(entity, partialTicks); | |
for (Portal portal : orderedPortalList) { | |
Portal.Side side = portal.getSide(position); | |
BlockPos min = new BlockPos(side.plane.minX, side.plane.minY, side.plane.minZ); | |
BlockPos max = new BlockPos(side.plane.maxX, side.plane.maxY, side.plane.maxZ); | |
if (entity.worldObj.isAreaLoaded(min, max)) continue; | |
GlStateManager.disableCull(); | |
GlStateManager.disableTexture2D(); | |
GlStateManager.enableCull(); | |
GlStateManager.enableTexture2D(); | |
/*GlStateManager.colorMask(false, false, false, false); | |
GlStateManager.depthMask(false); | |
GlStateManager.disableDepth(); | |
GL11.glEnable(GL11.GL_STENCIL); | |
GL11.glStencilOp(GL11.GL_INCR, zfail, zpass); | |
GL11.glStencilFunc(GL11.GL_NEVER, ref, mask); | |
drawQuad(side.portal.axis, side.plane);*/ | |
}/* | |
GL11.glStencilFunc(GL11.GL_NOTEQUAL, recursionLevel, mask); | |
GL11.glStencilOp(GL11.GL_INCR, GL11.GL_KEEP, GL11.GL_KEEP); | |
GL11.glStencilMask(0xFF); | |
GlStateManager.getFloat(GL11.GL_PROJECTION_MATRIX, projectionMatrixBuffer); | |
Matrix4f projMat = (Matrix4f) new Matrix4f().load(projectionMatrixBuffer.asReadOnlyBuffer()); | |
Quaternion clip = new Quaternion(); | |
Quaternion quat = new Quaternion(); | |
quat.x = (Math.signum(clip.x) + projMat.m20) / projMat.m00; | |
quat.y = (Math.signum(clip.y) + projMat.m21) / projMat.m11; | |
quat.z = -1.0F; | |
quat.w = (1.0F + projMat.m22) / projMat.m23; | |
float dot = 2f / Quaternion.dot(clip, quat); | |
projMat.m02 = clip.x * dot; | |
projMat.m12 = clip.y * dot; | |
projMat.m22 = clip.z * dot + 1F; | |
projMat.m32 = 1f; | |
projMat.store(projectionMatrixBuffer); | |
GlStateManager.matrixMode(GL11.GL_PROJECTION); | |
GL11.glLoadMatrix(projectionMatrixBuffer.asReadOnlyBuffer()); | |
// TODO https://cdn.discordapp.com/attachments/294069306608582656/436437528728567809/unknown.png | |
// Draw 5 quads based on portal plane, axis and portal side direction. | |
} | |
*/ | |
} | |
public static void renderWorldPass() { | |
Minecraft minecraft = Minecraft.getMinecraft(); | |
int pass = 2; | |
if (minecraft.gameSettings.anaglyph) | |
pass = EntityRenderer.anaglyphField; | |
GlStateManager.enableCull(); | |
minecraft.mcProfiler.endStartSection("camera"); | |
minecraft.entityRenderer.setupCameraTransform(partialTicks, pass); | |
ActiveRenderInfo.updateRenderInfo(minecraft.thePlayer, minecraft.gameSettings.thirdPersonView == 2); | |
GlStateManager.translate(0.0f, 10.0f, 0.0f); | |
minecraft.mcProfiler.endStartSection("frustum"); | |
ClippingHelperImpl.getInstance(); | |
minecraft.mcProfiler.endStartSection("culling"); | |
ICamera icamera = new Frustum(); | |
Entity entity = minecraft.getRenderViewEntity(); | |
Vec3d position = interpolate(entity.lastTickPosX, entity.lastTickPosY, entity.lastTickPosZ, entity.posX, entity.posY, entity.posZ); | |
icamera.setPosition(position.xCoord, position.yCoord, position.zCoord); | |
if (minecraft.gameSettings.renderDistanceChunks >= 4) { | |
minecraft.entityRenderer.setupFog(-1, partialTicks); | |
minecraft.mcProfiler.endStartSection("sky"); | |
GlStateManager.matrixMode(GL11.GL_PROJECTION); | |
GlStateManager.loadIdentity(); | |
Project.gluPerspective(minecraft.entityRenderer.getFOVModifier(partialTicks, true), minecraft.displayWidth / minecraft.displayHeight, 0.05F, minecraft.entityRenderer.farPlaneDistance * 2.0F); | |
GlStateManager.matrixMode(GL11.GL_MODELVIEW); | |
minecraft.renderGlobal.renderSky(partialTicks, pass); | |
GlStateManager.matrixMode(GL11.GL_PROJECTION); | |
GlStateManager.loadIdentity(); | |
Project.gluPerspective(minecraft.entityRenderer.getFOVModifier(partialTicks, true), minecraft.displayWidth / minecraft.displayHeight, 0.05F, minecraft.entityRenderer.farPlaneDistance * MathHelper.SQRT_2); | |
GlStateManager.matrixMode(GL11.GL_MODELVIEW); | |
} | |
minecraft.entityRenderer.setupFog(0, partialTicks); | |
GlStateManager.shadeModel(GL11.GL_SMOOTH); | |
if (entity.posY + entity.getEyeHeight() < 128.0D) | |
minecraft.entityRenderer.renderCloudsCheck(minecraft.renderGlobal, partialTicks, pass); | |
minecraft.mcProfiler.endStartSection("prepareterrain"); | |
minecraft.entityRenderer.setupFog(0, partialTicks); | |
TextureManager textureManager = minecraft.getTextureManager(); | |
textureManager.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); | |
RenderHelper.disableStandardItemLighting(); | |
minecraft.mcProfiler.endStartSection("terrain_setup"); | |
minecraft.renderGlobal.setupTerrain(entity, partialTicks, icamera, minecraft.entityRenderer.frameCount++, minecraft.thePlayer.isSpectator()); | |
if (pass != 1) { | |
minecraft.mcProfiler.endStartSection("updatechunks"); | |
minecraft.renderGlobal.updateChunks(Long.MAX_VALUE); | |
} | |
minecraft.mcProfiler.endStartSection("terrain"); | |
GlStateManager.matrixMode(GL11.GL_MODELVIEW); | |
GlStateManager.pushMatrix(); | |
GlStateManager.disableAlpha(); | |
minecraft.renderGlobal.renderBlockLayer(BlockRenderLayer.SOLID, partialTicks, pass, entity); | |
GlStateManager.enableAlpha(); | |
minecraft.renderGlobal.renderBlockLayer(BlockRenderLayer.CUTOUT_MIPPED, partialTicks, pass, entity); | |
textureManager.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).setBlurMipmap(false, false); | |
minecraft.renderGlobal.renderBlockLayer(BlockRenderLayer.CUTOUT, partialTicks, pass, entity); | |
textureManager.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).restoreLastBlurMipmap(); | |
GlStateManager.shadeModel(GL11.GL_FLAT); | |
GlStateManager.alphaFunc(GL11.GL_GREATER, 0.1F); | |
if (!minecraft.entityRenderer.debugView) { | |
GlStateManager.matrixMode(GL11.GL_MODELVIEW); | |
GlStateManager.popMatrix(); | |
GlStateManager.pushMatrix(); | |
RenderHelper.enableStandardItemLighting(); | |
minecraft.mcProfiler.endStartSection("entities"); | |
net.minecraftforge.client.ForgeHooksClient.setRenderPass(0); | |
minecraft.renderGlobal.renderEntities(entity, icamera, partialTicks); | |
net.minecraftforge.client.ForgeHooksClient.setRenderPass(0); | |
RenderHelper.disableStandardItemLighting(); | |
minecraft.entityRenderer.disableLightmap(); | |
} | |
GlStateManager.matrixMode(GL11.GL_MODELVIEW); | |
GlStateManager.popMatrix(); | |
if (minecraft.entityRenderer.isDrawBlockOutline() && minecraft.objectMouseOver != null && !entity.isInsideOfMaterial(Material.WATER)) { | |
EntityPlayer entityplayer = (EntityPlayer) entity; | |
GlStateManager.disableAlpha(); | |
minecraft.mcProfiler.endStartSection("outline"); | |
if (!net.minecraftforge.client.ForgeHooksClient.onDrawBlockHighlight(minecraft.renderGlobal, entityplayer, minecraft.objectMouseOver, 0, partialTicks)) | |
minecraft.renderGlobal.drawSelectionBox(entityplayer, minecraft.objectMouseOver, 0, partialTicks); | |
GlStateManager.enableAlpha(); | |
} | |
if (minecraft.debugRenderer.shouldRender()) | |
minecraft.debugRenderer.renderDebug(partialTicks, Long.MAX_VALUE); | |
minecraft.mcProfiler.endStartSection("destroyProgress"); | |
GlStateManager.enableBlend(); | |
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); | |
textureManager.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).setBlurMipmap(false, false); | |
minecraft.renderGlobal.drawBlockDamageTexture(Tessellator.getInstance(), Tessellator.getInstance().getBuffer(), entity, partialTicks); | |
textureManager.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).restoreLastBlurMipmap(); | |
GlStateManager.disableBlend(); | |
if (!minecraft.entityRenderer.debugView) { | |
minecraft.entityRenderer.enableLightmap(); | |
minecraft.mcProfiler.endStartSection("litParticles"); | |
minecraft.effectRenderer.renderLitParticles(entity, partialTicks); | |
RenderHelper.disableStandardItemLighting(); | |
minecraft.entityRenderer.setupFog(0, partialTicks); | |
minecraft.mcProfiler.endStartSection("particles"); | |
minecraft.effectRenderer.renderParticles(entity, partialTicks); | |
minecraft.entityRenderer.disableLightmap(); | |
} | |
GlStateManager.depthMask(false); | |
GlStateManager.enableCull(); | |
minecraft.mcProfiler.endStartSection("weather"); | |
minecraft.entityRenderer.renderRainSnow(partialTicks); | |
GlStateManager.depthMask(true); | |
minecraft.renderGlobal.renderWorldBorder(entity, partialTicks); | |
GlStateManager.disableBlend(); | |
GlStateManager.enableCull(); | |
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); | |
GlStateManager.alphaFunc(GL11.GL_GREATER, 0.1F); | |
minecraft.entityRenderer.setupFog(0, partialTicks); | |
GlStateManager.enableBlend(); | |
GlStateManager.depthMask(false); | |
textureManager.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); | |
GlStateManager.shadeModel(GL11.GL_SMOOTH); | |
minecraft.mcProfiler.endStartSection("translucent"); | |
minecraft.renderGlobal.renderBlockLayer(BlockRenderLayer.TRANSLUCENT, partialTicks, pass, entity); | |
if (!minecraft.entityRenderer.debugView) { | |
RenderHelper.enableStandardItemLighting(); | |
minecraft.mcProfiler.endStartSection("entities"); | |
net.minecraftforge.client.ForgeHooksClient.setRenderPass(1); | |
minecraft.renderGlobal.renderEntities(entity, icamera, partialTicks); | |
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); | |
net.minecraftforge.client.ForgeHooksClient.setRenderPass(-1); | |
RenderHelper.disableStandardItemLighting(); | |
} | |
GlStateManager.shadeModel(GL11.GL_FLAT); | |
GlStateManager.depthMask(true); | |
GlStateManager.enableCull(); | |
GlStateManager.disableBlend(); | |
GlStateManager.disableFog(); | |
if (entity.posY + entity.getEyeHeight() >= 128.0D) { | |
minecraft.mcProfiler.endStartSection("aboveClouds"); | |
minecraft.entityRenderer.renderCloudsCheck(minecraft.renderGlobal, partialTicks, pass); | |
} | |
RenderHandler.skipEvent = true; | |
minecraft.mcProfiler.endStartSection("forge_render_last"); | |
net.minecraftforge.client.ForgeHooksClient.dispatchRenderLast(minecraft.renderGlobal, partialTicks); | |
RenderHandler.skipEvent = false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment