package micdoodle8.mods.galacticraft.core.client.screen; import micdoodle8.mods.galacticraft.api.client.IGameScreen; import micdoodle8.mods.galacticraft.api.client.IScreenManager; import micdoodle8.mods.galacticraft.api.event.client.CelestialBodyRenderEvent; import micdoodle8.mods.galacticraft.api.galaxies.*; import micdoodle8.mods.galacticraft.api.world.IGalacticraftWorldProvider; import micdoodle8.mods.galacticraft.core.Constants; import micdoodle8.mods.galacticraft.core.GalacticraftCore; import micdoodle8.mods.galacticraft.core.client.render.RenderPlanet; import micdoodle8.mods.galacticraft.core.util.GCCoreUtil; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.MathHelper; import net.minecraft.world.WorldProvider; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.client.FMLClientHandler; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector3f; import java.nio.DoubleBuffer; public class GameScreenCelestial implements IGameScreen { private TextureManager renderEngine; private float frameA; private float frameBx; private float frameBy; private float centreX; private float centreY; private float scale; private final int lineSegments = 90; private final float cos = MathHelper.cos(Constants.twoPI / lineSegments); private final float sin = MathHelper.sin(Constants.twoPI / lineSegments); private DoubleBuffer planes; public GameScreenCelestial() { if (GCCoreUtil.getEffectiveSide().isClient()) { renderEngine = FMLClientHandler.instance().getClient().renderEngine; planes = BufferUtils.createDoubleBuffer(4 * Double.SIZE); } } @Override public void setFrameSize(float frameSize) { this.frameA = frameSize; } @Override public void render(int type, float ticks, float scaleX, float scaleY, IScreenManager scr) { centreX = scaleX / 2; centreY = scaleY / 2; frameBx = scaleX - frameA; frameBy = scaleY - frameA; this.scale = Math.max(scaleX, scaleY) - 0.2F; drawBlackBackground(0.0F); planeEquation(frameA, frameA, 0, frameA, frameBy, 0, frameA, frameBy, 1); GL11.glClipPlane(GL11.GL_CLIP_PLANE0, planes); GL11.glEnable(GL11.GL_CLIP_PLANE0); planeEquation(frameBx, frameBy, 0, frameBx, frameA, 0, frameBx, frameA, 1); GL11.glClipPlane(GL11.GL_CLIP_PLANE1, planes); GL11.glEnable(GL11.GL_CLIP_PLANE1); planeEquation(frameA, frameBy, 0, frameBx, frameBy, 0, frameBx, frameBy, 1); GL11.glClipPlane(GL11.GL_CLIP_PLANE2, planes); GL11.glEnable(GL11.GL_CLIP_PLANE2); planeEquation(frameBx, frameA, 0, frameA, frameA, 0, frameA, frameA, 1); GL11.glClipPlane(GL11.GL_CLIP_PLANE3, planes); GL11.glEnable(GL11.GL_CLIP_PLANE3); switch (type) { case 2: WorldProvider wp = scr.getWorldProvider(); CelestialBody body = null; if (wp instanceof IGalacticraftWorldProvider) { body = ((IGalacticraftWorldProvider) wp).getCelestialBody(); } if (body == null) { body = GalacticraftCore.planetOverworld; } drawCelestialBodies(body, ticks); break; case 3: drawCelestialBodiesZ(GalacticraftCore.planetOverworld, ticks); break; case 4: drawPlanetsTest(ticks); break; } GL11.glDisable(GL11.GL_CLIP_PLANE3); GL11.glDisable(GL11.GL_CLIP_PLANE2); GL11.glDisable(GL11.GL_CLIP_PLANE1); GL11.glDisable(GL11.GL_CLIP_PLANE0); } private void drawBlackBackground(float greyLevel) { GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glDisable(GL11.GL_TEXTURE_2D); final Tessellator tess = Tessellator.getInstance(); WorldRenderer worldRenderer = tess.getWorldRenderer(); GL11.glColor4f(greyLevel, greyLevel, greyLevel, 1.0F); worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); worldRenderer.pos(frameA, frameBy, 0.005F).endVertex(); worldRenderer.pos(frameBx, frameBy, 0.005F).endVertex(); worldRenderer.pos(frameBx, frameA, 0.005F).endVertex(); worldRenderer.pos(frameA, frameA, 0.005F).endVertex(); tess.draw(); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); GL11.glEnable(GL11.GL_TEXTURE_2D); } private void drawCelestialBodies(CelestialBody body, float ticks) { Star star = null; SolarSystem solarSystem = null; if (body instanceof Planet) { solarSystem = ((Planet) body).getParentSolarSystem(); } else if (body instanceof Moon) { solarSystem = ((Moon) body).getParentPlanet().getParentSolarSystem(); } else if (body instanceof Satellite) { solarSystem = ((Satellite) body).getParentPlanet().getParentSolarSystem(); } if (solarSystem == null) { solarSystem = GalacticraftCore.solarSystemSol; } star = solarSystem.getMainStar(); if (star != null && star.getBodyIcon() != null) { this.drawCelestialBody(star, 0F, 0F, ticks, 6F); } String mainSolarSystem = solarSystem.getUnlocalizedName(); for (Planet planet : GalaxyRegistry.getRegisteredPlanets().values()) { if (planet.getParentSolarSystem() != null && planet.getBodyIcon() != null) { if (planet.getParentSolarSystem().getUnlocalizedName().equalsIgnoreCase(mainSolarSystem)) { Vector3f pos = this.getCelestialBodyPosition(planet, ticks); this.drawCircle(planet); this.drawCelestialBody(planet, pos.x, pos.y, ticks, (planet.getRelativeDistanceFromCenter().unScaledDistance < 1.5F) ? 2F : 2.8F); } } } } private void drawCelestialBodiesZ(CelestialBody planet, float ticks) { this.drawCelestialBody(planet, 0F, 0F, ticks, 11F); for (Moon moon : GalaxyRegistry.getRegisteredMoons().values()) { if (moon.getParentPlanet() == planet && moon.getBodyIcon() != null) { Vector3f pos = this.getCelestialBodyPosition(moon, ticks); this.drawCircle(moon); this.drawCelestialBody(moon, pos.x, pos.y, ticks, 4F); } } for (Satellite satellite : GalaxyRegistry.getRegisteredSatellites().values()) { if (satellite.getParentPlanet() == planet) { Vector3f pos = this.getCelestialBodyPosition(satellite, ticks); this.drawCircle(satellite); this.drawCelestialBody(satellite, pos.x, pos.y, ticks, 3F); } } } private void drawTexturedRect(float x, float y, float width, float height) { Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldRenderer = tessellator.getWorldRenderer(); worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); worldRenderer.pos(x, y + height, 0F).tex(0, 1.0F).endVertex(); worldRenderer.pos(x + width, y + height, 0F).tex(1.0F, 1.0F).endVertex(); worldRenderer.pos(x + width, y, 0F).tex(1.0F, 0.0F).endVertex(); worldRenderer.pos(x, y, 0F).tex(0.0F, 0.0F).endVertex(); tessellator.draw(); } private void drawCelestialBody(CelestialBody planet, float xPos, float yPos, float ticks, float relSize) { if (xPos + centreX > frameBx || xPos + centreX < frameA) { return; } if (yPos + centreY > frameBy || yPos + centreY < frameA) { return; } GL11.glPushMatrix(); GL11.glTranslatef(xPos + centreX, yPos + centreY, 0F); float alpha = 1.0F; CelestialBodyRenderEvent.Pre preEvent = new CelestialBodyRenderEvent.Pre(planet, planet.getBodyIcon(), 12); MinecraftForge.EVENT_BUS.post(preEvent); GL11.glColor4f(1, 1, 1, alpha); if (preEvent.celestialBodyTexture != null) { this.renderEngine.bindTexture(preEvent.celestialBodyTexture); } if (!preEvent.isCanceled()) { float size = relSize / 70 * scale; this.drawTexturedRect(-size / 2, -size / 2, size, size); } CelestialBodyRenderEvent.Post postEvent = new CelestialBodyRenderEvent.Post(planet); MinecraftForge.EVENT_BUS.post(postEvent); GL11.glPopMatrix(); } private void drawCircle(CelestialBody cBody) { GL11.glPushMatrix(); GL11.glTranslatef(centreX, centreY, 0.002F); GL11.glDisable(GL11.GL_TEXTURE_2D); float sd = 0.002514F * scale; float x = this.getScale(cBody); float y = 0; float grey = 0.1F + 0.65F * Math.max(0F, (0.5F - x)); x = x * scale / sd; GL11.glColor4f(grey, grey, grey, 1.0F); GL11.glLineWidth(0.002F); GL11.glScalef(sd, sd, sd); CelestialBodyRenderEvent.CelestialRingRenderEvent.Pre preEvent = new CelestialBodyRenderEvent.CelestialRingRenderEvent.Pre(cBody, new Vector3f(0.0F, 0.0F, 0.0F)); MinecraftForge.EVENT_BUS.post(preEvent); if (!preEvent.isCanceled()) { GL11.glBegin(GL11.GL_LINE_LOOP); float temp; for (int i = 0; i < lineSegments; i++) { GL11.glVertex2f(x, y); temp = x; x = cos * x - sin * y; y = sin * temp + cos * y; } GL11.glEnd(); } CelestialBodyRenderEvent.CelestialRingRenderEvent.Post postEvent = new CelestialBodyRenderEvent.CelestialRingRenderEvent.Post(cBody); MinecraftForge.EVENT_BUS.post(postEvent); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glPopMatrix(); } private Vector3f getCelestialBodyPosition(CelestialBody cBody, float ticks) { float timeScale = cBody instanceof Planet ? 200.0F : 2.0F; float distanceFromCenter = this.getScale(cBody) * scale; return new Vector3f((float) Math.sin(ticks / (timeScale * cBody.getRelativeOrbitTime()) + cBody.getPhaseShift()) * distanceFromCenter, (float) Math.cos(ticks / (timeScale * cBody.getRelativeOrbitTime()) + cBody.getPhaseShift()) * distanceFromCenter, 0); } private float getScale(CelestialBody celestialBody) { float distance = celestialBody.getRelativeDistanceFromCenter().unScaledDistance; if (distance >= 1.375F) { if (distance >= 1.5F) { distance *= 1.15F; } else { distance += 0.075F; } } return 1 / 140.0F * distance * (celestialBody instanceof Planet ? 25.0F : 3.5F); } private void planeEquation(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3) { double[] result = new double[4]; result[0] = y1 * (z2 - z3) + y2 * (z3 - z1) + y3 * (z1 - z2); result[1] = z1 * (x2 - x3) + z2 * (x3 - x1) + z3 * (x1 - x2); result[2] = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2); result[3] = -(x1 * (y2 * z3 - y3 * z2) + x2 * (y3 * z1 - y1 * z3) + x3 * (y1 * z2 - y2 * z1)); planes.put(result, 0, 4); planes.position(0); } private void drawPlanetsTest(float ticks) { GL11.glPushMatrix(); GL11.glTranslatef(centreX, centreY, 0F); int id = (int) (ticks / 600F) % 5; RenderPlanet.renderID(id, scale, ticks); GL11.glPopMatrix(); } private void drawTexturedRectUV(float x, float y, float width, float height, float ticks) { for (int ysect = 0; ysect < 6; ysect++) { // drawTexturedRectUVSixth(x, y, width, height, (ticks / 600F) % 1F, ysect / 6F); float angle = 7.5F + 15F * ysect; drawTexturedRectUVSixth(x, y, width, height, (ticks / (900F - 80F * MathHelper.cos(angle))) % 1F, ysect / 6F); } } private void drawTexturedRectUVSixth(float x, float y, float width, float height, float prog, float y0) { y0 /= 2; prog = 1.0F - prog; float y1 = y0 + 1 / 12F; float y2 = 1F - y1; float y3 = 1F - y0; float yaa = y + height * y0; float yab = y + height * y1; float yba = y + height * y2; float ybb = y + height * y3; Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldRenderer = tessellator.getWorldRenderer(); if (prog <= 0.75F) { worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); worldRenderer.pos(x, yab, 0F).tex(prog, y1).endVertex(); worldRenderer.pos(x + width, yab, 0F).tex(prog + 0.25F, y1).endVertex(); worldRenderer.pos(x + width, yaa, 0F).tex(prog + 0.25F, y0).endVertex(); worldRenderer.pos(x, yaa, 0F).tex(prog, y0).endVertex(); tessellator.draw(); worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); worldRenderer.pos(x, ybb, 0F).tex(prog, y3).endVertex(); worldRenderer.pos(x + width, ybb, 0F).tex(prog + 0.25F, y3).endVertex(); worldRenderer.pos(x + width, yba, 0F).tex(prog + 0.25F, y2).endVertex(); worldRenderer.pos(x, yba, 0F).tex(prog, y2).endVertex(); tessellator.draw(); } else { double xp = x + width * (1F - prog) / 0.25F; worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); worldRenderer.pos(x, yab, 0F).tex(prog, y1).endVertex(); worldRenderer.pos(xp, yab, 0F).tex(1.0F, y1).endVertex(); worldRenderer.pos(xp, yaa, 0F).tex(1.0F, y0).endVertex(); worldRenderer.pos(x, yaa, 0F).tex(prog, y0).endVertex(); tessellator.draw(); worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); worldRenderer.pos(x, ybb, 0F).tex(prog, y3).endVertex(); worldRenderer.pos(xp, ybb, 0F).tex(1.0F, y3).endVertex(); worldRenderer.pos(xp, yba, 0F).tex(1.0F, y2).endVertex(); worldRenderer.pos(x, yba, 0F).tex(prog, y2).endVertex(); tessellator.draw(); worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); worldRenderer.pos(xp, yab, 0F).tex(0F, y1).endVertex(); worldRenderer.pos(x + width, yab, 0F).tex(prog - 0.75F, y1).endVertex(); worldRenderer.pos(x + width, yaa, 0F).tex(prog - 0.75F, y0).endVertex(); worldRenderer.pos(xp, yaa, 0F).tex(0F, y0).endVertex(); tessellator.draw(); worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); worldRenderer.pos(xp, ybb, 0F).tex(0F, y3).endVertex(); worldRenderer.pos(x + width, ybb, 0F).tex(prog - 0.75F, y3).endVertex(); worldRenderer.pos(x + width, yba, 0F).tex(prog - 0.75F, y2).endVertex(); worldRenderer.pos(xp, yba, 0F).tex(0F, y2).endVertex(); tessellator.draw(); } } }