Mesh.cpp 4.1 KB

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