New API for dobs

To fix bug where get_global_transform doesn't work with dobs outside the tree, there is a new API
This commit is contained in:
lawnjelly 2020-04-02 13:36:53 +01:00 committed by GitHub
parent d6717de5ba
commit 18eac7e810
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 625 additions and 210 deletions

BIN
config.pyc Normal file

Binary file not shown.

View File

@ -24,7 +24,7 @@
// you won't be able to get frame debugging of the visibility tree though.
#ifdef DEBUG_ENABLED
#pragma message ("LPortal DEBUG_ENABLED")
#pragma message ("LPortal DEBUG_ENABLED, verbose mode")
#define LPRINT_RUN(a, b) {if (!Lawn::LDebug::m_bRunning) {String sz;\
for (int n=0; n<Lawn::LDebug::m_iTabDepth; n++)\
sz += "\t";\

View File

@ -117,6 +117,7 @@ void LLight::Light_SetDefaults()
m_Source.Source_SetDefaults();
m_GodotID = 0;
m_DOB_id = -1;
// m_eType = LT_DIRECTIONAL;
// m_eClass = LT_STATIC;
// m_fSpread = 0.0f; // for spotlight

9
ldob.h
View File

@ -69,10 +69,13 @@ public:
Spatial * GetSpatial() const;
VisualInstance * GetVI() const;
ObjectID m_ID_Spatial;
ObjectID m_ID_VI;
bool m_bSlotTaken;
bool m_bVisible;
float m_fRadius;
int m_iRoomID;
ObjectID m_ID_Spatial;
ObjectID m_ID_VI;
};
@ -129,6 +132,8 @@ public:
LSource m_Source;
ObjectID m_GodotID;
int m_DOB_id;
// shadow casters
int m_FirstCaster;
int m_NumCasters;

179
ldoblist.cpp Normal file
View File

@ -0,0 +1,179 @@
#include "ldoblist.h"
#include "lroom_manager.h"
#include "ldebug.h"
// returns whether changed room
bool LDobList::FindDOBOldAndNewRoom(LRoomManager &manager, int dob_id, const Vector3 &pos, int &old_room_id, int &new_room_id)
{
LDob &dob = GetDob(dob_id);
bool bCamera = (dob_id == manager.m_DOB_id_camera);
float slop = 0.2f;
if (bCamera)
slop = 0.0f;
else
{
// print_line("dob position : " + String(Variant(pt)));
}
// current room
old_room_id = dob.m_iRoomID;
new_room_id = old_room_id; // default
bool bChangedRoom = false;
LRoom * pCurrentRoom = 0;
if (old_room_id == -1)
bChangedRoom = true;
else
{
pCurrentRoom = manager.GetRoom(old_room_id);
// deal with the case that the DOB has moved way outside the room
if (!pCurrentRoom->m_Bound.IsPointWithin(pos, 1.0f))
bChangedRoom = true;
}
// if changed room definitely?
if (bChangedRoom)
{
// revert to expensive method (may have been teleported etc)
new_room_id = manager.FindClosestRoom(pos);
if (new_room_id != old_room_id)
return true;
else
return false;
}
assert (pCurrentRoom);
// check each portal - has the object crossed it into the neighbouring room?
for (int p=0; p<pCurrentRoom->m_iNumPortals; p++)
{
const LPortal &port = manager.m_Portals[pCurrentRoom->m_iFirstPortal + p];
float dist = port.m_Plane.distance_to(pos);
if (dist > slop)
{
LPRINT(0, "DOB at pos " + pos + " ahead of portal " + port.get_name() + " by " + String(Variant(dist)));
new_room_id = manager.Portal_GetLinkedRoom(port).m_RoomID;
return true;
}
}
return false;
}
void LDobList::UpdateVisibility(LRoomManager &manager, Spatial * pDOBSpatial, int dob_id)
{
LDob &dob = GetDob(dob_id);
// get the room
LRoom * pRoom = manager.GetRoom(dob.m_iRoomID);
bool bRoomVisible = pRoom->IsVisible();
Spatial * pDOB = pDOBSpatial;
bool bDobVis = pDOB->is_visible_in_tree();
if (bDobVis != bRoomVisible)
{
//String sz = "DOB " + pDOB->get_name() + "\t";
if (bRoomVisible)
{
pDOB->show();
//sz += "coming into view";
}
else
{
pDOB->hide();
//sz += "exiting view";
}
//print_line(sz);
}
}
int LDobList::UpdateDob(LRoomManager &manager, int dob_id, const Vector3 &pos)
{
LDob &dob = GetDob(dob_id);
// get the VI for showing / hiding
Spatial * pSpat = (Spatial *) dob.GetVI();
int old_room, new_room;
if (FindDOBOldAndNewRoom(manager, dob_id, pos, old_room, new_room))
{
dob.m_iRoomID = new_room;
}
if (dob_id != manager.m_DOB_id_camera)
UpdateVisibility(manager, pSpat, dob_id);
return dob.m_iRoomID;
}
/*
// get _global_transform DOES NOT WORK when detached from scene tree (or hidden)
const Vector3 &pt = pDOB->get_global_transform().origin;
// is it the camera?
bool bCamera = pDOB->get_instance_id() == manager.m_ID_camera;
float slop = 0.2f;
if (bCamera)
slop = 0.0f;
else
{
// print_line("dob position : " + String(Variant(pt)));
}
// deal with the case that the DOB has moved way outside the room
if (!m_Bound.IsPointWithin(pt, 1.0f))
{
// revert to expensive method (may have been teleported etc)
int iRoomNum = manager.FindClosestRoom(pt);
//print_line("dob_teleport closest room " + itos(iRoomNum));
if (iRoomNum == -1)
return 0;
// could be no change of room...
if (iRoomNum == m_RoomID)
return 0;
return manager.GetRoom(iRoomNum);
}
// 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!
// if (bCamera)
// slop = 0.0f;
// check each portal - has the object crossed it into the neighbouring room?
for (int p=0; p<m_iNumPortals; p++)
{
const LPortal &port = manager.m_Portals[m_iFirstPortal + p];
float dist = port.m_Plane.distance_to(pt);
if (dist > slop)
{
LPRINT(0, "DOB at pos " + pt + " ahead of portal " + port.get_name() + " by " + String(Variant(dist)));
// we want to move into the adjoining room
return &manager.Portal_GetLinkedRoom(port);
}
}
return 0;
*/

58
ldoblist.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include "lvector.h"
#include "ldob.h"
class LRoomManager;
class LDobList
{
public:
// getting
LDob &GetDob(int n) {return m_List[n];}
const LDob &GetDob(int n) const {return m_List[n];}
// request delete
int Request();
void DeleteDob(int id);
// funcs
int UpdateDob(LRoomManager &manager, int dob_id, const Vector3 &pos);
void UpdateVisibility(LRoomManager &manager, Spatial * pDOBSpatial, int dob_id);
private:
bool FindDOBOldAndNewRoom(LRoomManager &manager, int dob_id, const Vector3 &pos, int &old_room_id, int &new_room_id);
LVector<LDob> m_List;
};
/////////////////////////////////////////////////////////
inline void LDobList::DeleteDob(int id)
{
GetDob(id).m_bSlotTaken = false;
}
inline int LDobList::Request()
{
for (int n=0; n<m_List.size(); n++)
{
LDob &d = m_List[n];
if (d.m_bSlotTaken == false)
{
d.m_bSlotTaken = true;
return n;
}
}
// none found, create new
LDob * p = m_List.request();
memset(p, 0, sizeof (LDob));
p->m_bSlotTaken = true;
p->m_iRoomID = -1;
return m_List.size()-1;
}

View File

@ -7,13 +7,17 @@
#define LDEBUG_CAMERA
#define LDEBUG_LIGHTS
#define LDEBUG_LIGHT_AFFECTED_ROOMS
//#define LDEBUG_DOB_VISIBILITY
#define LPORTAL_DOBS_NO_SOFTSHOW
//#define LPORTAL_DOBS_AUTO_UPDATE
//#define LDEBUG_UNMERGE
// single compilation unit
#include "register_types.cpp"
#include "ldebug.cpp"
#include "ldoblist.cpp"
#include "lroom.cpp"
#include "lroom_manager.cpp"
#include "lroom_converter.cpp"

View File

@ -55,19 +55,19 @@ Spatial * LRoom::GetGodotRoom() const
}
void LRoom::DOB_Add(const LDob &dob)
/*
void LRoom::DOB_Add(int id)
{
m_DOBs.push_back(dob);
m_DOB_ids.push_back(id);
}
unsigned int LRoom::DOB_Find(Node * pDOB) const
unsigned int LRoom::DOB_Find(int id) const
{
ObjectID id = pDOB->get_instance_id();
// ObjectID id = pDOB->get_instance_id();
for (int n=0; n<m_DOBs.size(); n++)
for (int n=0; n<m_DOB_ids.size(); n++)
{
if (m_DOBs[n].m_ID_Spatial == id)
if (m_DOB_ids[n] == id)
{
return n;
}
@ -78,9 +78,9 @@ unsigned int LRoom::DOB_Find(Node * pDOB) const
bool LRoom::DOB_Remove(unsigned int ui)
{
if (ui < m_DOBs.size())
if (ui < m_DOB_ids.size())
{
m_DOBs.remove_unsorted(ui);
m_DOB_ids.remove_unsorted(ui);
return true;
}
@ -91,6 +91,7 @@ bool LRoom::DOB_Remove(unsigned int ui)
// returns -1 if no change, or the linked room we are moving into
LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
{
// get _global_transform DOES NOT WORK when detached from scene tree (or hidden)
const Vector3 &pt = pDOB->get_global_transform().origin;
// is it the camera?
@ -98,6 +99,10 @@ LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
float slop = 0.2f;
if (bCamera)
slop = 0.0f;
else
{
// print_line("dob position : " + String(Variant(pt)));
}
// deal with the case that the DOB has moved way outside the room
if (!m_Bound.IsPointWithin(pt, 1.0f))
@ -139,7 +144,7 @@ LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
return 0;
}
*/
// 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
@ -316,6 +321,7 @@ void LRoom::FinalizeVisibility(LRoomManager &manager)
//print_line("FinalizeVisibility room " + get_name() + " NumSOBs " + itos(m_SOBs.size()) + ", NumDOBs " + itos(m_DOBs.size()));
#ifndef LPORTAL_DOBS_NO_SOFTSHOW
for (int n=0; n<m_DOBs.size(); n++)
{
const LDob &dob = m_DOBs[n];
@ -350,22 +356,7 @@ void LRoom::FinalizeVisibility(LRoomManager &manager)
// pS->hide();
}
}
}
// call when releasing a level, this should unregister all dobs within all rooms
void LRoom::Release(LRoomManager &manager)
{
for (int n=0; n<m_DOBs.size(); n++)
{
LDob &dob = m_DOBs[n];
Spatial * pS = dob.GetSpatial();
if (pS)
{
// signifies released or unregistered
manager.Meta_SetRoomNum(pS, -2);
}
}
#endif
}
@ -390,6 +381,7 @@ void LRoom::Room_MakeVisible(bool bVisible)
m_bVisible = bVisible;
/*
if (m_bVisible)
{
// show room
@ -418,6 +410,7 @@ void LRoom::Room_MakeVisible(bool bVisible)
p->hide();
}
}
*/
}

