Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // File: model.cpp, created on Jun 28, 2011 by WeltEnSTurm
- #include "model.hpp"
- #include "../generic/vec.hpp"
- #include "../generic/decoder.hpp"
- #include <fstream>
- namespace engine {
- namespace decode {
- struct obj_edge {
- obj_edge(): vertex(0), normal(0), uvw(0), texid(0){}
- vec*& operator[](uint i){
- switch(i){
- case 0:
- return vertex; break;
- case 1:
- return uvw; break;
- case 2:
- return normal; break;
- default:
- errexit("engine::decode::obj_edge[]: out of bounds");
- return vertex;
- }
- }
- vec* vertex;
- vec* normal;
- vec* uvw;
- uint texid;
- };
- struct obj_mtldata {
- uint texid;
- std::string name;
- texture* tex;
- };
- struct obj_commandpair {
- std::string cmd;
- void(*func)(std::string&);
- };
- std::vector<obj_commandpair> obj_commandlist = {
- {
- "f",
- [](std::string& c){
- }
- }
- };
- bool obj(const std::string& name, model* target){
- std::ifstream in(name.c_str(),std::ios::in);
- if(!in.is_open())
- return false;
- std::vector<std::vector<vec> > obj_data;
- obj_data.push_back(std::vector<vec>()); // vertices
- obj_data.push_back(std::vector<vec>()); // normals
- obj_data.push_back(std::vector<vec>()); // uvws
- std::vector<obj_edge> obj_edges;
- std::vector<obj_mtldata> obj_mtl;
- long line=0;
- std::string warn = "Model \""+name+"\"";
- int TexID_Current = 0;
- int TexID_Count = 0;
- while(in.good()){
- line++;
- std::string data;
- std::getline(in, data);
- data+='\n';
- while(data.find_first_of('#')<data.size()){
- long begin = data.find_first_of('#');
- long end = data.find_first_of('\n');
- if(end < (long)data.size() && end > begin)
- data.erase(begin, end-begin);
- }
- while(data.find_last_of('\r')<data.size()){
- data[data.find_last_of('\r')] = '\n';
- }
- std::string command="";
- for(uint i=0; i<data.length(); i++){
- if(data[i]!=' ' && data[i]!='\t' && data[i] != '\n'){
- command+=data[i];
- }else if(command.length()){
- if(command=="v" || command=="vt" || command=="vn"){
- vec t;
- std::string n="";
- int filltarget=0;
- for(; i<data.length(); i++){
- if(isnumberchar(data[i])){
- n+=data[i];
- }else if(n.length()){
- t[filltarget++]=tonumber(n);
- if(filltarget>2) break;
- n="";
- }
- }
- if(command=="v")
- obj_data[0].push_back(t);
- else if(command=="vt")
- obj_data[1].push_back(t);
- else if(command=="vn")
- obj_data[2].push_back(t);
- }
- else if(command=="f"){
- uint edges=0;
- for(; i<data.length(); i++){
- if(isnumberchar(data[i])){
- unsigned long end = data.find(' ', i);
- if(end>=data.length()) end=data.find('\t', i);
- if(end>=data.length()) end=data.find('\n', i);
- if(end>=data.length()){
- warning(warn+" may be corrupt");
- return false;
- }
- edges++;
- if(edges>3){ // we can only use triangles, so split all other
- obj_edges.push_back(obj_edges[obj_edges.size()-3]); // primitives up. do this by copying the last two
- obj_edges.push_back(obj_edges[obj_edges.size()-2]); // edges for each new one
- }
- std::string num;
- obj_edges.push_back(obj_edge());
- obj_edge* edge = &obj_edges[obj_edges.size()-1];
- edge->texid = TexID_Current;
- uint mode=0;
- for(;i<=end;i++){
- if(isnumberchar(data[i])){
- num+=data[i];
- }else if(num.length()){
- uint idx=tonumber(num);
- if(idx != tonumber(num) || idx<1 || idx>obj_data[mode].size()){
- warning(warn+" has dangerous "+(mode==0?"vertex":(mode==1?"uvw":"normal"))+
- " index ("+num+") at line "+line);
- return false;
- } else {
- (*edge)[mode] = &obj_data[mode][idx-1];
- }
- }
- if(data[i]=='/'){
- num="";
- mode++;
- if(mode==3){
- warning(warn+" has dangerous face at line "+line);
- return false;
- }
- }
- }
- i--;
- }
- }
- }
- else if(command=="mtllib"){
- for(; i<data.length(); i++){
- if(data[i]!=' '&& data[i] != '\t'){
- uint end = data.find('\n',i);
- if(end>=data.length()){
- warning(warn+": could not open MTL file (command end not found)");
- return false;
- }
- std::string mtlname = name.substr(0,name.find_last_of('/')+1)+data.substr(i, end-i);
- data = data.substr(end);
- std::ifstream mtllib_f(mtlname.c_str(), std::ios::in);
- if(!mtllib_f.is_open()){
- warning(warn+": could not open mtl file ("+mtlname+")");
- return false;
- }
- std::string MatName_Cur;
- GLint MaxTextures;
- glGetIntegerv(GL_MAX_TEXTURE_UNITS, &MaxTextures);
- while(mtllib_f.good()){
- std::string nl;
- std::getline(mtllib_f, nl);
- if(nl[0]=='#') continue;
- nl+='\n';
- std::string cmd="";
- for(uint mi=0; mi<nl.size(); mi++){
- if(nl[mi]!=' ' && nl[mi]!='\t'){
- cmd+=nl[mi];
- }else if(cmd.length()){
- if(cmd=="newmtl"){
- for(;mi<nl.length();mi++)
- if(nl[mi]!=' '&&nl[mi]!='\t') break;
- MatName_Cur=nl.substr(mi,nl.size()-mi-1);
- mi=nl.size()-mi-1;
- }
- else if(cmd=="map_Ka"){
- for(;mi<nl.length();mi++)
- if(nl[mi]!=' '&&nl[mi]!='\t') break;
- if(MaxTextures<(long)obj_mtl.size())
- warning(warn+" uses more textures than supported.");
- std::string path = nl.substr(mi,nl.size()-mi-1);
- texture* t = TextureManager::LoadTexture(path);
- if(t){
- obj_mtl.push_back(obj_mtldata());
- obj_mtldata* d = &obj_mtl[obj_mtl.size()-1];
- d->name = MatName_Cur;
- d->tex = t;
- d->texid = TexID_Count++;
- mi=nl.size()-mi-1;
- }
- else
- warning(warn+": failed to open "+path);
- }
- cmd="";
- }
- }
- }
- break;
- }
- }
- }
- else if(command=="usemtl"){
- for(; i<data.length(); i++){
- if(data[i] != ' ' && data[i] != '\t'){
- uint end = data.find('\n');
- std::string name = data.substr(i,end-i);
- data = data.substr(end);
- bool found=false;
- for(uint idx_matlist=0; idx_matlist<obj_mtl.size(); idx_matlist++){
- if(obj_mtl[idx_matlist].name == name){
- TexID_Current = obj_mtl[idx_matlist].texid;
- found = true;
- break;
- }
- }
- if(!found){
- warning(warn + " uses invalid material ("+name+") on line "+line);
- return false;
- }
- break;
- }
- }
- }
- else{
- static std::vector<std::string> unknowncommands;
- bool has = false;
- for(long cmdi = unknowncommands.size()-1; cmdi>=0; cmdi--)
- if(unknowncommands[cmdi] == command){
- has = true;
- break;
- }
- if(!has){
- warning(warn + " uses unknown command at line "+line+": "+command);
- unknowncommands.push_back(command);
- }
- i = data.find_first_of('\n', i);
- }
- command="";
- }
- }
- }
- in.close();
- for(uint i=0; i<obj_mtl.size(); i++){
- glActiveTexture(GL_TEXTURE0+i);
- glBindTexture(GL_TEXTURE_2D, obj_mtl[i].tex->id);
- target->tex.push_back(obj_mtl[i].tex);
- }
- target->data->Begin(GL_TRIANGLES, obj_edges.size(), obj_mtl.size());
- for(uint i=0; i<obj_edges.size(); i++){
- if(obj_edges[i].uvw){
- vec u = *obj_edges[i].uvw;
- target->data->MultiTexCoord2f(obj_edges[i].texid, u.x, u.y);
- }
- if(obj_edges[i].normal){
- vec n = obj_edges[i].normal->ogl().Normalize();
- target->data->Normal3f(n.x,n.y,n.z);
- }else{
- target->data->Normal3f(0,1,0);
- }
- if(!obj_edges[i].vertex)
- warning(warn+": edge "+(i+1)+"uses invalid vertex");
- else{
- vec v = obj_edges[i].vertex->ogl();
- target->data->Vertex3f(v.x,v.y,v.z);
- }
- }
- target->data->End();
- return true;
- }
- }
- model model::invalid;
- std::vector<model> ModelManager::ModelData;
- ModelManager ModelManager::Manager;
- ModelManager::~ModelManager(){
- for(uint i=0; i<ModelData.size(); i++){
- delete ModelData[i].data;
- ModelData[i].data=0;
- }
- }
- model* ModelManager::LoadModel(std::string name){
- name = PATH_CONTENT + PATH_MODELS + name;
- for(uint i=0; i<ModelData.size(); i++)
- if(ModelData[i].path == name)
- return &ModelData[i];
- ModelData.push_back(model());
- model& m = ModelData[ModelData.size()-1];
- m.SetData(name, new GLBatch);
- if(decode::obj(name,&m))
- return &m;
- ModelData.pop_back();
- warning("Failed to load model \""+name+"\"");
- return &model::invalid;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement