@@ -95,7 +95,7 @@ void Log::Helper(MessageType type, char const *fmt, va_list ap) | |||
array<WCHAR> widechar; | |||
widechar.Resize(buf.Count() + 1); | |||
MultiByteToWideChar(CP_UTF8, 0, buf.C(), (int)buf.Count() + 1, widechar.Data(), widechar.Count()); | |||
MultiByteToWideChar(CP_UTF8, 0, buf.C(), (int)buf.Count() + 1, widechar.Data(), (int)widechar.Count()); | |||
OutputDebugStringW(widechar.Data()); | |||
# else | |||
fprintf(stderr, "%s: ", prefix[type]); | |||
@@ -259,9 +259,9 @@ void LolImGui::TickDraw(float seconds, Scene &scene) | |||
{ | |||
super::TickDraw(seconds, scene); | |||
scene.AddPrimitive(new PrimitiveLolImGui()); | |||
scene.AddPrimitiveRenderer(this, new PrimitiveLolImGui()); | |||
} | |||
void PrimitiveLolImGui::Render() const | |||
void PrimitiveLolImGui::Render(Scene& scene, PrimitiveSource* primitive) | |||
{ | |||
g_renderer->Clear(ClearMask::Depth); | |||
@@ -174,11 +174,11 @@ protected: | |||
}; | |||
//----------------------------------------------------------------------------- | |||
class PrimitiveLolImGui : public PrimitiveSource | |||
class PrimitiveLolImGui : public PrimitiveRenderer | |||
{ | |||
public: | |||
PrimitiveLolImGui() { } | |||
virtual void Render() const; | |||
virtual void Render(Scene& scene, PrimitiveSource* primitive); | |||
}; | |||
//bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks); | |||
@@ -30,8 +30,11 @@ Mesh::~Mesh() | |||
void Mesh::Render(Scene& scene, mat4 const &matrix) | |||
{ | |||
for (int i = 0; i < m_submeshes.Count(); ++i) | |||
scene.AddPrimitive(new PrimitiveMesh(m_submeshes[i], matrix)); | |||
//if (scene.HasPrimitiveRenderer(this) < m_submeshes.Count()) | |||
{ | |||
for (int i = 0; i < m_submeshes.Count(); ++i) | |||
scene.AddPrimitiveRenderer(this, new PrimitiveMesh(m_submeshes[i], matrix)); | |||
} | |||
} | |||
void Mesh::Render() | |||
@@ -30,7 +30,7 @@ PrimitiveMesh::~PrimitiveMesh() | |||
{ | |||
} | |||
void PrimitiveMesh::Render(Scene& scene) | |||
void PrimitiveMesh::Render(Scene& scene, PrimitiveSource* primitive) | |||
{ | |||
/* TODO: this should be the main entry for rendering of all | |||
* primitives found in the scene graph. When we have one. */ | |||
@@ -53,10 +53,10 @@ void PrimitiveMesh::Render(Scene& scene) | |||
/* Per-scene matrices */ | |||
ShaderUniform u_mat; | |||
u_mat = shader->GetUniformLocation("u_projection"); | |||
u_mat = shader->GetUniformLocation("u_view"); | |||
u_mat = shader->GetUniformLocation("u_inv_view"); | |||
shader->SetUniform(u_mat, scene.GetCamera()->GetProjection()); | |||
u_mat = shader->GetUniformLocation("u_view"); | |||
shader->SetUniform(u_mat, scene.GetCamera()->GetView()); | |||
u_mat = shader->GetUniformLocation("u_inv_view"); | |||
shader->SetUniform(u_mat, inverse(scene.GetCamera()->GetView())); | |||
/* Per-object matrices, will be set later */ | |||
@@ -18,14 +18,14 @@ | |||
namespace lol | |||
{ | |||
class PrimitiveMesh : public PrimitiveSource | |||
class PrimitiveMesh : public PrimitiveRenderer | |||
{ | |||
friend class Scene; | |||
public: | |||
PrimitiveMesh(SubMesh *submesh, mat4 const &matrix); | |||
virtual ~PrimitiveMesh(); | |||
virtual void Render(Scene& scene); | |||
virtual void Render(Scene& scene, PrimitiveSource* primitive); | |||
private: | |||
SubMesh *m_submesh; | |||
@@ -46,6 +46,16 @@ struct Tile | |||
int id, o; | |||
}; | |||
/* | |||
* Scene implementation class | |||
*/ | |||
void PrimitiveSource::Render(Scene& scene) { UNUSED(scene); } | |||
void PrimitiveRenderer::Render(Scene& scene, PrimitiveSource* primitive) | |||
{ | |||
UNUSED(scene); | |||
UNUSED(primitive); | |||
} | |||
/* | |||
* Scene implementation class | |||
*/ | |||
@@ -249,6 +259,15 @@ void Scene::Reset() | |||
{ | |||
ASSERT(!!data, "Trying to access a non-ready scene"); | |||
/* New scenegraph: Release fire&forget primitives */ | |||
array<uintptr_t> keys = data->m_prim_renderers.keys(); | |||
for (uintptr_t key : keys) | |||
{ | |||
for (ptrdiff_t idx = 0; idx < data->m_prim_renderers[key].count(); ++idx) | |||
if (data->m_prim_renderers[key][idx]->m_fire_and_forget) | |||
ReleasePrimitiveRenderer(idx--, key); | |||
} | |||
for (int i = 0; i < data->m_tile_bufs.Count(); i++) | |||
delete data->m_tile_bufs[i]; | |||
data->m_tile_bufs.Empty(); | |||
@@ -267,71 +286,68 @@ void Scene::AddPrimitive(PrimitiveSource* primitive) | |||
} | |||
//---- Primitive source stuff ------------------------------------------------- | |||
#define _ENT_IDX (uintptr_t)entity /* TOUKY: I don't like that. hash should be fixed to handle these custom stuff */ | |||
//---- Primitive source stuff ------------------------------------------------- | |||
ptrdiff_t Scene::HasPrimitiveSource(Entity* entity) | |||
ptrdiff_t Scene::HasPrimitiveSource(uintptr_t key) | |||
{ | |||
ASSERT(entity); | |||
ptrdiff_t count; | |||
SceneData::m_prim_mutex.lock(); | |||
{ | |||
count = SceneData::m_prim_sources[_ENT_IDX].count(); | |||
count = SceneData::m_prim_sources[key].count(); | |||
} | |||
SceneData::m_prim_mutex.unlock(); | |||
return count; | |||
} | |||
ptrdiff_t Scene::AddPrimitiveSource(Entity* entity, PrimitiveSource* source) | |||
ptrdiff_t Scene::AddPrimitiveSource(uintptr_t key, PrimitiveSource* source) | |||
{ | |||
ASSERT(entity); | |||
ptrdiff_t count; | |||
SceneData::m_prim_mutex.lock(); | |||
{ | |||
count = SceneData::m_prim_sources[_ENT_IDX].count(); | |||
SceneData::m_prim_sources[_ENT_IDX].push(source); | |||
count = SceneData::m_prim_sources[key].count(); | |||
SceneData::m_prim_sources[key].push(source); | |||
} | |||
SceneData::m_prim_mutex.unlock(); | |||
return count; | |||
} | |||
void Scene::SetPrimitiveSource(ptrdiff_t index, Entity* entity, PrimitiveSource* source) | |||
void Scene::SetPrimitiveSource(ptrdiff_t index, uintptr_t key, PrimitiveSource* source) | |||
{ | |||
ASSERT(entity); | |||
ASSERT(source); | |||
ASSERT(index < 0); | |||
PrimitiveSource* old = nullptr; | |||
SceneData::m_prim_mutex.lock(); | |||
{ | |||
ASSERT(0 <= index && index < SceneData::m_prim_sources[_ENT_IDX].count()); | |||
old = SceneData::m_prim_sources[_ENT_IDX][index]; | |||
SceneData::m_prim_sources[_ENT_IDX][index] = source; | |||
if (index < SceneData::m_prim_sources[key].count()) | |||
old = SceneData::m_prim_sources[key][index]; | |||
else | |||
SceneData::m_prim_sources[key].resize(index + 1); | |||
SceneData::m_prim_sources[key][index] = source; | |||
} | |||
SceneData::m_prim_mutex.unlock(); | |||
//Delete old AFTER having released the lock | |||
if (old) delete old; | |||
} | |||
void Scene::ReleasePrimitiveSource(ptrdiff_t index, Entity* entity) | |||
void Scene::ReleasePrimitiveSource(ptrdiff_t index, uintptr_t key) | |||
{ | |||
ASSERT(entity); | |||
PrimitiveSource* old = nullptr; | |||
SceneData::m_prim_mutex.lock(); | |||
{ | |||
ASSERT(0 <= index && index < SceneData::m_prim_sources[_ENT_IDX].count()); | |||
old = SceneData::m_prim_sources[_ENT_IDX][index]; | |||
SceneData::m_prim_sources[_ENT_IDX].remove(index); | |||
ASSERT(0 <= index && index < SceneData::m_prim_sources[key].count()); | |||
old = SceneData::m_prim_sources[key][index]; | |||
SceneData::m_prim_sources[key].remove(index); | |||
} | |||
SceneData::m_prim_mutex.unlock(); | |||
//Delete old AFTER having released the lock | |||
if (old) delete old; | |||
} | |||
void Scene::ReleaseAllPrimitiveSource(Entity* entity) | |||
void Scene::ReleaseAllPrimitiveSource(uintptr_t key) | |||
{ | |||
ASSERT(entity); | |||
array<PrimitiveSource*> oldies; | |||
SceneData::m_prim_mutex.lock(); | |||
{ | |||
oldies.reserve(SceneData::m_prim_sources[_ENT_IDX].count()); | |||
for (PrimitiveSource* source : SceneData::m_prim_sources[_ENT_IDX]) | |||
oldies.reserve(SceneData::m_prim_sources[key].count()); | |||
for (PrimitiveSource* source : SceneData::m_prim_sources[key]) | |||
oldies << source; | |||
SceneData::m_prim_sources[_ENT_IDX].empty(); | |||
SceneData::m_prim_sources[key].empty(); | |||
} | |||
SceneData::m_prim_mutex.unlock(); | |||
@@ -341,45 +357,43 @@ void Scene::ReleaseAllPrimitiveSource(Entity* entity) | |||
} | |||
//---- Primitive renderer stuff ----------------------------------------------- | |||
ptrdiff_t Scene::HasPrimitiveRenderer(Entity* entity) | |||
ptrdiff_t Scene::HasPrimitiveRenderer(uintptr_t key) | |||
{ | |||
ASSERT(entity); | |||
return data->m_prim_renderers[_ENT_IDX].count(); | |||
return data->m_prim_renderers[key].count(); | |||
} | |||
ptrdiff_t Scene::AddPrimitiveRenderer(Entity* entity, PrimitiveRenderer* renderer) | |||
void Scene::AddPrimitiveRenderer(uintptr_t key, PrimitiveRenderer* renderer) | |||
{ | |||
ASSERT(entity); | |||
data->m_prim_renderers[_ENT_IDX].push(renderer); | |||
return data->m_prim_renderers[_ENT_IDX].count() - 1; | |||
renderer->m_fire_and_forget = true; | |||
data->m_prim_renderers[key].push(renderer); | |||
} | |||
void Scene::SetPrimitiveRenderer(ptrdiff_t index, Entity* entity, PrimitiveRenderer* renderer) | |||
void Scene::SetPrimitiveRenderer(ptrdiff_t index, uintptr_t key, PrimitiveRenderer* renderer) | |||
{ | |||
ASSERT(entity && renderer); | |||
ASSERT(0 <= index && index < data->m_prim_renderers[_ENT_IDX].count()); | |||
ASSERT(data->m_prim_renderers[_ENT_IDX][index]); | |||
delete data->m_prim_renderers[_ENT_IDX][index]; | |||
data->m_prim_renderers[_ENT_IDX][index] = renderer; | |||
ASSERT(renderer); | |||
ASSERT(index < 0); | |||
if (index < data->m_prim_renderers[key].count()) | |||
{ | |||
ASSERT(data->m_prim_renderers[key][index]); | |||
delete data->m_prim_renderers[key][index]; | |||
} | |||
else | |||
data->m_prim_renderers[key].resize(index + 1); | |||
data->m_prim_renderers[key][index] = renderer; | |||
} | |||
void Scene::ReleasePrimitiveRenderer(ptrdiff_t index, Entity* entity) | |||
void Scene::ReleasePrimitiveRenderer(ptrdiff_t index, uintptr_t key) | |||
{ | |||
ASSERT(entity); | |||
ASSERT(0 <= index && index < data->m_prim_renderers[_ENT_IDX].count()); | |||
ASSERT(data->m_prim_renderers[_ENT_IDX][index]); | |||
delete data->m_prim_renderers[_ENT_IDX][index]; | |||
data->m_prim_renderers[_ENT_IDX].remove(index); | |||
ASSERT(0 <= index && index < data->m_prim_renderers[key].count()); | |||
ASSERT(data->m_prim_renderers[key][index]); | |||
delete data->m_prim_renderers[key][index]; | |||
data->m_prim_renderers[key].remove(index); | |||
} | |||
void Scene::ReleaseAllPrimitiveRenderer(Entity* entity) | |||
void Scene::ReleaseAllPrimitiveRenderer(uintptr_t key) | |||
{ | |||
ASSERT(entity); | |||
for (PrimitiveRenderer* renderer : data->m_prim_renderers[_ENT_IDX]) | |||
for (PrimitiveRenderer* renderer : data->m_prim_renderers[key]) | |||
{ | |||
ASSERT(renderer); | |||
delete renderer; | |||
} | |||
} | |||
//---- Primitive source stuff ------------------------------------------------- | |||
#undef _ENT_IDX //(uintptr_t)entity /* TOUKY: I don't like that. hash should be fixed to handle these custom stuff */ | |||
//---- Primitive source stuff ------------------------------------------------- | |||
//----------------------------------------------------------------------------- | |||
void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale, float angle) | |||
@@ -478,6 +492,7 @@ void Scene::RenderPrimitives() | |||
{ | |||
p->Render(*this); | |||
} | |||
/* new scenegraph */ | |||
array<uintptr_t> keys = data->m_prim_renderers.keys(); | |||
for (uintptr_t key : keys) | |||
@@ -485,7 +500,7 @@ void Scene::RenderPrimitives() | |||
for (ptrdiff_t idx = 0; idx < data->m_prim_renderers[key].count(); ++idx) | |||
{ | |||
/* TODO: Not sure if thread compliant */ | |||
data->m_prim_renderers[key][idx]->Render(idx < SceneData::m_prim_sources[key].count() ? SceneData::m_prim_sources[key][idx] : nullptr); | |||
data->m_prim_renderers[key][idx]->Render(*this, idx < SceneData::m_prim_sources[key].count() ? SceneData::m_prim_sources[key][idx] : nullptr); | |||
} | |||
} | |||
} | |||
@@ -37,7 +37,7 @@ class PrimitiveSource | |||
public: | |||
PrimitiveSource() { } | |||
virtual ~PrimitiveSource() { } | |||
virtual void Render(Scene& scene) { } | |||
virtual void Render(Scene& scene); | |||
private: | |||
}; | |||
@@ -49,13 +49,12 @@ class PrimitiveRenderer | |||
public: | |||
PrimitiveRenderer() { } | |||
virtual ~PrimitiveRenderer() { } | |||
virtual void Render(PrimitiveSource* primitive) const { UNUSED(primitive); } | |||
virtual void Render(Scene& scene, PrimitiveSource* primitive); | |||
private: | |||
bool m_fire_and_forget = false; | |||
}; | |||
//----------------------------------------------------------------------------- | |||
//----------------------------------------------------------------------------- | |||
class Scene | |||
{ | |||
@@ -92,38 +91,108 @@ public: | |||
void Reset(); | |||
/* New scenegraph */ | |||
void AddPrimitive(PrimitiveSource* primitive); | |||
void AddPrimitive(class PrimitiveSource* primitive); | |||
/* ============================== */ | |||
# define _KEY_IDX (uintptr_t)key /* TOUKY: I don't like that. hash should be fixed to handle these custom stuff */ | |||
/* ============================== */ | |||
private: | |||
ptrdiff_t HasPrimitiveSource(uintptr_t key); | |||
ptrdiff_t AddPrimitiveSource(uintptr_t key, class PrimitiveSource* source); | |||
void SetPrimitiveSource(ptrdiff_t index, uintptr_t key, class PrimitiveSource* source); | |||
void ReleasePrimitiveSource(ptrdiff_t index, uintptr_t key); | |||
void ReleaseAllPrimitiveSource(uintptr_t key); | |||
public: | |||
/* === Primitive source stuff === */ | |||
/* Returns the number of primitive source set to the given entity */ | |||
ptrdiff_t HasPrimitiveSource(Entity* entity); | |||
template <typename T> | |||
ptrdiff_t HasPrimitiveSource(T* key) | |||
{ | |||
ASSERT(key); | |||
return HasPrimitiveSource(_KEY_IDX); | |||
} | |||
/* Add a primitive sources linked to the given entity | |||
* Returns the slot number */ | |||
ptrdiff_t AddPrimitiveSource(Entity* entity, PrimitiveSource* source); | |||
template <typename T> | |||
ptrdiff_t AddPrimitiveSource(T* key, class PrimitiveSource* source) | |||
{ | |||
ASSERT(key); | |||
return AddPrimitiveSource(_KEY_IDX, source); | |||
} | |||
/* Update the primitive source at index linked to the given entity | |||
* Deletes the old one | |||
* The slot is kept even if source == nullptr */ | |||
void SetPrimitiveSource(ptrdiff_t index, Entity* entity, PrimitiveSource* source); | |||
template <typename T> | |||
void SetPrimitiveSource(ptrdiff_t index, T* key, class PrimitiveSource* source) | |||
{ | |||
ASSERT(key); | |||
SetPrimitiveSource(index, _KEY_IDX, source); | |||
} | |||
/* Remove primitive source at index set to the given entity */ | |||
void ReleasePrimitiveSource(ptrdiff_t index, Entity* entity); | |||
template <typename T> | |||
void ReleasePrimitiveSource(ptrdiff_t index, T* key) | |||
{ | |||
ASSERT(key); | |||
ReleasePrimitiveSource(index, _KEY_IDX); | |||
} | |||
/* Remove all primitive source set to the given entity */ | |||
void ReleaseAllPrimitiveSource(Entity* entity); | |||
template <typename T> | |||
void ReleaseAllPrimitiveSource(T* key) | |||
{ | |||
ASSERT(key); | |||
ReleaseAllPrimitiveSource(_KEY_IDX); | |||
} | |||
private: | |||
ptrdiff_t HasPrimitiveRenderer(uintptr_t key); | |||
void AddPrimitiveRenderer(uintptr_t key, class PrimitiveRenderer* renderer); | |||
void SetPrimitiveRenderer(ptrdiff_t index, uintptr_t key, class PrimitiveRenderer* renderer); | |||
void ReleasePrimitiveRenderer(ptrdiff_t index, uintptr_t key); | |||
void ReleaseAllPrimitiveRenderer(uintptr_t key); | |||
public: | |||
/* === Primitive renderer stuff === */ | |||
/* Returns the number of primitive renderer set to the given entity */ | |||
ptrdiff_t HasPrimitiveRenderer(Entity* entity); | |||
template <typename T> | |||
ptrdiff_t HasPrimitiveRenderer(T* key) | |||
{ | |||
ASSERT(key); | |||
return HasPrimitiveRenderer(_KEY_IDX); | |||
} | |||
/* Add a primitive renderer linked to the given entity | |||
* Returns the slot number */ | |||
ptrdiff_t AddPrimitiveRenderer(Entity* entity, PrimitiveRenderer* renderer); | |||
* The primitive is considered as Fire&Forget and | |||
* will be destroyed at the end of the frame */ | |||
template <typename T> | |||
void AddPrimitiveRenderer(T* key, class PrimitiveRenderer* renderer) | |||
{ | |||
ASSERT(key); | |||
AddPrimitiveRenderer(_KEY_IDX, renderer); | |||
} | |||
/* Update the primitive renderer linked to the given entity | |||
* Deletes the old one | |||
* Will assert if renderer == nullptr */ | |||
void SetPrimitiveRenderer(ptrdiff_t index, Entity* entity, PrimitiveRenderer* renderer); | |||
template <typename T> | |||
void SetPrimitiveRenderer(ptrdiff_t index, T* key, class PrimitiveRenderer* renderer) | |||
{ | |||
ASSERT(key && renderer); | |||
SetPrimitiveRenderer(index, _KEY_IDX, renderer); | |||
} | |||
/* Remove primitive renderer at index set to the given entity */ | |||
void ReleasePrimitiveRenderer(ptrdiff_t index, Entity* entity); | |||
template <typename T> | |||
void ReleasePrimitiveRenderer(ptrdiff_t index, T* key) | |||
{ | |||
ASSERT(key); | |||
ReleasePrimitiveRenderer(index, _KEY_IDX); | |||
} | |||
/* Remove all primitive renderer set to the given entity */ | |||
void ReleaseAllPrimitiveRenderer(Entity* entity); | |||
template <typename T> | |||
void ReleaseAllPrimitiveRenderer(T* key) | |||
{ | |||
ASSERT(key); | |||
ReleaseAllPrimitiveRenderer(_KEY_IDX); | |||
} | |||
/* ============================== */ | |||
# undef _KEY_IDX /* (uintptr_t)key *//* TOUKY: I don't like that. hash should be fixed to handle these custom stuff */ | |||
/* ============================== */ | |||
/* FIXME: this should be deprecated -- it doesn't really match | |||
* the architecture we want to build */ | |||
@@ -464,7 +464,7 @@ void TickerData::DrawThreadTick() | |||
} | |||
//Do the scene render loop | |||
for (ptrdiff_t idx = 0; idx < Scene::GetCount(); ++idx) | |||
for (ptrdiff_t idx = 0; idx < Scene::GetCount() && !data->quit /* Stop as soon as required */; ++idx) | |||
{ | |||
Scene& scene = Scene::GetScene(idx); | |||