/*
* James Steven Supancic III
*/
#include <iostream>
#include <complex>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
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;
}