Advertisement
Guest User

Untitled

a guest
Sep 20th, 2019
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.45 KB | None | 0 0
  1. /*
  2.  *
  3.  * Demonstrates how to load and display an Wavefront OBJ file.
  4.  * Using triangles and normals as static object. No texture mapping.
  5.  *
  6.  * OBJ files must be triangulated!!!
  7.  * Non triangulated objects wont work!
  8.  * You can use Blender to triangulate
  9.  *
  10.  */
  11.  
  12. #include <windows.h>
  13. #include <iostream>
  14. #include <fstream>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <GL/gl.h>
  18. #include <GL/glu.h>
  19. #include <GL/glut.h>
  20. #include <iostream>
  21. #include <sstream>
  22. #include <fstream>
  23. #include <string>
  24. #include <vector>
  25. #include <cmath>
  26.  
  27. #define KEY_ESCAPE 27
  28.  
  29. using namespace std;
  30.  
  31. /************************************************************************
  32.  Window
  33.  ************************************************************************/
  34.  
  35. typedef struct {
  36.     int width;
  37.     int height;
  38.     char* title;
  39.  
  40.     float field_of_view_angle;
  41.     float z_near;
  42.     float z_far;
  43. } glutWindow;
  44.  
  45. /***************************************************************************
  46.  OBJ Loading
  47.  ***************************************************************************/
  48.  
  49. class Model_OBJ {
  50. public:
  51.     Model_OBJ();
  52.     float* calculateNormal(float* coord1, float* coord2, float* coord3);
  53.     int Load(char *filename); // Loads the model
  54.     void Draw(); // Draws the model on the screen
  55.     void Release(); // Release the model
  56.  
  57.     float* normals; // Stores the normals
  58.     float* Faces_Triangles; // Stores the triangles
  59.     float* vertexBuffer; // Stores the points which make the object
  60.     long TotalConnectedPoints; // Stores the total number of connected verteces
  61.     long TotalConnectedTriangles; // Stores the total number of connected triangles
  62.  
  63. };
  64.  
  65. #define POINTS_PER_VERTEX 3
  66. #define TOTAL_FLOATS_IN_TRIANGLE 9
  67. using namespace std;
  68.  
  69. Model_OBJ::Model_OBJ() {
  70.     this->TotalConnectedTriangles = 0;
  71.     this->TotalConnectedPoints = 0;
  72. }
  73.  
  74. float* Model_OBJ::calculateNormal(float *coord1, float *coord2, float *coord3) {
  75.     /* calculate Vector1 and Vector2 */
  76.     float va[3], vb[3], vr[3], val;
  77.     va[0] = coord1[0] - coord2[0];
  78.     va[1] = coord1[1] - coord2[1];
  79.     va[2] = coord1[2] - coord2[2];
  80.  
  81.     vb[0] = coord1[0] - coord3[0];
  82.     vb[1] = coord1[1] - coord3[1];
  83.     vb[2] = coord1[2] - coord3[2];
  84.  
  85.     /* cross product */
  86.     vr[0] = va[1] * vb[2] - vb[1] * va[2];
  87.     vr[1] = vb[0] * va[2] - va[0] * vb[2];
  88.     vr[2] = va[0] * vb[1] - vb[0] * va[1];
  89.  
  90.     /* normalization factor */
  91.     val = sqrt(vr[0] * vr[0] + vr[1] * vr[1] + vr[2] * vr[2]);
  92.  
  93.     float norm[3];
  94.     norm[0] = vr[0] / val;
  95.     norm[1] = vr[1] / val;
  96.     norm[2] = vr[2] / val;
  97.  
  98.     return norm;
  99. }
  100.  
  101. int Model_OBJ::Load(char* filename) {
  102.     string line;
  103.     ifstream objFile(filename);
  104.     if (objFile.is_open())                      // If obj file is open, continue
  105.     {
  106.         objFile.seekg(0, ios::end);                 // Go to end of the file,
  107.         long fileSize = objFile.tellg();                        // get file size
  108.         objFile.seekg(0, ios::beg); // we'll use this to register memory for our 3d model
  109.  
  110.         vertexBuffer = (float*) malloc(fileSize);// Allocate memory for the verteces
  111.         Faces_Triangles = (float*) malloc(fileSize * sizeof(float));// Allocate memory for the triangles
  112.         normals = (float*) malloc(fileSize * sizeof(float));// Allocate memory for the normals
  113.  
  114.         int triangle_index = 0;                 // Set triangle index to zero
  115.         int normal_index = 0;                       // Set normal index to zero
  116.  
  117.         while (!objFile.eof())                      // Start reading file data
  118.         {
  119.             getline(objFile, line);                     // Get line from file
  120.  
  121.             if (line.c_str()[0] == 'v') // The first character is a v: on this line is a vertex stored.
  122.                     {
  123.                 line[0] = ' ';// Set first character to 0. This will allow us to use sscanf
  124.  
  125.                 sscanf(line.c_str(),
  126.                         "%f %f %f ",    // Read floats from the line: v X Y Z
  127.                         &vertexBuffer[TotalConnectedPoints],
  128.                         &vertexBuffer[TotalConnectedPoints + 1],
  129.                         &vertexBuffer[TotalConnectedPoints + 2]);
  130.  
  131.                 TotalConnectedPoints += POINTS_PER_VERTEX;// Add 3 to the total connected points
  132.             }
  133.             if (line.c_str()[0] == 'f') // The first character is an 'f': on this line is a point stored
  134.                     {
  135.                 line[0] = ' ';// Set first character to 0. This will allow us to use sscanf
  136.  
  137.                 int vertexNumber[4] = { 0, 0, 0 };
  138.                 sscanf(line.c_str(), "%i%i%i",// Read integers from the line:  f 1 2 3
  139.                         &vertexNumber[0],// First point of our triangle. This is an
  140.                         &vertexNumber[1],   // pointer to our vertexBuffer list
  141.                         &vertexNumber[2]);  // each point represents an X,Y,Z.
  142.  
  143.                 vertexNumber[0] -= 1;       // OBJ file starts counting from 1
  144.                 vertexNumber[1] -= 1;       // OBJ file starts counting from 1
  145.                 vertexNumber[2] -= 1;       // OBJ file starts counting from 1
  146.  
  147.                 /********************************************************************
  148.                  * Create triangles (f 1 2 3) from points: (v X Y Z) (v X Y Z) (v X Y Z).
  149.                  * The vertexBuffer contains all verteces
  150.                  * The triangles will be created using the verteces we read previously
  151.                  */
  152.  
  153.                 int tCounter = 0;
  154.                 for (int i = 0; i < POINTS_PER_VERTEX; i++) {
  155.                     Faces_Triangles[triangle_index + tCounter] = vertexBuffer[3
  156.                             * vertexNumber[i]];
  157.                     Faces_Triangles[triangle_index + tCounter + 1] =
  158.                             vertexBuffer[3 * vertexNumber[i] + 1];
  159.                     Faces_Triangles[triangle_index + tCounter + 2] =
  160.                             vertexBuffer[3 * vertexNumber[i] + 2];
  161.                     tCounter += POINTS_PER_VERTEX;
  162.                 }
  163.  
  164.                 /*********************************************************************
  165.                  * Calculate all normals, used for lighting
  166.                  */
  167.                 float coord1[3] = { Faces_Triangles[triangle_index],
  168.                         Faces_Triangles[triangle_index + 1],
  169.                         Faces_Triangles[triangle_index + 2] };
  170.                 float coord2[3] = { Faces_Triangles[triangle_index + 3],
  171.                         Faces_Triangles[triangle_index + 4],
  172.                         Faces_Triangles[triangle_index + 5] };
  173.                 float coord3[3] = { Faces_Triangles[triangle_index + 6],
  174.                         Faces_Triangles[triangle_index + 7],
  175.                         Faces_Triangles[triangle_index + 8] };
  176.                 float *norm = this->calculateNormal(coord1, coord2, coord3);
  177.  
  178.                 tCounter = 0;
  179.                 for (int i = 0; i < POINTS_PER_VERTEX; i++) {
  180.                     normals[normal_index + tCounter] = norm[0];
  181.                     normals[normal_index + tCounter + 1] = norm[1];
  182.                     normals[normal_index + tCounter + 2] = norm[2];
  183.                     tCounter += POINTS_PER_VERTEX;
  184.                 }
  185.  
  186.                 triangle_index += TOTAL_FLOATS_IN_TRIANGLE;
  187.                 normal_index += TOTAL_FLOATS_IN_TRIANGLE;
  188.                 TotalConnectedTriangles += TOTAL_FLOATS_IN_TRIANGLE;
  189.             }
  190.         }
  191.         objFile.close();                                    // Close OBJ file
  192.     } else {
  193.         cout << "Unable to open file";
  194.     }
  195.     return 0;
  196. }
  197.  
  198. void Model_OBJ::Release() {
  199.     free(this->Faces_Triangles);
  200.     free(this->normals);
  201.     free(this->vertexBuffer);
  202. }
  203.  
  204. void Model_OBJ::Draw() {
  205.     glEnableClientState(GL_VERTEX_ARRAY);               // Enable vertex arrays
  206.     glEnableClientState(GL_NORMAL_ARRAY);               // Enable normal arrays
  207.     glVertexPointer(3, GL_FLOAT, 0, Faces_Triangles);// Vertex Pointer to triangle array
  208.     glNormalPointer(GL_FLOAT, 0, normals);  // Normal pointer to normal array
  209.     glDrawArrays(GL_TRIANGLES, 0, TotalConnectedTriangles); // Draw the triangles
  210.     glDisableClientState(GL_VERTEX_ARRAY);              // Disable vertex arrays
  211.     glDisableClientState(GL_NORMAL_ARRAY);              // Disable normal arrays
  212. }
  213.  
  214. /***************************************************************************
  215.  * Program code
  216.  ***************************************************************************/
  217.  
  218. Model_OBJ obj;
  219. float g_rotation;
  220. glutWindow win;
  221.  
  222. void display() {
  223.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  224.     glLoadIdentity();
  225.     gluLookAt(0, 1, 4, 0, 0, 0, 0, 1, 0);
  226.     glPushMatrix();
  227.     glRotatef(g_rotation, 0, 1, 0);
  228.     glRotatef(90, 0, 1, 0);
  229.     g_rotation++;
  230.     obj.Draw();
  231.     glPopMatrix();
  232.     glutSwapBuffers();
  233. }
  234.  
  235. void initialize() {
  236.     glMatrixMode(GL_PROJECTION);
  237.     glViewport(0, 0, win.width, win.height);
  238.     GLfloat aspect = (GLfloat) win.width / win.height;
  239.     glMatrixMode(GL_PROJECTION);
  240.     glLoadIdentity();
  241.     gluPerspective(win.field_of_view_angle, aspect, win.z_near, win.z_far);
  242.     glMatrixMode(GL_MODELVIEW);
  243.     glShadeModel(GL_SMOOTH);
  244.     glClearColor(0.0f, 0.1f, 0.0f, 0.5f);
  245.     glClearDepth(1.0f);
  246.     glEnable(GL_DEPTH_TEST);
  247.     glDepthFunc(GL_LEQUAL);
  248.     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  249.  
  250.     GLfloat amb_light[] = { 0.1, 0.1, 0.1, 1.0 };
  251.     GLfloat diffuse[] = { 0.6, 0.6, 0.6, 1 };
  252.     GLfloat specular[] = { 0.7, 0.7, 0.3, 1 };
  253.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb_light);
  254.     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
  255.     glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
  256.     glEnable(GL_LIGHT0);
  257.     glEnable(GL_COLOR_MATERIAL);
  258.     glShadeModel(GL_SMOOTH);
  259.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
  260.     glDepthFunc(GL_LEQUAL);
  261.     glEnable(GL_DEPTH_TEST);
  262.     glEnable(GL_LIGHTING);
  263.     glEnable(GL_LIGHT0);
  264. }
  265.  
  266. void keyboard(unsigned char key, int x, int y) {
  267.     switch (key) {
  268.     case KEY_ESCAPE:
  269.         exit(0);
  270.         break;
  271.     default:
  272.         break;
  273.     }
  274. }
  275.  
  276. int main(int argc, char **argv) {
  277.     // set window values
  278.     win.width = 800;
  279.     win.height = 600;
  280.     win.title = "OpenGL/GLUT OBJ Loader.";
  281.     win.field_of_view_angle = 80;
  282.     win.z_near = 1.0f;
  283.     win.z_far = 500.0f;
  284.  
  285.     // initialize and run program
  286.     glutInit(&argc, argv);                                // GLUT initialization
  287.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);  // Display Mode
  288.     glutInitWindowSize(win.width, win.height);              // set window size
  289.     glutCreateWindow(win.title);                                // create Window
  290.     glutDisplayFunc(display);                       // register Display Function
  291.     glutIdleFunc(display);                          // register Idle Function
  292.     glutKeyboardFunc(keyboard);                     // register Keyboard Handler
  293.     initialize();
  294.     obj.Load("untitled.obj");
  295.     glutMainLoop();                                         // run GLUT mainloop
  296.     return 0;
  297. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement