kick
/Users/morten/Programmering/cpp/kick/src/kick/ply/ply_load.cpp
00001 //
00002 //  ObjLoader.cpp
00003 //  KickObjLoader
00004 //
00005 //  Created by morten on 8/31/13.
00006 //  Copyright (c) 2013 morten. All rights reserved.
00007 //
00008 
00009 #include "kick/ply/ply_load.h"
00010 #include "kick/core/project.h"
00011 #include <fstream>
00012 #include <string>
00013 #include <cstring>
00014 #include <sstream>
00015 #include <cerrno>
00016 #include "glm/ext.hpp"
00017 #include "kick/core/debug.h"
00018 
00019 using namespace std;
00020 using namespace glm;
00021 
00022 namespace kick {
00023 
00024     namespace {
00025 
00026         enum class VertexAttributeType {
00027             Pos,
00028             Normal,
00029             Color,
00030             Unknown
00031         };
00032         enum class VertexAttributeDataType {
00033             v_char,//       character                 1
00034                     v_uchar,//      unsigned character        1
00035                     v_short,//      short integer             2
00036                     v_ushort,//     unsigned short integer    2
00037                     v_int,//        integer                   4
00038                     v_uint,//       unsigned integer          4
00039                     v_float,//      single-precision float    4
00040                     v_double,//     double-precision float    8
00041                     v_unknown
00042         };
00043 
00044         VertexAttributeDataType toType(string s){
00045             if (s=="char"){
00046                 return VertexAttributeDataType::v_char;
00047             }
00048             if (s=="uchar"){
00049                 return VertexAttributeDataType::v_uchar;
00050             }
00051             if (s=="short"){
00052                 return VertexAttributeDataType::v_short;
00053             }
00054             if (s=="ushort"){
00055                 return VertexAttributeDataType::v_ushort;
00056             }
00057             if (s=="int"){
00058                 return VertexAttributeDataType::v_int;
00059             }
00060             if (s=="uint"){
00061                 return VertexAttributeDataType::v_uint;
00062             }
00063             if (s=="float"){
00064                 return VertexAttributeDataType::v_float;
00065             }
00066             if (s=="double"){
00067                 return VertexAttributeDataType::v_double;
00068             }
00069             logWarning("Unknown type "+s);
00070             return VertexAttributeDataType::v_unknown;
00071         }
00072 
00073         struct VertexMapping{
00074             VertexAttributeType type;
00075             VertexAttributeDataType dataType;
00076         };
00077 
00078         // from http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring
00079         /*string getFileContents(string filename)
00080         {
00081             ifstream in{filename, ios::in | ios::binary};
00082             if (in)
00083             {
00084                 std::string contents;
00085                 in.seekg(0, std::ios::end);
00086                 contents.resize(in.tellg());
00087                 in.seekg(0, std::ios::beg);
00088                 in.read(&contents[0], contents.size());
00089                 in.close();
00090                 return contents;
00091             }
00092             logError(string{"Error loading file "}+filename+" error "+std::to_string(errno));
00093             return "";
00094         }  */
00095 
00096         std::string fixPathEnd(std::string &path){
00097             if (path.length() == 0){
00098                 return path;
00099             }
00100             char lastChar = path[path.length()-1];
00101             if (lastChar != '/'){
00102                 return path + "/";
00103             }
00104             return path;
00105         }
00106 
00107         vec3 toVec3(vector<string> &tokens, int offset, float div=1){
00108             vec3 res{0,0,0};
00109             for (int i=0;i<3;i++){
00110                 if (i+offset < tokens.size()){
00111                     res[i] = atof(tokens[i+offset].c_str())/div;
00112                 }
00113             }
00114             return res;
00115         }
00116 
00117 //        ObjFace toObjFace(vector<string> &tokens){
00118 //            ObjFace res;
00119 //            for (int i=1; i<tokens.size(); i++) {
00120 //                string & p = tokens[i];
00121 //                replace(p, "//","/0/");
00122 //
00123 //                if (p.length()==0){
00124 //                    continue;
00125 //                }
00126 //
00127 //                ObjVertex o{0,0,0};
00128 //
00129 //                stringstream ss{p};
00130 //                char buffer[50];
00131 //                ss.getline(buffer,50, '/');
00132 //                o.vertexPositionIdx = atoi(buffer);
00133 //                if (ss.good()){
00134 //                    ss.getline(buffer,50, '/');
00135 //                    o.textureIdx = atoi(buffer);
00136 //                }
00137 //                if (ss.good()){
00138 //                    ss.getline(buffer,50, '/');
00139 //                    o.normalIdx = atoi(buffer);
00140 //                }
00141 //                res.push_back(o);
00142 //            }
00143 //            return res;
00144 //        }
00145 
00146 
00147     }
00148 
00149     std::shared_ptr<MeshData> loadPlyData(std::string objSource){
00150         auto res = make_shared<MeshData>();
00151         stringstream ss{objSource};
00152         const int bufferSize = 256;
00153         char buffer[bufferSize];
00154         char buffer2[bufferSize];
00155         bool headerEnded = false;
00156         int vertices = -1;
00157         int faces = -1;
00158         int count = 0;
00159 
00160         vector<vec3> vertexPos;
00161         vector<vec3> normals;
00162         vector<vec4> colors;
00163         vector<unsigned short> indices;
00164 
00165         vector<VertexMapping> mapping;
00166 
00167         while (ss.good()){
00168             ss.getline(buffer, bufferSize);
00169             stringstream likeTokensizer{buffer};
00170             vector<string> tokens;
00171             while (likeTokensizer.good()) {
00172                 likeTokensizer.getline(buffer2, bufferSize, ' ');
00173                 tokens.push_back(buffer2);
00174             }
00175             if (tokens.size()==0){
00176                 continue;
00177             }
00178             if (tokens[0] == "ply"){
00179 
00180             } else if (tokens[0] == "format"){
00181                 if (tokens[1] != "ascii"){
00182                     logWarning("Only PLY ascii is supported");
00183                 }
00184             } else if (tokens[0] == "element"){
00185                 if (tokens[1] == "vertex"){
00186                     vertices = atoi(tokens[2].c_str());
00187                 } else if (tokens[1] == "face"){
00188                     faces = atoi(tokens[2].c_str());
00189                 }
00190             } else if (tokens[0] == "property"){
00191                 if (tokens[2]=="x"){
00192                     mapping.push_back({VertexAttributeType::Pos,toType(tokens[1])});
00193                 } else if (tokens[2]=="y" || tokens[2]=="z"){
00194 
00195                 } else if (tokens[2]=="nx"){
00196                     mapping.push_back({VertexAttributeType::Normal,toType(tokens[1])});
00197                 } else if (tokens[2]=="ny" || tokens[2]=="nz"){
00198 
00199                 } else if (tokens[2]=="red"){
00200                     mapping.push_back({VertexAttributeType::Color,toType(tokens[1])});
00201                 } else if (tokens[2]=="green" || tokens[2]=="blue"){
00202                 } else if (tokens[1]=="list"){
00203 
00204                 } else {
00205                     mapping.push_back({VertexAttributeType::Unknown,toType(tokens[1])});
00206                 }
00207             } else if (tokens[0] == "end_header"){
00208                 headerEnded = true;
00209                 if (vertices == -1){
00210                     logWarning("Undefined vertex count");
00211                 }
00212                 if (faces == -1){
00213                     logWarning("Undefined face count");
00214                 }
00215             } else if (headerEnded){
00216                 count++;
00217                 bool isVertex = count <= vertices;
00218                 if (isVertex){
00219                     int idx = 0;
00220                     for (auto t : mapping){
00221                         if (t.type == VertexAttributeType::Pos){
00222                             vertexPos.push_back(toVec3(tokens, idx));
00223                         }
00224                         else if (t.type == VertexAttributeType::Normal){
00225                             normals.push_back(toVec3(tokens, idx));
00226                         } else if (t.type == VertexAttributeType::Color) {
00227                             colors.push_back(vec4(toVec3(tokens, idx, 255),1));
00228                         }
00229                             idx += (t.type == VertexAttributeType::Unknown) ? 1 : 3;
00230                     }
00231                 } else {
00232                     int count = atoi(tokens[0].c_str());
00233                     for (int i=0;i<count;i++){
00234                         if (i>2){
00235                             // add first and last node to do simple triangulation
00236                             indices.push_back(atoi(tokens[1].c_str()));
00237                             indices.push_back(atoi(tokens[i].c_str()));
00238                         }
00239                         indices.push_back(atoi(tokens[i+1].c_str()));
00240                     }
00241 
00242                 }
00243             }
00244         }
00245         res->setPosition(vertexPos);
00246         if (normals.size()>0){
00247             res->setNormal(normals);
00248         }
00249         if (colors.size()>0){
00250             res->setColor(colors);
00251         }
00252         res->setSubmesh(0, indices, MeshType::Triangles);
00253         return res;
00254     }
00255 
00256 
00257     std::shared_ptr<MeshData> loadPlyData(std::string path, std::string filename){
00258         path = fixPathEnd(path);
00259 
00260         string fileSrc;// = getFileContents(path+filename);
00261         Project::loadTextResource(path+filename,fileSrc);
00262         return loadPlyData(fileSrc);
00263     }
00264 }
 All Classes Functions Variables