Merge branch 'multithread'

This commit is contained in:
2021-04-13 20:43:38 +02:00
10 changed files with 117 additions and 29 deletions

View File

@@ -6,7 +6,7 @@
}, },
"pointLights": [ "pointLights": [
{ {
"intensity": 10.0, "intensity": 7.5,
"position": [0.0, 1.0, 0.0], "position": [0.0, 1.0, 0.0],
"color": [1.0, 1.0, 1.0] "color": [1.0, 1.0, 1.0]
} }

View File

@@ -29,6 +29,7 @@ target_link_libraries(
${OPENGL_LIBRARIES} ${OPENGL_LIBRARIES}
${FREETYPE_LIBRARIES} ${FREETYPE_LIBRARIES}
imgui imgui
pthread
) )
target_compile_options(Fall-Fever PRIVATE -Wall -Wextra -pedantic) target_compile_options(Fall-Fever PRIVATE -Wall -Wextra -pedantic)

View File

@@ -111,7 +111,7 @@ void Controller::run()
world->getEntityById(0)->rotate(glm::vec3(0.0f, 1.0f, 0.0f), -0.2f * deltaTime); world->getEntityById(0)->rotate(glm::vec3(0.0f, 1.0f, 0.0f), -0.2f * deltaTime);
} }
static glm::vec3 lightColor = glm::vec3(1.f); 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->updatePointLight(0, true, world->getEntityByName("light")->getPosition(), lightColor, intensity);
world->updateDirectionalLight(true, world->getDirectionalLight()->getDirection(), lightColor); world->updateDirectionalLight(true, world->getDirectionalLight()->getDirection(), lightColor);
getShaderProgramByName("lightProgram")->bind(); getShaderProgramByName("lightProgram")->bind();

View File

@@ -2,8 +2,9 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <future>
JsonParser::JsonParser(std::string path) JsonParser::JsonParser(const std::string& path)
{ {
std::ifstream file(path.c_str(), std::ifstream::binary); std::ifstream file(path.c_str(), std::ifstream::binary);
@@ -33,16 +34,37 @@ std::vector<Model*> JsonParser::getModels()
const Json::Value modelsJson = root["models"]; 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++) { for (unsigned int index = 0; index < modelsJson.size(); index++) {
std::string model_name = modelsJson[index]["unique_name"].asString(); std::string model_name = modelsJson[index]["unique_name"].asString();
std::string model_path = modelsJson[index]["path"].asString(); std::string model_path = modelsJson[index]["path"].asString();
Model *current_model = new Model(model_name, model_path); ModelSkeleton model_skeleton = {model_name, model_path};
if(current_model) { model_skeletons.push_back(model_skeleton);
temp_models.push_back(current_model);
std::cout << "Loaded Model \"" << model_name << "\" from \"" << model_path << "\"" << std::endl;
}
} }
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; return temp_models;
} }

View File

