mirror of
https://github.com/Relintai/godot-lportal.git
synced 2025-04-19 21:43:10 +02:00
Backup while investigate Godot light cull bug
This commit is contained in:
parent
1e9152c69f
commit
0f8094e9f3
@ -10,8 +10,7 @@ Video of initial testing:\
|
||||
https://www.youtube.com/watch?v=xF_3Fe2HRdk \
|
||||
https://www.youtube.com/watch?v=NmlWkkhGoJA
|
||||
|
||||
_Feel free to leave suggestions / feature requests on the issue tracker, especially regarding ease of use._\
|
||||
_If you are interested in integrating LPortal into your game, feel free to get in touch, e.g. in the issue tracker, and I will endeavour to help._
|
||||
_Feel free to leave suggestions / feature requests on the issue tracker, especially regarding ease of use._
|
||||
|
||||
## Current status
|
||||
The basic system is mostly working. I am now testing / polishing the interface and adding debugging. I will leave PVS and closable portals until after the first release.
|
||||
|
104
lportal.cpp
104
lportal.cpp
@ -23,6 +23,25 @@
|
||||
#include "lroom.h"
|
||||
#include "ldebug.h"
|
||||
#include "lroom_manager.h"
|
||||
#include "scene/3d/light.h"
|
||||
|
||||
void LLight::SetDefaults()
|
||||
{
|
||||
m_GodotID = 0;
|
||||
m_eType = LT_DIRECTIONAL;
|
||||
m_fSpread = 0.0f; // for spotlight
|
||||
m_fMaxDist = 100.0f;
|
||||
m_RoomID = -1;
|
||||
}
|
||||
|
||||
|
||||
Light * LLight::GetGodotLight()
|
||||
{
|
||||
Object * pObj = ObjectDB::get_instance(m_GodotID);
|
||||
Light * p = Object::cast_to<Light>(pObj);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool LPortal::NameStartsWith(Node * pNode, String szSearch)
|
||||
@ -71,38 +90,91 @@ String LPortal::FindNameAfter(Node * pNode, String szStart)
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
void LPortal::Debug_CheckPlaneValidity(const Plane &p) const
|
||||
{
|
||||
assert (p.distance_to(m_ptCentre) < 0.0f);
|
||||
}
|
||||
|
||||
|
||||
// preprocess
|
||||
void LPortal::AddLightPlanes(const LLight &light, LVector<Plane> &planes) const
|
||||
void LPortal::AddLightPlanes(LRoomManager &manager, const LLight &light, LVector<Plane> &planes, bool bReverse) const
|
||||
{
|
||||
const Vector<Vector3> &pts = m_ptsWorld;
|
||||
|
||||
// assuming ortho light
|
||||
int nPoints = pts.size();
|
||||
ERR_FAIL_COND(nPoints < 3);
|
||||
|
||||
const int max_points = 32;
|
||||
Vector3 pushed_pts[max_points];
|
||||
|
||||
if (nPoints > max_points)
|
||||
nPoints = max_points;
|
||||
|
||||
// transform pushed points
|
||||
for (int n=0; n<nPoints; n++)
|
||||
if (light.m_eType == LLight::LT_DIRECTIONAL)
|
||||
{
|
||||
pushed_pts[n] = pts[n] + light.m_ptDir;
|
||||
// assuming ortho light
|
||||
const int max_points = 32;
|
||||
Vector3 pushed_pts[max_points];
|
||||
|
||||
if (nPoints > max_points)
|
||||
nPoints = max_points;
|
||||
|
||||
// transform pushed points
|
||||
Vector3 ptPush = light.m_ptDir * 2.0;
|
||||
|
||||
for (int n=0; n<nPoints; n++)
|
||||
{
|
||||
pushed_pts[n] = pts[n] + ptPush;
|
||||
}
|
||||
|
||||
Plane p;
|
||||
|
||||
for (int n=0; n<nPoints; n++)
|
||||
{
|
||||
int nPLUS = (n + 1) % nPoints;
|
||||
p = Plane(pts[n], pts[nPLUS], pushed_pts[n]);
|
||||
if (bReverse) p = -p;
|
||||
planes.push_back(p);
|
||||
Debug_CheckPlaneValidity(p);
|
||||
}
|
||||
|
||||
// first and last
|
||||
// p = Plane(pts[nPoints-1], pts[0], pushed_pts[0]);
|
||||
// if (bReverse) p = -p;
|
||||
// planes.push_back(p);
|
||||
// Debug_CheckPlaneValidity(p);
|
||||
|
||||
// debug
|
||||
if (manager.m_bDebugLights)
|
||||
{
|
||||
for (int n=1; n<nPoints; n++)
|
||||
{
|
||||
if (n == 2)
|
||||
continue;
|
||||
|
||||
manager.m_DebugPortalLightPlanes.push_back(pts[n-1]);
|
||||
manager.m_DebugPortalLightPlanes.push_back(pts[n]);
|
||||
manager.m_DebugPortalLightPlanes.push_back(pushed_pts[n]);
|
||||
manager.m_DebugPortalLightPlanes.push_back(pushed_pts[n]);
|
||||
manager.m_DebugPortalLightPlanes.push_back(pushed_pts[n-1]);
|
||||
manager.m_DebugPortalLightPlanes.push_back(pts[n-1]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// use a point for the light for omni and spotlight
|
||||
Plane p;
|
||||
|
||||
for (int n=1; n<nPoints; n++)
|
||||
for (int n=0; n<nPoints; n++)
|
||||
{
|
||||
p = Plane(pts[n-1], pts[n], pushed_pts[n]);
|
||||
int nPLUS = (n + 1) % nPoints;
|
||||
p = Plane(pts[nPLUS], pts[n], light.m_ptPos);
|
||||
if (bReverse) p = -p;
|
||||
planes.push_back(p);
|
||||
Debug_CheckPlaneValidity(p);
|
||||
}
|
||||
|
||||
// first and last
|
||||
p = Plane(pts[nPoints-1], pts[0], pushed_pts[0]);
|
||||
planes.push_back(p);
|
||||
// p = Plane(pts[0], pts[nPoints-1], light.m_ptPos);
|
||||
// if (bReverse) p = -p;
|
||||
// planes.push_back(p);
|
||||
// Debug_CheckPlaneValidity(p);
|
||||
|
||||
}
|
||||
|
||||
@ -129,11 +201,13 @@ void LPortal::AddPlanes(LRoomManager &manager, const Vector3 &ptCam, LVector<Pla
|
||||
// print(ptCam + pts[n] + pts[n-1]);
|
||||
// }
|
||||
planes.push_back(p);
|
||||
Debug_CheckPlaneValidity(p);
|
||||
}
|
||||
|
||||
// first and last
|
||||
p = Plane(ptCam, pts[0], pts[nPoints-1]);
|
||||
planes.push_back(p);
|
||||
Debug_CheckPlaneValidity(p);
|
||||
|
||||
// debug
|
||||
if (!manager.m_bDebugPlanes)
|
||||
|
25
lportal.h
25
lportal.h
@ -32,14 +32,31 @@
|
||||
|
||||
class LRoom;
|
||||
class LRoomManager;
|
||||
class Light;
|
||||
|
||||
|
||||
class LLight
|
||||
{
|
||||
public:
|
||||
enum eLightType
|
||||
{
|
||||
LT_DIRECTIONAL,
|
||||
LT_SPOTLIGHT,
|
||||
LT_OMNI,
|
||||
};
|
||||
void SetDefaults();
|
||||
Light * GetGodotLight();
|
||||
bool IsGlobal() const {return m_RoomID == -1;}
|
||||
|
||||
Vector3 m_ptDir;
|
||||
Vector3 m_ptPos;
|
||||
ObjectID m_GodotID;
|
||||
eLightType m_eType;
|
||||
float m_fSpread; // for spotlight
|
||||
float m_fMaxDist; // shadow distance not light distance
|
||||
|
||||
// source room
|
||||
int m_RoomID; // or -1 for global lights
|
||||
};
|
||||
|
||||
|
||||
@ -62,7 +79,10 @@ public:
|
||||
|
||||
LPortal::eClipResult ClipWithPlane(const Plane &p) const;
|
||||
void AddPlanes(LRoomManager &manager, const Vector3 &ptCam, LVector<Plane> &planes) const;
|
||||
void AddLightPlanes(const LLight &light, LVector<Plane> &planes) const;
|
||||
|
||||
// reverse direction if we are going back through portals TOWARDS the light rather than away from it
|
||||
// (the planes will need reversing because the portal winding will be opposite)
|
||||
void AddLightPlanes(LRoomManager &manager, const LLight &light, LVector<Plane> &planes, bool bReverse) const;
|
||||
|
||||
// normal determined by winding order
|
||||
Vector<Vector3> m_ptsWorld;
|
||||
@ -87,6 +107,9 @@ public:
|
||||
// useful funcs
|
||||
static bool NameStartsWith(Node * pNode, String szSearch);
|
||||
static String FindNameAfter(Node * pNode, String szStart);
|
||||
|
||||
private:
|
||||
void Debug_CheckPlaneValidity(const Plane &p) const;
|
||||
};
|
||||
|
||||
|
||||
|
65
lroom.cpp
65
lroom.cpp
@ -132,29 +132,48 @@ LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
|
||||
// objects can still be rendered outside immediate view for casting shadows.
|
||||
// All objects in view (that are set to cast shadows) should cast shadows, so the actual
|
||||
// shown objects are a superset of the softshown.
|
||||
void LRoom::SoftShow(VisualInstance * pVI, bool bShow)
|
||||
void LRoom::SoftShow(VisualInstance * pVI, uint32_t show_flags)
|
||||
{
|
||||
|
||||
// hijack this layer number
|
||||
uint32_t mask = pVI->get_layer_mask();
|
||||
uint32_t orig_mask = mask;
|
||||
|
||||
const int SOFT_SHOW_MASK = 1 << SOFT_SHOW_BIT;
|
||||
const int SOFT_HIDE_MASK = 1 << SOFT_HIDE_BIT;
|
||||
|
||||
// debug, to check shadow casters are correct for different light types
|
||||
//#define DEBUG_SHOW_CASTERS_ONLY
|
||||
#ifdef DEBUG_SHOW_CASTERS_ONLY
|
||||
bShow = true;
|
||||
if (bShow)
|
||||
{
|
||||
// set
|
||||
mask |= SOFT_SHOW_MASK;
|
||||
// clear
|
||||
mask &= ~(1 | SOFT_HIDE_MASK);
|
||||
|
||||
}
|
||||
#else
|
||||
if (show_flags & LAYER_MASK_CAMERA)
|
||||
mask |= LAYER_MASK_CAMERA; // set
|
||||
else
|
||||
{
|
||||
// set
|
||||
mask |= SOFT_HIDE_MASK;
|
||||
// clear
|
||||
mask &= ~(1 | SOFT_SHOW_MASK);
|
||||
}
|
||||
mask &= ~LAYER_MASK_CAMERA; // clear
|
||||
|
||||
if (show_flags & LAYER_MASK_LIGHT)
|
||||
mask |= LAYER_MASK_LIGHT;
|
||||
else
|
||||
mask &= ~LAYER_MASK_LIGHT;
|
||||
|
||||
// if (bShow)
|
||||
// {
|
||||
// // set
|
||||
// mask |= SOFT_SHOW_MASK;
|
||||
// // clear
|
||||
// mask &= ~(1 | SOFT_HIDE_MASK);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // set
|
||||
// mask |= SOFT_HIDE_MASK;
|
||||
// // clear
|
||||
// mask &= ~(1 | SOFT_SHOW_MASK);
|
||||
// }
|
||||
#endif
|
||||
|
||||
|
||||
// noop? don't touch the visual server if no change to mask
|
||||
@ -163,9 +182,7 @@ void LRoom::SoftShow(VisualInstance * pVI, bool bShow)
|
||||
|
||||
pVI->set_layer_mask(mask);
|
||||
|
||||
// pVI->set_layer_mask_bit(0, false);
|
||||
// pVI->set_layer_mask_bit(SOFT_HIDE_BIT, bShow == false);
|
||||
// pVI->set_layer_mask_bit(SOFT_SHOW_BIT, bShow);
|
||||
// test the visual server - NOT A BOTTLENECK. set_layer_mask is cheap
|
||||
}
|
||||
|
||||
|
||||
@ -174,6 +191,18 @@ void LRoom::AddShadowCasters(LRoomManager &manager)
|
||||
{
|
||||
LPRINT(2, "ADDSHADOWCASTERS room " + get_name() + ", " + itos(m_iNumShadowCasters_SOB) + " shadow casters");
|
||||
|
||||
// add all the active lights in this room
|
||||
for (int n=0; n<m_LocalLights.size(); n++)
|
||||
{
|
||||
int lightID = m_LocalLights[n];
|
||||
if (!manager.m_BF_ActiveLights.GetBit(lightID))
|
||||
{
|
||||
manager.m_BF_ActiveLights.SetBit(lightID, true);
|
||||
manager.m_ActiveLights.push_back(lightID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// new!! use precalced list of shadow casters
|
||||
int last = m_iFirstShadowCaster_SOB + m_iNumShadowCasters_SOB;
|
||||
for (int n=m_iFirstShadowCaster_SOB; n<last; n++)
|
||||
@ -189,7 +218,7 @@ void LRoom::AddShadowCasters(LRoomManager &manager)
|
||||
}
|
||||
else
|
||||
{
|
||||
LPRINT(2, "\t" + itos(sobID) + ", ALREADY CASTER " + manager.m_SOBs[sobID].GetSpatial()->get_name());
|
||||
//LPRINT(2, "\t" + itos(sobID) + ", ALREADY CASTER " + manager.m_SOBs[sobID].GetSpatial()->get_name());
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,6 +244,8 @@ void LRoom::AddShadowCasters(LRoomManager &manager)
|
||||
// (it might be expensive)
|
||||
void LRoom::FinalizeVisibility(LRoomManager &manager)
|
||||
{
|
||||
// make sure all lights needed are turned on
|
||||
|
||||
// int last_sob = m_iFirstSOB + m_iNumSOBs;
|
||||
// for (int n=m_iFirstSOB; n<last_sob; n++)
|
||||
// {
|
||||
|
13
lroom.h
13
lroom.h
@ -54,8 +54,12 @@ class LRoom
|
||||
private:
|
||||
|
||||
public:
|
||||
static const int SOFT_SHOW_BIT = 18;
|
||||
static const int SOFT_HIDE_BIT = 19;
|
||||
// using flags we can determine which the object is visible to - the camera, or the lights (i.e. shadow caster), or both
|
||||
static const int LAYER_LIGHT_BIT = 18;
|
||||
static const int LAYER_CAMERA_BIT = 19;
|
||||
|
||||
static const int LAYER_MASK_LIGHT = 1 << LAYER_LIGHT_BIT;
|
||||
static const int LAYER_MASK_CAMERA = 1 << LAYER_CAMERA_BIT;
|
||||
|
||||
// static objects are stored in the manager in a contiguous list
|
||||
int m_iFirstSOB;
|
||||
@ -64,6 +68,9 @@ public:
|
||||
// dynamic objects
|
||||
LVector<LDob> m_DOBs;
|
||||
|
||||
// local lights affecting this room
|
||||
LVector<int> m_LocalLights;
|
||||
|
||||
// portals are stored in the manager in a contiguous list
|
||||
int m_iFirstPortal;
|
||||
int m_iNumPortals;
|
||||
@ -130,7 +137,7 @@ public:
|
||||
// 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
|
||||
// objects can still be rendered outside immediate view for casting shadows.
|
||||
static void SoftShow(VisualInstance * pVI, bool bShow);
|
||||
static void SoftShow(VisualInstance * pVI, uint32_t show_flags);
|
||||
|
||||
private:
|
||||
// whether lportal thinks this room is currently visible
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#include "core/math/quick_hull.h"
|
||||
#include "ldebug.h"
|
||||
#include "scene/3d/light.h"
|
||||
|
||||
// save typing, I am lazy
|
||||
#define LMAN m_pManager
|
||||
@ -39,17 +40,21 @@ void LRoomConverter::Convert(LRoomManager &manager)
|
||||
LPRINT(5, "running convert");
|
||||
|
||||
LMAN = &manager;
|
||||
|
||||
// force clear all arrays
|
||||
manager.ReleaseResources(true);
|
||||
|
||||
int count = CountRooms();
|
||||
|
||||
LMAN->m_SOBs.clear();
|
||||
LMAN->m_ShadowCasters_SOB.clear();
|
||||
//LMAN->m_SOBs.clear();
|
||||
//LMAN->m_ShadowCasters_SOB.clear();
|
||||
int num_global_lights = LMAN->m_Lights.size();
|
||||
|
||||
// make sure bitfield is right size for number of rooms
|
||||
LMAN->m_BF_visible_rooms.Create(count);
|
||||
|
||||
|
||||
LMAN->m_Rooms.clear(true);
|
||||
// LMAN->m_Rooms.clear(true);
|
||||
LMAN->m_Rooms.resize(count);
|
||||
|
||||
m_TempRooms.clear(true);
|
||||
@ -68,7 +73,11 @@ void LRoomConverter::Convert(LRoomManager &manager)
|
||||
LMAN->m_BF_master_SOBs.Create(num_sobs);
|
||||
LMAN->m_BF_master_SOBs_prev.Create(num_sobs);
|
||||
|
||||
LMAN->m_BF_ActiveLights.Create(LMAN->m_Lights.size());
|
||||
LMAN->m_BF_ActiveLights_prev.Create(LMAN->m_Lights.size());
|
||||
|
||||
// must be done after the bitfields
|
||||
Convert_Lights();
|
||||
Convert_ShadowCasters();
|
||||
|
||||
// hide all in preparation for first frame
|
||||
@ -78,7 +87,7 @@ void LRoomConverter::Convert(LRoomManager &manager)
|
||||
m_TempRooms.clear(true);
|
||||
|
||||
// clear out the local room lights, leave only global lights
|
||||
LMAN->m_Lights.resize(num_global_lights);
|
||||
//LMAN->m_Lights.resize(num_global_lights);
|
||||
Lawn::LDebug::m_bRunning = true;
|
||||
}
|
||||
|
||||
@ -118,6 +127,25 @@ int LRoomConverter::FindRoom_ByName(String szName) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
void LRoomConverter::Convert_Room_SetDefaultCullMask_Recursive(Node * pParent)
|
||||
{
|
||||
int nChildren = pParent->get_child_count();
|
||||
for (int n=0; n<nChildren; n++)
|
||||
{
|
||||
Node * pChild = pParent->get_child(n);
|
||||
|
||||
// default cull mask should always be visible to camera and lights
|
||||
VisualInstance * pVI = Object::cast_to<VisualInstance>(pChild);
|
||||
if (pVI)
|
||||
{
|
||||
// LRoom::SoftShow(pVI, LRoom::LAYER_MASK_CAMERA | LRoom::LAYER_MASK_LIGHT);
|
||||
}
|
||||
|
||||
Convert_Room_SetDefaultCullMask_Recursive(pChild);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LRoomConverter::Convert_Room_FindObjects_Recursive(Node * pParent, LRoom &lroom, LAABB &bb_room)
|
||||
{
|
||||
int nChildren = pParent->get_child_count();
|
||||
@ -135,10 +163,18 @@ void LRoomConverter::Convert_Room_FindObjects_Recursive(Node * pParent, LRoom &l
|
||||
if (Node_IsBound(pChild))
|
||||
continue;
|
||||
|
||||
// lights
|
||||
if (Node_IsLight(pChild))
|
||||
{
|
||||
LRoom_DetectedLight(lroom, pChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
VisualInstance * pVI = Object::cast_to<VisualInstance>(pChild);
|
||||
if (pVI)
|
||||
{
|
||||
|
||||
|
||||
LPRINT(2, "\t\tFound VI : " + pVI->get_name());
|
||||
|
||||
|
||||
@ -153,6 +189,9 @@ void LRoomConverter::Convert_Room_FindObjects_Recursive(Node * pParent, LRoom &l
|
||||
|
||||
//lroom.m_SOBs.push_back(sob);
|
||||
LRoom_PushBackSOB(lroom, sob);
|
||||
|
||||
// take away layer 0 from the sob, so it can be culled effectively
|
||||
pVI->set_layer_mask(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -193,6 +232,9 @@ bool LRoomConverter::Convert_Room(Spatial * pNode, int lroomID)
|
||||
LAABB bb_room;
|
||||
bb_room.SetToMaxOpposite();
|
||||
|
||||
// set default cull masks
|
||||
Convert_Room_SetDefaultCullMask_Recursive(pNode);
|
||||
|
||||
// recursively find statics
|
||||
Convert_Room_FindObjects_Recursive(pNode, lroom, bb_room);
|
||||
|
||||
@ -309,15 +351,209 @@ void LRoomConverter::Convert_HideAll()
|
||||
}
|
||||
}
|
||||
|
||||
void LRoomConverter::Convert_Lights()
|
||||
{
|
||||
// trace local lights out from rooms and add to each room the light affects
|
||||
for (int n=0; n<LMAN->m_Lights.size(); n++)
|
||||
{
|
||||
LLight &l = LMAN->m_Lights[n];
|
||||
if (l.IsGlobal())
|
||||
continue; // ignore globals .. affect all rooms
|
||||
|
||||
Light_Trace(n);
|
||||
}
|
||||
}
|
||||
|
||||
void LRoomConverter::Light_Trace(int iLightID)
|
||||
{
|
||||
|
||||
LLight &l = LMAN->m_Lights[iLightID];
|
||||
|
||||
LPRINT(5,"\nLight_Trace " + itos (iLightID) + " direction " + l.m_ptDir);
|
||||
|
||||
// reset the planes pool for each render out from the source room
|
||||
LMAN->m_Pool.Reset();
|
||||
|
||||
|
||||
// the first set of planes are blank
|
||||
unsigned int pool_member = LMAN->m_Pool.Request();
|
||||
assert (pool_member != -1);
|
||||
|
||||
LVector<Plane> &planes = LMAN->m_Pool.Get(pool_member);
|
||||
planes.clear();
|
||||
|
||||
Lawn::LDebug::m_iTabDepth = 0;
|
||||
|
||||
Light_TraceRecursive(0, LMAN->m_Rooms[l.m_RoomID], l, iLightID, planes);
|
||||
}
|
||||
|
||||
|
||||
void LRoomConverter::Light_TraceRecursive(int depth, LRoom &lroom, const LLight &light, int iLightID, const LVector<Plane> &planes)
|
||||
{
|
||||
// prevent too much depth
|
||||
if (depth > 8)
|
||||
{
|
||||
LPRINT_RUN(2, "\t\t\tLight_TraceRecursive DEPTH LIMIT REACHED");
|
||||
return;
|
||||
}
|
||||
|
||||
Lawn::LDebug::m_iTabDepth = depth;
|
||||
LPRINT_RUN(2, "ROOM " + lroom.get_name() + " affected by local light");
|
||||
|
||||
|
||||
// add to the local lights affecting this room
|
||||
// already in list?
|
||||
bool bAlreadyInList = false;
|
||||
for (int n=0; n<lroom.m_LocalLights.size(); n++)
|
||||
{
|
||||
if (lroom.m_LocalLights[n] == iLightID)
|
||||
{
|
||||
bAlreadyInList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// add to local lights if not already in list
|
||||
if (!bAlreadyInList)
|
||||
{
|
||||
lroom.m_LocalLights.push_back(iLightID);
|
||||
}
|
||||
|
||||
|
||||
// look through every portal out
|
||||
for (int n=0; n<lroom.m_iNumPortals; n++)
|
||||
{
|
||||
int portalID = lroom.m_iFirstPortal + n;
|
||||
|
||||
const LPortal &port = LMAN->m_Portals[portalID];
|
||||
|
||||
LPRINT_RUN(2, "\tPORTAL " + itos (n) + " (" + itos(portalID) + ") " + port.get_name() + " normal " + port.m_Plane.normal);
|
||||
|
||||
float dot = port.m_Plane.normal.dot(light.m_ptDir);
|
||||
|
||||
if (dot <= 0.0f)
|
||||
{
|
||||
LPRINT_RUN(2, "\t\tCULLED (wrong direction)");
|
||||
continue;
|
||||
}
|
||||
|
||||
// is it culled by the planes?
|
||||
LPortal::eClipResult overall_res = LPortal::eClipResult::CLIP_INSIDE;
|
||||
|
||||
// cull portal with planes
|
||||
for (int l=0; l<planes.size(); l++)
|
||||
{
|
||||
LPortal::eClipResult res = port.ClipWithPlane(planes[l]);
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case LPortal::eClipResult::CLIP_OUTSIDE:
|
||||
overall_res = res;
|
||||
break;
|
||||
case LPortal::eClipResult::CLIP_PARTIAL:
|
||||
overall_res = res;
|
||||
break;
|
||||
default: // suppress warning
|
||||
break;
|
||||
}
|
||||
|
||||
if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE)
|
||||
break;
|
||||
}
|
||||
|
||||
// this portal is culled
|
||||
if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE)
|
||||
{
|
||||
LPRINT_RUN(2, "\t\tCULLED (outside planes)");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
LRoom &linked_room = LMAN->Portal_GetLinkedRoom(port);
|
||||
|
||||
|
||||
// recurse into that portal
|
||||
unsigned int uiPoolMem = LMAN->m_Pool.Request();
|
||||
if (uiPoolMem != -1)
|
||||
{
|
||||
// get a vector of planes from the pool
|
||||
LVector<Plane> &new_planes = LMAN->m_Pool.Get(uiPoolMem);
|
||||
|
||||
// copy the existing planes
|
||||
new_planes.copy_from(planes);
|
||||
|
||||
// add the planes for the portal
|
||||
port.AddLightPlanes(*LMAN, light, new_planes, false);
|
||||
|
||||
Light_TraceRecursive(depth + 1, linked_room, light, iLightID, new_planes);
|
||||
// for debugging need to reset tab depth
|
||||
Lawn::LDebug::m_iTabDepth = depth;
|
||||
|
||||
// we no longer need these planes
|
||||
LMAN->m_Pool.Free(uiPoolMem);
|
||||
}
|
||||
else
|
||||
{
|
||||
// planes pool is empty!
|
||||
// This will happen if the view goes through shedloads of portals
|
||||
// The solution is either to increase the plane pool size, or build levels
|
||||
// with views through multiple portals. Looking through multiple portals is likely to be
|
||||
// slow anyway because of the number of planes to test.
|
||||
WARN_PRINT_ONCE("LRoom_FindShadowCasters_Recursive : Planes pool is empty");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LRoomConverter::Convert_ShadowCasters()
|
||||
{
|
||||
LPRINT(5,"Convert_ShadowCasters ... numlights " + itos (LMAN->m_Lights.size()));
|
||||
int nLights = LMAN->m_Lights.size();
|
||||
LPRINT(5,"\nConvert_ShadowCasters ... numlights " + itos (nLights));
|
||||
|
||||
for (int n=0; n<LMAN->m_Rooms.size(); n++)
|
||||
|
||||
for (int l=0; l<nLights; l++)
|
||||
{
|
||||
LPRINT(2,"\tRoom " + itos(n));
|
||||
LRoom &lroom = LMAN->m_Rooms[n];
|
||||
LRoom_FindShadowCasters(lroom);
|
||||
const LLight &light = LMAN->m_Lights[l];
|
||||
String sz = "Light " + itos (l);
|
||||
if (light.IsGlobal())
|
||||
sz += " GLOBAL";
|
||||
else
|
||||
sz += " LOCAL from room " + itos(light.m_RoomID);
|
||||
|
||||
LPRINT(5, sz + " direction " + light.m_ptDir);
|
||||
|
||||
for (int n=0; n<LMAN->m_Rooms.size(); n++)
|
||||
{
|
||||
LRoom &lroom = LMAN->m_Rooms[n];
|
||||
|
||||
// global lights affect every room
|
||||
bool bAffectsRoom = true;
|
||||
|
||||
// if the light is local, does it affect this room?
|
||||
if (!light.IsGlobal())
|
||||
{
|
||||
// a local light .. does it affect this room?
|
||||
bAffectsRoom = false;
|
||||
for (int i=0; i<lroom.m_LocalLights.size(); i++)
|
||||
{
|
||||
// if the light id is found among the local lights for this room
|
||||
if (lroom.m_LocalLights[i] == l)
|
||||
{
|
||||
bAffectsRoom = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bAffectsRoom)
|
||||
{
|
||||
LPRINT(2,"\n\tAFFECTS room " + itos(n) + ", " + lroom.get_name());
|
||||
LRoom_FindShadowCasters_FromLight(lroom, light);
|
||||
//LRoom_FindShadowCasters(lroom, l, light);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,17 +637,37 @@ int LRoomConverter::CountRooms()
|
||||
|
||||
|
||||
// find all objects that cast shadows onto the objects in this room
|
||||
void LRoomConverter::LRoom_FindShadowCasters(LRoom &lroom)
|
||||
{
|
||||
// each global light, and each light affecting this room
|
||||
for (int n=0; n<LMAN->m_Lights.size(); n++)
|
||||
{
|
||||
LRoom_FindShadowCasters_FromLight(lroom, LMAN->m_Lights[n]);
|
||||
}
|
||||
//void LRoomConverter::LRoom_FindShadowCasters(LRoom &lroom, int lightID, const LLight &light)
|
||||
//{
|
||||
// // each global light, and each light affecting this room
|
||||
// for (int n=0; n<LMAN->m_Lights.size(); n++)
|
||||
// {
|
||||
// // if the light is not a global light, we are only interested if it emits from this room
|
||||
// const LLight &l = LMAN->m_Lights[n];
|
||||
|
||||
// bool bAffectsRoom = true;
|
||||
// if (l.m_RoomID != -1)
|
||||
// {
|
||||
// // a local light .. does it affect this room?
|
||||
// bAffectsRoom = false;
|
||||
// for (int i=0; i<lroom.m_LocalLights.size(); i++)
|
||||
// {
|
||||
// // if the light id is found among the local lights for this room
|
||||
// if (lroom.m_LocalLights[i] == n)
|
||||
// {
|
||||
// bAffectsRoom = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (bAffectsRoom)
|
||||
// LRoom_FindShadowCasters_FromLight(lroom, l);
|
||||
// }
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
// return;
|
||||
//}
|
||||
|
||||
void LRoomConverter::LRoom_AddShadowCaster_SOB(LRoom &lroom, int sobID)
|
||||
{
|
||||
@ -461,7 +717,7 @@ void LRoomConverter::LRoom_FindShadowCasters_FromLight(LRoom &lroom, const LLigh
|
||||
planes.clear();
|
||||
|
||||
Lawn::LDebug::m_iTabDepth = 0;
|
||||
LRoom_FindShadowCasters_Recursive(lroom, 0, lroom, light, planes);
|
||||
LRoom_FindShadowCasters_Recursive(lroom, 1, lroom, light, planes);
|
||||
|
||||
}
|
||||
|
||||
@ -507,7 +763,10 @@ void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int
|
||||
|
||||
|
||||
if (r_min > 0.0f)
|
||||
// if (r_max < 0.0f)
|
||||
{
|
||||
//LPRINT_RUN(2, "\tR_MIN is " + String(Variant(r_min)) + " R_MAX is " + String(Variant(r_max))+ ", for plane " + itos(p));
|
||||
|
||||
bShow = false;
|
||||
break;
|
||||
}
|
||||
@ -518,6 +777,10 @@ void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int
|
||||
LPRINT_RUN(2, "\tcaster " + itos(n) + ", " + sob.GetSpatial()->get_name());
|
||||
LRoom_AddShadowCaster_SOB(source_lroom, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
//LPRINT_RUN(2, "\tculled " + itos(n) + ", " + sob.GetSpatial()->get_name());
|
||||
}
|
||||
}
|
||||
|
||||
// look through every portal out
|
||||
@ -530,8 +793,21 @@ void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int
|
||||
LPRINT_RUN(2, "\tPORTAL " + itos (n) + " (" + itos(portalID) + ") " + port.get_name() + " normal " + port.m_Plane.normal);
|
||||
|
||||
// cull with light direction
|
||||
float dot = port.m_Plane.normal.dot(light.m_ptDir);
|
||||
if (dot <= 0.0f)
|
||||
float dot;
|
||||
if (light.m_eType == LLight::LT_DIRECTIONAL)
|
||||
{
|
||||
dot = port.m_Plane.normal.dot(light.m_ptDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// cull with light direction to portal
|
||||
Vector3 ptLightToPort = port.m_ptCentre - light.m_ptPos;
|
||||
dot = port.m_Plane.normal.dot(ptLightToPort);
|
||||
}
|
||||
|
||||
|
||||
// float dot = port.m_Plane.normal.dot(light.m_ptDir);
|
||||
if (dot >= 0.0f)
|
||||
{
|
||||
LPRINT_RUN(2, "\t\tCULLED (wrong direction)");
|
||||
continue;
|
||||
@ -583,7 +859,7 @@ void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int
|
||||
new_planes.copy_from(planes);
|
||||
|
||||
// add the planes for the portal
|
||||
port.AddLightPlanes(light, new_planes);
|
||||
port.AddLightPlanes(*LMAN, light, new_planes, true);
|
||||
|
||||
LRoom_FindShadowCasters_Recursive(source_lroom, depth + 1, linked_room, light, new_planes);
|
||||
// for debugging need to reset tab depth
|
||||
@ -696,6 +972,71 @@ void LRoomConverter::LRoom_MakePortalFinalList(LRoom &lroom, LTempRoom &troom)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LRoomConverter::LRoom_DetectedLight(LRoom &lroom, Node * pNode)
|
||||
{
|
||||
Light * pLight = Object::cast_to<Light>(pNode);
|
||||
assert (pLight);
|
||||
|
||||
LMAN->LightCreate(pLight, lroom.m_RoomID);
|
||||
/*
|
||||
// create new light
|
||||
LLight l;
|
||||
l.SetDefaults();
|
||||
l.m_GodotID = pLight->get_instance_id();
|
||||
// direction
|
||||
Transform tr = pLight->get_global_transform();
|
||||
l.m_ptPos = tr.origin;
|
||||
l.m_ptDir = -tr.basis.get_axis(2); // or possibly get_axis .. z is what we want
|
||||
l.m_fMaxDist = pLight->get_param(Light::PARAM_SHADOW_MAX_DISTANCE);
|
||||
|
||||
// source room ID
|
||||
l.m_RoomID = lroom.m_RoomID;
|
||||
|
||||
bool bOK = false;
|
||||
|
||||
// what kind of light?
|
||||
SpotLight * pSL = Object::cast_to<SpotLight>(pNode);
|
||||
if (pSL)
|
||||
{
|
||||
LPRINT(2, "\tSPOTLIGHT detected " + pNode->get_name());
|
||||
l.m_eType = LLight::LT_SPOTLIGHT;
|
||||
l.m_fSpread = pSL->get_param(Light::PARAM_SPOT_ANGLE);
|
||||
|
||||
bOK = true;
|
||||
}
|
||||
|
||||
OmniLight * pOL = Object::cast_to<OmniLight>(pNode);
|
||||
if (pOL)
|
||||
{
|
||||
LPRINT(2, "\tOMNILIGHT detected " + pNode->get_name());
|
||||
l.m_eType = LLight::LT_OMNI;
|
||||
bOK = true;
|
||||
}
|
||||
|
||||
DirectionalLight * pDL = Object::cast_to<DirectionalLight>(pNode);
|
||||
if (pDL)
|
||||
{
|
||||
LPRINT(2, "\tDIRECTIONALLIGHT detected " + pNode->get_name());
|
||||
l.m_eType = LLight::LT_DIRECTIONAL;
|
||||
bOK = true;
|
||||
}
|
||||
|
||||
// don't add if not recognised
|
||||
if (!bOK)
|
||||
{
|
||||
LPRINT(2, "\tLIGHT type unrecognised " + pNode->get_name());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// turn the local light off to start with
|
||||
pLight->hide();
|
||||
|
||||
LMAN->m_Lights.push_back(l);
|
||||
*/
|
||||
}
|
||||
|
||||
// found a portal mesh! create a matching LPortal
|
||||
void LRoomConverter::LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, MeshInstance * pMeshInstance, String szLinkRoom)
|
||||
{
|
||||
@ -792,6 +1133,16 @@ void LRoomConverter::TRoom_MakeOppositePortal(const LPortal &port, int iRoomOrig
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
// helper
|
||||
bool LRoomConverter::Node_IsLight(Node * pNode) const
|
||||
{
|
||||
Light * pLight = Object::cast_to<Light>(pNode);
|
||||
if (!pLight)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LRoomConverter::Node_IsRoom(Node * pNode) const
|
||||
{
|
||||
Spatial * pSpat = Object::cast_to<Spatial>(pNode);
|
||||
|
@ -89,11 +89,13 @@ private:
|
||||
void Convert_Rooms();
|
||||
bool Convert_Room(Spatial * pNode, int lroomID);
|
||||
void Convert_Room_FindObjects_Recursive(Node * pParent, LRoom &lroom, LAABB &bb_room);
|
||||
void Convert_Room_SetDefaultCullMask_Recursive(Node * pParent);
|
||||
|
||||
void Convert_Portals();
|
||||
void Convert_Bounds();
|
||||
bool Convert_Bound(LRoom &lroom, MeshInstance * pMI);
|
||||
void Convert_ShadowCasters();
|
||||
void Convert_Lights();
|
||||
void Convert_HideAll();
|
||||
|
||||
|
||||
@ -104,8 +106,13 @@ private:
|
||||
LPortal * LRoom_RequestNewPortal(LRoom &lroom);
|
||||
void LRoom_PushBackSOB(LRoom &lroom, const LSob &sob);
|
||||
|
||||
// lights
|
||||
void LRoom_DetectedLight(LRoom &lroom, Node * pNode);
|
||||
void Light_Trace(int iLightID);
|
||||
void Light_TraceRecursive(int depth, LRoom &lroom, const LLight &light, int iLightID, const LVector<Plane> &planes);
|
||||
|
||||
// shadows
|
||||
void LRoom_FindShadowCasters(LRoom &lroom);
|
||||
// void LRoom_FindShadowCasters(LRoom &lroom, int lightID, const LLight &light);
|
||||
void LRoom_FindShadowCasters_FromLight(LRoom &lroom, const LLight &light);
|
||||
void LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int depth, LRoom &lroom, const LLight &light, const LVector<Plane> &planes);
|
||||
void LRoom_AddShadowCaster_SOB(LRoom &lroom, int sobID);
|
||||
@ -118,6 +125,7 @@ private:
|
||||
bool Node_IsPortal(Node * pNode) const;
|
||||
bool Node_IsBound(Node * pNode) const;
|
||||
bool Node_IsIgnore(Node * pNode) const;
|
||||
bool Node_IsLight(Node * pNode) const;
|
||||
|
||||
int FindRoom_ByName(String szName) const;
|
||||
|
||||
|
@ -43,6 +43,7 @@ LRoomManager::LRoomManager()
|
||||
|
||||
m_bDebugPlanes = false;
|
||||
m_bDebugBounds = false;
|
||||
m_bDebugLights = false;
|
||||
}
|
||||
|
||||
int LRoomManager::FindClosestRoom(const Vector3 &pt) const
|
||||
@ -220,9 +221,20 @@ void LRoomManager::CreateDebug()
|
||||
m_mat_Debug_Bounds = Ref<SpatialMaterial>(memnew(SpatialMaterial));
|
||||
//m_mat_Debug_Bounds->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
|
||||
m_mat_Debug_Bounds->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
|
||||
m_mat_Debug_Bounds->set_cull_mode(SpatialMaterial::CULL_DISABLED);
|
||||
m_mat_Debug_Bounds->set_albedo(Color(0, 0, 1, 0.4));
|
||||
b->set_material_override(m_mat_Debug_Bounds);
|
||||
b->hide();
|
||||
|
||||
{
|
||||
ImmediateGeometry * b = memnew(ImmediateGeometry);
|
||||
b->set_name("debug_lights");
|
||||
add_child(b);
|
||||
m_ID_DebugLights = b->get_instance_id();
|
||||
b->set_material_override(m_mat_Debug_Bounds);
|
||||
//b->hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -231,7 +243,12 @@ ObjectID LRoomManager::DobRegister_FindVIRecursive(Node * pNode) const
|
||||
// is the node a VI?
|
||||
VisualInstance * pVI = Object::cast_to<VisualInstance>(pNode);
|
||||
if (pVI)
|
||||
{
|
||||
// take away layer 0 from the dob, so it can be culled effectively
|
||||
pVI->set_layer_mask(0);
|
||||
|
||||
return pVI->get_instance_id();
|
||||
}
|
||||
|
||||
// try the children
|
||||
for (int n=0; n<pNode->get_child_count(); n++)
|
||||
@ -453,6 +470,79 @@ bool LRoomManager::dob_unregister(Node * pDOB)
|
||||
}
|
||||
|
||||
|
||||
// common stuff for global and local light creation
|
||||
bool LRoomManager::LightCreate(Light * pLight, int roomID)
|
||||
{
|
||||
// set culling flag for light
|
||||
// 1 is for lighting objects outside the room system
|
||||
pLight->set_cull_mask(1 | LRoom::LAYER_MASK_LIGHT);
|
||||
|
||||
// create new light
|
||||
LLight l;
|
||||
l.SetDefaults();
|
||||
l.m_GodotID = pLight->get_instance_id();
|
||||
|
||||
// direction
|
||||
Transform tr = pLight->get_global_transform();
|
||||
l.m_ptPos = tr.origin;
|
||||
l.m_ptDir = -tr.basis.get_axis(2); // or possibly get_axis .. z is what we want
|
||||
l.m_RoomID = roomID;
|
||||
|
||||
l.m_fMaxDist = pLight->get_param(Light::PARAM_SHADOW_MAX_DISTANCE);
|
||||
|
||||
|
||||
//l.m_eType = LLight::LT_DIRECTIONAL;
|
||||
|
||||
//m_Lights.push_back(l);
|
||||
|
||||
|
||||
bool bOK = false;
|
||||
|
||||
// what kind of light?
|
||||
SpotLight * pSL = Object::cast_to<SpotLight>(pLight);
|
||||
if (pSL)
|
||||
{
|
||||
LPRINT(2, "\tSPOTLIGHT detected " + pLight->get_name());
|
||||
l.m_eType = LLight::LT_SPOTLIGHT;
|
||||
l.m_fSpread = pSL->get_param(Light::PARAM_SPOT_ANGLE);
|
||||
|
||||
bOK = true;
|
||||
}
|
||||
|
||||
OmniLight * pOL = Object::cast_to<OmniLight>(pLight);
|
||||
if (pOL)
|
||||
{
|
||||
LPRINT(2, "\tOMNILIGHT detected " + pLight->get_name());
|
||||
l.m_eType = LLight::LT_OMNI;
|
||||
bOK = true;
|
||||
}
|
||||
|
||||
DirectionalLight * pDL = Object::cast_to<DirectionalLight>(pLight);
|
||||
if (pDL)
|
||||
{
|
||||
LPRINT(2, "\tDIRECTIONALLIGHT detected " + pLight->get_name());
|
||||
l.m_eType = LLight::LT_DIRECTIONAL;
|
||||
bOK = true;
|
||||
}
|
||||
|
||||
// don't add if not recognised
|
||||
if (!bOK)
|
||||
{
|
||||
LPRINT(2, "\tLIGHT type unrecognised " + pLight->get_name());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// turn the local light off to start with
|
||||
if (!l.IsGlobal())
|
||||
pLight->hide();
|
||||
|
||||
m_Lights.push_back(l);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LRoomManager::light_register(Node * pLightNode)
|
||||
{
|
||||
if (!pLightNode)
|
||||
@ -470,18 +560,27 @@ bool LRoomManager::light_register(Node * pLightNode)
|
||||
return false;
|
||||
}
|
||||
|
||||
// create new light
|
||||
LLight l;
|
||||
l.m_GodotID = pLight->get_instance_id();
|
||||
return LightCreate(pLight, -1);
|
||||
|
||||
// direction
|
||||
Transform tr = pLight->get_global_transform();
|
||||
l.m_ptPos = tr.origin;
|
||||
l.m_ptDir = tr.basis.get_axis(2); // or possibly get_axis .. z is what we want
|
||||
// // set culling flag for light
|
||||
// // 1 is for lighting objects outside the room system
|
||||
// pLight->set_cull_mask(1 | LRoom::LAYER_MASK_LIGHT);
|
||||
|
||||
m_Lights.push_back(l);
|
||||
// // create new light
|
||||
// LLight l;
|
||||
// l.SetDefaults();
|
||||
// l.m_GodotID = pLight->get_instance_id();
|
||||
|
||||
return true;
|
||||
// // direction
|
||||
// Transform tr = pLight->get_global_transform();
|
||||
// l.m_ptPos = tr.origin;
|
||||
// l.m_ptDir = -tr.basis.get_axis(2); // or possibly get_axis .. z is what we want
|
||||
// l.m_RoomID = -1;
|
||||
// l.m_eType = LLight::LT_DIRECTIONAL;
|
||||
|
||||
// m_Lights.push_back(l);
|
||||
|
||||
// return true;
|
||||
}
|
||||
|
||||
|
||||
@ -523,6 +622,21 @@ Node * LRoomManager::rooms_get_room(int room_id)
|
||||
return pRoom->GetGodotRoom();
|
||||
}
|
||||
|
||||
void LRoomManager::rooms_set_debug_lights(bool bActive)
|
||||
{
|
||||
m_bDebugLights = bActive;
|
||||
Object * pObj = ObjectDB::get_instance(m_ID_DebugLights);
|
||||
ImmediateGeometry * im = Object::cast_to<ImmediateGeometry>(pObj);
|
||||
if (!im)
|
||||
return;
|
||||
|
||||
if (bActive)
|
||||
im->show();
|
||||
else
|
||||
im->hide();
|
||||
}
|
||||
|
||||
|
||||
void LRoomManager::rooms_set_debug_bounds(bool bActive)
|
||||
{
|
||||
m_bDebugBounds = bActive;
|
||||
@ -610,7 +724,8 @@ void LRoomManager::rooms_set_camera(Node * pCam)
|
||||
m_ID_camera = pCam->get_instance_id();
|
||||
|
||||
// new .. select the cull layer
|
||||
pCamera->set_cull_mask_bit(LRoom::SOFT_HIDE_BIT, false);
|
||||
// 1 is for showing objects outside the room system
|
||||
pCamera->set_cull_mask(1 | LRoom::LAYER_MASK_CAMERA);
|
||||
|
||||
// use this temporarily to force debug
|
||||
// rooms_log_frame();
|
||||
@ -626,7 +741,30 @@ void LRoomManager::rooms_convert()
|
||||
// free memory for current set of rooms, prepare for converting a new game level
|
||||
void LRoomManager::rooms_release()
|
||||
{
|
||||
m_Lights.clear();
|
||||
ReleaseResources(false);
|
||||
}
|
||||
|
||||
void LRoomManager::ReleaseResources(bool bPrepareConvert)
|
||||
{
|
||||
m_ShadowCasters_SOB.clear();
|
||||
m_Rooms.clear(true);
|
||||
m_Portals.clear(true);
|
||||
m_SOBs.clear();
|
||||
|
||||
if (!bPrepareConvert)
|
||||
m_Lights.clear();
|
||||
|
||||
m_ActiveLights.clear();
|
||||
m_ActiveLights_prev.clear();
|
||||
|
||||
m_VisibleRoomList_A.clear();
|
||||
m_VisibleRoomList_B.clear();
|
||||
|
||||
m_MasterList_SOBs.clear();
|
||||
m_MasterList_SOBs_prev.clear();
|
||||
|
||||
m_VisibleList_SOBs.clear();
|
||||
m_CasterList_SOBs.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -645,6 +783,7 @@ void LRoomManager::FrameUpdate_Prepare()
|
||||
|
||||
// keep previous
|
||||
m_BF_master_SOBs_prev.CopyFrom(m_BF_master_SOBs);
|
||||
m_BF_master_SOBs.Blank();
|
||||
|
||||
// note this can be done more efficiently with swapping pointer
|
||||
m_MasterList_SOBs_prev.copy_from(m_MasterList_SOBs);
|
||||
@ -655,7 +794,12 @@ void LRoomManager::FrameUpdate_Prepare()
|
||||
|
||||
m_BF_caster_SOBs.Blank();
|
||||
m_BF_visible_SOBs.Blank();
|
||||
m_BF_master_SOBs.Blank();
|
||||
|
||||
// lights
|
||||
m_BF_ActiveLights_prev.CopyFrom(m_BF_ActiveLights);
|
||||
m_ActiveLights_prev.copy_from(m_ActiveLights);
|
||||
m_ActiveLights.clear();
|
||||
m_BF_ActiveLights.Blank();
|
||||
|
||||
// as we hit visible rooms we will mark them in a bitset, so we can hide any rooms
|
||||
// that are showing that haven't been hit this frame
|
||||
@ -851,7 +995,53 @@ void LRoomManager::FrameUpdate_FinalizeVisibility_SoftShow()
|
||||
{
|
||||
//SoftShow(pVI, sob.m_bSOBVisible);
|
||||
bool bVisible = m_BF_visible_SOBs.GetBit(ID) != 0;
|
||||
LRoom::SoftShow(pVI, bVisible);
|
||||
bool bCaster = m_BF_caster_SOBs.GetBit(ID) != 0;
|
||||
|
||||
uint32_t flags = 0;
|
||||
if (bVisible) flags |= LRoom::LAYER_MASK_CAMERA;
|
||||
if (bCaster) flags |= LRoom::LAYER_MASK_LIGHT;
|
||||
|
||||
LRoom::SoftShow(pVI, flags);
|
||||
}
|
||||
}
|
||||
|
||||
// lights
|
||||
for (int n=0; n<m_ActiveLights.size(); n++)
|
||||
{
|
||||
int lid = m_ActiveLights[n];
|
||||
|
||||
if (!m_BF_ActiveLights_prev.GetBit(lid))
|
||||
{
|
||||
LLight &light = m_Lights[lid];
|
||||
Light * pLight = light.GetGodotLight();
|
||||
if (pLight)
|
||||
{
|
||||
//Lawn::LDebug::print("Showing light " + itos (n));
|
||||
pLight->show();
|
||||
|
||||
// FIX GODOT BUG - light cull mask is not preserved when hiding and showing
|
||||
// set culling flag for light
|
||||
// 1 is for lighting objects outside the room system
|
||||
//pLight->set_shadow(false);
|
||||
//pLight->set_shadow(true);
|
||||
//pLight->set_cull_mask(1 | LRoom::LAYER_MASK_LIGHT);
|
||||
Vector3 ptBugFix = pLight->get_translation();
|
||||
pLight->set_translation(ptBugFix);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int n=0; n<m_ActiveLights_prev.size(); n++)
|
||||
{
|
||||
int lid = m_ActiveLights_prev[n];
|
||||
if (!m_BF_ActiveLights.GetBit(lid))
|
||||
{
|
||||
LLight &light = m_Lights[lid];
|
||||
Light * pLight = light.GetGodotLight();
|
||||
if (pLight)
|
||||
{
|
||||
//Lawn::LDebug::print("Hiding light " + itos (n));
|
||||
pLight->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,7 +1076,17 @@ void LRoomManager::FrameUpdate_FinalizeVisibility_WithinRooms()
|
||||
{
|
||||
int ID = m_MasterList_SOBs[n];
|
||||
LSob &sob = m_SOBs[ID];
|
||||
|
||||
// show / hide is relatively expensive because of propagating messages between nodes ...
|
||||
// should be minimized
|
||||
sob.Show(true);
|
||||
|
||||
// see how expensive show is
|
||||
// for (int t=0; t<10000; t++)
|
||||
// {
|
||||
// sob.Show(false);
|
||||
// sob.Show(true);
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
@ -894,6 +1094,27 @@ void LRoomManager::FrameUpdate_FinalizeVisibility_WithinRooms()
|
||||
|
||||
void LRoomManager::FrameUpdate_DrawDebug(const LCamera &cam, const LRoom &lroom)
|
||||
{
|
||||
// light portal planes
|
||||
if (m_bDebugLights)
|
||||
{
|
||||
Object * pObj = ObjectDB::get_instance(m_ID_DebugLights);
|
||||
ImmediateGeometry * im = Object::cast_to<ImmediateGeometry>(pObj);
|
||||
if (!im)
|
||||
return;
|
||||
|
||||
im->clear();
|
||||
|
||||
im->begin(Mesh::PRIMITIVE_TRIANGLES, NULL);
|
||||
|
||||
int nVerts = m_DebugPortalLightPlanes.size();
|
||||
|
||||
for (int n=0; n<nVerts; n++)
|
||||
{
|
||||
im->add_vertex(m_DebugPortalLightPlanes[n]);
|
||||
}
|
||||
im->end();
|
||||
}
|
||||
|
||||
if (m_bDebugPlanes)
|
||||
{
|
||||
Vector3 ptCam = cam.m_ptPos;
|
||||
@ -949,6 +1170,8 @@ void LRoomManager::FrameUpdate_DrawDebug(const LCamera &cam, const LRoom &lroom)
|
||||
|
||||
im->end();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LRoomManager::_notification(int p_what) {
|
||||
@ -989,6 +1212,7 @@ void LRoomManager::_bind_methods()
|
||||
ClassDB::bind_method(D_METHOD("rooms_set_active"), &LRoomManager::rooms_set_active);
|
||||
ClassDB::bind_method(D_METHOD("rooms_set_debug_planes"), &LRoomManager::rooms_set_debug_planes);
|
||||
ClassDB::bind_method(D_METHOD("rooms_set_debug_bounds"), &LRoomManager::rooms_set_debug_bounds);
|
||||
ClassDB::bind_method(D_METHOD("rooms_set_debug_lights"), &LRoomManager::rooms_set_debug_lights);
|
||||
|
||||
|
||||
// functions to add dynamic objects to the culling system
|
||||
|
@ -90,7 +90,14 @@ private:
|
||||
|
||||
// static objects
|
||||
LVector<LSob> m_SOBs;
|
||||
|
||||
// lights
|
||||
LVector<LLight> m_Lights;
|
||||
// active lights
|
||||
LVector<int> m_ActiveLights;
|
||||
LVector<int> m_ActiveLights_prev;
|
||||
Lawn::LBitField_Dynamic m_BF_ActiveLights;
|
||||
Lawn::LBitField_Dynamic m_BF_ActiveLights_prev;
|
||||
|
||||
// master list of shadow casters for each room
|
||||
LVector<uint32_t> m_ShadowCasters_SOB;
|
||||
@ -127,8 +134,10 @@ private:
|
||||
bool DobRegister(Spatial * pDOB, float radius, int iRoom);
|
||||
ObjectID DobRegister_FindVIRecursive(Node * pNode) const;
|
||||
bool DobTeleport(Spatial * pDOB, int iNewRoomID);
|
||||
bool LightCreate(Light * pLight, int roomID);
|
||||
void CreateDebug();
|
||||
void DobChangeVisibility(Spatial * pDOB, const LRoom * pOld, const LRoom * pNew);
|
||||
void ReleaseResources(bool bPrepareConvert);
|
||||
|
||||
|
||||
// helper funcs
|
||||
@ -147,12 +156,16 @@ public:
|
||||
// whether debug planes is switched on
|
||||
bool m_bDebugPlanes;
|
||||
bool m_bDebugBounds;
|
||||
bool m_bDebugLights;
|
||||
|
||||
// the planes are shown as a list of lines from the camera to the portal verts
|
||||
LVector<Vector3> m_DebugPlanes;
|
||||
LVector<Vector3> m_DebugPortalLightPlanes;
|
||||
|
||||
private:
|
||||
ObjectID m_ID_DebugPlanes;
|
||||
ObjectID m_ID_DebugBounds;
|
||||
ObjectID m_ID_DebugLights;
|
||||
Ref<SpatialMaterial> m_mat_Debug_Planes;
|
||||
Ref<SpatialMaterial> m_mat_Debug_Bounds;
|
||||
|
||||
@ -179,6 +192,7 @@ public:
|
||||
void rooms_set_active(bool bActive);
|
||||
void rooms_set_debug_planes(bool bActive);
|
||||
void rooms_set_debug_bounds(bool bActive);
|
||||
void rooms_set_debug_lights(bool bActive);
|
||||
|
||||
// 0 to 6 .. defaults to 4 which is (2) in our priorities (i.e. 6 - level)
|
||||
void rooms_set_logging(int level);
|
||||
|
Loading…
Reference in New Issue
Block a user