//The Milky Way and Sol--by Maximilian Uriarte
//Click the planets!
// original galaxy code author : Philippe Guglielmetti (Dr. Goulu www.goulu.net)
// galaxy code was modified heavily to make it prettier and look more like the Milky Way, I just couldn't figure out the algorithm for the spiral alone
// textured sphere code adapted from processing.org example
// I really wanted to do all of the planets in 3D, but I couldn't figure out how to turn the textured sphere code into its own class,
// so I could only do one planet, so the others are just images.
import processing.opengl.*;
float pi=4*atan(1);
int mode = 0;
//solar system floats
PImage mercury,venus,mars,jupiter,uranus,neptune,saturn,sun;
float x,y;
float ex,ey,s;
float mx,my;
float vx,vy;
float Mx,My;
float jx,jy;
float satx,saty;
float ux,uy;
float nx,ny;
float ax,ay;
float ang;
float moonx,moony;
int stars=30000; //number of stars (far less than the 400 billion in real life)
int Rmax=350; // galaxy radius
float speed=0.004; // rotation speed
//galaxy floats
// stars follow elliptic orbits around the center
float eratio=.9020268; // ellipse ratio
float etwist=.028142858; // twisting factor (orbit axes depend on radius)
float []angle=new float[stars];
float []radius=new float[stars];
float cx; float cy; //center
float sx, sy;
//earth floats
PImage bg;
PImage texmap;
int sDetail = 35; // Sphere detail setting
float rotationX = 0;
float rotationY = 0;
float velocityX = 0;
float velocityY = 0;
float globeRadius = 450;
float pushBack = 0;
float[] c2x, c2z, sphereX, sphereY, sphereZ;
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION = 0.5;
int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION);
//
void setup(){
size(900,900,OPENGL);
background(0); // back to black
speed=speed/frameRate;
smooth();
//galaxy variables
// begin in the center
cx = width/2;
cy = height/2;
// itit stars
for (int i=0; i< stars; i++){
angle[i]= random(0,2*pi);
radius[i]=random(1,Rmax);
}
//solar system variables
mercury = loadImage("mercury.jpeg");
venus = loadImage("venus.jpeg");
mars = loadImage("mars.jpeg");
jupiter = loadImage("jupiter.jpeg");
saturn = loadImage("saturn.jpeg");
uranus = loadImage("uranus.jpeg");
neptune = loadImage("neptune.jpeg");
sun = loadImage("sun.jpeg");
ex = 0;
ey = 0;
mx = 0;
my = 0;
vx = 0;
vy = 0;
Mx = 0;
My = 0;
jx = 0;
jy = 0;
satx = 0;
saty = 0;
ux = 0;
uy = 0;
nx = 0;
ny = 0;
ax = 0;
ay = 0;
moonx = 0;
moony = 0;
ang = 0;
imageMode(CENTER);
//earth variables
texmap = loadImage("earth.png");
initializeSphere(sDetail);
}
void draw(){
background(0); // back to black
//info
if(mode == 0){
if(mousePressed == true){
fill(255);
text("Milky Way Galaxy",50,50);
text("Type: Barred Spiral Galaxy",50,75);
text("Stars: Est. 300-500 Billion",50,100);
text("Diameter: 100,000 Light Years",50,125);
text("Nearest Neigboring Galaxy: Andromeda",50,150);
text("Sol",450,630);
text("Perseus Arm", 400,700);
text("Scutum-Centaurus Arm",470,300);
text("Super-Massive Black Hole",390,520);
}
//solar system
if(mouseX > 400){
if(mouseX < 500){
if(mouseY > 600){
if(mouseY < 700){
text("Sol",450,630);
if(mousePressed == true){
mode = 1;
}
}
}
}
}
sx = 440;
sy = 620;
stroke(255);
noFill();
ellipse(sx, sy, 10,10);
//
stroke(255,255,255,150);
for (int i =0; i< stars; i++){
float r=radius[i];
float a=angle[i]+speed; // increment angle
angle[i]=a;
float x = r*sin(a);
float y= r*eratio*cos(a);
float b=r*etwist;
float s=sin(b);
float c=cos(b);
point(cx+s*x+c*y,cy+c*x-s*y); // a bit of trigo
}
for (int i =0; i< 200; i++){
float r=radius[i];
float a=angle[i]+speed; // increment angle
angle[i]=a;
float x = r*sin(a);
float y= r*eratio*cos(a);
float b=r*etwist;
float s=sin(b);
float c=cos(b);
noStroke();
fill(255,255,255,15);
ellipse(cx+s*x+c*y,cy+c*x-s*y,25,50); // a bit of trigo
}
for (int i =0; i< 300; i++){
float r=radius[i];
float a=angle[i]+speed; // increment angle
angle[i]=a;
float x = r*sin(a);
float y= r*eratio*cos(a);
float b=r*etwist;
float s=sin(b);
float c=cos(b);
noStroke();
fill(200,200,255,15);
ellipse(cx+s*x+c*y,cy+c*x-s*y+15,50,100); // a bit of trigo
}
for (int i =0; i< 50; i++){
float r=radius[i];
float a=angle[i]+speed; // increment angle
angle[i]=a;
float x = r*sin(a);
float y= r*eratio*cos(a);
float b=r*etwist;
float s=sin(b);
float c=cos(b);
noStroke();
fill(255,255,100,5);
ellipse(cx+s*x+c*y*2,cy+c*x-s*y+15,100,100); // a bit of trigo
}
}
if(mode == 1){
strokeWeight(.5);
background(0);
smooth();
//info
fill(255);
if(mousePressed == true){
text("Local Solar System 'Sol'",50,50);
text("Stars: 1",50,75);
text("Planets: 8 - 4 Solid, 4 Gaseous",50,100);
text("Dwarf Planets: 5",50,125);
}
//sun
fill(255,255,0);
noStroke();
ellipse(width/2,height/2,50,50);
if(mouseX > 425){ //begin rollover info
if(mouseX < 475){
if(mouseY > 425){
if(mouseY < 475){
noFill();
stroke(255);
line(450,450,470,490);
line(470,490,700,490);
text("Sun - Class: G2V Yellow Dwarf",475,485);
text("Diameter - 870,000 Miles",475,505);
noStroke();
if(mousePressed == true){
mode = 10;
}
}
}
}
}
if(mousePressed == true){ //sun mouse code
noFill();
stroke(255);
line(450,450,470,490);
line(470,490,700,490);
text("Sun - Class: G2V Yellow Dwarf",475,485);
text("Diameter - 870,000 Miles",475,505);
noStroke();
}
//earth
fill(5,255,23);
ex = cos(radians(ang++)) * 150 + width/2;
ey = sin(radians(ang)) * 150 + height/2;
ellipse(ex,ey,20,20);
if(mouseX > ex-50){ //begin rollover info
if(mouseX < ex+50){
if(mouseY > ey-50){
if(mouseY < ey+50){
noFill();
stroke(255);
ellipse(width/2,height/2,300,300);
line(ex,ey,ex+20,ey-10);
line(ex+20,ey-10,ex+200,ey-10);
text("Earth - Orbit 1 Earth Year", ex+25,ey-15);
text("Diameter - 7,926 Miles", ex+25,ey+5);
noStroke();
if(mousePressed == true){
mode = 2;
}
}
}
}
}
if(mousePressed == true){ //earth mouse code
noFill();
stroke(255);
ellipse(width/2,height/2,300,300);
line(ex,ey,ex+20,ey-10);
line(ex+20,ey-10,ex+200,ey-10);
text("Earth - Orbit 1 Earth Year", ex+25,ey-15);
text("Diameter - 7,926 Miles", ex+25,ey+5);
noStroke();
}
//earth moon
fill(250);
moonx = cos(radians(ex/2)) * 20 + ex;
moony = sin(radians(ey/2)) * 20 + ey;
ellipse(moonx,moony,10,10);
//mercury
fill(240);
mx = cos(radians(ang*4.16)) * 50 + width/2;
my = sin(radians(ang*4.16)) * 50 + height/2;
ellipse(mx,my,5,5);
noFill();
ellipse(width/2,height/2,50,50);
if(mouseX > mx-25){
if(mouseX < mx+25){
if(mouseY > my-25){
if(mouseY < my+25){
noFill();
stroke(255);
ellipse(width/2,height/2,100,100);
line(mx,my,mx+20,my-10);
line(mx+20,my-10,mx+200,my-10);
text("Mercury - Orbit .24 Earth Years", mx+25,my-15);
text("Diameter - 3,031 Miles",mx+25,my+5);
noStroke();
if(mousePressed == true){
mode = 3;
}
}
}
}
}
if(mousePressed == true){ //mercury mouse code
noFill();
stroke(255);
ellipse(width/2,height/2,100,100);
line(mx,my,mx+20,my-10);
line(mx+20,my-10,mx+200,my-10);
text("Mercury - Orbit .24 Earth Years", mx+25,my-15);
text("Diameter - 3,031 Miles",mx+25,my+5);
noStroke();
}
//venus
fill(233,237,41);
vx = cos(radians(ang*1.63)) * 100 + width/2;
vy = sin(radians(ang*1.63)) * 100 + height/2;
ellipse(vx,vy,18,18);
if(mouseX > vx-50){
if(mouseX < vx+50){
if(mouseY > vy-50){
if(mouseY < vy+50){
noFill();
stroke(255);
ellipse(width/2,height/2,200,200);
line(vx,vy,vx+20,vy-10);
line(vx+20,vy-10,vx+200,vy-10);
text("Venus - Orbit .62 Earth Years", vx+25,vy-15);
text("Diameter - 7,521 Miles",vx+25,vy+5);
noStroke();
if(mousePressed == true){
mode = 4;
}
}
}
}
}
if(mousePressed == true){ //venus mouse code
noFill();
stroke(255);
ellipse(width/2,height/2,200,200);
line(vx,vy,vx+20,vy-10);
line(vx+20,vy-10,vx+200,vy-10);
text("Venus - Orbit .62 Earth Years", vx+25,vy-15);
text("Diameter - 7,521 Miles",vx+25,vy+5);
noStroke();
}
//mars
fill(183,32,24);
Mx = cos(radians(ang*.53)) * 200 + width/2;
My = sin(radians(ang*.53)) * 200 + height/2;
ellipse(Mx,My,15,15);
if(mouseX > Mx-50){
if(mouseX < Mx+50){
if(mouseY > My-50){
if(mouseY < My+50){
noFill();
stroke(255);
ellipse(width/2,height/2,400,400);
line(Mx,My,Mx+20,My-10);
line(Mx+20,My-10,Mx+200,My-10);
text("Mars - Orbit 1.8 Earth Years", Mx+25,My-15);
text("Diameter - 4,220 Miles",Mx+25,My+5);
noStroke();
if(mousePressed == true){
mode = 5;
}
}
}
}
}
if(mousePressed == true){ //mars mouse code
noFill();
stroke(255);
ellipse(width/2,height/2,400,400);
line(Mx,My,Mx+20,My-10);
line(Mx+20,My-10,Mx+200,My-10);
text("Mars - Orbit 1.8 Earth Years", Mx+25,My-15);
text("Diameter - 4,220 Miles",Mx+25,My+5);
noStroke();
}
//jupiter
fill(180,157,109);
jx = cos(radians(ang*.08)) * 300 + width/2;
jy = sin(radians(ang*.08)) * 300 + height/2;
ellipse(jx,jy,40,40);
if(mouseX > jx-50){
if(mouseX < jx+50){
if(mouseY > jy-50){
if(mouseY < jy+50){
noFill();
stroke(255);
ellipse(width/2,height/2,600,600);
line(jx,jy,jx+20,jy-10);
line(jx+20,jy-10,jx+200,jy-10);
text("Jupiter - Orbit 11.86 Earth Years", jx+25,jy-15);
text("Diameter - 88,700 Miles",jx+25,jy+5);
noStroke();
if(mousePressed == true){
mode = 6;
}
}
}
}
}
if(mousePressed == true){ //jupiter mouse code
noFill();
stroke(255);
ellipse(width/2,height/2,600,600);
line(jx,jy,jx+20,jy-10);
line(jx+20,jy-10,jx+200,jy-10);
text("Jupiter - Orbit 11.86 Earth Years", jx+25,jy-15);
text("Diameter - 88,700 Miles",jx+25,jy+5);
noStroke();
}
//saturn
fill(214,145,6);
satx = cos(radians(ang*.033)) * 350 + width/2;
saty = sin(radians(ang*.033)) * 350 + height/2;
ellipse(satx,saty,30,30);
noFill();
stroke(255);
ellipse(satx,saty,50,25);
noStroke();
if(mouseX > satx-30){
if(mouseX < satx+30){
if(mouseY > saty-30){
if(mouseY < saty+30){
noFill();
stroke(255);
ellipse(width/2,height/2,700,700);
line(satx,saty,satx-20,saty+10);
line(satx-20,saty+10,satx-250,saty+10);
text("Saturn - Orbit 29.45 Earth Years", satx-235,saty+5);
text("Diameter - 74,898 Miles", satx-235,saty+25);
noStroke();
if(mousePressed == true){
mode = 7;
}
}
}
}
}
if(mousePressed == true){ //Saturn mouse code
noFill();
stroke(255);
ellipse(width/2,height/2,700,700);
line(satx,saty,satx-20,saty+10);
line(satx-20,saty+10,satx-250,saty+10);
text("Saturn - Orbit 29.45 Earth Years", satx-235,saty+5);
text("Diameter - 74,898 Miles", satx-235,saty+25);
noStroke();
}
//uranus
fill(73,151,227);
ux = cos(radians(ang*.011)) * 400 + width/2;
uy = sin(radians(ang*.011)) * 400 + height/2;
ellipse(ux,uy,25,25);
if(mouseX > ux-20){
if(mouseX < ux+20){
if(mouseY > uy-20){
if(mouseY < uy+20){
noFill();
stroke(255);
ellipse(width/2,height/2,800,800);
line(ux,uy,ux-20,uy+10);
line(ux-20,uy+10,ux-250,uy+10);
text("Uranus - Orbit 84.32 Earth Years", ux-235,uy+5);
text("Diameter - 31,763 Miles", ux-235,uy+25);
noStroke();
if(mousePressed == true){
mode = 8;
}
}
}
}
}
if(mousePressed == true){ //Uranus mouse code
noFill();
stroke(255);
ellipse(width/2,height/2,800,800);
line(ux,uy,ux-20,uy+10);
line(ux-20,uy+10,ux-250,uy+10);
text("Uranus - Orbit 84.32 Earth Years", ux-235,uy+5);
text("Diameter - 31,763 Miles", ux-235,uy+25);
noStroke();
}
//neptune
fill(10,92,250);
nx = cos(radians(ang*.006)) * 430 + width/2;
ny = sin(radians(ang*.006)) * 430 + height/2;
ellipse(nx,ny,25,25);
if(mouseX > nx-20){
if(mouseX < nx+20){
if(mouseY > ny-20){
if(mouseY < ny+20){
noFill();
stroke(255);
ellipse(width/2,height/2,860,860);
line(nx,ny,nx-20,ny+10);
line(nx-20,ny+10,nx-250,ny+10);
text("Neptune - Orbit 164.79 Earth Years", nx-235,ny+5);
text("Diameter - 30,775 Miles",nx-235,ny+25);
noStroke();
if(mousePressed == true){
mode = 9;
}
}
}
}
}
if(mousePressed == true){ //Neptune Mouse Code
noFill();
stroke(255);
ellipse(width/2,height/2,860,860);
line(nx,ny,nx-20,ny+10);
line(nx-20,ny+10,nx-250,ny+10);
text("Neptune - Orbit 164.79 Earth Years", nx-235,ny+5);
text("Diameter - 30,775 Miles",nx-235,ny+25);
noStroke();
}
//back button
noFill();
stroke(255);
rect(700,50,50,20);
fill(255);
text("BACK",710,65);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 50){
if(mouseY < 70){
if(mousePressed == true){
mode = 0;
}
}
}
}
}
}
if(mode == 2){
//background(0);
renderGlobe();
if(mousePressed == true){
text("Earth",50,100);
text("Moons: 1",50,125);
text("Diameter: 7,926 Miles",50,150);
text("Population: 7 Billion Humans",50,175);
text("7 Continental Land Masses", 50, 200);
}
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//mercury
if(mode == 3){
image(mercury, height/2,width/2,100,100);
text("Mercury",50,100);
text("Diameter: 3,031 Miles",50,125);
text("Moons: 0",50,150);
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//venus
if(mode == 4){
image(venus,width/2,height/2,300,300);
text("Venus",50,100);
text("Diameter: 7,521 Miles",50,125);
text("Moons: 0",50,150);
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//mars
if(mode == 5){
image(mars,width/2,height/2,250,250);
text("Mars",50,100);
text("Diameter: 4,220 Miles",50,125);
text("Moons: 2",50,150);
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//jupiter
if(mode == 6){
image(jupiter,width/2,height/2,650,650);
text("Jupiter",50,100);
text("Diameter: 88,700 Miles",50,125);
text("Moons: 64",50,150);
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//saturn
if(mode == 7){
image(saturn,width/2,height/2,670,600);
text("Saturn",50,100);
text("Diameter: 74,898 Miles",50,125);
text("Moons: 62",50,150);
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//Uranus
if(mode == 8){
image(uranus,width/2,height/2,400,900);
text("Uranus",50,100);
text("Diameter: 31,763 Miles",50,125);
text("Moons: 27",50,150);
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//Neptune
if(mode == 9){
image(neptune,width/2,height/2,500,500);
text("Neptune",50,100);
text("Diameter: 30,775",50,125);
text("Moons: 13", 50,150);
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//Sun
if(mode == 10){
image(sun,height/2,width/2,900,900);
text("Sun",50,100);
text("Diameter: 870,000 Miles",50,125);
text("Class G2V Yellow Dwarf Star",50,150);
text("Orbiting Planets: 8 Primary",50,175);
text("Age: 4.57 Billion Years",50,200);
//back button
noFill();
stroke(255);
rect(700,700,50,20);
text("BACK",710,715);
if(mouseX > 700){
if(mouseX < 750){
if(mouseY > 700){
if(mouseY < 720){
if(mousePressed == true){
mode = 1;
}
}
}
}
}
}
//closes draw loop
}
//sphere code
void renderGlobe() {
pushMatrix();
translate(width/2.0, height/2.0, pushBack);
pushMatrix();
noFill();
stroke(255,200);
strokeWeight(2);
smooth();
popMatrix();
lights();
pushMatrix();
rotateX( radians(-rotationX) );
rotateY( radians(270 - rotationY) );
fill(200);
noStroke();
textureMode(IMAGE);
texturedSphere(globeRadius, texmap);
popMatrix();
popMatrix();
rotationX += velocityX;
rotationY += velocityY;
velocityX *= 0.95;
velocityY *= 0.95;
//Implements mouse control (interaction will be inverse when sphere is upside down)
if(mousePressed){
velocityX += (mouseY-pmouseY) * 0.01;
velocityY -= (mouseX-pmouseX) * 0.01;
}
}
void initializeSphere(int res)
{
sinLUT = new float[SINCOS_LENGTH];
cosLUT = new float[SINCOS_LENGTH];
for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
}
float delta = (float)SINCOS_LENGTH/res;
float[] c2x = new float[res];
float[] c2z = new float[res];
// Calc unit circle in XZ plane
for (int i = 0; i < res; i++) {
c2x[i] = -cosLUT[(int) (i*delta) % SINCOS_LENGTH];
c2z[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
}
// Computing vertexlist vertexlist starts at south pole
int vertCount = res * (res-1) + 2;
int currVert = 0;
// Re-init arrays to store vertices
sphereX = new float[vertCount];
sphereY = new float[vertCount];
sphereZ = new float[vertCount];
float angle_step = (SINCOS_LENGTH*0.5f)/res;
float angle = angle_step;
// Step along Y axis
for (int i = 1; i < res; i++) {
float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
for (int j = 0; j < res; j++) {
sphereX[currVert] = c2x[j] * curradius;
sphereY[currVert] = currY;
sphereZ[currVert++] = c2z[j] * curradius;
}
angle += angle_step;
}
sDetail = res;
}
// Generic routine to draw textured sphere
void texturedSphere(float r, PImage t)
{
int v1,v11,v2;
r = (r + 240 ) * 0.33;
beginShape(TRIANGLE_STRIP);
texture(t);
float iu=(float)(t.width-1)/(sDetail);
float iv=(float)(t.height-1)/(sDetail);
float u=0,v=iv;
for (int i = 0; i < sDetail; i++) {
vertex(0, -r, 0,u,0);
vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v);
u+=iu;
}
vertex(0, -r, 0,u,0);
vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v);
endShape();
// Middle rings
int voff = 0;
for(int i = 2; i < sDetail; i++) {
v1=v11=voff;
voff += sDetail;
v2=voff;
u=0;
beginShape(TRIANGLE_STRIP);
texture(t);
for (int j = 0; j < sDetail; j++) {
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v+iv);
u+=iu;
}
// Close each ring
v1=v11;
v2=voff;
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v+iv);
endShape();
v+=iv;
}
u=0;
// Add the northern cap
beginShape(TRIANGLE_STRIP);
texture(t);
for (int i = 0; i < sDetail; i++) {
v2 = voff + i;
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v);
vertex(0, r, 0,u,v+iv);
u+=iu;
}
vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v);
endShape();
}
An enhanced version of my midterm that includes the Milky Way galaxy and more in-depth looks at each planet of our solar system! Click the planets!