Gerard-Meier

Model loader V2

Jun 18th, 2011
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.43 KB | None | 0 0
  1. #ifndef MODELHELPER_H
  2. #define MODELHELPER_H
  3.  
  4. #include <iostream>
  5. #include <string>
  6. #include <sstream>
  7. #include <cstdlib>
  8. #include <gl\glut.h>
  9.  
  10. #include "Vertex.h"
  11. #include "Mesh.h"
  12. #include "Face.h"
  13.  
  14. using namespace std;
  15.  
  16. class ModelHelper {
  17.     public:
  18.         static Mesh* parsePolygon(const char* const fileName) {
  19.             FILE        *fileStream;
  20.             char        data[255];
  21.             errno_t     errorCode;
  22.  
  23.             vector<Vertex>* v  = new vector<Vertex>(); // Vertex
  24.             vector<Vertex>* vt = new vector<Vertex>(); // Texture
  25.             vector<Vertex>* vn = new vector<Vertex>(); // normal
  26.             vector<Face>*   f  = new vector<Face>(); // faces
  27.            
  28.             //vector<Polygon>* polygons = new vector<Polygon>();
  29.  
  30.             // Open the file stream, 0 means no errors are found.
  31.             if((errorCode = fopen_s(&fileStream, fileName, "rt")) == 0) {
  32.                 cout << "Starting to read the model file " << fileName << endl;
  33.                
  34.                 vector<float>* parsedFloats;
  35.  
  36.                 // Read until the end of file is reached.
  37.                 while(!feof(fileStream)) {
  38.                    
  39.                     // Read a line into a char array.
  40.                     readLine(fileStream, data);
  41.                    
  42.                     // Determine what kind of data we are dealing with:
  43.                     switch(data[0]) {
  44.                         case 'm':
  45.                             cout << "Found material file: " << data;
  46.                             break;
  47.                         case 's':
  48.                             //cout << "Using shadow: " << data;
  49.                             break;
  50.                         case 'u':
  51.                             cout << "Using texture: " << data;
  52.                             break;
  53.                         case 'g': // A named group, or label.
  54.                             cout << "Found group:" << data;
  55.                             break;
  56.                         case 'v': // We're dealing with a vertex:
  57.                             parsedFloats = parseNums(data);
  58.                             switch(data[1]) {
  59.                                 case ' ':
  60.                                     v->push_back(Vertex(parsedFloats->at(0), parsedFloats->at(1), parsedFloats->at(2)));
  61.                                     break;
  62.                                 case 't': {
  63.                                     // Note: The 3rd argument is optional.
  64.                                     vt->push_back(Vertex(parsedFloats->at(0), parsedFloats->at(1), (parsedFloats->size() > 2) ? parsedFloats->at(2) : 0));
  65.                                     } break;
  66.                                 case 'n':
  67.                                     vn->push_back(Vertex(parsedFloats->at(0), parsedFloats->at(1), parsedFloats->at(2)));
  68.                                     break;
  69.                             }
  70.  
  71.                             delete parsedFloats;
  72.                             break;
  73.                         case 'f': // We're dealing with a face:
  74.                             vector<stringstream>* chunks = stringSplit(data, ' ', '\n');
  75.                             vector<float>* tmp;
  76.  
  77.                             Face newFace;
  78.                            
  79.                             // For each batch of "0/0/0":
  80.                             for(int i = 0; i < chunks->size(); ++i) {
  81.                                 if(isNumericString(chunks->at(i).str())) {
  82.                                     tmp = parseNums(chunks->at(i).str().c_str());
  83.                                    
  84.                                     // For each number in "0/0/0":
  85.                                     for(int j = 0; j < tmp->size(); ++j) {
  86.                                         switch(j) {
  87.                                             case 0: newFace.vertexIndices.push_back(tmp->at(j)); break;
  88.                                             case 1: newFace.textureIndices.push_back(tmp->at(j)); break;
  89.                                             case 2: newFace.normalIndices.push_back(tmp->at(j)); break;
  90.                                         }
  91.                                     }
  92.                                    
  93.                                     delete tmp;
  94.                                 }
  95.                             }
  96.  
  97.                             f->push_back(newFace);
  98.  
  99.                             delete chunks;
  100.                             //delete tmp;
  101.                             break;
  102.                     }
  103.  
  104.                 }
  105.                 cout << "The end of file " << fileName << " has been reached." << endl;
  106.             } else {
  107.                 cout << "The specified file " << fileName << " cannot be opened. Error code: " << errorCode << endl;
  108.             }
  109.  
  110.             Mesh* mesh = new Mesh(f, v, vt, vn);
  111.  
  112.             return mesh;
  113.         }
  114.  
  115.     private:
  116.         static void readLine(FILE* fileStream, char * string) {
  117.             do {
  118.                 fgets(string, 255, fileStream);
  119.                
  120.             // Simple continue reading if an empty line was found, or a source code comment.
  121.             // Also accounts for the end of a file
  122.             } while (((string[0] == '/') || (string[0] == '\n') || (string[0] == '#')) && !feof(fileStream));
  123.         }
  124.  
  125.         static vector<stringstream>* stringSplit(const char * string, const char needle1, const char needle2 = '!', const char needle3 = '/') { // TODO: use va_arg?
  126.             unsigned char numChunks = 0;
  127.             vector<stringstream>* stringChunks = new vector<stringstream>(3); // Using the initial size of 3 as it's the most common figure.
  128.            
  129.             // Iterate over each character:
  130.             for(unsigned char i = 0; i < strlen(string); ++i) {
  131.                 // We found the split character, increment to the next string buffer.
  132.                 if(string[i] == needle1 || string[i] == needle2 || string[i] == needle3) {
  133.                     ++numChunks;
  134.  
  135.                     // Allocate another stringstream, if required.
  136.                     if(stringChunks->size() <= numChunks) {
  137.                         stringChunks->push_back(stringstream());
  138.                     }
  139.  
  140.                 } else {
  141.                     stringChunks->at(numChunks) << string[i];
  142.                 }
  143.  
  144.             }
  145.  
  146.             return stringChunks;
  147.         }
  148.  
  149.         static vector<float>* parseNums(const char * string) {
  150.             vector<float>* nums = new vector<float>();
  151.  
  152.             vector<stringstream>* chunks = stringSplit(string, ' ', '\n', '/');
  153.  
  154.             for(int i = 0; i < chunks->size(); ++i) {
  155.                
  156.                 if(isNumericString(chunks->at(i).str())) {
  157.                     nums->push_back(atof(chunks->at(i).str().c_str()));
  158.                 }
  159.             }
  160.  
  161.             //for(int i = 0; i < nums->size(); ++i) { cout << nums->at(i) << " "; }
  162.             //cout << endl;
  163.  
  164.             delete chunks;
  165.  
  166.             return nums;
  167.         }
  168.  
  169.         // I'm sure this could've been done better...
  170.         static bool isNumericString(const string str) {
  171.             for(int i = 0; i < str.length(); ++i) {
  172.                 switch(str.at(i)) {
  173.                     case '0': case '1': case '2': // Intentional fall-through.
  174.                     case '3': case '4': case '5':
  175.                     case '6': case '7': case '8':
  176.                     case '9': case '-': case '.':
  177.                     case 'e': case '/':
  178.                     break;
  179.                     default: return false;
  180.                 }
  181.             }
  182.  
  183.             if(str.length() == 0) return false;
  184.  
  185.             return true;
  186.         }
  187.  
  188. };
  189.  
  190. #endif
Advertisement
Add Comment
Please, Sign In to add comment