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 "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" #include "scene/3d/spatial.h"
class VisualInstance;
// static object // static object
class LSob class LSob
{ {
public: public:
Spatial * GetSpatial() const;
ObjectID m_ID; // godot object ObjectID m_ID; // godot object
AABB m_aabb; // world space AABB m_aabb; // world space
bool m_bVisible;
}; };
// dynamic object // dynamic object
class LDob class LDob
{ {
public: public:
Spatial * GetSpatial() const;
ObjectID m_ID; ObjectID m_ID;
bool m_bVisible;
float m_fRadius;
}; };

View File

@ -23,10 +23,13 @@
#include "lroom.h" #include "lroom.h"
//#define LPORTAL_VERBOSE
bool LPortal::m_bRunning = false; bool LPortal::m_bRunning = false;
void LPortal::print(String sz) void LPortal::print(String sz)
{ {
#ifdef LPORTAL_VERBOSE
if (m_bRunning) if (m_bRunning)
{ {
} }
@ -34,6 +37,7 @@ void LPortal::print(String sz)
{ {
print_line(sz); print_line(sz);
} }
#endif
} }
@ -64,7 +68,20 @@ String LPortal::FindNameAfter(Node * pNode, String szStart)
String name = pNode->get_name(); String name = pNode->get_name();
szRes = name.substr(szStart.length()); 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; return szRes;
} }
@ -115,7 +132,9 @@ LPortal::eClipResult LPortal::ClipWithPlane(const Plane &p) const
if (nOutside == nPoints) if (nOutside == nPoints)
{ {
#ifdef LPORTAL_VERBOSE
print("LPortal::ClipWithPlane : Outside plane " + p); print("LPortal::ClipWithPlane : Outside plane " + p);
#endif
return CLIP_OUTSIDE; return CLIP_OUTSIDE;
} }
@ -133,7 +152,7 @@ void LPortal::CreateGeometry(PoolVector<Vector3> p_vertices, const Transform &tr
m_ptsWorld.resize(nPoints); 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++) 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_ptsWorld.set(n, ptWorld);
m_ptCentre += 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(); SortVertsClockwise();
@ -237,7 +256,7 @@ void LPortal::ReverseWindingOrder()
void LPortal::CopyReversedGeometry(const LPortal &source) void LPortal::CopyReversedGeometry(const LPortal &source)
{ {
print("CopyReversedGeometry"); //print("\t\t\tCopyReversedGeometry");
// points are the same but reverse winding order // points are the same but reverse winding order
int nPoints = source.m_ptsWorld.size(); int nPoints = source.m_ptsWorld.size();
m_ptCentre = source.m_ptCentre; m_ptCentre = source.m_ptCentre;
@ -247,7 +266,7 @@ void LPortal::CopyReversedGeometry(const LPortal &source)
for (int n=0; n<nPoints; n++) for (int n=0; n<nPoints; n++)
{ {
m_ptsWorld.set(n, source.m_ptsWorld[nPoints - n - 1]); 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(); PlaneFromPoints();
@ -263,7 +282,7 @@ void LPortal::PlaneFromPoints()
// create plane from points // create plane from points
m_Plane = Plane(m_ptsWorld[0], m_ptsWorld[1], m_ptsWorld[2]); 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() { LPortal::LPortal() {
// unset // unset
m_iRoomNum = -1; m_iRoomNum = -1;
m_bMirror = false;
// m_uiFrameTouched_Blocked = 0; // m_uiFrameTouched_Blocked = 0;
} }

View File

@ -57,6 +57,10 @@ public:
Vector3 m_ptCentre; // world Vector3 m_ptCentre; // world
Plane m_Plane; 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 // frame counter when last touched .. prevents going backward through portals
//unsigned int m_uiFrameTouched_Blocked; //unsigned int m_uiFrameTouched_Blocked;

194
lroom.cpp
View File

@ -25,9 +25,13 @@
#include "lbitfield_dynamic.h" #include "lbitfield_dynamic.h"
#include "lroom_manager.h" #include "lroom_manager.h"
//#define LROOM_VERBOSE
void LRoom::print(String sz) void LRoom::print(String sz)
{ {
#ifdef LROOM_VERBOSE
LPortal::print(sz); LPortal::print(sz);
#endif
} }
LRoom::LRoom() { 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; // LDob dob;
dob.m_ID = pDOB->get_instance_id(); // dob.m_ID = pDOB->get_instance_id();
m_DOBs.push_back(dob); 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(); ObjectID id = pDOB->get_instance_id();
@ -68,11 +72,21 @@ bool LRoom::DOB_Remove(Node * pDOB)
{ {
if (m_DOBs[n].m_ID == id) if (m_DOBs[n].m_ID == id)
{ {
m_DOBs.remove(n); return n;
return true;
} }
} }
return -1;
}
bool LRoom::DOB_Remove(unsigned int ui)
{
if (ui < m_DOBs.size())
{
m_DOBs.remove_unsorted(ui);
return true;
}
return false; return false;
} }
@ -102,7 +116,9 @@ LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
if (dist > slop) if (dist > slop)
{ {
#ifdef LROOM_VERBOSE
print("DOB at pos " + pt + " ahead of portal " + port.get_name() + " by " + String(Variant(dist))); print("DOB at pos " + pt + " ahead of portal " + port.get_name() + " by " + String(Variant(dist)));
#endif
// we want to move into the adjoining room // we want to move into the adjoining room
return &manager.Portal_GetLinkedRoom(port); return &manager.Portal_GetLinkedRoom(port);
@ -112,6 +128,61 @@ LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
return 0; 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) void LRoom::FirstTouch(LRoomManager &manager)
{ {
@ -123,14 +194,11 @@ void LRoom::FirstTouch(LRoomManager &manager)
// hide all objects // hide all objects
for (int n=0; n<m_SOBs.size(); n++) for (int n=0; n<m_SOBs.size(); n++)
{ m_SOBs[n].m_bVisible = false;
const LSob sob = m_SOBs[n];
Object * pNode = ObjectDB::get_instance(sob.m_ID);
VisualInstance * pObj = Object::cast_to<VisualInstance>(pNode);
if (pObj) // hide all dobs
pObj->hide(); 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 // prevent too much depth
if (depth >= 8) if (depth >= 8)
{ {
#ifdef LROOM_VERBOSE
print("\t\t\tDEPTH LIMIT REACHED"); print("\t\t\tDEPTH LIMIT REACHED");
#endif
return; return;
} }
#ifdef LROOM_VERBOSE
print("DetermineVisibility_Recursive from " + get_name()); print("DetermineVisibility_Recursive from " + get_name());
#endif
// only handle one touch per frame so far (one portal into room) // 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 // first touch
if (m_uiFrameTouched < manager.m_uiFrameCounter) if (m_uiFrameTouched < manager.m_uiFrameCounter)
@ -156,6 +228,51 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
GetGodotRoom()->show(); GetGodotRoom()->show();
manager.m_BF_visible_rooms.SetBit(m_RoomID, true); 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 // clip all objects in this room to the clipping planes
for (int n=0; n<m_SOBs.size(); n++) for (int n=0; n<m_SOBs.size(); n++)
{ {
@ -196,19 +313,56 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
} }
if (bShow) if (bShow)
pObj->show(); sob.m_bVisible = true;
// pObj->show();
// else // else
// pObj->hide(); // 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++) for (int p=0; p<m_iNumPortals; p++)
{ {
int port_id = m_iFirstPortal + p; int port_id = m_iFirstPortal + p;
// ignore if the portal we are looking in from // 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) if (port_id == portalID_from)
continue; continue;
@ -218,14 +372,16 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
// get the room pointed to by the portal // get the room pointed to by the portal
LRoom * pLinkedRoom = &manager.Portal_GetLinkedRoom(port); LRoom * pLinkedRoom = &manager.Portal_GetLinkedRoom(port);
if (pLinkedRoom->m_uiFrameTouched == manager.m_uiFrameCounter) // if (pLinkedRoom->m_uiFrameTouched == manager.m_uiFrameCounter)
continue; // continue;
// cull by portal angle to camera. // 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 // 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. // 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; const Vector3 &portal_normal = port.m_Plane.normal;
#ifdef LROOM_VERBOSE
print("\ttesting portal " + port.get_name() + " normal " + portal_normal); 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 // 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) // (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); // float dot = cam.m_ptDir.dot(portal_normal);
if (dot <= -0.0f) // 0.0 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); print("\t\tportal culled (wrong direction) dot is " + String(Variant(dot)) + ", dir_portal is " + dir_portal);
#endif
continue; continue;
} }
@ -269,7 +427,9 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
// this portal is culled // this portal is culled
if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE) if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE)
{ {
#ifdef LROOM_VERBOSE
print("\t\tportal culled (outside planes)"); print("\t\tportal culled (outside planes)");
#endif
continue; continue;
} }

15
lroom.h
View File

@ -59,7 +59,7 @@ private:
LVector<LSob> m_SOBs; LVector<LSob> m_SOBs;
// dynamic objects // dynamic objects
Vector<LDob> m_DOBs; LVector<LDob> m_DOBs;
// portals are stored in the manager in a contiguous list // portals are stored in the manager in a contiguous list
int m_iFirstPortal; 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 DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &planes, int portalID_from = -1);
void FirstTouch(LRoomManager &manager); void FirstTouch(LRoomManager &manager);
// hide godot room and all linked dobs
void Hide_All();
void DOB_Add(Spatial * pDOB); // hide all the objects not hit on this frame .. instead of calling godot hide without need
bool DOB_Remove(Node * pDOB); // (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); LRoom * DOB_Update(LRoomManager &manager, Spatial * pDOB);
public: 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 // 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) void LRoomConverter::LRoom_DetectPortalMeshes(LRoom &lroom, LTempRoom &troom)
{ {
print("DetectPortalMeshes"); print("DetectPortalMeshes from room " + lroom.get_name());
Spatial * pGRoom = lroom.GetGodotRoom(); Spatial * pGRoom = lroom.GetGodotRoom();
assert (pGRoom); assert (pGRoom);
for (int n=0; n<pGRoom->get_child_count(); n++) for (int n=0; n<pGRoom->get_child_count(); n++)
{ {
Node * pChild = pGRoom->get_child(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); 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 // 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 // found a portal mesh! create a matching LPortal
void LRoomConverter::LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, MeshInstance * pMeshInstance, String szLinkRoom) 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? // which room does this portal want to link to?
int iLinkRoom = FindRoom_ByName(szLinkRoom); int iLinkRoom = FindRoom_ByName(szLinkRoom);
if (iLinkRoom == -1) 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; return;
} }
@ -281,10 +315,8 @@ void LRoomConverter::LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, Me
// create the portal geometry // create the portal geometry
lport.CreateGeometry(p_vertices, pMeshInstance->get_global_transform()); 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(); print("\t\t\tnum portals now " + itos(troom.m_Portals.size()));
pMeshInstance->get_parent()->remove_child(pMeshInstance);
pMeshInstance->queue_delete();
} }
@ -292,28 +324,39 @@ void LRoomConverter::LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, Me
// will automatically create a mirror portal the other way. // will automatically create a mirror portal the other way.
void LRoomConverter::LRoom_MakePortalsTwoWay(LRoom &lroom, LTempRoom &troom, int iRoomNum) 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++) for (int n=0; n<troom.m_Portals.size(); n++)
{ {
const LPortal &portal_orig = troom.m_Portals[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 // get the temproom this portal is linking to
LTempRoom &nroom = m_TempRooms[portal_orig.m_iRoomNum]; LTempRoom &nroom = m_TempRooms[portal_orig.m_iRoomNum];
// does a portal already exist back to the orig room? // does a portal already exist back to the orig room?
// NOTE this doesn't cope with multiple portals between pairs of rooms yet. // 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++) // for (int p=0; p<nroom.m_Portals.size(); p++)
{ // {
if (nroom.m_Portals[p].m_iRoomNum == n) // if (nroom.m_Portals[p].m_iRoomNum == n)
{ // {
bAlreadyLinked = true; // bAlreadyLinked = true;
break; // break;
} // }
} // }
if (bAlreadyLinked) // if (bAlreadyLinked)
continue; // continue;
// needs a new reverse link if got to here // needs a new reverse link if got to here
TRoom_MakeOppositePortal(portal_orig, iRoomNum); 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(); LPortal &new_port = *nroom.m_Portals.request();
new_port.m_szName = orig_lroom.m_szName; new_port.m_szName = orig_lroom.m_szName;
new_port.m_iRoomNum = iRoomOrig; new_port.m_iRoomNum = iRoomOrig;
new_port.m_bMirror = true;
// the portal vertices should be the same but reversed (to flip the normal) // the portal vertices should be the same but reversed (to flip the normal)
new_port.CopyReversedGeometry(port); new_port.CopyReversedGeometry(port);

View File

@ -30,8 +30,8 @@ LRoomManager::LRoomManager()
m_uiFrameCounter = 0; m_uiFrameCounter = 0;
// to know which rooms to hide we keep track of which were shown this, and the previous frame // 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_pCurr_VisibleRoomList = &m_VisibleRoomList_A;
m_pPrev_VisibleRoomList = &m_VisibleRoomList[1]; m_pPrev_VisibleRoomList = &m_VisibleRoomList_B;
} }
int LRoomManager::FindClosestRoom(const Vector3 &pt) const 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()); print_line("register_dob " + pDOB->get_name());
@ -139,7 +139,11 @@ void LRoomManager::dob_register(Node * pDOB)
if (!pRoom) if (!pRoom)
return; 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 // save the room ID on the dob metadata
Obj_SetRoomNum(pSpat, iRoomNum); 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 // remove from the list in old room and add to list in new room, and change the metadata
int iRoomNum = pNewRoom->m_RoomID; int iRoomNum = pNewRoom->m_RoomID;
pRoom->DOB_Remove(pDOB); // get dob data to move to new room
pNewRoom->DOB_Add(pSpat); 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 // save the room ID on the dob metadata
Obj_SetRoomNum(pSpat, iRoomNum); Obj_SetRoomNum(pSpat, iRoomNum);
@ -186,7 +200,13 @@ bool LRoomManager::dob_teleport(Node * pDOB)
void LRoomManager::dob_unregister(Node * pDOB) void LRoomManager::dob_unregister(Node * pDOB)
{ {
LRoom * pRoom = GetRoomFromDOB(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) int LRoomManager::dob_get_room_id(Node * pDOB)
@ -316,7 +336,7 @@ void LRoomManager::FrameUpdate()
{ {
if (!m_BF_visible_rooms.GetBit(n)) if (!m_BF_visible_rooms.GetBit(n))
{ {
m_Rooms[n].GetGodotRoom()->hide(); m_Rooms[n].Hide_All();
} }
} }
} }
@ -328,14 +348,29 @@ void LRoomManager::FrameUpdate()
int r = (*m_pPrev_VisibleRoomList)[n]; int r = (*m_pPrev_VisibleRoomList)[n];
if (!m_BF_visible_rooms.GetBit(r)) if (!m_BF_visible_rooms.GetBit(r))
m_Rooms[r].GetGodotRoom()->hide(); m_Rooms[r].Hide_All();
}
}
// 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 // swap the current and previous visible room list
LVector<int> * pTemp = m_pCurr_VisibleRoomList; LVector<int> * pTemp = m_pCurr_VisibleRoomList;
m_pCurr_VisibleRoomList = m_pPrev_VisibleRoomList; m_pCurr_VisibleRoomList = m_pPrev_VisibleRoomList;
m_pPrev_VisibleRoomList = pTemp; m_pPrev_VisibleRoomList = pTemp;
}
// hide all the DOB
// when running, emit less debugging output so as not to choke the IDE // when running, emit less debugging output so as not to choke the IDE
LPortal::m_bRunning = true; 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 // 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; 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_pCurr_VisibleRoomList;
LVector<int> * m_pPrev_VisibleRoomList; LVector<int> * m_pPrev_VisibleRoomList;
@ -71,7 +73,7 @@ public:
// These are defined by their ability to move from room to room. // 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) // You can still move static objects within the same room (e.g. elevators, moving platforms)
// as these don't require checks for changing rooms. // 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); void dob_unregister(Node * pDOB);
bool dob_update(Node * pDOB); bool dob_update(Node * pDOB);
bool dob_teleport(Node * pDOB); bool dob_teleport(Node * pDOB);

View File

@ -21,7 +21,7 @@
// SOFTWARE. // 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 "core/vector.h"
#include <assert.h> #include <assert.h>
#include <vector> #include <vector>
@ -31,6 +31,7 @@ template <class T> class LVector
public: public:
// array subscript access // array subscript access
// note this is not available in Godot Vector
T& operator[](unsigned int ui) T& operator[](unsigned int ui)
{ {
assert (ui < m_iSize); assert (ui < m_iSize);
@ -83,6 +84,14 @@ public:
m_Vec[ui] = t; 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() T * request()
{ {
m_iSize++; m_iSize++;