From: timoore Date: Thu, 29 Nov 2007 23:56:31 +0000 (+0000) Subject: Avoid copying drawables and dirtying display lists. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=34704a17f29db20dc6535fe918a5bb7aa3a214b1;p=simgear.git Avoid copying drawables and dirtying display lists. For the alpha-test animation, use an OVERRIDE attribute on the state set of the top level node instead of copying drawables and state sets throughout the model. As a temporary hack in the blend animation, don't use display lists in the cloned drawables. These changes are aimed at cutting down the number of display lists that the pager needs to compile. --- diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 3381743f..ba4bb75e 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -10,8 +10,10 @@ #include // for strcmp() #include #include +#include #include +#include #include #include @@ -19,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -449,6 +452,24 @@ public: } }; +namespace +{ +// Set all drawables to not use display lists. OSG will use +// glDrawArrays instead. +struct DoDrawArraysVisitor : public osg::NodeVisitor { + DoDrawArraysVisitor() : + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) + {} + void apply(osg::Geode& geode) + { + using namespace osg; + using namespace std; + + for (int i = 0; i < geode.getNumDrawables(); ++i) + geode.getDrawable(i)->setUseDisplayList(false); + } +}; +} SGAnimation::SGAnimation(const SGPropertyNode* configNode, SGPropertyNode* modelRoot) : @@ -1462,30 +1483,74 @@ SGAlphaTestAnimation::SGAlphaTestAnimation(const SGPropertyNode* configNode, { } +namespace +{ +// Keep one copy of the most common alpha test its state set. +OpenThreads::ReentrantMutex alphaTestMutex; +osg::ref_ptr standardAlphaFunc; +osg::ref_ptr alphaFuncStateSet; + +osg::AlphaFunc* makeAlphaFunc(float clamp) +{ + using namespace OpenThreads; + ScopedLock lock(alphaTestMutex); + if (osg::equivalent(clamp, 0.01f)) { + if (standardAlphaFunc.valid()) + return standardAlphaFunc.get(); + clamp = .01; + } + osg::AlphaFunc* alphaFunc = new osg::AlphaFunc; + alphaFunc->setFunction(osg::AlphaFunc::GREATER); + alphaFunc->setReferenceValue(clamp); + alphaFunc->setDataVariance(osg::Object::STATIC); + if (osg::equivalent(clamp, 0.01f)) + standardAlphaFunc = alphaFunc; + return alphaFunc; +} + +osg::StateSet* makeAlphaTestStateSet(float clamp) +{ + using namespace OpenThreads; + ScopedLock lock(alphaTestMutex); + if (osg::equivalent(clamp, 0.01f)) { + if (alphaFuncStateSet.valid()) + return alphaFuncStateSet.get(); + } + osg::AlphaFunc* alphaFunc = makeAlphaFunc(clamp); + osg::StateSet* stateSet = new osg::StateSet; + stateSet->setAttributeAndModes(alphaFunc, + (osg::StateAttribute::ON + | osg::StateAttribute::OVERRIDE)); + stateSet->setDataVariance(osg::Object::STATIC); + if (osg::equivalent(clamp, 0.01f)) + alphaFuncStateSet = stateSet; + return stateSet; +} +} void SGAlphaTestAnimation::install(osg::Node& node) { SGAnimation::install(node); - - cloneDrawables(node); - removeMode(node, GL_ALPHA_TEST); - removeAttribute(node, osg::StateAttribute::ALPHAFUNC); - osg::StateSet* stateSet = node.getOrCreateStateSet(); - osg::AlphaFunc* alphaFunc = new osg::AlphaFunc; - alphaFunc->setFunction(osg::AlphaFunc::GREATER); float alphaClamp = getConfig()->getFloatValue("alpha-factor", 0); - alphaFunc->setReferenceValue(alphaClamp); - stateSet->setAttribute(alphaFunc); - stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON); + osg::StateSet* stateSet = node.getStateSet(); + if (!stateSet) { + node.setStateSet(makeAlphaTestStateSet(alphaClamp)); + } else { + stateSet->setAttributeAndModes(makeAlphaFunc(alphaClamp), + (osg::StateAttribute::ON + | osg::StateAttribute::OVERRIDE)); + } } - ////////////////////////////////////////////////////////////////////// // Blend animation installer ////////////////////////////////////////////////////////////////////// +// XXX This needs to be replaced by something using TexEnvCombine to +// change the blend factor. Changing the alpha values in the geometry +// is bogus. class SGBlendAnimation::BlendVisitor : public osg::NodeVisitor { public: BlendVisitor(float blend) : @@ -1503,7 +1568,6 @@ public: unsigned nDrawables = node.getNumDrawables(); for (unsigned i = 0; i < nDrawables; ++i) { osg::Drawable* drawable = node.getDrawable(i); - updateStateSet(drawable->getStateSet()); osg::Geometry* geometry = drawable->asGeometry(); if (!geometry) continue; @@ -1513,11 +1577,11 @@ public: osg::Vec4Array* vec4Array = dynamic_cast(array); if (!vec4Array) continue; - geometry->dirtyDisplayList(); - vec4Array->dirty(); for (unsigned k = 0; k < vec4Array->size(); ++k) { (*vec4Array)[k][3] = _blend; } + vec4Array->dirty(); + updateStateSet(drawable->getStateSet()); } } void updateStateSet(osg::StateSet* stateSet) @@ -1592,6 +1656,8 @@ SGBlendAnimation::install(osg::Node& node) // make sure we do not change common geometries, // that also creates new display lists for these subgeometries. cloneDrawables(node); + DoDrawArraysVisitor visitor; + node.accept(visitor); }