diff --git a/src/base/log.cpp b/src/base/log.cpp index ffe3ae8a..db005058 100644 --- a/src/base/log.cpp +++ b/src/base/log.cpp @@ -95,7 +95,7 @@ void Log::Helper(MessageType type, char const *fmt, va_list ap) array 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]); diff --git a/src/lolimgui.cpp b/src/lolimgui.cpp index 0f90ed2e..c2adfda2 100644 --- a/src/lolimgui.cpp +++ b/src/lolimgui.cpp @@ -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); diff --git a/src/lolimgui.h b/src/lolimgui.h index 5634834f..fd7b96b1 100644 --- a/src/lolimgui.h +++ b/src/lolimgui.h @@ -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); diff --git a/src/mesh/mesh.cpp b/src/mesh/mesh.cpp index 14894e77..a9a40032 100644 --- a/src/mesh/mesh.cpp +++ b/src/mesh/mesh.cpp @@ -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() diff --git a/src/mesh/primitive.cpp b/src/mesh/primitive.cpp index 91b219cd..6119ce08 100644 --- a/src/mesh/primitive.cpp +++ b/src/mesh/primitive.cpp @@ -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 */ diff --git a/src/mesh/primitive.h b/src/mesh/primitive.h index 6f1f5834..34a26a3e 100644 --- a/src/mesh/primitive.h +++ b/src/mesh/primitive.h @@ -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; diff --git a/src/scene.cpp b/src/scene.cpp index 75c6b0a9..fc8f7f7f 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -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 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 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 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); } } } diff --git a/src/scene.h b/src/scene.h index 9a2f7b7f..ec39d3a8 100644 --- a/src/scene.h +++ b/src/scene.h @@ -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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 */ diff --git a/src/ticker.cpp b/src/ticker.cpp index 293ea01e..f6d4885a 100644 --- a/src/ticker.cpp +++ b/src/ticker.cpp @@ -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);