From 7cad808ebe723c8afd1a00be357b6d50afb89bad Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Sun, 15 Sep 2019 19:26:18 +0100 Subject: [PATCH] Allow multiportal views Multiple portals can view into a room. Added functions for querying current room of DOB. --- lportal.cpp | 4 +++ lportal.h | 4 +++ lroom.cpp | 72 ++++++++++++++++++++++++++++++++--------------- lroom.h | 7 +++-- lroom_manager.cpp | 58 +++++++++++++++++++++++++------------- lroom_manager.h | 16 +++++++---- 6 files changed, 110 insertions(+), 51 deletions(-) diff --git a/lportal.cpp b/lportal.cpp index 71320f1..98e2448 100644 --- a/lportal.cpp +++ b/lportal.cpp @@ -139,6 +139,7 @@ void LPortal::CreateGeometry(PoolVector p_vertices, const Transform &tr { Vector3 ptWorld = trans.xform(p_vertices[n]); m_ptsWorld.set(n, ptWorld); + m_ptCentre += ptWorld; print("\t\t" + itos(n) + "\tLocal : " + Variant(p_vertices[n]) + "\tWorld : " + ptWorld); } @@ -166,6 +167,7 @@ void LPortal::SortVertsClockwise() ptCentre += verts[n]; } ptCentre /= nPoints; + m_ptCentre = ptCentre; // now algorithm @@ -238,6 +240,7 @@ void LPortal::CopyReversedGeometry(const LPortal &source) print("CopyReversedGeometry"); // points are the same but reverse winding order int nPoints = source.m_ptsWorld.size(); + m_ptCentre = source.m_ptCentre; m_ptsWorld.resize(nPoints); @@ -268,6 +271,7 @@ void LPortal::PlaneFromPoints() LPortal::LPortal() { // unset m_iRoomNum = -1; +// m_uiFrameTouched_Blocked = 0; } diff --git a/lportal.h b/lportal.h index 17d2bd4..a1b7e7b 100644 --- a/lportal.h +++ b/lportal.h @@ -54,8 +54,12 @@ public: // normal determined by winding order Vector m_ptsWorld; + Vector3 m_ptCentre; // world Plane m_Plane; + // frame counter when last touched .. prevents going backward through portals + //unsigned int m_uiFrameTouched_Blocked; + LPortal(); void CopyReversedGeometry(const LPortal &source); diff --git a/lroom.cpp b/lroom.cpp index 9b128d3..a57d96f 100644 --- a/lroom.cpp +++ b/lroom.cpp @@ -52,7 +52,7 @@ Spatial * LRoom::GetGodotRoom() const -void LRoom::AddDOB(Spatial * pDOB) +void LRoom::DOB_Add(Spatial * pDOB) { LDob dob; dob.m_ID = pDOB->get_instance_id(); @@ -60,7 +60,7 @@ void LRoom::AddDOB(Spatial * pDOB) m_DOBs.push_back(dob); } -bool LRoom::RemoveDOB(Node * pDOB) +bool LRoom::DOB_Remove(Node * pDOB) { ObjectID id = pDOB->get_instance_id(); @@ -78,11 +78,15 @@ bool LRoom::RemoveDOB(Node * pDOB) // returns -1 if no change, or the linked room we are moving into -LRoom * LRoom::UpdateDOB(LRoomManager &manager, Spatial * pDOB) +LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB) { const Vector3 &pt = pDOB->get_global_transform().origin; - const float slop = 0.2f; + // is it the camera? + bool bCamera = pDOB->get_instance_id() == manager.m_cameraID; + float slop = 0.2f; + if (bCamera) + slop = 0.0f; // the camera can't have slop because we might end up front side of a door without entering the room, // hence can't see into the room through the portal! @@ -109,6 +113,27 @@ LRoom * LRoom::UpdateDOB(LRoomManager &manager, Spatial * pDOB) } +void LRoom::FirstTouch(LRoomManager &manager) +{ + // set the frame counter + m_uiFrameTouched = manager.m_uiFrameCounter; + + // keep track of which rooms are shown this frame + manager.m_pCurr_VisibleRoomList->push_back(m_RoomID); + + // hide all objects + for (int n=0; n(pNode); + + if (pObj) + pObj->hide(); + } +} + + void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, int portalID_from) { // prevent too much depth @@ -125,13 +150,7 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons // first touch if (m_uiFrameTouched < manager.m_uiFrameCounter) - { - // set the frame counter - m_uiFrameTouched = manager.m_uiFrameCounter; - - // keep track of which rooms are shown this frame - manager.m_pCurr_VisibleRoomList->push_back(m_RoomID); - } + FirstTouch(manager); // show this room and add to visible list of rooms GetGodotRoom()->show(); @@ -178,8 +197,8 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons if (bShow) pObj->show(); - else - pObj->hide(); +// else +// pObj->hide(); } } @@ -202,17 +221,25 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons if (pLinkedRoom->m_uiFrameTouched == manager.m_uiFrameCounter) continue; -// const Vector3 &portal_normal = pPortal->m_Plane.normal; -// print("\ttesting portal " + pPortal->get_name() + " normal " + portal_normal); + // 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; + print("\ttesting portal " + port.get_name() + " normal " + portal_normal); + + // 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) + Vector3 dir_portal = port.m_ptCentre - cam.m_ptPos; + + // doesn't actually need to be normalized? + float dot = dir_portal.dot(portal_normal); - // direction with the camera? (might not need to check) // float dot = cam.m_ptDir.dot(portal_normal); -// if (dot <= -0.0f) // 0.0 -// { -// Variant vd = dot; -// print("\t\tportal culled (wrong direction) dot is " + String(vd)); -// continue; -// } + if (dot <= -0.0f) // 0.0 + { + print("\t\tportal culled (wrong direction) dot is " + String(Variant(dot)) + ", dir_portal is " + dir_portal); + continue; + } // is it culled by the planes? LPortal::eClipResult overall_res = LPortal::eClipResult::CLIP_INSIDE; @@ -259,6 +286,7 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons // add the planes for the portal port.AddPlanes(cam.m_ptPos, new_planes); + if (pLinkedRoom) pLinkedRoom->DetermineVisibility_Recursive(manager, depth + 1, cam, new_planes, port_id); diff --git a/lroom.h b/lroom.h index 7cfbf83..53ab8c8 100644 --- a/lroom.h +++ b/lroom.h @@ -85,11 +85,12 @@ public: protected: // main function void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, int portalID_from = -1); + void FirstTouch(LRoomManager &manager); - void AddDOB(Spatial * pDOB); - bool RemoveDOB(Node * pDOB); - LRoom * UpdateDOB(LRoomManager &manager, Spatial * pDOB); + void DOB_Add(Spatial * pDOB); + bool DOB_Remove(Node * pDOB); + LRoom * DOB_Update(LRoomManager &manager, Spatial * pDOB); public: LRoom(); diff --git a/lroom_manager.cpp b/lroom_manager.cpp index 50ee101..7db9cab 100644 --- a/lroom_manager.cpp +++ b/lroom_manager.cpp @@ -119,7 +119,7 @@ LRoom * LRoomManager::GetRoomFromDOB(Node * pNode) } -void LRoomManager::register_dob(Node * pDOB) +void LRoomManager::dob_register(Node * pDOB) { print_line("register_dob " + pDOB->get_name()); @@ -139,14 +139,14 @@ void LRoomManager::register_dob(Node * pDOB) if (!pRoom) return; - pRoom->AddDOB(pSpat); + pRoom->DOB_Add(pSpat); // save the room ID on the dob metadata Obj_SetRoomNum(pSpat, iRoomNum); } -bool LRoomManager::update_dob(Node * pDOB) +bool LRoomManager::dob_update(Node * pDOB) { // find the room the object is attached to LRoom * pRoom = GetRoomFromDOB(pDOB); @@ -157,41 +157,56 @@ bool LRoomManager::update_dob(Node * pDOB) if (!pSpat) return false; - // is it the camera? - //bool bCamera = pDOB->get_instance_id() == m_cameraID; - - LRoom * pNewRoom = pRoom->UpdateDOB(*this, pSpat); + LRoom * pNewRoom = pRoom->DOB_Update(*this, pSpat); if (pNewRoom) { // remove from the list in old room and add to list in new room, and change the metadata int iRoomNum = pNewRoom->m_RoomID; - pRoom->RemoveDOB(pDOB); - pNewRoom->AddDOB(pSpat); + pRoom->DOB_Remove(pDOB); + pNewRoom->DOB_Add(pSpat); // save the room ID on the dob metadata Obj_SetRoomNum(pSpat, iRoomNum); + + return true; } return false; } -bool LRoomManager::teleport_dob(Node * pDOB) +bool LRoomManager::dob_teleport(Node * pDOB) { return true; } -void LRoomManager::unregister_dob(Node * pDOB) +void LRoomManager::dob_unregister(Node * pDOB) { LRoom * pRoom = GetRoomFromDOB(pDOB); - pRoom->RemoveDOB(pDOB); + pRoom->DOB_Remove(pDOB); +} + +int LRoomManager::dob_get_room_id(Node * pDOB) +{ + return Obj_GetRoomNum(pDOB); +} + +Node * LRoomManager::rooms_get_room(int room_id) +{ + const LRoom * pRoom = GetRoom(room_id); + + if (!pRoom) + return NULL; + + return pRoom->GetGodotRoom(); } -void LRoomManager::set_camera(Node * pCam) + +void LRoomManager::rooms_set_camera(Node * pCam) { m_cameraID = 0; @@ -212,7 +227,7 @@ void LRoomManager::set_camera(Node * pCam) } // convert empties and meshes to rooms and portals -void LRoomManager::convert() +void LRoomManager::rooms_convert() { LRoomConverter conv; conv.Convert(*this); @@ -347,14 +362,17 @@ void LRoomManager::_notification(int p_what) { void LRoomManager::_bind_methods() { // main functions - ClassDB::bind_method(D_METHOD("rooms_convert"), &LRoomManager::convert); - ClassDB::bind_method(D_METHOD("rooms_set_camera"), &LRoomManager::set_camera); + ClassDB::bind_method(D_METHOD("rooms_convert"), &LRoomManager::rooms_convert); + ClassDB::bind_method(D_METHOD("rooms_set_camera"), &LRoomManager::rooms_set_camera); + ClassDB::bind_method(D_METHOD("rooms_get_room"), &LRoomManager::rooms_get_room); // functions to add dynamic objects to the culling system // Note that these should not be placed directly in rooms, the system will 'soft link' to them // so they can be held, e.g. in pools elsewhere in the scene graph - ClassDB::bind_method(D_METHOD("dob_register"), &LRoomManager::register_dob); - ClassDB::bind_method(D_METHOD("dob_unregister"), &LRoomManager::unregister_dob); - ClassDB::bind_method(D_METHOD("dob_update"), &LRoomManager::update_dob); - ClassDB::bind_method(D_METHOD("dob_teleport"), &LRoomManager::teleport_dob); + ClassDB::bind_method(D_METHOD("dob_register"), &LRoomManager::dob_register); + ClassDB::bind_method(D_METHOD("dob_unregister"), &LRoomManager::dob_unregister); + ClassDB::bind_method(D_METHOD("dob_update"), &LRoomManager::dob_update); + ClassDB::bind_method(D_METHOD("dob_teleport"), &LRoomManager::dob_teleport); + + ClassDB::bind_method(D_METHOD("dob_get_room_id"), &LRoomManager::dob_get_room_id); } diff --git a/lroom_manager.h b/lroom_manager.h index 2ba594e..9f9c722 100644 --- a/lroom_manager.h +++ b/lroom_manager.h @@ -61,20 +61,24 @@ public: LRoomManager(); // convert empties and meshes to rooms and portals - void convert(); + void rooms_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); + void rooms_set_camera(Node * pCam); // Dynamic objects .. cameras, players, boxes etc // 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 register_dob(Node * pDOB); - void unregister_dob(Node * pDOB); - bool update_dob(Node * pDOB); - bool teleport_dob(Node * pDOB); + void dob_register(Node * pDOB); + void dob_unregister(Node * pDOB); + bool dob_update(Node * pDOB); + bool dob_teleport(Node * pDOB); + + // supplementary functions available from script + int dob_get_room_id(Node * pDOB); + Node * rooms_get_room(int room_id); protected: