/******************************************************************/ /* 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 #include #include #include #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_list) { // define buffers auto vertex_list = std::make_shared>(); auto normal_list = std::make_shared>(); auto textureCoord_list = std::make_shared>(); // 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 vidx; std::vector nidx; std::vector 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. }