This commit is contained in:
Lendemor 2017-08-26 23:12:06 +02:00
commit 9c388118a6
13 changed files with 460 additions and 4 deletions

38
deploy/data/woodbox.pack Normal file
View File

@ -0,0 +1,38 @@
{
"TextureResource": [
{
"woodbox albedo",
"woodframe_albedo.png",
24,
1,
1
}
{
"woodbox roughness",
"woodframe_roughness.png",
8,
1,
1
}
{
"woodbox metallic",
"woodframe_metallic.png",
8,
1,
1
}
{
"woodbox normals",
"woodframe_normal.png",
24,
1,
1
}
],
"ResourcePack": [
{
"woodbox",
[{"TextureResource", 0}]
}
]
}

View File

@ -14,6 +14,7 @@
#include "imgui/imgui.h"
#include "tools/loader.h"
#include "guitools.h"
#include "tools/loadingthread.h"
Engine::Engine() :
m_window(nullptr),
@ -34,6 +35,7 @@ Engine::Engine() :
Engine::~Engine()
{
LoadingThread::destroy();
delete m_clock;
delete m_renderer;
if(m_window != NULL)
@ -65,6 +67,7 @@ void Engine::createWindow(std::string title,
m_renderer->initGL(w, h);
m_sparrowshell = new SparrowShell(m_window);
m_guiTools = new GuiTools();
m_loadingThread = LoadingThread::init();
}
void Engine::initPhysics()
@ -109,6 +112,7 @@ void Engine::update()
bool isMouseVisible = m_mouseVisible;
if(ImGui::Checkbox("Mouse cursor ( shortcut : [M] )", &isMouseVisible))
toggleMouseVisibility();
ImGui::ProgressBar(m_loadingThread->getTotalProgress());
ImGui::End();
}
}

View File

@ -9,6 +9,7 @@ class SceneTree;
class SparrowShell;
class PhysicsDebugNode;
class GuiTools;
class LoadingThread;
namespace sf
{
@ -53,6 +54,7 @@ public:
SparrowShell* getShell() const {return m_sparrowshell;}
PhysicsDebugNode* getPhysicsDebug() const {return m_physicsDebugNode;}
GuiTools* getGuiTools() const {return m_guiTools;}
LoadingThread* getLoadingThread() const {return m_loadingThread;}
SceneTree* getScene() const;
unsigned int getTime() const;
@ -79,6 +81,7 @@ private:
PhysicsDebugNode *m_physicsDebugNode;
SparrowRenderer* m_renderer;
GuiTools* m_guiTools;
LoadingThread* m_loadingThread;
void update();

View File

@ -3,6 +3,7 @@
#include "engine.h"
#include "tools/scenepicker.h"
#include "scene/scenetree.h"
#include "tools/resourcepack.h"
#include <imgui/imgui.h>
@ -15,6 +16,7 @@
GuiTools::GuiTools() :
m_pickerNode(new ScenePicker()),
m_selectedMesh(nullptr),
m_editedResourcePack(nullptr),
m_pickerEnabled(false),
m_materialEditorEnabled(false)
{
@ -37,6 +39,9 @@ void GuiTools::update()
if(m_materialEditorEnabled)
materialGui();
if(m_editedResourcePack != nullptr)
m_editedResourcePack->gui();
}
void GuiTools::materialGui()
@ -98,3 +103,14 @@ void GuiTools::toggleRenderingPipelineGui()
DeferredPipeline* pipeline = dynamic_cast<DeferredPipeline*>(m_scene->getPipeline());
pipeline->toggleDebugGui();
}
void GuiTools::toggleResourcePackGui()
{
if(m_editedResourcePack == nullptr)
m_editedResourcePack = new ResourcePack();
else
{
delete m_editedResourcePack;
m_editedResourcePack = nullptr;
}
}

View File

@ -5,12 +5,14 @@
class Engine;
class ScenePicker;
class ResourcePack;
class Mesh;
class GuiTools : public ContainerNode
{
ScenePicker* m_pickerNode;
Mesh* m_selectedMesh;
ResourcePack* m_editedResourcePack;
bool m_pickerEnabled;
bool m_materialEditorEnabled;
public:
@ -21,6 +23,7 @@ public:
void togglePicker();
void toggleMaterialEditor();
void toggleRenderingPipelineGui();
void toggleResourcePackGui();
};
#endif // GUITOOLS_H

View File

@ -22,6 +22,7 @@ ScriptNode::ScriptNode()
LUA_SET_FUN(picker);
LUA_SET_FUN(materialEditor);
LUA_SET_FUN(rendering);
LUA_SET_FUN(resourcePackEditor);
m_script.new_usertype<Engine>("Engine",
"time",&Engine::getTime
@ -103,3 +104,7 @@ void ScriptNode::materialEditor(){
void ScriptNode::rendering(){
this->getEngine().getGuiTools()->toggleRenderingPipelineGui();
}
void ScriptNode::resourcePackEditor(){
this->getEngine().getGuiTools()->toggleResourcePackGui();
}

View File

@ -25,6 +25,7 @@ public:
void picker();
void materialEditor();
void rendering();
void resourcePackEditor();
};
#endif // SCRIPTNODE_H

View File

@ -7,8 +7,11 @@
#include "SparrowRenderer/pbrmaterial.h"
#include "scene/meshnode.h"
#include "tools/loader.h"
#include "tools/loadingthread.h"
#include "SparrowRenderer/texture.h"
#include "scene/graphicalcontainernode.h"
#include "resourcemanager.h"
#include <imgui/imgui.h>
#define PHYSICS_OFFSET 0.01f
@ -66,7 +69,7 @@ Potator::Potator(PlayerCharacterNode * player,
m_cubeMesh->addTriangle(id+7, id+5, id+6);
}
PBRMaterial *mat = new PBRMaterial();
PBRMaterial *mat = new PBRMaterial(); /*
Image* img = Loader::loadImage("woodframe_albedo.png", 24);
mat->setTexture(PBRMaterial::ALBEDO_SLOT, new Texture(img));
img = Loader::loadImage("woodframe_metallic.png", 8);
@ -74,7 +77,7 @@ Potator::Potator(PlayerCharacterNode * player,
img = Loader::loadImage("woodframe_roughness.png", 8);
mat->setTexture(PBRMaterial::ROUGHNESS_SLOT, new Texture(img));
img = Loader::loadImage("woodframe_normal.png", 24);
mat->setTexture(PBRMaterial::NORMALS_SLOT, new Texture(img));
mat->setTexture(PBRMaterial::NORMALS_SLOT, new Texture(img)); */
m_cubeMesh->setMaterial(mat);
m_cubeMesh->computeTangents();
@ -87,7 +90,7 @@ Potator::Potator(PlayerCharacterNode * player,
// creating sphere
mat = new PBRMaterial();
img = Loader::loadImage("slipperystonework_albedo.png", 24);
Image* img = Loader::loadImage("slipperystonework_albedo.png", 24);
mat->setTexture(PBRMaterial::ALBEDO_SLOT, new Texture(img));
img = Loader::loadImage("slipperystonework_metallic.png", 8);
mat->setTexture(PBRMaterial::METALLIC_SLOT, new Texture(img));
@ -188,4 +191,18 @@ void Potator::update()
throwSword();
}
}
ImGui::Begin("Potator");
if(ImGui::Button("Load pack"))
LoadingThread::get()->loadResourcePack("woodbox");
if(ImGui::Button("apply textures"))
{
PBRMaterial* mat = dynamic_cast<PBRMaterial*>(m_cubeMesh->getMaterial());
mat->setTexture(PBRMaterial::ALBEDO_SLOT, RESOURCE_GET(Texture, "woodbox albedo"));
mat->setTexture(PBRMaterial::METALLIC_SLOT, RESOURCE_GET(Texture, "woodbox metallic"));
mat->setTexture(PBRMaterial::ROUGHNESS_SLOT, RESOURCE_GET(Texture, "woodbox roughness"));
mat->setTexture(PBRMaterial::NORMALS_SLOT, RESOURCE_GET(Texture, "woodbox normals"));
m_scene->registerMeshType(m_cubeMesh->getFlags());
}
ImGui::End();
}

View File

@ -19,7 +19,7 @@ class Loader
public:
static std::string* loadTextFile(const std::string &filename);
static std::unordered_map<std::string, std::string>* loadConfigFile(const std::string &filename);
static Image* loadImage(const std::string &filename, int depth = 32, bool reversed = true);
static Image* loadImage(const std::string &filename, int depth = 24, bool reversed = true);
static std::vector<Mesh*> loadMesh(const std::string &filename);
static Font* loadFont(const std::string &texture, const std::string &description);
static bool loadMTL(const std::string &filename);

