/* * James Steven Supancic III */ #include #include #include #include using namespace std; double mandelbrot(int x, int y) { /* The point value is the numbre of iterations it takes for * the algorithm to meet the escape condition */ int x0 = x, y0 = y, x2 = x*x, y2 = y*y; int itr = 0, most = 500; while(x2+y2 < 4 and itr < most) { y = 2 * x * y + y0; x = x2 - y2 + x0; x2 = x*x; y2 = y*y; itr++; } /* I want values between 0 and 1*/ return itr/500; } int vertexFromXY(int x, int y, int max_x) { //C++ is row major? return x*max_x+y; } int main(int argc, char** argv) { int win_width = 800, win_height = 600; //dimensions of output window /* SDL code, sets up the output for any platform * Because some people refuse to use X11... */ SDL_Surface *screen; if(SDL_Init(SDL_INIT_VIDEO)) { cout << "Error seting up video" << endl; return 1; } SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); screen = SDL_SetVideoMode( win_width, win_height, 16, SDL_OPENGL ); /* introduce ourself to the graphics computer */ glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_INDEX_ARRAY); glClearColor(.2,.2,1,0); //blue background (sky) glViewport(0,0,win_width, win_height); //inform the video computer of output. /* generate the data for drawing*/ const int range_x = 500, range_y = 500; double (*vertex_data)[range_y][6] = new double[range_x][range_y][6]; //Going to use GL_QUADS GLint (*index_data)[range_y-1][4] = new GLint[range_x-1][range_y-1][4]; for(int xtr = 0; xtr < range_x;xtr++) { for(int ytr = 0; ytr < range_y; ytr++) { /* Fill the Vertex array*/ double thisMan = mandelbrot(xtr,ytr); vertex_data[xtr][ytr][0] = xtr; //x coord; vertex_data[xtr][ytr][1] = ytr; //y coord; vertex_data[xtr][ytr][2] = thisMan*500; //value in [0,500] vertex_data[xtr][ytr][3] = thisMan; //r vertex_data[xtr][ytr][4] = thisMan; //g vertex_data[xtr][ytr][5] = thisMan; //b /* Fill the Index Array */ if(xtr == range_x-1 or ytr == range_y -1) { continue; } index_data[xtr][ytr][0] = vertexFromXY(xtr,ytr,range_x); index_data[xtr][ytr][1] = vertexFromXY(xtr,ytr+1,range_x); index_data[xtr][ytr][2] = vertexFromXY(xtr+1,ytr+1,range_x); index_data[xtr][ytr][3] = vertexFromXY(xtr+1,ytr,range_x); } }// O[n^3]!!! //get the address of the VBO functions. //native VBO support is fairly recent, so to support older machines we need to do this void (*glGenBuffers)(GLsizei,GLuint*) = (void (*)(GLsizei,GLuint*))SDL_GL_GetProcAddress("glGenBuffers"); void (*glBindBuffer)(GLenum,GLuint) = (void (*)(GLenum,GLuint))SDL_GL_GetProcAddress("glBindBuffer"); void (*glBufferData)(GLenum,GLsizeiptr,const GLvoid*,GLenum) = (void (*)(GLenum,GLsizeiptr,const GLvoid*,GLenum))SDL_GL_GetProcAddress("glBufferData"); if(glGenBuffers == NULL || glBindBuffer == NULL || glBufferData == NULL) { cout << "Your machine doesn't support VBOs" << endl; cout << "good bye" << endl; } //get vertex buffers and upload data to the graphics computer GLuint buffers[2]; glGenBuffers(2,buffers); glBindBuffer(GL_ARRAY_BUFFER,buffers[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[1]); glBufferData(GL_ARRAY_BUFFER,range_x*range_y*6,vertex_data,GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER,range_x*range_y*4,index_data,GL_STATIC_DRAW); //now tell the graphics machine what the data means... glVertexPointer(3,GL_DOUBLE,3,vertex_data); glColorPointer(3,GL_DOUBLE,3,vertex_data+3); /* enter a input polling loop with SDL * Normally I would use xlib, but some people * still insist on use non x11 based hosts... */ SDL_Event ev; while(true) { /* clear the frame */ glClear(GL_COLOR_BUFFER_BIT); /* setup the camera */ glLoadIdentity(); gluLookAt(range_x/2,range_y/2,800, range_x/2,range_y/2,0, 0,1,0); /*draw the frame*/ cout << "Drawing " << range_x*range_y*4 << " vertex" << endl; glDrawElements(GL_QUADS,range_x*range_y*4,GL_UNSIGNED_INT,index_data); /* show the frame*/ glFlush(); SDL_GL_SwapBuffers(); /* Check for Input * exit the application on escape */ SDL_PollEvent(&ev); switch(ev.type) { case SDL_KEYUP: switch(ev.key.keysym.sym) { case SDLK_ESCAPE: cout << "you hit escape! " << endl; return 0; } default: continue; } } return 0; }