From 819b3ad27f3e93889e393e7c6921850207b08e30 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 25 Jul 2022 09:41:35 +0800 Subject: [PATCH] Add minimap rendering --- lib/graphics_engine/include/ge_main.hpp | 1 + lib/graphics_engine/include/ge_spm.hpp | 2 + lib/graphics_engine/include/ge_spm_buffer.hpp | 3 + .../src/ge_vulkan_mesh_scene_node.cpp | 9 +++ .../src/ge_vulkan_mesh_scene_node.hpp | 6 ++ .../src/ge_vulkan_scene_manager.cpp | 66 +++++++++++++++++-- src/tracks/graph.cpp | 39 ++++++++--- 7 files changed, 113 insertions(+), 13 deletions(-) diff --git a/lib/graphics_engine/include/ge_main.hpp b/lib/graphics_engine/include/ge_main.hpp index 4963c45ab..5234e6275 100644 --- a/lib/graphics_engine/include/ge_main.hpp +++ b/lib/graphics_engine/include/ge_main.hpp @@ -12,6 +12,7 @@ class GEVulkanDriver; struct GEConfig { bool m_disable_npot_texture; +bool m_convert_irrlicht_mesh; }; void setVideoDriver(irr::video::IVideoDriver* driver); diff --git a/lib/graphics_engine/include/ge_spm.hpp b/lib/graphics_engine/include/ge_spm.hpp index 51b3161f8..dcb0098ea 100644 --- a/lib/graphics_engine/include/ge_spm.hpp +++ b/lib/graphics_engine/include/ge_spm.hpp @@ -15,9 +15,11 @@ class SPMeshLoader; namespace GE { class GESPMBuffer; +class GEVulkanSceneManager; class GESPM : public IAnimatedMesh { +friend class GEVulkanSceneManager; friend class ::B3DMeshLoader; friend class ::SPMeshLoader; private: diff --git a/lib/graphics_engine/include/ge_spm_buffer.hpp b/lib/graphics_engine/include/ge_spm_buffer.hpp index d988c11bb..8f7e44b75 100644 --- a/lib/graphics_engine/include/ge_spm_buffer.hpp +++ b/lib/graphics_engine/include/ge_spm_buffer.hpp @@ -10,8 +10,11 @@ class SPMeshLoader; namespace GE { +class GEVulkanSceneManager; + class GESPMBuffer : public irr::scene::IMeshBuffer { +friend class GEVulkanSceneManager; friend class ::B3DMeshLoader; friend class ::SPMeshLoader; private: diff --git a/lib/graphics_engine/src/ge_vulkan_mesh_scene_node.cpp b/lib/graphics_engine/src/ge_vulkan_mesh_scene_node.cpp index 03f8fc73d..ce610ff9c 100644 --- a/lib/graphics_engine/src/ge_vulkan_mesh_scene_node.cpp +++ b/lib/graphics_engine/src/ge_vulkan_mesh_scene_node.cpp @@ -2,6 +2,7 @@ #include "ge_spm.hpp" +#include "IMeshCache.h" #include "ISceneManager.h" namespace GE @@ -14,8 +15,16 @@ GEVulkanMeshSceneNode::GEVulkanMeshSceneNode(irr::scene::IMesh* mesh, : irr::scene::CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale) { + m_remove_from_mesh_cache = false; } // GEVulkanMeshSceneNode +// ---------------------------------------------------------------------------- +GEVulkanMeshSceneNode::~GEVulkanMeshSceneNode() +{ + if (m_remove_from_mesh_cache) + SceneManager->getMeshCache()->removeMesh(Mesh); +} // ~GEVulkanMeshSceneNode + // ---------------------------------------------------------------------------- GESPM* GEVulkanMeshSceneNode::getSPM() const { diff --git a/lib/graphics_engine/src/ge_vulkan_mesh_scene_node.hpp b/lib/graphics_engine/src/ge_vulkan_mesh_scene_node.hpp index 8049813a5..e771a3778 100644 --- a/lib/graphics_engine/src/ge_vulkan_mesh_scene_node.hpp +++ b/lib/graphics_engine/src/ge_vulkan_mesh_scene_node.hpp @@ -9,6 +9,8 @@ class GESPM; class GEVulkanMeshSceneNode : public irr::scene::CMeshSceneNode { +private: + bool m_remove_from_mesh_cache; public: // ------------------------------------------------------------------------ GEVulkanMeshSceneNode(irr::scene::IMesh* mesh, @@ -17,6 +19,10 @@ public: const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0), const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f)); // ------------------------------------------------------------------------ + ~GEVulkanMeshSceneNode(); + // ------------------------------------------------------------------------ + void setRemoveFromMeshCache(bool val) { m_remove_from_mesh_cache = val; } + // ------------------------------------------------------------------------ GESPM* getSPM() const; // ------------------------------------------------------------------------ virtual void OnRegisterSceneNode(); diff --git a/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp b/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp index 38adc3eed..3a3f4b066 100644 --- a/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp +++ b/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp @@ -2,7 +2,9 @@ #include "../source/Irrlicht/os.h" +#include "ge_main.hpp" #include "ge_spm.hpp" +#include "ge_spm_buffer.hpp" #include "ge_vulkan_animated_mesh_scene_node.hpp" #include "ge_vulkan_camera_scene_node.hpp" #include "ge_vulkan_command_loader.hpp" @@ -13,6 +15,9 @@ #include "ge_vulkan_mesh_scene_node.hpp" #include "ge_vulkan_texture_descriptor.hpp" +#include "mini_glm.hpp" +#include + namespace GE { // ---------------------------------------------------------------------------- @@ -95,6 +100,7 @@ irr::scene::IMeshSceneNode* GEVulkanSceneManager::addMeshSceneNode( if (!alsoAddIfMeshPointerZero && !mesh) return NULL; + bool convert_irrlicht_mesh = false; if (mesh) { for (unsigned i = 0; i < mesh->getMeshBufferCount(); i++) @@ -102,9 +108,17 @@ irr::scene::IMeshSceneNode* GEVulkanSceneManager::addMeshSceneNode( irr::scene::IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexType() != irr::video::EVT_SKINNED_MESH) { - return irr::scene::CSceneManager::addMeshSceneNode( - mesh, parent, id, position, rotation, scale, - alsoAddIfMeshPointerZero); + if (!getGEConfig()->m_convert_irrlicht_mesh) + { + return irr::scene::CSceneManager::addMeshSceneNode( + mesh, parent, id, position, rotation, scale, + alsoAddIfMeshPointerZero); + } + else + { + convert_irrlicht_mesh = true; + break; + } } } } @@ -112,10 +126,54 @@ irr::scene::IMeshSceneNode* GEVulkanSceneManager::addMeshSceneNode( if (!parent) parent = this; - irr::scene::IMeshSceneNode* node = + if (convert_irrlicht_mesh) + { + GESPM* spm = new GESPM(); + for (unsigned i = 0; i < mesh->getMeshBufferCount(); i++) + { + std::vector vertices; + scene::IMeshBuffer* mb = mesh->getMeshBuffer(i); + if (!mb) + continue; + + GESPMBuffer* spm_mb = new GESPMBuffer(); + assert(mb->getVertexType() == video::EVT_STANDARD); + video::S3DVertex* v_ptr = (video::S3DVertex*)mb->getVertices(); + for (unsigned j = 0; j < mb->getVertexCount(); j++) + { + video::S3DVertexSkinnedMesh sp; + sp.m_position = v_ptr[j].Pos; + sp.m_normal = MiniGLM::compressVector3(v_ptr[j].Normal); + sp.m_color = v_ptr[j].Color; + sp.m_all_uvs[0] = MiniGLM::toFloat16(v_ptr[j].TCoords.X); + sp.m_all_uvs[1] = MiniGLM::toFloat16(v_ptr[j].TCoords.Y); + spm_mb->m_vertices.push_back(sp); + } + uint16_t* idx_ptr = mb->getIndices(); + std::vector indices(idx_ptr, idx_ptr + mb->getIndexCount()); + std::swap(spm_mb->m_indices, indices); + spm_mb->m_material = mb->getMaterial(); + spm_mb->recalculateBoundingBox(); + spm->m_buffer.push_back(spm_mb); + } + spm->finalize(); + std::stringstream oss; + oss << (uint64_t)spm; + getMeshCache()->addMesh(oss.str().c_str(), spm); + mesh = spm; + } + + GEVulkanMeshSceneNode* vulkan_node = new GEVulkanMeshSceneNode(mesh, parent, this, id, position, rotation, scale); + irr::scene::IMeshSceneNode* node = vulkan_node; node->drop(); + + if (convert_irrlicht_mesh) + { + vulkan_node->setRemoveFromMeshCache(true); + mesh->drop(); + } return node; } // addMeshSceneNode diff --git a/src/tracks/graph.cpp b/src/tracks/graph.cpp index 4f44aaa48..b6977a16b 100644 --- a/src/tracks/graph.cpp +++ b/src/tracks/graph.cpp @@ -100,7 +100,17 @@ void Graph::createDebugMesh() } #endif +#ifndef SERVER_ONLY + bool vk = (GE::getVKDriver() != NULL); + if (vk) + GE::getGEConfig()->m_convert_irrlicht_mesh = true; +#endif m_node = irr_driver->addMesh(m_mesh, "track-debug-mesh"); +#ifndef SERVER_ONLY + if (vk) + GE::getGEConfig()->m_convert_irrlicht_mesh = false; +#endif + #ifdef DEBUG m_node->setName("track-debug-mesh"); #endif @@ -192,10 +202,11 @@ void Graph::createMesh(bool show_invisible, bool enable_transparency, } if (flatten) { - vptr[0].Pos.Y = 0; - vptr[1].Pos.Y = 0; - vptr[2].Pos.Y = 0; - vptr[3].Pos.Y = 0; + // Vulkan driver needs 0.1 instead of 0 + vptr[0].Pos.Y = 0.1f; + vptr[1].Pos.Y = 0.1f; + vptr[2].Pos.Y = 0.1f; + vptr[3].Pos.Y = 0.1f; } // Set up the indices for the triangles @@ -220,10 +231,10 @@ void Graph::createMesh(bool show_invisible, bool enable_transparency, m_all_nodes[0]->getVertices(lap_v, lap_color); if (flatten) { - lap_v[0].Pos.Y = 0; - lap_v[1].Pos.Y = 0; - lap_v[2].Pos.Y = 0; - lap_v[3].Pos.Y = 0; + lap_v[0].Pos.Y = 0.1f; + lap_v[1].Pos.Y = 0.1f; + lap_v[2].Pos.Y = 0.1f; + lap_v[3].Pos.Y = 0.1f; } // Now scale the length (distance between vertix 0 and 3 @@ -417,7 +428,7 @@ RenderTarget* Graph::makeMiniMap(const core::dimension2du &dimension, #ifdef SERVER_ONLY return NULL; #else - if (GUIEngine::isNoGraphics() || GE::getVKDriver()) return NULL; + if (GUIEngine::isNoGraphics()) return NULL; #endif const video::SColor oldClearColor = irr_driver->getClearColor(); @@ -471,7 +482,17 @@ RenderTarget* Graph::makeMiniMap(const core::dimension2du &dimension, } #endif +#ifndef SERVER_ONLY + bool vk = (GE::getVKDriver() != NULL); + if (vk) + GE::getGEConfig()->m_convert_irrlicht_mesh = true; +#endif m_node = irr_driver->addMesh(m_mesh, "mini_map"); +#ifndef SERVER_ONLY + if (vk) + GE::getGEConfig()->m_convert_irrlicht_mesh = false; +#endif + #ifdef DEBUG m_node->setName("minimap-mesh"); #endif