DOB visibility culling added

This commit is contained in:
lawnjelly 2019-09-16 14:23:10 +01:00 committed by GitHub
parent b7c5f74062
commit 2969fd4900
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 370 additions and 61 deletions

View File

@ -1,2 +1,20 @@
#include "ldob.h"
#include "scene/3d/mesh_instance.h"
Spatial * LSob::GetSpatial() const
{
Object * pObj = ObjectDB::get_instance(m_ID);
Spatial * pSpat = Object::cast_to<Spatial>(pObj);
return pSpat;
}
Spatial * LDob::GetSpatial() const
{
Object * pObj = ObjectDB::get_instance(m_ID);
Spatial * pSpat = Object::cast_to<Spatial>(pObj);
return pSpat;
}

8
ldob.h
View File

@ -2,18 +2,26 @@
#include "scene/3d/spatial.h"
class VisualInstance;
// static object
class LSob
{
public:
Spatial * GetSpatial() const;
ObjectID m_ID; // godot object
AABB m_aabb; // world space
bool m_bVisible;
};
// dynamic object
class LDob
{
public:
Spatial * GetSpatial() const;
ObjectID m_ID;
bool m_bVisible;
float m_fRadius;
};

View File

@ -23,10 +23,13 @@
#include "lroom.h"
//#define LPORTAL_VERBOSE
bool LPortal::m_bRunning = false;
void LPortal::print(String sz)
{
#ifdef LPORTAL_VERBOSE
if (m_bRunning)
{
}
@ -34,6 +37,7 @@ void LPortal::print(String sz)
{
print_line(sz);
}
#endif
}
@ -64,7 +68,20 @@ String LPortal::FindNameAfter(Node * pNode, String szStart)
String name = pNode->get_name();
szRes = name.substr(szStart.length());
print("\t\tNameAfter is " + szRes);
// because godot doesn't support multiple nodes with the same name, we will strip e.g. a number
// after an @ on the end of the name...
// e.g. portal_kitchen@2
for (int c=0; c<szRes.length(); c++)
{
if (szRes[c] == '*')
{
// remove everything after and including this character
szRes = szRes.substr(0, c);
break;
}
}
//print("\t\tNameAfter is " + szRes);
return szRes;
}
@ -115,7 +132,9 @@ LPortal::eClipResult LPortal::ClipWithPlane(const Plane &p) const
if (nOutside == nPoints)
{
#ifdef LPORTAL_VERBOSE
print("LPortal::ClipWithPlane : Outside plane " + p);
#endif
return CLIP_OUTSIDE;
}
@ -133,7 +152,7 @@ void LPortal::CreateGeometry(PoolVector<Vector3> p_vertices, const Transform &tr
m_ptsWorld.resize(nPoints);
print("\tLPortal::CreateGeometry nPoints : " + itos(nPoints));
//print("\t\t\tLPortal::CreateGeometry nPoints : " + itos(nPoints));
for (int n=0; n<nPoints; n++)
{
@ -141,7 +160,7 @@ void LPortal::CreateGeometry(PoolVector<Vector3> p_vertices, const Transform &tr
m_ptsWorld.set(n, ptWorld);
m_ptCentre += ptWorld;
print("\t\t" + itos(n) + "\tLocal : " + Variant(p_vertices[n]) + "\tWorld : " + ptWorld);
//print("\t\t\t\t" + itos(n) + "\tLocal : " + Variant(p_vertices[n]) + "\tWorld : " + ptWorld);
}
SortVertsClockwise();
@ -237,7 +256,7 @@ void LPortal::ReverseWindingOrder()
void LPortal::CopyReversedGeometry(const LPortal &source)
{
print("CopyReversedGeometry");
//print("\t\t\tCopyReversedGeometry");
// points are the same but reverse winding order
int nPoints = source.m_ptsWorld.size();
m_ptCentre = source.m_ptCentre;
@ -247,7 +266,7 @@ void LPortal::CopyReversedGeometry(const LPortal &source)
for (int n=0; n<nPoints; n++)
{
m_ptsWorld.set(n, source.m_ptsWorld[nPoints - n - 1]);
print("\t\t" + itos(n) + "\t: " + Variant(m_ptsWorld[n]));
//print("\t\t\t\t" + itos(n) + "\t: " + Variant(m_ptsWorld[n]));
}
PlaneFromPoints();
@ -263,7 +282,7 @@ void LPortal::PlaneFromPoints()
// create plane from points
m_Plane = Plane(m_ptsWorld[0], m_ptsWorld[1], m_ptsWorld[2]);
print("Plane normal world space : " + m_Plane);
//print("\t\t\t\t\tPlane normal world space : " + m_Plane);
}
@ -271,6 +290,7 @@ void LPortal::PlaneFromPoints()
LPortal::LPortal() {
// unset
m_iRoomNum = -1;
m_bMirror = false;
// m_uiFrameTouched_Blocked = 0;
}

View File

@ -57,6 +57,10 @@ public:
Vector3 m_ptCentre; // world
Plane m_Plane;
// whether this is an autogenerated mirror portal
// this is used only on conversion of 2 way portals to prevent recursion .. maybe not needed at runtime?
bool m_bMirror;
// frame counter when last touched .. prevents going backward through portals
//unsigned int m_uiFrameTouched_Blocked;

194
lroom.cpp
View File

@ -25,9 +25,13 @@
#include "lbitfield_dynamic.h"
#include "lroom_manager.h"
//#define LROOM_VERBOSE
void LRoom::print(String sz)
{
#ifdef LROOM_VERBOSE
LPortal::print(sz);
#endif
}
LRoom::LRoom() {
@ -52,15 +56,15 @@ Spatial * LRoom::GetGodotRoom() const
void LRoom::DOB_Add(Spatial * pDOB)
void LRoom::DOB_Add(const LDob &dob)
{
LDob dob;
dob.m_ID = pDOB->get_instance_id();
// LDob dob;
// dob.m_ID = pDOB->get_instance_id();
m_DOBs.push_back(dob);
}
bool LRoom::DOB_Remove(Node * pDOB)
unsigned int LRoom::DOB_Find(Node * pDOB) const
{
ObjectID id = pDOB->get_instance_id();
@ -68,11 +72,21 @@ bool LRoom::DOB_Remove(Node * pDOB)
{
if (m_DOBs[n].m_ID == id)
{
m_DOBs.remove(n);
return true;
return n;
}
}
return -1;
}
bool LRoom::DOB_Remove(unsigned int ui)
{
if (ui < m_DOBs.size())
{
m_DOBs.remove_unsorted(ui);
return true;
}
return false;
}
@ -102,7 +116,9 @@ LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
if (dist > slop)
{
#ifdef LROOM_VERBOSE
print("DOB at pos " + pt + " ahead of portal " + port.get_name() + " by " + String(Variant(dist)));
#endif
// we want to move into the adjoining room
return &manager.Portal_GetLinkedRoom(port);
@ -112,6 +128,61 @@ LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
return 0;
}
// hide all the objects not hit on this frame .. instead of calling godot hide without need
// (it might be expensive)
void LRoom::FinalizeVisibility(LRoomManager &manager)
{
//print_line("FinalizeVisibility room " + get_name() + " NumSOBs " + itos(m_SOBs.size()) + ", NumDOBs " + itos(m_DOBs.size()));
for (int n=0; n<m_SOBs.size(); n++)
{
const LSob &sob = m_SOBs[n];
Spatial * pS = sob.GetSpatial();
if (pS)
{
if (sob.m_bVisible)
pS->show();
else
pS->hide();
}
}
for (int n=0; n<m_DOBs.size(); n++)
{
const LDob &dob = m_DOBs[n];
// don't cull the main camera
if (dob.m_ID == manager.m_cameraID)
continue;
Spatial * pS = dob.GetSpatial();
if (pS)
{
if (dob.m_bVisible)
{
//print("LRoom::FinalizeVisibility making visible dob " + pS->get_name());
pS->show();
}
else
pS->hide();
}
}
}
// hide godot room and all linked dobs
void LRoom::Hide_All()
{
GetGodotRoom()->hide();
for (int n=0; n<m_DOBs.size(); n++)
{
LDob &dob = m_DOBs[n];
Spatial * pS = dob.GetSpatial();
if (pS)
pS->hide();
}
}
void LRoom::FirstTouch(LRoomManager &manager)
{
@ -123,14 +194,11 @@ void LRoom::FirstTouch(LRoomManager &manager)
// hide all objects
for (int n=0; n<m_SOBs.size(); n++)
{
const LSob sob = m_SOBs[n];
Object * pNode = ObjectDB::get_instance(sob.m_ID);
VisualInstance * pObj = Object::cast_to<VisualInstance>(pNode);
m_SOBs[n].m_bVisible = false;
if (pObj)
pObj->hide();
}
// hide all dobs
for (int n=0; n<m_DOBs.size(); n++)
m_DOBs[n].m_bVisible = false;
}
@ -139,14 +207,18 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
// prevent too much depth
if (depth >= 8)
{
#ifdef LROOM_VERBOSE
print("\t\t\tDEPTH LIMIT REACHED");
#endif
return;
}
#ifdef LROOM_VERBOSE
print("DetermineVisibility_Recursive from " + get_name());
#endif
// only handle one touch per frame so far (one portal into room)
assert (manager.m_uiFrameCounter > m_uiFrameTouched);
//assert (manager.m_uiFrameCounter > m_uiFrameTouched);
// first touch
if (m_uiFrameTouched < manager.m_uiFrameCounter)
@ -156,6 +228,51 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
GetGodotRoom()->show();
manager.m_BF_visible_rooms.SetBit(m_RoomID, true);
#define LPORTAL_CULL_STATIC
#ifdef LPORTAL_CULL_STATIC
// clip all objects in this room to the clipping planes
for (int n=0; n<m_SOBs.size(); n++)
{
LSob &sob = m_SOBs[n];
// already determined to be visible through another portal
if (sob.m_bVisible)
continue;
bool bShow = true;
// estimate the radius .. for now
const AABB &bb = sob.m_aabb;
// print("\t\t\tculling object " + pObj->get_name());
for (int p=0; p<planes.size(); p++)
{
// float dist = planes[p].distance_to(pt);
// print("\t\t\t\t" + itos(p) + " : dist " + String(Variant(dist)));
float r_min, r_max;
bb.project_range_in_plane(planes[p], r_min, r_max);
// print("\t\t\t\t" + itos(p) + " : r_min " + String(Variant(r_min)) + ", r_max " + String(Variant(r_max)));
if (r_min > 0.0f)
{
bShow = false;
break;
}
}
if (bShow)
sob.m_bVisible = true;
}
#else
// clip all objects in this room to the clipping planes
for (int n=0; n<m_SOBs.size(); n++)
{
@ -196,19 +313,56 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
}
if (bShow)
pObj->show();
sob.m_bVisible = true;
// pObj->show();
// else
// pObj->hide();
}
}
#endif
// cull DOBs
for (int n=0; n<m_DOBs.size(); n++)
{
LDob &dob = m_DOBs[n];
Spatial * pObj = dob.GetSpatial();
if (pObj)
{
bool bShow = true;
const Vector3 &pt = pObj->get_global_transform().origin;
//print_line("\t\t\tculling dob " + pObj->get_name());
float radius = dob.m_fRadius;
for (int p=0; p<planes.size(); p++)
{
float dist = planes[p].distance_to(pt);
//print("\t\t\t\t" + itos(p) + " : dist " + String(Variant(dist)));
if (dist > radius)
{
bShow = false;
break;
}
}
if (bShow)
dob.m_bVisible = true;
}
}
// look through portals
for (int p=0; p<m_iNumPortals; p++)
{
int port_id = m_iFirstPortal + p;
// ignore if the portal we are looking in from
// is this needed? surely the portal we are looking in from is in another room?
if (port_id == portalID_from)
continue;
@ -218,14 +372,16 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
// get the room pointed to by the portal
LRoom * pLinkedRoom = &manager.Portal_GetLinkedRoom(port);
if (pLinkedRoom->m_uiFrameTouched == manager.m_uiFrameCounter)
continue;
// if (pLinkedRoom->m_uiFrameTouched == manager.m_uiFrameCounter)
// continue;
// cull by portal angle to camera.
// Note we need to deal with 'side on' portals, and the camera has a spreading view, so we cannot simply dot
// the portal normal with camera direction, we need to take into account angle to the portal itself.
const Vector3 &portal_normal = port.m_Plane.normal;
#ifdef LROOM_VERBOSE
print("\ttesting portal " + port.get_name() + " normal " + portal_normal);
#endif
// we will dot the portal angle with a ray from the camera to the portal centre
// (there might be an even better ray direction but this will do for now)
@ -237,7 +393,9 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
// float dot = cam.m_ptDir.dot(portal_normal);
if (dot <= -0.0f) // 0.0
{
#ifdef LROOM_VERBOSE
print("\t\tportal culled (wrong direction) dot is " + String(Variant(dot)) + ", dir_portal is " + dir_portal);
#endif
continue;
}
@ -269,7 +427,9 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
// this portal is culled
if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE)
{
#ifdef LROOM_VERBOSE
print("\t\tportal culled (outside planes)");
#endif
continue;
}

15
lroom.h
View File

@ -59,7 +59,7 @@ private:
LVector<LSob> m_SOBs;
// dynamic objects
Vector<LDob> m_DOBs;
LVector<LDob> m_DOBs;
// portals are stored in the manager in a contiguous list
int m_iFirstPortal;
@ -87,9 +87,18 @@ protected:
void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &planes, int portalID_from = -1);
void FirstTouch(LRoomManager &manager);
// hide godot room and all linked dobs
void Hide_All();
void DOB_Add(Spatial * pDOB);
bool DOB_Remove(Node * pDOB);
// hide all the objects not hit on this frame .. instead of calling godot hide without need
// (it might be expensive)
void FinalizeVisibility(LRoomManager &manager);
void DOB_Add(const LDob &dob);
const LDob &DOB_Get(unsigned int ui) const {return m_DOBs[ui];}
unsigned int DOB_Find(Node * pDOB) const;
bool DOB_Remove(unsigned int ui);
LRoom * DOB_Update(LRoomManager &manager, Spatial * pDOB);
public:

View File

@ -208,11 +208,12 @@ int LRoomConverter::CountRooms()
// go through the nodes hanging off the room looking for those that are meshes to mark portal locations
void LRoomConverter::LRoom_DetectPortalMeshes(LRoom &lroom, LTempRoom &troom)
{
print("DetectPortalMeshes");
print("DetectPortalMeshes from room " + lroom.get_name());
Spatial * pGRoom = lroom.GetGodotRoom();
assert (pGRoom);
for (int n=0; n<pGRoom->get_child_count(); n++)
{
Node * pChild = pGRoom->get_child(n);
@ -228,9 +229,41 @@ void LRoomConverter::LRoom_DetectPortalMeshes(LRoom &lroom, LTempRoom &troom)
LRoom_DetectedPortalMesh(lroom, troom, pMesh, szLinkRoom);
}
}
}
// we need an enclosing while loop because we might be deleting children and mucking up the iterator
bool bDetectedOne = true;
while (bDetectedOne)
{
bDetectedOne = false;
for (int n=0; n<pGRoom->get_child_count(); n++)
{
Node * pChild = pGRoom->get_child(n);
MeshInstance * pMesh = Object::cast_to<MeshInstance>(pChild);
if (pMesh)
{
// name must start with 'portal_'
// and ends with the name of the room we want to link to (without the 'room_')
if (LPortal::NameStartsWith(pMesh, "portal_"))
{
// delete the original child, as it is no longer needed at runtime (except maybe for debugging .. NYI?)
// pMeshInstance->hide();
pMesh->get_parent()->remove_child(pMesh);
pMesh->queue_delete();
bDetectedOne = true;
}
}
if (bDetectedOne)
break;
} // for loop
} // while
}
// handles the slight faff involved in getting a new portal in the manager contiguous list of portals
@ -258,13 +291,14 @@ void LRoomConverter::LRoom_MakePortalFinalList(LRoom &lroom, LTempRoom &troom)
// found a portal mesh! create a matching LPortal
void LRoomConverter::LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, MeshInstance * pMeshInstance, String szLinkRoom)
{
print("\tDetected PortalMesh");
print("\tDetected PortalMesh to " + szLinkRoom);
// which room does this portal want to link to?
int iLinkRoom = FindRoom_ByName(szLinkRoom);
if (iLinkRoom == -1)
{
WARN_PRINTS("portal to room " + szLinkRoom + ", room not found");
print("\t\tWARNING : portal to room " + szLinkRoom + ", room not found");
//WARN_PRINTS("portal to room " + szLinkRoom + ", room not found");
return;
}
@ -281,10 +315,8 @@ void LRoomConverter::LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, Me
// create the portal geometry
lport.CreateGeometry(p_vertices, pMeshInstance->get_global_transform());
// delete the original child, as it is no longer needed at runtime (except maybe for debugging .. NYI?)
// pMeshInstance->hide();
pMeshInstance->get_parent()->remove_child(pMeshInstance);
pMeshInstance->queue_delete();
print("\t\t\tnum portals now " + itos(troom.m_Portals.size()));
}
@ -292,28 +324,39 @@ void LRoomConverter::LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, Me
// will automatically create a mirror portal the other way.
void LRoomConverter::LRoom_MakePortalsTwoWay(LRoom &lroom, LTempRoom &troom, int iRoomNum)
{
print("LRoomConverter::LRoom_MakePortalsTwoWay from room " + lroom.get_name() + ", contains " + itos (troom.m_Portals.size()) + " portals");
for (int n=0; n<troom.m_Portals.size(); n++)
{
const LPortal &portal_orig = troom.m_Portals[n];
print("\tconsidering portal " + portal_orig.get_name());
// only make original portals into mirror portals, to prevent infinite recursion
if (portal_orig.m_bMirror)
{
print ("\t\tis MIRROR, ignoring");
continue;
}
print("\t\tcreating opposite portal");
// get the temproom this portal is linking to
LTempRoom &nroom = m_TempRooms[portal_orig.m_iRoomNum];
// does a portal already exist back to the orig room?
// NOTE this doesn't cope with multiple portals between pairs of rooms yet.
bool bAlreadyLinked =false;
// bool bAlreadyLinked =false;
for (int p=0; p<nroom.m_Portals.size(); p++)
{
if (nroom.m_Portals[p].m_iRoomNum == n)
{
bAlreadyLinked = true;
break;
}
}
// for (int p=0; p<nroom.m_Portals.size(); p++)
// {
// if (nroom.m_Portals[p].m_iRoomNum == n)
// {
// bAlreadyLinked = true;
// break;
// }
// }
if (bAlreadyLinked)
continue;
// if (bAlreadyLinked)
// continue;
// needs a new reverse link if got to here
TRoom_MakeOppositePortal(portal_orig, iRoomNum);
@ -330,6 +373,7 @@ void LRoomConverter::TRoom_MakeOppositePortal(const LPortal &port, int iRoomOrig
LPortal &new_port = *nroom.m_Portals.request();
new_port.m_szName = orig_lroom.m_szName;
new_port.m_iRoomNum = iRoomOrig;
new_port.m_bMirror = true;
// the portal vertices should be the same but reversed (to flip the normal)
new_port.CopyReversedGeometry(port);

View File

@ -30,8 +30,8 @@ LRoomManager::LRoomManager()
m_uiFrameCounter = 0;
// to know which rooms to hide we keep track of which were shown this, and the previous frame
m_pCurr_VisibleRoomList = &m_VisibleRoomList[0];
m_pPrev_VisibleRoomList = &m_VisibleRoomList[1];
m_pCurr_VisibleRoomList = &m_VisibleRoomList_A;
m_pPrev_VisibleRoomList = &m_VisibleRoomList_B;
}
int LRoomManager::FindClosestRoom(const Vector3 &pt) const
@ -119,7 +119,7 @@ LRoom * LRoomManager::GetRoomFromDOB(Node * pNode)
}
void LRoomManager::dob_register(Node * pDOB)
void LRoomManager::dob_register(Node * pDOB, float radius)
{
print_line("register_dob " + pDOB->get_name());
@ -139,7 +139,11 @@ void LRoomManager::dob_register(Node * pDOB)
if (!pRoom)
return;
pRoom->DOB_Add(pSpat);
LDob dob;
dob.m_ID = pSpat->get_instance_id();
dob.m_fRadius = radius;
pRoom->DOB_Add(dob);
// save the room ID on the dob metadata
Obj_SetRoomNum(pSpat, iRoomNum);
@ -164,8 +168,18 @@ bool LRoomManager::dob_update(Node * pDOB)
// remove from the list in old room and add to list in new room, and change the metadata
int iRoomNum = pNewRoom->m_RoomID;
pRoom->DOB_Remove(pDOB);
pNewRoom->DOB_Add(pSpat);
// get dob data to move to new room
unsigned int dob_id = pRoom->DOB_Find(pDOB);
assert (dob_id != -1);
// copy across data before removing
const LDob &data = pRoom->DOB_Get(dob_id);
pNewRoom->DOB_Add(data);
// remove from old room
pRoom->DOB_Remove(dob_id);
// save the room ID on the dob metadata
Obj_SetRoomNum(pSpat, iRoomNum);
@ -186,7 +200,13 @@ bool LRoomManager::dob_teleport(Node * pDOB)
void LRoomManager::dob_unregister(Node * pDOB)
{
LRoom * pRoom = GetRoomFromDOB(pDOB);
pRoom->DOB_Remove(pDOB);
if (pRoom)
{
unsigned int dob_id = pRoom->DOB_Find(pDOB);
assert (dob_id != -1);
pRoom->DOB_Remove(dob_id);
}
}
int LRoomManager::dob_get_room_id(Node * pDOB)
@ -316,7 +336,7 @@ void LRoomManager::FrameUpdate()
{
if (!m_BF_visible_rooms.GetBit(n))
{
m_Rooms[n].GetGodotRoom()->hide();
m_Rooms[n].Hide_All();
}
}
}
@ -328,15 +348,30 @@ void LRoomManager::FrameUpdate()
int r = (*m_pPrev_VisibleRoomList)[n];
if (!m_BF_visible_rooms.GetBit(r))
m_Rooms[r].GetGodotRoom()->hide();
m_Rooms[r].Hide_All();
}
// swap the current and previous visible room list
LVector<int> * pTemp = m_pCurr_VisibleRoomList;
m_pCurr_VisibleRoomList = m_pPrev_VisibleRoomList;
m_pPrev_VisibleRoomList = pTemp;
}
// and hide all the dobs that are in visible rooms that haven't been made visible
// if (m_pCurr_VisibleRoomList->size() == 0)
// print_line("WARNING : vis room list size is 0");
for (int n=0; n<m_pCurr_VisibleRoomList->size(); n++)
{
int r = (*m_pCurr_VisibleRoomList)[n];
m_Rooms[r].FinalizeVisibility(*this);
}
// swap the current and previous visible room list
LVector<int> * pTemp = m_pCurr_VisibleRoomList;
m_pCurr_VisibleRoomList = m_pPrev_VisibleRoomList;
m_pPrev_VisibleRoomList = pTemp;
// hide all the DOB
// when running, emit less debugging output so as not to choke the IDE
LPortal::m_bRunning = true;
}

