#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;

}

}

}