mirror of
https://github.com/Relintai/godot-lportal.git
synced 2024-11-11 10:52:09 +01:00
Using pool and vector wrapper for planes to prevent allocations
This commit is contained in:
parent
da3dff21ba
commit
a2281009a2
1
SCsub
1
SCsub
@ -6,6 +6,7 @@ sources = [
|
||||
"lroom.cpp",
|
||||
"lroom_manager.cpp",
|
||||
"lportal.cpp",
|
||||
"lplanes_pool.cpp",
|
||||
"CoBitField_Dynamic.cpp",
|
||||
]
|
||||
|
||||
|
47
lplanes_pool.cpp
Normal file
47
lplanes_pool.cpp
Normal file
@ -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; n++)
|
||||
{
|
||||
m_Planes[n].reserve(32);
|
||||
}
|
||||
}
|
||||
|
||||
void LPlanesPool::Reset()
|
||||
{
|
||||
memset(m_ucTaken, 0, sizeof ( m_ucTaken));
|
||||
m_uiCount = 0;
|
||||
}
|
||||
|
||||
unsigned int LPlanesPool::Request()
|
||||
{
|
||||
// can't do, pool run out
|
||||
if (m_uiCount >= POOL_MAX)
|
||||
return -1;
|
||||
|
||||
for (unsigned int n=0; n<POOL_MAX; n++)
|
||||
{
|
||||
if (m_ucTaken[n] == 0)
|
||||
{
|
||||
m_ucTaken[n] = 255;
|
||||
m_uiCount++;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
assert (0);
|
||||
}
|
||||
|
||||
void LPlanesPool::Free(unsigned int ui)
|
||||
{
|
||||
assert (ui <= POOL_MAX);
|
||||
assert (m_ucTaken[ui]);
|
||||
assert (m_uiCount);
|
||||
|
||||
m_ucTaken[ui] = 0;
|
||||
m_uiCount--;
|
||||
}
|
23
lplanes_pool.h
Normal file
23
lplanes_pool.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "lvector.h"
|
||||
#include "core/math/plane.h"
|
||||
|
||||
class LPlanesPool
|
||||
{
|
||||
public:
|
||||
const static int POOL_MAX = 32;
|
||||
|
||||
void Reset();
|
||||
|
||||
unsigned int Request();
|
||||
void Free(unsigned int ui);
|
||||
|
||||
LVector<Plane> &Get(unsigned int ui) {return m_Planes[ui];}
|
||||
|
||||
LPlanesPool();
|
||||
private:
|
||||
LVector<Plane> m_Planes[ POOL_MAX];
|
||||
unsigned char m_ucTaken[POOL_MAX];
|
||||
unsigned int m_uiCount;
|
||||
};
|
18
lportal.cpp
18
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<Plane> &planes) const
|
||||
void LPortal::AddPlanes(const Vector3 &ptCam, LVector<Plane> &planes) const
|
||||
{
|
||||
// short version
|
||||
const Vector<Vector3> &pts = m_ptsWorld;
|
||||
|
||||
int nPoints = pts.size();
|
||||
// ERR_FAIL_COND(nPoints < 3);
|
||||
ERR_FAIL_COND(nPoints < 3);
|
||||
|
||||
Plane p;
|
||||
|
||||
for (int n=1; n<nPoints; n++)
|
||||
{
|
||||
p = Plane(ptCam, pts[n], pts[n-1]);
|
||||
|
||||
// detect null plane
|
||||
// if (p.normal.length_squared() < 0.1f)
|
||||
// {
|
||||
// print("NULL plane detected from points : ");
|
||||
// print(ptCam + pts[n] + pts[n-1]);
|
||||
// }
|
||||
planes.push_back(p);
|
||||
}
|
||||
|
||||
// first and last
|
||||
p = Plane(ptCam, pts[0], pts[nPoints-1]);
|
||||
planes.push_back(p);
|
||||
}
|
||||
|
||||
|
||||
@ -93,7 +104,10 @@ LPortal::eClipResult LPortal::ClipWithPlane(const Plane &p) const
|
||||
}
|
||||
|
||||
if (nOutside == nPoints)
|
||||
{
|
||||
print("LPortal::ClipWithPlane : Outside plane " + p);
|
||||
return CLIP_OUTSIDE;
|
||||
}
|
||||
|
||||
if (nOutside == 0)
|
||||
return CLIP_INSIDE;
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
|
||||
#include "scene/3d/spatial.h"
|
||||
#include "lvector.h"
|
||||
|
||||
class LRoom;
|
||||
|
||||
@ -52,7 +53,7 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
LPortal::eClipResult ClipWithPlane(const Plane &p) const;
|
||||
void AddPlanes(const Vector3 &ptCam, Vector<Plane> &planes) const;
|
||||
void AddPlanes(const Vector3 &ptCam, LVector<Plane> &planes) const;
|
||||
|
||||
public:
|
||||
// normal determined by winding order
|
||||
|
27
lroom.cpp
27
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<Plane> &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from)
|
||||
void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &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<VisualInstance>(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<nPortals; p++)
|
||||
{
|
||||
@ -165,7 +167,14 @@ void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const V
|
||||
}
|
||||
|
||||
// else recurse into that portal
|
||||
Vector<Plane> new_planes = planes;
|
||||
unsigned int uiPoolMem = manager.m_Pool.Request();
|
||||
if (uiPoolMem != -1)
|
||||
{
|
||||
// get a vector of planes from the pool
|
||||
LVector<Plane> &new_planes = manager.m_Pool.Get(uiPoolMem);
|
||||
|
||||
// copy the existing planes
|
||||
new_planes.copy_from(planes);
|
||||
|
||||
// add the planes for the portal
|
||||
pPortal->AddPlanes(cam.m_ptPos, new_planes);
|
||||
@ -173,7 +182,15 @@ void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const V
|
||||
// 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);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
4
lroom.h
4
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<Plane> &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from = 0);
|
||||
void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from = 0);
|
||||
|
||||
// specific
|
||||
public:
|
||||
|
@ -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<Plane> planes;
|
||||
// reset the pool for another frame
|
||||
m_Pool.Reset();
|
||||
unsigned int pool_member = m_Pool.Request();
|
||||
assert (pool_member != -1);
|
||||
|
||||
LVector<Plane> &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
|
||||
|
@ -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<ObjectID> 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<int> m_VisibleRoomList[2];
|
||||
// int m_CurrentVisibleRoomList;
|
||||
Vector<int> 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);
|
||||
|
113
lvector.h
Normal file
113
lvector.h
Normal file
@ -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 <assert.h>
|
||||
|
||||
template <class T> 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<T> &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.size(); n++)
|
||||
{
|
||||
set(n, o[n]);
|
||||
}
|
||||
}
|
||||
|
||||
void copy_from(const Vector<T> &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.size(); n++)
|
||||
{
|
||||
set(n, o[n]);
|
||||
}
|
||||
}
|
||||
|
||||
LVector()
|
||||
{
|
||||
m_iSize = 0;
|
||||
}
|
||||
|
||||
int size() const {return m_iSize;}
|
||||
|
||||
private:
|
||||
Vector<T> m_Vec;
|
||||
|
||||
// working size
|
||||
int m_iSize;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user