Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <allegro5/allegro.h>
- #include <math.h>
- #define GL_GLEXT_PROTOTYPES
- #include <GL/gl.h>
- #include <GL/glext.h>
- #define FPS 60
- #define SCREEN_W 640
- #define SCREEN_H 640
- struct glinfo
- {
- GLuint program;
- GLint attribute_coord2d;
- GLint attribute_colour;
- GLuint cube_vertices;
- GLuint cube_colours;
- GLuint cube_elements;
- GLint uniform_mvp;
- GLint uniform_rotation;
- GLint uniform_translation;
- };
- struct allegroinfo
- {
- ALLEGRO_DISPLAY * display;
- ALLEGRO_EVENT_QUEUE * event_queue;
- ALLEGRO_TIMER * timer;
- ALLEGRO_EVENT ev;
- };
- GLint makeshader(char * filename, GLenum type);
- void print_log(GLuint object);
- int init_resources( struct glinfo * glpointers );
- void draw(int rotation, struct glinfo * glpointers );
- struct allegroinfo * startallegro( void );
- void translate(float x, float y, float z, float result[4][4]);
- void multmatrix(float a[4][4], float b[4][4], float result[4][4]);
- void perspective(float fovy, float aspect, float zNear, float zFar, float result[4][4]);
- void lookat(float eyeX, float eyeY, float eyeZ, float centreX, float centreY, float centreZ, float upX, float upY, float upZ, float result[4][4]);
- void rotate(float angle, float x, float y, float z, float result[4][4]);
- int main(void)
- {
- bool redraw=true;
- struct allegroinfo * alinfo = startallegro();
- int rotation = 0;
- struct glinfo * glpointers = malloc ( sizeof ( struct glinfo ) );
- init_resources( glpointers );
- while(1)
- {
- ALLEGRO_EVENT ev;
- al_wait_for_event(alinfo -> event_queue, &ev);
- if(ev.type==ALLEGRO_EVENT_TIMER)
- {
- redraw=true;
- rotation++;
- }
- else if(ev.type==ALLEGRO_EVENT_DISPLAY_CLOSE)
- {
- break;
- }
- if(redraw && al_is_event_queue_empty( alinfo -> event_queue))
- {
- redraw=false;
- draw(rotation, glpointers);
- al_flip_display();
- }
- }
- return 0;
- }
- struct allegroinfo * startallegro( void )
- {
- struct allegroinfo * retval = malloc ( sizeof ( struct allegroinfo ) );
- if(!al_init())
- {
- fprintf(stderr, "failed to initialise allegro!\n");
- return 0;
- }
- retval -> timer = al_create_timer ( 1.0 / FPS );
- if(!retval -> timer )
- {
- fprintf( stderr, "failed to create timer!\n" );
- return 0;
- }
- al_set_new_display_flags(ALLEGRO_OPENGL);
- retval -> display = al_create_display ( SCREEN_W , SCREEN_H );
- if(!retval -> display)
- {
- fprintf(stderr, "failed to create display!\n");
- return 0;
- }
- retval -> event_queue = al_create_event_queue();
- if(!retval -> event_queue)
- {
- fprintf(stderr, "failed to create event queue!\n");
- return 0;
- }
- al_register_event_source(retval -> event_queue, al_get_display_event_source(retval->display));
- al_register_event_source( retval -> event_queue, al_get_timer_event_source(retval->timer));
- al_start_timer ( retval -> timer );
- return retval;
- }
- int init_resources( struct glinfo * glpointers)
- {
- GLint link_ok = GL_FALSE;
- GLuint vs;
- GLuint fs;
- glEnable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- GLfloat cube_vertices[] = {
- // front
- -1.0, -1.0, 1.0,
- 1.0, -1.0, 1.0,
- 1.0, 1.0, 1.0,
- -1.0, 1.0, 1.0,
- // back
- -1.0, -1.0, -1.0,
- 1.0, -1.0, -1.0,
- 1.0, 1.0, -1.0,
- -1.0, 1.0, -1.0,
- };
- GLfloat cube_colours[] = {
- //front colors
- 1.0, 0.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 0.0, 1.0,
- 1.0, 1.0, 1.0,
- // back colors
- 1.0, 0.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 0.0, 1.0,
- 1.0, 1.0, 1.0,
- };
- GLushort cube_elements[] = {
- //front
- 0,1,2,
- 2,3,0,
- //top
- 1,5,6,
- 6,2,1,
- //back
- 7,6,5,
- 5,4,7,
- //bottom
- 4,0,3,
- 3,7,4,
- //left
- 4,5,1,
- 1,0,4,
- //right
- 3,2,6,
- 6,7,3
- };
- glGenBuffers(1, &( glpointers -> cube_vertices ));
- glBindBuffer(GL_ARRAY_BUFFER, glpointers -> cube_vertices);
- glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);
- glGenBuffers(1, &( glpointers -> cube_colours));
- glBindBuffer(GL_ARRAY_BUFFER, glpointers -> cube_colours);
- glBufferData(GL_ARRAY_BUFFER, sizeof(cube_colours), cube_colours, GL_STATIC_DRAW);
- glGenBuffers(1, &( glpointers -> cube_elements));
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glpointers -> cube_elements);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- if(( vs = makeshader("vertex.v.glsl", GL_VERTEX_SHADER)) == 0)
- return 0;
- if(( fs = makeshader("fragment.f.glsl", GL_FRAGMENT_SHADER)) == 0)
- return 0;
- glpointers -> program = glCreateProgram();
- glAttachShader( glpointers -> program, vs);
- glAttachShader( glpointers -> program, fs);
- glLinkProgram( glpointers -> program);
- glGetProgramiv( glpointers -> program, GL_LINK_STATUS, &link_ok);
- if (!link_ok) {
- fprintf(stderr, "glLinkProgram:");
- print_log( glpointers -> program);
- return 0;
- }
- const char* attribute_name = "coord2d";
- glpointers -> attribute_coord2d = glGetAttribLocation( glpointers -> program, attribute_name);
- if (glpointers -> attribute_coord2d == -1) {
- fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
- return 0;
- }
- attribute_name = "v_colour";
- glpointers -> attribute_colour = glGetAttribLocation( glpointers -> program, attribute_name);
- if(glpointers -> attribute_colour == -1)
- {
- fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
- return 1;
- }
- attribute_name = "mvp";
- glpointers -> uniform_mvp = glGetUniformLocation (glpointers -> program, attribute_name);
- if(glpointers -> uniform_mvp == -1)
- {
- fprintf(stderr, "Could not bind uniform %s\n", attribute_name);
- return 0;
- }
- return 1;
- }
- void draw(int rotation, struct glinfo * glpointers)
- {
- int size;
- float r[4][4]; //holds a rotation, to be applied before m, so multiplied in before it
- float m[4][4]; //holds a translation to move the cube away from the screen
- float v[4][4]; //holds the view matrix output by lookat()
- float p[4][4]; //holds the projection matrix we get from perspective
- float mvp[4][4]; //holds the final matrix equal to p * v * m * r
- float temp[4][4];
- float temp2[4][4];
- perspective(45.0, SCREEN_W/(float)SCREEN_H, 0.1, 10, p);
- translate(0.0, 0.0, -4.0, m);
- lookat(0,2,0,0,0,-4,0,1,0, v);
- rotate(((float)rotation)/60.0, 0.0, 1.0, 0.0, r);
- if(rotation%360==0)
- {
- printf("Full turn!\n");
- }
- multmatrix(p,v,temp);
- multmatrix(temp,m,temp2);
- multmatrix(temp2, r, mvp);
- /* Clear the background as white */
- glClearColor(1.0, 1.0, 1.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glUseProgram(glpointers -> program);
- glUniformMatrix4fv(glpointers -> uniform_mvp, 1, GL_FALSE, (GLfloat *) mvp);
- glBindBuffer(GL_ARRAY_BUFFER, glpointers -> cube_vertices);
- glEnableVertexAttribArray(glpointers -> attribute_coord2d);
- /* Describe our vertices array to OpenGL (it can't guess its format automatically) */
- glVertexAttribPointer(
- glpointers -> attribute_coord2d, // attribute
- 3, // number of elements per vertex, here (x,y,z)
- GL_FLOAT, // the type of each element
- GL_FALSE, // take our values as-is
- 0, // stride
- 0 // offset of first element
- );
- glBindBuffer(GL_ARRAY_BUFFER, glpointers -> cube_colours);
- glEnableVertexAttribArray(glpointers -> attribute_colour);
- glVertexAttribPointer(
- glpointers -> attribute_colour,
- 3,
- GL_FLOAT,
- GL_FALSE,
- 0,
- 0
- );
- /* Push each element in buffer_vertices to the vertex shader */
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glpointers -> cube_elements);
- glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
- glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
- glDisableVertexAttribArray(glpointers -> attribute_coord2d);
- glDisableVertexAttribArray(glpointers -> attribute_colour);
- }
- #define BLOCKSIZE 512
- #define BLOCK (BLOCKSIZE*sizeof(char))
- char * readfile(char * filename)
- {
- int size;
- int read=0; //total we've read
- char * retval = malloc(size=(BLOCK));
- char * temp;
- FILE * in = fopen(filename, "r");
- if(!retval)
- {
- printf("Memory allocation failure in readfile\n");
- return NULL;
- }
- if ( ! in )
- {
- printf("%s\n", strerror(errno));
- }
- read+=fread(retval, sizeof(char), BLOCKSIZE, in);
- while(!feof(in))
- {
- temp=realloc(retval, size+=BLOCK);
- if(temp)
- {
- retval=temp;
- }
- else
- {
- printf("Memory allocation failure in readfile\n");
- return NULL;
- }
- read+=fread(retval+read, sizeof(char), BLOCK, in);
- }
- retval=realloc(retval, read+1);
- retval[read]='\0';
- return retval;
- }
- /*
- * Display compilation errors from the OpenGL shader compiler
- */
- void print_log(GLuint object)
- {
- GLint log_length = 0;
- if (glIsShader(object))
- glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
- else if (glIsProgram(object))
- glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
- else {
- fprintf(stderr, "printlog: Not a shader or a program\n");
- return;
- }
- char* log = (char*)malloc(log_length);
- if (glIsShader(object))
- glGetShaderInfoLog(object, log_length, NULL, log);
- else if (glIsProgram(object))
- glGetProgramInfoLog(object, log_length, NULL, log);
- fprintf(stderr, "%s", log);
- free(log);
- }
- GLint makeshader(char * filename, GLenum type)
- {
- const GLchar * source = readfile(filename);
- GLuint shader = glCreateShader(type);
- GLint compile_ok = GL_FALSE;
- if(source==NULL)
- {
- printf("Failure reading file\n");
- return 0;
- }
- glShaderSource(shader, 1, &source, NULL);
- free((void *) source);
- glCompileShader(shader);
- glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_ok);
- if(!compile_ok)
- {
- fprintf(stderr, "%s", filename);
- print_log(shader);
- glDeleteShader(shader);
- return 0;
- }
- return shader;
- }
- void normalise(float vec[4])
- {
- float x=vec[0]/vec[3];
- float y=vec[1]/vec[3];
- float z=vec[2]/vec[3];
- float length=sqrtf(x*x + y*y + z*z);
- vec[0]=x/length;
- vec[1]=y/length;
- vec[2]=z/length;
- vec[3]=1;
- }
- void perspective(float fovy, float aspect, float zNear, float zFar, float result[4][4])
- {
- float f=1/tanf(fovy/2);
- result[0][0]=f/aspect;
- result[0][1]=0;
- result[0][2]=0;
- result[0][3]=0;
- result[1][0]=0;
- result[1][1]=f;
- result[1][2]=0;
- result[1][3]=0;
- result[2][0]=0;
- result[2][1]=0;
- result[2][2]=(zFar+zNear)/(zNear-zFar);
- result[2][3]=-1;
- result[3][0]=0;
- result[3][1]=0;
- result[3][2]=(2*zNear*zFar)/(zNear-zFar);
- result[3][3]=0;
- }
- void crossproduct(float a[4], float b[4], float result[4]);
- void lookat(float eyeX, float eyeY, float eyeZ, float centreX, float centreY, float centreZ, float upX, float upY, float upZ, float result[4][4])
- {
- float f[4] = {centreX-eyeX, centreY-eyeY, centreZ-eyeZ, 1};
- float u[4] = {upX, upY, upZ, 1};
- float s[4];
- float temp[4][4];
- float temp2[4][4];
- normalise(f);
- normalise(u);
- crossproduct(f, u, s);
- crossproduct(s, f, u);
- temp[0][0]=s[0];
- temp[1][0]=s[1];
- temp[2][0]=s[2];
- temp[3][0]=0;
- temp[0][1]=u[0];
- temp[1][1]=u[1];
- temp[2][1]=u[2];
- temp[3][1]=0;
- temp[0][2]=-f[0];
- temp[1][2]=-f[1];
- temp[2][2]=-f[2];
- temp[3][2]=0;
- temp[0][3]=0;
- temp[1][3]=0;
- temp[2][3]=0;
- temp[3][3]=1;
- translate(-eyeX, -eyeY, -eyeZ, temp2);
- multmatrix(temp, temp2, result);
- }
- void crossproduct(float a[4], float b[4], float result[4])
- {
- result[0] = (a[1]*b[2]) - (a[2] * b[1]);
- result[1] = (a[2]*b[0]) - (a[0] * b[2]);
- result[2] = (a[0]*b[1]) - (a[1] * b[0]);
- result[3] = 1;
- }
- void multmatrix(float a[4][4], float b[4][4], float result[4][4])
- {
- int i;
- int j;
- int k;
- float total;
- for(i=0;i<4;i++)
- for(j=0;j<4;j++)
- {
- total=0;
- for(k=0;k<4;k++)
- total+=a[k][i]*b[j][k];
- result[j][i]=total;
- }
- }
- void translate(float x, float y, float z, float result[4][4])
- {
- result[0][0]=1;
- result[0][1]=0;
- result[0][2]=0;
- result[0][3]=0;
- result[1][0]=0;
- result[1][1]=1;
- result[1][2]=0;
- result[1][3]=0;
- result[2][0]=0;
- result[2][1]=0;
- result[2][2]=1;
- result[2][3]=0;
- result[3][0]=x;
- result[3][1]=y;
- result[3][2]=z;
- result[3][3]=1;
- }
- void rotate(float angle, float x, float y, float z, float result[4][4])
- {
- float vec[4]={x, y, z, 1};
- float c=cosf(angle);
- float s=sinf(angle);
- normalise(vec);
- result[0][0]=x*x*(1-c)+c;
- result[0][1]=y*x*(1-c)+z*s;
- result[0][2]=z*x*(1-c)-y*s;
- result[0][3]=0;
- result[1][0]=x*y*(1-c)-z*s;
- result[1][1]=y*y*(1-c)+c;
- result[1][2]=z*y*(1-c)+x*s;
- result[1][3]=0;
- result[2][0]=x*z*(1-c)+y*s;
- result[2][1]=y*z*(1-c)-x*s;
- result[2][2]=z*z*(1-c)+c;
- result[2][3]=0;
- result[3][0]=0;
- result[3][1]=0;
- result[3][2]=0;
- result[3][3]=1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement