From a2281009a2c8ab1f9f2e54c16c50589a36a08307 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Thu, 12 Sep 2019 19:53:24 +0100 Subject: [PATCH] Using pool and vector wrapper for planes to prevent allocations --- SCsub | 1 + lplanes_pool.cpp | 47 +++++++++++++++++++ lplanes_pool.h | 23 ++++++++++ lportal.cpp | 18 +++++++- lportal.h | 3 +- lroom.cpp | 37 +++++++++++---- lroom.h | 4 +- lroom_manager.cpp | 13 ++++-- lroom_manager.h | 11 ++++- lvector.h | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 251 insertions(+), 19 deletions(-) create mode 100644 lplanes_pool.cpp create mode 100644 lplanes_pool.h create mode 100644 lvector.h diff --git a/SCsub b/SCsub index 6785a19..b8f8f4e 100644 --- a/SCsub +++ b/SCsub @@ -6,6 +6,7 @@ sources = [ "lroom.cpp", "lroom_manager.cpp", "lportal.cpp", + "lplanes_pool.cpp", "CoBitField_Dynamic.cpp", ] diff --git a/lplanes_pool.cpp b/lplanes_pool.cpp new file mode 100644 index 0000000..66b4032 --- /dev/null +++ b/lplanes_pool.cpp @@ -0,0 +1,47 @@ +#include "lplanes_pool.h" + +LPlanesPool::LPlanesPool() +{ + Reset(); + + // preallocate the vectors to a reasonable size + for (int n=0; n= POOL_MAX) + return -1; + + for (unsigned int n=0; n &Get(unsigned int ui) {return m_Planes[ui];} + + LPlanesPool(); +private: + LVector m_Planes[ POOL_MAX]; + unsigned char m_ucTaken[POOL_MAX]; + unsigned int m_uiCount; +}; diff --git a/lportal.cpp b/lportal.cpp index 566d89c..97e95f8 100644 --- a/lportal.cpp +++ b/lportal.cpp @@ -61,21 +61,32 @@ String LPortal::FindNameAfter(Node * pNode, String szStart) ////////////////////////////////////////////////////////// // add clipping planes to the vector formed by each portal edge and the camera -void LPortal::AddPlanes(const Vector3 &ptCam, Vector &planes) const +void LPortal::AddPlanes(const Vector3 &ptCam, LVector &planes) const { // short version const Vector &pts = m_ptsWorld; int nPoints = pts.size(); -// ERR_FAIL_COND(nPoints < 3); + ERR_FAIL_COND(nPoints < 3); Plane p; for (int n=1; n &planes) const; + void AddPlanes(const Vector3 &ptCam, LVector &planes) const; public: // normal determined by winding order diff --git a/lroom.cpp b/lroom.cpp index 721f7e9..e9c39cd 100644 --- a/lroom.cpp +++ b/lroom.cpp @@ -23,17 +23,19 @@ #include "scene/3d/mesh_instance.h" #include "lportal.h" #include "CoBitField_Dynamic.h" +#include "lroom_manager.h" void LRoom::print(String sz) { // print_line(sz); + LPortal::print(sz); } LRoom::LRoom() { m_LocalRoomID = -1; } -void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const Vector &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from) +void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from) { // prevent too much depth if (depth >= 8) @@ -60,7 +62,7 @@ void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const V VisualInstance * pObj = Object::cast_to(pNode); if (pObj) { - Vector3 pt = pObj->get_global_transform().origin; + //Vector3 pt = pObj->get_global_transform().origin; bool bShow = true; @@ -102,7 +104,7 @@ void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const V // go through each portal out of here int nPortals = m_portal_IDs.size(); - ObjectID this_room_id = get_instance_id(); +// ObjectID this_room_id = get_instance_id(); for (int p=0; p new_planes = planes; + unsigned int uiPoolMem = manager.m_Pool.Request(); + if (uiPoolMem != -1) + { + // get a vector of planes from the pool + LVector &new_planes = manager.m_Pool.Get(uiPoolMem); - // add the planes for the portal - pPortal->AddPlanes(cam.m_ptPos, new_planes); + // copy the existing planes + new_planes.copy_from(planes); - // get the room pointed to by the portal - LRoom * pLinkedRoom = pPortal->GetLinkedRoom(); - if (pLinkedRoom) - pLinkedRoom->DetermineVisibility_Recursive(depth + 1, cam, new_planes, BF_visible, id); + // add the planes for the portal + pPortal->AddPlanes(cam.m_ptPos, new_planes); + + // get the room pointed to by the portal + LRoom * pLinkedRoom = pPortal->GetLinkedRoom(); + if (pLinkedRoom) + pLinkedRoom->DetermineVisibility_Recursive(manager, depth + 1, cam, new_planes, BF_visible, id); + + manager.m_Pool.Free(uiPoolMem); + } + else + { + // planes pool is empty! + WARN_PRINT_ONCE("Planes pool is empty"); + } } } diff --git a/lroom.h b/lroom.h index 303bc2f..3d66a76 100644 --- a/lroom.h +++ b/lroom.h @@ -28,11 +28,13 @@ #include "scene/3d/spatial.h" +#include "lvector.h" namespace Core {class CoBitField_Dynamic;} class LPortal; +class LRoomManager; class MeshInstance; class LCamera @@ -68,7 +70,7 @@ public: void MakePortalQuickList(); // main function - void DetermineVisibility_Recursive(int depth, const LCamera &cam, const Vector &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from = 0); + void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from = 0); // specific public: diff --git a/lroom_manager.cpp b/lroom_manager.cpp index bbea7ce..f7c96f4 100644 --- a/lroom_manager.cpp +++ b/lroom_manager.cpp @@ -28,6 +28,7 @@ LRoomManager::LRoomManager() { m_room_curr = 0; m_cameraID = 0; + } @@ -232,7 +233,13 @@ void LRoomManager::FrameUpdate() cam.m_ptPos = Vector3(0, 0, 0); cam.m_ptDir = Vector3 (-1, 0, 0); - Vector planes; + // reset the pool for another frame + m_Pool.Reset(); + unsigned int pool_member = m_Pool.Request(); + assert (pool_member != -1); + + LVector &planes = m_Pool.Get(pool_member); + planes.clear(); // get the camera desired and make into lcamera if (m_cameraID) @@ -246,11 +253,11 @@ void LRoomManager::FrameUpdate() cam.m_ptPos = tr.origin; cam.m_ptDir = tr.basis.get_row(2); // or possibly get_axis .. z is what we want - planes = pCamera->get_frustum(); + planes.copy_from(pCamera->get_frustum()); } } - pRoom->DetermineVisibility_Recursive(0, cam, planes, m_BF_visible_rooms); + pRoom->DetermineVisibility_Recursive(*this, 0, cam, planes, m_BF_visible_rooms); // finally hide all the rooms that are currently visible but not in the visible bitfield as having been hit diff --git a/lroom_manager.h b/lroom_manager.h index 9c70d2d..6c1da31 100644 --- a/lroom_manager.h +++ b/lroom_manager.h @@ -28,10 +28,13 @@ #include "scene/3d/spatial.h" #include "CoBitField_Dynamic.h" +#include "lplanes_pool.h" class LRoomManager : public Spatial { GDCLASS(LRoomManager, Spatial); + friend class LRoom; + // a quick list of object IDs of child rooms Vector m_room_IDs; @@ -40,20 +43,24 @@ class LRoomManager : public Spatial { // keep track of which rooms are visible, so we can hide ones that aren't hit that were previously on Core::CoBitField_Dynamic m_BF_visible_rooms; -// Vector m_VisibleRoomList[2]; -// int m_CurrentVisibleRoomList; + Vector m_VisibleRoomList[2]; + int m_CurrentVisibleRoomList; public: LRoomManager(); // convert empties and meshes to rooms and portals void convert(); + + // choose which camera you want to use to determine visibility. + // normally this will be your main camera, but you can choose another for debugging void set_camera(Node * pCam); protected: static void _bind_methods(); void _notification(int p_what); + LPlanesPool m_Pool; private: void Convert_Rooms(); bool Convert_Room(Spatial * pNode); diff --git a/lvector.h b/lvector.h new file mode 100644 index 0000000..4b68d31 --- /dev/null +++ b/lvector.h @@ -0,0 +1,113 @@ +#pragma once + +// just a light wrapper around the Godot vector until we get the allocation issues sorted +#include "core/vector.h" +#include + +template class LVector +{ +public: + + // array subscript access + T& operator[](unsigned int ui) + { + assert (ui < m_iSize); + return m_Vec[ui]; + } + const T& operator[](unsigned int ui) const + { + assert (ui < m_iSize); + return m_Vec[ui]; + } + + void clear(bool bCompact = false) + { + m_iSize = 0; + if (bCompact) + compact(); + } + + void compact() + { + m_Vec.resize(m_iSize); + } + + void reserve(int s) + { + m_Vec.resize(s); + } + + void set(unsigned int ui, const T &t) + { + assert (ui < m_iSize); + m_Vec.set(ui, t); + } + + void push_back(const T &t) + { + int size_p1 = m_iSize+1; + + if (size_p1 < m_Vec.size()) + { + int size = m_iSize; + m_iSize = size_p1; + m_Vec.set(size, t); + } + else + { + // need more space + reserve(m_Vec.size() * 2); + + // call recursive + push_back(t); + } + } + + void copy_from(const LVector &o) + { + // make sure enough space + if (o.size() > m_Vec.size()) + { + reserve(o.size()); + } + + clear(); + m_iSize = o.size(); + + for (int n=0; n &o) + { + // make sure enough space + if (o.size() > m_Vec.size()) + { + reserve(o.size()); + } + + clear(); + m_iSize = o.size(); + + for (int n=0; n m_Vec; + + // working size + int m_iSize; +}; +