1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-03 19:39:41 +00:00

Add multiple camera support to LightManager

This commit is contained in:
scrawl 2015-10-23 01:58:22 +02:00
parent 6ef139e1d7
commit 8552a9d82c
2 changed files with 41 additions and 31 deletions

View file

@ -126,15 +126,13 @@ namespace SceneUtil
}; };
LightManager::LightManager() LightManager::LightManager()
: mLightsInViewSpace(false) : mStartLight(0)
, mStartLight(0)
{ {
setUpdateCallback(new LightManagerUpdateCallback); setUpdateCallback(new LightManagerUpdateCallback);
} }
LightManager::LightManager(const LightManager &copy, const osg::CopyOp &copyop) LightManager::LightManager(const LightManager &copy, const osg::CopyOp &copyop)
: osg::Group(copy, copyop) : osg::Group(copy, copyop)
, mLightsInViewSpace(false)
, mStartLight(copy.mStartLight) , mStartLight(copy.mStartLight)
{ {
@ -142,8 +140,8 @@ namespace SceneUtil
void LightManager::update() void LightManager::update()
{ {
mLightsInViewSpace = false;
mLights.clear(); mLights.clear();
mLightsInViewSpace.clear();
// do an occasional cleanup for orphaned lights // do an occasional cleanup for orphaned lights
if (mStateSetCache.size() > 5000) if (mStateSetCache.size() > 5000)
@ -161,22 +159,6 @@ namespace SceneUtil
mLights.push_back(l); mLights.push_back(l);
} }
void LightManager::prepareForCamera(osg::Camera *cam)
{
// later on we need to store this per camera
if (!mLightsInViewSpace)
{
for (std::vector<LightSourceTransform>::iterator it = mLights.begin(); it != mLights.end(); ++it)
{
LightSourceTransform& l = *it;
osg::Matrix worldViewMat = l.mWorldMatrix * cam->getViewMatrix();
l.mViewBound = osg::BoundingSphere(osg::Vec3f(0,0,0), l.mLightSource->getRadius());
transformBoundingSphere(worldViewMat, l.mViewBound);
}
mLightsInViewSpace = true;
}
}
osg::ref_ptr<osg::StateSet> LightManager::getLightListStateSet(const LightList &lightList) osg::ref_ptr<osg::StateSet> LightManager::getLightListStateSet(const LightList &lightList)
{ {
// possible optimization: return a StateSet containing all requested lights plus some extra lights (if a suitable one exists) // possible optimization: return a StateSet containing all requested lights plus some extra lights (if a suitable one exists)
@ -212,6 +194,30 @@ namespace SceneUtil
return mLights; return mLights;
} }
const std::vector<LightManager::LightSourceViewBound>& LightManager::getLightsInViewSpace(osg::Camera *camera)
{
osg::observer_ptr<osg::Camera> camPtr (camera);
std::map<osg::observer_ptr<osg::Camera>, LightSourceViewBoundCollection>::iterator it = mLightsInViewSpace.find(camPtr);
if (it == mLightsInViewSpace.end())
{
it = mLightsInViewSpace.insert(std::make_pair(camPtr, LightSourceViewBoundCollection())).first;
for (std::vector<LightSourceTransform>::iterator lightIt = mLights.begin(); lightIt != mLights.end(); ++lightIt)
{
osg::Matrix worldViewMat = lightIt->mWorldMatrix * camera->getViewMatrix();
osg::BoundingSphere viewBound = osg::BoundingSphere(osg::Vec3f(0,0,0), lightIt->mLightSource->getRadius());
transformBoundingSphere(worldViewMat, viewBound);
LightSourceViewBound l;
l.mLightSource = lightIt->mLightSource;
l.mViewBound = viewBound;
it->second.push_back(l);
}
}
return it->second;
}
void LightManager::setStartLight(int start) void LightManager::setStartLight(int start)
{ {
mStartLight = start; mStartLight = start;
@ -241,7 +247,7 @@ namespace SceneUtil
} }
bool sortLights (const LightManager::LightSourceTransform* left, const LightManager::LightSourceTransform* right) bool sortLights (const LightManager::LightSourceViewBound* left, const LightManager::LightSourceViewBound* right)
{ {
return left->mViewBound.center().length2() - left->mViewBound.radius2()/4.f < right->mViewBound.center().length2() - right->mViewBound.radius2()/4.f; return left->mViewBound.center().length2() - left->mViewBound.radius2()/4.f < right->mViewBound.center().length2() - right->mViewBound.radius2()/4.f;
} }
@ -273,13 +279,11 @@ namespace SceneUtil
} }
} }
mLightManager->prepareForCamera(cv->getCurrentCamera());
// Possible optimizations: // Possible optimizations:
// - cull list of lights by the camera frustum // - cull list of lights by the camera frustum
// - organize lights in a quad tree // - organize lights in a quad tree
const std::vector<LightManager::LightSourceTransform>& lights = mLightManager->getLights(); const std::vector<LightManager::LightSourceViewBound>& lights = mLightManager->getLightsInViewSpace(cv->getCurrentCamera());
if (lights.size()) if (lights.size())
{ {
@ -288,10 +292,10 @@ namespace SceneUtil
osg::Matrixf mat = *cv->getModelViewMatrix(); osg::Matrixf mat = *cv->getModelViewMatrix();
transformBoundingSphere(mat, nodeBound); transformBoundingSphere(mat, nodeBound);
std::vector<const LightManager::LightSourceTransform*> lightList; LightManager::LightList lightList;
for (unsigned int i=0; i<lights.size(); ++i) for (unsigned int i=0; i<lights.size(); ++i)
{ {
const LightManager::LightSourceTransform& l = lights[i]; const LightManager::LightSourceViewBound& l = lights[i];
if (l.mViewBound.intersects(nodeBound)) if (l.mViewBound.intersects(nodeBound))
lightList.push_back(&l); lightList.push_back(&l);
} }

View file

@ -74,18 +74,23 @@ namespace SceneUtil
// Called automatically by the LightSource's UpdateCallback // Called automatically by the LightSource's UpdateCallback
void addLight(LightSource* lightSource, osg::Matrix worldMat); void addLight(LightSource* lightSource, osg::Matrix worldMat);
void prepareForCamera(osg::Camera* cam);
struct LightSourceTransform struct LightSourceTransform
{ {
LightSource* mLightSource; LightSource* mLightSource;
osg::Matrix mWorldMatrix; osg::Matrix mWorldMatrix;
osg::BoundingSphere mViewBound;
}; };
const std::vector<LightSourceTransform>& getLights() const; const std::vector<LightSourceTransform>& getLights() const;
typedef std::vector<const LightSourceTransform*> LightList; struct LightSourceViewBound
{
LightSource* mLightSource;
osg::BoundingSphere mViewBound;
};
const std::vector<LightSourceViewBound>& getLightsInViewSpace(osg::Camera* camera);
typedef std::vector<const LightSourceViewBound*> LightList;
osg::ref_ptr<osg::StateSet> getLightListStateSet(const LightList& lightList); osg::ref_ptr<osg::StateSet> getLightListStateSet(const LightList& lightList);
@ -98,7 +103,8 @@ namespace SceneUtil
// Lights collected from the scene graph. Only valid during the cull traversal. // Lights collected from the scene graph. Only valid during the cull traversal.
std::vector<LightSourceTransform> mLights; std::vector<LightSourceTransform> mLights;
bool mLightsInViewSpace; typedef std::vector<LightSourceViewBound> LightSourceViewBoundCollection;
std::map<osg::observer_ptr<osg::Camera>, LightSourceViewBoundCollection> mLightsInViewSpace;
// < Light list hash , StateSet > // < Light list hash , StateSet >
typedef std::map<size_t, osg::ref_ptr<osg::StateSet> > LightStateSetMap; typedef std::map<size_t, osg::ref_ptr<osg::StateSet> > LightStateSetMap;