15
lroom.h
View File

@ -58,7 +58,7 @@ public:
int m_iNumSOBs;
// dynamic objects
LVector<LDob> m_DOBs;
//LVector<uint32_t> m_DOB_ids;
// local lights affecting this room
LVector<int> m_LocalLights;
@ -105,9 +105,6 @@ public:
// allows us to show / hide all dobs as the room visibility changes
void Room_MakeVisible(bool bVisible);
// call when releasing a level, this should unregister all dobs within all rooms
void Release(LRoomManager &manager);
// show godot room and all linked dobs and all sobs
void Debug_ShowAll(bool bActive);
@ -118,11 +115,11 @@ public:
// naive version, adds all the non visible objects in visible rooms as shadow casters
void AddShadowCasters(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);
// void DOB_Add(int id);
// int DOB_GetID(unsigned int ui) const {return m_DOB_ids[ui];}
// unsigned int DOB_Find(int id) const;
// bool DOB_Remove(unsigned int ui);
// LRoom * DOB_Update(LRoomManager &manager, Spatial * pDOB);
LRoom();
Spatial * GetGodotRoom() const;

View File

@ -336,7 +336,7 @@ bool LRoomConverter::Convert_Room(Spatial * pNode, int lroomID, int areaID)
// save the room ID on the godot room metadata
// This is used when registering DOBs and teleporting them with hints
// i.e. the Godot room is used to lookup the room ID of the startroom.
LMAN->Meta_SetRoomNum(pNode, lroomID);
// LMAN->Meta_SetRoomNum(pNode, lroomID);
// create a new LRoom to exchange the children over to, and delete the original empty
lroom.m_szName = szRoom;

View File

