mirror of
https://github.com/Relintai/godot-lportal.git
synced 2024-11-11 10:52:09 +01:00
DOB visibility culling added
This commit is contained in:
parent
b7c5f74062
commit
2969fd4900
18
ldob.cpp
18
ldob.cpp
@ -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
8
ldob.h
@ -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;
|
||||||
};
|
};
|
||||||
|
32
lportal.cpp
32
lportal.cpp
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
194
lroom.cpp
@ -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
15
lroom.h
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
11
lvector.h
11
lvector.h
@ -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++;
|
||||||
|
Loading…
Reference in New Issue
Block a user