package com.team.futurecraft.space; import static org.lwjgl.opengl.GL11.glLineWidth; import static org.lwjgl.opengl.GL11.glPopMatrix; import static org.lwjgl.opengl.GL11.glPushMatrix; import java.util.ArrayList; import org.lwjgl.opengl.GL11; import com.team.futurecraft.Mat4f; import com.team.futurecraft.Vec3f; import com.team.futurecraft.Vec4f; import com.team.futurecraft.rendering.Camera; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; /** * Represents any celestial object (stars, planets, moons, asteroids, etc). * * @author Joseph */ public abstract class CelestialObject { private ArrayList<CelestialObject> children = new ArrayList<CelestialObject>(); private CelestialObject parent; public OrbitalParameters orbit; public PhysicalParameters physical; public String name = "Planet"; public CelestialObject(CelestialObject parent) { this.parent = parent; this.orbit = new OrbitalParameters(63082454400L, 0, 149f, 0, 0, 0, 0, 0); this.physical = new PhysicalParameters(1, 0.00470989f, 0, 1, 0, 0, 0); } /** * Adds an object to orbit this object. This should be called inside the constructor. */ public void add(CelestialObject object) { children.add(object); } /** * Gets the type of this object. Either PLANET, or STAR. */ public abstract EnumCelestialType getType(); /** * Renders the planet by itself without calculating orbits or anything. * Used for rendering planets on gui buttons. */ public abstract void renderStatic(Minecraft mc); /** * Called when this object is rendered in space. */ public abstract void render(Camera cam, float time); /** * Returns if this object has a dimension you can travel to. */ public abstract boolean isLandable(); public void renderOrbits(float time) { Tessellator tessellator = Tessellator.getInstance(); WorldRenderer renderer = tessellator.getWorldRenderer(); GL11.glDepthMask(false); GlStateManager.disableTexture2D(); GlStateManager.disableLighting(); if (this.getParent() != null) { glPushMatrix(); float parentObliquity = this.getParent().physical.obliquity; float parentEqAscNode = this.getParent().physical.eqAscNode; Vec3f parentPos = this.getParent().getPosition(time); GL11.glTranslated(parentPos.x, parentPos.y, parentPos.z); GL11.glRotatef(parentEqAscNode, 0F, 1F, 0F); GL11.glRotatef(parentObliquity, 0F, 0F, 1F); GL11.glRotatef(this.orbit.ascendingNode, 0, 1, 0); GL11.glRotatef(this.orbit.inclination, 0, 0, 1); GL11.glRotatef(this.orbit.argOfPericenter, 0, 1, 0); GL11.glTranslated(0, 0, - (this.orbit.semiMajorAxis * this.orbit.eccentricity)); GL11.glScalef((1 - this.orbit.eccentricity), 1, 1); GL11.glRotatef((((time - this.orbit.epoch) / 86400) / this.orbit.period * 360) + this.orbit.meanAnomaly - 90, 0F, 1F, 0F); GlStateManager.enableAlpha(); glLineWidth(1); renderer.startDrawing(3); Vec3f color = new Vec3f(0, 150, 0); if (this.parent.getType() == EnumCelestialType.PLANET || this.parent.getType() == EnumCelestialType.BARYCENTER) { color = new Vec3f(150, 75, 0); } for (int k = 0; k < 360; k++) { renderer.setColorRGBA((int)color.x, (int)color.y, (int)color.z, (int)(((330 - k) / 200.0f) * 255)); double radians = Math.toRadians(k); renderer.addVertex((Math.cos(radians) * this.orbit.semiMajorAxis), 0, Math.sin(radians) * this.orbit.semiMajorAxis); } tessellator.draw(); glPopMatrix(); } Vec3f pos = this.getPosition(time); glPushMatrix(); GL11.glTranslated(pos.x, pos.y, pos.z); renderer.startDrawing(3); renderer.setColorRGBA(150, 0, 0, 255); renderer.addVertex(0, 0, 0); renderer.addVertex(0, 0, this.physical.diameter / 1000000); tessellator.draw(); glPopMatrix(); GlStateManager.enableTexture2D(); GlStateManager.enableLighting(); CelestialObject[] children = this.getChildren(); for (int i = 0; i < children.length; i++) { children[i].renderOrbits(time); } GL11.glDepthMask(true); } public Vec3f getPosition(float time) { Vec3f offsetPos = new Vec3f(0, 0, 0); if (this.orbit != null && this.parent != null) { Vec3f parentPos = this.getParent().getPosition(time); float parentObliquity = this.getParent().physical.obliquity; float parentEqAscNode = this.getParent().physical.eqAscNode; Mat4f mat = new Mat4f(); mat = mat.multiply(Mat4f.translate(parentPos.x, parentPos.y, parentPos.z)); mat = mat.multiply(Mat4f.rotate(parentEqAscNode, 0F, 1F, 0F)); mat = mat.multiply(Mat4f.rotate(parentObliquity, 0F, 0F, 1F)); mat = mat.multiply(Mat4f.rotate(this.orbit.ascendingNode, 0, 1, 0)); mat = mat.multiply(Mat4f.rotate(this.orbit.inclination, 0, 0, 1)); mat = mat.multiply(Mat4f.rotate(this.orbit.argOfPericenter, 0, 1, 0)); mat = mat.multiply(Mat4f.translate(0, 0, -(this.orbit.semiMajorAxis * this.orbit.eccentricity))); mat = mat.multiply(Mat4f.scale((1 - this.orbit.eccentricity), 1, 1)); double radians = Math.toRadians(-(((time - this.orbit.epoch) / 86400) / this.orbit.period * 360) - this.orbit.meanAnomaly + 90); Vec3f orbitPos = new Vec3f(Math.cos(radians) * this.orbit.semiMajorAxis, 0, Math.sin(radians) * this.orbit.semiMajorAxis); Vec4f finalPos = mat.multiply(new Vec4f(orbitPos, 1)); return new Vec3f(finalPos.x, finalPos.y, finalPos.z); } return offsetPos; } //TODO: this is soooo outdated now public Vec3f getDirection(float time) { if (this.orbit != null) return new Vec3f(-1, 1, 0).rotateYaw((float) Math.toRadians(time * this.physical.rotationPeriod)); else return new Vec3f(-1, 1, 0); } public void init() { this.initChildren(); } public void initChildren() { CelestialObject[] children = this.getChildren(); for (int i = 0; i < children.length; i++) { children[i].init(); } } /** * Calls render for all this object's children. */ public void renderChildren(Camera cam, float time) { CelestialObject[] children = this.getChildren(); for (int i = 0; i < children.length; i++) { children[i].render(cam, time); } } /** * Gets a list of all children. */ public CelestialObject[] getChildren() { return this.children.toArray(new CelestialObject[] {}); } /** * Gets this object's parent. */ public CelestialObject getParent() { return this.parent; } }