1. #include <iostream>
  2. #include <cstdlib>
  3. #include <stdlib.h>
  4. #include <time.h>
  5.  
  6. #include <Windows.h>
  7.  
  8. #include <GLTools.h>
  9.  
  10. #include <math3d.h>
  11.  
  12. #include <SFML\System.hpp>
  13. #include <SFML\Audio.hpp>
  14. #include <SFML\Window.hpp>
  15.  
  16. //defines
  17. #define BOX_ARRAY_SIZE 5
  18. #define MAX_X 2
  19. #define MAX_Z 2
  20. #define MAX_TEXTURES 1
  21. #define FOV 70.0f
  22. #define ASPECT_RATIO 800.0f/600.0f
  23.  
  24. typedef struct Box {
  25.     M3DVector4f position;
  26.     float rotationOffset, xoffset, zoffset;
  27.     int texture;
  28. } Box;
  29.  
  30. //struct for vertices
  31. typedef struct Vertex {
  32.     M3DVector3f position;
  33.     M3DVector2f texCoord;
  34. } Vertex;
  35.  
  36. //A gigantic global to hold all my stuff
  37. static struct {
  38.     struct {
  39.         M3DMatrix44f projection;
  40.         M3DMatrix44f camera;
  41.         M3DMatrix44f modelViewProjection;
  42.     } modelviewProjection;
  43.  
  44.     GLuint htextures[MAX_TEXTURES];
  45.     GLuint hvBuffer, hiBuffer,htcBuffer,hitcBuffer;
  46.  
  47.     struct {
  48.         GLint m4ModelViewProjection;
  49.         GLint colorMap;
  50.     } uniforms;
  51.  
  52.     struct {
  53.         GLint vVertex, vTexCoord;
  54.     } attributes;
  55.  
  56.     struct {
  57.         GLuint hVertexShader, hFragmentShader, hProgram;
  58.     } shader;
  59.  
  60.     Vertex points[36];
  61. } resources;
  62. //make a simple box object, this si currently irrelevant
  63.  
  64.  
  65. bool readShader(char* name, char** destination) {
  66.     FILE *shader;
  67.     char* shaderText, *nullOffset;
  68.     size_t result;
  69.     long size;
  70.  
  71.     shader = fopen(name, "rb");
  72.     if(shader == NULL) return false;
  73.  
  74.     fseek(shader, 0, SEEK_END);
  75.     size=ftell(shader);
  76.     rewind(shader);
  77.  
  78.     *destination = (char*) malloc(sizeof(char)*(size + 1));
  79.     result = fread(*destination, 1, size, shader);
  80.     nullOffset = (char*)(*destination + sizeof(char)*(size));
  81.     *nullOffset='\0';
  82.     fprintf(stdout, *destination);
  83.     fclose(shader);
  84.     return true;
  85. };
  86.  
  87.  
  88. //boring copypasted tga loading utiilty
  89. static short le_short(unsigned char *bytes)
  90. {
  91.     return bytes[0] | ((char)bytes[1] << 8);
  92. };
  93.  
  94. void *read_tga(const char *filename, int *width, int *height)
  95. {
  96.     struct tga_header {
  97.        char  id_length;
  98.        char  color_map_type;
  99.        char  data_type_code;
  100.        unsigned char  color_map_origin[2];
  101.        unsigned char  color_map_length[2];
  102.        char  color_map_depth;
  103.        unsigned char  x_origin[2];
  104.        unsigned char  y_origin[2];
  105.        unsigned char  width[2];
  106.        unsigned char  height[2];
  107.        char  bits_per_pixel;
  108.        char  image_descriptor;
  109.     } header;
  110.     int i, color_map_size, pixels_size;
  111.     FILE *f;
  112.     size_t read;
  113.     void *pixels;
  114.  
  115.     f = fopen(filename, "rb");
  116.  
  117.     if (!f) {
  118.         fprintf(stderr, "Unable to open %s for reading\n", filename);
  119.         return NULL;
  120.     }
  121.  
  122.     read = fread(&header, 1, sizeof(header), f);
  123.  
  124.     if (read != sizeof(header)) {
  125.         fprintf(stderr, "%s has incomplete tga header\n", filename);
  126.         fclose(f);
  127.         return NULL;
  128.     }
  129.     if (header.data_type_code != 2) {
  130.         fprintf(stderr, "%s is not an uncompressed RGB tga file\n", filename);
  131.         fclose(f);
  132.         return NULL;
  133.     }
  134.     if (header.bits_per_pixel != 24) {
  135.         fprintf(stderr, "%s is not a 24-bit uncompressed RGB tga file\n", filename);
  136.         fclose(f);
  137.         return NULL;
  138.     }
  139.  
  140.     for (i = 0; i < header.id_length; ++i)
  141.         if (getc(f) == EOF) {
  142.             fprintf(stderr, "%s has incomplete id string\n", filename);
  143.             fclose(f);
  144.             return NULL;
  145.         }
  146.  
  147.     color_map_size = le_short(header.color_map_length) * (header.color_map_depth/8);
  148.     for (i = 0; i < color_map_size; ++i)
  149.         if (getc(f) == EOF) {
  150.             fprintf(stderr, "%s has incomplete color map\n", filename);
  151.             fclose(f);
  152.             return NULL;
  153.         }
  154.  
  155.     *width = le_short(header.width); *height = le_short(header.height);
  156.     pixels_size = *width * *height * (header.bits_per_pixel/8);
  157.     pixels = malloc(pixels_size);
  158.  
  159.     read = fread(pixels, 1, pixels_size, f);
  160.  
  161.     if (read != pixels_size) {
  162.         fprintf(stderr, "%s has incomplete image\n", filename);
  163.         fclose(f);
  164.         free(pixels);
  165.         return NULL;
  166.     }
  167.  
  168.     return pixels;
  169. };
  170.  
  171.  
  172. int shaderSetup() {
  173.     char* shaderSrc = NULL;
  174.     GLint shaderStatus;
  175.  
  176.     //read the vertex shader
  177.     if (!readShader("vertexShader.vs", &shaderSrc)) {
  178.         fprintf(stderr, "Vertex Shader Not Found");
  179.         return -1;
  180.     };
  181.     //compile and bind it
  182.     resources.shader.hVertexShader=glCreateShader(GL_VERTEX_SHADER);
  183.     glShaderSource(resources.shader.hVertexShader, 1, (const GLchar**)&shaderSrc, NULL);
  184.     glCompileShader(resources.shader.hVertexShader);
  185.     //check for compiling errors
  186.     glGetShaderiv(resources.shader.hVertexShader, GL_COMPILE_STATUS, &shaderStatus);
  187.     if(shaderStatus==GL_FALSE) {
  188.         char infoLog[1024];
  189.         glGetShaderInfoLog(resources.shader.hVertexShader, 1024, NULL, infoLog);
  190.        
  191.         fprintf(stderr, "Failed to compile shader:\n%s", infoLog);
  192.         return -1;
  193.     };
  194.  
  195.     //free the pointer
  196.     free(shaderSrc);
  197.  
  198.     //same thing again, not sure why I didn't make it more efficient
  199.     if(!readShader("fragmentShader.fs", &shaderSrc)) {
  200.         fprintf(stderr, "Fragment Shader Not Found");
  201.         return -1;
  202.     };
  203.     //same thing
  204.     resources.shader.hFragmentShader=glCreateShader(GL_FRAGMENT_SHADER);
  205.     glShaderSource(resources.shader.hFragmentShader, 1, (const GLchar**)&shaderSrc, NULL);
  206.     glCompileShader(resources.shader.hFragmentShader);
  207.     //check for more fun
  208.     glGetShaderiv(resources.shader.hFragmentShader, GL_COMPILE_STATUS, &shaderStatus);
  209.     if(shaderStatus==GL_FALSE) {
  210.         char infoLog[1024];
  211.         glGetShaderInfoLog(resources.shader.hFragmentShader, 1024, NULL, infoLog);
  212.  
  213.         fprintf(stderr, "Failed to compile shader:\n%s", infoLog);
  214.         return -1;
  215.     };
  216.     //refree the pointer
  217.     free(shaderSrc);
  218.  
  219.     //create a program, bind shaders to it
  220.     resources.shader.hProgram=glCreateProgram();
  221.     glAttachShader(resources.shader.hProgram, resources.shader.hVertexShader);
  222.     glAttachShader(resources.shader.hProgram, resources.shader.hFragmentShader);
  223.     //link it
  224.     glLinkProgram(resources.shader.hProgram);
  225.     //clean up
  226.     glDeleteShader(resources.shader.hFragmentShader);
  227.     glDeleteShader(resources.shader.hVertexShader);
  228.     //final error check
  229.     glGetProgramiv(resources.shader.hProgram, GL_LINK_STATUS, &shaderStatus);
  230.     if(shaderStatus == GL_FALSE) {
  231.         char infoLog[1024];
  232.         glGetProgramInfoLog(resources.shader.hProgram, 1024, NULL, infoLog);
  233.         fprintf(stderr, "The program failed to link:\n%s", infoLog);
  234.         return -1;
  235.     };
  236.     //dig around for attributes and uniforms.
  237.     resources.attributes.vVertex=glGetAttribLocation(resources.shader.hProgram, "vVertex");
  238.     resources.attributes.vTexCoord=glGetAttribLocation(resources.shader.hProgram, "vTexCoord");
  239.     //not sure if these are binding correctly.
  240.     resources.uniforms.m4ModelViewProjection=glGetUniformLocation(resources.shader.hProgram, "m4ModelViewProjection");
  241.     resources.uniforms.colorMap=glGetUniformLocation(resources.shader.hProgram, "colorMap");
  242. };
  243.  
  244. void textureSetup() {
  245.     glGenTextures(4, resources.htextures);
  246.     //load image
  247.     int width, height;
  248.     void *soviet = read_tga("soviet.tga", &width, &height);
  249.     if(!soviet) {
  250.         fprintf(stderr, "could not load texture");
  251.     };
  252.  
  253.     glBindTexture(GL_TEXTURE_2D, resources.htextures[0]);
  254.     //set up the right texture parameters
  255.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  256.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  257.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  258.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  259.  
  260.     //load texture into thing
  261.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, soviet);
  262.     free(soviet);
  263.     if(resources.htextures[0]==0) fprintf(stderr, "failure");
  264. };
  265.  
  266. void makeBuffer(GLuint &handle, void* data, GLenum target, GLsizei bufferSize) {
  267.     glGenBuffers(1, &handle);
  268.     glBindBuffer(target, handle);
  269.     glBufferData(target,bufferSize,data,GL_STATIC_DRAW);
  270. };
  271.  
  272. void testRender() {
  273.     glClearColor(.25f, 0.35f, 0.15f, 1.0f);
  274.     glClear(GL_COLOR_BUFFER_BIT);
  275.     glUniformMatrix4fv(resources.uniforms.m4ModelViewProjection, 1, GL_FALSE, (const GLfloat*)resources.modelviewProjection.modelViewProjection);
  276.     glEnableVertexAttribArray(resources.attributes.vTexCoord);
  277.     glEnableVertexAttribArray(resources.attributes.vVertex);
  278.     //deal with vTexCoord first
  279.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,resources.hiBuffer);
  280.     glBindBuffer(GL_ARRAY_BUFFER, resources.htcBuffer);
  281.     glVertexAttribPointer(resources.attributes.vTexCoord,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*2,(void*)0);
  282.     //now the other one
  283.     glBindBuffer(GL_ARRAY_BUFFER,resources.hvBuffer);
  284.     glVertexAttribPointer(resources.attributes.vVertex,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*3,(void*)0);
  285.     glActiveTexture(GL_TEXTURE0);
  286.     glBindTexture(GL_TEXTURE_2D, resources.htextures[0]);
  287.     glUniform1i(resources.uniforms.colorMap, 0);
  288.     glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (void*)0);
  289.     //clean up a bit
  290. };
  291. int main(int argc, char* argv) {
  292.  
  293.     Box boxes[BOX_ARRAY_SIZE];
  294.  
  295.     srand(time(NULL));
  296.     sf::Window frame(sf::VideoMode(800, 600, 32), "3D Textured Box Thing");
  297.     sf::Event action;
  298.  
  299.     frame.UseVerticalSync(true);
  300.     GLenum err=glewInit();
  301.     if(GLEW_OK != err) return 1;
  302.  
  303.     glEnable(GL_DEPTH_TEST);
  304.     //glEnable(GL_CULL_FACE);
  305.  
  306.     shaderSetup();
  307.     textureSetup();
  308.     //setup boxes, five of them. This number is to change with array size
  309.     for(int i = 0; i<BOX_ARRAY_SIZE; i++) {
  310.         boxes[i].rotationOffset= (rand() % 3600) /10.0f;
  311.         boxes[i].position[0]=((rand() % (MAX_X*20))/10.0f)-MAX_X;
  312.         boxes[i].position[1]=2.0f;
  313.         boxes[i].position[2]=((rand() % (MAX_Z*20))/10.0f)-MAX_Z;
  314.         boxes[i].position[3]=1.0f;
  315.         boxes[i].texture=rand() % MAX_TEXTURES;
  316.     };
  317.     /////////////////////////////////////////////////////
  318.     //set up the projection matrix and camera matrix
  319.     m3dMakePerspectiveMatrix(resources.modelviewProjection.projection, m3dDegToRad(FOV), ASPECT_RATIO, 0.1f, -3.0f);
  320.     //load camera with identity and create a matrix to use with operations
  321.     M3DMatrix44f operation;
  322.     //construct camera as -2 Z
  323.     m3dLoadIdentity44(resources.modelviewProjection.camera);
  324.     m3dTranslationMatrix44(operation, -0.5f, 0.0f,2.0f);
  325.     m3dMatrixMultiply44(resources.modelviewProjection.camera, operation, resources.modelviewProjection.camera);
  326.     //construct viewProjectionMatrix
  327.     //that is, Projection * Camera
  328.     //but first make sure that the camera is inverted
  329.     m3dInvertMatrix44(resources.modelviewProjection.camera, resources.modelviewProjection.camera);
  330.     m3dMatrixMultiply44(resources.modelviewProjection.modelViewProjection, resources.modelviewProjection.projection, resources.modelviewProjection.camera);
  331.     //construct the giant thing of vertex attributes
  332.     GLfloat aCoordinates[108]={//front top triangle
  333.                                   -.25f, .25f, .25f,
  334.                                   .25f, .25f, .25f,
  335.                                   .25f, -.25f, .25f,
  336.                                   //front bottom triangle
  337.                                   -.25, -.25f, .25f,
  338.                                   -.25f, .25f, .25f,
  339.                                   .25f, -.25f, .25f,
  340.                                   //top upper triangle
  341.                                   .25f, .25f, -.25f,
  342.                                   -.25, -.25, .25,
  343.                                   .25, .25, .25,
  344.                                   //top lower triangle
  345.                                   -.25, .25, .25,
  346.                                   .25, .25, .25,
  347.                                   -.25, .25, -.25,
  348.                                   //back upper triangle
  349.                                   .25,-.25,-.25,
  350.                                   -.25,-.25,-.25,
  351.                                   .25,.25,-.25,
  352.                                   //back lower trianle, which is upper
  353.                                   -.25,.25,-.25,
  354.                                   .25,.25,-.25,
  355.                                   -.25,-.25,-.25,
  356.                                   //bottom upper triangle
  357.                                   .25,-.25,.25,
  358.                                   -.25,-.25,.25,
  359.                                   .25,-.25,-.25,
  360.                                   //bottom lower triangle
  361.                                   -.25,-.25,-.25,
  362.                                   .25,-.25,-.25,
  363.                                   -.25,-.25,.25,
  364.                                   //right upper triangle
  365.                                   .25,.25,-.25,
  366.                                   .25,.25,.25,
  367.                                   .25,-.25,-.25,
  368.                                   //right lower triangle
  369.                                   .25,-.25,.25,
  370.                                   .25,-.25,-.25,
  371.                                   .25,.25,.25,
  372.                                   //left upper triangle
  373.                                   -.25,.25,.25,
  374.                                   -.25,.25,-.25,
  375.                                   -.25,-.25,-.25,
  376.                                   //left lower triangle
  377.                                   -.25,-.25,.25,
  378.                                   -.25,.25,.25,
  379.                                   -.25,-.25,-.25,
  380.     };
  381.     GLfloat aTexCoordinates[72]={//front upper triangle
  382.                                      0.0f, 1.0f,
  383.                                      1/6.0f,1.0f,
  384.                                      1/6.0f,1.0f,
  385.                                      //front lower triangle
  386.                                      0.0f,0.0f,
  387.                                      0.0f,1.0f,
  388.                                      1/6.0f,0.0f,
  389.                                      //top upper triangle
  390.                                      2/6.0f,1.0f,
  391.                                      1/6,1.0f,
  392.                                      2/6,0.0f,
  393.                                      //top lower triangle
  394.                                      1/6,0.0f,
  395.                                      2/6,0.0f,
  396.                                      1/6,1.0,
  397.                                      //back upper triangle
  398.                                      3.6,0.0f,
  399.                                      2/6,0.0f,
  400.                                      3/6,1.0f,
  401.                                      //back lower triangle
  402.                                      2/6,1.0f,
  403.                                      3/6,1.0f,
  404.                                      2/6,0.0f,
  405.                                      //bottom upper triangle
  406.                                      4/6,1.0f,
  407.                                      3/6,1.0f,
  408.                                      4/6,0.0f,
  409.                                      //bottom lower triangle
  410.                                      3/6,0.0f,
  411.                                      4/6,0.0f,
  412.                                      3/6,1.0f,
  413.                                      //right upper triangle
  414.                                      5/6,1.0f,
  415.                                      4/6,1.0f,
  416.                                      5/6,0.0f,
  417.                                      //right lower triangle
  418.                                      4/6,0.0f,
  419.                                      5/6,0.0f,
  420.                                      4/6,1.0f,
  421.                                      //left upper triangle
  422.                                      1.0f,1.0f,
  423.                                      5/6,1.0f,
  424.                                      5/6,0.0f,
  425.                                      //left lower triangle
  426.                                      1.0f,0.0f,
  427.                                      1.0f,1.0f,
  428.                                      5/6,0.0f
  429.     };
  430.     GLint elements[36]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35};
  431.     glClearColor(0.35f, 0.35f, 0.35f, 1.0f);
  432.     //use the right shader first
  433.     glUseProgram(resources.shader.hProgram);
  434.     //setup the vertex coordinate buffer
  435.     makeBuffer(resources.hvBuffer,aCoordinates,GL_ARRAY_BUFFER,sizeof(GLfloat)*108);
  436.     makeBuffer(resources.htcBuffer,aTexCoordinates,GL_ARRAY_BUFFER,sizeof(GLfloat)*72);
  437.     makeBuffer(resources.hiBuffer,elements,GL_ELEMENT_ARRAY_BUFFER,sizeof(GLint)*36);
  438.  
  439.  
  440.     while(frame.IsOpened()) {
  441.         frame.GetEvent(action);
  442.         testRender();
  443.         frame.Display();
  444.         if(action.Type == sf::Event::Closed) frame.Close();
  445.     };
  446.     return 0;
  447. };