Added multithreading template in utils, using cereal instead of sparrowserializer for the config file

This commit is contained in:
Anselme 2018-05-13 21:21:30 +02:00
parent cd714f62e2
commit 13add53503
4 changed files with 87 additions and 40 deletions

View File

@ -1,8 +1,7 @@
#ifndef SCENENODE_H #ifndef SCENENODE_H
#define SCENENODE_H #define SCENENODE_H
#include <glm/mat4x4.hpp> #include <glm/ext.hpp>
#include <glm/vec3.hpp>
#include "LinearMath/btMotionState.h" #include "LinearMath/btMotionState.h"
#include <SparrowRenderer/scene.h> #include <SparrowRenderer/scene.h>

View File

@ -7,7 +7,6 @@
#include "Version.h" #include "Version.h"
#include "SparrowInput/Version.h" #include "SparrowInput/Version.h"
#include "SparrowRenderer/Version.h" #include "SparrowRenderer/Version.h"
#include "SparrowSerializer/Version.h"
#include "tools/utils.h" #include "tools/utils.h"
#include "editor.h" #include "editor.h"
#include "keymapper.h" #include "keymapper.h"

View File

@ -35,6 +35,7 @@
//#include "potator.h" //#include "potator.h"
#include "SparrowSerializer/serializationmanager.h" #include "SparrowSerializer/serializationmanager.h"
#include "SparrowSerializer/serializable.h" #include "SparrowSerializer/serializable.h"
#include <cereal/archives/json.hpp>
#include <fstream> #include <fstream>
#include "resourcemanager.h" #include "resourcemanager.h"
@ -81,10 +82,9 @@ public:
} }
}; };
void generateTerrain(SceneTree *scene, btDiscreteDynamicsWorld *world) void generateTerrain(SceneTree *scene)
{ {
SceneNode* terrainContainer = new SceneNode(); SceneNode* terrainContainer = new SceneNode();
scene->getRootObject()->addChild(terrainContainer);
TestGen gen; TestGen gen;
PBRMaterial *mat = new PBRMaterial(); PBRMaterial *mat = new PBRMaterial();
mat->albedo = glm::vec3(0.1f, 0.4f, 0.2f); mat->albedo = glm::vec3(0.1f, 0.4f, 0.2f);
@ -108,12 +108,13 @@ void generateTerrain(SceneTree *scene, btDiscreteDynamicsWorld *world)
node->setMesh(chunk->mesh); node->setMesh(chunk->mesh);
node->getGeometryNode()->modelMatrix = glm::translate(glm::scale(glm::mat4(), glm::vec3(2.f)), pos*8.f); node->getGeometryNode()->modelMatrix = glm::translate(glm::scale(glm::mat4(), glm::vec3(2.f)), pos*8.f);
node->setTransform(node->getGeometryNode()->modelMatrix); node->setTransform(node->getGeometryNode()->modelMatrix);
terrainContainer->addChild(node);
btRigidBody* body = utils::buildStaticCollider(node->getGeometryNode()); btRigidBody* body = utils::buildStaticCollider(node->getGeometryNode());
node->setRigidBody(body); node->setRigidBody(body);
world->addRigidBody(body); scene->getPhysics()->addRigidBody(body);
terrainContainer->addChild(node);
} }
} }
scene->getRootObject()->addChild(terrainContainer);
} }
void generateSponza(SceneTree *scene, btDiscreteDynamicsWorld *world) void generateSponza(SceneTree *scene, btDiscreteDynamicsWorld *world)
@ -153,14 +154,13 @@ void generateSponza(SceneTree *scene, btDiscreteDynamicsWorld *world)
} }
} }
struct Config : public Serializable struct Config
{ {
P_STRING(mode) // fullscreen / windowed / borderless std::string mode; // fullscreen / windowed / borderless
P_STRING(scene) // terrain / sponza / none std::string scene; // terrain / sponza / none
P_BOOL(vsync) bool vsync;
P_INT(width) int width;
P_INT(height) int height;
SERIALIZABLE(Config, CAST(mode), CAST(scene), CAST(vsync), CAST(width), CAST(height))
Config() Config()
{ {
@ -171,30 +171,43 @@ struct Config : public Serializable
height = 600; height = 600;
} }
static Config* load() void save()
{
std::fstream configFile;
configFile.open("config.ini", std::ios_base::out);
cereal::JSONOutputArchive output(configFile);
output(cereal::make_nvp("mode", mode));
output(cereal::make_nvp("scene", scene));
output(cereal::make_nvp("vsync", vsync));
output(cereal::make_nvp("width", width));
output(cereal::make_nvp("height", height));
output.finishNode();
configFile << std::endl;
configFile.close();
}
void load()
{ {
std::fstream configFile; std::fstream configFile;
configFile.open("config.ini", std::ios_base::in); configFile.open("config.ini", std::ios_base::in);
Config *conf;
if(configFile.is_open()) if(configFile.is_open())
{ {
ObjectLoader loader; try
loader.loadAscii(configFile); {
configFile.close(); cereal::JSONInputArchive input(configFile);
const std::vector<Config*>& confVec = loader.getObjects<Config>(); input(cereal::make_nvp("mode", mode));
if(confVec.size() != 0) input(cereal::make_nvp("scene", scene));
conf = confVec[0]; input(cereal::make_nvp("vsync", vsync));
else input(cereal::make_nvp("width", width));
conf = new Config(); input(cereal::make_nvp("height", height));
}
catch(cereal::Exception e)
{
std::cerr << "Config file contains errors : " << e.what() << std::endl;
} }
else
conf = new Config();
ObjectSaver saver;
saver.addObject(conf);
configFile.open("config.ini", std::ios_base::out);
saver.saveAscii(configFile);
configFile.close(); configFile.close();
return conf; }
save();
} }
}; };
@ -253,7 +266,7 @@ public:
else if(m_config->scene == "terrain") else if(m_config->scene == "terrain")
{ {
sun->initShadowMap(4096); sun->initShadowMap(4096);
generateTerrain(scene, m_engine->getScene()->getPhysics()); generateTerrain(scene);
m_player->setPosition(0.f, 15.f, 0.f); m_player->setPosition(0.f, 15.f, 0.f);
sun->setShadowView(glm::vec3(130, 130, 70)); sun->setShadowView(glm::vec3(130, 130, 70));
} }
@ -350,10 +363,9 @@ public:
std::string getScene(){return m_menu_scene;} std::string getScene(){return m_menu_scene;}
}; };
INIT_SERIALIZABLE(Config)
int main(){ int main(){
Config* config = Config::load(); Config* config = new Config();
config->load();
Engine engine; Engine engine;
Loader::setObjDirectory("data/"); Loader::setObjDirectory("data/");

View File

@ -4,6 +4,9 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <algorithm>
#include <functional>
#include <thread>
class ScriptNode; class ScriptNode;
class btRigidBody; class btRigidBody;
@ -15,11 +18,6 @@ namespace utils
std::vector<std::string> split(const std::string &line, char sep); std::vector<std::string> split(const std::string &line, char sep);
void initScriptingUtilsFunctions(ScriptNode* scriptNode); void initScriptingUtilsFunctions(ScriptNode* scriptNode);
void initStandardScene(); void initStandardScene();
//void setPosition2D(MeshNode*, glm::vec2);
//void resize2D(MeshNode*, glm::vec2, glm::vec2);
//void scale2D(MeshNode*, glm::vec2);
//void rotate2D(MeshNode* mnode, glm::vec2 center, float angle);
//void setDepth2D(MeshNode* mnode, float depth);
/** /**
* @warning collisions on static meshes does not work if the transform is modified after the rigidbody construction * @warning collisions on static meshes does not work if the transform is modified after the rigidbody construction
@ -27,6 +25,45 @@ void initStandardScene();
btRigidBody* buildStaticCollider(GeometryNode* node); btRigidBody* buildStaticCollider(GeometryNode* node);
SceneNode* createTerrain(const std::string &heightMap, const std::string &colorMap, float maxHeight = 100); SceneNode* createTerrain(const std::string &heightMap, const std::string &colorMap, float maxHeight = 100);
template <typename T>
void parallelFor(T startVal, T endVal, std::function<void(T)> fun, unsigned int nbThreads = 0)
{
std::vector<std::thread*> threads;
// each thread will execute this lambda once
auto taskLoop = [=](T start, T end){
for(T i=start; i<end; ++i)
fun(i);
};
// check parameters
if(nbThreads == 0)
nbThreads = std::thread::hardware_concurrency();
if(nbThreads == 0)
nbThreads = 1;
T totalSize = endVal - startVal;
if(totalSize < nbThreads)
return; // nope
// start threads
int interval = totalSize/nbThreads;
for(unsigned int i=0; i<nbThreads; ++i)
{
T end = (i == nbThreads - 1) ? endVal : startVal + interval;
threads.push_back(new std::thread(taskLoop, startVal, end));
startVal = end;
}
// synchronize threads
for(std::thread* t : threads)
{
t->join();
delete t;
}
} }
} // namespace utils
#endif // UTILS_H #endif // UTILS_H