kick
|
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 }