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": [
{
"intensity": 10.0,
"intensity": 7.5,
"position": [0.0, 1.0, 0.0],
"color": [1.0, 1.0, 1.0]
}

View File

@@ -29,6 +29,7 @@ target_link_libraries(
${OPENGL_LIBRARIES}
${FREETYPE_LIBRARIES}
imgui
pthread
)
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);
}
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();

View File

@@ -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;
}

View File

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

View File

@@ -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 *) &currentTextureId, 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];

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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"));