home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gambler 19
/
GAMBLERCD19.BIN
/
UTILS
/
RIVA128
/
Uzytki
/
ssystem-1.2
/
SOURCE
/
SSYSTEM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-02
|
16KB
|
547 lines
#include <time.h>
#ifndef WIN32
#include <sys/times.h>
#endif
#include "planets.h"
#define TIMEFUNC clock()
#define WIDTH 640
#define HEIGHT 480
GLdouble camx=0.0, camy=0.0, camz=1.0, eyex=0.0, eyey=0.0, eyez=-1.0;
GLdouble upx=0.0, upy=1.0, upz=0.0,speed=0.0,d;
int frames=0,i,pause=0,linked=1,currplanet=EARTH,width=WIDTH,height=HEIGHT;
int demomode=0,bench=0,help=0,fakecurrplanet=EARTH;
float sec;
char sbuf[80];
int planorder[RINGS]={SUN,MERCURY,VENUS,EARTH,MOON,MARS,JUPITER,IO,EUROPA,
GANYMEDE,CALLISTO,SATURN,TETHYS,DIONE,RHEA,TITAN,URANUS,NEPTUNE,TRITON,
PLUTO,CHARON};
static void Reshape( int x, int y )
{
width=x;
height=y;
glViewport( 0, 0, width, height );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,width/(float)height,RADIUSSCALE(0.1),DISTCORRECTION(1000.0));
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
/* Cloned from David Bucciarelli's demos */
static void printstring(void *font, char *string)
{
int len,i;
len=(int)strlen(string);
for(i=0;i<len;i++)
glutBitmapCharacter(font,string[i]);
}
static void OnScreenInfo()
{
time_t t;
struct tm *tm;
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,(float) width,(float) height,0.0,0.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(1.0,1.0,1.0);
glRasterPos2i(0,10);
printstring(GLUT_BITMAP_HELVETICA_10,planets[currplanet].Name);
glRasterPos2i(0,20);
t=(int) ((10093.0+days)*24.0*3600.0);
tm=gmtime(&t);
strftime(sbuf,80,"%m / %d / %Y %X (UTC)",tm);
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(0,30);
sprintf(sbuf,"Distance from Sun (million Km): %.2f",DISTANCE(planets[currplanet].posx,
planets[currplanet].posy,planets[currplanet].posz)*100.0);
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(0,height-5);
sprintf(sbuf,"Camera distance from Sun (million Km): %.2f",DISTANCE(camx,camy,camz)*100.0);
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(0,height-15);
sprintf(sbuf,"Time factor: %.4f hours / iteration",timefactor*60.0);
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(0,height-25);
sprintf(sbuf,"Camera speed (Km / iteration): %.2f",speed*100000000.0);
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width-70,height-5);
if (linked) printstring(GLUT_BITMAP_HELVETICA_10,"Linked Camera");
else printstring(GLUT_BITMAP_HELVETICA_10,"Free Camera");
if (demomode) {
glRasterPos2i(width-70,height-15);
printstring(GLUT_BITMAP_HELVETICA_10,"Demo Mode");
}
if (pause) {
glRasterPos2i(width-30,10);
printstring(GLUT_BITMAP_HELVETICA_10,"Pause");
}
if (help) {
glRasterPos2i(width/4,height/4);
sprintf(sbuf,"Home/End: Select previous/next body");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+15);
sprintf(sbuf,"t : Texture on/off");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+30);
sprintf(sbuf,"l : Lighting on/off");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+45);
sprintf(sbuf,"f : Flat/Smooth shading model");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+60);
sprintf(sbuf,"s : Stars on/off");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+75);
sprintf(sbuf,"d : Demo mode on/off");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+90);
sprintf(sbuf,"n : Place camera near current target planet");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+105);
sprintf(sbuf,"c : Toggle between free and linked to planet camera mode");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+120);
sprintf(sbuf,"p : Pause");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+135);
sprintf(sbuf,"+/- : Increase/Decrease timefactor *");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+150);
sprintf(sbuf,"Arrow keys : Camera rotation *");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+165);
sprintf(sbuf,"Page Up/Down : Increase/decrease speed *");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
glRasterPos2i(width/4,height/4+195);
sprintf(sbuf,"* hold SHIFT for faster operation");
printstring(GLUT_BITMAP_HELVETICA_10,sbuf);
}
Reshape(width,height);
}
static void Idle( void )
{
if (bench & (frames==1000)) {
sec=(TIMEFUNC-sec)/(float)CLOCKS_PER_SEC;
#ifdef WIN32
sprintf(sbuf,"\n%.2f frames/sec\n\n",frames/sec);
MessageBox(NULL,sbuf,"Overall Performance", MB_OK);
#else
printf("\n%.2f frames/sec\n\n",frames/sec);
#endif
exit(2);
}
if (!pause) {
days+=timefactor;
UpdatePositions();
}
if (linked) {
eyex=planets[currplanet].posx-camx;
eyey=planets[currplanet].posy-camy;
eyez=planets[currplanet].posz-camz;
d=DISTANCE(eyex,eyey,eyez);
eyex/=d; eyey/=d; eyez/=d;
if (d<RADIUSSCALE(planets[currplanet].Radius*1.5)) speed*=(double)demomode;
}
camx+=eyex*speed; camy+=eyey*speed; camz+=eyez*speed;
glutPostRedisplay();
}
/* Rotates (rx,ry,rz) point about the (x,y,z) axis 'angle' radians,
borrowed from Mesa */
void Rotation( GLdouble angle, GLdouble x, GLdouble y, GLdouble z,
GLdouble *rx, GLdouble *ry, GLdouble *rz)
{
GLdouble mag, s, c;
GLdouble xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
s = sin(angle);
c = cos(angle);
mag = DISTANCE(x,y,z);
if (mag == 0.0) return;
x /= mag;
y /= mag;
z /= mag;
xx = x * x;
yy = y * y;
zz = z * z;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * s;
ys = y * s;
zs = z * s;
one_c = 1.0F - c;
x = *rx*((one_c * xx) + c);
y = *rx*((one_c * xy) - zs);
z = *rx*((one_c * zx) + ys);
x += *ry*((one_c * xy) + zs);
y += *ry*((one_c * yy) + c);
z += *ry*((one_c * yz) - xs);
x += *rz*((one_c * zx) - ys);
y += *rz*((one_c * yz) + xs);
z += *rz*((one_c * zz) + c);
*rx=x; *ry=y; *rz=z;
}
/* Separate function for future enhancements */
static void Camera()
{
gluLookAt(camx,camy,camz,
camx+eyex,camy+eyey,camz+eyez,
upx, upy, upz);
}
static void SunHalo( void )
{
static double x[4],y[4],z[4];
static double alfa,beta;
static int i;
#define SIZE RADIUSSCALE(109.0)
x[0]=x[3]=y[0]=y[1]=SIZE;
x[1]=x[2]=y[2]=y[3]=-SIZE;
z[0]=z[1]=z[2]=z[3]=0.0;
alfa=atan2(camz,camx)-PI/2.0;
beta=atan2(camy,sqrt(camx*camx+camz*camz));
for (i=0;i<4;i++) {
Rotation(beta,1.0,0.0,0.0,&x[i],&y[i],&z[i]);
Rotation(alfa,0.0,1.0,0.0,&x[i],&y[i],&z[i]);
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glBegin(GL_POLYGON);
glTexCoord2f(0.0,0.0); glVertex3f(x[0],y[0],z[0]);
glTexCoord2f(0.0,1.0); glVertex3f(x[1],y[1],z[1]);
glTexCoord2f(1.0,1.0); glVertex3f(x[2],y[2],z[2]);
glTexCoord2f(1.0,0.0); glVertex3f(x[3],y[3],z[3]);
glEnd();
glDisable(GL_BLEND);
}
static void Display( void )
{
glEnable(GL_DEPTH_TEST);
glLoadIdentity();
Camera();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
if (drawstars) {
glPushMatrix();
glCallList(Stars);
glPopMatrix();
}
if (lighting) glEnable(GL_LIGHTING);
if (texture) glEnable(GL_TEXTURE_2D);
LightPos[0]=planets[SUN].posx;
LightPos[1]=planets[SUN].posy;
LightPos[2]=planets[SUN].posz;
glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
glMaterialfv(GL_FRONT, GL_DIFFUSE, White);
glMaterialfv(GL_FRONT, GL_EMISSION, Black);
for (i=1;i<=RINGS;i++) {
glBindTexture(GL_TEXTURE_2D, texName[i]);
glPushMatrix();
glTranslatef(planets[i].posx,planets[i].posy,planets[i].posz);
glRotatef(-planets[i].Degrees-planets[planets[i].Sat].Degrees-90.0,1.0,0.0,0.0);
glRotatef(planets[i].DeltaRotation,0.0,0.0,1.0);
glCallList(planets[i].Sphere);
glPopMatrix();
}
glMaterialfv(GL_FRONT, GL_EMISSION, White);
glBindTexture(GL_TEXTURE_2D, texName[SUN]);
glPushMatrix();
if (texture) SunHalo(); else glCallList(planets[SUN].Sphere);
glPopMatrix();
OnScreenInfo();
glutSwapBuffers();
frames++;
}
static void Key( unsigned char key, int x, int y )
{
static int m;
m=glutGetModifiers();
switch (key) {
case 27:
sec=(TIMEFUNC-sec)/(float)CLOCKS_PER_SEC;
#ifdef WIN32
sprintf(sbuf,"\n%.2f frames/sec\n\n",frames/sec);
MessageBox(NULL,sbuf,"Overall Performance", MB_OK);
#else
printf("\n%.2f frames/sec\n\n",frames/sec);
#endif
exit(0);
break;
case 'c': linked=!linked;
if (!linked) {
upx=upz=0.0;
upy=1.0;
eyey=0.0;
}
break;
case 'p': pause=!pause;
break;
case 'f': smodel=(smodel==GL_FLAT) ? GL_SMOOTH : GL_FLAT;
glShadeModel(smodel);
break;
case 't': texture=!texture;
break;
case 's': drawstars=!drawstars;
break;
case 'n': if (currplanet==SUN) break;
d=DISTANCE(planets[currplanet].posx,
planets[currplanet].posy,planets[currplanet].posz);
camx=planets[currplanet].posx/d*
(d-RADIUSSCALE(planets[currplanet].Radius*8.0));
camy=planets[currplanet].posy;
camz=planets[currplanet].posz/d*
(d-RADIUSSCALE(planets[currplanet].Radius*8.0));
eyex=planets[currplanet].posx-camx;
eyey=planets[currplanet].posy-camy;
eyez=planets[currplanet].posz-camz;
upx=0.0; upy=1.0; upz=0.0;
d=DISTANCE(eyex,eyey,eyez);
eyex/=d; eyey/=d; eyez/=d;
break;
case 'h': help=!help;
break;
case 'd': demomode=!demomode;
break;
case 'l': lighting=!lighting;
break;
case '+': if (m & GLUT_ACTIVE_SHIFT) timefactor*=1.1;
else timefactor+=1/122400.0; /* one second/iteration */
break;
case '-': if (m & GLUT_ACTIVE_SHIFT) timefactor/=1.1;
else timefactor-=1/122400.0; /* one second/iteration */
break;
}
glutPostRedisplay();
}
static void Special(int k, int x, int y)
{
static double rot,xx,yy,zz;
static int m;
m=glutGetModifiers();
if (m & GLUT_ACTIVE_SHIFT) rot=0.05;
else rot=0.003;
switch (k) {
case GLUT_KEY_LEFT:Rotation(-rot,upx,upy,upz,&eyex,&eyey,&eyez);
break;
case GLUT_KEY_RIGHT: Rotation(rot,upx,upy,upz,&eyex,&eyey,&eyez);
break;
case GLUT_KEY_DOWN: xx=upy*eyez-upz*eyey;
yy=-upx*eyez+upz*eyex;
zz=upx*eyey-upy*eyex;
Rotation(rot,xx,yy,zz,&upx,&upy,&upz);
Rotation(rot,xx,yy,zz,&eyex,&eyey,&eyez);
break;
case GLUT_KEY_UP: xx=upy*eyez-upz*eyey;
yy=-upx*eyez+upz*eyex;
zz=upx*eyey-upy*eyex;
Rotation(-rot,xx,yy,zz,&upx,&upy,&upz);
Rotation(-rot,xx,yy,zz,&eyex,&eyey,&eyez);
break;
case GLUT_KEY_PAGE_UP: if (m & GLUT_ACTIVE_SHIFT) speed*=10.0;
else speed+=0.000001;
break;
case GLUT_KEY_PAGE_DOWN: if (m & GLUT_ACTIVE_SHIFT) speed/=10.0;
else speed-=0.000001;
break;
case GLUT_KEY_HOME: if (fakecurrplanet) currplanet=planorder[--fakecurrplanet];
break;
case GLUT_KEY_END: if (fakecurrplanet<(RINGS-1)) currplanet=planorder[++fakecurrplanet];
break;
}
if (fabs(speed)<0.000001) speed=0.0;
if (speed<-0.0001) speed=-0.0001;
if (speed>0.0001) speed=0.0001;
}
static void Timer(int i)
{
if (demomode) {
fakecurrplanet=rand()%(RINGS);
currplanet=planorder[fakecurrplanet];
if (currplanet!=SUN) {
d=DISTANCE(planets[currplanet].posx,
planets[currplanet].posy,planets[currplanet].posz);
camx=planets[currplanet].posx/d*
(d-RADIUSSCALE(planets[currplanet].Radius*8.0));
camy=planets[currplanet].posy;
camz=planets[currplanet].posz/d*
(d-RADIUSSCALE(planets[currplanet].Radius*8.0));
}
eyex=planets[currplanet].posx-camx;
eyey=planets[currplanet].posy-camy;
eyez=planets[currplanet].posz-camz;
upx=0.0; upy=1.0; upz=0.0;
d=DISTANCE(eyex,eyey,eyez);
eyex/=d; eyey/=d; eyez/=d;
}
glutTimerFunc(10000,Timer,0);
}
#ifdef WIN32
void ParseCmdLineWIN32(char *s)
{
int error=0;
char *endp=NULL;
char *tmp=s;
while ((*tmp) && (!error)) {
error=0;
if (tmp[0]=='-') {
tmp++;
if (!strncmp(tmp,"bench",5)) {
bench=1;
tmp+=5;
continue;
}
if (!strncmp(tmp,"slices ",7)) {
tmp+=7;
SLICES=strtol(tmp,&endp,10);
tmp=endp;
continue;
}
if (!strncmp(tmp,"stacks ",7)) {
tmp+=7;
STACKS=strtol(tmp,&endp,10);
tmp=endp;
continue;
}
error=1;
}
if (*tmp!=' ') error=1; else tmp++;
};
if (error) {
sprintf(sbuf,"ssystem [-bench] [-slices N] [-stacks N]");
MessageBox(NULL,sbuf,"ERROR: Invalid command line option",
MB_OK | MB_ICONERROR);
exit(0);
}
}
#else
void ParseCmdLine(int n, char **s)
{
int i=1,error=0;
char *endp=NULL;
while ((i<n) && (!error)) {
error=0;
if (!strcmp(s[i],"-bench")) {
bench=1;
i++;
continue;
}
if (!strcmp(s[i],"-slices")) {
i++;
if (i==n) { error=1; continue; };
SLICES=strtol(s[i],&endp,10);
error=*endp;
i++;
continue;
}
if (!strcmp(s[i],"-stacks")) {
i++;
if (i==n) { error=1; continue; };
STACKS=strtol(s[i],&endp,10);
error=*endp;
i++;
continue;
}
error=1;
};
if (error) {
printf("ERROR: Invalid command line option\n");
printf("\n\tssystem [-bench] [-slices N] [-stacks N] \n\n");
exit(0);
}
}
#endif
#ifdef WIN32
int PASCAL
WinMain(HANDLE hInst, HANDLE hPrevInst, LPSTR lpszCmndLine,int cmdShow )
#else
int main(int argc, char *argv[])
#endif
{
#ifdef WIN32
int argc=1;
char *argv[1];
char *s="ssystem.exe";
argv[0]=s;
ParseCmdLineWIN32(lpszCmndLine);
#else
ParseCmdLine(argc,argv);
#endif
glutInit( &argc, argv);
glutInitWindowPosition( 0, 0 );
glutInitWindowSize(width,height);
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
glutCreateWindow( "ssystem 1.2" );
Init();
currplanet=EARTH;
if (bench) days=1000.0;
demomode=!bench;
UpdatePositions();
camx=planets[EARTH].posx/1.005;
camy=planets[EARTH].posy;
camz=planets[EARTH].posz/1.005;
speed=-0.000002;
glutKeyboardFunc( Key );
glutSpecialFunc( Special );
glutDisplayFunc( Display );
glutIdleFunc( Idle );
glutTimerFunc(10000,Timer,0);
glutReshapeFunc( Reshape );
sec=TIMEFUNC;
glutMainLoop();
return 0;
}