Allow multiportal views

Multiple portals can view into a room.
Added functions for querying current room of DOB.
This commit is contained in:
lawnjelly 2019-09-15 19:26:18 +01:00 committed by GitHub
parent 4fa3991280
commit 7cad808ebe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 110 additions and 51 deletions

View File

@ -139,6 +139,7 @@ void LPortal::CreateGeometry(PoolVector<Vector3> 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;
}

View File

@ -54,8 +54,12 @@ public:
// normal determined by winding order
Vector<Vector3> 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);

View File

@ -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<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);
if (pObj)
pObj->hide();
}
}
void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &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);

View File

@ -85,11 +85,12 @@ public:
protected:
// main function
void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &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();

View File

@ -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);
}

View File

@ -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: