#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <GL/glx.h>
#include <GL/gl.h>
static int snglBuf[]={GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE,1,GLX_BLUE_SIZE,1,GLX_DEPTH_SIZE,12,None};
static int dblBuf[]={GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1 , GLX_DEPTH_SIZE, 12, GLX_DOUBLEBUFFER, None};
static int indextable[5][5] = {{21, 22, 23, 24, 25},{16, 17, 18, 19, 20}, {11,12, 13, 14, 15}, {6, 7, 8, 9, 10}, {1, 2, 3, 4, 5}};
#define MAX_MAPPED_STRING_LENGTH 10
Display *dpy;
Window win, win2;
Bool doubleBuffer = True;
/* Initial 3D object orientation */
GLfloat xAngle = 42.0, yAngle = 82.0, zAngle = 112.0;
int xwidth, xheight, window, zoomindex;
static int zoomfactor = 0;
static Bool displayListInited = False;
Bool bo1 = True, bo2 = True, bo3 = False;
/* Data structure of genes for each 3D Biomorph */
struct gene {
int gene[16];
Bool gene17;
Bool gene18;
Bool gene19;
int gene2021[2];
Bool gene22;
GLfloat gene23;
GLfloat gene24;
GLfloat gene25;
int dx[8];
int dy[8];
int dz[8];
int startdir;
};
/* Data structure of each line segment */
struct lineseg {
GLfloat frontptx;
GLfloat frontpty;
GLfloat frontptz;
GLfloat endptx;
GLfloat endpty;
GLfloat endptz;
struct lineseg *nextline;
};
typedef struct gene Mygene;
/* Array to store genes of each offerspring */
Mygene offerspring[26];
typedef struct lineseg Myline;
/* Array of pointers that point to the head of stacks of line segments which represent each 3D Biomorph */
Myline *startbiomorph[25];
/* Array of pointers that point to the tail of stacks of line segments which represent each 3D Biomorph */
Myline *currentbiomorph[25];
/* Function to push line segment to specific 3D Biomorph */
void push(morphindex, xstart, ystart, zstart, xnew, ynew, znew)
int morphindex, xstart, ystart, zstart, xnew, ynew, znew;
{
if (startbiomorph[morphindex] == NULL)
{
startbiomorph[morphindex] = (Myline *)malloc(sizeof (Myline));
startbiomorph[morphindex]->frontptx = (GLfloat) xstart / 50.0;
startbiomorph[morphindex]->frontpty = (GLfloat) ystart / 50.0;
startbiomorph[morphindex]->frontptz = (GLfloat) zstart / 50.0;
startbiomorph[morphindex]->endptx = (GLfloat) xnew / 50.0;
startbiomorph[morphindex]->endpty = (GLfloat) ynew / 50.0;
startbiomorph[morphindex]->endptz = (GLfloat) znew / 50.0;
currentbiomorph[morphindex] = startbiomorph[morphindex];
currentbiomorph[morphindex]->nextline = NULL;
}
else
{
currentbiomorph[morphindex]->nextline = malloc (sizeof (Myline));
currentbiomorph[morphindex] = currentbiomorph[morphindex]->nextline;
currentbiomorph[morphindex]->frontptx = (GLfloat) xstart / 50.0;
currentbiomorph[morphindex]->frontpty = (GLfloat) ystart / 50.0;
currentbiomorph[morphindex]->frontptz = (GLfloat) zstart / 50.0;
currentbiomorph[morphindex]->endptx = (GLfloat) xnew / 50.0;
currentbiomorph[morphindex]->endpty = (GLfloat) ynew / 50.0;
currentbiomorph[morphindex]->endptz = (GLfloat) znew / 50.0;
currentbiomorph[morphindex]->nextline = NULL;
}
}
/* Translate genes into variables needed by 3D Biomorph */
int PlugIn(breeding)
Mygene * breeding;
{
breeding->dx[3] = breeding->gene[0];
breeding->dx[4] = breeding->gene[1];
breeding->dx[5] = breeding->gene[2];
breeding->dx[1] = -breeding->dx[3];
breeding->dx[0] = -breeding->dx[4];
breeding->dx[7] = -breeding->dx[5];
breeding->dx[2] = 0;
breeding->dx[6] = 0;
breeding->dy[2] = breeding->gene[3];
breeding->dy[3] = breeding->gene[4];
breeding->dy[4] = breeding->gene[5];
breeding->dy[5] = breeding->gene[6];
breeding->dy[6] = breeding->gene[7];
breeding->dy[0] = breeding->dy[4];
breeding->dy[1] = breeding->dy[3];
breeding->dy[7] = breeding->dy[5];
breeding->dz[2] = breeding->gene[8];
breeding->dz[3] = breeding->gene[9];
breeding->dz[4] = breeding->gene[10];
breeding->dz[5] = breeding->gene[11];
breeding->dz[6] = breeding->gene[12];
breeding->dz[0] = breeding->dz[4];
breeding->dz[1] = breeding->dz[3];
breeding->dz[7] = breeding->dz[5];
return abs(breeding->gene[13]);
}
/* Tree is called with the arrays dx, dy & dz specifying the form of the tree, and the starting value of length specifying the number
of length specifying the number of branchings. Tree calls itself recursively with a progressively decreasing value of length until
length reaches 0 */
void tree(morphindex, x, y, z, length, dir, dx, dy, dz)
int morphindex, x, y, z, length, dir;
int * dx;
int * dy;
int * dz;
{
int xnew, ynew, znew;
if (dir < 0)
dir += 8;
if (dir >= 8)
dir -= 8;
xnew = x + length * dx[dir];
ynew = y + length * dy[dir];
znew = z + length * dz[dir];
push(morphindex, x, y, z, xnew, ynew, znew);
if (length > 0)
{
tree(morphindex, xnew, ynew, znew, length - 1, dir - 1, dx, dy, dz);
tree(morphindex, xnew, ynew, znew, length - 1, dir + 1, dx, dy, dz);
}
}
/* Free the memory space occupied by 3D Biomorphs */
void freeptr()
{
int i;
Myline * temp;
for (i = 0; i < 25; i++)
{
while (startbiomorph[i] != NULL)
{
temp = startbiomorph[i]->nextline;
free (startbiomorph[i]);
startbiomorph[i] = temp;
}
}
}
/* Zoom in or zoom out 3D Biomorph to fit the viewport */
void zoomobj(int factor)
{
float objfactor, offset, xoffset, yoffset, zoffset;
Myline *tempptr;
int i;
glDeleteLists(26,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, xwidth, xheight);
zoomfactor += factor;
if (zoomfactor == 0)
glCallList(zoomindex);
else
{
if (zoomfactor > 0)
{
objfactor = 1.0 + zoomfactor * 0.1;
tempptr = startbiomorph[zoomindex - 1];
/* Calculate the direction vector of each segement */
offset = sqrt((tempptr->frontptx - tempptr->endptx)*(tempptr->frontptx - tempptr->endptx) + (tempptr->frontpty - tempptr->endpty)*(tempptr->frontpty - tempptr->endpty) + (tempptr->frontptz - tempptr->endptz)*(tempptr->frontptz - tempptr->endptz));
xoffset = (tempptr->endptx - tempptr->frontptx)/offset * offerspring[zoomindex].gene[15] / 50;
yoffset = (tempptr->endpty - tempptr->frontpty)/offset * offerspring[zoomindex].gene[15] / 50;
zoffset = (tempptr->endptz - tempptr->frontptz)/offset * offerspring[zoomindex].gene[15] / 50;
/* Create display list for 3D Biomorph */
glNewList(26, GL_COMPILE_AND_EXECUTE);
glBegin(GL_LINES);
glColor3f(offerspring[zoomindex].gene23, offerspring[zoomindex].gene24, offerspring[zoomindex].gene25);
for (i = 1; i <= offerspring[zoomindex].gene[14] ; i++)
{
while (tempptr != NULL)
{
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, (tempptr->frontpty + (i - 1) * yoffset) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, (tempptr->endpty + (i - 1) * yoffset) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor);
/* Check the symmetric attribute of y and z axis */
if (offerspring[zoomindex].gene18 && offerspring[zoomindex].gene19)
{
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, ((tempptr->frontpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, ((tempptr->endpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor);
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, ((tempptr->frontpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor * -1);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, ((tempptr->endpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor * -1);
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, (tempptr->frontpty + (i - 1) * yoffset) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor * -1);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, (tempptr->endpty + (i - 1) * yoffset) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor * -1);
}
else
{
/* Check the symmetric attribute of y axis */
if (offerspring[zoomindex].gene18)
{
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, ((tempptr->frontpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, ((tempptr->endpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor);
}
/* Check the symmetric attribute of z axis */
if (offerspring[zoomindex].gene19)
{
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, (tempptr->frontpty + (i - 1) * yoffset) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor * -1);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, (tempptr->endpty + (i - 1) * yoffset) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor * -1);
}
}
tempptr = tempptr->nextline;
}
tempptr = startbiomorph[zoomindex - 1];
}
tempptr = startbiomorph[zoomindex - 1];
glVertex3f(tempptr->frontptx * objfactor, tempptr->frontpty * objfactor, tempptr->frontptz * objfactor);
glVertex3f((tempptr->endptx + (i - 2) * xoffset) * objfactor, (tempptr->endpty + (i - 2) * yoffset) * objfactor, (tempptr->endptz + (i - 2) * zoffset) * objfactor);
glEnd();
glEndList();
}
else
{
/* Check the limitation of zoom out factor */
if (zoomfactor > -10)
objfactor = 1 + zoomfactor * 0.1;
else
{
objfactor = 0.1;
zoomfactor = -9;
}
tempptr = startbiomorph[zoomindex - 1];
/* Compute the unit direction vector */
offset = sqrt((tempptr->frontptx - tempptr->endptx)*(tempptr->frontptx - tempptr->endptx) + (tempptr->frontpty - tempptr->endpty)*(tempptr->frontpty - tempptr->endpty) + (tempptr->frontptz - tempptr->endptz)*(tempptr->frontptz - tempptr->endptz));
xoffset = (tempptr->endptx - tempptr->frontptx)/offset * offerspring[zoomindex].gene[15] / 50;
yoffset = (tempptr->endpty - tempptr->frontpty)/offset * offerspring[zoomindex].gene[15] / 50;
zoffset = (tempptr->endptz - tempptr->frontptz)/offset * offerspring[zoomindex].gene[15] / 50;
/* Create display list 26 */
glNewList(26, GL_COMPILE_AND_EXECUTE);
glBegin(GL_LINES);
/* Set color of 3D Biomorph */
glColor3f(offerspring[zoomindex].gene23, offerspring[zoomindex].gene24, offerspring[zoomindex].gene25);
for (i = 1; i <= offerspring[zoomindex].gene[14] ; i++)
{
while (tempptr != NULL)
{
glVertex3f((tempptr->frontptx + (i - 1) * xoffset)*objfactor, (tempptr->frontpty + (i - 1) * yoffset) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, (tempptr->endpty + (i - 1) * yoffset) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor);
/* Check the symmetric attributes of y an z axises */
if (offerspring[zoomindex].gene18 && offerspring[zoomindex].gene19)
{
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, ((tempptr->frontpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, ((tempptr->endpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor);
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, ((tempptr->frontpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor * -1);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, ((tempptr->endpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor * -1);
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, (tempptr->frontpty + (i - 1) * yoffset) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor * -1);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, (tempptr->endpty + (i - 1) * yoffset) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor * -1);
}
else
{
/* Check the symmetric attribute of y axis */
if (offerspring[zoomindex].gene18)
{
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, ((tempptr->frontpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, ((tempptr->endpty + (i - 1) * yoffset) * -1) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor);
}
/* Check the symmetric attribute of z axis */
if (offerspring[zoomindex].gene19)
{
glVertex3f((tempptr->frontptx + (i - 1) * xoffset) * objfactor, (tempptr->frontpty + (i - 1) * yoffset) * objfactor, (tempptr->frontptz + (i - 1) * zoffset) * objfactor * -1);
glVertex3f((tempptr->endptx + (i - 1) * xoffset) * objfactor, (tempptr->endpty + (i - 1) * yoffset) * objfactor, (tempptr->endptz + (i - 1) * zoffset) * objfactor * -1);
}
}
tempptr = tempptr->nextline;
}
tempptr = startbiomorph[zoomindex - 1];
}
tempptr = startbiomorph[zoomindex - 1];
/* link all of the segments of a 3D Biomprph */
glVertex3f(tempptr->frontptx * objfactor, tempptr->frontpty * objfactor, tempptr->frontptz * objfactor);
glVertex3f((tempptr->endptx + (i - 2) * xoffset) * objfactor, (tempptr->endpty + (i - 2) * yoffset) * objfactor, (tempptr->endptz + (i - 2) * zoffset) * objfactor);
glEnd();
glEndList();
}
}
/* Switch contents from double buffer */
if(doubleBuffer)
glXSwapBuffers(dpy,win);
else
glFlush();
}
/* Change the viewport to single object mode */
void zoomout(int cursorwidth, int cursorheight)
{
int i, j;
Myline *tempptr;
GLfloat offset, xoffset, yoffset, zoffset;
i = cursorwidth / (xwidth/5);
j = cursorheight / (xheight/5);
zoomindex = indextable[j][i];
glDeleteLists(26,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Set viewport to the whole window */
glViewport(0, 0, xwidth, xheight);
tempptr = startbiomorph[zoomindex - 1];
/* Calculate the direction vector of each segement */
offset = sqrt((tempptr->frontptx - tempptr->endptx)*(tempptr->frontptx - tempptr->endptx) + (tempptr->frontpty - tempptr->endpty)*(tempptr->frontpty - tempptr->endpty) + (tempptr->frontptz - tempptr->endptz)*(tempptr->frontptz - tempptr->endptz));
xoffset = (tempptr->endptx - tempptr->frontptx)/offset * offerspring[zoomindex].gene[15] / 50;
yoffset = (tempptr->endpty - tempptr->frontpty)/offset * offerspring[zoomindex].gene[15] / 50;
zoffset = (tempptr->endptz - tempptr->frontptz)/offset * offerspring[zoomindex].gene[15] / 50;
/* Create display list 26 */
glNewList(26, GL_COMPILE_AND_EXECUTE);
glBegin(GL_LINES);
glColor3f(offerspring[zoomindex].gene23, offerspring[zoomindex].gene24, offerspring[zoomindex].gene25);
for (i = 1; i <= offerspring[zoomindex].gene[14] ; i++)
{
while (tempptr != NULL)
{
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, tempptr->frontpty + (i - 1) * yoffset, tempptr->frontptz + (i - 1) * zoffset);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, tempptr->endpty + (i - 1) * yoffset, tempptr->endptz + (i - 1) * zoffset);
/* Check the symmetric attributes of y and z axises */
if(offerspring[zoomindex].gene18 && offerspring[zoomindex].gene19)
{
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, (tempptr->frontpty + (i - 1) * yoffset) * -1, tempptr->frontptz + (i - 1) * zoffset);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, (tempptr->endpty + (i - 1) * yoffset) * -1, tempptr->endptz + (i - 1) * zoffset);
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, tempptr->frontpty + (i - 1) * yoffset, (tempptr->frontptz + (i - 1) * zoffset) * -1);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, tempptr->endpty + (i - 1) * yoffset, (tempptr->endptz + (i - 1) * zoffset) * -1);
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, tempptr->frontpty + (i - 1) * yoffset * -1, (tempptr->frontptz + (i - 1) * zoffset) * -1);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, tempptr->endpty + (i - 1) * yoffset * -1, (tempptr->endptz + (i - 1) * zoffset) * -1);
}
else
{
/* Check the symmetric attribute of y axis */
if (offerspring[zoomindex].gene18)
{
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, (tempptr->frontpty + (i - 1) * yoffset) * -1, tempptr->frontptz + (i - 1) * zoffset);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, (tempptr->endpty + (i - 1) * yoffset) * -1, tempptr->endptz + (i - 1) * zoffset);
}
/* Check the symmetric attribute of z axis */
if (offerspring[zoomindex].gene19)
{
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, tempptr->frontpty + (i - 1) * yoffset, (tempptr->frontptz + (i - 1) * zoffset) * -1);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, tempptr->endpty + (i - 1) * yoffset, (tempptr->endptz + (i - 1) * zoffset) * -1);
}
}
tempptr = tempptr->nextline;
}
tempptr = startbiomorph[zoomindex - 1];
}
tempptr = startbiomorph[zoomindex - 1];
/* Link all segment of one 3D Biomorph */
glVertex3f(tempptr->frontptx, tempptr->frontpty, tempptr->frontptz);
glVertex3f(tempptr->endptx + (i - 2) * xoffset, tempptr->endpty + (i - 2) * yoffset, tempptr->endptz + (i - 2) * zoffset);
glEnd();
glEndList();
/* Switch contents from double buffer */
if(doubleBuffer)
glXSwapBuffers(dpy,win);
else
glFlush();
}
/* Breed the next generation of 3D Biomorph */
void breed(int cursorwidth, int cursorheight)
{
int i, j, parent, length, lentemp, genetemp, startdir, colortemp, segtemp, testsymm;
GLfloat colorindex;
/* Find the parent of next generation */
i = cursorwidth / (xwidth/5);
j = cursorheight / (xheight/5);
parent = indextable[j][i];
memcpy (&offerspring[0], &offerspring[parent], sizeof(Mygene));
for (i = 1; i < 26; i++)
memcpy (&offerspring[i], &offerspring[0], sizeof(Mygene));
/* Control gene 1 to gene 13 for the next generation */
for (i = 1; i < 14; i++)
{
/* Check gene22 to determine the mutation rate of each gene */
if (!offerspring[i].gene22)
offerspring[i].gene[i -1] = offerspring[i].gene[i - 1] * 0.5;
/* Determine the change of gene of the offerspring */
genetemp = rand() / 16384;
if(genetemp)
{
offerspring[i].gene[i - 1]++;
}
else
{
offerspring[i].gene[i - 1]--;
}
/* Determine the branchings of the offerspring */
lentemp = rand() / 10923;
lentemp--;
if (offerspring[i].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[i].gene[13] += lentemp;
}
else
offerspring[i].gene[13] += lentemp;
/* Get number of brachings of the offerspring */
length = PlugIn(&offerspring[i]);
/* Save the number of branchings of the offerspring, this number will
be used if this 3D Biomorph choosen as the parent of the next
generation */
startdir = rand() / 4096;
offerspring[i].startdir = startdir;
tree(i - 1, 0, 0, 0, length, startdir, offerspring[i].dx, offerspring[i].dy, offerspring[i].dz);
}
length = PlugIn(&offerspring[14]);
tree(13, 0, 0, 0, length, offerspring[14].startdir, offerspring[14].dx, offerspring[14].dy, offerspring[14].dz);
/* Determine the change of gene 15 (number of segments) and gene 16 (distance
of segments) */
for (i = 15; i < 17; i++)
{
segtemp = rand()/10923;
segtemp--;
if (segtemp > 0)
offerspring[i].gene[i - 1] += segtemp;
else
if(offerspring[i].gene[i - 1] > 1)
offerspring[i].gene[i - 1] += segtemp;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[i].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[i].gene[13] += lentemp;
}
else
offerspring[i].gene[13] += lentemp;
startdir = rand() / 4096;
offerspring[i].startdir = startdir;
length = PlugIn(&offerspring[i]);
tree(i - 1, 0, 0, 0, length, startdir, offerspring[i].dx, offerspring[i].dy, offerspring[i].dz);
}
/* Gene 17 control the symmetric attribute of x axis (Bilateral Symmetry).
In this program, I assume that the 3D Biomorphs are always bilateral
symmetry */
startdir = rand() / 4096;
offerspring[17].startdir = startdir;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[17].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[17].gene[13] += lentemp;
}
else
offerspring[17].gene[13] += lentemp;
length = PlugIn(&offerspring[17]);
tree(16, 0, 0, 0, length, startdir, offerspring[17].dx, offerspring[17].dy, offerspring[17].dz);
startdir = rand() / 4096;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[18].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[18].gene[13] += lentemp;
}
else
offerspring[18].gene[13] += lentemp;
/* Gene 18 control the symmetric attribute of y axis. There are 33%
probability that the gene change form True to False and vice versa */
testsymm = rand() / 16384;
if (testsymm)
if (offerspring[18].gene18)
offerspring[18].gene18 = False;
else
offerspring[18].gene18 = True;
offerspring[18].startdir = startdir;
length = PlugIn(&offerspring[18]);
tree(17, 0, 0, 0, length, startdir, offerspring[18].dx, offerspring[18].dy, offerspring[18].dz);
startdir = rand() / 4096;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[19].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[19].gene[13] += lentemp;
}
else
offerspring[19].gene[13] += lentemp;
/* Gene 19 control the symmetric attribute of z axis. There are 33%
probability that the gene change form True to False and vice versa */
testsymm = rand() / 16384;
if (testsymm)
if (offerspring[19].gene19)
offerspring[19].gene19 = False;
else
offerspring[19].gene19 = True;
offerspring[19].startdir = startdir;
length = PlugIn(&offerspring[19]);
tree(18, 0, 0, 0, length, startdir, offerspring[19].dx, offerspring[19].dy, offerspring[19].dz);
startdir = rand() / 4096;
offerspring[20].startdir = startdir;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[20].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[20].gene[13] += lentemp;
}
else
offerspring[20].gene[13] += lentemp;
length = PlugIn(&offerspring[20]);
tree(19, 0, 0, 0, length, startdir, offerspring[20].dx, offerspring[20].dy, offerspring[20].dz);
startdir = rand() / 4096;
offerspring[21].startdir = startdir;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[21].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[21].gene[13] += lentemp;
}
else
offerspring[21].gene[13] += lentemp;
length = PlugIn(&offerspring[21]);
tree(20, 0, 0, 0, length, startdir, offerspring[21].dx, offerspring[21].dy, offerspring[21].dz);
startdir = rand() / 4096;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[22].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[22].gene[13] += lentemp;
}
else
offerspring[22].gene[13] += lentemp;
/* Gene 22 control the mutation rate. There are 33% probability
that the gene change form True to False and vice versa */
if (testsymm)
if (offerspring[22].gene22)
offerspring[22].gene22 = False;
else
offerspring[22].gene22 = True;
offerspring[22].startdir = startdir;
length = PlugIn(&offerspring[22]);
tree(21, 0, 0, 0, length, startdir, offerspring[22].dx, offerspring[22].dy, offerspring[22].dz);
startdir = rand() / 4096;
offerspring[23].startdir = startdir;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[23].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[23].gene[13] += lentemp;
}
else
offerspring[23].gene[13] += lentemp;
lentemp = rand() / 10923;
colortemp = rand() /10923;
colorindex = (GLfloat) colortemp/10.0 - 0.1;
lentemp--;
if (offerspring[23].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[23].gene[13] += lentemp;
}
else
offerspring[23].gene[13] += lentemp;
/* Gene 23 control the intensity of color red. There are 33% probability
that the intensity will add or minus 0.1 */
if (colorindex < 0)
{
if (offerspring[23].gene23 >= 0.1)
offerspring[23].gene23 += colorindex;
}
else
offerspring[23].gene23 += colorindex;
length = PlugIn(&offerspring[23]);
tree(22, 0, 0, 0, length, startdir, offerspring[23].dx, offerspring[23].dy, offerspring[23].dz);
startdir = rand() / 4096;
offerspring[24].startdir = startdir;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[24].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[24].gene[13] += lentemp;
}
else
offerspring[24].gene[13] += lentemp;
lentemp = rand() / 10923;
colortemp = rand() /10923;
colorindex = (GLfloat) colortemp/10.0 - 0.1;
lentemp--;
if (offerspring[24].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[24].gene[13] += lentemp;
}
else
offerspring[24].gene[13] += lentemp;
/* Gene 24 control the intensity of color green. There are 33% probability
that the intensity will add or minus 0.1 */
if (colorindex < 0)
{
if (offerspring[24].gene24 >= 0.1)
offerspring[24].gene24 += colorindex;
}
else
offerspring[24].gene24 += colorindex;
length = PlugIn(&offerspring[24]);
tree(23, 0, 0, 0, length, startdir, offerspring[24].dx, offerspring[24].dy, offerspring[24].dz);
startdir = rand() / 4096;
offerspring[25].startdir = startdir;
lentemp = rand() / 10923;
lentemp--;
if (offerspring[25].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[25].gene[13] += lentemp;
}
else
offerspring[25].gene[13] += lentemp;
lentemp = rand() / 10923;
colortemp = rand() /10923;
colorindex = (GLfloat) colortemp/10.0 - 0.1;
lentemp--;
if (offerspring[25].gene[13] == 1)
{
if (lentemp >= 0)
offerspring[25].gene[13] += lentemp;
}
else
offerspring[25].gene[13] += lentemp;
/* Gene 25 control the intensity of color blue. There are 33% probability
that the intensity will add or minus 0.1. */
if (colorindex < 0)
{
if (offerspring[25].gene25 >= 0.1)
offerspring[25].gene25 += colorindex;
}
else
offerspring[25].gene25 += colorindex;
length = PlugIn(&offerspring[25]);
tree(24, 0, 0, 0, length, startdir, offerspring[25].dx, offerspring[25].dy, offerspring[25].dz);
}
/* Initial the 3D Biomorphs to the beginning state */
void GetInit()
{
int i;
time_t t;
srand((unsigned) time(&t));
for (i = 0; i < 12; i++)
offerspring[0].gene[i] = (int) rint((double) rand() / 32767 * 18) - 9;
offerspring[0].gene[13] = 1;
offerspring[0].gene[14] = 1;
offerspring[0].gene[15] = 10;
offerspring[0].gene17 = True;
offerspring[0].gene18 = False;
offerspring[0].gene19 = False;
offerspring[0].gene2021[0] = 1;
offerspring[0].gene2021[1] = 1;
offerspring[0].gene22 = True;
offerspring[0].gene23 = (GLfloat) rand()/32767.0;
offerspring[0].gene24 = (GLfloat) rand()/32767.0;
offerspring[0].gene25 = (GLfloat) rand()/32767.0;
for (i = 1; i < 26; i++)
memcpy(&offerspring[i],&offerspring[0],sizeof(struct gene));
}
/* Create display list for 3D Biomorph */
void createlist(int morphindex, int xcor, int ycor, int xlim, int ylim)
{
Myline * tempptr;
GLfloat offset, xoffset, yoffset, zoffset;
int i;
/* Set viewport of each 3D Biomorph */
glViewport(xcor, ycor, xlim, ylim);
tempptr = startbiomorph[morphindex - 1];
/* Compute the unit direction vector of the 3D Biomorph */
offset = sqrt((tempptr->frontptx - tempptr->endptx)*(tempptr->frontptx - tempptr->endptx) + (tempptr->frontpty - tempptr->endpty)*(tempptr->frontpty - tempptr->endpty) + (tempptr->frontptz - tempptr->endptz)*(tempptr->frontptz - tempptr->endptz));
xoffset = (tempptr->endptx - tempptr->frontptx)/offset * offerspring[morphindex].gene[15] / 50;
yoffset = (tempptr->endpty - tempptr->frontpty)/offset * offerspring[morphindex].gene[15] / 50;
zoffset = (tempptr->endptz - tempptr->frontptz)/offset * offerspring[morphindex].gene[15] / 50;
/* Create a display list */
glNewList(morphindex, GL_COMPILE_AND_EXECUTE);
glBegin(GL_LINES);
glColor3f(offerspring[morphindex].gene23, offerspring[morphindex].gene24, offerspring[morphindex].gene25);
for (i = 1; i <= offerspring[morphindex].gene[14] ; i++)
{
while (tempptr != NULL)
{
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, tempptr->frontpty + (i - 1) * yoffset, tempptr->frontptz + (i - 1) * zoffset);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, tempptr->endpty + (i - 1) * yoffset, tempptr->endptz + (i - 1) * zoffset);
/* Check the symmetric attributes of y and z axises of the 3D Biomorph */
if(offerspring[zoomindex].gene18 && offerspring[morphindex].gene19)
{
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, (tempptr->frontpty + (i - 1) * yoffset) * -1, tempptr->frontptz + (i - 1) * zoffset);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, (tempptr->endpty + (i - 1) * yoffset) * -1, tempptr->endptz + (i - 1) * zoffset);
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, tempptr->frontpty + (i - 1) * yoffset, (tempptr->frontptz + (i - 1) * zoffset) * -1);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, tempptr->endpty + (i - 1) * yoffset, (tempptr->endptz + (i - 1) * zoffset) * -1);
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, tempptr->frontpty + (i - 1) * yoffset * -1, (tempptr->frontptz + (i - 1) * zoffset) * -1);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, tempptr->endpty + (i - 1) * yoffset * -1, (tempptr->endptz + (i - 1) * zoffset) * -1);
}
else
{
/* Check the symmetric attribute of y axis */
if (offerspring[morphindex].gene18)
{
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, (tempptr->frontpty + (i - 1) * yoffset) * -1, tempptr->frontptz + (i - 1) * zoffset);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, (tempptr->endpty + (i - 1) * yoffset) * -1, tempptr->endptz + (i - 1) * zoffset);
}
/* Check the symmetric attribute of z axis */
if (offerspring[morphindex].gene19)
{
glVertex3f(tempptr->frontptx + (i - 1) * xoffset, tempptr->frontpty + (i - 1) * yoffset, (tempptr->frontptz + (i - 1) * zoffset) * -1);
glVertex3f(tempptr->endptx + (i - 1) * xoffset, tempptr->endpty + (i - 1) * yoffset, (tempptr->endptz + (i - 1) * zoffset) * -1);
}
}
tempptr = tempptr->nextline;
}
tempptr = startbiomorph[morphindex - 1];
}
tempptr = startbiomorph[morphindex - 1];
/* Link all segments of the 3D Biomorph */
glVertex3f(tempptr->frontptx, tempptr->frontpty, tempptr->frontptz);
glVertex3f(tempptr->endptx + (i - 2) * xoffset, tempptr->endpty + (i - 2) * yoffset, tempptr->endptz + (i - 2) * zoffset);
glEnd();
glEndList();
}
void
redraw()
{
Myline *tempptr;
GLfloat offset, xoffset, yoffset, zoffset;
int morphindex, displayindex, i, j, k;
if (displayListInited) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* If the size of window changes, redisplay the 3D Biomorphs */
glViewport(0, 0, xwidth/5, xheight/5);
glCallList(1);
glViewport(xwidth/5, 0, xwidth/5,xheight/5);
glCallList(2);
glViewport(xwidth/5*2, 0, xwidth/5,xheight/5);
glCallList(3);
glViewport(xwidth/5*3, 0, xwidth/5, xheight/5);
glCallList(4);
glViewport(xwidth/5*4, 0, xwidth/5,xheight/5);
glCallList(5);
glViewport(0, xheight/5, xwidth/5,xheight/5);
glCallList(6);
glViewport(xwidth/5, xheight/5, xwidth/5, xheight/5);
glCallList(7);
glViewport(xwidth/5*2, xheight/5, xwidth/5,xheight/5);
glCallList(8);
glViewport(xwidth/5*3, xheight/5, xwidth/5,xheight/5);
glCallList(9);
glViewport(xwidth/5*4, xheight/5, xwidth/5, xheight/5);
glCallList(10);
glViewport(0, xheight/5*2, xwidth/5,xheight/5);
glCallList(11);
glViewport(xwidth/5, xheight/5*2, xwidth/5, xheight/5);
glCallList(12);
glViewport(xwidth/5*2, xheight/5*2, xwidth/5,xheight/5);
glCallList(13);
glViewport(xwidth/5*3, xheight/5*2, xwidth/5,xheight/5);
glCallList(14);
glViewport(xwidth/5*4, xheight/5*2, xwidth/5, xheight/5);
glCallList(15);
glViewport(0, xheight/5*3, xwidth/5,xheight/5);
glCallList(16);
glViewport(xwidth/5, xheight/5*3, xwidth/5, xheight/5);
glCallList(17);
glViewport(xwidth/5*2, xheight/5*3, xwidth/5,xheight/5);
glCallList(18);
glViewport(xwidth/5*3, xheight/5*3, xwidth/5,xheight/5);
glCallList(19);
glViewport(xwidth/5*4, xheight/5*3, xwidth/5, xheight/5);
glCallList(20);
glViewport(0, xheight/5*4, xwidth/5,xheight/5);
glCallList(21);
glViewport(xwidth/5, xheight/5*4, xwidth/5, xheight/5);
glCallList(22);
glViewport(xwidth/5*2, xheight/5*4, xwidth/5,xheight/5);
glCallList(23);
glViewport(xwidth/5*3, xheight/5*4, xwidth/5,xheight/5);
glCallList(24);
glViewport(xwidth/5*4, xheight/5*4, xwidth/5, xheight/5);
glCallList(25);
}
else {
glDeleteLists(1,25);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Create display lists of all 3D Biomorphs */
morphindex = 1;
for (k = 0; k < 5; k++)
for (j = 0; j < 5; j++)
{
createlist(morphindex, j * xwidth/5, k * xheight/5, xwidth/5, xheight/5);
morphindex++;
}
displayListInited = True;
}
if(doubleBuffer)
glXSwapBuffers(dpy,win);
else
glFlush();
}
void fatalError(char *errmsg)
{
fprintf(stderr,errmsg);
exit(1);
}
void
main(int argc, char **argv)
{
int i, length;
XVisualInfo *vi;
Colormap cmap;
XSetWindowAttributes swa;
GLXContext cx;
XEvent event;
Bool needRedraw = False, recalcModelView = True;
int dummy;
char buffer[MAX_MAPPED_STRING_LENGTH];
int bufsize = MAX_MAPPED_STRING_LENGTH;
KeySym keysym;
XComposeStatus compose;
int count;
/* Open a connection to X Server */
dpy = XOpenDisplay(NULL);
if(dpy == NULL)
fatalError("could not open display");
if(!glXQueryExtension(dpy, &dummy, &dummy))
fatalError("X server has no OpenGL GLX extension");
/* Find an appropriate OpenGL-capable visual */
vi = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf);
if(vi == NULL){
vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf);
if(vi == NULL)
fatalError("no RGB visual with depth buffer");
doubleBuffer = False;
}
if (vi->class != TrueColor)
fatalError("TrueColor visual required for this program");
/* Create an OpenGL rendering context */
cx = glXCreateContext(dpy,vi,None,True);
if (cx == NULL)
fatalError ("could not create rendering context");
/* Create an X window with the selected visual. */
cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
swa.colormap = cmap;
swa.border_pixel = 0;
swa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask | KeyPressMask;
win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 1000, 1000, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);
XSetStandardProperties(dpy, win, "3D Birmorph", "3D Biomorph", None, argv, argc, NULL);
glXMakeCurrent(dpy, win,cx);
XMapWindow(dpy, win);
/* Enable depth buffering */
glEnable(GL_DEPTH_TEST);
/* Set up projection transform. */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0,1.0,-1.0,1.0,1.0,20.0);
GetInit();
length = PlugIn(&offerspring[1]);
tree(0, 0, 0, 0, length, 0, offerspring[1].dx, offerspring[1].dy, offerspring[1].dz);
for (i = 1; i < 25 ; i++)
startbiomorph[i] = startbiomorph[0];
while(1){
do {
XNextEvent(dpy, &event);
switch(event.type){
case ButtonPress:
switch(event.xbutton.button){
case 1:
/* Event to detect press of mouse button 1 */
/* Choose parent to breed next generation */
if(bo1)
{
freeptr();
breed(event.xconfigure.width,event.xconfigure.height);
displayListInited = False;
needRedraw = True;
}
break;
case 2:
/* Event to detect press of mouse button 2 */
/* Change the display mode to single object mode */
if (bo2)
{
zoomout(event.xconfigure.width,event.xconfigure.height);
bo1 = False;
bo2 = False;
bo3 = True;
}
break;
case 3:
/* Event to detect press of mouse button 3 */
/* Switch the display mode to outline mode */
if (bo3)
{
needRedraw = True;
bo1 = True;
bo2 = True;
bo3 = False;
zoomfactor = 0;
}
break;
}
break;
/* Detect to size of X window */
case ConfigureNotify:
xwidth = event.xconfigure.width;
xheight = event.xconfigure.height;
case Expose:
needRedraw = True;
break;
case KeyPress:
count = XLookupString(&event, buffer, bufsize, &keysym, &compose);
/* Exit the program */
if (keysym == XK_F1)
exit(1);
/* Initialize the program */
if (keysym == XK_F2)
{
freeptr();
GetInit();
length = PlugIn(&offerspring[1]);
tree(0, 0, 0, 0, length, 0, offerspring[1].dx, offerspring[1].dy, offerspring[1].dz);
for (i = 1; i < 25 ; i++)
startbiomorph[i] = startbiomorph[0];
displayListInited = False;
needRedraw = True;
bo1 = True;
bo2 = True;
bo3 = False;
}
if (bo2 == False)
{
/* Zoom in */
if (keysym == XK_Left)
{
zoomobj(1);
}
/* Zoom out */
if (keysym == XK_Right)
{
zoomobj(-1);
}
/* Rotate by X axis in 3 degrees */
if (keysym == XK_Insert)
{
recalcModelView = True;
xAngle += 3.0;
}
/* Rotate by Y axis in 3 degrees */
if (keysym == XK_Home)
{
recalcModelView = True;
yAngle += 3.0;
}
/* Rotate by Z axis in 3 degrees */
if (keysym == XK_Page_Up)
{
recalcModelView = True;
zAngle += 3.0;
}
/* Rotate by X axis in -3 degrees */
if (keysym == XK_Delete)
{
recalcModelView = True;
xAngle -= 3.0;
}
/* Rotate by Y axis in -3 degrees */
if (keysym == XK_End)
{
recalcModelView = True;
yAngle -= 3.0;
}
/* Rotate by Z axis in -3 degrees */
if (keysym == XK_Page_Down)
{
recalcModelView = True;
zAngle -= 3.0;
}
}
break;
}
} while (XPending(dpy)); /* Detect the event messages in the event queue */
if (recalcModelView) {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* Move the camera back three units. */
glTranslatef(0.0, 0.0, -3.0);
/* Rotate the 3D Biomorphs */
glRotatef(xAngle, 0.1, 0.0, 0.0);
glRotatef(yAngle, 0.0, 0.1, 0.0);
glRotatef(zAngle, 0.0, 0.0, 1.0);
recalcModelView = False;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, xwidth, xheight);
glCallList(26);
if(doubleBuffer)
glXSwapBuffers(dpy,win);
else
glFlush();
}
/* Redraw the 3D Biomorphs */
if (needRedraw){
redraw();
needRedraw = False;
}
}
}