Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef MODELHELPER_H
- #define MODELHELPER_H
- #include <iostream>
- #include <string>
- #include <sstream>
- #include <cstdlib>
- #include <gl\glut.h>
- #include "Vertex.h"
- #include "Mesh.h"
- #include "Face.h"
- using namespace std;
- class ModelHelper {
- public:
- static Mesh* parsePolygon(const char* const fileName) {
- FILE *fileStream;
- char data[255];
- errno_t errorCode;
- vector<Vertex>* v = new vector<Vertex>(); // Vertex
- vector<Vertex>* vt = new vector<Vertex>(); // Texture
- vector<Vertex>* vn = new vector<Vertex>(); // normal
- vector<Face>* f = new vector<Face>(); // faces
- //vector<Polygon>* polygons = new vector<Polygon>();
- // Open the file stream, 0 means no errors are found.
- if((errorCode = fopen_s(&fileStream, fileName, "rt")) == 0) {
- cout << "Starting to read the model file " << fileName << endl;
- vector<float>* parsedFloats;
- // Read until the end of file is reached.
- while(!feof(fileStream)) {
- // Read a line into a char array.
- readLine(fileStream, data);
- // Determine what kind of data we are dealing with:
- switch(data[0]) {
- case 'm':
- cout << "Found material file: " << data;
- break;
- case 's':
- //cout << "Using shadow: " << data;
- break;
- case 'u':
- cout << "Using texture: " << data;
- break;
- case 'g': // A named group, or label.
- cout << "Found group:" << data;
- break;
- case 'v': // We're dealing with a vertex:
- parsedFloats = parseNums(data);
- switch(data[1]) {
- case ' ':
- v->push_back(Vertex(parsedFloats->at(0), parsedFloats->at(1), parsedFloats->at(2)));
- break;
- case 't': {
- // Note: The 3rd argument is optional.
- vt->push_back(Vertex(parsedFloats->at(0), parsedFloats->at(1), (parsedFloats->size() > 2) ? parsedFloats->at(2) : 0));
- } break;
- case 'n':
- vn->push_back(Vertex(parsedFloats->at(0), parsedFloats->at(1), parsedFloats->at(2)));
- break;
- }
- delete parsedFloats;
- break;
- case 'f': // We're dealing with a face:
- vector<stringstream>* chunks = stringSplit(data, ' ', '\n');
- vector<float>* tmp;
- Face newFace;
- // For each batch of "0/0/0":
- for(int i = 0; i < chunks->size(); ++i) {
- if(isNumericString(chunks->at(i).str())) {
- tmp = parseNums(chunks->at(i).str().c_str());
- // For each number in "0/0/0":
- for(int j = 0; j < tmp->size(); ++j) {
- switch(j) {
- case 0: newFace.vertexIndices.push_back(tmp->at(j)); break;
- case 1: newFace.textureIndices.push_back(tmp->at(j)); break;
- case 2: newFace.normalIndices.push_back(tmp->at(j)); break;
- }
- }
- delete tmp;
- }
- }
- f->push_back(newFace);
- delete chunks;
- //delete tmp;
- break;
- }
- }
- cout << "The end of file " << fileName << " has been reached." << endl;
- } else {
- cout << "The specified file " << fileName << " cannot be opened. Error code: " << errorCode << endl;
- }
- Mesh* mesh = new Mesh(f, v, vt, vn);
- return mesh;
- }
- private:
- static void readLine(FILE* fileStream, char * string) {
- do {
- fgets(string, 255, fileStream);
- // Simple continue reading if an empty line was found, or a source code comment.
- // Also accounts for the end of a file
- } while (((string[0] == '/') || (string[0] == '\n') || (string[0] == '#')) && !feof(fileStream));
- }
- static vector<stringstream>* stringSplit(const char * string, const char needle1, const char needle2 = '!', const char needle3 = '/') { // TODO: use va_arg?
- unsigned char numChunks = 0;
- vector<stringstream>* stringChunks = new vector<stringstream>(3); // Using the initial size of 3 as it's the most common figure.
- // Iterate over each character:
- for(unsigned char i = 0; i < strlen(string); ++i) {
- // We found the split character, increment to the next string buffer.
- if(string[i] == needle1 || string[i] == needle2 || string[i] == needle3) {
- ++numChunks;
- // Allocate another stringstream, if required.
- if(stringChunks->size() <= numChunks) {
- stringChunks->push_back(stringstream());
- }
- } else {
- stringChunks->at(numChunks) << string[i];
- }
- }
- return stringChunks;
- }
- static vector<float>* parseNums(const char * string) {
- vector<float>* nums = new vector<float>();
- vector<stringstream>* chunks = stringSplit(string, ' ', '\n', '/');
- for(int i = 0; i < chunks->size(); ++i) {
- if(isNumericString(chunks->at(i).str())) {
- nums->push_back(atof(chunks->at(i).str().c_str()));
- }
- }
- //for(int i = 0; i < nums->size(); ++i) { cout << nums->at(i) << " "; }
- //cout << endl;
- delete chunks;
- return nums;
- }
- // I'm sure this could've been done better...
- static bool isNumericString(const string str) {
- for(int i = 0; i < str.length(); ++i) {
- switch(str.at(i)) {
- case '0': case '1': case '2': // Intentional fall-through.
- case '3': case '4': case '5':
- case '6': case '7': case '8':
- case '9': case '-': case '.':
- case 'e': case '/':
- break;
- default: return false;
- }
- }
- if(str.length() == 0) return false;
- return true;
- }
- };
- #endif
Advertisement
Add Comment
Please, Sign In to add comment