diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index a3761e1b64..46f6440ae6 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -846,14 +846,12 @@ namespace MWMechanics mAI = true; } - bool MechanicsManager::isBoundItem(const MWWorld::Ptr& item) + namespace { - static std::set boundItemIDCache; - - // If this is empty then we haven't executed the GMST cache logic yet; or there isn't any sMagicBound* GMST's - // for some reason - if (boundItemIDCache.empty()) + std::set makeBoundItemIdCache() { + std::set boundItemIDCache; + // Build a list of known bound item ID's const MWWorld::Store& gameSettings = MWBase::Environment::get().getESMStore()->get(); @@ -870,15 +868,16 @@ namespace MWMechanics boundItemIDCache.insert(ESM::RefId::stringRefId(currentGMSTValue)); } - } - // Perform bound item check and assign the Flag_Bound bit if it passes - const ESM::RefId& tempItemID = item.getCellRef().getRefId(); + return boundItemIDCache; + } + } - if (boundItemIDCache.count(tempItemID) != 0) - return true; + bool MechanicsManager::isBoundItem(const MWWorld::Ptr& item) + { + static const std::set boundItemIdCache = makeBoundItemIdCache(); - return false; + return boundItemIdCache.find(item.getCellRef().getRefId()) != boundItemIdCache.end(); } bool MechanicsManager::isAllowedToUse(const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, MWWorld::Ptr& victim) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 5b7d1db78a..c6ef6536ac 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -388,17 +388,20 @@ namespace std::string_view mEffectId; }; - osg::ref_ptr getVFXLightModelInstance() + namespace { - static osg::ref_ptr lightModel = nullptr; - - if (!lightModel) + osg::ref_ptr makeVFXLightModelInstance() { - lightModel = new osg::LightModel; + osg::ref_ptr lightModel = new osg::LightModel; lightModel->setAmbientIntensity({ 1, 1, 1, 1 }); + return lightModel; } - return lightModel; + const osg::ref_ptr& getVFXLightModelInstance() + { + static const osg::ref_ptr lightModel = makeVFXLightModelInstance(); + return lightModel; + } } void assignBoneBlendCallbackRecursive(MWRender::BoneAnimBlendController* controller, osg::Node* parent, bool isRoot) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 66aa027a89..0db44195ce 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -451,8 +451,7 @@ namespace MWWorld } else if (!ESM::isEsm4Ext(worldspace)) { - static std::vector defaultHeight; - defaultHeight.resize(verts * verts, ESM::Land::DEFAULT_HEIGHT); + static const std::vector defaultHeight(verts * verts, ESM::Land::DEFAULT_HEIGHT); mPhysics->addHeightField(defaultHeight.data(), cellX, cellY, worldsize, verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get()); } diff --git a/components/esm3/loadmgef.cpp b/components/esm3/loadmgef.cpp index 357dd94413..3ff725fcf7 100644 --- a/components/esm3/loadmgef.cpp +++ b/components/esm3/loadmgef.cpp @@ -132,53 +132,61 @@ namespace ESM esm.writeHNOString("DESC", mDescription); } - short MagicEffect::getResistanceEffect(short effect) + namespace { - // Source https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attribute - - // - static std::map effects; - if (effects.empty()) + std::map makeEffectsMap() { - effects[DisintegrateArmor] = Sanctuary; - effects[DisintegrateWeapon] = Sanctuary; + std::map effects; - for (int i = DrainAttribute; i <= DamageSkill; ++i) - effects[i] = ResistMagicka; - for (int i = AbsorbAttribute; i <= AbsorbSkill; ++i) - effects[i] = ResistMagicka; - for (int i = WeaknessToFire; i <= WeaknessToNormalWeapons; ++i) - effects[i] = ResistMagicka; + effects[MagicEffect::Effects::DisintegrateArmor] = MagicEffect::Effects::Sanctuary; + effects[MagicEffect::Effects::DisintegrateWeapon] = MagicEffect::Effects::Sanctuary; + + for (int i = MagicEffect::Effects::DrainAttribute; i <= MagicEffect::Effects::DamageSkill; ++i) + effects[i] = MagicEffect::Effects::ResistMagicka; + for (int i = MagicEffect::Effects::AbsorbAttribute; i <= MagicEffect::Effects::AbsorbSkill; ++i) + effects[i] = MagicEffect::Effects::ResistMagicka; + for (int i = MagicEffect::Effects::WeaknessToFire; i <= MagicEffect::Effects::WeaknessToNormalWeapons; ++i) + effects[i] = MagicEffect::Effects::ResistMagicka; - effects[Burden] = ResistMagicka; - effects[Charm] = ResistMagicka; - effects[Silence] = ResistMagicka; - effects[Blind] = ResistMagicka; - effects[Sound] = ResistMagicka; + effects[MagicEffect::Effects::Burden] = MagicEffect::Effects::ResistMagicka; + effects[MagicEffect::Effects::Charm] = MagicEffect::Effects::ResistMagicka; + effects[MagicEffect::Effects::Silence] = MagicEffect::Effects::ResistMagicka; + effects[MagicEffect::Effects::Blind] = MagicEffect::Effects::ResistMagicka; + effects[MagicEffect::Effects::Sound] = MagicEffect::Effects::ResistMagicka; for (int i = 0; i < 2; ++i) { - effects[CalmHumanoid + i] = ResistMagicka; - effects[FrenzyHumanoid + i] = ResistMagicka; - effects[DemoralizeHumanoid + i] = ResistMagicka; - effects[RallyHumanoid + i] = ResistMagicka; + effects[MagicEffect::Effects::CalmHumanoid + i] = MagicEffect::Effects::ResistMagicka; + effects[MagicEffect::Effects::FrenzyHumanoid + i] = MagicEffect::Effects::ResistMagicka; + effects[MagicEffect::Effects::DemoralizeHumanoid + i] = MagicEffect::Effects::ResistMagicka; + effects[MagicEffect::Effects::RallyHumanoid + i] = MagicEffect::Effects::ResistMagicka; } - effects[TurnUndead] = ResistMagicka; + effects[MagicEffect::Effects::TurnUndead] = MagicEffect::Effects::ResistMagicka; + + effects[MagicEffect::Effects::FireDamage] = MagicEffect::Effects::ResistFire; + effects[MagicEffect::Effects::FrostDamage] = MagicEffect::Effects::ResistFrost; + effects[MagicEffect::Effects::ShockDamage] = MagicEffect::Effects::ResistShock; + effects[MagicEffect::Effects::Vampirism] = MagicEffect::Effects::ResistCommonDisease; + effects[MagicEffect::Effects::Corprus] = MagicEffect::Effects::ResistCorprusDisease; + effects[MagicEffect::Effects::Poison] = MagicEffect::Effects::ResistPoison; + effects[MagicEffect::Effects::Paralyze] = MagicEffect::Effects::ResistParalysis; - effects[FireDamage] = ResistFire; - effects[FrostDamage] = ResistFrost; - effects[ShockDamage] = ResistShock; - effects[Vampirism] = ResistCommonDisease; - effects[Corprus] = ResistCorprusDisease; - effects[Poison] = ResistPoison; - effects[Paralyze] = ResistParalysis; + return effects; } + } - if (effects.find(effect) != effects.end()) - return effects[effect]; - else - return -1; + short MagicEffect::getResistanceEffect(short effect) + { + // Source https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attribute + + // + static const std::map effects = makeEffectsMap(); + + if (const auto it = effects.find(effect); it != effects.end()) + return it->second; + + return -1; } short MagicEffect::getWeaknessEffect(short effect) diff --git a/components/sceneutil/attach.cpp b/components/sceneutil/attach.cpp index 1c21221ac4..7b43380c98 100644 --- a/components/sceneutil/attach.cpp +++ b/components/sceneutil/attach.cpp @@ -82,18 +82,32 @@ namespace SceneUtil std::string_view mFilter; }; - void mergeUserData(const osg::UserDataContainer* source, osg::Object* target) + namespace { - if (!source) - return; - if (!target->getUserDataContainer()) - target->setUserDataContainer(osg::clone(source, osg::CopyOp::SHALLOW_COPY)); - else + void mergeUserData(const osg::UserDataContainer* source, osg::Object* target) { - for (unsigned int i = 0; i < source->getNumUserObjects(); ++i) - target->getUserDataContainer()->addUserObject( - osg::clone(source->getUserObject(i), osg::CopyOp::SHALLOW_COPY)); + if (!source) + return; + + if (!target->getUserDataContainer()) + target->setUserDataContainer(osg::clone(source, osg::CopyOp::SHALLOW_COPY)); + else + { + for (unsigned int i = 0; i < source->getNumUserObjects(); ++i) + target->getUserDataContainer()->addUserObject( + osg::clone(source->getUserObject(i), osg::CopyOp::SHALLOW_COPY)); + } + } + + osg::ref_ptr makeFrontFaceStateSet() + { + osg::ref_ptr frontFace = new osg::FrontFace; + frontFace->setMode(osg::FrontFace::CLOCKWISE); + + osg::ref_ptr frontFaceStateSet = new osg::StateSet; + frontFaceStateSet->setAttributeAndModes(frontFace, osg::StateAttribute::ON); + return frontFaceStateSet; } } @@ -159,14 +173,8 @@ namespace SceneUtil // Note: for absolute correctness we would need to check the current front face for every mesh then // invert it However MW isn't doing this either, so don't. Assuming all meshes are using backface // culling is more efficient. - static osg::ref_ptr frontFaceStateSet; - if (!frontFaceStateSet) - { - frontFaceStateSet = new osg::StateSet; - osg::FrontFace* frontFace = new osg::FrontFace; - frontFace->setMode(osg::FrontFace::CLOCKWISE); - frontFaceStateSet->setAttributeAndModes(frontFace, osg::StateAttribute::ON); - } + static const osg::ref_ptr frontFaceStateSet = makeFrontFaceStateSet(); + trans->setStateSet(frontFaceStateSet); } diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index 63b55abb21..99938d7b3a 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -404,63 +404,68 @@ namespace Terrain } } - void updateWaterCullingView( - HeightCullCallback* callback, ViewData* vd, osgUtil::CullVisitor* cv, float cellworldsize, bool outofworld) + namespace { - if (!(cv->getTraversalMask() & callback->getCullMask())) - return; - float lowZ = std::numeric_limits::max(); - float highZ = callback->getHighZ(); - if (cv->getEyePoint().z() <= highZ || outofworld) + osg::ref_ptr makeStateSet() { - callback->setLowZ(-std::numeric_limits::max()); - return; + osg::ref_ptr stateSet = new osg::StateSet; + stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); + stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + stateSet->setAttributeAndModes( + new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE), + osg::StateAttribute::ON); + osg::ref_ptr material = new osg::Material; + material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 1, 1)); + material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 0, 1)); + material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 0, 1)); + stateSet->setAttributeAndModes(material, osg::StateAttribute::ON); + stateSet->setRenderBinDetails(100, "RenderBin"); + return stateSet; } - cv->pushCurrentMask(); - static bool debug = getenv("OPENMW_WATER_CULLING_DEBUG") != nullptr; - for (unsigned int i = 0; i < vd->getNumEntries(); ++i) + + void updateWaterCullingView( + HeightCullCallback* callback, ViewData* vd, osgUtil::CullVisitor* cv, float cellworldsize, bool outofworld) { - ViewDataEntry& entry = vd->getEntry(i); - osg::BoundingBox bb - = static_cast(entry.mRenderingNode->asGroup()->getChild(0))->getWaterBoundingBox(); - if (!bb.valid()) - continue; - osg::Vec3f ofs( - entry.mNode->getCenter().x() * cellworldsize, entry.mNode->getCenter().y() * cellworldsize, 0.f); - bb._min += ofs; - bb._max += ofs; - bb._min.z() = highZ; - bb._max.z() = highZ; - if (cv->isCulled(bb)) - continue; - lowZ = bb._min.z(); - - if (!debug) - break; - osg::Box* b = new osg::Box; - b->set(bb.center(), bb._max - bb.center()); - osg::ShapeDrawable* drw = new osg::ShapeDrawable(b); - static osg::ref_ptr stateset = nullptr; - if (!stateset) + if (!(cv->getTraversalMask() & callback->getCullMask())) + return; + float lowZ = std::numeric_limits::max(); + float highZ = callback->getHighZ(); + if (cv->getEyePoint().z() <= highZ || outofworld) { - stateset = new osg::StateSet; - stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); - stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); - stateset->setAttributeAndModes( - new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE), - osg::StateAttribute::ON); - osg::Material* m = new osg::Material; - m->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 1, 1)); - m->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 0, 1)); - m->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(0, 0, 0, 1)); - stateset->setAttributeAndModes(m, osg::StateAttribute::ON); - stateset->setRenderBinDetails(100, "RenderBin"); + callback->setLowZ(-std::numeric_limits::max()); + return; + } + cv->pushCurrentMask(); + static bool debug = getenv("OPENMW_WATER_CULLING_DEBUG") != nullptr; + for (unsigned int i = 0; i < vd->getNumEntries(); ++i) + { + ViewDataEntry& entry = vd->getEntry(i); + osg::BoundingBox bb = static_cast(entry.mRenderingNode->asGroup()->getChild(0)) + ->getWaterBoundingBox(); + if (!bb.valid()) + continue; + osg::Vec3f ofs( + entry.mNode->getCenter().x() * cellworldsize, entry.mNode->getCenter().y() * cellworldsize, 0.f); + bb._min += ofs; + bb._max += ofs; + bb._min.z() = highZ; + bb._max.z() = highZ; + if (cv->isCulled(bb)) + continue; + lowZ = bb._min.z(); + + if (!debug) + break; + osg::Box* b = new osg::Box; + b->set(bb.center(), bb._max - bb.center()); + osg::ShapeDrawable* drw = new osg::ShapeDrawable(b); + static const osg::ref_ptr stateset = makeStateSet(); + drw->setStateSet(stateset); + drw->accept(*cv); } - drw->setStateSet(stateset); - drw->accept(*cv); + callback->setLowZ(lowZ); + cv->popCurrentMask(); } - callback->setLowZ(lowZ); - cv->popCurrentMask(); } void QuadTreeWorld::accept(osg::NodeVisitor& nv)