diff options
Diffstat (limited to 'hw6/src/importOBJ.cpp')
-rw-r--r-- | hw6/src/importOBJ.cpp | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/hw6/src/importOBJ.cpp b/hw6/src/importOBJ.cpp new file mode 100644 index 0000000..53354be --- /dev/null +++ b/hw6/src/importOBJ.cpp @@ -0,0 +1,152 @@ +/******************************************************************/ +/* This file is part of the homework assignments for CSCI-427/527 */ +/* at The College of William & Mary and authored by Pieter Peers. */ +/* No part of this file, whether altered or in original form, can */ +/* be distributed or used outside the context of CSCI-427/527 */ +/* without consent of either the College of William & Mary or */ +/* Pieter Peers. */ +/******************************************************************/ + +#include <memory> +#include <string> +#include <cassert> +#include <fstream> + +#include "vec3d.h" +#include "vec2d.h" +#include "importOBJ.h" +#include "errorMessage.h" + +void skipLine(std::ifstream& ifs) +{ + unsigned char c = ifs.get(); + while(ifs.good() && c != '\r' && c != '\n') c = ifs.get(); + while(ifs.good() && (c == '\r' || c == '\n')) c = ifs.get(); + ifs.unget(); +} + +void importOBJ(const std::string filename, std::vector<triangle>& triangle_list) +{ + // define buffers + auto vertex_list = std::make_shared<std::vector<vec3d>>(); + auto normal_list = std::make_shared<std::vector<vec3d>>(); + auto textureCoord_list = std::make_shared<std::vector<vec2d>>(); + + // open obj file + std::ifstream ifs(filename, std::ifstream::in | std::ifstream::binary); + if(!ifs.is_open()) + errorMessage("Unable to import OBJ (%s).", filename.c_str()); + + // read line by line + unsigned char key; + while(ifs.good()) + { + // get key + key = ifs.get(); + + // VERTEX DATA: + if(key == 'v') + { + // get vertex data + key = ifs.get(); + + // Vertex Coordinate + if(key == ' ') + { + vec3d v; + ifs >> v.x >> v.y >> v.z; + vertex_list->push_back(v); + } + + // Texture Coordinate + else if(key == 't') + { + vec2d t; + ifs >> t.u >> t.v; + textureCoord_list->push_back(t); + } + + // Normal + else if(key == 'n') + { + vec3d n; + ifs >> n.x >> n.y >> n.z; + normal_list->push_back(n); + } + + // Unknown => ERROR + else errorMessage("Unknown OBJ vertex-key: v%c.", key); + } + + // POLYGON: + else if(key == 'f') + { + // temp data structures + std::vector<unsigned int> vidx; + std::vector<unsigned int> nidx; + std::vector<unsigned int> tidx; + + // get polygon data + // can be either: + // 1) v0 v1 .. vn + // 2) v0//n0 v1//n1 .. vn//nn + // 3) v0/t0 v1/t1 ... vn/tn + // 4) v0/t0/n0 ... vn/tn/nn + bool done=false; + while(!done) + { + // read entry + signed int vi, vt=-1, vn=-1; + ifs >> vi; + unsigned char c = ifs.get(); + + if(c == '/') + { + c = ifs.get(); + if(c != '/') { ifs.unget(); ifs >> vt; c = ifs.get(); } + if(c == '/') { ifs >> vn; c = ifs.get(); } + } + + // sanity check + assert(vt != 0 && vn != 0 && vi != 0); + + // store in polygon + if(vt != -1) { assert(vt-1 < textureCoord_list->size()); tidx.push_back(vt-1); } + if(vn != -1) { assert(vn-1 < normal_list->size()); nidx.push_back(vn-1); } + if(vi != -1) { assert(vi-1 < vertex_list->size()); vidx.push_back(vi-1); } + + // eat spaces and end-of-lines + ifs.unget(); + c = ifs.get(); + while(ifs.good() && (c == ' ' ||c == '\r' || c == '\n')) + { + if(c == '\r' || c == '\n') done = true; + c = ifs.get(); + } + ifs.unget(); + + // sanity check + assert(tidx.empty() || tidx.size() == vidx.size()); + assert(nidx.empty() || nidx.size() == vidx.size()); + + // store triangle + if(vidx.size() >= 3) + { + size_t m=vidx.size() - 2; + size_t l=vidx.size() - 1; + if(tidx.empty() && nidx.empty()) triangle_list.push_back( triangle(vidx[0], vidx[m], vidx[l], vertex_list) ); + if(tidx.empty() && !nidx.empty()) triangle_list.push_back( triangle(vidx[0], vidx[m], vidx[l], vertex_list, + nidx[0], nidx[m], nidx[l], normal_list) ); + if(!tidx.empty() && nidx.empty()) triangle_list.push_back( triangle(vidx[0], vidx[m], vidx[l], vertex_list, + tidx[0], tidx[m], tidx[l], textureCoord_list) ); + if(!tidx.empty() && !nidx.empty()) triangle_list.push_back( triangle(vidx[0], vidx[m], vidx[l], vertex_list, + nidx[0], nidx[m], nidx[l], normal_list, + tidx[0], tidx[m], tidx[l], textureCoord_list) ); + } + } + } + else { ifs.unget(); skipLine(ifs); } + } + + // Done. +} |