@ -42,7 +42,8 @@ return false;\
LRoomManager::LRoomManager()
{
m_ID_camera = 0;
// m_ID_camera = 0;
m_DOB_id_camera = -1;
m_ID_DebugPlanes = 0;
m_ID_DebugBounds = 0;
m_ID_DebugLights = 0;
@ -183,6 +184,8 @@ int LRoomManager::Meta_GetLightID(Node * pNode) const
}
/*
CANT BE TRUSTED
void LRoomManager::Meta_SetRoomNum(Node * pNode, int num)
{
pNode->set_meta("_lroom", num);
@ -199,33 +202,10 @@ int LRoomManager::Meta_GetRoomNum(Node * pNode) const
return v;
}
LRoom * LRoomManager::GetRoomFromDOB(Node * pNode)
{
int iRoom = Meta_GetRoomNum(pNode);
if (iRoom < 0)
{
if (iRoom == -1)
{
WARN_PRINT_ONCE("LRoomManager::GetRoomFromDOB : metadata is empty");
}
if (iRoom == -2)
{
WARN_PRINT_ONCE("LRoomManager::GetRoomFromDOB : are you updating an unregistered DOB?");
}
return 0;
}
LRoom * pRoom = GetRoom(iRoom);
if (pRoom == 0)
{
WARN_PRINT_ONCE("LRoomManager::GetRoomFromDOB : pRoom is NULL");
}
return pRoom;
}
*/
/*
// register but let LPortal know which room the dob should start in
bool LRoomManager::dob_register_hint(Node * pDOB, float radius, Node * pRoom)
{
@ -258,7 +238,7 @@ bool LRoomManager::dob_register_hint(Node * pDOB, float radius, Node * pRoom)
return DobRegister(pSpat, radius, iRoom);
}
*/
void LRoomManager::CreateDebug()
{
@ -373,7 +353,7 @@ ObjectID LRoomManager::DobRegister_FindVIRecursive(Node * pNode) const
return 0;
}
bool LRoomManager::DobRegister(Spatial * pDOB, float radius, int iRoom)
int LRoomManager::DobRegister(Spatial * pDOB, const Vector3 &pos, float radius, int iRoom)
{
//LPRINT(3, "register_dob " + pDOB->get_name());
@ -383,38 +363,56 @@ bool LRoomManager::DobRegister(Spatial * pDOB, float radius, int iRoom)
return false;
}
LRoom * pRoom = GetRoom(iRoom);
if (!pRoom)
return false;
int did = m_DobList.Request();
LDob &dob = m_DobList.GetDob(did);
// 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_iRoomID = iRoom;
dob.m_ID_Spatial = pDOB->get_instance_id();
dob.m_fRadius = radius;
// LRoom * pRoom = GetRoom(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_Spatial = pDOB->get_instance_id();
// dob.m_fRadius = radius;
dob.m_ID_VI = DobRegister_FindVIRecursive(pDOB);
pRoom->DOB_Add(dob);
// pRoom->DOB_Add(dob);
// save the room ID on the dob metadata
Meta_SetRoomNum(pDOB, iRoom);
// Meta_SetRoomNum(pDOB, iRoom);
#ifdef LPORTAL_DOBS_NO_SOFTSHOW
VisualInstance * pVI = dob.GetVI();
if (pVI)
{
uint32_t mask = 0;
mask = LRoom::LAYER_MASK_CAMERA | LRoom::LAYER_MASK_LIGHT;
LRoom::SoftShow(pVI, mask);
}
#endif
// change visibility
DobChangeVisibility(pDOB, 0, pRoom);
m_DobList.UpdateDob(*this, did, pos);
// DobUpdateVisibility(pDOB, pRoom);
return true;
return did;
}
bool LRoomManager::dob_register(Node * pDOB, float radius)
int LRoomManager::dob_register(Node * pDOB, const Vector3 &pos, float radius)
{
CHECK_ROOM_LIST
if (!pDOB)
{
WARN_PRINT_ONCE("dob_register : pDOB is NULL");
return false;
return -1;
}
LPRINT(3, "dob_register " + pDOB->get_name() + " instance ID " + itos(pDOB->get_instance_id()));
@ -423,30 +421,30 @@ bool LRoomManager::dob_register(Node * pDOB, float radius)
if (!pSpat)
{
WARN_PRINT_ONCE("dob_register : DOB is not a spatial");
return false;
return -1;
}
Vector3 pt = pSpat->get_global_transform().origin;
// Vector3 pt = pSpat->get_global_transform().origin;
int iRoomNum = FindClosestRoom(pt);
int iRoomNum = FindClosestRoom(pos);
LPRINT(2, "dob_register closest room " + itos(iRoomNum));
return DobRegister(pSpat, radius, iRoomNum);
return DobRegister(pSpat, pos, radius, iRoomNum);
}
int LRoomManager::dob_update(Node * pDOB)
/*
// where pRoom is current room
int LRoomManager::DobUpdate(Spatial * pDOB_Spatial, LRoom * pRoom)
{
// find the room the object is attached to
LRoom * pRoom = GetRoomFromDOB(pDOB);
if (!pRoom)
return -1;
LRoom * pNewRoom = pRoom->DOB_Update(*this, pDOB_Spatial);
Spatial * pSpat = Object::cast_to<Spatial>(pDOB);
if (!pSpat)
return -1;
// // update visibility
// if (pNewRoom)
// DobUpdateVisibility(pSpat, pNewRoom);
// else
// DobUpdateVisibility(pSpat, pRoom);
LRoom * pNewRoom = pRoom->DOB_Update(*this, pSpat);
if (pNewRoom)
{
@ -456,7 +454,7 @@ int LRoomManager::dob_update(Node * pDOB)
// get dob data to move to new room
//unsigned int uidob_instance_id = pDOB->get_instance_id();
unsigned int dob_id = pRoom->DOB_Find(pDOB);
unsigned int dob_id = pRoom->DOB_Find(pDOB_Spatial);
// if (dob_id == -1)
// {
// WARN_PRINT_ONCE("DOB is not found in room");
@ -464,6 +462,8 @@ int LRoomManager::dob_update(Node * pDOB)
// }
assert (dob_id != -1);
print_line("dob " + itos(dob_id) + " entering room " + pNewRoom->get_name());
// copy across data before removing
const LDob &data = pRoom->DOB_Get(dob_id);
pNewRoom->DOB_Add(data);
@ -472,19 +472,75 @@ int LRoomManager::dob_update(Node * pDOB)
pRoom->DOB_Remove(dob_id);
// change visibility
DobChangeVisibility(pSpat, pRoom, pNewRoom);
DobUpdateVisibility(pDOB_Spatial, pNewRoom);
// save the room ID on the dob metadata
Meta_SetRoomNum(pSpat, iRoomNum);
Meta_SetRoomNum(pDOB_Spatial, iRoomNum);
// new room number
return iRoomNum;
}
//#ifdef LDEBUG_DOB_VISIBILITY
//#pragma message ("LPortal LDEBUG_DOB_VISIBILITY, dobs will flicker when hidden")
// bool bVis = pRoom->IsVisible();
// bool bSpatVisible = pSpat->is_visible_in_tree();
// if (bVis != bSpatVisible)
// {
// WARN_PRINT("DOB visibility incorrect");
// }
// bool bShow = true;
// if (!bVis)
// {
// if ((Engine::get_singleton()->get_frames_drawn() % 2) == 0)
// {
// pSpat->show();
// }
// else
// {
// pSpat->hide();
// }
// }
// else
// {
// pSpat->show();
// }
//#endif
// still in the same room
return pRoom->m_RoomID;
}
*/
int LRoomManager::dob_update(int dob_id, const Vector3 &pos)
{
#ifdef LPORTAL_DOBS_AUTO_UPDATE
return -1;
#endif
return m_DobList.UpdateDob(*this, dob_id, pos);
// find the room the object is attached to
// LRoom * pRoom = GetRoomFromDOB(pDOB);
// if (!pRoom)
// return -1;
// Spatial * pSpat = Object::cast_to<Spatial>(pDOB);
// if (!pSpat)
// return -1;
// return DobUpdate(pSpat, pRoom);
}
/*
bool LRoomManager::dob_teleport_hint(Node * pDOB, Node * pRoom)
{
CHECK_ROOM_LIST
@ -515,8 +571,9 @@ bool LRoomManager::dob_teleport_hint(Node * pDOB, Node * pRoom)
return DobTeleport(pSpat, iRoom);
}
*/
/*
bool LRoomManager::DobTeleport(Spatial * pDOB, int iNewRoomID)
{
LPRINT(5, "teleporting " + pDOB->get_name() + " to room " + itos(iNewRoomID));
@ -561,50 +618,55 @@ bool LRoomManager::DobTeleport(Spatial * pDOB, int iNewRoomID)
Meta_SetRoomNum(pDOB, iNewRoomID);
// change visibility
DobChangeVisibility(pDOB, pOldRoom, pNewRoom);
DobUpdateVisibility(pDOB, pNewRoom);
return true;
}
*/
// not tested...
/*
bool LRoomManager::dob_teleport(Node * pDOB)
{
CHECK_ROOM_LIST
Spatial * pSpat = Object::cast_to<Spatial>(pDOB);
if (!pSpat)
return false;
return true;
Vector3 pt = pSpat->get_global_transform().origin;
// Spatial * pSpat = Object::cast_to<Spatial>(pDOB);
// if (!pSpat)
// return false;
int iRoomNum = FindClosestRoom(pt);
//print_line("dob_teleport closest room " + itos(iRoomNum));
// Vector3 pt = pSpat->get_global_transform().origin;
if (iRoomNum == -1)
return false;
// int iRoomNum = FindClosestRoom(pt);
// //print_line("dob_teleport closest room " + itos(iRoomNum));
return DobTeleport(pSpat, iRoomNum);
// if (iRoomNum == -1)
// return false;
// return DobTeleport(pSpat, iRoomNum);
}
*/
bool LRoomManager::dob_unregister(Node * pDOB)
bool LRoomManager::dob_unregister(int dob_id)
{
CHECK_ROOM_LIST
LRoom * pRoom = GetRoomFromDOB(pDOB);
// LRoom * pRoom = GetRoomFromDOB(pDOB);
// change the meta data on the DOB .. this will catch trying to update an unregistered DOB
Meta_SetRoomNum(pDOB, -2);
// // change the meta data on the DOB .. this will catch trying to update an unregistered DOB
// Meta_SetRoomNum(pDOB, -2);
if (pRoom)
{
unsigned int dob_id = pRoom->DOB_Find(pDOB);
return pRoom->DOB_Remove(dob_id);
}
// if (pRoom)
// {
// unsigned int dob_id = pRoom->DOB_Find(pDOB);
// return pRoom->DOB_Remove(dob_id);
// }
return false;
m_DobList.DeleteDob(dob_id);
return true;
}
@ -729,7 +791,13 @@ bool LRoomManager::Light_FindCasters(int lightID)
void LRoomManager::Light_UpdateTransform(LLight &light, const Light &glight) const
{
// assert (glight.is_in_tree());
if (!glight.get_parent())
{
WARN_PRINT_ONCE("LRoomManager::Light_UpdateTransform Light is not in tree");
return;
}
// get global transform only works if glight is in the tree
Transform tr = glight.get_global_transform();
light.m_Source.m_ptPos = tr.origin;
light.m_Source.m_ptDir = -tr.basis.get_axis(2); // or possibly get_axis .. z is what we want
@ -815,14 +883,13 @@ bool LRoomManager::LightCreate(Light * pLight, int roomID, String szArea)
}
bool LRoomManager::dynamic_light_register(Node * pLightNode, float radius)
int LRoomManager::dynamic_light_register(Node * pLightNode, float radius)
{
CHECK_ROOM_LIST
if (!pLightNode)
{
WARN_PRINT_ONCE("dynamic_light_register : pLightNode is NULL");
return false;
return -1;
}
ObjectID light_id = pLightNode->get_instance_id();
@ -834,31 +901,85 @@ bool LRoomManager::dynamic_light_register(Node * pLightNode, float radius)
{
m_Lights[n].m_Source.m_eClass = LSource::SC_DYNAMIC;
// do an update on the light
//dynamic_light_update(n, pos, dir);
// store the light ID in the metadata for the node
Meta_SetLightID(pLightNode, n);
return true;
//Meta_SetLightID(pLightNode, n);
return n;
}
}
return false;
}
bool LRoomManager::dynamic_light_register_hint(Node * pLightNode, float radius, Node * pRoom)
{
// NYI
return true;
return -1;
}
bool LRoomManager::dynamic_light_unregister(Node * pLightNode)
bool LRoomManager::dynamic_light_unregister(int light_id)
{
// NYI
return true;
}
int LRoomManager::dynamic_light_update(Node * pLightNode) // returns room within
// returns room within or -1 if no dob
int LRoomManager::dynamic_light_update(int light_id, const Vector3 &pos, const Vector3 &dir) // returns room within
{
// doesn't now matter if not in tree as position and dir are passed directly
if ((unsigned int) light_id >= (unsigned int) m_Lights.size())
{
WARN_PRINT_ONCE("dynamic_light_update : meta light ID out of range");
return -1;
}
LLight &light = m_Lights[light_id];
int iRoom = light.m_Source.m_RoomID;
if (iRoom == -1)
{
WARN_PRINT_ONCE("dynamic_light_update : can't update global light");
return -1;
}
light.m_Source.m_ptPos = pos;
light.m_Source.m_ptDir = dir.normalized();
// update dob
if (light.m_DOB_id != -1)
{
int iNewRoom = m_DobList.UpdateDob(*this, light.m_DOB_id, pos);
light.m_Source.m_RoomID = iNewRoom;
}
// update with a new Trace (we are assuming update is only called if the light has moved)
// remove the old local lights
for (int n=0; n<light.m_NumAffectedRooms; n++)
{
int r = light.m_AffectedRooms[n];
GetRoom(r)->RemoveLocalLight(light_id);
}
light.ClearAffectedRooms();
// now do a new trace, and add all the rooms that are hit
m_Trace.Trace_Light(*this, light, LTrace::LR_ROOMS);
// we should now have a list of the rooms hit in m_LightRender.m_Temp_Visible_Rooms
for (int n=0; n<m_LightRender.m_Temp_Visible_Rooms.size(); n++)
{
int r = m_LightRender.m_Temp_Visible_Rooms[n];
// add to the list on the light
light.AddAffectedRoom(r);
// add to the list of local lights in the room
GetRoom(r)->AddLocalLight(light_id);
}
// this may or may not have changed
return light.m_Source.m_RoomID;
/*
if (!pLightNode)
{
WARN_PRINT_ONCE("dynamic_light_update : pLightNode is NULL");
@ -949,6 +1070,8 @@ int LRoomManager::dynamic_light_update(Node * pLightNode) // returns room within
// this may or may not have changed
return light.m_Source.m_RoomID;
*/
return 0;
}
void LRoomManager::DebugString_Light_AffectedRooms(int light_id)
@ -973,7 +1096,7 @@ void LRoomManager::DebugString_Light_AffectedRooms(int light_id)
}
bool LRoomManager::light_register(Node * pLightNode, String szArea)
bool LRoomManager::global_light_register(Node * pLightNode, String szArea)
{
//CHECK_ROOM_LIST
@ -1002,33 +1125,39 @@ bool LRoomManager::light_register(Node * pLightNode, String szArea)
return LightCreate(pLight, -1, szArea);
}
void LRoomManager::DobChangeVisibility(Spatial * pDOB, const LRoom * pOld, const LRoom * pNew)
/*
void LRoomManager::DobUpdateVisibility(int dob_id)
{
bool bVisOld = false;
bool bVisNew = false;
LDob &dob = m_DobList.GetDob(dob_id);
if (pOld)
bVisOld = pOld->IsVisible();
// return;
if (pNew)
bVisNew = pNew->IsVisible();
bool bRoomVis = pRoom->IsVisible();
bool bDobVis = pDOB->is_visible_in_tree();
if (bVisOld != bVisNew)
if (bDobVis != bRoomVis)
{
if (!bVisOld)
String sz = "DOB " + pDOB->get_name() + "\t";
if (bRoomVis)
{
pDOB->show();
sz += "coming into view";
}
else
{
pDOB->hide();
sz += "exiting view";
}
print_line(sz);
}
}
*/
int LRoomManager::dob_get_room_id(Node * pDOB)
int LRoomManager::dob_get_room_id(int dob_id)
{
return Meta_GetRoomNum(pDOB);
return m_DobList.GetDob(dob_id).m_iRoomID;
}
// helpers to enable the client to manage switching on and off physics and AI
@ -1192,15 +1321,14 @@ void LRoomManager::rooms_log_frame()
}
bool LRoomManager::rooms_set_camera(Node * pCam)
bool LRoomManager::rooms_set_camera(int dob_id, Node * pCam)
{
CHECK_ROOM_LIST
// is it the first setting of the camera? if so hide all
if (m_ID_camera == 0)
if (m_DOB_id_camera == -1)
ShowAll(false);
m_ID_camera = 0;
if (!pCam)
return false;
@ -1212,15 +1340,17 @@ bool LRoomManager::rooms_set_camera(Node * pCam)
return false;
}
int id = pCam->get_instance_id();
// int id = pCam->get_instance_id();
// was this a change in camera?
if (id != m_ID_camera)
if (m_DOB_id_camera != dob_id)
{
m_ID_camera = id;
m_DOB_id_camera = dob_id;
//m_ID_camera = id;
// make sure the camera room is correct by doing a teleport
dob_teleport(pCam);
//dob_teleport(pCam);
}
// new .. select the cull layer
@ -1458,17 +1588,18 @@ void LRoomManager::rooms_release()
rooms_set_active(false);
// unregister all the dobs
for (int n=0; n<m_Rooms.size(); n++)
{
LRoom &lroom = m_Rooms[n];
lroom.Release(*this);
}
// for (int n=0; n<m_Rooms.size(); n++)
// {
// LRoom &lroom = m_Rooms[n];
// lroom.Release(*this);
// }
ReleaseResources(false);
m_ID_camera = 0;
m_DOB_id_camera = -1;
//m_ID_camera = 0;
m_ID_RoomList = 0;
m_uiFrameCounter = 0;
@ -1577,6 +1708,11 @@ bool LRoomManager::FrameUpdate()
CHECK_ROOM_LIST
#ifdef LPORTAL_DOBS_AUTO_UPDATE
DobsAutoUpdate();
#endif
if (m_bFrustumOnly)
{
// debugging emulate view frustum
@ -1593,26 +1729,32 @@ bool LRoomManager::FrameUpdate()
// get the camera desired and make into lcamera
Camera * pCamera = 0;
if (m_ID_camera)
if (m_DOB_id_camera == -1)
{
Object *pObj = ObjectDB::get_instance(m_ID_camera);
pCamera = Object::cast_to<Camera>(pObj);
// always doing dob update here for camera, this ensures it is not one frame behind
// depending on scene tree, which can cause camera lroom id to be the old one after crossing
// a portal plane, causing a flicker on changing room...
dob_update(pCamera);
}
else
// camera not set .. do nothing
return false;
}
LDob &dob = m_DobList.GetDob(m_DOB_id_camera);
pCamera = Object::cast_to<Camera>(dob.GetSpatial());
// camera not a camera?? shouldn't happen but we'll check
if (!pCamera)
return false;
//Object *pObj = ObjectDB::get_instance(m_ID_camera);
//pCamera = Object::cast_to<Camera>(pObj);
// always doing dob update here for camera, this ensures it is not one frame behind
// depending on scene tree, which can cause camera lroom id to be the old one after crossing
// a portal plane, causing a flicker on changing room...
dob_update(m_DOB_id_camera, pCamera->get_global_transform().origin);
//dob_update(pCamera);
// Which room is the camera currently in?
LRoom * pRoom = GetRoomFromDOB(pCamera);
LRoom * pRoom = GetRoom(dob.m_iRoomID);
if (!pRoom)
{
@ -2073,21 +2215,21 @@ void LRoomManager::_bind_methods()
// 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", "dob", "radius"), &LRoomManager::dob_register);
ClassDB::bind_method(D_METHOD("dob_unregister", "dob"), &LRoomManager::dob_unregister);
ClassDB::bind_method(D_METHOD("dob_update", "dob"), &LRoomManager::dob_update);
ClassDB::bind_method(D_METHOD("dob_teleport", "dob"), &LRoomManager::dob_teleport);
ClassDB::bind_method(D_METHOD("dob_register", "node", "pos", "radius"), &LRoomManager::dob_register);
ClassDB::bind_method(D_METHOD("dob_unregister", "dob_id"), &LRoomManager::dob_unregister);
ClassDB::bind_method(D_METHOD("dob_update", "dob_id", "pos"), &LRoomManager::dob_update);
// ClassDB::bind_method(D_METHOD("dob_teleport", "dob"), &LRoomManager::dob_teleport);
ClassDB::bind_method(D_METHOD("dob_register_hint", "dob", "radius", "room"), &LRoomManager::dob_register_hint);
ClassDB::bind_method(D_METHOD("dob_teleport_hint", "dob", "room"), &LRoomManager::dob_teleport_hint);
// ClassDB::bind_method(D_METHOD("dob_register_hint", "dob", "radius", "room"), &LRoomManager::dob_register_hint);
// ClassDB::bind_method(D_METHOD("dob_teleport_hint", "dob", "room"), &LRoomManager::dob_teleport_hint);
ClassDB::bind_method(D_METHOD("dob_get_room_id", "dob"), &LRoomManager::dob_get_room_id);
ClassDB::bind_method(D_METHOD("light_register", "light", "area"), &LRoomManager::light_register);
ClassDB::bind_method(D_METHOD("global_light_register", "light", "area"), &LRoomManager::global_light_register);
ClassDB::bind_method(D_METHOD("dynamic_light_register", "light", "radius"), &LRoomManager::dynamic_light_register);
ClassDB::bind_method(D_METHOD("dynamic_light_register_hint", "light", "radius", "room"), &LRoomManager::dynamic_light_register_hint);
// ClassDB::bind_method(D_METHOD("dynamic_light_register_hint", "light", "radius", "room"), &LRoomManager::dynamic_light_register_hint);
ClassDB::bind_method(D_METHOD("dynamic_light_unregister", "light"), &LRoomManager::dynamic_light_unregister);
ClassDB::bind_method(D_METHOD("dynamic_light_update", "light"), &LRoomManager::dynamic_light_update);
@ -2261,3 +2403,35 @@ void LRoomManager::rooms_set_debug_frame_string(bool bActive)
{
m_bDebugFrameString = bActive;
}
//void LRoomManager::DobsAutoUpdate()
//{
// // go through each room, each dob
// for (int n=0; n<m_Rooms.size(); n++)
// {
// LRoom &lroom = m_Rooms[n];
// int iRoomNum = lroom.m_RoomID;
// for (int d=0; d<lroom.m_DOBs.size(); d++)
// {
// LDob &dob = lroom.m_DOBs[d];
// Spatial * pDOB_Spatial = dob.GetSpatial();
// if (!pDOB_Spatial)
// continue;
// int iNewRoom = DobUpdate(pDOB_Spatial, &lroom);
// // changed?
// if (iNewRoom != iRoomNum)
// {
// // very inefficient but will do for testing
// DobsAutoUpdate();
// return;
// }
// }
// }
//}

View File

@ -30,6 +30,7 @@
#include "lbitfield_dynamic.h"
#include "lplanes_pool.h"
#include "ldoblist.h"
#include "lroom.h"
#include "lportal.h"
#include "larea.h"
@ -44,6 +45,7 @@ class LRoomManager : public Spatial {
friend class LHelper;
friend class LTrace;
friend class LMainCamera;
friend class LDobList;
public:
// PUBLIC INTERFACE TO GDSCRIPT
@ -65,7 +67,7 @@ public:
// choose which camera you want to use to determine visibility.
// normally this will be your main camera, but you can choose another for debugging
bool rooms_set_camera(Node * pCam);
bool rooms_set_camera(int dob_id, Node * pCam);
// get the Godot room that is associated with an LPortal room
// (can be used to find the name etc of a room ID returned by dob_update)
@ -81,30 +83,24 @@ public:
// 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.
bool dob_register(Node * pDOB, float radius);
// register but let LPortal know which room the dob should start in
bool dob_register_hint(Node * pDOB, float radius, Node * pRoom);
bool dob_unregister(Node * pDOB);
// returns DOB ID
int dob_register(Node * pDOB, const Vector3 &pos, float radius);
bool dob_unregister(int dob_id);
// returns the room ID within
int dob_update(Node * pDOB);
// if we are moving the DOB possibly through multiple rooms, then teleport rather than detect
// portal crossings
bool dob_teleport(Node * pDOB);
bool dob_teleport_hint(Node * pDOB, Node * pRoom);
int dob_update(int dob_id, const Vector3 &pos);
//______________________________________________________________________________________
// LIGHTS
// global directional lights that will apply to all rooms
bool light_register(Node * pLightNode, String szArea);
bool global_light_register(Node * pLightNode, String szArea);
// dynamic lights (spot or omni within rooms)
bool dynamic_light_register(Node * pLightNode, float radius);
bool dynamic_light_register_hint(Node * pLightNode, float radius, Node * pRoom);
bool dynamic_light_unregister(Node * pLightNode);
int dynamic_light_update(Node * pLightNode); // returns room within
// returns light ID
// only lights within the rooms on conversion are supported so far
int dynamic_light_register(Node * pLightNode, float radius);
bool dynamic_light_unregister(int light_id);
int dynamic_light_update(int light_id, const Vector3 &pos, const Vector3 &dir); // returns room within
//______________________________________________________________________________________
// LIGHTMAPS
@ -130,7 +126,7 @@ public:
bool rooms_is_room_visible(int room_id) const;
Array rooms_get_visible_rooms() const;
// helper func, not needed usually as dob_update returns the room
int dob_get_room_id(Node * pDOB);
int dob_get_room_id(int dob_id);
bool export_scene_DAE(Node * pNode, String szFilename);
@ -161,8 +157,8 @@ public:
private:
// PER FRAME STUFF
// godot ID of the camera (which should be registered as a DOB to allow moving between rooms)
ObjectID m_ID_camera;
// camera
int m_DOB_id_camera;
// 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;
@ -249,6 +245,7 @@ private:
// We use a pool for this instead of allocating on the fly.
LPlanesPool m_Pool;
LDobList m_DobList;
public:
// whether debug planes is switched on
@ -325,10 +322,16 @@ private:
bool RoomsConvert(bool bVerbose, bool bDeleteLights, bool bSingleRoomMode);
// dobs
bool DobRegister(Spatial * pDOB, float radius, int iRoom);
int DobRegister(Spatial * pDOB, const Vector3 &pos, float radius, int iRoom);
ObjectID DobRegister_FindVIRecursive(Node * pNode) const;
bool DobTeleport(Spatial * pDOB, int iNewRoomID);
void DobChangeVisibility(Spatial * pDOB, const LRoom * pOld, const LRoom * pNew);
// bool DobTeleport(Spatial * pDOB, int iNewRoomID);
//int DobUpdate(Spatial * pDOB_Spatial, LRoom * pRoom);
void DobUpdateVisibility(int dob_id);
// for debugging only have autoupdate mode where all dobs are updated
// void DobsAutoUpdate();
void CreateDebug();
void ReleaseResources(bool bPrepareConvert);
@ -351,15 +354,14 @@ private:
const LRoom * GetRoom(int i) const;
LRoom * GetRoom(int i);
LRoom * GetRoomFromDOB(Node * pNode);
int FindClosestRoom(const Vector3 &pt) const;
LRoom &Portal_GetLinkedRoom(const LPortal &port);
// for DOBs, we need some way of storing the room ID on them, so we use metadata (currently)
// this is pretty gross but hey ho
int Meta_GetRoomNum(Node * pNode) const;
void Meta_SetRoomNum(Node * pNode, int num);
// int Meta_GetRoomNum(Node * pNode) const;
// void Meta_SetRoomNum(Node * pNode, int num);
// for lights we store the light ID in the metadata
void Meta_SetLightID(Node * pNode, int id);

View File

@ -105,7 +105,7 @@ void LTrace::CullSOBs(LRoom &room, const LVector<Plane> &planes)
void LTrace::CullDOBs(LRoom &room, const LVector<Plane> &planes)
{
// NYI this isn't efficient, there may be more than 1 portal to the same room
/*
// cull DOBs
int nDOBs = room.m_DOBs.size();
@ -145,7 +145,7 @@ void LTrace::CullDOBs(LRoom &room, const LVector<Plane> &planes)
}
}
} // for through dobs
*/
}
@ -601,6 +601,8 @@ void LTrace::FirstTouch(LRoom &room)
// m_pVisible_Rooms->push_back(room.m_RoomID);
// hide all dobs
/*
for (int n=0; n<room.m_DOBs.size(); n++)
room.m_DOBs[n].m_bVisible = false;
*/
}