Mesh.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. Mesh::Mesh()
  18. :mBox(Vector3::Infinity, Vector3::NegInfinity)
  19. ,mVertexArray(nullptr)
  20. ,mRadius(0.0f)
  21. ,mSpecPower(100.0f)
  22. {
  23. }
  24. Mesh::~Mesh()
  25. {
  26. }
  27. bool Mesh::Load(const std::string& fileName, Renderer* renderer)
  28. {
  29. std::ifstream file(fileName);
  30. if (!file.is_open())
  31. {
  32. SDL_Log("File not found: Mesh %s", fileName.c_str());
  33. return false;
  34. }
  35. std::stringstream fileStream;
  36. fileStream << file.rdbuf();
  37. std::string contents = fileStream.str();
  38. rapidjson::StringStream jsonStr(contents.c_str());
  39. rapidjson::Document doc;
  40. doc.ParseStream(jsonStr);
  41. if (!doc.IsObject())
  42. {
  43. SDL_Log("Mesh %s is not valid json", fileName.c_str());
  44. return false;
  45. }
  46. int ver = doc["version"].GetInt();
  47. // Check the version
  48. if (ver != 1)
  49. {
  50. SDL_Log("Mesh %s not version 1", fileName.c_str());
  51. return false;
  52. }
  53. mShaderName = doc["shader"].GetString();
  54. // Skip the vertex format/shader for now
  55. // (This is changed in a later chapter's code)
  56. size_t vertSize = 8;
  57. // Load textures
  58. const rapidjson::Value& textures = doc["textures"];
  59. if (!textures.IsArray() || textures.Size() < 1)
  60. {
  61. SDL_Log("Mesh %s has no textures, there should be at least one", fileName.c_str());
  62. return false;
  63. }
  64. mSpecPower = static_cast<float>(doc["specularPower"].GetDouble());
  65. for (rapidjson::SizeType i = 0; i < textures.Size(); i++)
  66. {
  67. // Is this texture already loaded?
  68. std::string texName = textures[i].GetString();
  69. Texture* t = renderer->GetTexture(texName);
  70. if (t == nullptr)
  71. {
  72. // Try loading the texture
  73. t = renderer->GetTexture(texName);
  74. if (t == nullptr)
  75. {
  76. // If it's still null, just use the default texture
  77. t = renderer->GetTexture("Assets/Default.png");
  78. }
  79. }
  80. mTextures.emplace_back(t);
  81. }
  82. // Load in the vertices
  83. const rapidjson::Value& vertsJson = doc["vertices"];
  84. if (!vertsJson.IsArray() || vertsJson.Size() < 1)
  85. {
  86. SDL_Log("Mesh %s has no vertices", fileName.c_str());
  87. return false;
  88. }
  89. std::vector<float> vertices;
  90. vertices.reserve(vertsJson.Size() * vertSize);
  91. mRadius = 0.0f;
  92. for (rapidjson::SizeType i = 0; i < vertsJson.Size(); i++)
  93. {
  94. // For now, just assume we have 8 elements
  95. const rapidjson::Value& vert = vertsJson[i];
  96. if (!vert.IsArray() || vert.Size() != 8)
  97. {
  98. SDL_Log("Unexpected vertex format for %s", fileName.c_str());
  99. return false;
  100. }
  101. Vector3 pos(vert[0].GetDouble(), vert[1].GetDouble(), vert[2].GetDouble());
  102. mRadius = Math::Max(mRadius, pos.LengthSq());
  103. mBox.UpdateMinMax(pos);
  104. // Add the floats
  105. for (rapidjson::SizeType i = 0; i < vert.Size(); i++)
  106. {
  107. vertices.emplace_back(static_cast<float>(vert[i].GetDouble()));
  108. }
  109. }
  110. // We were computing length squared earlier
  111. mRadius = Math::Sqrt(mRadius);
  112. // Load in the indices
  113. const rapidjson::Value& indJson = doc["indices"];
  114. if (!indJson.IsArray() || indJson.Size() < 1)
  115. {
  116. SDL_Log("Mesh %s has no indices", fileName.c_str());
  117. return false;
  118. }
  119. std::vector<unsigned int> indices;
  120. indices.reserve(indJson.Size() * 3);
  121. for (rapidjson::SizeType i = 0; i < indJson.Size(); i++)
  122. {
  123. const rapidjson::Value& ind = indJson[i];
  124. if (!ind.IsArray() || ind.Size() != 3)
  125. {
  126. SDL_Log("Invalid indices for %s", fileName.c_str());
  127. return false;
  128. }
  129. indices.emplace_back(ind[0].GetUint());
  130. indices.emplace_back(ind[1].GetUint());
  131. indices.emplace_back(ind[2].GetUint());
  132. }
  133. // Now create a vertex array
  134. mVertexArray = new VertexArray(vertices.data(), static_cast<unsigned>(vertices.size()) / vertSize,
  135. indices.data(), static_cast<unsigned>(indices.size()));
  136. return true;
  137. }
  138. void Mesh::Unload()
  139. {
  140. delete mVertexArray;
  141. mVertexArray = nullptr;
  142. }
  143. Texture* Mesh::GetTexture(size_t index)
  144. {
  145. if (index < mTextures.size())
  146. {
  147. return mTextures[index];
  148. }
  149. else
  150. {
  151. return nullptr;
  152. }
  153. }