| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- // ----------------------------------------------------------------
- // From Game Programming in C++ by Sanjay Madhav
- // Copyright (C) 2017 Sanjay Madhav. All rights reserved.
- //
- // Released under the BSD License
- // See LICENSE in root directory for full details.
- // ----------------------------------------------------------------
- #include "Mesh.h"
- #include "Renderer.h"
- #include "Texture.h"
- #include "VertexArray.h"
- #include <fstream>
- #include <sstream>
- #include <rapidjson/document.h>
- #include <SDL/SDL_log.h>
- #include "Math.h"
- Mesh::Mesh()
- :mBox(Vector3::Infinity, Vector3::NegInfinity)
- ,mVertexArray(nullptr)
- ,mRadius(0.0f)
- ,mSpecPower(100.0f)
- {
- }
- Mesh::~Mesh()
- {
- }
- bool Mesh::Load(const std::string& fileName, Renderer* renderer)
- {
- std::ifstream file(fileName);
- if (!file.is_open())
- {
- SDL_Log("File not found: Mesh %s", fileName.c_str());
- return false;
- }
- std::stringstream fileStream;
- fileStream << file.rdbuf();
- std::string contents = fileStream.str();
- rapidjson::StringStream jsonStr(contents.c_str());
- rapidjson::Document doc;
- doc.ParseStream(jsonStr);
- if (!doc.IsObject())
- {
- SDL_Log("Mesh %s is not valid json", fileName.c_str());
- return false;
- }
- int ver = doc["version"].GetInt();
- // Check the version
- if (ver != 1)
- {
- SDL_Log("Mesh %s not version 1", fileName.c_str());
- return false;
- }
- mShaderName = doc["shader"].GetString();
- // Skip the vertex format/shader for now
- // (This is changed in a later chapter's code)
- size_t vertSize = 8;
- // Load textures
- const rapidjson::Value& textures = doc["textures"];
- if (!textures.IsArray() || textures.Size() < 1)
- {
- SDL_Log("Mesh %s has no textures, there should be at least one", fileName.c_str());
- return false;
- }
- mSpecPower = static_cast<float>(doc["specularPower"].GetDouble());
- for (rapidjson::SizeType i = 0; i < textures.Size(); i++)
- {
- // Is this texture already loaded?
- std::string texName = textures[i].GetString();
- Texture* t = renderer->GetTexture(texName);
- if (t == nullptr)
- {
- // Try loading the texture
- t = renderer->GetTexture(texName);
- if (t == nullptr)
- {
- // If it's still null, just use the default texture
- t = renderer->GetTexture("Assets/Default.png");
- }
- }
- mTextures.emplace_back(t);
- }
- // Load in the vertices
- const rapidjson::Value& vertsJson = doc["vertices"];
- if (!vertsJson.IsArray() || vertsJson.Size() < 1)
- {
- SDL_Log("Mesh %s has no vertices", fileName.c_str());
- return false;
- }
- std::vector<float> vertices;
- vertices.reserve(vertsJson.Size() * vertSize);
- mRadius = 0.0f;
- for (rapidjson::SizeType i = 0; i < vertsJson.Size(); i++)
- {
- // For now, just assume we have 8 elements
- const rapidjson::Value& vert = vertsJson[i];
- if (!vert.IsArray() || vert.Size() != 8)
- {
- SDL_Log("Unexpected vertex format for %s", fileName.c_str());
- return false;
- }
- Vector3 pos(vert[0].GetDouble(), vert[1].GetDouble(), vert[2].GetDouble());
- mRadius = Math::Max(mRadius, pos.LengthSq());
- mBox.UpdateMinMax(pos);
- // Add the floats
- for (rapidjson::SizeType i = 0; i < vert.Size(); i++)
- {
- vertices.emplace_back(static_cast<float>(vert[i].GetDouble()));
- }
- }
- // We were computing length squared earlier
- mRadius = Math::Sqrt(mRadius);
- // Load in the indices
- const rapidjson::Value& indJson = doc["indices"];
- if (!indJson.IsArray() || indJson.Size() < 1)
- {
- SDL_Log("Mesh %s has no indices", fileName.c_str());
- return false;
- }
- std::vector<unsigned int> indices;
- indices.reserve(indJson.Size() * 3);
- for (rapidjson::SizeType i = 0; i < indJson.Size(); i++)
- {
- const rapidjson::Value& ind = indJson[i];
- if (!ind.IsArray() || ind.Size() != 3)
- {
- SDL_Log("Invalid indices for %s", fileName.c_str());
- return false;
- }
- indices.emplace_back(ind[0].GetUint());
- indices.emplace_back(ind[1].GetUint());
- indices.emplace_back(ind[2].GetUint());
- }
- // Now create a vertex array
- mVertexArray = new VertexArray(vertices.data(), static_cast<unsigned>(vertices.size()) / vertSize,
- indices.data(), static_cast<unsigned>(indices.size()));
- return true;
- }
- void Mesh::Unload()
- {
- delete mVertexArray;
- mVertexArray = nullptr;
- }
- Texture* Mesh::GetTexture(size_t index)
- {
- if (index < mTextures.size())
- {
- return mTextures[index];
- }
- else
- {
- return nullptr;
- }
- }
|