💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
9.1 KiB

7 years ago
  1. /*
  2. * Copyright (C) 2017 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper Source Code.
  5. *
  6. * Antkeeper Source Code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper Source Code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper Source Code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "model-loader.hpp"
  20. #include "material-loader.hpp"
  21. #include <fstream>
  22. template <typename T>
  23. inline static void read8(T* result, unsigned char** data)
  24. {
  25. std::uint8_t temp = (*data)[0];
  26. *result = *reinterpret_cast<T*>(&temp);
  27. *data += 1;
  28. }
  29. template <typename T>
  30. inline static void read16(T* result, unsigned char** data)
  31. {
  32. std::uint16_t temp = ((*data)[0] << 0) | ((*data)[1] << 8);
  33. *result = *reinterpret_cast<T*>(&temp);
  34. *data += 2;
  35. }
  36. template <typename T>
  37. inline static void read32(T* result, unsigned char** data)
  38. {
  39. std::uint32_t temp = ((*data)[0] << 0) | ((*data)[1] << 8) | ((*data)[2] << 16) | ((*data)[3] << 24);
  40. *result = *reinterpret_cast<T*>(&temp);
  41. *data += 4;
  42. }
  43. inline static void readString(std::string* result, unsigned char** data)
  44. {
  45. result->resize((*data)[0]);
  46. for (std::size_t i = 0; i < result->size(); ++i)
  47. {
  48. (*result)[i] = (*data)[i + 1];
  49. }
  50. *data += result->size() + 1;
  51. }
  52. ModelLoader::ModelLoader():
  53. materialLoader(nullptr)
  54. {}
  55. ModelLoader::~ModelLoader()
  56. {}
  57. Model* ModelLoader::load(const std::string& filename)
  58. {
  59. // Open file
  60. std::ifstream file(filename.c_str(), std::ifstream::in | std::ifstream::binary | std::ifstream::ate);
  61. if (!file.is_open())
  62. {
  63. std::cerr << "ModelLoader::load(): Failed to open model file \"" << filename << "\"" << std::endl;
  64. return nullptr;
  65. }
  66. // Allocate file data buffer
  67. int filesize = file.tellg();
  68. unsigned char* buffer = new unsigned char[filesize];
  69. // Read file data into buffer
  70. file.seekg(0, file.beg);
  71. file.read(reinterpret_cast<char*>(&buffer[0]), filesize);
  72. unsigned char* bufferOffset = &buffer[0];
  73. // Close file
  74. file.close();
  75. // Allocate model data
  76. ModelData* modelData = new ModelData();
  77. // Allocate material groups
  78. read32(&modelData->groupCount, &bufferOffset);
  79. modelData->groups = new MaterialGroup[modelData->groupCount];
  80. // Read material groups (and calculate triangle count)
  81. std::uint32_t triangleCount = 0;
  82. for (std::size_t i = 0; i < modelData->groupCount; ++i)
  83. {
  84. MaterialGroup* group = &modelData->groups[i];
  85. readString(&group->materialName, &bufferOffset);
  86. read32(&group->indexOffset, &bufferOffset);
  87. read32(&group->triangleCount, &bufferOffset);
  88. // Read bounds
  89. Vector3 min;
  90. Vector3 max;
  91. read32(&min.x, &bufferOffset);
  92. read32(&min.y, &bufferOffset);
  93. read32(&min.z, &bufferOffset);
  94. read32(&max.x, &bufferOffset);
  95. read32(&max.y, &bufferOffset);
  96. read32(&max.z, &bufferOffset);
  97. group->bounds.setMin(min);
  98. group->bounds.setMax(max);
  99. triangleCount += group->triangleCount;
  100. }
  101. // Read vertex format and count
  102. read32(&modelData->vertexFormat, &bufferOffset);
  103. read32(&modelData->vertexCount, &bufferOffset);
  104. // Read bounds
  105. Vector3 min;
  106. Vector3 max;
  107. read32(&min.x, &bufferOffset);
  108. read32(&min.y, &bufferOffset);
  109. read32(&min.z, &bufferOffset);
  110. read32(&max.x, &bufferOffset);
  111. read32(&max.y, &bufferOffset);
  112. read32(&max.z, &bufferOffset);
  113. modelData->bounds.setMin(min);
  114. modelData->bounds.setMax(max);
  115. // Calculate vertex size
  116. std::uint32_t vertexSize =
  117. 3 // Position
  118. + 3 // Normal
  119. + 2 * ((modelData->vertexFormat & UV) != 0) // UV
  120. + 4 * ((modelData->vertexFormat & TANGENT) != 0) // Tangent
  121. + 4 * ((modelData->vertexFormat & TANGENT) != 0) // Bitangent
  122. + 4 * ((modelData->vertexFormat & WEIGHTS) != 0) // Indices
  123. + 4 * ((modelData->vertexFormat & WEIGHTS) != 0); // Weights
  124. // Allocate vertex data
  125. modelData->vertexData = new float[modelData->vertexCount * vertexSize];
  126. // Read vertex data
  127. float* vertexDataOffset = &modelData->vertexData[0];
  128. for (std::size_t i = 0; i < modelData->vertexCount; ++i)
  129. {
  130. for (std::size_t j = 0; j < vertexSize; ++j)
  131. {
  132. read32(vertexDataOffset, &bufferOffset);
  133. ++vertexDataOffset;
  134. }
  135. }
  136. // Allocate index data
  137. std::uint32_t indexCount = triangleCount * 3;
  138. modelData->indexData = new std::uint32_t[indexCount];
  139. // Read index data
  140. for (std::size_t i = 0; i < indexCount; ++i)
  141. {
  142. read32(&modelData->indexData[i], &bufferOffset);
  143. }
  144. // Free file data buffer
  145. delete[] buffer;
  146. GLuint vao;
  147. GLuint vbo;
  148. GLuint ibo;
  149. // Generate and bind VAO
  150. glGenVertexArrays(1, &vao);
  151. glBindVertexArray(vao);
  152. // Generate and bind VBO, then upload vertex data
  153. glGenBuffers(1, &vbo);
  154. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  155. glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * modelData->vertexCount, modelData->vertexData, GL_STATIC_DRAW);
  156. // Setup vertex attribute arrays
  157. std::size_t attribOffset = 0;
  158. std::size_t attribSize = 0;
  159. // Vertex position attribute
  160. attribSize = 3;
  161. glEnableVertexAttribArray(EMERGENT_VERTEX_POSITION);
  162. glVertexAttribPointer(EMERGENT_VERTEX_POSITION, attribSize, GL_FLOAT, GL_FALSE, sizeof(float) * vertexSize, (char*)0 + attribOffset * sizeof(float));
  163. attribOffset += attribSize;
  164. // Vertex normal attribute
  165. attribSize = 3;
  166. glEnableVertexAttribArray(EMERGENT_VERTEX_NORMAL);
  167. glVertexAttribPointer(EMERGENT_VERTEX_NORMAL, attribSize, GL_FLOAT, GL_FALSE, sizeof(float) * vertexSize, (char*)0 + attribOffset * sizeof(float));
  168. attribOffset += attribSize;
  169. // Vertex UV attribute
  170. if ((modelData->vertexFormat & UV) != 0)
  171. {
  172. attribSize = 2;
  173. glEnableVertexAttribArray(EMERGENT_VERTEX_TEXCOORD);
  174. glVertexAttribPointer(EMERGENT_VERTEX_TEXCOORD, attribSize, GL_FLOAT, GL_FALSE, sizeof(float) * vertexSize, (char*)0 + attribOffset * sizeof(float));
  175. attribOffset += attribSize;
  176. }
  177. // Vertex tangent and bitangent attributes
  178. if ((modelData->vertexFormat & TANGENT) != 0)
  179. {
  180. // Tangent
  181. attribSize = 4;
  182. glEnableVertexAttribArray(EMERGENT_VERTEX_TANGENT);
  183. glVertexAttribPointer(EMERGENT_VERTEX_TANGENT, attribSize, GL_FLOAT, GL_FALSE, sizeof(float) * vertexSize, (char*)0 + attribOffset * sizeof(float));
  184. attribOffset += attribSize;
  185. // Bitangent
  186. attribSize = 4;
  187. glEnableVertexAttribArray(EMERGENT_VERTEX_BITANGENT);
  188. glVertexAttribPointer(EMERGENT_VERTEX_BITANGENT, attribSize, GL_FLOAT, GL_FALSE, sizeof(float) * vertexSize, (char*)0 + attribOffset * sizeof(float));
  189. attribOffset += attribSize;
  190. }
  191. // Vertex indices and weights attributes
  192. if ((modelData->vertexFormat & TANGENT) != 0)
  193. {
  194. // Indices
  195. attribSize = 4;
  196. glEnableVertexAttribArray(EMERGENT_VERTEX_BONE_INDICES);
  197. glVertexAttribPointer(EMERGENT_VERTEX_BONE_INDICES, attribSize, GL_FLOAT, GL_FALSE, sizeof(float) * vertexSize, (char*)0 + attribOffset * sizeof(float));
  198. attribOffset += attribSize;
  199. // Weights
  200. attribSize = 4;
  201. glEnableVertexAttribArray(EMERGENT_VERTEX_BONE_WEIGHTS);
  202. glVertexAttribPointer(EMERGENT_VERTEX_BONE_WEIGHTS, attribSize, GL_FLOAT, GL_FALSE, sizeof(float) * vertexSize, (char*)0 + attribOffset * sizeof(float));
  203. attribOffset += attribSize;
  204. }
  205. // Generate and bind IBO, then upload index data
  206. glGenBuffers(1, &ibo);
  207. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
  208. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(std::uint32_t) * indexCount, modelData->indexData, GL_STATIC_DRAW);
  209. // Delete vertex and index data
  210. delete[] modelData->vertexData;
  211. delete[] modelData->indexData;
  212. // Allocate model
  213. Model* model = new Model();
  214. model->setBounds(modelData->bounds);
  215. // Create model groups
  216. for (std::size_t i = 0; i < modelData->groupCount; ++i)
  217. {
  218. ModelLoader::MaterialGroup* modelDataGroup = &modelData->groups[i];
  219. // Allocate model group
  220. Model::Group* modelGroup = new Model::Group();
  221. // Set model group name
  222. modelGroup->name = modelDataGroup->materialName;
  223. // Load material
  224. std::string materialFilename = std::string("data/materials/") + modelDataGroup->materialName + std::string(".mtl");
  225. if (materialLoader != nullptr)
  226. {
  227. modelGroup->material = materialLoader->load(materialFilename);
  228. if (!modelGroup->material)
  229. {
  230. std::cerr << "ModelLoader::load(): Failed to load material file \"" << materialFilename << "\" for model file \"" << filename << "\"" << std::endl;
  231. }
  232. }
  233. else
  234. {
  235. modelGroup->material = nullptr;
  236. std::cerr << "ModelLoader::load(): No valid material loader, material file \"" << materialFilename << "\" not loaded" << std::endl;
  237. }
  238. // Setup model group geometry
  239. modelGroup->indexOffset = modelDataGroup->indexOffset;
  240. modelGroup->triangleCount = modelDataGroup->triangleCount;
  241. modelGroup->bounds = modelDataGroup->bounds;
  242. // Add model group to model
  243. model->addGroup(modelGroup);
  244. }
  245. // Delete model data groups
  246. delete[] modelData->groups;
  247. // Delete model data
  248. delete modelData;
  249. return model;
  250. }
  251. void ModelLoader::setMaterialLoader(MaterialLoader* materialLoader)
  252. {
  253. this->materialLoader = materialLoader;
  254. }