kick
/Users/morten/Programmering/cpp/kick/src/kick/obj/obj_data.cpp
00001 //
00002 //  ObjData.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/obj/obj_data.h"
00010 #include <stdexcept>
00011 #include <string>
00012 #include "kick/core/debug.h"
00013 #include "kick/core/project.h"
00014 
00015 using namespace std;
00016 
00017 namespace kick {
00018     bool ObjData::verifyFaces() {
00019         for (auto & face : faces) {
00020             if (face.size()<3){
00021 //                throw length_error();
00022                 logError("Faces must be at least 3 vertices");
00023                 return false;
00024             }
00025             
00026             for (auto & vertex : face) {
00027                 if (vertex.vertexPositionIdx > vertexPositions.size()){
00028                     logError(string{"Invalid vertex position index. Index was "} +
00029                             std::to_string(vertex.vertexPositionIdx) +
00030                             " number of vertex positions is "+
00031                             std::to_string(vertexPositions.size()));
00032                     return false;
00033                 }
00034                 if (vertex.vertexPositionIdx<=0){
00035                     logError(string{"Invalid vertex position index. Must be positive. Was "} +
00036                             std::to_string(vertex.vertexPositionIdx));
00037                     return false;
00038                 }
00039                 
00040                 if (vertex.textureIdx > textureCoords.size()){
00041                     logError(string{"Invalid texture index. Index was "} +
00042                             std::to_string(vertex.textureIdx) +
00043                             " number of texture indices is "+
00044                             std::to_string(textureCoords.size()));
00045                     return false;
00046                 }
00047                 
00048                 if (vertex.normalIdx > normals.size()){
00049                     logError(string{"Invalid normal index. Index was "} +
00050                             std::to_string(vertex.normalIdx) +
00051                             " number of normals is "+
00052                             std::to_string(normals.size()));
00053                     return false;
00054                 }
00055             }
00056         }
00057         
00058         return true;
00059     }
00060     
00061     ObjMaterial* ObjData::material(std::string name){
00062         for (auto & mat : materials){
00063             if (mat.name == name){
00064                 return &mat;
00065             }
00066         }
00067         return nullptr;
00068     }
00069 
00070     std::vector<unsigned int> ObjData::indices() {
00071         std::vector<unsigned int> res;
00072         for (auto & f : faces){
00073             assert (f.size()==3);
00074             for (int i=0;i<3;i++){
00075                 res.push_back((unsigned short)(f[i].vertexPositionIdx-1));
00076             }
00077             for (int i=3;i<f.size();i++){
00078                 res.push_back((unsigned short)(f[0].vertexPositionIdx-1));
00079                 res.push_back((unsigned short)(f[i-1].vertexPositionIdx-1));
00080                 res.push_back((unsigned short)(f[i].vertexPositionIdx-1));
00081             }
00082         }
00083         return res;
00084     }
00085 
00086     std::shared_ptr<MeshData> ObjData::meshData() {
00087         auto meshData = make_shared<MeshData>();
00088 
00089         struct tuple_hash
00090         {
00091             std::size_t operator()(const tuple<int,int,int>& k) const
00092             {
00093                 return (std::get<0>(k) << 16) | (std::get<1>(k) << 8) | std::get<2>(k);
00094             }
00095         };
00096 
00097         unordered_map<tuple<int, int, int>, int, tuple_hash> map;
00098         std::vector<glm::vec3> vertices;
00099         std::vector<glm::vec2> uv;
00100         std::vector<glm::vec3> ns;
00101         std::vector<unsigned short> indices;
00102 
00103         auto insert = [&](int i, ObjFace& f){
00104             tuple<int,int,int> t{f[i].vertexPositionIdx, f[i].textureIdx, f[i].normalIdx};
00105             auto res = map.find(t);
00106             if (res != map.end()){
00107                 int index = res->second;
00108                 indices.push_back(index);
00109             } else {
00110                 int index = map.size();
00111                 map[t] = index;
00112                 indices.push_back((unsigned short) index);
00113                 vertices.push_back((glm::vec3)vertexPositions[f[i].vertexPositionIdx-1]);
00114                 if (textureCoords.size() > f[i].textureIdx-1){
00115                     uv.push_back((glm::vec2)textureCoords[f[i].textureIdx-1]);
00116                 }
00117                 if (normals.size() > f[i].normalIdx-1){
00118                     ns.push_back((glm::vec3)normals[f[i].normalIdx-1]);
00119                 }
00120             }
00121         };
00122 
00123         for (auto & f : faces){
00124             assert (f.size()>=3);
00125             for (int i=0;i<3;i++){
00126                 insert(i, f);
00127             }
00128             for (int i=3;i<f.size();i++){
00129                 insert(0, f);
00130                 insert(i-1, f);
00131                 insert(i, f);
00132             }
00133         }
00134 
00135         meshData->setPosition(vertices);
00136         meshData->setSubmesh(0, indices, MeshType::Triangles);
00137         if (uv.size()>0){
00138             meshData->setTexCoord0(uv);
00139         }
00140         if (ns.size()==0){
00141             meshData->recomputeNormals();
00142         } else {
00143             if (ns[0] == glm::vec3{0}){
00144                 logWarning("Invalid normal import.Was {0,0,0}");
00145                 meshData->recomputeNormals();
00146             } else {
00147                 meshData->setNormal(ns);
00148             }
00149         }
00150 
00151         return meshData;
00152     }
00153 }
 All Classes Functions Variables