From 8552a9d82c8e9f01e9d843745664788f9d460976 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 23 Oct 2015 01:58:22 +0200 Subject: [PATCH] Add multiple camera support to LightManager --- components/sceneutil/lightmanager.cpp | 56 ++++++++++++++------------- components/sceneutil/lightmanager.hpp | 16 +++++--- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 07ec0aff6..77551e006 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -126,15 +126,13 @@ namespace SceneUtil }; LightManager::LightManager() - : mLightsInViewSpace(false) - , mStartLight(0) + : mStartLight(0) { setUpdateCallback(new LightManagerUpdateCallback); } LightManager::LightManager(const LightManager ©, const osg::CopyOp ©op) : osg::Group(copy, copyop) - , mLightsInViewSpace(false) , mStartLight(copy.mStartLight) { @@ -142,8 +140,8 @@ namespace SceneUtil void LightManager::update() { - mLightsInViewSpace = false; mLights.clear(); + mLightsInViewSpace.clear(); // do an occasional cleanup for orphaned lights if (mStateSetCache.size() > 5000) @@ -161,22 +159,6 @@ namespace SceneUtil mLights.push_back(l); } - void LightManager::prepareForCamera(osg::Camera *cam) - { - // later on we need to store this per camera - if (!mLightsInViewSpace) - { - for (std::vector::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 LightManager::getLightListStateSet(const LightList &lightList) { // 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; } + const std::vector& LightManager::getLightsInViewSpace(osg::Camera *camera) + { + osg::observer_ptr camPtr (camera); + std::map, LightSourceViewBoundCollection>::iterator it = mLightsInViewSpace.find(camPtr); + + if (it == mLightsInViewSpace.end()) + { + it = mLightsInViewSpace.insert(std::make_pair(camPtr, LightSourceViewBoundCollection())).first; + + for (std::vector::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) { 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; } @@ -273,13 +279,11 @@ namespace SceneUtil } } - mLightManager->prepareForCamera(cv->getCurrentCamera()); - // Possible optimizations: // - cull list of lights by the camera frustum // - organize lights in a quad tree - const std::vector& lights = mLightManager->getLights(); + const std::vector& lights = mLightManager->getLightsInViewSpace(cv->getCurrentCamera()); if (lights.size()) { @@ -288,10 +292,10 @@ namespace SceneUtil osg::Matrixf mat = *cv->getModelViewMatrix(); transformBoundingSphere(mat, nodeBound); - std::vector lightList; + LightManager::LightList lightList; for (unsigned int i=0; i& getLights() const; - typedef std::vector LightList; + struct LightSourceViewBound + { + LightSource* mLightSource; + osg::BoundingSphere mViewBound; + }; + + const std::vector& getLightsInViewSpace(osg::Camera* camera); + + typedef std::vector LightList; osg::ref_ptr getLightListStateSet(const LightList& lightList); @@ -98,7 +103,8 @@ namespace SceneUtil // Lights collected from the scene graph. Only valid during the cull traversal. std::vector mLights; - bool mLightsInViewSpace; + typedef std::vector LightSourceViewBoundCollection; + std::map, LightSourceViewBoundCollection> mLightsInViewSpace; // < Light list hash , StateSet > typedef std::map > LightStateSetMap;