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]); Vector3 ptWorld = trans.xform(p_vertices[n]);
m_ptsWorld.set(n, ptWorld); m_ptsWorld.set(n, ptWorld);
m_ptCentre += ptWorld;
print("\t\t" + itos(n) + "\tLocal : " + Variant(p_vertices[n]) + "\tWorld : " + ptWorld); print("\t\t" + itos(n) + "\tLocal : " + Variant(p_vertices[n]) + "\tWorld : " + ptWorld);
} }
@ -166,6 +167,7 @@ void LPortal::SortVertsClockwise()
ptCentre += verts[n]; ptCentre += verts[n];
} }
ptCentre /= nPoints; ptCentre /= nPoints;
m_ptCentre = ptCentre;
// now algorithm // now algorithm
@ -238,6 +240,7 @@ void LPortal::CopyReversedGeometry(const LPortal &source)
print("CopyReversedGeometry"); print("CopyReversedGeometry");
// 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_ptsWorld.resize(nPoints); m_ptsWorld.resize(nPoints);
@ -268,6 +271,7 @@ void LPortal::PlaneFromPoints()
LPortal::LPortal() { LPortal::LPortal() {
// unset // unset
m_iRoomNum = -1; m_iRoomNum = -1;
// m_uiFrameTouched_Blocked = 0;
} }

View File

@ -54,8 +54,12 @@ public:
// normal determined by winding order // normal determined by winding order
Vector<Vector3> m_ptsWorld; Vector<Vector3> m_ptsWorld;
Vector3 m_ptCentre; // world
Plane m_Plane; Plane m_Plane;
// frame counter when last touched .. prevents going backward through portals
//unsigned int m_uiFrameTouched_Blocked;
LPortal(); LPortal();
void CopyReversedGeometry(const LPortal &source); 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; LDob dob;
dob.m_ID = pDOB->get_instance_id(); dob.m_ID = pDOB->get_instance_id();
@ -60,7 +60,7 @@ void LRoom::AddDOB(Spatial * pDOB)
m_DOBs.push_back(dob); m_DOBs.push_back(dob);
} }
bool LRoom::RemoveDOB(Node * pDOB) bool LRoom::DOB_Remove(Node * pDOB)
{ {
ObjectID id = pDOB->get_instance_id(); 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 // 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 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, // 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! // 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) void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &planes, int portalID_from)
{ {
// prevent too much depth // prevent too much depth
@ -125,13 +150,7 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
// first touch // first touch
if (m_uiFrameTouched < manager.m_uiFrameCounter) if (m_uiFrameTouched < manager.m_uiFrameCounter)
{ FirstTouch(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);
}
// show this room and add to visible list of rooms // show this room and add to visible list of rooms
GetGodotRoom()->show(); GetGodotRoom()->show();
@ -178,8 +197,8 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
if (bShow) if (bShow)
pObj->show(); pObj->show();
else // else
pObj->hide(); // pObj->hide();
} }
} }
@ -202,17 +221,25 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
if (pLinkedRoom->m_uiFrameTouched == manager.m_uiFrameCounter) if (pLinkedRoom->m_uiFrameTouched == manager.m_uiFrameCounter)
continue; continue;
// const Vector3 &portal_normal = pPortal->m_Plane.normal; // cull by portal angle to camera.
// print("\ttesting portal " + pPortal->get_name() + " normal " + portal_normal); // 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); // float dot = cam.m_ptDir.dot(portal_normal);
// if (dot <= -0.0f) // 0.0 if (dot <= -0.0f) // 0.0
// { {
// Variant vd = dot; 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(vd)); continue;
// continue; }
// }
// is it culled by the planes? // is it culled by the planes?
LPortal::eClipResult overall_res = LPortal::eClipResult::CLIP_INSIDE; 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 // add the planes for the portal
port.AddPlanes(cam.m_ptPos, new_planes); port.AddPlanes(cam.m_ptPos, new_planes);
if (pLinkedRoom) if (pLinkedRoom)
pLinkedRoom->DetermineVisibility_Recursive(manager, depth + 1, cam, new_planes, port_id); pLinkedRoom->DetermineVisibility_Recursive(manager, depth + 1, cam, new_planes, port_id);

View File

