kick
|
00001 // 00002 // ObjInterleavedData.cpp 00003 // KickObjLoader 00004 // 00005 // Created by morten on 9/2/13. 00006 // Copyright (c) 2013 morten. All rights reserved. 00007 // 00008 00009 #include "obj_interleaved_data.h" 00010 #include <unordered_map> 00011 #include <glm/glm.hpp> 00012 #include <cassert> 00013 #include <algorithm> 00014 00015 using namespace std; 00016 using namespace glm; 00017 00018 namespace kick { 00019 00020 struct ObjVertexHash { 00021 std::size_t operator()(const ObjVertex& k) const { 00022 return (( k.vertexPositionIdx << 16 ) ^ ( k.textureIdx << 8 )) ^ k.normalIdx; 00023 } 00024 }; 00025 00026 struct ObjVertexEqual { 00027 bool operator()(const ObjVertex& lhs, const ObjVertex& rhs) const { 00028 return lhs.vertexPositionIdx == rhs.vertexPositionIdx && 00029 lhs.textureIdx == rhs.textureIdx && 00030 lhs.normalIdx == rhs.normalIdx; 00031 } 00032 }; 00033 00034 using ObjVertexHashTable = unordered_map<ObjVertex,int,ObjVertexHash, ObjVertexEqual>; 00035 00036 int getCreateIndex(ObjVertex &vertexIndex, int nextIndex, ObjVertexHashTable& usedVertices){ 00037 auto pos = usedVertices.find(vertexIndex); 00038 if (pos != usedVertices.end()){ 00039 return pos->second; 00040 } 00041 usedVertices.emplace(vertexIndex, nextIndex); 00042 return nextIndex; 00043 } 00044 00045 ObjInterleavedData::ObjInterleavedData(ObjData & objData, bool includeTextureCoordinates, bool includeNormals, int vertexPositionSize, int texCoordinateSize) 00046 :includeTextureCoordinates(includeTextureCoordinates), includeNormals(includeNormals), vertexPositionSize(vertexPositionSize), texCoordinateSize(texCoordinateSize) { 00047 00048 vertexLength = vertexPositionSize; 00049 if (includeTextureCoordinates){ 00050 textureOffset = vertexLength; 00051 vertexLength += texCoordinateSize; 00052 } 00053 if (includeNormals){ 00054 normalsOffset = vertexLength; 00055 vertexLength += 3; 00056 } 00057 00058 indices.push_back({"___Default material___", {}}); 00059 00060 ObjInterleavedIndex * currentIndex = &indices.back(); 00061 ObjVertexHashTable usedVertices{42,ObjVertexHash{}, ObjVertexEqual{}}; 00062 00063 int vertexCount = 0; 00064 int faceCount = 0; 00065 auto materialChanges = objData.materialChanges.begin(); 00066 for (auto & face : objData.faces){ 00067 faceCount++; 00068 if (materialChanges != objData.materialChanges.end()){ 00069 if (materialChanges->faceIndex == faceCount){ 00070 bool foundMaterial = false; 00071 for (auto & idx : indices) { 00072 if (idx.materialName == materialChanges->name){ 00073 foundMaterial = true; 00074 currentIndex = &idx; 00075 break; 00076 } 00077 } 00078 if (!foundMaterial){ 00079 indices.push_back({materialChanges->name, {}}); 00080 currentIndex = &indices.back(); 00081 } 00082 materialChanges++; 00083 } 00084 } 00085 for (int i=2;i < face.size();i++){ 00086 int triangle[] = {0, i-1, i}; 00087 for (int triangleIndex : triangle){ 00088 auto & vertexIndexObject = face[triangleIndex]; 00089 int vertexIndex = getCreateIndex(vertexIndexObject, vertexCount, usedVertices); 00090 bool existInInterleavedData = vertexIndex != vertexCount; 00091 if (!existInInterleavedData){ 00092 // read data 00093 vec4 vertexPosition = objData.vertexPositions[vertexIndexObject.vertexPositionIdx - 1]; 00094 vec3 textureCoord{0,0,0}; 00095 if (vertexIndexObject.textureIdx > 0 && includeTextureCoordinates){ 00096 textureCoord = objData.textureCoords[vertexIndexObject.textureIdx - 1]; 00097 } 00098 vec3 normal; 00099 if (vertexIndexObject.normalIdx > 0 && includeNormals){ 00100 normal = objData.normals[vertexIndexObject.normalIdx-1]; 00101 } 00102 // write interleaved data 00103 for (int j=0;j<vertexPositionSize;j++){ 00104 interleavedData.push_back(vertexPosition[j]); 00105 } 00106 if (includeTextureCoordinates){ 00107 for (int j=0;j<texCoordinateSize;j++){ 00108 interleavedData.push_back(textureCoord[j]); 00109 } 00110 } 00111 if (includeNormals){ 00112 for (int j=0;j<3;j++){ 00113 interleavedData.push_back(normal[j]); 00114 } 00115 } 00116 vertexCount++; 00117 } 00118 currentIndex->vertexIndices.push_back(vertexIndex); 00119 } 00120 } 00121 } 00122 00123 // remove unused materials 00124 indices.erase(std::remove_if(indices.begin(), indices.end(), [](const ObjInterleavedIndex &a){ return a.vertexIndices.size()==0;}), 00125 indices.end()); 00126 } 00127 00128 int ObjInterleavedData::vertexCount(){ 00129 return (int)(interleavedData.size() / vertexLength); 00130 } 00131 00132 glm::vec4 ObjInterleavedData::vertex(int index){ 00133 int i = vertexLength*index; 00134 return glm::vec4{interleavedData[i], interleavedData[i+1], interleavedData[i+2], vertexPositionSize==4?interleavedData[i+3]:1}; 00135 } 00136 00137 void ObjInterleavedData::setVertex(int index, glm::vec4 value){ 00138 int i = vertexLength*index; 00139 for (int j=0;j<vertexPositionSize;j++){ 00140 interleavedData[i+j] = value[j]; 00141 } 00142 } 00143 glm::vec3 ObjInterleavedData::textureCoordinate(int index){ 00144 int i = vertexLength*index + textureOffset; 00145 return glm::vec3{interleavedData[i], interleavedData[i+1], texCoordinateSize==3?interleavedData[i+2]:0}; 00146 } 00147 void ObjInterleavedData::setTextureCoordinate(int index, glm::vec3 value){ 00148 int i = vertexLength*index + textureOffset; 00149 for (int j=0;j<texCoordinateSize;j++){ 00150 interleavedData[i+j] = value[j]; 00151 } 00152 } 00153 glm::vec3 ObjInterleavedData::normal(int index){ 00154 int i = vertexLength*index + normalsOffset; 00155 return glm::vec3{interleavedData[i], interleavedData[i+1], interleavedData[i+2]}; 00156 } 00157 00158 void ObjInterleavedData::setNormal(int index, glm::vec3 value){ 00159 int i = vertexLength*index + normalsOffset; 00160 for (int j=0;j<3;j++){ 00161 interleavedData[i+j] = value[j]; 00162 } 00163 } 00164 }