Advertisement
Guest User

cube

a guest
Feb 21st, 2012
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.59 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <allegro5/allegro.h>
  3. #include <math.h>
  4.  
  5. #define GL_GLEXT_PROTOTYPES
  6. #include <GL/gl.h>
  7. #include <GL/glext.h>
  8.  
  9. #define FPS 60
  10. #define SCREEN_W 640
  11. #define SCREEN_H 640
  12.  
  13. struct glinfo
  14. {
  15.     GLuint program;
  16.     GLint attribute_coord2d;
  17.     GLint attribute_colour;
  18.     GLuint cube_vertices;
  19.     GLuint cube_colours;
  20.     GLuint cube_elements;
  21.     GLint uniform_mvp;
  22.     GLint uniform_rotation;
  23.     GLint uniform_translation;
  24. };
  25.  
  26. struct allegroinfo
  27. {
  28.     ALLEGRO_DISPLAY * display;
  29.     ALLEGRO_EVENT_QUEUE * event_queue;
  30.     ALLEGRO_TIMER * timer;
  31.     ALLEGRO_EVENT ev;
  32. };
  33.  
  34. GLint makeshader(char * filename, GLenum type);
  35. void print_log(GLuint object);
  36. int init_resources( struct glinfo * glpointers );
  37. void draw(int rotation, struct glinfo * glpointers );
  38. struct allegroinfo * startallegro( void );
  39. void translate(float x, float y, float z, float result[4][4]);
  40. void multmatrix(float a[4][4], float b[4][4], float result[4][4]);
  41. void perspective(float fovy, float aspect, float zNear, float zFar, float result[4][4]);
  42. void lookat(float eyeX, float eyeY, float eyeZ, float centreX, float centreY, float centreZ, float upX, float upY, float upZ, float result[4][4]);
  43. void rotate(float angle, float x, float y, float z, float result[4][4]);
  44.  
  45.  
  46. int main(void)
  47. {
  48.     bool redraw=true;
  49.     struct allegroinfo * alinfo = startallegro();
  50.     int rotation = 0;
  51.     struct glinfo * glpointers = malloc ( sizeof ( struct glinfo ) );
  52.  
  53.     init_resources( glpointers );
  54.  
  55.     while(1)
  56.     {
  57.         ALLEGRO_EVENT ev;
  58.         al_wait_for_event(alinfo -> event_queue, &ev);
  59.  
  60.         if(ev.type==ALLEGRO_EVENT_TIMER)
  61.         {
  62.             redraw=true;
  63.             rotation++;
  64.         }
  65.         else if(ev.type==ALLEGRO_EVENT_DISPLAY_CLOSE)
  66.         {
  67.             break;
  68.         }
  69.  
  70.         if(redraw && al_is_event_queue_empty( alinfo -> event_queue))
  71.         {
  72.             redraw=false;
  73.  
  74.             draw(rotation, glpointers);
  75.             al_flip_display();
  76.         }
  77.     }
  78.  
  79.     return 0;
  80.  
  81. }
  82.  
  83. struct allegroinfo * startallegro( void )
  84. {
  85.     struct allegroinfo * retval = malloc ( sizeof ( struct allegroinfo ) );
  86.  
  87.     if(!al_init())
  88.     {
  89.         fprintf(stderr, "failed to initialise allegro!\n");
  90.         return 0;
  91.     }
  92.  
  93.     retval -> timer = al_create_timer ( 1.0 / FPS );
  94.     if(!retval -> timer )
  95.     {
  96.         fprintf( stderr, "failed to create timer!\n" );
  97.         return 0;
  98.     }
  99.  
  100.  
  101.     al_set_new_display_flags(ALLEGRO_OPENGL);
  102.     retval -> display =  al_create_display ( SCREEN_W , SCREEN_H );
  103.     if(!retval -> display)
  104.     {
  105.         fprintf(stderr, "failed to create display!\n");
  106.         return 0;
  107.     }
  108.  
  109.     retval -> event_queue = al_create_event_queue();
  110.     if(!retval -> event_queue)
  111.     {
  112.         fprintf(stderr, "failed to create event queue!\n");
  113.         return 0;
  114.     }
  115.  
  116.     al_register_event_source(retval -> event_queue, al_get_display_event_source(retval->display));
  117.     al_register_event_source( retval -> event_queue, al_get_timer_event_source(retval->timer));
  118.     al_start_timer ( retval -> timer );
  119.  
  120.     return retval;
  121. }
  122.  
  123. int init_resources( struct glinfo * glpointers)
  124. {
  125.     GLint link_ok = GL_FALSE;
  126.     GLuint vs;
  127.     GLuint fs;
  128.  
  129.     glEnable(GL_BLEND);
  130.     glEnable(GL_DEPTH_TEST);
  131.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  132.  
  133.     GLfloat cube_vertices[] = {
  134.         // front
  135.         -1.0, -1.0,  1.0,
  136.         1.0, -1.0,  1.0,
  137.         1.0,  1.0,  1.0,
  138.         -1.0,  1.0,  1.0,
  139.         // back
  140.         -1.0, -1.0, -1.0,
  141.         1.0, -1.0, -1.0,
  142.         1.0,  1.0, -1.0,
  143.         -1.0,  1.0, -1.0,
  144.     };
  145.  
  146.     GLfloat cube_colours[] = {
  147.         //front colors
  148.         1.0, 0.0, 0.0,
  149.         0.0, 1.0, 0.0,
  150.         0.0, 0.0, 1.0,
  151.         1.0, 1.0, 1.0,
  152.         // back colors
  153.         1.0, 0.0, 0.0,
  154.         0.0, 1.0, 0.0,
  155.         0.0, 0.0, 1.0,
  156.         1.0, 1.0, 1.0,
  157.     };
  158.  
  159.     GLushort cube_elements[] = {
  160.         //front
  161.         0,1,2,
  162.         2,3,0,
  163.         //top
  164.         1,5,6,
  165.         6,2,1,
  166.         //back
  167.         7,6,5,
  168.         5,4,7,
  169.         //bottom
  170.         4,0,3,
  171.         3,7,4,
  172.         //left
  173.         4,5,1,
  174.         1,0,4,
  175.         //right
  176.         3,2,6,
  177.         6,7,3
  178.     };
  179.  
  180.     glGenBuffers(1, &( glpointers -> cube_vertices ));
  181.     glBindBuffer(GL_ARRAY_BUFFER, glpointers -> cube_vertices);
  182.     glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);
  183.  
  184.     glGenBuffers(1, &( glpointers -> cube_colours));
  185.     glBindBuffer(GL_ARRAY_BUFFER, glpointers -> cube_colours);
  186.     glBufferData(GL_ARRAY_BUFFER, sizeof(cube_colours), cube_colours, GL_STATIC_DRAW);
  187.  
  188.     glGenBuffers(1, &( glpointers -> cube_elements));
  189.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glpointers -> cube_elements);
  190.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW);
  191.  
  192.     glBindBuffer(GL_ARRAY_BUFFER, 0);
  193.  
  194.     if(( vs = makeshader("vertex.v.glsl", GL_VERTEX_SHADER)) == 0)
  195.         return 0;
  196.     if(( fs = makeshader("fragment.f.glsl", GL_FRAGMENT_SHADER)) == 0)
  197.         return 0;
  198.     glpointers -> program = glCreateProgram();
  199.     glAttachShader( glpointers -> program, vs);
  200.     glAttachShader( glpointers -> program, fs);
  201.     glLinkProgram( glpointers -> program);
  202.     glGetProgramiv( glpointers -> program, GL_LINK_STATUS, &link_ok);
  203.     if (!link_ok) {
  204.         fprintf(stderr, "glLinkProgram:");
  205.         print_log( glpointers -> program);
  206.         return 0;
  207.     }
  208.  
  209.     const char* attribute_name = "coord2d";
  210.     glpointers -> attribute_coord2d = glGetAttribLocation( glpointers -> program, attribute_name);
  211.     if (glpointers -> attribute_coord2d == -1) {
  212.         fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
  213.         return 0;
  214.     }
  215.  
  216.     attribute_name = "v_colour";
  217.     glpointers -> attribute_colour = glGetAttribLocation( glpointers -> program, attribute_name);
  218.     if(glpointers -> attribute_colour == -1)
  219.     {
  220.         fprintf(stderr, "Could not bind attribute %s\n", attribute_name);
  221.         return 1;
  222.     }
  223.  
  224.     attribute_name = "mvp";
  225.     glpointers -> uniform_mvp = glGetUniformLocation (glpointers -> program, attribute_name);
  226.     if(glpointers -> uniform_mvp == -1)
  227.     {
  228.         fprintf(stderr, "Could not bind uniform %s\n", attribute_name);
  229.         return 0;
  230.     }
  231.  
  232.     return 1;
  233. }
  234.  
  235. void draw(int rotation, struct glinfo * glpointers)
  236. {
  237.     int size;
  238.     float r[4][4]; //holds a rotation, to be applied before m, so multiplied in before it
  239.     float m[4][4]; //holds a translation to move the cube away from the screen
  240.     float v[4][4]; //holds the view matrix output by lookat()
  241.     float p[4][4]; //holds the projection matrix we get from perspective
  242.     float mvp[4][4]; //holds the final matrix equal to p * v * m * r
  243.     float temp[4][4];
  244.     float temp2[4][4];
  245.  
  246.     perspective(45.0, SCREEN_W/(float)SCREEN_H, 0.1, 10, p);
  247.     translate(0.0, 0.0, -4.0, m);
  248.     lookat(0,2,0,0,0,-4,0,1,0, v);
  249.     rotate(((float)rotation)/60.0, 0.0, 1.0, 0.0, r);
  250.  
  251.         if(rotation%360==0)
  252.         {
  253.             printf("Full turn!\n");
  254.         }
  255.     multmatrix(p,v,temp);
  256.     multmatrix(temp,m,temp2);
  257.     multmatrix(temp2, r, mvp);
  258.  
  259.     /* Clear the background as white */
  260.     glClearColor(1.0, 1.0, 1.0, 1.0);
  261.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  262.  
  263.     glUseProgram(glpointers -> program);
  264.  
  265.     glUniformMatrix4fv(glpointers -> uniform_mvp, 1, GL_FALSE, (GLfloat *) mvp);
  266.  
  267.     glBindBuffer(GL_ARRAY_BUFFER, glpointers -> cube_vertices);
  268.  
  269.     glEnableVertexAttribArray(glpointers -> attribute_coord2d);
  270.  
  271.     /* Describe our vertices array to OpenGL (it can't guess its format automatically) */
  272.     glVertexAttribPointer(
  273.         glpointers -> attribute_coord2d,      // attribute
  274.         3,                      // number of elements per vertex, here (x,y,z)
  275.         GL_FLOAT,               // the type of each element
  276.         GL_FALSE,           // take our values as-is
  277.         0,          //  stride
  278.         0               // offset of first element
  279.     );
  280.  
  281.     glBindBuffer(GL_ARRAY_BUFFER, glpointers -> cube_colours);
  282.     glEnableVertexAttribArray(glpointers -> attribute_colour);
  283.  
  284.     glVertexAttribPointer(
  285.         glpointers -> attribute_colour,
  286.         3,
  287.         GL_FLOAT,
  288.         GL_FALSE,
  289.         0,
  290.         0
  291.     );
  292.  
  293.     /* Push each element in buffer_vertices to the vertex shader */
  294.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glpointers -> cube_elements);
  295.     glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
  296.     glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
  297.  
  298.     glDisableVertexAttribArray(glpointers -> attribute_coord2d);
  299.     glDisableVertexAttribArray(glpointers -> attribute_colour);
  300.  
  301. }
  302.  
  303. #define BLOCKSIZE 512
  304. #define BLOCK (BLOCKSIZE*sizeof(char))
  305.  
  306. char * readfile(char * filename)
  307. {
  308.     int size;
  309.     int read=0; //total we've read
  310.     char * retval = malloc(size=(BLOCK));
  311.     char * temp;
  312.     FILE * in = fopen(filename, "r");
  313.  
  314.     if(!retval)
  315.     {
  316.         printf("Memory allocation failure in readfile\n");
  317.         return NULL;
  318.     }
  319.  
  320.     if ( ! in )
  321.     {
  322.         printf("%s\n", strerror(errno));
  323.     }
  324.  
  325.     read+=fread(retval, sizeof(char), BLOCKSIZE, in);
  326.  
  327.     while(!feof(in))
  328.     {
  329.         temp=realloc(retval, size+=BLOCK);
  330.         if(temp)
  331.         {
  332.             retval=temp;
  333.         }
  334.         else
  335.         {
  336.             printf("Memory allocation failure in readfile\n");
  337.             return NULL;
  338.         }
  339.         read+=fread(retval+read, sizeof(char), BLOCK, in);
  340.     }
  341.  
  342.     retval=realloc(retval, read+1);
  343.     retval[read]='\0';
  344.     return retval;
  345. }
  346.  
  347. /*
  348.  *   Display compilation errors from the OpenGL shader compiler
  349.  */
  350. void print_log(GLuint object)
  351. {
  352.     GLint log_length = 0;
  353.     if (glIsShader(object))
  354.         glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
  355.     else if (glIsProgram(object))
  356.         glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
  357.     else {
  358.         fprintf(stderr, "printlog: Not a shader or a program\n");
  359.         return;
  360.     }
  361.  
  362.     char* log = (char*)malloc(log_length);
  363.  
  364.     if (glIsShader(object))
  365.         glGetShaderInfoLog(object, log_length, NULL, log);
  366.     else if (glIsProgram(object))
  367.         glGetProgramInfoLog(object, log_length, NULL, log);
  368.  
  369.     fprintf(stderr, "%s", log);
  370.     free(log);
  371. }
  372.  
  373. GLint makeshader(char * filename, GLenum type)
  374. {
  375.     const GLchar * source = readfile(filename);
  376.     GLuint shader = glCreateShader(type);
  377.     GLint compile_ok = GL_FALSE;
  378.  
  379.     if(source==NULL)
  380.     {
  381.         printf("Failure reading file\n");
  382.         return 0;
  383.     }
  384.  
  385.     glShaderSource(shader, 1, &source, NULL);
  386.  
  387.     free((void *) source);
  388.  
  389.     glCompileShader(shader);
  390.     glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_ok);
  391.     if(!compile_ok)
  392.     {
  393.         fprintf(stderr, "%s", filename);
  394.         print_log(shader);
  395.         glDeleteShader(shader);
  396.         return 0;
  397.     }
  398.     return shader;
  399. }
  400.  
  401. void normalise(float vec[4])
  402. {
  403.     float x=vec[0]/vec[3];
  404.     float y=vec[1]/vec[3];
  405.     float z=vec[2]/vec[3];
  406.     float length=sqrtf(x*x + y*y + z*z);
  407.  
  408.     vec[0]=x/length;
  409.     vec[1]=y/length;
  410.     vec[2]=z/length;
  411.     vec[3]=1;
  412. }
  413.  
  414. void perspective(float fovy, float aspect, float zNear, float zFar, float result[4][4])
  415. {
  416.     float f=1/tanf(fovy/2);
  417.  
  418.     result[0][0]=f/aspect;
  419.     result[0][1]=0;
  420.     result[0][2]=0;
  421.     result[0][3]=0;
  422.     result[1][0]=0;
  423.     result[1][1]=f;
  424.     result[1][2]=0;
  425.     result[1][3]=0;
  426.     result[2][0]=0;
  427.     result[2][1]=0;
  428.     result[2][2]=(zFar+zNear)/(zNear-zFar);
  429.     result[2][3]=-1;
  430.     result[3][0]=0;
  431.     result[3][1]=0;
  432.     result[3][2]=(2*zNear*zFar)/(zNear-zFar);
  433.     result[3][3]=0;
  434. }
  435.  
  436. void crossproduct(float a[4], float b[4], float result[4]);
  437.  
  438. void lookat(float eyeX, float eyeY, float eyeZ, float centreX, float centreY, float centreZ, float upX, float upY, float upZ, float result[4][4])
  439. {
  440.     float f[4] = {centreX-eyeX, centreY-eyeY, centreZ-eyeZ, 1};
  441.     float u[4] = {upX, upY, upZ, 1};
  442.     float s[4];
  443.     float temp[4][4];
  444.     float temp2[4][4];
  445.     normalise(f);
  446.     normalise(u);
  447.  
  448.     crossproduct(f, u, s);
  449.     crossproduct(s, f, u);
  450.  
  451.     temp[0][0]=s[0];
  452.     temp[1][0]=s[1];
  453.     temp[2][0]=s[2];
  454.     temp[3][0]=0;
  455.     temp[0][1]=u[0];
  456.     temp[1][1]=u[1];
  457.     temp[2][1]=u[2];
  458.     temp[3][1]=0;
  459.     temp[0][2]=-f[0];
  460.     temp[1][2]=-f[1];
  461.     temp[2][2]=-f[2];
  462.     temp[3][2]=0;
  463.     temp[0][3]=0;
  464.     temp[1][3]=0;
  465.     temp[2][3]=0;
  466.     temp[3][3]=1;
  467.  
  468.     translate(-eyeX, -eyeY, -eyeZ, temp2);
  469.     multmatrix(temp, temp2, result);
  470. }
  471.  
  472. void crossproduct(float a[4], float b[4], float result[4])
  473. {
  474.     result[0] = (a[1]*b[2]) - (a[2] * b[1]);
  475.     result[1] = (a[2]*b[0]) - (a[0] * b[2]);
  476.     result[2] = (a[0]*b[1]) - (a[1] * b[0]);
  477.     result[3] = 1;
  478. }
  479.  
  480. void multmatrix(float a[4][4], float b[4][4], float result[4][4])
  481. {
  482.     int i;
  483.     int j;
  484.     int k;
  485.     float total;
  486.  
  487.     for(i=0;i<4;i++)
  488.         for(j=0;j<4;j++)
  489.         {
  490.             total=0;
  491.             for(k=0;k<4;k++)
  492.                 total+=a[k][i]*b[j][k];
  493.             result[j][i]=total;
  494.         }
  495.  
  496. }
  497.  
  498. void translate(float x, float y, float z, float result[4][4])
  499. {
  500.     result[0][0]=1;
  501.     result[0][1]=0;
  502.     result[0][2]=0;
  503.     result[0][3]=0;
  504.     result[1][0]=0;
  505.     result[1][1]=1;
  506.     result[1][2]=0;
  507.     result[1][3]=0;
  508.     result[2][0]=0;
  509.     result[2][1]=0;
  510.     result[2][2]=1;
  511.     result[2][3]=0;
  512.     result[3][0]=x;
  513.     result[3][1]=y;
  514.     result[3][2]=z;
  515.     result[3][3]=1;
  516. }
  517.  
  518. void rotate(float angle, float x, float y, float z, float result[4][4])
  519. {
  520.     float vec[4]={x, y, z, 1};
  521.     float c=cosf(angle);
  522.     float s=sinf(angle);
  523.     normalise(vec);
  524.  
  525.     result[0][0]=x*x*(1-c)+c;
  526.     result[0][1]=y*x*(1-c)+z*s;
  527.     result[0][2]=z*x*(1-c)-y*s;
  528.     result[0][3]=0;
  529.     result[1][0]=x*y*(1-c)-z*s;
  530.     result[1][1]=y*y*(1-c)+c;
  531.     result[1][2]=z*y*(1-c)+x*s;
  532.     result[1][3]=0;
  533.     result[2][0]=x*z*(1-c)+y*s;
  534.     result[2][1]=y*z*(1-c)-x*s;
  535.     result[2][2]=z*z*(1-c)+c;
  536.     result[2][3]=0;
  537.     result[3][0]=0;
  538.     result[3][1]=0;
  539.     result[3][2]=0;
  540.     result[3][3]=1;
  541. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement