/***************************************************************************
* Copyright (C) 2008 by Lorenzo La Porta *
* lorelapo@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define D2(p1, p2) ((p1.position.x-p2.position.x)*(p1.position.x-p2.position.x)+\
(p1.position.y-p2.position.y)*(p1.position.y-p2.position.y)+\
(p1.position.z-p2.position.z)*(p1.position.z-p2.position.z))
#define G 6.67428e-11
#define ZOOM 1e-11
#define N 9
typedef long double float_t;
typedef struct __vector
{
float_t x, y, z;
} vector;
typedef struct __planetary_body
{
vector position;
vector speed;
float_t r, g, b;
float_t mass;
float_t radius;
} planet;
float k=.2, DELTA = 10000, pr=700.0;
planet ssp[N], sun;
/* GLUT callback Handlers */
static void resize(int width, int height)
{
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 10000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
static void display(void)
{
int i;
glColor3d(1, 1, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0*k, 0.0*k, 20.0*k, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
glPushMatrix();
glPushMatrix();
glTranslated(ZOOM*sun.position.x,ZOOM*sun.position.y,ZOOM*sun.position.z);
glutSolidSphere(ZOOM*sun.radius,20,20);
glPopMatrix();
glColor3d(1, 0, 0);
for(i=0;i<N;i++)
{
glColor3f(ssp[i].r, ssp[i].g, ssp[i].b);
glPushMatrix();
glTranslated(ZOOM*ssp[i].position.x,ZOOM*ssp[i].position.y,ZOOM*ssp[i].position.z*(i==3?1.1:1.0));
glutSolidSphere(pr*ZOOM*ssp[i].radius,20,20);
glPopMatrix();
}
glPopMatrix();
glutSwapBuffers();
}
static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 27 :
case 'q':
exit(0);
break;
case 'a':
DELTA+=100;
break;
case 's':
DELTA-=100;
break;
case 'z':
pr+=100;
break;
case 'x':
pr-=100;
break;
case '+':
k-=0.01;
break;
case '-':
k+=0.01;
break;
default:
}
glutPostRedisplay();
}
void initData(void)
{
int i;
/*inizializza pianeti e sole*/
sun.position.x=0.0;
sun.position.y=0.0;
sun.position.z=0.0;
sun.speed.x=0.0;
sun.speed.y=0.0;
sun.speed.z=0.0;
sun.mass=1.9891e30;
sun.radius=6e9;
FILE *fp=fopen("/root/GLUTex/bin/Debug/Planet.txt", "rt");
if(fp==NULL)
{
printf("NO DATA FILE FOUND in %s\n",__FILE__
);
exit(1);
}
for(i=0;i<N;i++)
{
fscanf(fp,"(%Lg;%Lg;%Lg)\n",&ssp[i].position.x,&ssp[i].position.y,&ssp[i].position.z);
fscanf(fp,"(%Lg;%Lg;%Lg)\n",&ssp[i].speed.x,&ssp[i].speed.y,&ssp[i].speed.z);
fscanf(fp,"(%Lg;%Lg;%Lg)\n",&ssp[i].r,&ssp[i].g,&ssp[i].b);
fscanf(fp,"%Lg\n",&ssp[i].mass);
fscanf(fp,"%Lg\n",&ssp[i].radius);
}
fclose(fp);
}
float gravPwr(planet p1, planet p2)
{
float_t d2=D2(p1,p2),
mp=p1.mass*p2.mass*G;
return mp/d2;
}
float ang1(planet p1, planet p2)
{
float_t ang=atan2(p1.position.y-p2.position.y, p1.position.x-p2.position.x);
return ang;
}
float ang2(planet p1, planet p2)
{
float_t ang=atan2(p1.position.y-p2.position.y, p1.position.z-p2.position.z);
return ang;
}
float ang3(planet p1, planet p2)
{
float_t ang=atan2(p1.position.z-p2.position.z, p1.position.x-p2.position.x);
return ang;
}
static void idle(void)
{
/*
*differenzia la posizione dei pianeti
*/
int i,j;
float_t pwr, ang;
for(i=0;i<N;i++)
{
pwr=gravPwr(sun, ssp[i]);
//printf("%Lg\n",pwr);
ang=ang1(sun,ssp[i]);
sun.speed.y-=DELTA*sin(ang)*pwr/sun.mass;
sun.speed.x-=DELTA*cos(ang)*pwr/sun.mass;
ssp[i].speed.y+=DELTA*sin(ang)*pwr/ssp[i].mass;
ssp[i].speed.x+=DELTA*cos(ang)*pwr/ssp[i].mass;
ang=ang2(sun,ssp[i]);
//sun.speed.y+=DELTA*sin(ang)*pwr/sun.mass;
sun.speed.z-=DELTA*cos(ang)*pwr/sun.mass;
// ssp[i].speed.y+=DELTA*sin(ang)*pwr/ssp[i].mass;
ssp[i].speed.z+=DELTA*cos(ang)*pwr/ssp[i].mass;
/* ang=ang3(sun,ssp[i]);
sun.speed.z+=DELTA*sin(ang)*pwr/sun.mass;
sun.speed.x+=DELTA*cos(ang)*pwr/sun.mass;
ssp[i].speed.z+=DELTA*sin(ang)*pwr/ssp[i].mass;
ssp[i].speed.x+=DELTA*cos(ang)*pwr/ssp[i].mass;*/
}
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(i==j)continue;
pwr=gravPwr(ssp[j], ssp[i]);
//printf("%Lg\n",pwr);
ang=ang1(ssp[j],ssp[i]);
ssp[j].speed.y-=DELTA*sin(ang)*pwr/ssp[j].mass;
ssp[j].speed.x-=DELTA*cos(ang)*pwr/ssp[j].mass;
/*ssp[i].speed.y+=DELTA*sin(ang)*pwr/ssp[i].mass;
ssp[i].speed.x+=DELTA*cos(ang)*pwr/ssp[i].mass;*/
ang=ang2(ssp[j],ssp[i]);
//sun.speed.y+=DELTA*sin(ang)*pwr/sun.mass;
ssp[j].speed.z-=DELTA*cos(ang)*pwr/ssp[j].mass;
//ssp[i].speed.y+=DELTA*sin(ang)*pwr/ssp[i].mass;
// ssp[i].speed.z+=DELTA*cos(ang)*pwr/ssp[i].mass;
/*ang=ang3(sun,ssp[i]);
sun.speed.z+=DELTA*sin(ang)*pwr/sun.mass;
sun.speed.x+=DELTA*cos(ang)*pwr/sun.mass;
ssp[i].speed.z+=DELTA*sin(ang)*pwr/ssp[i].mass;
ssp[i].speed.x+=DELTA*cos(ang)*pwr/ssp[i].mass;*/
}
}
for(i=0;i<N;i++)
{
ssp[i].position.x+=DELTA*ssp[i].speed.x;
ssp[i].position.y+=DELTA*ssp[i].speed.y;
ssp[i].position.z+=DELTA*ssp[i].speed.z;
}
sun.position.x+=DELTA*sun.speed.x;
sun.position.y+=DELTA*sun.speed.y;
sun.position.z+=DELTA*sun.speed.z;
glutPostRedisplay();
}
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 100.0f };
/* Program entry point */
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Solar System");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idle);
glClearColor(0,0,0,0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
initData();
glutMainLoop();
return EXIT_SUCCESS;
}