From 9e049894e8e06a16d833288aae69051b7a1a7ccc Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 14 Jun 2015 21:22:44 +0200 Subject: [PATCH] Reduce the number of StateSets created for NIF scene graphs The Material state is now set on the NiTriShape's node rather than the Geode, thus merged with other state like NiTexturingProperties, etc that are typically attached to the NiTriShape. Effectively cuts in half the number of StatSets for a NIF file, resulting in big speedup (~10%) in the Cull and Draw phases. --- components/nifosg/nifloader.cpp | 38 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index b95eeebfc..63121fda2 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -525,20 +525,20 @@ namespace NifOsg { const Nif::NiTriShape* triShape = static_cast(nifNode); if (triShape->skin.empty()) - handleTriShape(triShape, transformNode, boundTextures, animflags); + handleTriShape(triShape, transformNode, composite, boundTextures, animflags); else - handleSkinnedTriShape(triShape, transformNode, boundTextures, animflags); + handleSkinnedTriShape(triShape, transformNode, composite, boundTextures, animflags); if (!nifNode->controller.empty()) handleMeshControllers(nifNode, composite, boundTextures, animflags); } + if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles) + handleParticleSystem(nifNode, transformNode, composite, animflags, particleflags, rootNode); + if (composite->getNumControllers() > 0) transformNode->addUpdateCallback(composite); - if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles) - handleParticleSystem(nifNode, transformNode, animflags, particleflags, rootNode); - if (!nifNode->controller.empty()) handleNodeControllers(nifNode, transformNode, animflags); @@ -606,9 +606,8 @@ namespace NifOsg } } - static void handleMaterialControllers(const Nif::Property *materialProperty, osg::Node* node, int animflags) + static void handleMaterialControllers(const Nif::Property *materialProperty, osg::Node* node, SceneUtil::CompositeStateSetUpdater* composite, int animflags) { - osg::ref_ptr composite = new SceneUtil::CompositeStateSetUpdater; for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next) { if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) @@ -630,8 +629,6 @@ namespace NifOsg else std::cerr << "Unexpected material controller " << ctrl->recType << std::endl; } - if (composite->getNumControllers() > 0) - node->addUpdateCallback(composite); } static void handleTextureControllers(const Nif::Property *texProperty, SceneUtil::CompositeStateSetUpdater* composite, Resource::TextureManager* textureManager, osg::StateSet *stateset, int animflags) @@ -789,7 +786,7 @@ namespace NifOsg return emitter; } - static void handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, int animflags, int particleflags, osg::Node* rootNode) + static void handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, int animflags, int particleflags, osg::Node* rootNode) { osg::ref_ptr partsys (new ParticleSystem); partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT); @@ -863,10 +860,10 @@ namespace NifOsg std::vector materialProps; collectMaterialProperties(nifNode, materialProps); - applyMaterialProperties(geode, materialProps, true, animflags); + applyMaterialProperties(parentNode, materialProps, composite, true, animflags); // Particles don't have normals, so can't be diffuse lit. - osg::Material* mat = static_cast(geode->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL)); + osg::Material* mat = static_cast(parentNode->getStateSet()->getAttribute(osg::StateAttribute::MATERIAL)); if (mat) { osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK); @@ -891,7 +888,7 @@ namespace NifOsg } } - static void triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, osg::Geode* parentGeode, const std::map& boundTextures, int animflags) + static void triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::map& boundTextures, int animflags) { const Nif::NiTriShapeData* data = triShape->data.getPtr(); @@ -928,10 +925,10 @@ namespace NifOsg // above the actual renderable would be tedious. std::vector materialProps; collectMaterialProperties(triShape, materialProps); - applyMaterialProperties(parentGeode, materialProps, !data->colors.empty(), animflags); + applyMaterialProperties(parentNode, materialProps, composite, !data->colors.empty(), animflags); } - static void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map& boundTextures, int animflags) + static void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::map& boundTextures, int animflags) { osg::ref_ptr geometry; if(!triShape->controller.empty()) @@ -955,7 +952,7 @@ namespace NifOsg geometry = new osg::Geometry; osg::ref_ptr geode (new osg::Geode); - triShapeToGeometry(triShape, geometry, geode, boundTextures, animflags); + triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags); geode->addDrawable(geometry); @@ -1029,12 +1026,13 @@ namespace NifOsg return morphGeom; } - static void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, const std::map& boundTextures, int animflags) + static void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, + const std::map& boundTextures, int animflags) { osg::ref_ptr geode (new osg::Geode); osg::ref_ptr geometry (new osg::Geometry); - triShapeToGeometry(triShape, geometry, geode, boundTextures, animflags); + triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags); osg::ref_ptr rig(new SceneUtil::RigGeometry); rig->setSourceGeometry(geometry); @@ -1275,7 +1273,7 @@ namespace NifOsg } } - static void applyMaterialProperties(osg::Node* node, const std::vector& properties, + static void applyMaterialProperties(osg::Node* node, const std::vector& properties, SceneUtil::CompositeStateSetUpdater* composite, bool hasVertexColors, int animflags) { osg::StateSet* stateset = node->getOrCreateStateSet(); @@ -1310,7 +1308,7 @@ namespace NifOsg mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness); if (!matprop->controller.empty()) - handleMaterialControllers(matprop, node, animflags); + handleMaterialControllers(matprop, node, composite, animflags); break; }