From 1447bfa215e2ce44ec97ec06a714bfc27c9a9e71 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 4 Feb 2017 15:12:01 +0100 Subject: [PATCH 1/7] Improve scene loading performance by creating collision objects with the correct rotation right away instead of adjusting it later --- apps/openmw/mwworld/scene.cpp | 43 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 0cf47163e..c194dcca4 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -29,6 +29,26 @@ namespace { + void setNodeRotation(const MWWorld::Ptr& ptr, MWRender::RenderingManager& rendering, bool inverseRotationOrder) + { + if (!ptr.getRefData().getBaseNode()) + return; + + osg::Quat worldRotQuat(ptr.getRefData().getPosition().rot[2], osg::Vec3(0,0,-1)); + if (!ptr.getClass().isActor()) + { + float xr = ptr.getRefData().getPosition().rot[0]; + float yr = ptr.getRefData().getPosition().rot[1]; + if (!inverseRotationOrder) + worldRotQuat = worldRotQuat * osg::Quat(yr, osg::Vec3(0,-1,0)) * + osg::Quat(xr, osg::Vec3(-1,0,0)); + else + worldRotQuat = osg::Quat(xr, osg::Vec3(-1,0,0)) * osg::Quat(yr, osg::Vec3(0,-1,0)) * worldRotQuat; + } + + rendering.rotateObject(ptr, worldRotQuat); + } + void addObject(const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering) { @@ -37,6 +57,8 @@ namespace if (id == "prisonmarker" || id == "divinemarker" || id == "templemarker" || id == "northmarker") model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player ptr.getClass().insertObjectRendering(ptr, model, rendering); + setNodeRotation(ptr, rendering, false); + ptr.getClass().insertObject (ptr, model, physics); if (ptr.getClass().isActor()) @@ -46,23 +68,8 @@ namespace void updateObjectRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering, bool inverseRotationOrder) { - if (ptr.getRefData().getBaseNode() != NULL) - { - osg::Quat worldRotQuat(ptr.getRefData().getPosition().rot[2], osg::Vec3(0,0,-1)); - if (!ptr.getClass().isActor()) - { - float xr = ptr.getRefData().getPosition().rot[0]; - float yr = ptr.getRefData().getPosition().rot[1]; - if (!inverseRotationOrder) - worldRotQuat = worldRotQuat * osg::Quat(yr, osg::Vec3(0,-1,0)) * - osg::Quat(xr, osg::Vec3(-1,0,0)); - else - worldRotQuat = osg::Quat(xr, osg::Vec3(-1,0,0)) * osg::Quat(yr, osg::Vec3(0,-1,0)) * worldRotQuat; - } - - rendering.rotateObject(ptr, worldRotQuat); - physics.updateRotation(ptr); - } + setNodeRotation(ptr, rendering, inverseRotationOrder); + physics.updateRotation(ptr); } void updateObjectScale(const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, @@ -130,7 +137,6 @@ namespace try { addObject(ptr, mPhysics, mRendering); - updateObjectRotation(ptr, mPhysics, mRendering, false); } catch (const std::exception& e) { @@ -602,7 +608,6 @@ namespace MWWorld try { addObject(ptr, *mPhysics, mRendering); - updateObjectRotation(ptr, false); MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().getScale()); } catch (std::exception& e) From 5f2539adb69169059eaace5d3022153256dbea92 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 4 Feb 2017 16:05:22 +0100 Subject: [PATCH 2/7] Optimize scrollbar/progress skins by using one widget for the track instead of one widget per pixel --- files/mygui/openmw_hud_energybar.skin.xml | 12 ++++++------ files/mygui/openmw_list.skin.xml | 2 ++ files/mygui/openmw_progress.skin.xml | 13 +++++++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/files/mygui/openmw_hud_energybar.skin.xml b/files/mygui/openmw_hud_energybar.skin.xml index 640133d66..2b41b5ea9 100644 --- a/files/mygui/openmw_hud_energybar.skin.xml +++ b/files/mygui/openmw_hud_energybar.skin.xml @@ -61,14 +61,14 @@ - + - + @@ -76,7 +76,7 @@ - + @@ -84,7 +84,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -100,7 +100,7 @@ - + diff --git a/files/mygui/openmw_list.skin.xml b/files/mygui/openmw_list.skin.xml index c1e8114e9..9f5b2e94d 100644 --- a/files/mygui/openmw_list.skin.xml +++ b/files/mygui/openmw_list.skin.xml @@ -9,6 +9,7 @@ + @@ -50,6 +51,7 @@ + diff --git a/files/mygui/openmw_progress.skin.xml b/files/mygui/openmw_progress.skin.xml index 71bbfe9f0..95f5b378c 100644 --- a/files/mygui/openmw_progress.skin.xml +++ b/files/mygui/openmw_progress.skin.xml @@ -54,7 +54,7 @@ - + @@ -62,7 +62,7 @@ - + @@ -70,7 +70,7 @@ - + @@ -78,18 +78,19 @@ - + - + + - + From 7201cf5fe281507962c3b47ba65111e2b2572ded Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 4 Feb 2017 16:22:38 +0100 Subject: [PATCH 3/7] ItemWidget: skip setImageTexture if the icon has not changed --- apps/openmw/mwgui/itemwidget.cpp | 22 +++++++++++++++++----- apps/openmw/mwgui/itemwidget.hpp | 3 +++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/itemwidget.cpp b/apps/openmw/mwgui/itemwidget.cpp index fe7cb79de..a31eb9c76 100644 --- a/apps/openmw/mwgui/itemwidget.cpp +++ b/apps/openmw/mwgui/itemwidget.cpp @@ -67,20 +67,30 @@ namespace MWGui void ItemWidget::setIcon(const std::string &icon) { - if (mItemShadow) - mItemShadow->setImageTexture(icon); - if (mItem) - mItem->setImageTexture(icon); + if (mCurrentIcon != icon) + { + mCurrentIcon = icon; + + if (mItemShadow) + mItemShadow->setImageTexture(icon); + if (mItem) + mItem->setImageTexture(icon); + } } void ItemWidget::setFrame(const std::string &frame, const MyGUI::IntCoord &coord) { if (mFrame) { - mFrame->setImageTexture(frame); mFrame->setImageTile(MyGUI::IntSize(coord.width, coord.height)); // Why is this needed? MyGUI bug? mFrame->setImageCoord(coord); } + + if (mCurrentFrame != frame) + { + mCurrentFrame = frame; + mFrame->setImageTexture(frame); + } } void ItemWidget::setIcon(const MWWorld::Ptr &ptr) @@ -105,6 +115,8 @@ namespace MWGui mItemShadow->setImageTexture(""); mItem->setImageTexture(""); mText->setCaption(""); + mCurrentIcon.clear(); + mCurrentFrame.clear(); return; } diff --git a/apps/openmw/mwgui/itemwidget.hpp b/apps/openmw/mwgui/itemwidget.hpp index ce9f58f50..dd1717d11 100644 --- a/apps/openmw/mwgui/itemwidget.hpp +++ b/apps/openmw/mwgui/itemwidget.hpp @@ -47,6 +47,9 @@ namespace MWGui MyGUI::ImageBox* mItemShadow; MyGUI::ImageBox* mFrame; MyGUI::TextBox* mText; + + std::string mCurrentIcon; + std::string mCurrentFrame; }; } From 1eb338404361dee9a5c987b23836758cbe264f3f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 4 Feb 2017 17:07:35 +0100 Subject: [PATCH 4/7] Avoid rotating by zero in CharacterController --- apps/openmw/mwmechanics/character.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 297cb0804..9fd37cc8e 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1872,10 +1872,14 @@ void CharacterController::update(float duration) { if(mHitState != CharState_KnockDown && mHitState != CharState_KnockOut) { - world->rotateObject(mPtr, rot.x(), rot.y(), rot.z(), true); + if (rot != osg::Vec3f()) + world->rotateObject(mPtr, rot.x(), rot.y(), rot.z(), true); } else //avoid z-rotating for knockdown - world->rotateObject(mPtr, rot.x(), rot.y(), 0.0f, true); + { + if (rot.x() != 0 && rot.y() != 0) + world->rotateObject(mPtr, rot.x(), rot.y(), 0.0f, true); + } if (!mMovementAnimationControlled) world->queueMovement(mPtr, vec); From a2cede8f3470b900c6bbef65b8da697c1e1f8e6a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 4 Feb 2017 17:20:47 +0100 Subject: [PATCH 5/7] Add timer for updateEquippedLight --- apps/openmw/mwmechanics/actors.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index db8598a75..6290109b2 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -396,7 +396,6 @@ namespace MWMechanics { updateDrowning(ptr, duration); calculateNpcStatModifiers(ptr, duration); - updateEquippedLight(ptr, duration); } void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) @@ -1018,10 +1017,13 @@ namespace MWMechanics { static float timerUpdateAITargets = 0; static float timerUpdateHeadTrack = 0; + static float timerUpdateEquippedLight = 0; + const float updateEquippedLightInterval = 1.0f; // target lists get updated once every 1.0 sec if (timerUpdateAITargets >= 1.0f) timerUpdateAITargets = 0; if (timerUpdateHeadTrack >= 0.3f) timerUpdateHeadTrack = 0; + if (timerUpdateEquippedLight >= updateEquippedLightInterval) timerUpdateEquippedLight = 0; MWWorld::Ptr player = getPlayer(); @@ -1096,7 +1098,12 @@ namespace MWMechanics } if(iter->first.getTypeName() == typeid(ESM::NPC).name()) + { updateNpc(iter->first, duration); + + if (timerUpdateEquippedLight == 0) + updateEquippedLight(iter->first, updateEquippedLightInterval); + } } } From ee4073541cc1ecfc10a1ed35219e9bd0e5121401 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 4 Feb 2017 17:41:41 +0100 Subject: [PATCH 6/7] Animation: cache getVelocity() --- apps/openmw/mwrender/animation.cpp | 8 ++++++++ apps/openmw/mwrender/animation.hpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index d0806b511..cdbeffa19 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -575,6 +575,8 @@ namespace MWRender mAccumCtrl = NULL; mAnimSources.clear(); + + mAnimVelocities.clear(); } bool Animation::hasAnimation(const std::string &anim) const @@ -952,6 +954,10 @@ namespace MWRender if (!mAccumRoot) return 0.0f; + std::map::const_iterator found = mAnimVelocities.find(groupname); + if (found != mAnimVelocities.end()) + return found->second; + // Look in reverse; last-inserted source has priority. AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin()); for(;animsrc != mAnimSources.rend();++animsrc) @@ -999,6 +1005,8 @@ namespace MWRender } } + mAnimVelocities.insert(std::make_pair(groupname, velocity)); + return velocity; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 584eca614..f765a7a40 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -274,6 +274,8 @@ protected: float mAlpha; + mutable std::map mAnimVelocities; + osg::ref_ptr mLightListCallback; const NodeMap& getNodeMap() const; From 3065600a86a0ff725b88cb224c5573bb09b84b06 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 4 Feb 2017 17:54:59 +0100 Subject: [PATCH 7/7] Skip expensive visitEffectSources call if no summoned creatures or summon effects are active --- apps/openmw/mwmechanics/actors.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6290109b2..73d6d9cf3 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -732,11 +732,19 @@ namespace MWMechanics } } - UpdateSummonedCreatures updateSummonedCreatures(ptr); - creatureStats.getActiveSpells().visitEffectSources(updateSummonedCreatures); - if (ptr.getClass().hasInventoryStore(ptr)) - ptr.getClass().getInventoryStore(ptr).visitEffectSources(updateSummonedCreatures); - updateSummonedCreatures.process(); + bool hasSummonEffect = false; + for (MagicEffects::Collection::const_iterator it = effects.begin(); it != effects.end(); ++it) + if (it->first.mId >= ESM::MagicEffect::SummonScamp && it->first.mId <= ESM::MagicEffect::SummonStormAtronach) + hasSummonEffect = true; + + if (!creatureStats.getSummonedCreatureMap().empty() || !creatureStats.getSummonedCreatureGraveyard().empty() || hasSummonEffect) + { + UpdateSummonedCreatures updateSummonedCreatures(ptr); + creatureStats.getActiveSpells().visitEffectSources(updateSummonedCreatures); + if (ptr.getClass().hasInventoryStore(ptr)) + ptr.getClass().getInventoryStore(ptr).visitEffectSources(updateSummonedCreatures); + updateSummonedCreatures.process(); + } } void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr, float duration)