/* Hilbert curve drawing program * by Josh Holtrop */ /* includes */ #include #include #include #include /* constants */ #define SEGMENTS 16 #define WIDTH 800 #define HEIGHT 600 /* macros */ #define keepingMatrix(x) { glPushMatrix(); x; glPopMatrix(); } /* functions */ void usage(void); void initgl(void); void display(void); void mainloop(void); void initLists(void); void tlRtDrwCyl(float x, float y, float z, float a, float u, float v, float w); void drawHilbert(int level, float size, int cap1, int cap2); void drawHilbert1(int cap1, int cap2); /* global variables */ int level = 1; float size = 0.4; SDL_Surface * sdlScreen; int winWidth = WIDTH; int winHeight = HEIGHT; int hilbertList = -1; int sphereList = -1; int cylList = -1; const float diffuse[4] = {0.9f, 0.6f, 0.1f, 1.0f}; int main(int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) { if (!strncmp("-l", argv[i], 2)) { sscanf(argv[i] + 2, "%d", &level); if (level < 1) usage(); } else if (!strncmp("-s", argv[i], 2)) { sscanf(argv[i] + 2, "%f", &size); if (size < 0.01 || size > 0.99) usage(); } else { usage(); } } if (SDL_Init(SDL_INIT_VIDEO)) { printf("Failed to initialize SDL!\n"); return 1; } atexit(SDL_Quit); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if (!(sdlScreen = SDL_SetVideoMode(WIDTH, HEIGHT, 16, SDL_OPENGL | SDL_RESIZABLE))) { printf("Failed to set video mode!\n"); SDL_Quit(); return 2; } SDL_WM_SetCaption(argv[0], argv[0]); initgl(); initLists(); mainloop(); return 0; } void mainloop(void) { SDL_Event event; display(); while (SDL_WaitEvent(&event)) { switch (event.type) { case SDL_QUIT: return; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: return; default: break; } break; case SDL_VIDEORESIZE: break; } } } void initgl(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glShadeModel(GL_SMOOTH); glViewport(0, 0, winWidth, winHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, 1, 0.01, 3000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(10, -10, 10, 0, 0, 0, 0, 0, 1); /* set up materials */ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, diffuse); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glCallList(hilbertList); SDL_GL_SwapBuffers(); } void drawHilbert(int level, float size, int cap1, int cap2) { if (level == 1) { drawHilbert1(cap1, cap2); } } void drawHilbert1(int cap1, int cap2) { if (cap1) { keepingMatrix( glTranslatef(-0.5f, -0.5f, -0.5f); glCallList(sphereList); ) } else { tlRtDrwCyl(-0.5, -1.0, -0.5, 90, 1.0, 0.0, 0.0); tlRtDrwCyl(-0.5, -0.5, -0.5, 90, 1.0, 0.0, 0.0); } if (cap2) { keepingMatrix( glTranslatef(0.5f, 0.5f, 0.5f); glCallList(sphereList); ) } else { tlRtDrwCyl(-0.5, -1.0, 0.5, 90, 1.0, 0.0, 0.0); tlRtDrwCyl(-0.5, -0.5, 0.5, 90, 1.0, 0.0, 0.0); } glColor3f(0.2, 0.2, 1.0); glDisable(GL_LIGHTING); glBegin(GL_LINE_STRIP); glVertex3f(-0.5, -0.5, -0.5); glVertex3f(-0.5, 0.5, -0.5); glVertex3f(0.5, 0.5, -0.5); glVertex3f(0.5, -0.5, -0.5); glVertex3f(0.5, -0.5, 0.5); glVertex3f(0.5, 0.5, 0.5); glVertex3f(-0.5, 0.5, 0.5); glVertex3f(-0.5, -0.5, 0.5); glEnd(); glEnable(GL_LIGHTING); } void tlRtDrwCyl(float x, float y, float z, float a, float u, float v, float w) { keepingMatrix( glTranslatef(x, y, z); glRotatef(a, u, v, w); glCallList(cylList); ) } void initLists(void) { GLUquadric * q; hilbertList = glGenLists(1); sphereList = glGenLists(1); cylList = glGenLists(1); if (hilbertList < 0 || sphereList < 0 || cylList < 0) { fprintf(stderr, "Error allocating display list!\n"); exit(132); } /* get a quadric object to draw with */ q = gluNewQuadric(); /* draw a sphere */ glNewList(sphereList, GL_COMPILE); gluSphere(q, size, SEGMENTS, SEGMENTS/2); glEndList(); /* draw a cylinder */ glNewList(cylList, GL_COMPILE); gluCylinder(q, size, size, 0.25, SEGMENTS, SEGMENTS/4); glEndList(); /* draw Hilbert curve */ glNewList(hilbertList, GL_COMPILE); drawHilbert(level, size, 1, 1); glEndList(); /* free quadric memory */ gluDeleteQuadric(q); } void usage(void) { printf("Options:\n" " -l level of Hilbert curve to draw (1-?)\n" " -s radius of Hilbert curve (0.01-0.99)\n"); exit(42); }