/******************************************************************/ /* 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 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); 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(); // COMMENTS: if(key == '#' || key == ' ') { std::string comment; ifs >> comment; // comment: skip line } // VERTEX DATA: else 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; } } // store in polygon if(vt != -1) tidx.push_back(vt-1); if(vn != -1) nidx.push_back(vn-1); if(vi != -1) vidx.push_back(vi-1); // check if we did not eat the end-of-line chararters ifs.unget(); c = ifs.get(); if(c == '\r' || c == '\n') done = true; // eat remaining spaces c = ifs.get(); while(c == ' ') c = ifs.get(); // check again for end if(c == '\r' || c == '\n') done = true; 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) ); } } } } // Done. }