113
src/tools/loadingthread.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "loadingthread.h"
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <fstream>
#include <cstdio>
#include <SparrowSerializer/serializationmanager.h>
#include <SparrowRenderer/opengl.h>
LoadingThread* LoadingThread::singleton = nullptr;
std::thread* LoadingThread::thread = nullptr;
LoadingThread::LoadingThread() :
m_currentTask(nullptr),
m_running(true),
m_taskProgress(0),
m_nbTaskProcessed(0)
{
}
LoadingThread* LoadingThread::init()
{
if(singleton == nullptr)
{
singleton = new LoadingThread();
thread = new std::thread(LoadingThread::run);
}
return singleton;
}
void LoadingThread::destroy()
{
if(singleton != nullptr)
{
singleton->m_running = false;
thread->join();
delete singleton;
singleton = nullptr;
thread = nullptr;
}
}
void LoadingThread::run()
{
sf::Context openglContext;
singleton->processTasks();
}
void LoadingThread::processTasks()
{
while(m_running)
{
if(m_resourceQueue.empty())
sf::sleep(sf::milliseconds(500)); // wait for half a second
else
{
ResourceInterface* res = m_resourceQueue.front();
m_resourceQueue.pop_front();
res->load(m_taskProgress);
glFlush();
if(m_taskProgress < 1.0)
fprintf(stderr, "failed to process the following task : %s\n", res->m_name.c_str());
else
++m_nbTaskProcessed;
}
}
}
const std::string& LoadingThread::getCurrentTaskName()
{
const static std::string noTask = "No current task";
if(m_currentTask != nullptr)
return m_currentTask->m_name;
else
return noTask;
}
void LoadingThread::loadResourcePack(const std::string& name)
{
std::fstream file;
file.open("data/" + name + ".pack", std::ios_base::in);
ObjectLoader loader;
loader.loadAscii(file);
file.close();
const std::vector<ResourcePack*>& packVec = loader.getObjects<ResourcePack>();
ResourcePack* pack = packVec[0];
m_packs[name] = pack;
for(ResourceInterface* res : pack->m_resources)
{
if((m_references[res->m_name] += 1) == 1)
m_resourceQueue.push_back(res);
else
delete res;
}
}
void LoadingThread::freeResourcePack(const std::string& name)
{
ResourcePack* pack = m_packs[name];
for(ResourceInterface* res : pack->m_resources)
{
if((m_references[res->m_name] -= 1) == 0)
{
m_references.erase(res->m_name);
delete res;
}
}
m_packs.erase(name);
delete pack;
}

44
src/tools/loadingthread.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef LOADINGTHREAD_H
#define LOADINGTHREAD_H
#include <string>
#include <deque>
#include <thread>
#include "resourcepack.h"
class LoadingThread
{
static LoadingThread* singleton;
static std::thread* thread;
std::deque<ResourceInterface*> m_resourceQueue;
std::unordered_map<std::string, ResourcePack*> m_packs;
std::unordered_map<std::string, int> m_references;
ResourceInterface* m_currentTask;
bool m_running;
float m_taskProgress;
int m_nbTaskProcessed;
LoadingThread();
void processTasks();
public:
static LoadingThread *init();
static void destroy();
static void run();
static LoadingThread* get() { return singleton; }
float getTotalProgress() { return float(m_nbTaskProcessed)/float(m_resourceQueue.size() + m_nbTaskProcessed); }
void resetTotalProgress() { m_nbTaskProcessed = 0; }
float getCurrentTaskProgress() { return m_taskProgress; }
const std::string& getCurrentTaskName();
void loadResourcePack(const std::string& name);
// please don't call this if the queue isn't empty
void freeResourcePack(const std::string& name);
};
#endif // LOADINGTHREAD_H

149
src/tools/resourcepack.cpp Normal file
View File

@ -0,0 +1,149 @@
#include "resourcepack.h"
#include "loader.h"
#include "resourcemanager.h"
#include <fstream>
#include <SparrowRenderer/texture.h>
#include <SparrowRenderer/image.h>
#include <SparrowSerializer/serializationmanager.h>
#include <imgui/imgui.h>
INIT_SERIALIZABLE(ResourcePack)
void ResourcePack::gui()
{
static ResourceInterface* currentResource = nullptr;
ImGui::Begin("ResourcePack");
char buf[1024] = {0};
strcpy(buf, m_name.c_str());
if(ImGui::InputText("Pack name", buf, 1024))
m_name = buf;
if(ImGui::Button("Save resource pack"))
{
std::fstream file;
ObjectSaver saver;
saver.addObject(this);
file.open("data/" + m_name + ".pack", std::ios_base::out);
saver.saveAscii(file);
file.close();
}
if(ImGui::Button("Load resource pack"))
{
std::fstream file;
file.open("data/" + m_name + ".pack", std::ios_base::in);
ObjectLoader loader;
loader.loadAscii(file);
file.close();
const std::vector<ResourcePack*>& packVec = loader.getObjects<ResourcePack>();
for(ResourceInterface* res : m_resources)
delete res;
m_resources = packVec[0]->m_resources;
delete packVec[0];
}
if(ImGui::Button("Add a texture"))
{
TextureResource* resource = new TextureResource();
m_resources.push_back(resource);
}
for(ResourceInterface* res : m_resources)
{
if(ImGui::Button(res->m_name.c_str()))
currentResource = res;
}
ImGui::End();
if(currentResource != nullptr)
{
bool opened = true;
ImGui::Begin("Resource Editor", &opened);
char resBuf[1024] = {0};
strcpy(resBuf, currentResource->m_name.c_str());
if(ImGui::InputText("Name (should be unique)", resBuf, 1024))
currentResource->m_name = resBuf;
currentResource->gui();
if(ImGui::Button("Delete resource"))
{
for(unsigned int i=0; i<m_resources.size(); ++i)
{
if(m_resources[i] == currentResource)
{
m_resources.erase(m_resources.begin() + i);
delete currentResource;
currentResource = nullptr;
}
}
}
ImGui::End();
if(!opened)
currentResource = nullptr;
}
}
INIT_SERIALIZABLE(TextureResource)
TextureResource::TextureResource() :
m_texture(nullptr)
{
m_name = "new texture";
m_path = "myTexture.jpg";
m_bitsPerPixel = 24;
m_isVerticallyReversed = true;
m_needsMipMaps = true;
}
TextureResource::~TextureResource()
{
destroy();
}
void TextureResource::load(float & progress)
{
progress = 0;
Image* img = Loader::loadImage(m_path, m_bitsPerPixel, m_isVerticallyReversed);
progress = 0.5;
if(img == nullptr)
return;
m_texture = new Texture(img, m_needsMipMaps);
RESOURCE_ADD(m_texture, Texture, m_name);
delete img;
progress = 1;
}
void TextureResource::destroy()
{
if(m_texture != nullptr)
{
delete m_texture;
m_texture = nullptr;
}
}
void TextureResource::gui()
{
char buf[1024] = {0};
strcpy(buf, m_path.c_str());
if(ImGui::InputText("Image file", buf, 1024))
m_path = buf;
ImGui::InputInt("bits per pixel", &m_bitsPerPixel);
ImGui::Checkbox("is vertically reversed", &m_isVerticallyReversed);
ImGui::Checkbox("needs mipmaps", &m_needsMipMaps);
ImGui::Text(m_texture == nullptr ? "Texture not loaded" : "Texture loaded");
if(ImGui::Button(m_texture == nullptr ? "Load" : "Destroy"))
{
float temp;
if(m_texture == nullptr)
load(temp);
else
destroy();
}
}

63
src/tools/resourcepack.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef RESOURCEPACK_H
#define RESOURCEPACK_H
#include <SparrowSerializer/serializable.h>
class Texture;
/**
* @brief The ResourceInterface struct holds a resource, it handles its loading and its destruction
*/
struct ResourceInterface : public Serializable
{
P_STRING(m_name)
virtual void load(float & progress) = 0;
virtual void destroy() = 0;
virtual void gui() {}
};
/**
* @brief The ResourcePack class is just a container of LoadTask, it only exists for serialization purposes
*/
struct ResourcePack : public Serializable
{
P_STRING(m_name)
P_VECTOR_REFERENCE(ResourceInterface, m_resources)
ResourcePack() {}
void gui();
SERIALIZABLE(ResourcePack, CAST(m_name), CAST(m_resources))
};
//
// Some LoadTask implementations
//
class TextureResource : public ResourceInterface
{
P_STRING(m_path)
P_INT(m_bitsPerPixel)
P_BOOL(m_isVerticallyReversed)
P_BOOL(m_needsMipMaps)
Texture* m_texture;
public:
TextureResource();
virtual ~TextureResource();
SERIALIZABLE(TextureResource, CAST(m_name), CAST(m_path), CAST(m_bitsPerPixel), CAST(m_isVerticallyReversed), CAST(m_needsMipMaps))
void load(float & progress);
void destroy();
void gui();
};
#endif // RESOURCEPACK_H