From 9e7b392651825fbb7305450255082166446030ff Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Tue, 24 Sep 2019 15:37:38 +0100 Subject: [PATCH] Culling via layers Changed culling to via the Godot layers mechanism, as a hack to allow shadows. --- ldob.cpp | 17 ++++- ldob.h | 5 +- lroom.cpp | 177 ++++++++++++++++++++++++++++++++++------------ lroom.h | 24 +++++-- lroom_manager.cpp | 67 ++++++++++++++++-- lroom_manager.h | 2 + 6 files changed, 237 insertions(+), 55 deletions(-) diff --git a/ldob.cpp b/ldob.cpp index a032375..ee5e83e 100644 --- a/ldob.cpp +++ b/ldob.cpp @@ -34,11 +34,26 @@ Spatial * LSob::GetSpatial() const } +VisualInstance * LSob::GetVI() const +{ + Object * pObj = ObjectDB::get_instance(m_ID); + VisualInstance * pVI = Object::cast_to(pObj); + return pVI; +} + + Spatial * LDob::GetSpatial() const { - Object * pObj = ObjectDB::get_instance(m_ID); + Object * pObj = ObjectDB::get_instance(m_ID_Spatial); Spatial * pSpat = Object::cast_to(pObj); return pSpat; } +VisualInstance * LDob::GetVI() const +{ + Object * pObj = ObjectDB::get_instance(m_ID_VI); + VisualInstance * pVI = Object::cast_to(pObj); + return pVI; +} + diff --git a/ldob.h b/ldob.h index cfabf2f..d1c3613 100644 --- a/ldob.h +++ b/ldob.h @@ -34,6 +34,7 @@ class LSob { public: Spatial * GetSpatial() const; + VisualInstance * GetVI() const; ObjectID m_ID; // godot object AABB m_aabb; // world space @@ -45,8 +46,10 @@ class LDob { public: Spatial * GetSpatial() const; + VisualInstance * GetVI() const; - ObjectID m_ID; + ObjectID m_ID_Spatial; + ObjectID m_ID_VI; bool m_bVisible; float m_fRadius; }; diff --git a/lroom.cpp b/lroom.cpp index 3eed00b..3ea882c 100644 --- a/lroom.cpp +++ b/lroom.cpp @@ -32,6 +32,7 @@ LRoom::LRoom() { m_uiFrameTouched = 0; m_iFirstPortal = 0; m_iNumPortals = 0; + m_bVisible = true; } @@ -63,7 +64,7 @@ unsigned int LRoom::DOB_Find(Node * pDOB) const for (int n=0; nget_layer_mask(); + uint32_t orig_mask = mask; + + const int SOFT_SHOW_MASK = 1 << SOFT_SHOW_BIT; + const int SOFT_HIDE_MASK = 1 << SOFT_HIDE_BIT; + + if (bShow) + { + // set + mask |= SOFT_SHOW_MASK; + // clear + mask &= ~(1 | SOFT_HIDE_MASK); + } + else + { + // set + mask |= SOFT_HIDE_MASK; + // clear + mask &= ~(1 | SOFT_SHOW_MASK); + } + + + // noop? don't touch the visual server if no change to mask + if (mask == orig_mask) + return; + + pVI->set_layer_mask(mask); + +// pVI->set_layer_mask_bit(0, false); +// pVI->set_layer_mask_bit(SOFT_HIDE_BIT, bShow == false); +// pVI->set_layer_mask_bit(SOFT_SHOW_BIT, bShow); +} + + // 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) @@ -128,14 +172,15 @@ void LRoom::FinalizeVisibility(LRoomManager &manager) for (int n=0; nshow(); - else - pS->hide(); + SoftShow(pVI, sob.m_bVisible); +// if (sob.m_bVisible) +// pVI->show(); +// else +// pVI->hide(); } } @@ -144,57 +189,99 @@ void LRoom::FinalizeVisibility(LRoomManager &manager) const LDob &dob = m_DOBs[n]; // don't cull the main camera - if (dob.m_ID == manager.m_ID_camera) + if (dob.m_ID_Spatial == manager.m_ID_camera) continue; - Spatial * pS = dob.GetSpatial(); - if (pS) +// Spatial * pSpat = dob.GetSpatial(); +// if (pSpat) +// { +// // all should be showing .. this is mostly a no op +// pSpat->show(); +// } + + VisualInstance * pVI = dob.GetVI(); + if (pVI) { - if (dob.m_bVisible) - { - //print("LRoom::FinalizeVisibility making visible dob " + pS->get_name()); - pS->show(); - } - else - pS->hide(); + SoftShow(pVI, dob.m_bVisible); +// 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() +// allows us to show / hide all dobs as the room visibility changes +void LRoom::Room_MakeVisible(bool bVisible) { - GetGodotRoom()->hide(); + // noop + if (bVisible == m_bVisible) + return; - for (int n=0; nhide(); + // show room + GetGodotRoom()->show(); + + // show all dobs + for (int n=0; nshow(); + } + } + else + { + // hide room + GetGodotRoom()->hide(); + + // hide all dobs + for (int n=0; nhide(); + } } } + +// hide godot room and all linked dobs +//void LRoom::Hide_All() +//{ +// GetGodotRoom()->hide(); + +// for (int n=0; nhide(); +// } +//} + // show godot room and all linked dobs and all sobs -void LRoom::Show_All() +void LRoom::Debug_ShowAll() { - GetGodotRoom()->show(); + Room_MakeVisible(true); - for (int n=0; nshow(); - } + // NYI .. change layers to all be visible +// for (int n=0; nshow(); +// } - for (int n=0; nshow(); - } } @@ -203,6 +290,11 @@ void LRoom::FirstTouch(LRoomManager &manager) // set the frame counter m_uiFrameTouched = manager.m_uiFrameCounter; + // show this room and add to visible list of rooms + Room_MakeVisible(true); + + manager.m_BF_visible_rooms.SetBit(m_RoomID, true); + // keep track of which rooms are shown this frame manager.m_pCurr_VisibleRoomList->push_back(m_RoomID); @@ -238,9 +330,6 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons if (m_uiFrameTouched < manager.m_uiFrameCounter) FirstTouch(manager); - // show this room and add to visible list of rooms - GetGodotRoom()->show(); - manager.m_BF_visible_rooms.SetBit(m_RoomID, true); #define LPORTAL_CULL_STATIC #ifdef LPORTAL_CULL_STATIC diff --git a/lroom.h b/lroom.h index 0facb3a..12e3512 100644 --- a/lroom.h +++ b/lroom.h @@ -54,6 +54,8 @@ class LRoom private: public: + static const int SOFT_SHOW_BIT = 18; + static const int SOFT_HIDE_BIT = 19; // static objects LVector m_SOBs; @@ -81,7 +83,6 @@ public: // when registering DOBs and teleporting them LBound m_Bound; - String m_szName; //////////////////////////////////////////////////////////// @@ -91,13 +92,16 @@ public: void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, int portalID_from = -1); void FirstTouch(LRoomManager &manager); + + // allows us to show / hide all dobs as the room visibility changes + void Room_MakeVisible(bool bVisible); + // hide godot room and all linked dobs // USED AT RUNTIME - void Hide_All(); +// void Hide_All(); // show godot room and all linked dobs and all sobs - // ONLY USED IN DEBUGGING to turn LPortal on and off - void Show_All(); + void Debug_ShowAll(); // hide all the objects not hit on this frame .. instead of calling godot hide without need // (it might be expensive) @@ -115,6 +119,18 @@ public: // retained purely for debugging visualization Geometry::MeshData m_Bound_MeshData; + + bool IsVisible() const {return m_bVisible;} +private: + // instead of directly showing and hiding objects we now set their layer, + // and the camera will hide them with a cull mask. This is so that + // objects can still be rendered outside immediate view for casting shadows. + void SoftShow(VisualInstance * pVI, bool bShow) const; + + // whether lportal thinks this room is currently visible + // this allows us to show / hide dobs as they cross room boundaries + bool m_bVisible; + }; diff --git a/lroom_manager.cpp b/lroom_manager.cpp index 69b6521..b78fb35 100644 --- a/lroom_manager.cpp +++ b/lroom_manager.cpp @@ -25,6 +25,7 @@ #include "lroom_converter.h" #include "ldebug.h" #include "scene/3d/immediate_geometry.h" +#include "lroom.h" LRoomManager::LRoomManager() { @@ -224,6 +225,24 @@ void LRoomManager::CreateDebug() } +ObjectID LRoomManager::DobRegister_FindVIRecursive(Node * pNode) const +{ + // is the node a VI? + VisualInstance * pVI = Object::cast_to(pNode); + if (pVI) + return pVI->get_instance_id(); + + // try the children + for (int n=0; nget_child_count(); n++) + { + ObjectID res = DobRegister_FindVIRecursive(pNode->get_child(n)); + if (res) + return res; + } + + return 0; +} + bool LRoomManager::DobRegister(Spatial * pDOB, float radius, int iRoom) { //LPRINT(3, "register_dob " + pDOB->get_name()); @@ -238,14 +257,22 @@ bool LRoomManager::DobRegister(Spatial * pDOB, float radius, int iRoom) if (!pRoom) return false; + // The dob is derived from spatial, but the visual instances may be children of the dob + // rather than the node itself .. we need visual instances for layer culling for shadows LDob dob; - dob.m_ID = pDOB->get_instance_id(); + dob.m_ID_Spatial = pDOB->get_instance_id(); dob.m_fRadius = radius; + dob.m_ID_VI = DobRegister_FindVIRecursive(pDOB); + pRoom->DOB_Add(dob); // save the room ID on the dob metadata Obj_SetRoomNum(pDOB, iRoom); + + // change visibility + DobChangeVisibility(pDOB, 0, pRoom); + return true; } @@ -305,7 +332,8 @@ int LRoomManager::dob_update(Node * pDOB) // remove from old room pRoom->DOB_Remove(dob_id); - + // change visibility + DobChangeVisibility(pSpat, pRoom, pNewRoom); // save the room ID on the dob metadata Obj_SetRoomNum(pSpat, iRoomNum); @@ -383,6 +411,9 @@ bool LRoomManager::DobTeleport(Spatial * pDOB, int iNewRoomID) // save the room ID on the dob metadata Obj_SetRoomNum(pDOB, iNewRoomID); + // change visibility + DobChangeVisibility(pDOB, pOldRoom, pNewRoom); + return true; } @@ -420,6 +451,29 @@ bool LRoomManager::dob_unregister(Node * pDOB) return false; } +void LRoomManager::DobChangeVisibility(Spatial * pDOB, const LRoom * pOld, const LRoom * pNew) +{ + bool bVisOld = false; + bool bVisNew = false; + + if (pOld) + bVisOld = pOld->IsVisible(); + + if (pNew) + bVisNew = pNew->IsVisible(); + + + if (bVisOld != bVisNew) + { + if (!bVisOld) + pDOB->show(); + else + pDOB->hide(); + } + +} + + int LRoomManager::dob_get_room_id(Node * pDOB) { return Obj_GetRoomNum(pDOB); @@ -486,7 +540,7 @@ void LRoomManager::rooms_set_active(bool bActive) for (int n=0; nget_instance_id(); + // new .. select the cull layer + pCamera->set_cull_mask_bit(LRoom::SOFT_HIDE_BIT, false); + // use this temporarily to force debug // rooms_log_frame(); } @@ -637,7 +694,7 @@ void LRoomManager::FrameUpdate() { if (!m_BF_visible_rooms.GetBit(n)) { - m_Rooms[n].Hide_All(); + m_Rooms[n].Room_MakeVisible(false); } } } @@ -649,7 +706,7 @@ void LRoomManager::FrameUpdate() int r = (*m_pPrev_VisibleRoomList)[n]; if (!m_BF_visible_rooms.GetBit(r)) - m_Rooms[r].Hide_All(); + m_Rooms[r].Room_MakeVisible(false); } } diff --git a/lroom_manager.h b/lroom_manager.h index 940d6cd..7f19884 100644 --- a/lroom_manager.h +++ b/lroom_manager.h @@ -125,8 +125,10 @@ protected: private: // internal bool DobRegister(Spatial * pDOB, float radius, int iRoom); + ObjectID DobRegister_FindVIRecursive(Node * pNode) const; bool DobTeleport(Spatial * pDOB, int iNewRoomID); void CreateDebug(); + void DobChangeVisibility(Spatial * pDOB, const LRoom * pOld, const LRoom * pNew); // helper funcs