@@ -13,7 +13,7 @@
class JsonParser class JsonParser
{ {
public: public:
JsonParser(std::string path); JsonParser(const std::string& path);
~JsonParser(); ~JsonParser();
std::vector<Model*> getModels(); std::vector<Model*> getModels();

View File

@@ -5,7 +5,7 @@
uint32_t Model::id_counter = 0; 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) unique_name(modelName)
{ {
directory = modelPath.substr(0, modelPath.find_last_of('/')); directory = modelPath.substr(0, modelPath.find_last_of('/'));
@@ -24,6 +24,11 @@ Model::~Model()
void Model::draw(ShaderProgram *shaderProgram) 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 // Iterate through every mesh and call the draw function
for (auto it = meshes.begin(); it != meshes.end(); it++) { for (auto it = meshes.begin(); it != meshes.end(); it++) {
(*it)->draw(shaderProgram); (*it)->draw(shaderProgram);
@@ -32,13 +37,18 @@ void Model::draw(ShaderProgram *shaderProgram)
void Model::drawWithoutTextures() 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 // Iterate through every mesh and call the draw function
for (auto it = meshes.begin(); it != meshes.end(); it++) { for (auto it = meshes.begin(); it != meshes.end(); it++) {
(*it)->drawWithoutTextures(); (*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); std::ifstream input(pathToModel, std::ios::in | std::ios::binary);
@@ -71,10 +81,15 @@ void Model::loadModel(std::string &pathToModel)
textureSources.push_back(currentTextureSource); textureSources.push_back(currentTextureSource);
} }
for (unsigned int i = 0; i < numTextures; i++) { for (unsigned int i = 0; i < numTextures; i++) {
std::string textureSource = directory + '/' + textureSources[i].c_str(); TexturePrototype texture_prototype;
Texture *newTex = new Texture(textureSource.c_str(), textureTypes[i]); std::string texturePath = directory + '/' + textureSources[i].c_str();
loadedTextures.push_back(newTex);
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 // When there is no normal map bound, please use fallback texture
@@ -85,8 +100,12 @@ void Model::loadModel(std::string &pathToModel)
} }
if (!hasNormalMap) { if (!hasNormalMap) {
Texture *newTex = new Texture("data/res/models/tex/fallback_normal.png", textureType::texture_normal); TexturePrototype texture_prototype;
loadedTextures.push_back(newTex);
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 // Here starts the first mesh
@@ -95,6 +114,8 @@ void Model::loadModel(std::string &pathToModel)
for (unsigned int j = 0; j < numMeshes; j++) { for (unsigned int j = 0; j < numMeshes; j++) {
MeshPrototype mesh_prototype;
uint32_t numMeshVertices, numMeshIndices, numMeshTextureIds; uint32_t numMeshVertices, numMeshIndices, numMeshTextureIds;
input.read((char *) &numMeshVertices, sizeof(uint32_t)); input.read((char *) &numMeshVertices, sizeof(uint32_t));
@@ -109,30 +130,53 @@ void Model::loadModel(std::string &pathToModel)
std::vector<Vertex> meshVertices; std::vector<Vertex> meshVertices;
meshVertices.resize(numMeshVertices); meshVertices.resize(numMeshVertices);
input.read((char *) meshVertices.data(), vertexBlockSize); input.read((char *) meshVertices.data(), vertexBlockSize);
mesh_prototype.meshVertices = std::move(meshVertices);
std::vector<uint32_t> meshIndices; std::vector<uint32_t> meshIndices;
meshIndices.resize(numMeshIndices); meshIndices.resize(numMeshIndices);
input.read((char *) meshIndices.data(), indexBlockSize); input.read((char *) meshIndices.data(), indexBlockSize);
mesh_prototype.meshIndices = std::move(meshIndices);
std::vector<Texture *> meshTextures;
for (unsigned int i = 0; i < numMeshTextureIds; i++) { for (unsigned int i = 0; i < numMeshTextureIds; i++) {
uint32_t currentTextureId; uint32_t currentTextureId;
input.read((char *) &currentTextureId, sizeof(uint32_t)); input.read((char *) &currentTextureId, sizeof(uint32_t));
meshTextures.push_back(loadedTextures[currentTextureId]); mesh_prototype.textureIds.push_back(currentTextureId);
} }
if (!hasNormalMap) { if (!hasNormalMap) {
// This will be the last texture // This will be the last texture
meshTextures.push_back(loadedTextures[numTextures]); mesh_prototype.textureIds.push_back(numTextures);
} }
Mesh *currentMesh = new Mesh(meshVertices, meshIndices, meshTextures); modelMeshPrototypes.push_back(std::move(mesh_prototype));
meshes.push_back(currentMesh);
} }
input.close(); 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) Mesh* Model::getMesh(unsigned int index)
{ {
return meshes[index]; return meshes[index];

View File

@@ -5,12 +5,25 @@
#include "Mesh.h" #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 class Model
{ {
public: public:
Model(std::string &modelName, std::string &pathToModel); Model(const std::string& modelName, const std::string& pathToModel);
~Model(); ~Model();
void prepareModel();
void draw(ShaderProgram *shaderProgram); void draw(ShaderProgram *shaderProgram);
void drawWithoutTextures(); void drawWithoutTextures();
@@ -18,14 +31,19 @@ public:
std::string getUniqueName(); std::string getUniqueName();
private: private:
void loadModel(std::string &pathToModel); void loadModel(const std::string &pathToModel);
private: private:
std::vector<Mesh *> meshes; std::vector<Mesh *> meshes;
std::vector<Texture *> loadedTextures; std::vector<Texture *> loadedTextures;
std::vector<TexturePrototype> modelTexturePrototypes;
std::vector<MeshPrototype> modelMeshPrototypes;
std::string directory; std::string directory;
bool model_prepared = false;
static uint32_t id_counter; static uint32_t id_counter;
uint32_t id; uint32_t id;
std::string unique_name; std::string unique_name;

View File

@@ -3,13 +3,11 @@
#include <stb/stb_image.h> #include <stb/stb_image.h>
#include <iostream> #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); 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 internalFormat;
GLenum dataFormat; GLenum dataFormat;

View File

@@ -15,7 +15,7 @@ enum cubeMapFaces {cm_right, cm_left, cm_top, cm_bottom, cm_back, cm_front, CUBE
class Texture class Texture
{ {
public: public:
Texture(const char *texturePath, uint8_t textureType); Texture(const std::string& texturePath, uint8_t textureType);
~Texture(); ~Texture();
void bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum); void bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum);

View File

@@ -21,6 +21,11 @@ World::World(std::vector<ShaderProgram*> shaderPrograms) :
JsonParser modelParser("data/models.json"); JsonParser modelParser("data/models.json");
models = modelParser.getModels(); models = modelParser.getModels();
for (const auto& it : models) {
it->prepareModel();
}
entities = modelParser.getEntities(models, shaderPrograms); entities = modelParser.getEntities(models, shaderPrograms);
skybox = modelParser.getSkybox(getModelByName("cube"), Controller::getShaderProgramByName(shaderPrograms, "skyboxProgram")); skybox = modelParser.getSkybox(getModelByName("cube"), Controller::getShaderProgramByName(shaderPrograms, "skyboxProgram"));