@ -85,11 +85,12 @@ public:
protected: protected:
// main function // main function
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 AddDOB(Spatial * pDOB); void DOB_Add(Spatial * pDOB);
bool RemoveDOB(Node * pDOB); bool DOB_Remove(Node * pDOB);
LRoom * UpdateDOB(LRoomManager &manager, Spatial * pDOB); LRoom * DOB_Update(LRoomManager &manager, Spatial * pDOB);
public: public:
LRoom(); 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()); print_line("register_dob " + pDOB->get_name());
@ -139,14 +139,14 @@ void LRoomManager::register_dob(Node * pDOB)
if (!pRoom) if (!pRoom)
return; return;
pRoom->AddDOB(pSpat); pRoom->DOB_Add(pSpat);
// save the room ID on the dob metadata // save the room ID on the dob metadata
Obj_SetRoomNum(pSpat, iRoomNum); Obj_SetRoomNum(pSpat, iRoomNum);
} }
bool LRoomManager::update_dob(Node * pDOB) bool LRoomManager::dob_update(Node * pDOB)
{ {
// find the room the object is attached to // find the room the object is attached to
LRoom * pRoom = GetRoomFromDOB(pDOB); LRoom * pRoom = GetRoomFromDOB(pDOB);
@ -157,41 +157,56 @@ bool LRoomManager::update_dob(Node * pDOB)
if (!pSpat) if (!pSpat)
return false; return false;
// is it the camera? LRoom * pNewRoom = pRoom->DOB_Update(*this, pSpat);
//bool bCamera = pDOB->get_instance_id() == m_cameraID;
LRoom * pNewRoom = pRoom->UpdateDOB(*this, pSpat);
if (pNewRoom) if (pNewRoom)
{ {
// 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->RemoveDOB(pDOB); pRoom->DOB_Remove(pDOB);
pNewRoom->AddDOB(pSpat); pNewRoom->DOB_Add(pSpat);
// save the room ID on the dob metadata // save the room ID on the dob metadata
Obj_SetRoomNum(pSpat, iRoomNum); Obj_SetRoomNum(pSpat, iRoomNum);
return true;
} }
return false; return false;
} }
bool LRoomManager::teleport_dob(Node * pDOB) bool LRoomManager::dob_teleport(Node * pDOB)
{ {
return true; return true;
} }
void LRoomManager::unregister_dob(Node * pDOB) void LRoomManager::dob_unregister(Node * pDOB)
{ {
LRoom * pRoom = GetRoomFromDOB(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; m_cameraID = 0;
@ -212,7 +227,7 @@ void LRoomManager::set_camera(Node * pCam)
} }
// convert empties and meshes to rooms and portals // convert empties and meshes to rooms and portals
void LRoomManager::convert() void LRoomManager::rooms_convert()
{ {
LRoomConverter conv; LRoomConverter conv;
conv.Convert(*this); conv.Convert(*this);
@ -347,14 +362,17 @@ void LRoomManager::_notification(int p_what) {
void LRoomManager::_bind_methods() void LRoomManager::_bind_methods()
{ {
// main functions // main functions
ClassDB::bind_method(D_METHOD("rooms_convert"), &LRoomManager::convert); ClassDB::bind_method(D_METHOD("rooms_convert"), &LRoomManager::rooms_convert);
ClassDB::bind_method(D_METHOD("rooms_set_camera"), &LRoomManager::set_camera); 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 // 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 // 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 // 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_register"), &LRoomManager::dob_register);
ClassDB::bind_method(D_METHOD("dob_unregister"), &LRoomManager::unregister_dob); ClassDB::bind_method(D_METHOD("dob_unregister"), &LRoomManager::dob_unregister);
ClassDB::bind_method(D_METHOD("dob_update"), &LRoomManager::update_dob); ClassDB::bind_method(D_METHOD("dob_update"), &LRoomManager::dob_update);
ClassDB::bind_method(D_METHOD("dob_teleport"), &LRoomManager::teleport_dob); 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(); LRoomManager();
// convert empties and meshes to rooms and portals // convert empties and meshes to rooms and portals
void convert(); void rooms_convert();
// choose which camera you want to use to determine visibility. // choose which camera you want to use to determine visibility.
// normally this will be your main camera, but you can choose another for debugging // 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 // Dynamic objects .. cameras, players, boxes etc
// 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 register_dob(Node * pDOB); void dob_register(Node * pDOB);
void unregister_dob(Node * pDOB); void dob_unregister(Node * pDOB);
bool update_dob(Node * pDOB); bool dob_update(Node * pDOB);
bool teleport_dob(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: protected: