mirror of
https://github.com/Relintai/godot-lportal.git
synced 2024-11-11 10:52:09 +01:00
Preliminary lighting support
This commit is contained in:
parent
09dd7e90d7
commit
0a4f14b6c9
18
README.md
18
README.md
@ -10,18 +10,19 @@ 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 working, I am now currently working on shadow casters. In a simple system you would pre-bake your lighting with e.g. lightmaps, however with realtime lights, shadow casters outside the view of the camera can cast shadows onto the objects in view. Rather than rendering everything as a possible shadow caster, it makes sense to use the same room / portal system to cull out as many shadow casters as possible that could not contribute to the final image.
|
||||
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.
|
||||
|
||||
Note that I've had to move from showing and hiding objects, to using Godot object and camera layers to differentiate between which objects to render from the camera and which for shadows, at least for now. This is a little hacky, and might interfere with your own code if you are using godot layers - layer 1 (default layer) is unset for all objects, and 19 and 20 are currently used by the system to determine whether objects are shadow casters or visible (or both), respectively.
|
||||
I am now working on shadows. Shadows can be cast by objects that are not 'in view', thus with the naive culling system, in some circumstances shadows will pop into and out of view.
|
||||
|
||||
I've also uncovered a bug in Godot core shadow casting:
|
||||
https://github.com/godotengine/godot/pull/32475
|
||||
There are three possibilities here:
|
||||
1) Draw everything in the shadow pass (use Godot default octree). This gets rid of artefacts but would be slow and negate a lot of the benefits of visibility culling.
|
||||
2) Draw everything roughly around the visible objects. The current version does this now, with the main pass only rendering objects in view, but the shadow pass draws everything within the rooms in view. This is better than naive version, but still can suffer 'popping' of shadows at doorways.
|
||||
3) More intelligent system to try and work out which shadow casters are relevant to the view.
|
||||
|
||||
which I'm finding the best fix for to help with the showing / hiding of shadow casters. There is a workaround but I'm keen to get it fixed in core.
|
||||
Note that I've had to move from showing and hiding objects, to using Godot object and camera layers to differentiate between which objects to render from the camera and which for shadows, at least for now. This is a little hacky, and might interfere with your own code if you are using godot layers - layer 1 (default layer) is unset for all objects, and 19 and 20 are currently used by the system to toggle visibility internally.
|
||||
|
||||
## Roadmap
|
||||
* Auto conversion of named room spatials and portal mesh instances to LRoom and LPortal DONE
|
||||
@ -36,10 +37,11 @@ which I'm finding the best fix for to help with the showing / hiding of shadow c
|
||||
* Optional convex hull bound for rooms DONE
|
||||
* Add debug graphical view of portal planes DONE
|
||||
* Add debug graphical view of room bounds DONE
|
||||
* Dealing with shadows from objects outside of view ONGOING
|
||||
* Dealing with shadows from objects outside of view
|
||||
* Bug fixing / testing ONGOING
|
||||
* Closable portals
|
||||
* PVS (primary and secondary)
|
||||
* Investigate multiple passes (shadows, lights)
|
||||
|
||||
## Instructions
|
||||
See [INSTRUCTIONS.md](INSTRUCTIONS.md) and [TUTORIAL.md](TUTORIAL.md)
|
||||
|
@ -6,7 +6,7 @@ namespace Lawn
|
||||
int LDebug::m_iLoggingLevel = 0; // 2
|
||||
int LDebug::m_iWarningLevel = 0;
|
||||
int LDebug::m_iTabDepth = 0;
|
||||
bool LDebug::m_bRunning = false;
|
||||
bool LDebug::m_bRunning = true;
|
||||
|
||||
|
||||
void LDebug::print(String sz)
|
||||
|
10
ldebug.h
10
ldebug.h
@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
//#define LPRINT_RUN(a, b) ;
|
||||
#define LPRINT_RUN(a, b) ;
|
||||
|
||||
#define LPRINT_RUN(a, b) {String sz;\
|
||||
for (int n=0; n<Lawn::LDebug::m_iTabDepth; n++)\
|
||||
sz += "\t";\
|
||||
LPRINT(a, sz + b);}
|
||||
//#define LPRINT_RUN(a, b) {String sz;\
|
||||
//for (int n=0; n<Lawn::LDebug::m_iTabDepth; n++)\
|
||||
//sz += "\t";\
|
||||
//LPRINT(a, sz + b);}
|
||||
|
||||
#define LPRINT(a, b) if (!Lawn::LDebug::m_bRunning) {\
|
||||
if (a >= Lawn::LDebug::m_iLoggingLevel)\
|
||||
|
104
ldob.cpp
104
ldob.cpp
@ -24,8 +24,67 @@
|
||||
|
||||
#include "ldob.h"
|
||||
#include "scene/3d/mesh_instance.h"
|
||||
#include "scene/3d/light.h"
|
||||
|
||||
|
||||
void LHidable::Hidable_Create(Node * pNode)
|
||||
{
|
||||
// m_pNode = 0; m_pParent = 0; m_bShow = true;
|
||||
m_pNode = pNode;
|
||||
m_pParent = m_pNode->get_parent();
|
||||
m_bShow = true;
|
||||
}
|
||||
|
||||
|
||||
void LHidable::Show(bool bShow)
|
||||
{
|
||||
// noop
|
||||
if (bShow == m_bShow)
|
||||
return;
|
||||
|
||||
// new state
|
||||
m_bShow = bShow;
|
||||
|
||||
assert (m_pParent);
|
||||
|
||||
if (bShow)
|
||||
{
|
||||
// add to tree
|
||||
m_pParent->add_child(m_pNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove from tree
|
||||
m_pParent->remove_child(m_pNode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LLight::SetDefaults()
|
||||
{
|
||||
m_GodotID = 0;
|
||||
m_eType = LT_DIRECTIONAL;
|
||||
m_fSpread = 0.0f; // for spotlight
|
||||
m_fMaxDist = 100.0f;
|
||||
m_RoomID = -1;
|
||||
|
||||
m_FirstCaster = 0;
|
||||
m_NumCasters = 0;
|
||||
}
|
||||
|
||||
|
||||
Light * LLight::GetGodotLight()
|
||||
{
|
||||
Object * pObj = ObjectDB::get_instance(m_GodotID);
|
||||
Light * p = Object::cast_to<Light>(pObj);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
Spatial * LSob::GetSpatial() const
|
||||
{
|
||||
Object * pObj = ObjectDB::get_instance(m_ID);
|
||||
@ -59,18 +118,53 @@ VisualInstance * LSob::GetVI() const
|
||||
return pVI;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void LSob::Show(bool bShow)
|
||||
{
|
||||
// noop
|
||||
if (bShow == m_bShow)
|
||||
return;
|
||||
|
||||
// new state
|
||||
m_bShow = bShow;
|
||||
|
||||
Spatial * pS = GetSpatial();
|
||||
if (!pS)
|
||||
return;
|
||||
|
||||
if (bShow)
|
||||
pS->show();
|
||||
else
|
||||
pS->hide();
|
||||
}
|
||||
assert (m_pParent);
|
||||
|
||||
if (bShow)
|
||||
{
|
||||
// add to tree
|
||||
m_pParent->add_child(m_pNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove from tree
|
||||
m_pParent->remove_child(m_pNode);
|
||||
}
|
||||
|
||||
// noop
|
||||
// if (pS->is_visible() == bShow)
|
||||
// return;
|
||||
|
||||
// if (bShow)
|
||||
// pS->show();
|
||||
// else
|
||||
// pS->hide();
|
||||
|
||||
// GeometryInstance * pGI = Object::cast_to<GeometryInstance>(pS);
|
||||
// if (pGI)
|
||||
// {
|
||||
// // godot visible bug workaround
|
||||
// pGI->set_extra_cull_margin(0.0f);
|
||||
// }
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
Spatial * LDob::GetSpatial() const
|
||||
|
49
ldob.h
49
ldob.h
@ -28,19 +28,33 @@
|
||||
#include "scene/3d/spatial.h"
|
||||
|
||||
class VisualInstance;
|
||||
class Light;
|
||||
|
||||
class LHidable
|
||||
{
|
||||
public:
|
||||
void Hidable_Create(Node * pNode);
|
||||
void Show(bool bShow);
|
||||
|
||||
// new .. can be separated from the scene tree to cull
|
||||
Node * m_pNode;
|
||||
Node * m_pParent;
|
||||
|
||||
// separate flag so we don't have to touch the godot lookup
|
||||
bool m_bShow;
|
||||
};
|
||||
|
||||
// static object
|
||||
class LSob
|
||||
class LSob : public LHidable
|
||||
{
|
||||
public:
|
||||
Spatial * GetSpatial() const;
|
||||
VisualInstance * GetVI() const;
|
||||
void Show(bool bShow);
|
||||
//void Show(bool bShow);
|
||||
bool IsShadowCaster() const;
|
||||
|
||||
ObjectID m_ID; // godot object
|
||||
AABB m_aabb; // world space
|
||||
//bool m_bSOBVisible;
|
||||
};
|
||||
|
||||
// dynamic object
|
||||
@ -55,3 +69,32 @@ public:
|
||||
bool m_bVisible;
|
||||
float m_fRadius;
|
||||
};
|
||||
|
||||
|
||||
class LLight : public LHidable
|
||||
{
|
||||
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
|
||||
|
||||
// shadow casters
|
||||
int m_FirstCaster;
|
||||
int m_NumCasters;
|
||||
};
|
||||
|
86
lportal.cpp
86
lportal.cpp
@ -25,6 +25,7 @@
|
||||
#include "lroom_manager.h"
|
||||
|
||||
|
||||
|
||||
bool LPortal::NameStartsWith(Node * pNode, String szSearch)
|
||||
{
|
||||
int sl = szSearch.length();
|
||||
@ -71,38 +72,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 +183,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)
|
||||
|
16
lportal.h
16
lportal.h
@ -32,15 +32,9 @@
|
||||
|
||||
class LRoom;
|
||||
class LRoomManager;
|
||||
class Light;
|
||||
|
||||
|
||||
class LLight
|
||||
{
|
||||
public:
|
||||
Vector3 m_ptDir;
|
||||
Vector3 m_ptPos;
|
||||
ObjectID m_GodotID;
|
||||
};
|
||||
|
||||
|
||||
class LPortal {
|
||||
@ -62,7 +56,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 +84,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;
|
||||
};
|
||||
|
||||
|
||||
|
158
lroom.cpp
158
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,51 +182,76 @@ 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 godot bug
|
||||
// GeometryInstance * pGI = Object::cast_to<GeometryInstance>(pVI);
|
||||
// if (pGI)
|
||||
// {
|
||||
// // godot visible bug workaround
|
||||
// pGI->set_extra_cull_margin(0.0f);
|
||||
// }
|
||||
|
||||
|
||||
// test the visual server - NOT A BOTTLENECK. set_layer_mask is cheap
|
||||
}
|
||||
|
||||
|
||||
// naive version, adds all the non visible objects in visible rooms as shadow casters
|
||||
void LRoom::AddShadowCasters(LRoomManager &manager)
|
||||
{
|
||||
LPRINT(2, "ADDSHADOWCASTERS room " + get_name() + ", " + itos(m_iNumShadowCasters_SOB) + " shadow casters");
|
||||
LPRINT_RUN(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);
|
||||
|
||||
// add all shadow casters for this light (new method)
|
||||
const LLight &light = manager.m_Lights[lightID];
|
||||
int last_caster = light.m_FirstCaster + light.m_NumCasters;
|
||||
for (int c=light.m_FirstCaster; c<last_caster; c++)
|
||||
{
|
||||
int sobID = manager.m_LightCasters_SOB[c];
|
||||
|
||||
// only add to the caster list if not in it already (does this check need to happen, can this ever occur?)
|
||||
if (!manager.m_BF_caster_SOBs.GetBit(sobID))
|
||||
{
|
||||
LPRINT_RUN(2, "\t" + itos(sobID) + ", " + manager.m_SOBs[sobID].GetSpatial()->get_name());
|
||||
manager.m_BF_caster_SOBs.SetBit(sobID, true);
|
||||
manager.m_CasterList_SOBs.push_back(sobID);
|
||||
}
|
||||
else
|
||||
{
|
||||
//LPRINT(2, "\t" + itos(sobID) + ", ALREADY CASTER " + manager.m_SOBs[sobID].GetSpatial()->get_name());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// new!! use precalced list of shadow casters
|
||||
int last = m_iFirstShadowCaster_SOB + m_iNumShadowCasters_SOB;
|
||||
for (int n=m_iFirstShadowCaster_SOB; n<last; n++)
|
||||
{
|
||||
int sobID = manager.m_ShadowCasters_SOB[n];
|
||||
// int last = m_iFirstShadowCaster_SOB + m_iNumShadowCasters_SOB;
|
||||
// for (int n=m_iFirstShadowCaster_SOB; n<last; n++)
|
||||
// {
|
||||
// int sobID = manager.m_ShadowCasters_SOB[n];
|
||||
|
||||
// only add to the caster list if not in it already
|
||||
if (!manager.m_BF_caster_SOBs.GetBit(sobID))
|
||||
{
|
||||
LPRINT(2, "\t" + itos(sobID) + ", " + manager.m_SOBs[sobID].GetSpatial()->get_name());
|
||||
manager.m_BF_caster_SOBs.SetBit(sobID, true);
|
||||
manager.m_CasterList_SOBs.push_back(sobID);
|
||||
}
|
||||
else
|
||||
{
|
||||
LPRINT(2, "\t" + itos(sobID) + ", ALREADY CASTER " + manager.m_SOBs[sobID].GetSpatial()->get_name());
|
||||
}
|
||||
}
|
||||
// // only add to the caster list if not in it already
|
||||
// if (!manager.m_BF_caster_SOBs.GetBit(sobID))
|
||||
// {
|
||||
// LPRINT(2, "\t" + itos(sobID) + ", " + manager.m_SOBs[sobID].GetSpatial()->get_name());
|
||||
// manager.m_BF_caster_SOBs.SetBit(sobID, true);
|
||||
// manager.m_CasterList_SOBs.push_back(sobID);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //LPRINT(2, "\t" + itos(sobID) + ", ALREADY CASTER " + manager.m_SOBs[sobID].GetSpatial()->get_name());
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
/*
|
||||
int last_sob = m_iFirstSOB + m_iNumSOBs;
|
||||
for (int n=m_iFirstSOB; n<last_sob; n++)
|
||||
{
|
||||
// bool bVisible = manager.m_BF_visible_SOBs.GetBit(n) != 0;
|
||||
|
||||
// // already in list
|
||||
// if (bVisible)
|
||||
// continue;
|
||||
|
||||
manager.m_BF_caster_SOBs.SetBit(n, true);
|
||||
manager.m_CasterList_SOBs.push_back(n);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@ -215,6 +259,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++)
|
||||
// {
|
||||
@ -250,7 +296,13 @@ void LRoom::FinalizeVisibility(LRoomManager &manager)
|
||||
VisualInstance * pVI = dob.GetVI();
|
||||
if (pVI)
|
||||
{
|
||||
SoftShow(pVI, dob.m_bVisible);
|
||||
uint32_t mask = 0;
|
||||
if (dob.m_bVisible)
|
||||
{
|
||||
mask = LRoom::LAYER_MASK_CAMERA | LRoom::LAYER_MASK_LIGHT;
|
||||
}
|
||||
|
||||
SoftShow(pVI, mask);
|
||||
// if (dob.m_bVisible)
|
||||
// {
|
||||
// //print("LRoom::FinalizeVisibility making visible dob " + pS->get_name());
|
||||
@ -317,7 +369,7 @@ void LRoom::Room_MakeVisible(bool bVisible)
|
||||
//}
|
||||
|
||||
// show godot room and all linked dobs and all sobs
|
||||
void LRoom::Debug_ShowAll()
|
||||
void LRoom::Debug_ShowAll(bool bActive)
|
||||
{
|
||||
Room_MakeVisible(true);
|
||||
|
||||
@ -328,6 +380,12 @@ void LRoom::Debug_ShowAll()
|
||||
// Spatial * pS = sob.GetSpatial();
|
||||
// if (pS)
|
||||
// pS->show();
|
||||
|
||||
// VisualInstance * pVI = sob.GetVI();
|
||||
// if (pVI)
|
||||
// {
|
||||
// SoftShow(pVI, LRoom::LAYER_MASK_CAMERA | LRoom::LAYER_MASK_LIGHT);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
15
lroom.h
15
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;
|
||||
@ -105,7 +112,7 @@ public:
|
||||
// void Hide_All();
|
||||
|
||||
// show godot room and all linked dobs and all sobs
|
||||
void Debug_ShowAll();
|
||||
void Debug_ShowAll(bool bActive);
|
||||
|
||||
// hide all the objects not hit on this frame .. instead of calling godot hide without need
|
||||
// (it might be expensive)
|
||||
@ -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,17 @@ 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();
|
||||
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.resize(count);
|
||||
|
||||
m_TempRooms.clear(true);
|
||||
@ -68,7 +69,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 +83,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 +123,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 +159,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());
|
||||
|
||||
|
||||
@ -150,9 +182,13 @@ void LRoomConverter::Convert_Room_FindObjects_Recursive(Node * pParent, LRoom &l
|
||||
LSob sob;
|
||||
sob.m_ID = pVI->get_instance_id();
|
||||
sob.m_aabb = bb;
|
||||
sob.Hidable_Create(pChild);
|
||||
|
||||
//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 +229,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);
|
||||
|
||||
@ -307,17 +346,272 @@ void LRoomConverter::Convert_HideAll()
|
||||
LSob &sob = LMAN->m_SOBs[n];
|
||||
sob.Show(false);
|
||||
}
|
||||
|
||||
// hide all lights that are non global
|
||||
for (int n=0; n<LMAN->m_Lights.size(); n++)
|
||||
{
|
||||
LLight &light = LMAN->m_Lights[n];
|
||||
if (!light.IsGlobal())
|
||||
light.Show(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// blank this each time as it is used to create the list of casters
|
||||
LMAN->m_BF_caster_SOBs.Blank();
|
||||
|
||||
// get the light
|
||||
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, 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);
|
||||
}
|
||||
|
||||
// add each light caster that is within the planes to the light caster list
|
||||
// clip all objects in this room to the clipping planes
|
||||
int last_sob = lroom.m_iFirstSOB + lroom.m_iNumSOBs;
|
||||
for (int n=lroom.m_iFirstSOB; n<last_sob; n++)
|
||||
{
|
||||
LSob &sob = LMAN->m_SOBs[n];
|
||||
|
||||
//LPRINT_RUN(2, "sob " + itos(n) + " " + sob.GetSpatial()->get_name());
|
||||
// already determined to be visible through another portal
|
||||
// if (LMAN->m_BF_caster_SOBs.GetBit(n))
|
||||
// {
|
||||
// //LPRINT_RUN(2, "\talready visible");
|
||||
// continue;
|
||||
// }
|
||||
|
||||
bool bShow = true;
|
||||
|
||||
|
||||
// estimate the radius .. for now
|
||||
const AABB &bb = sob.m_aabb;
|
||||
|
||||
// print("\t\t\tculling object " + pObj->get_name());
|
||||
|
||||
for (int p=0; p<planes.size(); p++)
|
||||
{
|
||||
// float dist = planes[p].distance_to(pt);
|
||||
// print("\t\t\t\t" + itos(p) + " : dist " + String(Variant(dist)));
|
||||
|
||||
float r_min, r_max;
|
||||
bb.project_range_in_plane(planes[p], r_min, r_max);
|
||||
|
||||
// print("\t\t\t\t" + itos(p) + " : r_min " + String(Variant(r_min)) + ", r_max " + String(Variant(r_max)));
|
||||
|
||||
|
||||
if (r_min > 0.0f)
|
||||
{
|
||||
bShow = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bShow)
|
||||
{
|
||||
Light_AddCaster_SOB(light, n);
|
||||
}
|
||||
|
||||
} // for through sobs
|
||||
|
||||
|
||||
|
||||
// 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,18 +695,59 @@ int LRoomConverter::CountRooms()
|
||||
|
||||
|
||||
// find all objects that cast shadows onto the objects in this room
|
||||
void LRoomConverter::LRoom_FindShadowCasters(LRoom &lroom)
|
||||
//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;
|
||||
//}
|
||||
|
||||
void LRoomConverter::Light_AddCaster_SOB(LLight &light, int sobID)
|
||||
{
|
||||
// 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]);
|
||||
}
|
||||
// we will reuse the rendering bitflags for shadow casters for this ... to check for double entries (fnaa fnaa)
|
||||
if (LMAN->m_BF_caster_SOBs.GetBit(sobID))
|
||||
return;
|
||||
|
||||
|
||||
return;
|
||||
LPRINT_RUN(2, "\t\t\tLightCaster " + itos(sobID));
|
||||
|
||||
LMAN->m_BF_caster_SOBs.SetBit(sobID, true);
|
||||
|
||||
|
||||
// first?
|
||||
if (!light.m_NumCasters)
|
||||
light.m_FirstCaster = LMAN->m_LightCasters_SOB.size();
|
||||
|
||||
LMAN->m_LightCasters_SOB.push_back(sobID);
|
||||
light.m_NumCasters++;
|
||||
}
|
||||
|
||||
|
||||
void LRoomConverter::LRoom_AddShadowCaster_SOB(LRoom &lroom, int sobID)
|
||||
{
|
||||
// we will reuse the rendering bitflags for shadow casters for this ... to check for double entries (fnaa fnaa)
|
||||
@ -461,7 +796,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 +842,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 +856,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 +872,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 +938,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 +1051,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 +1212,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,12 +106,19 @@ 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, LLight &light, int iLightID, const LVector<Plane> &planes);
|
||||
void Light_AddCaster_SOB(LLight &light, int sobID);
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
void TRoom_MakeOppositePortal(const LPortal &port, int iRoomOrig);
|
||||
|
||||
|
||||
@ -118,6 +127,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,83 @@ 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.Hidable_Create(pLight);
|
||||
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())
|
||||
{
|
||||
// l.Show(false);
|
||||
//pLight->hide();
|
||||
}
|
||||
|
||||
m_Lights.push_back(l);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LRoomManager::light_register(Node * pLightNode)
|
||||
{
|
||||
if (!pLightNode)
|
||||
@ -470,18 +564,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 +626,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;
|
||||
@ -574,10 +692,33 @@ void LRoomManager::rooms_set_active(bool bActive)
|
||||
for (int n=0; n<m_Rooms.size(); n++)
|
||||
{
|
||||
LRoom &lroom = m_Rooms[n];
|
||||
lroom.Debug_ShowAll();
|
||||
lroom.Debug_ShowAll(bActive);
|
||||
}
|
||||
|
||||
|
||||
for (int n=0; n<m_SOBs.size(); n++)
|
||||
{
|
||||
LSob &sob = m_SOBs[n];
|
||||
Spatial * pS = sob.GetSpatial();
|
||||
if (pS)
|
||||
if (!bActive)
|
||||
pS->show();
|
||||
else
|
||||
pS->hide();
|
||||
|
||||
VisualInstance * pVI = sob.GetVI();
|
||||
if (pVI)
|
||||
{
|
||||
uint32_t mask = 0;
|
||||
if (!bActive)
|
||||
{
|
||||
mask = LRoom::LAYER_MASK_CAMERA | LRoom::LAYER_MASK_LIGHT;
|
||||
}
|
||||
LRoom::SoftShow(pVI, mask);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LRoomManager::rooms_set_logging(int level)
|
||||
@ -610,7 +751,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 +768,31 @@ 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_LightCasters_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 +811,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 +822,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
|
||||
@ -833,6 +1005,7 @@ void LRoomManager::FrameUpdate_AddShadowCasters()
|
||||
m_Rooms[r].AddShadowCasters(*this);
|
||||
}
|
||||
|
||||
LPRINT(2, "TOTAL shadow casters " + itos(m_CasterList_SOBs.size()));
|
||||
}
|
||||
|
||||
void LRoomManager::FrameUpdate_FinalizeVisibility_SoftShow()
|
||||
@ -851,7 +1024,56 @@ 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.Show(true);
|
||||
|
||||
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.Show(false);
|
||||
// Light * pLight = light.GetGodotLight();
|
||||
// if (pLight)
|
||||
// {
|
||||
// //Lawn::LDebug::print("Hiding light " + itos (n));
|
||||
// pLight->hide();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,7 +1108,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 +1126,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 +1202,8 @@ void LRoomManager::FrameUpdate_DrawDebug(const LCamera &cam, const LRoom &lroom)
|
||||
|
||||
im->end();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void LRoomManager::_notification(int p_what) {
|
||||
@ -989,6 +1244,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,11 +90,21 @@ 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;
|
||||
|
||||
// master list of casters for each light
|
||||
LVector<uint32_t> m_LightCasters_SOB;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
@ -127,8 +137,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 +159,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 +195,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