// SETI Visualizations
// by Immanuel Buder
#include <stdlib.h>
#include <iostream.h>
#include <GL/glut.h>
#include "tgaload.cpp" //routine for loading texture from targa
#include <time.h>
int mainwindow,controlwindow, Rbutton, fpbutton, nebutton;
double R, fp, ne, fl, fi, fc, L; //Drake factors
double P; //civilization density
GLint height, width; //window size
GLuint map; //texture, galaxy map
GLint cheight, cwidth; //controol window size
void display (); //main display function
void outtext (double x, double y, double z, char *string, void *font);
void drakeinit() {
R= 10; //known with some accuracy
fp = .2; //reasonable estimate
ne = 1; // good... if we are average
fl= 1; //optimistic
fi = .9; //optimistic
fc = .1; //blatant guess
L = 1000; //low side of Dolphin range
}
void loadtextures () { //load texture
glPixelStorei (GL_UNPACK_ALIGNMENT,1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
map = tgaLoadAndBind ("milky.tga",TGA_DEFAULT); //map identifies texture
}
void controldisplay () {
glClear(GL_COLOR_BUFFER_BIT); //reset to background
}
void Rdisplay () {
glClearColor (.6,.1,0,0); //background color
glClear (GL_COLOR_BUFFER_BIT); //set background
glLoadIdentity(); //put basic matrix into memory
glOrtho (0,10,0,10,-1,1); //dimensions of view
glColor3f (0,0,0); //write in black
outtext (1,3,0,"R",GLUT_BITMAP_TIMES_ROMAN_24);//label
glFlush(); //force drawing
}
void fldisplay () {
glClearColor (.6,.1,0,0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho (0,10,0,10,-1,1);
glColor3f (0,0,0);
outtext (1,3,0,"fl",GLUT_BITMAP_TIMES_ROMAN_24);
glFlush();
}
void fpdisplay () {
glClearColor (.6,.1,0,0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho (0,10,0,10,-1,1);
glColor3f (0,0,0);
outtext (1,3,0,"fp",GLUT_BITMAP_TIMES_ROMAN_24);
glFlush();
}
void Ldisplay () {
glClearColor (.6,.1,0,0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho (0,10,0,10,-1,1);
glColor3f (0,0,0);
outtext (1,3,0,"L",GLUT_BITMAP_TIMES_ROMAN_24);
glFlush();
}
void fidisplay () {
glClearColor (.6,.1,0,0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho (0,10,0,10,-1,1);
glColor3f (0,0,0);
outtext (1,3,0,"fi",GLUT_BITMAP_TIMES_ROMAN_24);
glFlush();
}
void fcdisplay () {
glClearColor (.6,.1,0,0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho (0,10,0,10,-1,1);
glColor3f (0,0,0);
outtext (1,3,0,"fc",GLUT_BITMAP_TIMES_ROMAN_24);
glFlush();
}
void Pdisplay () {
glClearColor (.6,.1,0,0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho (0,10,0,10,-1,1);
glColor3f (0,0,0);
outtext (1,3,0,"P",GLUT_BITMAP_TIMES_ROMAN_24);
glFlush();
}
void nedisplay () {
glClearColor (.6,.1,0,0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho (0,10,0,10,-1,1);
glColor3f (0,0,0);
outtext (1,3,0,"ne",GLUT_BITMAP_TIMES_ROMAN_24);
glFlush();
}
void nemouse (int button, int state, int x, int y) {
if (state == GLUT_DOWN) { //if pressed
cout<<"Enter a new value for ne, the number of earthlike planets per star."<<endl;
cout<<"The old value is "<<ne<<endl;
cout<<"This parameter is not well known; however, if the solar system is representative of other star systems, this number is between 1 and 5."<<endl;
cin>>ne;
glutPostWindowRedisplay(mainwindow); //redraw main window
cout<<"ne changed to "<<ne<<endl; //inform user of change
glFlush(); //force drawing
}
}
void Rmouse (int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
cout<<"Enter a new value for R, the number of stars formed per year."<<endl;
cout<<"The old value is "<<R<<endl;
cout<<"This parameter is believed to be between 1 and 20"<<endl;
cin>>R;
cout<<"R changed to "<<R<<endl;
glutPostWindowRedisplay(mainwindow);
glFlush();
}
}
void fcmouse (int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
cout<<"Enter a new value for fc, the fraction of intelligent beings that communicate"<<endl;
cout<<"The old value is "<<fc<<endl;
cout<<"This parameter is largely unknown. Some guess it is between .1 and .2, since many intelligent beings do not develop technology (e.g. dolphins)."<<endl;
cin>>fc;
cout<<"fc changed to "<<fc<<endl; //inform user of change
glutPostWindowRedisplay(mainwindow);
glFlush();
}
}
void flmouse (int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
cout<<"Enter a new value for fl, the fraction of earthlike planets on which life occurs"<<endl;
cout<<"The old value is "<<fl<<endl;
cout<<"This parameter is assumed to be close to 1, given how quickly life evolved on earth"<<endl;
cin>>fl;
cout<<"fl changed to "<<fl<<endl; //inform user of change
glutPostWindowRedisplay(mainwindow);
glFlush();
}
}
void fimouse (int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
cout<<"Enter a new value for fi, the fraction of life-bearing planets which develop intelligence."<<endl;
cout<<"The old value is "<<fi<<endl;
cout<<"This parameter is believed to be close to 1, since intelligence has great survival value."<<endl;
cin>>fi;
cout<<"fi changed to "<<fi<<endl; //inform user of change
glutPostWindowRedisplay(mainwindow);
glFlush();
}
}
void Pmouse (int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
cout<<"The current civilization density is "<<P<<endl;
}
}
void Lmouse (int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
cout<<"Enter a new value for L, the length of time (in years) a communicating civilization remains detectable."<<endl;
cout<<"The old value is "<<L<<endl;
cout<<"This parameter is guessed to be between 1,000 and 100,000,000"<<endl;
cin>>L;
cout<<"L changed to "<<L<<endl; //inform user of change
glutPostWindowRedisplay(mainwindow);
glFlush();
}
}
void fpmouse (int button, int state, int x, int y) {
if (state == GLUT_DOWN) {
cout<<"Enter a new value for fp, the fraction of stars with planets."<<endl;
cout<<"The old value is "<<fp<<endl;
cout<<"This parameter is believed to be between .2 and .5"<<endl;
cin>>fp;
cout<<"fp changed to "<<fp<<endl; //inform user of change
glutPostWindowRedisplay(mainwindow);
glFlush();
}
}
void initialize () {
height = width = 500; //set size
glutInitDisplayMode(GLUT_DEPTH|GLUT_SINGLE|GLUT_RGB); //single buffered mode
glutInitWindowSize(width, height);
mainwindow = glutCreateWindow("SETI Visualizations"); //create main window
glutDisplayFunc(display); //function for main drawing
glEnable(GL_RGB); //RGB mode
glEnable (GL_TEXTURE_2D); //textures on
glEnable(GL_DEPTH_TEST); //
glDepthFunc(GL_LEQUAL); // more texture stuff
glEnable(GL_BLEND); //
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); //
loadtextures(); //load texture from milky.tga
glEnable(GL_RGB);
glClearColor(.3,.3,.6,0);
glMatrixMode(GL_PROJECTION); //create view
glLoadIdentity();
glOrtho(-1,1,-1,1,-1,1);
cwidth= 200; cheight = 200; //control window size
glutInitWindowSize(cwidth, cheight); //control windoe
controlwindow = glutCreateWindow("Controls");
glutDisplayFunc(controldisplay); //drawing function for controls
glClearColor (1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT); //set background
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1,1,-1,1,-1,1);
//create buttons
Rbutton = glutCreateSubWindow(controlwindow, 10, 10, 22, 40);
glutDisplayFunc (Rdisplay); //display function for buttons
glutMouseFunc(Rmouse); //function for mouse click
fpbutton = glutCreateSubWindow(controlwindow, 50, 10, 30, 40);
glutDisplayFunc (fpdisplay);
glutMouseFunc(fpmouse);
nebutton = glutCreateSubWindow(controlwindow, 90, 10, 30, 40);
glutDisplayFunc (nedisplay);
glutMouseFunc(nemouse);
glutCreateSubWindow(controlwindow, 130, 10, 20, 40);
glutDisplayFunc(fldisplay);
glutMouseFunc(flmouse);
glutCreateSubWindow(controlwindow, 160, 10, 20, 40);
glutDisplayFunc(fidisplay);
glutMouseFunc(fimouse);
glutCreateSubWindow(controlwindow, 10, 60, 30, 40);
glutDisplayFunc(fcdisplay);
glutMouseFunc(fcmouse);
glutCreateSubWindow(controlwindow, 50, 60, 30, 40);
glutDisplayFunc(Ldisplay);
glutMouseFunc(Lmouse);
glutCreateSubWindow(controlwindow, 90, 60, 30, 40);
glutDisplayFunc(Pdisplay);
glutMouseFunc(Pmouse);
}
void outtext (double x, double y, double z, char *string, void *font) {
glRasterPos3f(x,y,z); //locate position for output
int len = strlen (string); //find length of output
for (int i = 0; i < len; i++) {
glutBitmapCharacter(font,string[i]); //output by chars
}
}
void display () {
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); //clear
glBindTexture(GL_TEXTURE_2D, map); //use texture
glColor3f (1.0,1.0,1.0);
glBegin(GL_QUADS); //square, background
glTexCoord2f (0,0); //point on texture
glVertex3f (-1,-1,.1); //point on screen
glTexCoord2f (0,1);
glVertex3f (-1,1,.1);
glTexCoord2f (1,1);
glVertex3f (1,1,.1);
glTexCoord2f (1,0);
glVertex3f (1,-1,.1);
glEnd(); //done with quads
glColor3f(1.0,1.,1.0); //set draw color
glBegin(GL_POINTS); //begin drawing points
glColor3f(1.0,0,0); //set draw color
double x,y, xstep, ystep, points;
xstep = ystep = .005; //dist between points
points = 4/ (xstep * ystep); //number of possible points on screen
P = R*fp*ne*fl*fi*fc*L/points; //current point density
if (P >= 1) cout<<"Warning: maximum saturation reached"<<endl;
for (x = -1; x <1; x+= xstep) //move across screen
for (y = -1; y < 1; y += ystep)
if (P > (double(rand())/double(RAND_MAX)))
glVertex3f(x,y,0.2); //draw point
glEnd(); //done with points
glFlush(); //force drawing
}
int main (int argc, char ** argv) {
srand(unsigned(time(NULL))); //seed random numbers
drakeinit(); //initialize Drake factors
glutInit(&argc, argv); //initialize graphics
initialize(); //more graphics initialization
glutMainLoop(); //hand control over to OpenGL
return 0;
}