View File

@ -48,7 +48,9 @@ class LRoomManager : public Spatial {
// keep track of which rooms are visible, so we can hide ones that aren't hit that were previously on
Lawn::LBitField_Dynamic m_BF_visible_rooms;
LVector<int> m_VisibleRoomList[2];
LVector<int> m_VisibleRoomList_A;
LVector<int> m_VisibleRoomList_B;
LVector<int> * m_pCurr_VisibleRoomList;
LVector<int> * m_pPrev_VisibleRoomList;
@ -71,7 +73,7 @@ public:
// These are defined by their ability to move from room to room.
// You can still move static objects within the same room (e.g. elevators, moving platforms)
// as these don't require checks for changing rooms.
void dob_register(Node * pDOB);
void dob_register(Node * pDOB, float radius);
void dob_unregister(Node * pDOB);
bool dob_update(Node * pDOB);
bool dob_teleport(Node * pDOB);

View File

@ -21,7 +21,7 @@
// SOFTWARE.
// just a light wrapper around the a vector until we get the Godot vector allocation issues sorted
// just a light wrapper around a vector until we get the Godot vector allocation issues sorted
#include "core/vector.h"
#include <assert.h>
#include <vector>
@ -31,6 +31,7 @@ template <class T> class LVector
public:
// array subscript access
// note this is not available in Godot Vector
T& operator[](unsigned int ui)
{
assert (ui < m_iSize);
@ -83,6 +84,14 @@ public:
m_Vec[ui] = t;
}
// efficient unsorted
void remove_unsorted(unsigned int ui)
{
// just swap the end element and decrement count
m_Vec[ui] = m_Vec[m_iSize-1];
m_iSize--;
}
T * request()
{
m_iSize++;