mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-03 13:39:40 +00:00
Add multiple camera support to LightManager
This commit is contained in:
parent
6ef139e1d7
commit
8552a9d82c
2 changed files with 41 additions and 31 deletions
|
@ -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 ©, const osg::CopyOp ©op)
|
LightManager::LightManager(const LightManager ©, const osg::CopyOp ©op)
|
||||||
: 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue