/* Chad Brewbaker 12.10.2000 * CS147 * 3D Serpenski Triangle Program ver1.0 * * This program draws a 3-D serpenski pyramid. * *Think of all the coordinates as a 3 sided pyramid: * * C * / \ * E/ \G * / \ * A--------B * F * Base * * I * / \ * / \ * h-----J * Middle * * D on Top */ #include #include #include #include #include #define MENU_NULL 0 #define MENU_QUIT 3 #define MENU_START_ROTATION 4 #define MENU_STOP_ROTATION 5 #define MENU_POLY_LINE_TOGGLE 8 int rotationToggle =0; float eyeDif =0.02; int ITERATION_NUM = 4; polyLineToggle =0; static GLfloat rotAngle[3] = {0.0,0.0,0.0}; GLdouble lookVec[]={0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}; void Serpenski( int iterationNum, float xa, float ya, float za, float xb, float yb, float zb, float xc, float yc, float zc, float xd, float yd, float zd) { //the new points to be computed float xe, ye, ze, xf, yf, zf, xg, yg, zg, xh, yh, zh, xi, yi, zi, xj, yj, zj; if(iterationNum < 1) { if(polyLineToggle%2) { glBegin(GL_LINES); //ABD glVertex3f(xa,ya,za); glVertex3f(xb,yb,zb); glVertex3f(xb,yb,zb); glVertex3f(xd,yd,zd); glVertex3f(xd,yd,zd); glVertex3f(xa,ya,za); //BCD glVertex3f(xb,yb,zb); glVertex3f(xc,yc,zc); glVertex3f(xc,yc,zc); glVertex3f(xd,yd,zd); glVertex3f(xd,yd,zd); glVertex3f(xb,yb,zb); //CAD glVertex3f(xc,yc,zc); glVertex3f(xa,ya,za); glVertex3f(xa,ya,za); glVertex3f(xd,yd,zd); glVertex3f(xd,yd,zd); glVertex3f(xc,yc,zc); //ABC glVertex3f(xa,ya,za); glVertex3f(xb,yb,zb); glVertex3f(xb,yb,zb); glVertex3f(xc,yc,zc); glVertex3f(xc,yc,zc); glVertex3f(xa,ya,za); glEnd(); } else { glBegin(GL_POLYGON); //ABD glVertex3f(xa,ya,za); glVertex3f(xb,yb,zb); glVertex3f(xd,yd,zd); glEnd(); glBegin(GL_POLYGON); //BCD glVertex3f(xb,yb,zb); glVertex3f(xc,yc,zc); glVertex3f(xd,yd,zd); glEnd(); glBegin(GL_POLYGON); //CAD glVertex3f(xc,yc,zc); glVertex3f(xa,ya,za); glVertex3f(xd,yd,zd); glEnd(); glBegin(GL_POLYGON); //ABC glVertex3f(xa,ya,za); glVertex3f(xb,yb,zb); glVertex3f(xc,yc,zc); glEnd(); } return; } xe = (xa +xb)/2.0; ye = (ya+yb)/2.0; ze = (za+zb)/2.0; xf = (xc+xb)/2.0; yf = (yc+yb)/2.0; zf = (zc+zb)/2.0; xg = (xa+xc)/2.0; yg = (ya+yc)/2.0; zg = (za+zc)/2.0; xh = (xa +xd)/2.0; yh = (ya+yd)/2.0; zh = (za+zd)/2.0; xi = (xc+xd)/2.0; yi = (yc+yd)/2.0; zi = (zc+zd)/2.0; xj = (xb+xd)/2.0; yj = (yb+yd)/2.0; zj = (zb+zd)/2.0; iterationNum--; //A triangle Serpenski(iterationNum, xa,ya,za, xe,ye,ze, xg,yg,zg, xh,yh,zh); //B triangle Serpenski(iterationNum, xe, ye, ze, xb, yb, zb, xf, yf, zf, xj, yj, zj); //CTriangle Serpenski(iterationNum, xg, yg, zg, xf, yf, zf, xc, yc, zc, xi, yi, zi); //D triangle Serpenski(iterationNum, xh, yh, zh, xj, yj, zj, xi, yi, zi, xd, yd, zd); return; } void serpenskiMain() { Serpenski(ITERATION_NUM, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.4142); //1.4142 == sqrt of two return; } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glColor4f(1.0,0.0,0.0, .5); glTranslatef(eyeDif,0.0,-2.0); glRotatef(rotAngle[0], 1.0, 0.0, 0.0); glRotatef(rotAngle[1], 0.0, 1.0, 0.0); glRotatef(rotAngle[2], 0.0, 0.0, 1.0); serpenskiMain(); glPopMatrix(); glPushMatrix(); glColor4f(0.0,0.0,1.0,.5); glTranslatef(-eyeDif,0.0,-2.0); glRotatef(rotAngle[0], 1.0, 0.0, 0.0); glRotatef(rotAngle[1], 0.0, 1.0, 0.0); glRotatef(rotAngle[2], 0.0, 0.0, 1.0); serpenskiMain(); glPopMatrix(); reshape(800,800 ); glFlush(); glutSwapBuffers(); return; } void rotateCenterOfVision(float theta) { float xcord, zcord; //translate to origin xcord = lookVec[0]-lookVec[3]; zcord = lookVec[2]-lookVec[5]; //rotate theta in the xz plane xcord = ( xcord*cos(theta)) - (zcord*sin(theta)); zcord = (zcord*cos(theta)) +(xcord*sin(theta)); //translate back lookVec[0] = xcord + lookVec[3]; lookVec[2] = zcord + lookVec[5]; } void move(float amount) { float xzSlope,deltaX,deltaZ,distance,xAmount, zAmount, tempX; //find the change in x and z deltaX =lookVec[0]-lookVec[3]; deltaZ =lookVec[2]-lookVec[5]; //Compute the slope xzSlope = deltaZ/deltaX; //now find the distance between (x0,z0) and (x1,z1) distance = sqrt( (deltaX*deltaX)+(deltaZ*deltaZ)); //use the ratio: deltaX/distance == X/amount // deltaZ/distance == Z/amount xAmount=(deltaX*amount)/distance; zAmount=(deltaZ*amount)/distance; //Change center lookVec[2] += zAmount; lookVec[0] += xAmount; //Change eye lookVec[5] += zAmount; lookVec[3] += xAmount; } void keyboard(unsigned char key, int x, int y) { if (key ==27) /* Escape Key */ exit(0); //turn left if(key =='a') rotateCenterOfVision(-.02); //turn right if(key=='d') rotateCenterOfVision(.02); //backwards if(key =='s') move(.05); //forwards if(key == 'w') move(-.05); //Y Up if(key =='r') {lookVec[1] += .1; lookVec[4] += .1;} //Y Down if(key == 'f') {lookVec[1] -= .1; lookVec[4] -= .1;} //Change iterations if(key =='c') ITERATION_NUM ++; if(key == 'v') ITERATION_NUM --; //Focus change if(key =='z') {eyeDif -= .01; printf("\neyedif%f\n", eyeDif);} if(key == 'x') {eyeDif += .01; printf("\neyedif%f\n", eyeDif);} } void init() { srand(clock()); printf("\n***** Serp3D.c ver 1.0 12-10-2000***** "); printf("\n by Chad Brewbaker"); printf("\nRightClick for menu options\n"); printf("\na->Turn left, d->Turn right\nw->Forward,s->backward"); printf("\nr->Y Up, f->Y Down"); printf("\nz,x->Change focus\nc->More Iterations, v->Less Iterations\n"); } void twist() { int cases,i; if(rotationToggle) { cases = (int) (3.0*rand()/(RAND_MAX+1.0));//rand 1-3 for(i=0;i<3;i++) { if(cases == i) { rotAngle[i] += .5; if(rotAngle[i] > 360.0) rotAngle[i] == 0.0; } } } display(); } void myMenu(int menuID) { switch(menuID) { case MENU_START_ROTATION: rotationToggle =1; break; case MENU_STOP_ROTATION: rotationToggle =0; break; case MENU_POLY_LINE_TOGGLE: polyLineToggle ++; break; case MENU_QUIT: exit(0); } } void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, 1.0, .1, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(lookVec[0], lookVec[1], lookVec[2], lookVec[3],lookVec[4], lookVec[5],lookVec[6],lookVec[7],lookVec[8]); } int main (int argc, char ** argv) { glutInit(& argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowPosition(50, 50); glutInitWindowSize(800, 800); glutCreateWindow("Serpenski 3D by Chad Brewbaker"); glutIdleFunc(twist); init(); glClearColor(0.0,0.0,0.0,0.0); glShadeModel(GL_SMOOTH); glutKeyboardFunc(keyboard); glutDisplayFunc(display); glutReshapeFunc(reshape); glutCreateMenu(myMenu); glutAddMenuEntry("Serpenski 3D by CHAD BREWBAKER",MENU_NULL); glutAddMenuEntry("Stop Rotation",MENU_STOP_ROTATION); glutAddMenuEntry("Start Rotation",MENU_START_ROTATION); glutAddMenuEntry("Toggle Line/Polygon mode",MENU_POLY_LINE_TOGGLE); glutAddMenuEntry("Quit",MENU_QUIT); glutAttachMenu(GLUT_RIGHT_BUTTON); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glutMainLoop(); return 0; }