Compare commits

..

11 Commits
v0.1 ... master

Author SHA1 Message Date
lawnjelly
8c1f7bb718
Update README.md 2020-06-15 09:25:04 +01:00
lawnjelly
c63c317d76
Removed verbose 2020-06-04 13:43:28 +01:00
lawnjelly
bfb31a9287
Update README.md 2020-06-04 13:35:25 +01:00
lawnjelly
6d3d3ec643
Update README.md 2020-06-04 12:54:58 +01:00
lawnjelly
9e84c7a7cd
Update README.md 2020-04-02 14:00:38 +01:00
lawnjelly
ccc8cd2a1a
Update INSTRUCTIONS.md 2020-04-02 13:57:45 +01:00
lawnjelly
d682efb517
Update README.md 2020-04-02 13:43:16 +01:00
lawnjelly
18eac7e810
New API for dobs
To fix bug where get_global_transform doesn't work with dobs outside the tree, there is a new API
2020-04-02 13:36:53 +01:00
lawnjelly
d6717de5ba
Update README.md 2020-03-08 09:07:57 +00:00
lawnjelly
1b40e8d6c2
Update README.md 2020-02-26 13:32:37 +00:00
lawnjelly
9f049a86c1
Update README.md 2020-02-26 13:29:33 +00:00
16 changed files with 659 additions and 244 deletions

View File

@ -40,7 +40,7 @@ before_build:
- SET "SCONS_CACHE=%SCONS_CACHE_ROOT%\3.2"
build_script:
- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% debug_symbols=no verbose=yes progress=no gdnative_wrapper=yes
- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% debug_symbols=no progress=no gdnative_wrapper=yes
#- scons --version
#- cd ..
- ls

View File

@ -141,21 +141,19 @@ Somewhat counter-intuitively, all DOBs should be maintained in your game __OUTSI
All the following functions should be called on the LRoomManager node.
* Call `dob_register(cam, 0.0)` to register a DOB to be handled
* Call `dob_id = dob_register(godot_node, position, radius)` to register a DOB to be handled
The number 0.0 is the radius of the DOB in the visibility system. All DOBs are managed as spheres. For a camera the radius can be zero because it will never be visible (however it DOES require to be a DOB so that the system can keep track of which room it is in).
The radius is needed because all DOBs are managed as spheres. For a camera the radius can be zero because it will never be visible (however it DOES require to be a DOB so that the system can keep track of which room it is in). It returns a dob_id which will need to be stored in your game and used to refer to the dob.
If a DOB is being culled (popping out of view) when it should not, it is normally because the bounding radius needs to be larger. On the other hand, too large a radius will make the DOB render when it is not necessary, so it is a good idea to tweak this value. It is in Godot world units, so you may be able to simply measure you object in the IDE.
* Each frame, call `dob_update(dob_node)` to keep that DOB updated in the system
* Each frame, call `dob_update(dob_id, position)` to keep that DOB updated in the system with the new position
If the DOB is not moving, or you want to deactivate it to save processing, simply don't call update again until you want to reactivate it. Note that there is no need to call dob_update on the selected camera, it will be updated automatically.
* When you have finished with a DOB you should call `dob_unregister(cam)` to remove the soft link from the system. This is more important when you are creating and deleting DOBs (say with multiple game levels). If you call rooms_release when unloading a level and want to keep DOBs in between levels, it is crucial that you do not update them until you have re-registered them after calling rooms_convert to create the new level (you will get an error message otherwise).
* When you have finished with a DOB you should call `dob_unregister(dob_id)` to remove the soft link from the system. This is more important when you are creating and deleting DOBs (say with multiple game levels). If you call rooms_release when unloading a level and want to keep DOBs in between levels, it is crucial that you do not update them until you have re-registered them after calling rooms_convert to create the new level (you will get an error message otherwise).
* If you are suddenly moving a DOB a large distance (rather than into a neighbouring room), you should call `dob_teleport(cam)`. This uses a different system to estimate the new room that the DOB is in. If you know in advance what room the dob will teleport to, there is a hint version of the function.
* DOBs should only move between rooms via the portals. In fact that is how their movement between rooms is defined. This is why a room's portals should form a convex space, never concave. In order to limit movement between rooms to the portals, you should use e.g. physics, or a navmesh.
* DOBs should usually only move between rooms via the portals. In fact that is how their movement between rooms is defined. This is why a room's portals should form a convex space, never concave. In order to limit movement between rooms to the portals, you should use e.g. physics, or a navmesh.
## Conversion
Build your rooms and portals and placed them as children in a scene graph structure something like this:
@ -186,10 +184,10 @@ Root
This will provide some output to indicate the building of the optimized internal visibility structure.
* Set which camera you want LPortal to use by calling `rooms_set_camera(cam)`
* Register the camera as a DOB (see above section on DOBs) and update each frame.
* Set which camera you want LPortal to use by calling `rooms_set_camera(dob_id, camera_node)`
* If you want to unload a level and load a new one, call `rooms_release()`, free the old level, load the new one, and call `rooms_convert()` again (which clears the old data), and repeat each step.
_Be aware that if you unload (using queue_free) and load levels with the same name then Godot can rename them to avoid name conflicts. The nodepath to the rooms assigned to the LRoomManager must be correct!_
@ -380,12 +378,16 @@ var m_node_KitchenLight = get_node("/root").find_node("kitchen_light", true, fal
Then after converting the level, call
```
# where LRoomManager is your LRoomManager
$LRoomManager.dynamic_light_register(m_node_KitchenLight)
light_id = $LRoomManager.dynamic_light_register(m_node_KitchenLight, radius)
```
Move or rotate the light as you would normally, but to keep LPortal up to date, immediately after moving the light call 'dynamic_light_update':
```
m_node_KitchenLight.rotate_y(0.01) # just an example
$LRoomManager.dynamic_light_update(m_node_KitchenLight)
$LRoomManager.dynamic_light_update(light_id, position, direction)
```
The direction is important for spotlights, you can calculate it using the following formula:
```
var dir = (-node_Spotlight.global_transform.basis.z).normalized()
```
#### Global Directional lights
@ -398,7 +400,7 @@ As directional lights are not associated with any particular room, you should ad
```
# where $DirectionalLight is your light node,
# and "myarea" is the name of your area (e.g. area_myarea) that you want it to affect
$LRoomManager.light_register($DirectionalLight, "myarea")
$LRoomManager.global_light_register($DirectionalLight, "myarea")
```
That's all you need to do. If any of the visible rooms (as calculated by LPortal) are part of the area affected by the light, the light will be drawn. If not, it will not. LPortal also calculates only those shadow casters that are relevant, but directional lights cannot as yet (Godot 3) take advantage of this information. This may change in Godot 4.
@ -487,20 +489,3 @@ Note that you should usually assign the shader to the materials while creating t
### Command reference
_(There is a full reference available from the help section in the IDE under 'LRoomManager')_
* `rooms_convert()` - prepare lportal for rendering
* `rooms_set_camera()` - set which camera visibility is calculated from
* `Node * rooms_get_room()` - returns godot room node from lportal room id
* `rooms_set_active()` - turns on and off lportal
* `rooms_log_frame()` - output debug logs for the next frame
* `rooms_set_logging()` - set debug logging level, 0 - 6 (0 is none, 6 is most)
* `rooms_set_debug_planes()` - turns on and off graphic debugging of portal planes
* `rooms_set_debug_bounds()` - turns on and off graphic debugging of room bounds
* `dob_register()` - have lportal find start room
* `dob_register_hint()` - user provides start room
* `dob_unregister()`
* `int dob_update()` - returns room ID within
* `dob_teleport()` - have lportal find start room
* `dob_teleport_hint()` - user provides start room
* `int dob_get_room_id()` - return room ID the dob is currently within

View File

@ -1,4 +1,4 @@
# godot-lportal
# godot-lportal 0.2
Portal rendering / Occlusion culling module for Godot 3.2
You can either use LPortal as a full occlusion culling system if you can create your level as rooms and portals, or use it in a simplified single room mode to speed up culling in any 3d level.
@ -26,9 +26,17 @@ https://github.com/lawnjelly/lportal-demos
_Feel free to leave suggestions / feature requests on the issue tracker, especially regarding ease of use._
## Current status
As everything is now basically working, I am currently working on a small demo / test first person shooter game. This is helping me find bugs / add usability features as I go.
April 2nd 2020 - New API for DOBS. I had identified a breaking bug in the DOB visibility caused by the assumptions from the data coming from godot. It turns out when DOBs are hidden I can't retrieve their position etc from the Godot node, so I'm having to change the API for DOBs and dynamic lights so you pass the position manually each update. I've tested and this works.
Note I'm also currently rewriting the Godot 2d GLES renderer in core, so that has to take priority until it is working.
Note that the new dob culling isn't totally finished yet, it simply culls based on which room the dob is within, and whether that room is visible. This is approximate and won't deal with the case where a dob should be casting a shadow into the frustum from a room that is not visible. I'll get more accurate dob culling and light tracing working again in time, but it should be okay for most cases to start with.
I am currently working on a small demo / test first person shooter game. This is helping me find bugs / add usability features as I go.
I've also written a small lightmapper which started out as a bit of fun, but will be integrated in LPortal. The current voxel based lightmapper in core 3.x has a lot of bugs. JFons has been writing a replacement lightmapper for core, and I may switch to that when it is available, or have both options available. My lightmapper (and I believe JFons also) are based on path tracing rather than voxels. Reduz has also written a new lightmapper for 4.x, but whether that will be backported to 3.x and will work on CPUs remains to be seen.
I'm going to be working on improving the user interface for LPortal, exposing some of the features in the LRoomManager node, and having editor plugins for both the lightmapper and lportal.
Note I'm also working on core renderers (batching in GLES2 and GLES3, and the new 4.x GLES renderers), so there may be some periods of inactivity on LPortal.
## Instructions
* [OVERVIEW](OCCLUSION_CULLING.md)
@ -62,7 +70,14 @@ Note I'm also currently rewriting the Godot 2d GLES renderer in core, so that ha
* PVS (primary and secondary)
## Installation
You will need to compile Godot from source (for now). See:
For convenience to trial LPortal I have provided a win64 build under the 'releases' tab in github. However, note that for production use (on multiple platforms) you will currently have to compile from source.
I will work on increasing the number of builds for different platforms.
## Compiling from source
See:
http://docs.godotengine.org/en/3.0/development/compiling/index.html
Once the engine is compiling okay on your system, to add the module:

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;
*/
}