Merge branch 'multithread'
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
},
|
||||
"pointLights": [
|
||||
{
|
||||
"intensity": 10.0,
|
||||
"intensity": 7.5,
|
||||
"position": [0.0, 1.0, 0.0],
|
||||
"color": [1.0, 1.0, 1.0]
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ target_link_libraries(
|
||||
${OPENGL_LIBRARIES}
|
||||
${FREETYPE_LIBRARIES}
|
||||
imgui
|
||||
pthread
|
||||
)
|
||||
|
||||
target_compile_options(Fall-Fever PRIVATE -Wall -Wextra -pedantic)
|
||||
|
||||
@@ -111,7 +111,7 @@ void Controller::run()
|
||||
world->getEntityById(0)->rotate(glm::vec3(0.0f, 1.0f, 0.0f), -0.2f * deltaTime);
|
||||
}
|
||||
static glm::vec3 lightColor = glm::vec3(1.f);
|
||||
static float intensity = 20.f;
|
||||
static float intensity = 7.5f;
|
||||
world->updatePointLight(0, true, world->getEntityByName("light")->getPosition(), lightColor, intensity);
|
||||
world->updateDirectionalLight(true, world->getDirectionalLight()->getDirection(), lightColor);
|
||||
getShaderProgramByName("lightProgram")->bind();
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <future>
|
||||
|
||||
JsonParser::JsonParser(std::string path)
|
||||
JsonParser::JsonParser(const std::string& path)
|
||||
{
|
||||
std::ifstream file(path.c_str(), std::ifstream::binary);
|
||||
|
||||
@@ -33,16 +34,37 @@ std::vector<Model*> JsonParser::getModels()
|
||||
|
||||
const Json::Value modelsJson = root["models"];
|
||||
|
||||
struct ModelSkeleton {
|
||||
std::string model_name;
|
||||
std::string model_path;
|
||||
};
|
||||
|
||||
std::vector<ModelSkeleton> model_skeletons;
|
||||
|
||||
for (unsigned int index = 0; index < modelsJson.size(); index++) {
|
||||
std::string model_name = modelsJson[index]["unique_name"].asString();
|
||||
std::string model_path = modelsJson[index]["path"].asString();
|
||||
Model *current_model = new Model(model_name, model_path);
|
||||
if(current_model) {
|
||||
temp_models.push_back(current_model);
|
||||
std::cout << "Loaded Model \"" << model_name << "\" from \"" << model_path << "\"" << std::endl;
|
||||
}
|
||||
ModelSkeleton model_skeleton = {model_name, model_path};
|
||||
model_skeletons.push_back(model_skeleton);
|
||||
}
|
||||
|
||||
std::vector<std::future<void>> futures;
|
||||
std::mutex mutex;
|
||||
|
||||
auto* temp_models_ptr = &temp_models;
|
||||
for (const auto& model_skeleton : model_skeletons) {
|
||||
auto loadModel = [&]() {
|
||||
Model *current_model = new Model(model_skeleton.model_name, model_skeleton.model_path);
|
||||
if(current_model) {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
temp_models_ptr->push_back(current_model);
|
||||
std::cout << "Loaded Model \"" << model_skeleton.model_name << "\" from \"" << model_skeleton.model_path << "\"" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
futures.push_back(std::async(std::launch::async, loadModel));
|
||||
}
|
||||
|
||||
return temp_models;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
class JsonParser
|
||||
{
|
||||
public:
|
||||
JsonParser(std::string path);
|
||||
JsonParser(const std::string& path);
|
||||
~JsonParser();
|
||||
|
||||
std::vector<Model*> getModels();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
uint32_t Model::id_counter = 0;
|
||||
|
||||
Model::Model(std::string &modelName, std::string &modelPath) :
|
||||
Model::Model(const std::string &modelName, const std::string &modelPath) :
|
||||
unique_name(modelName)
|
||||
{
|
||||
directory = modelPath.substr(0, modelPath.find_last_of('/'));
|
||||
@@ -24,6 +24,11 @@ Model::~Model()
|
||||
|
||||
void Model::draw(ShaderProgram *shaderProgram)
|
||||
{
|
||||
if (!model_prepared) {
|
||||
std::cout << "WARNING: Model not prepared! Unable to draw!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate through every mesh and call the draw function
|
||||
for (auto it = meshes.begin(); it != meshes.end(); it++) {
|
||||
(*it)->draw(shaderProgram);
|
||||
@@ -32,13 +37,18 @@ void Model::draw(ShaderProgram *shaderProgram)
|
||||
|
||||
void Model::drawWithoutTextures()
|
||||
{
|
||||
if (!model_prepared) {
|
||||
std::cout << "WARNING: Model not prepared! Unable to draw!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate through every mesh and call the draw function
|
||||
for (auto it = meshes.begin(); it != meshes.end(); it++) {
|
||||
(*it)->drawWithoutTextures();
|
||||
}
|
||||
}
|
||||
|
||||
void Model::loadModel(std::string &pathToModel)
|
||||
void Model::loadModel(const std::string &pathToModel)
|
||||
{
|
||||
std::ifstream input(pathToModel, std::ios::in | std::ios::binary);
|
||||
|
||||
@@ -71,10 +81,15 @@ void Model::loadModel(std::string &pathToModel)
|
||||
textureSources.push_back(currentTextureSource);
|
||||
}
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < numTextures; i++) {
|
||||
std::string textureSource = directory + '/' + textureSources[i].c_str();
|
||||
Texture *newTex = new Texture(textureSource.c_str(), textureTypes[i]);
|
||||
loadedTextures.push_back(newTex);
|
||||
TexturePrototype texture_prototype;
|
||||
std::string texturePath = directory + '/' + textureSources[i].c_str();
|
||||
|
||||
texture_prototype.texturePath = std::move(texturePath);
|
||||
texture_prototype.textureType = textureTypes[i];
|
||||
|
||||
modelTexturePrototypes.push_back(texture_prototype);
|
||||
}
|
||||
|
||||
// When there is no normal map bound, please use fallback texture
|
||||
@@ -85,8 +100,12 @@ void Model::loadModel(std::string &pathToModel)
|
||||
}
|
||||
|
||||
if (!hasNormalMap) {
|
||||
Texture *newTex = new Texture("data/res/models/tex/fallback_normal.png", textureType::texture_normal);
|
||||
loadedTextures.push_back(newTex);
|
||||
TexturePrototype texture_prototype;
|
||||
|
||||
texture_prototype.texturePath = "data/res/models/tex/fallback_normal.png";
|
||||
texture_prototype.textureType = textureType::texture_normal;
|
||||
|
||||
modelTexturePrototypes.push_back(texture_prototype);
|
||||
}
|
||||
|
||||
// Here starts the first mesh
|
||||
@@ -95,6 +114,8 @@ void Model::loadModel(std::string &pathToModel)
|
||||
|
||||
for (unsigned int j = 0; j < numMeshes; j++) {
|
||||
|
||||
MeshPrototype mesh_prototype;
|
||||
|
||||
uint32_t numMeshVertices, numMeshIndices, numMeshTextureIds;
|
||||
|
||||
input.read((char *) &numMeshVertices, sizeof(uint32_t));
|
||||
@@ -109,30 +130,53 @@ void Model::loadModel(std::string &pathToModel)
|
||||
std::vector<Vertex> meshVertices;
|
||||
meshVertices.resize(numMeshVertices);
|
||||
input.read((char *) meshVertices.data(), vertexBlockSize);
|
||||
mesh_prototype.meshVertices = std::move(meshVertices);
|
||||
|
||||
std::vector<uint32_t> meshIndices;
|
||||
meshIndices.resize(numMeshIndices);
|
||||
input.read((char *) meshIndices.data(), indexBlockSize);
|
||||
mesh_prototype.meshIndices = std::move(meshIndices);
|
||||
|
||||
std::vector<Texture *> meshTextures;
|
||||
for (unsigned int i = 0; i < numMeshTextureIds; i++) {
|
||||
uint32_t currentTextureId;
|
||||
input.read((char *) ¤tTextureId, sizeof(uint32_t));
|
||||
meshTextures.push_back(loadedTextures[currentTextureId]);
|
||||
mesh_prototype.textureIds.push_back(currentTextureId);
|
||||
}
|
||||
|
||||
if (!hasNormalMap) {
|
||||
// This will be the last texture
|
||||
meshTextures.push_back(loadedTextures[numTextures]);
|
||||
mesh_prototype.textureIds.push_back(numTextures);
|
||||
}
|
||||
|
||||
Mesh *currentMesh = new Mesh(meshVertices, meshIndices, meshTextures);
|
||||
meshes.push_back(currentMesh);
|
||||
modelMeshPrototypes.push_back(std::move(mesh_prototype));
|
||||
}
|
||||
|
||||
input.close();
|
||||
}
|
||||
|
||||
void Model::prepareModel()
|
||||
{
|
||||
model_prepared = true;
|
||||
|
||||
// Create textures on GPU
|
||||
for (auto& it : modelTexturePrototypes) {
|
||||
Texture *newTex = new Texture(it.texturePath.c_str(), it.textureType);
|
||||
loadedTextures.push_back(newTex);
|
||||
}
|
||||
|
||||
// Create meshes on GPU
|
||||
for (const auto& it : modelMeshPrototypes) {
|
||||
std::vector<Texture *> meshTextures;
|
||||
for (const auto it2 : it.textureIds) {
|
||||
meshTextures.push_back(loadedTextures[it2]);
|
||||
}
|
||||
|
||||
Mesh *currentMesh = new Mesh(std::move(it.meshVertices), std::move(it.meshIndices), meshTextures);
|
||||
meshes.push_back(currentMesh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Mesh* Model::getMesh(unsigned int index)
|
||||
{
|
||||
return meshes[index];
|
||||
|
||||
22
src/Model.h
22
src/Model.h
@@ -5,12 +5,25 @@
|
||||
|
||||
#include "Mesh.h"
|
||||
|
||||
struct TexturePrototype {
|
||||
uint32_t textureType;
|
||||
std::string texturePath;
|
||||
};
|
||||
|
||||
struct MeshPrototype {
|
||||
std::vector<uint32_t> textureIds;
|
||||
std::vector<Vertex> meshVertices;
|
||||
std::vector<uint32_t> meshIndices;
|
||||
};
|
||||
|
||||
class Model
|
||||
{
|
||||
public:
|
||||
Model(std::string &modelName, std::string &pathToModel);
|
||||
Model(const std::string& modelName, const std::string& pathToModel);
|
||||
~Model();
|
||||
|
||||
void prepareModel();
|
||||
|
||||
void draw(ShaderProgram *shaderProgram);
|
||||
void drawWithoutTextures();
|
||||
|
||||
@@ -18,14 +31,19 @@ public:
|
||||
std::string getUniqueName();
|
||||
|
||||
private:
|
||||
void loadModel(std::string &pathToModel);
|
||||
void loadModel(const std::string &pathToModel);
|
||||
|
||||
private:
|
||||
std::vector<Mesh *> meshes;
|
||||
std::vector<Texture *> loadedTextures;
|
||||
|
||||
std::vector<TexturePrototype> modelTexturePrototypes;
|
||||
std::vector<MeshPrototype> modelMeshPrototypes;
|
||||
|
||||
std::string directory;
|
||||
|
||||
bool model_prepared = false;
|
||||
|
||||
static uint32_t id_counter;
|
||||
uint32_t id;
|
||||
std::string unique_name;
|
||||
|
||||
@@ -3,13 +3,11 @@
|
||||
#include <stb/stb_image.h>
|
||||
#include <iostream>
|
||||
|
||||
Texture::Texture(const char *texturePath, uint8_t textureType)
|
||||
Texture::Texture(const std::string& texturePath, uint8_t textureType) :
|
||||
texturePath(texturePath), textureType(textureType)
|
||||
{
|
||||
this->texturePath = texturePath;
|
||||
this->textureType = textureType;
|
||||
|
||||
stbi_set_flip_vertically_on_load(1);
|
||||
auto *textureBuffer = stbi_load(texturePath, &textureWidth, &textureHeight, &numComponents, 0);
|
||||
auto *textureBuffer = stbi_load(texturePath.c_str(), &textureWidth, &textureHeight, &numComponents, 0);
|
||||
|
||||
GLenum internalFormat;
|
||||
GLenum dataFormat;
|
||||
|
||||
@@ -15,7 +15,7 @@ enum cubeMapFaces {cm_right, cm_left, cm_top, cm_bottom, cm_back, cm_front, CUBE
|
||||
class Texture
|
||||
{
|
||||
public:
|
||||
Texture(const char *texturePath, uint8_t textureType);
|
||||
Texture(const std::string& texturePath, uint8_t textureType);
|
||||
~Texture();
|
||||
|
||||
void bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum);
|
||||
|
||||
@@ -21,6 +21,11 @@ World::World(std::vector<ShaderProgram*> shaderPrograms) :
|
||||
|
||||
JsonParser modelParser("data/models.json");
|
||||
models = modelParser.getModels();
|
||||
|
||||
for (const auto& it : models) {
|
||||
it->prepareModel();
|
||||
}
|
||||
|
||||
entities = modelParser.getEntities(models, shaderPrograms);
|
||||
skybox = modelParser.getSkybox(getModelByName("cube"), Controller::getShaderProgramByName(shaderPrograms, "skyboxProgram"));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user