Mesh.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // ----------------------------------------------------------------
  2. // From Game Programming in C++ by Sanjay Madhav
  3. // Copyright (C) 2017 Sanjay Madhav. All rights reserved.
  4. //
  5. // Released under the BSD License
  6. // See LICENSE in root directory for full details.
  7. // ----------------------------------------------------------------
  8. #include "Mesh.h"
  9. #include "Renderer.h"
  10. #include "Texture.h"
  11. #include "VertexArray.h"
  12. #include <fstream>
  13. #include <sstream>
  14. #include <rapidjson/document.h>
  15. #include <SDL/SDL_log.h>
  16. #include "Math.h"
  17. namespace
  18. {
  19. union Vertex
  20. {
  21. float f;
  22. uint8_t b[4];
  23. };
  24. }
  25. Mesh::Mesh()
  26. :mBox(Vector3::Infinity, Vector3::NegInfinity)
  27. ,mVertexArray(nullptr)
  28. ,mRadius(0.0f)
  29. ,mSpecPower(100.0f)
  30. {
  31. }
  32. Mesh::~Mesh()
  33. {
  34. }
  35. bool Mesh::Load(const std::string& fileName, Renderer* renderer)
  36. {
  37. std::ifstream file(fileName);
  38. if (!file.is_open())
  39. {
  40. SDL_Log("File not found: Mesh %s", fileName.c_str());
  41. return false;
  42. }
  43. std::stringstream fileStream;
  44. fileStream << file.rdbuf();
  45. std::string contents = fileStream.str();
  46. rapidjson::StringStream jsonStr(contents.c_str());
  47. rapidjson::Document doc;
  48. doc.ParseStream(jsonStr);
  49. if (!doc.IsObject())
  50. {
  51. SDL_Log("Mesh %s is not valid json", fileName.c_str());
  52. return false;
  53. }
  54. int ver = doc["version"].GetInt();
  55. // Check the version
  56. if (ver != 1)
  57. {
  58. SDL_Log("Mesh %s not version 1", fileName.c_str());
  59. return false;
  60. }
  61. mShaderName = doc["shader"].GetString();
  62. // Set the vertex layout/size based on the format in the file
  63. VertexArray::Layout layout = VertexArray::PosNormTex;
  64. size_t vertSize = 8;
  65. std::string vertexFormat = doc["vertexformat"].GetString();
  66. if (vertexFormat == "PosNormSkinTex")
  67. {
  68. layout = VertexArray::PosNormSkinTex;
  69. // This is the number of "Vertex" unions, which is 8 + 2 (for skinning)s
  70. vertSize = 10;
  71. }
  72. // Load textures
  73. const rapidjson::Value& textures = doc["textures"];
  74. if (!textures.IsArray() || textures.Size() < 1)
  75. {
  76. SDL_Log("Mesh %s has no textures, there should be at least one", fileName.c_str());
  77. return false;
  78. }
  79. mSpecPower = static_cast<float>(doc["specularPower"].GetDouble());
  80. for (rapidjson::SizeType i = 0; i < textures.Size(); i++)
  81. {
  82. // Is this texture already loaded?
  83. std::string texName = textures[i].GetString();
  84. Texture* t = renderer->GetTexture(texName);
  85. if (t == nullptr)
  86. {
  87. // Try loading the texture
  88. t = renderer->GetTexture(texName);
  89. if (t == nullptr)
  90. {
  91. // If it's still null, just use the default texture
  92. t = renderer->GetTexture("Assets/Default.png");
  93. }
  94. }
  95. mTextures.emplace_back(t);
  96. }
  97. // Load in the vertices
  98. const rapidjson::Value& vertsJson = doc["vertices"];
  99. if (!vertsJson.IsArray() || vertsJson.Size() < 1)
  100. {
  101. SDL_Log("Mesh %s has no vertices", fileName.c_str());
  102. return false;
  103. }
  104. std::vector<Vertex> vertices;
  105. vertices.reserve(vertsJson.Size() * vertSize);
  106. mRadius = 0.0f;
  107. for (rapidjson::SizeType i = 0; i < vertsJson.Size(); i++)
  108. {
  109. // For now, just assume we have 8 elements
  110. const rapidjson::Value& vert = vertsJson[i];
  111. if (!vert.IsArray())
  112. {
  113. SDL_Log("Unexpected vertex format for %s", fileName.c_str());
  114. return false;
  115. }
  116. Vector3 pos(vert[0].GetDouble(), vert[1].GetDouble(), vert[2].GetDouble());
  117. mRadius = Math::Max(mRadius, pos.LengthSq());
  118. mBox.UpdateMinMax(pos);
  119. if (layout == VertexArray::PosNormTex)
  120. {
  121. Vertex v;
  122. // Add the floats
  123. for (rapidjson::SizeType j = 0; j < vert.Size(); j++)
  124. {
  125. v.f = static_cast<float>(vert[j].GetDouble());
  126. vertices.emplace_back(v);
  127. }
  128. }
  129. else
  130. {
  131. Vertex v;
  132. // Add pos/normal
  133. for (rapidjson::SizeType j = 0; j < 6; j++)
  134. {
  135. v.f = static_cast<float>(vert[j].GetDouble());
  136. vertices.emplace_back(v);
  137. }
  138. // Add skin information
  139. for (rapidjson::SizeType j = 6; j < 14; j += 4)
  140. {
  141. v.b[0] = vert[j].GetUint();
  142. v.b[1] = vert[j + 1].GetUint();
  143. v.b[2] = vert[j + 2].GetUint();
  144. v.b[3] = vert[j + 3].GetUint();
  145. vertices.emplace_back(v);
  146. }
  147. // Add tex coords
  148. for (rapidjson::SizeType j = 14; j < vert.Size(); j++)
  149. {
  150. v.f = vert[j].GetDouble();
  151. vertices.emplace_back(v);
  152. }
  153. }
  154. }
  155. // We were computing length squared earlier
  156. mRadius = Math::Sqrt(mRadius);
  157. // Load in the indices
  158. const rapidjson::Value& indJson = doc["indices"];
  159. if (!indJson.IsArray() || indJson.Size() < 1)
  160. {
  161. SDL_Log("Mesh %s has no indices", fileName.c_str());
  162. return false;
  163. }
  164. std::vector<unsigned int> indices;
  165. indices.reserve(indJson.Size() * 3);
  166. for (rapidjson::SizeType i = 0; i < indJson.Size(); i++)
  167. {
  168. const rapidjson::Value& ind = indJson[i];
  169. if (!ind.IsArray() || ind.Size() != 3)
  170. {
  171. SDL_Log("Invalid indices for %s", fileName.c_str());
  172. return false;
  173. }
  174. indices.emplace_back(ind[0].GetUint());
  175. indices.emplace_back(ind[1].GetUint());
  176. indices.emplace_back(ind[2].GetUint());
  177. }
  178. // Now create a vertex array
  179. mVertexArray = new VertexArray(vertices.data(), static_cast<unsigned>(vertices.size()) / vertSize,
  180. layout, indices.data(), static_cast<unsigned>(indices.size()));
  181. return true;
  182. }
  183. void Mesh::Unload()
  184. {
  185. delete mVertexArray;
  186. mVertexArray = nullptr;
  187. }
  188. Texture* Mesh::GetTexture(size_t index)
  189. {
  190. if (index < mTextures.size())
  191. {
  192. return mTextures[index];
  193. }
  194. else
  195. {
  196. return nullptr;
  197. }
  198. }