From bc8db8b8f5efe06ffccbc8b7f9fb05fee0642de8 Mon Sep 17 00:00:00 2001 From: Jacob Turnbull Date: Tue, 6 Apr 2021 20:12:51 -0500 Subject: [PATCH 01/37] Fix for enchanted items being removed on item equip cycling when they are re-equipped --- apps/openmw/mwworld/actionequip.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 4cb0dbe51..23599b528 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -91,13 +91,30 @@ namespace MWWorld // move all slots one towards begin(), then equip the item in the slot that is now free if (slot == slots_.first.end()) { - for (slot=slots_.first.begin();slot!=slots_.first.end(); ++slot) + ContainerStoreIterator enchItem = invStore.getSelectedEnchantItem(); + bool bReEquipEnchItem = false; + for (slot = slots_.first.begin(); slot != slots_.first.end(); ++slot) { invStore.unequipSlot(*slot, actor, false); - if (slot+1 != slots_.first.end()) - invStore.equip(*slot, invStore.getSlot(*(slot+1)), actor); + if (slot + 1 != slots_.first.end()) + { + invStore.equip(*slot, invStore.getSlot(*(slot + 1)), actor); + } else + { invStore.equip(*slot, it, actor); + } + + //if an enchanted item was re-equipped, set reEquipEnchItem = true + if (invStore.getSlot(*slot) == enchItem) + { + bReEquipEnchItem = true; + } + } + //if re-equip flag is true, select the enchanted item again + if (bReEquipEnchItem) + { + invStore.setSelectedEnchantItem(enchItem); } } } From d9376ee08e758d144491b47d799bcc0a415a05b2 Mon Sep 17 00:00:00 2001 From: Jacob Turnbull Date: Wed, 7 Apr 2021 16:57:06 -0500 Subject: [PATCH 02/37] Trim down comment and change flag name --- apps/openmw/mwworld/actionequip.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 23599b528..92cd04438 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -92,7 +92,7 @@ namespace MWWorld if (slot == slots_.first.end()) { ContainerStoreIterator enchItem = invStore.getSelectedEnchantItem(); - bool bReEquipEnchItem = false; + bool reEquip = false; for (slot = slots_.first.begin(); slot != slots_.first.end(); ++slot) { invStore.unequipSlot(*slot, actor, false); @@ -105,14 +105,13 @@ namespace MWWorld invStore.equip(*slot, it, actor); } - //if an enchanted item was re-equipped, set reEquipEnchItem = true + //Fix for issue of selected enchated item getting remmoved on cycle if (invStore.getSlot(*slot) == enchItem) { - bReEquipEnchItem = true; + reEquip = true; } } - //if re-equip flag is true, select the enchanted item again - if (bReEquipEnchItem) + if (reEquip) { invStore.setSelectedEnchantItem(enchItem); } From 55416a57ef58aeaf39cf0cbde6b131d0fadc1668 Mon Sep 17 00:00:00 2001 From: Lamoot Date: Mon, 19 Apr 2021 20:11:13 +0200 Subject: [PATCH 03/37] Document the newly added settings under [Models] section, used for dehardcoded mesh paths. --- .../reference/modding/settings/models.rst | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/docs/source/reference/modding/settings/models.rst b/docs/source/reference/modding/settings/models.rst index b0da374d6..c0192067a 100644 --- a/docs/source/reference/modding/settings/models.rst +++ b/docs/source/reference/modding/settings/models.rst @@ -29,3 +29,213 @@ If enabled, this setting allows the NIF loader to make use of that functionality To help debug possible issues OpenMW will log its progress in loading every file that uses an unsupported NIF version. + +xbaseanim +--------- + +:Type: string +:Range: +:Default: meshes/xbase_anim.nif + +Path to the file used for 3rd person base animation model that looks also for the corresponding kf-file. + +.. note:: + If you are using the COLLADA format, you don't need to separate the files as they are separated between .nif and .kf files. It works if you plug the same COLLADA file into all animation-related entries, just make sure there is a corresponding textkeys file. You can read more about the textkeys in :doc:`../../modding/custom-models/pipeline-blender-collada`. + +baseanim +-------- + +:Type: string +:Range: +:Default: meshes/base_anim.nif + +Path to the file used for 3rd person base model with textkeys-data. + +xbaseanim1st +------------ + +:Type: string +:Range: +:Default: meshes/xbase_anim.1st.nif + +Path to the file used for 1st person base animation model that looks also for corresponding kf-file. + +baseanimkna +----------- + +:Type: string +:Range: +:Default: meshes/base_animkna.nif + +Path to the file used for 3rd person beast race base model with textkeys-data. + +baseanimkna1st +-------------- + +:Type: string +:Range: +:Default: meshes/base_animkna.1st.nif + +Path to the file used for 1st person beast race base animation model. + +xbaseanimfemale +--------------- + +:Type: string +:Range: +:Default: meshes/xbase_anim_female.nif + +Path to the file used for 3rd person female base animation model. + +baseanimfemale +-------------- + +:Type: string +:Range: +:Default: meshes/base_anim_female.nif + +Path to the file used for 3rd person female base model with textkeys-data. + +baseanimfemale1st +----------------- + +:Type: string +:Range: +:Default: meshes/base_anim_female.1st.nif + +Path to the file used for 1st person female base model with textkeys-data. + +wolfskin +-------- + +:Type: string +:Range: +:Default: meshes/wolf/skin.nif + +Path to the file used for 3rd person werewolf skin. + +wolfskin1st +----------- + +:Type: string +:Range: +:Default: meshes/wolf/skin.1st.nif + +Path to the file used for 1st person werewolf skin. + +xargonianswimkna +---------------- + +:Type: string +:Range: +:Default: meshes/xargonian_swimkna.nif + +Path to the file used for Argonian swimkna. + +xbaseanimkf +----------- + +:Type: string +:Range: +:Default: meshes/xbase_anim.kf + +File to load xbaseanim 3rd person animations. + +xbaseanim1stkf +-------------- + +:Type: string +:Range: +:Default: meshes/xbase_anim.1st.kf + +File to load xbaseanim 3rd person animations. + +xbaseanimfemalekf +----------------- + +:Type: string +:Range: +:Default: meshes/xbase_anim_female.kf + +File to load xbaseanim animations from. + +xargonianswimknakf +------------------ + +:Type: string +:Range: +:Default: meshes/xargonian_swimkna.kf + +File to load xargonianswimkna animations from. + +skyatmosphere +------------- + +:Type: string +:Range: +:Default: meshes/sky_atmosphere.nif + +Path to the file used for the sky atmosphere mesh, which is one of the three meshes needed to render the sky. It's used to make the top half of the sky blue and renders in front of the background color. + +skyclouds +--------- + +:Type: string +:Range: +:Default: meshes/sky_clouds_01.nif. + +Path to the file used for the sky clouds mesh, which is one of the three meshes needed to render the sky. It displays a scrolling texture of clouds in front of the atmosphere mesh and background color + +skynight01 +---------- + +:Type: string +:Range: +:Default: meshes/sky_night_01.nif + +Path to the file used for the sky stars mesh, which is one of the three meshes needed to render the sky. During night, it displays a texture with stars in front of the atmosphere and behind the clouds. If skynight02 is present, skynight01 will not be used. + +skynight02 +---------- + +:Type: string +:Range: +:Default: meshes/sky_night_02.nif + +Path to the file used for the sky stars mesh, which is one of the three meshes needed to render the sky. During night, it displays a texture with stars in front of the atmosphere and behind the clouds. If it's present it will be used instead of skynight01. + +weatherashcloud +--------------- + +:Type: string +:Range: +:Default: meshes/ashcloud.nif + +Path to the file used for the ash clouds weather effect in Morrowind. OpenMW doesn't use this file, instead it renders a similar looking particle effect. Changing this won't have any effect. + +weatherblightcloud +------------------ + +:Type: string +:Range: +:Default: meshes/blightcloud.nif + +Path to the file used for the blight clouds weather effect in Morrowind. OpenMW doesn't use this file, instead it renders a similar looking particle effect. Changing this won't have any effect. + +weathersnow +----------- + +:Type: string +:Range: +:Default: meshes/snow.nif + +Path to the file used for the snow falling weather effect in Morrowind. OpenMW doesn't use this file, instead it renders a similar looking particle effect. Changing this won't have any effect. + +weatherblizzard +--------------- + +:Type: string +:Range: +:Default: meshes/blizzard.nif + +Path to the file used for the blizzard clouds weather effect in Morrowind. OpenMW doesn't use this file, instead it renders a similar looking particle effect. Changing this won't have any effect. From cbfaab51e71feb763a89fa48cce7c187de763f72 Mon Sep 17 00:00:00 2001 From: Lamoot Date: Mon, 19 Apr 2021 21:21:53 +0200 Subject: [PATCH 04/37] Mention and link settings for dehardcoded models in index page of custom models section. --- docs/source/reference/modding/custom-models/index.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/source/reference/modding/custom-models/index.rst b/docs/source/reference/modding/custom-models/index.rst index 8f575bf3c..b204dffd9 100644 --- a/docs/source/reference/modding/custom-models/index.rst +++ b/docs/source/reference/modding/custom-models/index.rst @@ -2,7 +2,11 @@ Custom Models ############# -Custom models can be imported into OpenMW using a variety of formats. Below is a quick overview of supported formats, followed by separate articles with further look at the pipelines. +Custom models can be imported into OpenMW using a variety of formats. Models for the majority of in-game objects are assigned through openMW-CS :doc:`/manuals/openmw-cs/index`. + +Some models, however, are essential for OpenMW to even run. These include player and NPC animations, and meshes for the sky. They are assigned in the ``settings.cfg`` file, with more information available in :doc:`/reference/modding/settings/models` . + +Below is a quick overview of supported formats, followed by separate articles with further look at the pipelines. * **COLLADA** has no license restrictions and is suitable for modding as well as standalone games based on the OpenMW engine. It supports static and animated models. While it doesn't yet work in all parts of the engine, work is being done to resolve the remaining limitations. From fb55207328fd3367db9e9207993699a8aa8face2 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 21 Apr 2021 19:08:06 +0200 Subject: [PATCH 05/37] Remove some useless includes from the wizzard --- apps/wizard/componentselectionpage.hpp | 2 -- apps/wizard/conclusionpage.hpp | 2 -- apps/wizard/existinginstallationpage.hpp | 2 -- apps/wizard/importpage.hpp | 2 -- apps/wizard/inisettings.cpp | 2 -- apps/wizard/installationtargetpage.hpp | 2 -- apps/wizard/intropage.hpp | 2 -- apps/wizard/languageselectionpage.hpp | 2 -- apps/wizard/main.cpp | 2 -- apps/wizard/mainwizard.hpp | 2 -- apps/wizard/methodselectionpage.hpp | 2 -- apps/wizard/utils/componentlistwidget.cpp | 1 - 12 files changed, 23 deletions(-) diff --git a/apps/wizard/componentselectionpage.hpp b/apps/wizard/componentselectionpage.hpp index 2509b9f5e..961669ab5 100644 --- a/apps/wizard/componentselectionpage.hpp +++ b/apps/wizard/componentselectionpage.hpp @@ -1,8 +1,6 @@ #ifndef COMPONENTSELECTIONPAGE_HPP #define COMPONENTSELECTIONPAGE_HPP -#include - #include "ui_componentselectionpage.h" namespace Wizard diff --git a/apps/wizard/conclusionpage.hpp b/apps/wizard/conclusionpage.hpp index f5f27dfca..72af2cceb 100644 --- a/apps/wizard/conclusionpage.hpp +++ b/apps/wizard/conclusionpage.hpp @@ -1,8 +1,6 @@ #ifndef CONCLUSIONPAGE_HPP #define CONCLUSIONPAGE_HPP -#include - #include "ui_conclusionpage.h" namespace Wizard diff --git a/apps/wizard/existinginstallationpage.hpp b/apps/wizard/existinginstallationpage.hpp index bb229e249..fbbbe432e 100644 --- a/apps/wizard/existinginstallationpage.hpp +++ b/apps/wizard/existinginstallationpage.hpp @@ -1,8 +1,6 @@ #ifndef EXISTINGINSTALLATIONPAGE_HPP #define EXISTINGINSTALLATIONPAGE_HPP -#include - #include "ui_existinginstallationpage.h" namespace Wizard diff --git a/apps/wizard/importpage.hpp b/apps/wizard/importpage.hpp index 412d39ac1..b1f26409a 100644 --- a/apps/wizard/importpage.hpp +++ b/apps/wizard/importpage.hpp @@ -1,8 +1,6 @@ #ifndef IMPORTPAGE_HPP #define IMPORTPAGE_HPP -#include - #include "ui_importpage.h" namespace Wizard diff --git a/apps/wizard/inisettings.cpp b/apps/wizard/inisettings.cpp index d4a63c676..e9cec12f5 100644 --- a/apps/wizard/inisettings.cpp +++ b/apps/wizard/inisettings.cpp @@ -1,7 +1,5 @@ #include "inisettings.hpp" -#include - #include #include #include diff --git a/apps/wizard/installationtargetpage.hpp b/apps/wizard/installationtargetpage.hpp index 7cba29573..1f1e95228 100644 --- a/apps/wizard/installationtargetpage.hpp +++ b/apps/wizard/installationtargetpage.hpp @@ -1,8 +1,6 @@ #ifndef INSTALLATIONTARGETPAGE_HPP #define INSTALLATIONTARGETPAGE_HPP -#include - #include "ui_installationtargetpage.h" namespace Files diff --git a/apps/wizard/intropage.hpp b/apps/wizard/intropage.hpp index c8cd69016..3fae6a747 100644 --- a/apps/wizard/intropage.hpp +++ b/apps/wizard/intropage.hpp @@ -1,8 +1,6 @@ #ifndef INTROPAGE_HPP #define INTROPAGE_HPP -#include - #include "ui_intropage.h" namespace Wizard diff --git a/apps/wizard/languageselectionpage.hpp b/apps/wizard/languageselectionpage.hpp index cc86ba9b3..81f8faa48 100644 --- a/apps/wizard/languageselectionpage.hpp +++ b/apps/wizard/languageselectionpage.hpp @@ -1,8 +1,6 @@ #ifndef LANGUAGESELECTIONPAGE_HPP #define LANGUAGESELECTIONPAGE_HPP -#include - #include "ui_languageselectionpage.h" namespace Wizard diff --git a/apps/wizard/main.cpp b/apps/wizard/main.cpp index e3624742a..67410df14 100644 --- a/apps/wizard/main.cpp +++ b/apps/wizard/main.cpp @@ -1,7 +1,5 @@ #include -#include #include -#include #include "mainwizard.hpp" diff --git a/apps/wizard/mainwizard.hpp b/apps/wizard/mainwizard.hpp index 4c221635e..249ae1cf9 100644 --- a/apps/wizard/mainwizard.hpp +++ b/apps/wizard/mainwizard.hpp @@ -1,9 +1,7 @@ #ifndef MAINWIZARD_HPP #define MAINWIZARD_HPP -#include #include -#include #include diff --git a/apps/wizard/methodselectionpage.hpp b/apps/wizard/methodselectionpage.hpp index 57d551d27..e844024b4 100644 --- a/apps/wizard/methodselectionpage.hpp +++ b/apps/wizard/methodselectionpage.hpp @@ -1,8 +1,6 @@ #ifndef METHODSELECTIONPAGE_HPP #define METHODSELECTIONPAGE_HPP -#include - #include "ui_methodselectionpage.h" namespace Wizard diff --git a/apps/wizard/utils/componentlistwidget.cpp b/apps/wizard/utils/componentlistwidget.cpp index 6a5d019b5..ff37e5d8c 100644 --- a/apps/wizard/utils/componentlistwidget.cpp +++ b/apps/wizard/utils/componentlistwidget.cpp @@ -1,7 +1,6 @@ #include "componentlistwidget.hpp" #include -#include ComponentListWidget::ComponentListWidget(QWidget *parent) : QListWidget(parent) From bd45449f9d0964445ef3d2ee5e1ea4f98ff57c7c Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 1 May 2021 14:07:29 +0200 Subject: [PATCH 06/37] Allow activation of inventory items --- CHANGELOG.md | 1 + apps/openmw/mwscript/miscextensions.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87009f58d..c50054a74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,6 +118,7 @@ Bug #5923: Clicking on empty spaces between journal entries might show random topics Bug #5934: AddItem command doesn't accept negative values Bug #5975: NIF controllers from sheath meshes are used + Bug #5991: Activate should always be allowed for inventory items Bug #5995: NiUVController doesn't calculate the UV offset properly Feature #390: 3rd person look "over the shoulder" Feature #832: OpenMW-CS: Handle deleted references diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index d78337a62..5538e8536 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -278,7 +278,7 @@ namespace MWScript MWWorld::Ptr ptr = R()(runtime); - if (ptr.getRefData().activateByScript()) + if (ptr.getRefData().activateByScript() || ptr.getContainerStore()) context.executeActivation(ptr, MWMechanics::getPlayer()); } }; From 4fa0972b2dc82dad05113f43a200db347e7d64ae Mon Sep 17 00:00:00 2001 From: fredzio Date: Sat, 1 May 2021 14:13:17 +0200 Subject: [PATCH 07/37] Tone down actor's skip simulation flag to an optional skip collision detection flag. --- apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwphysics/actor.cpp | 19 ++++++++++--------- apps/openmw/mwphysics/actor.hpp | 6 ++++-- apps/openmw/mwphysics/movementsolver.cpp | 4 ++-- apps/openmw/mwphysics/mtphysics.cpp | 1 - apps/openmw/mwphysics/physicssystem.cpp | 4 +--- apps/openmw/mwphysics/physicssystem.hpp | 1 + .../mwscript/transformationextensions.cpp | 8 ++++---- apps/openmw/mwworld/worldimp.cpp | 4 ++-- apps/openmw/mwworld/worldimp.hpp | 2 +- 10 files changed, 26 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 6cee36b40..7afd0697e 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -287,7 +287,7 @@ namespace MWBase virtual MWWorld::Ptr moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, float x, float y, float z, bool movePhysics=true) = 0; ///< @return an updated Ptr - virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, osg::Vec3f vec, bool moveToActive) = 0; + virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, osg::Vec3f vec, bool moveToActive, bool ignoreCollisions) = 0; ///< @return an updated Ptr virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0; diff --git a/apps/openmw/mwphysics/actor.cpp b/apps/openmw/mwphysics/actor.cpp index f14805c6f..4b97ecffb 100644 --- a/apps/openmw/mwphysics/actor.cpp +++ b/apps/openmw/mwphysics/actor.cpp @@ -123,7 +123,7 @@ void Actor::updatePosition() mSimulationPosition = mWorldPosition; mPositionOffset = osg::Vec3f(); mStandingOnPtr = nullptr; - mSkipSimulation = true; + mSkipCollisions = true; } void Actor::updateWorldPosition() @@ -140,9 +140,7 @@ osg::Vec3f Actor::getWorldPosition() const void Actor::setSimulationPosition(const osg::Vec3f& position) { - if (!mSkipSimulation) - mSimulationPosition = position; - mSkipSimulation = false; + mSimulationPosition = position; } osg::Vec3f Actor::getSimulationPosition() const @@ -176,21 +174,19 @@ osg::Vec3f Actor::getCollisionObjectPosition() const bool Actor::setPosition(const osg::Vec3f& position) { std::scoped_lock lock(mPositionMutex); - // position is being forced, ignore simulation results until we sync up - if (mSkipSimulation) - return false; - bool hasChanged = mPosition != position || mPositionOffset.length() != 0 || mWorldPositionChanged; updateWorldPosition(); applyOffsetChange(); + bool hasChanged = mPosition != position || mWorldPositionChanged; mPreviousPosition = mPosition; mPosition = position; return hasChanged; } -void Actor::adjustPosition(const osg::Vec3f& offset) +void Actor::adjustPosition(const osg::Vec3f& offset, bool ignoreCollisions) { std::scoped_lock lock(mPositionMutex); mPositionOffset += offset; + mSkipCollisions = mSkipCollisions || ignoreCollisions; } void Actor::applyOffsetChange() @@ -302,4 +298,9 @@ void Actor::setStandingOnPtr(const MWWorld::Ptr& ptr) mStandingOnPtr = ptr; } +bool Actor::skipCollisions() +{ + return std::exchange(mSkipCollisions, false); +} + } diff --git a/apps/openmw/mwphysics/actor.hpp b/apps/openmw/mwphysics/actor.hpp index 472a79bff..54f9009bf 100644 --- a/apps/openmw/mwphysics/actor.hpp +++ b/apps/openmw/mwphysics/actor.hpp @@ -101,7 +101,7 @@ namespace MWPhysics void updatePosition(); // register a position offset that will be applied during simulation. - void adjustPosition(const osg::Vec3f& offset); + void adjustPosition(const osg::Vec3f& offset, bool ignoreCollisions); // apply position offset. Can't be called during simulation void applyOffsetChange(); @@ -177,6 +177,8 @@ namespace MWPhysics mLastStuckPosition = position; } + bool skipCollisions(); + private: MWWorld::Ptr mStandingOnPtr; /// Removes then re-adds the collision object to the dynamics world @@ -206,7 +208,7 @@ namespace MWPhysics osg::Vec3f mPreviousPosition; osg::Vec3f mPositionOffset; bool mWorldPositionChanged; - bool mSkipSimulation; + bool mSkipCollisions; btTransform mLocalTransform; mutable std::mutex mPositionMutex; diff --git a/apps/openmw/mwphysics/movementsolver.cpp b/apps/openmw/mwphysics/movementsolver.cpp index 1c04ee65a..fd0e090fc 100644 --- a/apps/openmw/mwphysics/movementsolver.cpp +++ b/apps/openmw/mwphysics/movementsolver.cpp @@ -131,7 +131,7 @@ namespace MWPhysics // Reset per-frame data physicActor->setWalkingOnWater(false); // Anything to collide with? - if(!physicActor->getCollisionMode()) + if(!physicActor->getCollisionMode() || actor.mSkipCollisionDetection) { actor.mPosition += (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) * osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1)) @@ -437,7 +437,7 @@ namespace MWPhysics return; auto* physicActor = actor.mActorRaw; - if(!physicActor->getCollisionMode()) // noclipping/tcl + if(!physicActor->getCollisionMode() || actor.mSkipCollisionDetection) // noclipping/tcl return; auto* collisionObject = physicActor->getCollisionObject(); diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index 4957ef422..95a741825 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -361,7 +361,6 @@ namespace MWPhysics for (const auto& [_, actor] : actors) { actor->updatePosition(); - actor->setSimulationPosition(actor->getWorldPosition()); // updatePosition skip next simulation, now we need to "consume" it actor->updateCollisionObjectPosition(); mMovedActors.emplace_back(actor->getPtr()); } diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index c5ba902fc..c52ecc68f 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -954,9 +954,7 @@ namespace MWPhysics void ActorFrameData::updatePosition(btCollisionWorld* world) { mActorRaw->updateWorldPosition(); - // If physics runs "fast enough", position are interpolated without simulation - // By calling this here, we are sure that offsets are applied at least once per frame, - // regardless of simulation speed. + mSkipCollisionDetection = mActorRaw->skipCollisions(); mActorRaw->applyOffsetChange(); mPosition = mActorRaw->getPosition(); if (mWaterCollision && mPosition.z() < mWaterlevel && canMoveToWaterSurface(mActorRaw, mWaterlevel, world)) diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index ce10b4246..23b278675 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -91,6 +91,7 @@ namespace MWPhysics bool mFloatToSurface; bool mNeedLand; bool mWaterCollision; + bool mSkipCollisionDetection; float mWaterlevel; float mSlowFall; float mOldHeight; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index ba211503e..dbd8e905a 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -32,7 +32,7 @@ namespace MWScript std::vector actors; MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors); for (auto& actor : actors) - MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff, false); + MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff, false, false); } template @@ -303,7 +303,7 @@ namespace MWScript } dynamic_cast(runtime.getContext()).updatePtr(ptr, - MWBase::Environment::get().getWorld()->moveObjectBy(ptr, newPos - curPos, true)); + MWBase::Environment::get().getWorld()->moveObjectBy(ptr, newPos - curPos, true, true)); } }; @@ -726,7 +726,7 @@ namespace MWScript // This approach can be used to create elevators. moveStandingActors(ptr, diff); dynamic_cast(runtime.getContext()).updatePtr(ptr, - MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff, false)); + MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff, false, true)); } }; @@ -762,7 +762,7 @@ namespace MWScript // This approach can be used to create elevators. moveStandingActors(ptr, diff); dynamic_cast(runtime.getContext()).updatePtr(ptr, - MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff, false)); + MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff, false, true)); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 8bb73c689..e406992e2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1253,12 +1253,12 @@ namespace MWWorld return moveObject(ptr, cell, x, y, z, movePhysics); } - MWWorld::Ptr World::moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive) + MWWorld::Ptr World::moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive, bool ignoreCollisions) { auto* actor = mPhysics->getActor(ptr); osg::Vec3f newpos = ptr.getRefData().getPosition().asVec3() + vec; if (actor) - actor->adjustPosition(vec); + actor->adjustPosition(vec, ignoreCollisions); if (ptr.getClass().isActor()) return moveObject(ptr, newpos.x(), newpos.y(), newpos.z(), false, moveToActive && ptr != getPlayerPtr()); return moveObject(ptr, newpos.x(), newpos.y(), newpos.z()); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 5447e20c3..2789e22c1 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -377,7 +377,7 @@ namespace MWWorld MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z, bool movePhysics=true) override; ///< @return an updated Ptr - MWWorld::Ptr moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive) override; + MWWorld::Ptr moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive, bool ignoreCollisions) override; ///< @return an updated Ptr void scaleObject (const Ptr& ptr, float scale) override; From d45184a7305d2a1a7c518b7edd6aa399ee8da3d8 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Sun, 2 May 2021 14:43:46 +0200 Subject: [PATCH 08/37] Sprinkle some const-ref to avoid unnecessary copies --- apps/openmw/mwworld/cellpreloader.cpp | 6 +++--- components/sceneutil/mwshadowtechnique.cpp | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index 6bc60968c..dfd69b2e5 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -448,7 +448,7 @@ namespace MWWorld void CellPreloader::abortTerrainPreloadExcept(const CellPreloader::PositionCellGrid *exceptPos) { const float resetThreshold = ESM::Land::REAL_SIZE; - for (auto pos : mTerrainPreloadPositions) + for (const auto& pos : mTerrainPreloadPositions) if (exceptPos && (pos.first-exceptPos->first).length2() < resetThreshold*resetThreshold && pos.second == exceptPos->second) return; if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone()) @@ -461,10 +461,10 @@ namespace MWWorld bool contains(const std::vector& container, const std::vector& contained) { - for (auto pos : contained) + for (const auto& pos : contained) { bool found = false; - for (auto pos2 : container) + for (const auto& pos2 : container) { if ((pos.first-pos2.first).length2() < 1 && pos.second == pos2.second) { diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index bf6581ae6..e9eb9b2b2 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -1361,7 +1361,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) if (settings->getMultipleShadowMapHint() == ShadowSettings::CASCADED) { cropShadowCameraToMainFrustum(frustum, camera, cascaseNear, cascadeFar, extraPlanes); - for (auto plane : extraPlanes) + for (const auto& plane : extraPlanes) local_polytope.getPlaneList().push_back(plane); local_polytope.setupMask(); } @@ -1998,19 +1998,19 @@ struct ConvexHull Vertices findInternalEdges(osg::Vec3d mainVertex, Vertices connectedVertices) { Vertices internalEdgeVertices; - for (auto vertex : connectedVertices) + for (const auto& vertex : connectedVertices) { osg::Matrixd matrix; osg::Vec3d dir = vertex - mainVertex; matrix.makeLookAt(mainVertex, vertex, dir.z() == 0 ? osg::Vec3d(0, 0, 1) : osg::Vec3d(1, 0, 0)); Vertices testVertices; - for (auto testVertex : connectedVertices) + for (const auto& testVertex : connectedVertices) { if (vertex != testVertex) testVertices.push_back(testVertex); } std::vector bearings; - for (auto testVertex : testVertices) + for (const auto& testVertex : testVertices) { osg::Vec3d transformedVertex = testVertex * matrix; bearings.push_back(atan2(transformedVertex.y(), transformedVertex.x())); @@ -2039,7 +2039,7 @@ struct ConvexHull // Collect the set of vertices VertexSet vertices; - for (Edge edge : _edges) + for (const Edge& edge : _edges) { vertices.insert(edge.first); vertices.insert(edge.second); @@ -2069,7 +2069,7 @@ struct ConvexHull for (auto vertex : extremeVertices) { Vertices connectedVertices; - for (Edge edge : _edges) + for (const Edge& edge : _edges) { if (edge.first == vertex) connectedVertices.push_back(edge.second); @@ -2107,7 +2107,7 @@ struct ConvexHull osg::Vec3d vertex = *unprocessedConnectedVertices.begin(); unprocessedConnectedVertices.erase(unprocessedConnectedVertices.begin()); connectedVertices.insert(vertex); - for (Edge edge : _edges) + for (const Edge& edge : _edges) { osg::Vec3d otherEnd; if (edge.first == vertex) @@ -2124,7 +2124,7 @@ struct ConvexHull } } - for (Edge edge : _edges) + for (const Edge& edge : _edges) { if (connectedVertices.count(edge.first) || connectedVertices.count(edge.second)) finalEdges.push_back(edge); From 6fd04cb8f644ecdc47490e9e73ed7c3751df4727 Mon Sep 17 00:00:00 2001 From: fredzio Date: Sun, 2 May 2021 17:48:50 +0200 Subject: [PATCH 09/37] Remove support for single-precision Bullet, fail during configuration instead of during linking. --- CI/before_script.msvc.sh | 29 +++++--------------- CI/before_script.osx.sh | 1 - CMakeLists.txt | 7 ++++- cmake/CheckBulletPrecision.cmake | 45 ++++++++++++++++++++++++++++++++ components/CMakeLists.txt | 6 ++--- extern/CMakeLists.txt | 2 +- 6 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 cmake/CheckBulletPrecision.cmake diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index e1afdb059..d98c28038 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -73,9 +73,6 @@ CONFIGURATIONS=() TEST_FRAMEWORK="" GOOGLE_INSTALL_ROOT="" INSTALL_PREFIX="." -BULLET_DOUBLE=true -BULLET_DBL="" -BULLET_DBL_DISPLAY="Single precision" ACTIVATE_MSVC="" SINGLE_CONFIG="" @@ -99,9 +96,6 @@ while [ $# -gt 0 ]; do d ) SKIP_DOWNLOAD=true ;; - D ) - BULLET_DOUBLE=true ;; - e ) SKIP_EXTRACT=true ;; @@ -149,8 +143,6 @@ Options: For single-config generators, several configurations can be set up at once by specifying -c multiple times. -d Skip checking the downloads. - -D - Use double-precision Bullet -e Skip extracting dependencies. -h @@ -433,9 +425,6 @@ if [ -n "$SINGLE_CONFIG" ]; then if [ -n "$SKIP_DOWNLOAD" ]; then RECURSIVE_OPTIONS+=("-d") fi - if [ -n "$BULLET_DOUBLE" ]; then - RECURSIVE_OPTIONS+=("-D") - fi if [ -n "$SKIP_EXTRACT" ]; then RECURSIVE_OPTIONS+=("-e") fi @@ -508,12 +497,6 @@ if ! [ -z $UNITY_BUILD ]; then add_cmake_opts "-DOPENMW_UNITY_BUILD=True" fi -if [ -n "$BULLET_DOUBLE" ]; then - BULLET_DBL="-double" - BULLET_DBL_DISPLAY="Double precision" - add_cmake_opts "-DBULLET_USE_DOUBLES=True" -fi - echo echo "===================================" echo "Starting prebuild on MSVC${MSVC_DISPLAY_YEAR} WIN${BITS}" @@ -538,9 +521,9 @@ if [ -z $SKIP_DOWNLOAD ]; then fi # Bullet - download "Bullet 2.89 (${BULLET_DBL_DISPLAY})" \ - "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" \ - "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" + download "Bullet 2.89" \ + "https://gitlab.com/OpenMW/openmw-deps/-/raw/main/windows/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}-double.7z" \ + "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}-double.7z" # FFmpeg download "FFmpeg 4.2.2" \ @@ -680,15 +663,15 @@ fi cd $DEPS echo # Bullet -printf "Bullet 2.89 (${BULLET_DBL_DISPLAY})... " +printf "Bullet 2.89... " { cd $DEPS_INSTALL if [ -d Bullet ]; then printf -- "Exists. (No version checking) " elif [ -z $SKIP_EXTRACT ]; then rm -rf Bullet - eval 7z x -y "${DEPS}/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}.7z" $STRIP - mv "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}${BULLET_DBL}" Bullet + eval 7z x -y "${DEPS}/Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}-double.7z" $STRIP + mv "Bullet-2.89-msvc${MSVC_YEAR}-win${BITS}-double" Bullet fi add_cmake_opts -DBULLET_ROOT="$(real_pwd)/Bullet" echo Done. diff --git a/CI/before_script.osx.sh b/CI/before_script.osx.sh index f9191eb89..265e05b8e 100755 --- a/CI/before_script.osx.sh +++ b/CI/before_script.osx.sh @@ -25,6 +25,5 @@ cmake \ -D BUILD_BSATOOL=TRUE \ -D BUILD_ESSIMPORTER=TRUE \ -D BUILD_NIFTEST=TRUE \ --D BULLET_USE_DOUBLES=TRUE \ -G"Unix Makefiles" \ .. diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b7d6ad84..693f7fc87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,6 @@ option(BUILD_DOCS "Build documentation." OFF ) option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest" OFF) option(BUILD_BENCHMARKS "Build benchmarks with Google Benchmark" OFF) -option(BULLET_USE_DOUBLES "Use double precision for Bullet" ON) set(OpenGL_GL_PREFERENCE LEGACY) # Use LEGACY as we use GL2; GLNVD is for GL3 and up. @@ -314,6 +313,12 @@ if(OPENMW_USE_SYSTEM_BULLET) endif() find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath) + include(cmake/CheckBulletPrecision.cmake) + if (HAS_DOUBLE_PRECISION_BULLET) + message(STATUS "Bullet uses double precision") + else() + message(FATAL_ERROR "Bullet does not uses double precision") + endif() endif() if (NOT WIN32 AND BUILD_WIZARD) # windows users can just run the morrowind installer diff --git a/cmake/CheckBulletPrecision.cmake b/cmake/CheckBulletPrecision.cmake new file mode 100644 index 000000000..ec3624034 --- /dev/null +++ b/cmake/CheckBulletPrecision.cmake @@ -0,0 +1,45 @@ +set(TMP_ROOT ${CMAKE_BINARY_DIR}/try-compile) +file(MAKE_DIRECTORY ${TMP_ROOT}) + +file(WRITE ${TMP_ROOT}/checkbullet.cpp +" +#include +int main(int argc, char** argv) +{ + btSphereShape shape(1.0); + btScalar mass(1.0); + btVector3 inertia; + shape.calculateLocalInertia(mass, inertia); + return 0; +} +") + +file(WRITE ${TMP_ROOT}/CMakeLists.txt +" +cmake_minimum_required(VERSION 3.1.0) +project(checkbullet) +add_executable(checkbullet checkbullet.cpp) +find_package(Bullet REQUIRED COMPONENTS BulletCollision LinearMath) +target_compile_definitions(checkbullet PUBLIC BT_USE_DOUBLE_PRECISION) +include_directories(\$\{BULLET_INCLUDE_DIRS\}) +include(${CMAKE_SOURCE_DIR}/cmake/OSIdentity.cmake) +if (UBUNTU_FOUND OR DEBIAN_FOUND) + target_link_libraries(checkbullet BulletCollision-float64 LinearMath-float64) +else() + target_link_libraries(checkbullet \$\{BULLET_LIBRARIES\}) +endif() +") + +if (DEFINED BULLET_ROOT) + set(ROOT "-DBULLET_ROOT=${BULLET_ROOT}") +endif() + +message(STATUS "Checking if Bullet uses double precision") + +try_compile(RESULT_VAR + ${CMAKE_BINARY_DIR}/temp + ${TMP_ROOT} + checkbullet + CMAKE_FLAGS "${ROOT}" + ) +set(HAS_DOUBLE_PRECISION_BULLET ${RESULT_VAR}) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 2fe09070a..9b65c3da0 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -254,7 +254,7 @@ target_link_libraries(components RecastNavigation::Recast ) -if (BULLET_USE_DOUBLES AND (UBUNTU_FOUND OR DEBIAN_FOUND) AND OPENMW_USE_SYSTEM_BULLET) +if ((UBUNTU_FOUND OR DEBIAN_FOUND) AND OPENMW_USE_SYSTEM_BULLET) target_link_libraries(components BulletCollision-float64 LinearMath-float64) else() target_link_libraries(components ${BULLET_LIBRARIES}) @@ -292,6 +292,4 @@ endif() # Make the variable accessible for other subdirectories set(COMPONENT_FILES ${COMPONENT_FILES} PARENT_SCOPE) -if (BULLET_USE_DOUBLES) - target_compile_definitions(components PUBLIC BT_USE_DOUBLE_PRECISION) -endif() +target_compile_definitions(components PUBLIC BT_USE_DOUBLE_PRECISION) diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 3842b8357..8257b6b23 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -28,7 +28,7 @@ if(NOT OPENMW_USE_SYSTEM_BULLET) set(BUILD_CPU_DEMOS OFF CACHE BOOL "") set(BUILD_EGL OFF CACHE BOOL "") - set(USE_DOUBLE_PRECISION ${BULLET_USE_DOUBLES} CACHE BOOL "") + set(USE_DOUBLE_PRECISION ON CACHE BOOL "") set(BULLET2_MULTITHREADING ON CACHE BOOL "") if(BULLET_STATIC) From ad5ee1aa1c18b3a9ebaebcb4894c92a9a467026e Mon Sep 17 00:00:00 2001 From: Dobrohotov Alexei Date: Mon, 3 May 2021 01:34:54 +0300 Subject: [PATCH 10/37] Don't flip NV PPL shader Y axis erroneously --- files/shaders/nv_default_fragment.glsl | 2 -- 1 file changed, 2 deletions(-) diff --git a/files/shaders/nv_default_fragment.glsl b/files/shaders/nv_default_fragment.glsl index eadadba39..1bd0f4e31 100644 --- a/files/shaders/nv_default_fragment.glsl +++ b/files/shaders/nv_default_fragment.glsl @@ -56,8 +56,6 @@ void main() #if @normalMap vec4 normalTex = texture2D(normalMap, normalMapUV); - // Must flip Y for DirectX format normal maps - normalTex.y = 1.0 - normalTex.y; vec3 normalizedNormal = normalize(passNormal); vec3 normalizedTangent = normalize(passTangent.xyz); From e3a6cb1695336c834c9664eabc40028f01e3b99f Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sun, 2 May 2021 17:13:16 +0100 Subject: [PATCH 11/37] Remove OsIdentity.cmake Removes the OsIdentity.cmake file and uses a cross-compilation friendly and OS-independent method of detecting system double-precision bullet instead. --- CMakeLists.txt | 23 +++++++++-- cmake/CheckBulletPrecision.cmake | 21 ++++++---- cmake/OSIdentity.cmake | 67 -------------------------------- components/CMakeLists.txt | 6 +-- 4 files changed, 33 insertions(+), 84 deletions(-) delete mode 100644 cmake/OSIdentity.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fc63152e..c3c17ddcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,9 +13,6 @@ if(POLICY CMP0083) cmake_policy(SET CMP0083 NEW) endif() -# Detect OS -include(cmake/OSIdentity.cmake) - option(OPENMW_GL4ES_MANUAL_INIT "Manually initialize gl4es. This is more reliable on platforms without a windowing system. Requires gl4es to be configured with -DNOEGL=ON -DNO_LOADER=ON -DNO_INIT_CONSTRUCTOR=ON." OFF) if(OPENMW_GL4ES_MANUAL_INIT) add_definitions(-DOPENMW_GL4ES_MANUAL_INIT) @@ -312,7 +309,25 @@ if(OPENMW_USE_SYSTEM_BULLET) set(REQUIRED_BULLET_VERSION 283) # but for build testing, 283 is fine endif() - find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath) + # First, try BulletConfig-float64.cmake which comes with Debian derivatives. + # This file does not define the Bullet version in a CMake-friendly way. + find_package(Bullet CONFIGS BulletConfig-float64.cmake QUIET COMPONENTS BulletCollision LinearMath) + if (BULLET_FOUND) + string(REPLACE "." "" _bullet_version_num ${BULLET_VERSION_STRING}) + if (_bullet_version_num VERSION_LESS REQUIRED_BULLET_VERSION) + message(FATAL_ERROR "System bullet version too old, OpenMW requires at least ${REQUIRED_BULLET_VERSION}, got ${_bullet_version_num}") + endif() + # Fix the relative include: + set(BULLET_INCLUDE_DIRS "${BULLET_ROOT_DIR}/${BULLET_INCLUDE_DIRS}") + include(FindPackageMessage) + find_package_message(Bullet "Found Bullet: ${BULLET_LIBRARIES} ${BULLET_VERSION_STRING}" "${BULLET_VERSION_STRING}-float64") + else() + find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath) + endif() + + # Only link the Bullet libraries that we need: + string(REGEX MATCHALL "((optimized|debug);)?[^;]*(BulletCollision|LinearMath)[^;]*" BULLET_LIBRARIES "${BULLET_LIBRARIES}") + include(cmake/CheckBulletPrecision.cmake) if (HAS_DOUBLE_PRECISION_BULLET) message(STATUS "Bullet uses double precision") diff --git a/cmake/CheckBulletPrecision.cmake b/cmake/CheckBulletPrecision.cmake index ec3624034..4700f1651 100644 --- a/cmake/CheckBulletPrecision.cmake +++ b/cmake/CheckBulletPrecision.cmake @@ -18,16 +18,21 @@ file(WRITE ${TMP_ROOT}/CMakeLists.txt " cmake_minimum_required(VERSION 3.1.0) project(checkbullet) -add_executable(checkbullet checkbullet.cpp) -find_package(Bullet REQUIRED COMPONENTS BulletCollision LinearMath) -target_compile_definitions(checkbullet PUBLIC BT_USE_DOUBLE_PRECISION) -include_directories(\$\{BULLET_INCLUDE_DIRS\}) -include(${CMAKE_SOURCE_DIR}/cmake/OSIdentity.cmake) -if (UBUNTU_FOUND OR DEBIAN_FOUND) - target_link_libraries(checkbullet BulletCollision-float64 LinearMath-float64) + +# First, try BulletConfig-float64.cmake which comes with Debian derivatives. +find_package(Bullet CONFIGS BulletConfig-float64.cmake QUIET COMPONENTS BulletCollision LinearMath) +if (BULLET_FOUND) + # Fix the relative include: + set(BULLET_INCLUDE_DIRS \"\$\{BULLET_ROOT_DIR\}/\$\{BULLET_INCLUDE_DIRS\}\") else() - target_link_libraries(checkbullet \$\{BULLET_LIBRARIES\}) + find_package(Bullet REQUIRED COMPONENTS BulletCollision LinearMath) endif() +string(REGEX MATCHALL \"((optimized|debug);)?[^;]*(BulletCollision|LinearMath)[^;]*\" BULLET_LIBRARIES \"$\{BULLET_LIBRARIES\}\") + +add_executable(checkbullet checkbullet.cpp) +target_compile_definitions(checkbullet PUBLIC BT_USE_DOUBLE_PRECISION) +target_include_directories(checkbullet PUBLIC \$\{BULLET_INCLUDE_DIRS\}) +target_link_libraries(checkbullet \$\{BULLET_LIBRARIES\}) ") if (DEFINED BULLET_ROOT) diff --git a/cmake/OSIdentity.cmake b/cmake/OSIdentity.cmake deleted file mode 100644 index 40b7b2089..000000000 --- a/cmake/OSIdentity.cmake +++ /dev/null @@ -1,67 +0,0 @@ -if (UNIX) - - if (APPLE) - - set(CMAKE_OS_NAME "OSX" CACHE STRING "Operating system name" FORCE) - - else (APPLE) - - ## Check for Debian GNU/Linux ________________ - - find_file(DEBIAN_FOUND debian_version debconf.conf - PATHS /etc - ) - if (DEBIAN_FOUND) - set(CMAKE_OS_NAME "Debian" CACHE STRING "Operating system name" FORCE) - endif (DEBIAN_FOUND) - - ## Check for Fedora _________________________ - - find_file(FEDORA_FOUND fedora-release - PATHS /etc - ) - if (FEDORA_FOUND) - set(CMAKE_OS_NAME "Fedora" CACHE STRING "Operating system name" FORCE) - endif (FEDORA_FOUND) - - ## Check for RedHat _________________________ - - find_file(REDHAT_FOUND redhat-release inittab.RH - PATHS /etc - ) - if (REDHAT_FOUND) - set(CMAKE_OS_NAME "RedHat" CACHE STRING "Operating system name" FORCE) - endif (REDHAT_FOUND) - - ## Extra check for Ubuntu ____________________ - - if (DEBIAN_FOUND) - - ## At its core Ubuntu is a Debian system, with - ## a slightly altered configuration; hence from - ## a first superficial inspection a system will - ## be considered as Debian, which signifies an - ## extra check is required. - - find_file(UBUNTU_EXTRA legal issue - PATHS /etc - ) - - if (UBUNTU_EXTRA) - ## Scan contents of file - file(STRINGS ${UBUNTU_EXTRA} UBUNTU_FOUND - REGEX Ubuntu - ) - ## Check result of string search - if (UBUNTU_FOUND) - set(CMAKE_OS_NAME "Ubuntu" CACHE STRING "Operating system name" FORCE) - set(DEBIAN_FOUND FALSE) - endif (UBUNTU_FOUND) - - endif (UBUNTU_EXTRA) - - endif (DEBIAN_FOUND) - - endif (APPLE) - -endif (UNIX) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 9b65c3da0..b901b2e17 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -254,11 +254,7 @@ target_link_libraries(components RecastNavigation::Recast ) -if ((UBUNTU_FOUND OR DEBIAN_FOUND) AND OPENMW_USE_SYSTEM_BULLET) - target_link_libraries(components BulletCollision-float64 LinearMath-float64) -else() - target_link_libraries(components ${BULLET_LIBRARIES}) -endif() +target_link_libraries(components ${BULLET_LIBRARIES}) if (WIN32) target_link_libraries(components From 22aebcea74e1690fcf09d71b998d4de941e5b203 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 02:17:40 +0200 Subject: [PATCH 12/37] Remove useless rcMarkWalkableTriangles call It fills areas.data with walkable triangles but right after it's overwritten and rcClearUnwalkableTriangles is called instead that fills areas.data with unwalkable triangles. --- components/detournavigator/makenavmesh.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index 9701b4950..c4abddf29 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -189,23 +189,6 @@ namespace { const auto chunk = chunkyMesh.getChunk(cid); - std::fill( - areas.begin(), - std::min(areas.begin() + static_cast(chunk.mSize), - areas.end()), - AreaType_null - ); - - rcMarkWalkableTriangles( - &context, - config.walkableSlopeAngle, - recastMesh.getVertices().data(), - static_cast(recastMesh.getVerticesCount()), - chunk.mIndices, - static_cast(chunk.mSize), - areas.data() - ); - for (std::size_t i = 0; i < chunk.mSize; ++i) areas[i] = chunk.mAreaTypes[i]; From bce06df254b3fbc2136a0472a256e3781e6d8f6b Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 12:47:11 +0200 Subject: [PATCH 13/37] Add missing array header --- components/detournavigator/makenavmesh.cpp | 1 + components/detournavigator/recastmeshbuilder.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index c4abddf29..5d3f63689 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace { diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index f8456acf0..3c6364028 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace DetourNavigator { From ec87b3f8f715761404deb32a8ff3154ac88c4d9e Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 02:08:36 +0200 Subject: [PATCH 14/37] Remove redundant ChunkyTriMesh This AABB tree required when need to filter out input mesh that has not influence navmesh tile output. This filtering is already done before. Each recast mesh corresponds to a single navmesh tile and has appropriate bounds. --- .../detournavigator/navmeshtilescache.cpp | 3 +- .../detournavigator/navigator.cpp | 1 - .../detournavigator/navmeshtilescache.cpp | 31 ++- .../detournavigator/recastmeshbuilder.cpp | 1 - .../tilecachedrecastmeshmanager.cpp | 1 - components/CMakeLists.txt | 1 - components/detournavigator/chunkytrimesh.cpp | 179 ------------------ components/detournavigator/chunkytrimesh.hpp | 102 ---------- components/detournavigator/makenavmesh.cpp | 63 +++--- components/detournavigator/recastmesh.cpp | 3 +- components/detournavigator/recastmesh.hpp | 9 +- .../detournavigator/recastmeshbuilder.cpp | 4 +- components/detournavigator/settings.cpp | 1 - components/detournavigator/settings.hpp | 1 - .../reference/modding/settings/navigator.rst | 9 - files/settings-default.cfg | 3 - 16 files changed, 39 insertions(+), 373 deletions(-) delete mode 100644 components/detournavigator/chunkytrimesh.cpp delete mode 100644 components/detournavigator/chunkytrimesh.hpp diff --git a/apps/benchmarks/detournavigator/navmeshtilescache.cpp b/apps/benchmarks/detournavigator/navmeshtilescache.cpp index 10aa0672a..2c7a981ad 100644 --- a/apps/benchmarks/detournavigator/navmeshtilescache.cpp +++ b/apps/benchmarks/detournavigator/navmeshtilescache.cpp @@ -114,9 +114,8 @@ namespace generateAreaTypes(std::back_inserter(areaTypes), indices.size() / 3, random); std::vector water; generateWater(std::back_inserter(water), 2, random); - const std::size_t trianglesPerChunk = 256; RecastMesh recastMesh(generation, revision, std::move(indices), std::move(vertices), - std::move(areaTypes), std::move(water), trianglesPerChunk); + std::move(areaTypes), std::move(water)); std::vector offMeshConnections; generateOffMeshConnection(std::back_inserter(offMeshConnections), 300, random); return Key {agentHalfExtents, tilePosition, std::move(recastMesh), std::move(offMeshConnections)}; diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index 3b7dc4915..619276588 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -68,7 +68,6 @@ namespace mSettings.mMaxNavMeshTilesCacheSize = 1024 * 1024; mSettings.mMaxPolygonPathSize = 1024; mSettings.mMaxSmoothPathSize = 1024; - mSettings.mTrianglesPerChunk = 256; mSettings.mMaxPolys = 4096; mSettings.mMaxTilesNumber = 512; mSettings.mMinUpdateInterval = std::chrono::milliseconds(50); diff --git a/apps/openmw_test_suite/detournavigator/navmeshtilescache.cpp b/apps/openmw_test_suite/detournavigator/navmeshtilescache.cpp index 5d4b1602f..a16c3af1d 100644 --- a/apps/openmw_test_suite/detournavigator/navmeshtilescache.cpp +++ b/apps/openmw_test_suite/detournavigator/navmeshtilescache.cpp @@ -31,9 +31,7 @@ namespace const std::vector mVertices {{0, 0, 0, 1, 0, 0, 1, 1, 0}}; const std::vector mAreaTypes {1, AreaType_ground}; const std::vector mWater {}; - const std::size_t mTrianglesPerChunk {1}; - const RecastMesh mRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, mWater, mTrianglesPerChunk}; + const RecastMesh mRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, mWater}; const std::vector mOffMeshConnections {}; unsigned char* const mData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData mNavMeshData {mData, 1}; @@ -130,8 +128,7 @@ namespace const std::size_t maxSize = 1; NavMeshTilesCache cache(maxSize); const std::vector water {1, RecastMesh::Water {1, btTransform::getIdentity()}}; - const RecastMesh unexistentRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, water, mTrianglesPerChunk}; + const RecastMesh unexistentRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water}; cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, mOffMeshConnections, std::move(mNavMeshData)); EXPECT_FALSE(cache.get(mAgentHalfExtents, mTilePosition, unexistentRecastMesh, mOffMeshConnections)); @@ -145,8 +142,7 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water {1, RecastMesh::Water {1, btTransform::getIdentity()}}; - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, water, mTrianglesPerChunk}; + const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water}; const auto anotherData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData anotherNavMeshData {anotherData, 1}; @@ -166,8 +162,7 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water {1, RecastMesh::Water {1, btTransform::getIdentity()}}; - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, water, mTrianglesPerChunk}; + const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water}; const auto anotherData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData anotherNavMeshData {anotherData, 1}; @@ -186,13 +181,13 @@ namespace const std::vector leastRecentlySetWater {1, RecastMesh::Water {1, btTransform::getIdentity()}}; const RecastMesh leastRecentlySetRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, leastRecentlySetWater, mTrianglesPerChunk}; + mAreaTypes, leastRecentlySetWater}; const auto leastRecentlySetData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData leastRecentlySetNavMeshData {leastRecentlySetData, 1}; const std::vector mostRecentlySetWater {1, RecastMesh::Water {2, btTransform::getIdentity()}}; const RecastMesh mostRecentlySetRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, mostRecentlySetWater, mTrianglesPerChunk}; + mAreaTypes, mostRecentlySetWater}; const auto mostRecentlySetData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData mostRecentlySetNavMeshData {mostRecentlySetData, 1}; @@ -218,13 +213,13 @@ namespace const std::vector leastRecentlyUsedWater {1, RecastMesh::Water {1, btTransform::getIdentity()}}; const RecastMesh leastRecentlyUsedRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, leastRecentlyUsedWater, mTrianglesPerChunk}; + mAreaTypes, leastRecentlyUsedWater}; const auto leastRecentlyUsedData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData leastRecentlyUsedNavMeshData {leastRecentlyUsedData, 1}; const std::vector mostRecentlyUsedWater {1, RecastMesh::Water {2, btTransform::getIdentity()}}; const RecastMesh mostRecentlyUsedRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, mostRecentlyUsedWater, mTrianglesPerChunk}; + mAreaTypes, mostRecentlyUsedWater}; const auto mostRecentlyUsedData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData mostRecentlyUsedNavMeshData {mostRecentlyUsedData, 1}; @@ -261,7 +256,7 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water {1, RecastMesh::Water {1, btTransform::getIdentity()}}; - const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk}; + const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water}; const auto tooLargeData = reinterpret_cast(dtAlloc(2, DT_ALLOC_PERM)); NavMeshData tooLargeNavMeshData {tooLargeData, 2}; @@ -280,13 +275,13 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector anotherWater {1, RecastMesh::Water {1, btTransform::getIdentity()}}; - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, anotherWater, mTrianglesPerChunk}; + const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, anotherWater}; const auto anotherData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData anotherNavMeshData {anotherData, 1}; const std::vector tooLargeWater {1, RecastMesh::Water {2, btTransform::getIdentity()}}; const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, tooLargeWater, mTrianglesPerChunk}; + mAreaTypes, tooLargeWater}; const auto tooLargeData = reinterpret_cast(dtAlloc(2, DT_ALLOC_PERM)); NavMeshData tooLargeNavMeshData {tooLargeData, 2}; @@ -310,7 +305,7 @@ namespace const std::vector water {1, RecastMesh::Water {1, btTransform::getIdentity()}}; const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, - mAreaTypes, water, mTrianglesPerChunk}; + mAreaTypes, water}; const auto anotherData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData anotherNavMeshData {anotherData, 1}; @@ -333,7 +328,7 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water {1, RecastMesh::Water {1, btTransform::getIdentity()}}; - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk}; + const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water}; const auto anotherData = reinterpret_cast(dtAlloc(1, DT_ALLOC_PERM)); NavMeshData anotherNavMeshData {anotherData, 1}; diff --git a/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp b/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp index bcbf448ac..5f43f4800 100644 --- a/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp +++ b/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp @@ -37,7 +37,6 @@ namespace DetourNavigatorRecastMeshBuilderTest() { mSettings.mRecastScaleFactor = 1.0f; - mSettings.mTrianglesPerChunk = 256; mBounds.mMin = osg::Vec2f(-std::numeric_limits::max() * std::numeric_limits::epsilon(), -std::numeric_limits::max() * std::numeric_limits::epsilon()); mBounds.mMax = osg::Vec2f(std::numeric_limits::max() * std::numeric_limits::epsilon(), diff --git a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp index be5209001..2d6d9f66b 100644 --- a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp @@ -24,7 +24,6 @@ namespace mSettings.mCellSize = 0.2f; mSettings.mRecastScaleFactor = 0.017647058823529415f; mSettings.mTileSize = 64; - mSettings.mTrianglesPerChunk = 256; } void onChangedTile(const TilePosition& tilePosition) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index b901b2e17..9041ee533 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -173,7 +173,6 @@ add_component_dir(detournavigator navmeshmanager navigatorimpl asyncnavmeshupdater - chunkytrimesh recastmesh tilecachedrecastmeshmanager recastmeshobject diff --git a/components/detournavigator/chunkytrimesh.cpp b/components/detournavigator/chunkytrimesh.cpp deleted file mode 100644 index ffd39d0a9..000000000 --- a/components/detournavigator/chunkytrimesh.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "chunkytrimesh.hpp" -#include "exceptions.hpp" - -#include - -#include - -namespace DetourNavigator -{ - namespace - { - struct BoundsItem - { - Rect mBounds; - std::ptrdiff_t mOffset; - unsigned char mAreaTypes; - }; - - template - struct LessBoundsItem - { - bool operator ()(const BoundsItem& lhs, const BoundsItem& rhs) const - { - return lhs.mBounds.mMinBound[axis] < rhs.mBounds.mMinBound[axis]; - } - }; - - void calcExtends(const std::vector& items, const std::size_t imin, const std::size_t imax, - Rect& bounds) - { - bounds = items[imin].mBounds; - - std::for_each( - items.begin() + static_cast(imin) + 1, - items.begin() + static_cast(imax), - [&] (const BoundsItem& item) - { - for (int i = 0; i < 2; ++i) - { - bounds.mMinBound[i] = std::min(bounds.mMinBound[i], item.mBounds.mMinBound[i]); - bounds.mMaxBound[i] = std::max(bounds.mMaxBound[i], item.mBounds.mMaxBound[i]); - } - }); - } - - void subdivide(std::vector& items, const std::size_t imin, const std::size_t imax, - const std::size_t trisPerChunk, const std::vector& inIndices, const std::vector& inAreaTypes, - std::size_t& curNode, std::vector& nodes, std::size_t& curTri, - std::vector& outIndices, std::vector& outAreaTypes) - { - const auto inum = imax - imin; - const auto icur = curNode; - - if (curNode >= nodes.size()) - return; - - ChunkyTriMeshNode& node = nodes[curNode++]; - - if (inum <= trisPerChunk) - { - // Leaf - calcExtends(items, imin, imax, node.mBounds); - - // Copy triangles. - node.mOffset = static_cast(curTri); - node.mSize = inum; - - for (std::size_t i = imin; i < imax; ++i) - { - std::copy( - inIndices.begin() + items[i].mOffset * 3, - inIndices.begin() + items[i].mOffset * 3 + 3, - outIndices.begin() + static_cast(curTri) * 3 - ); - outAreaTypes[curTri] = inAreaTypes[static_cast(items[i].mOffset)]; - curTri++; - } - } - else - { - // Split - calcExtends(items, imin, imax, node.mBounds); - - if (node.mBounds.mMaxBound.x() - node.mBounds.mMinBound.x() - >= node.mBounds.mMaxBound.y() - node.mBounds.mMinBound.y()) - { - // Sort along x-axis - std::sort( - items.begin() + static_cast(imin), - items.begin() + static_cast(imax), - LessBoundsItem<0> {} - ); - } - else - { - // Sort along y-axis - std::sort( - items.begin() + static_cast(imin), - items.begin() + static_cast(imax), - LessBoundsItem<1> {} - ); - } - - const auto isplit = imin + inum / 2; - - // Left - subdivide(items, imin, isplit, trisPerChunk, inIndices, inAreaTypes, curNode, nodes, curTri, outIndices, outAreaTypes); - // Right - subdivide(items, isplit, imax, trisPerChunk, inIndices, inAreaTypes, curNode, nodes, curTri, outIndices, outAreaTypes); - - const auto iescape = static_cast(curNode) - static_cast(icur); - // Negative index means escape. - node.mOffset = -iescape; - } - } - } - - ChunkyTriMesh::ChunkyTriMesh(const std::vector& verts, const std::vector& indices, - const std::vector& flags, const std::size_t trisPerChunk) - : mMaxTrisPerChunk(0) - { - const auto trianglesCount = indices.size() / 3; - - if (trianglesCount == 0) - return; - - const auto nchunks = (trianglesCount + trisPerChunk - 1) / trisPerChunk; - - mNodes.resize(nchunks * 4); - mIndices.resize(trianglesCount * 3); - mAreaTypes.resize(trianglesCount); - - // Build tree - std::vector items(trianglesCount); - - for (std::size_t i = 0; i < trianglesCount; i++) - { - auto& item = items[i]; - - item.mOffset = static_cast(i); - item.mAreaTypes = flags[i]; - - // Calc triangle XZ bounds. - const auto baseIndex = static_cast(indices[i * 3]) * 3; - - item.mBounds.mMinBound.x() = item.mBounds.mMaxBound.x() = verts[baseIndex + 0]; - item.mBounds.mMinBound.y() = item.mBounds.mMaxBound.y() = verts[baseIndex + 2]; - - for (std::size_t j = 1; j < 3; ++j) - { - const auto index = static_cast(indices[i * 3 + j]) * 3; - - item.mBounds.mMinBound.x() = std::min(item.mBounds.mMinBound.x(), verts[index + 0]); - item.mBounds.mMinBound.y() = std::min(item.mBounds.mMinBound.y(), verts[index + 2]); - - item.mBounds.mMaxBound.x() = std::max(item.mBounds.mMaxBound.x(), verts[index + 0]); - item.mBounds.mMaxBound.y() = std::max(item.mBounds.mMaxBound.y(), verts[index + 2]); - } - } - - std::size_t curTri = 0; - std::size_t curNode = 0; - subdivide(items, 0, trianglesCount, trisPerChunk, indices, flags, curNode, mNodes, curTri, mIndices, mAreaTypes); - - items.clear(); - - mNodes.resize(curNode); - - // Calc max tris per node. - for (auto& node : mNodes) - { - const bool isLeaf = node.mOffset >= 0; - if (!isLeaf) - continue; - if (node.mSize > mMaxTrisPerChunk) - mMaxTrisPerChunk = node.mSize; - } - } -} diff --git a/components/detournavigator/chunkytrimesh.hpp b/components/detournavigator/chunkytrimesh.hpp deleted file mode 100644 index 7f98f5d22..000000000 --- a/components/detournavigator/chunkytrimesh.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_CHUNKYTRIMESH_H -#define OPENMW_COMPONENTS_DETOURNAVIGATOR_CHUNKYTRIMESH_H - -#include "areatype.hpp" - -#include - -#include -#include - -namespace DetourNavigator -{ - struct Rect - { - osg::Vec2f mMinBound; - osg::Vec2f mMaxBound; - }; - - struct ChunkyTriMeshNode - { - Rect mBounds; - std::ptrdiff_t mOffset; - std::size_t mSize; - }; - - struct Chunk - { - const int* const mIndices; - const AreaType* const mAreaTypes; - const std::size_t mSize; - }; - - inline bool checkOverlapRect(const Rect& lhs, const Rect& rhs) - { - bool overlap = true; - overlap = (lhs.mMinBound.x() > rhs.mMaxBound.x() || lhs.mMaxBound.x() < rhs.mMinBound.x()) ? false : overlap; - overlap = (lhs.mMinBound.y() > rhs.mMaxBound.y() || lhs.mMaxBound.y() < rhs.mMinBound.y()) ? false : overlap; - return overlap; - } - - class ChunkyTriMesh - { - public: - /// Creates partitioned triangle mesh (AABB tree), - /// where each node contains at max trisPerChunk triangles. - ChunkyTriMesh(const std::vector& verts, const std::vector& tris, - const std::vector& flags, const std::size_t trisPerChunk); - - ChunkyTriMesh(ChunkyTriMesh&&) = default; - ChunkyTriMesh& operator=(ChunkyTriMesh&&) = default; - - ChunkyTriMesh(const ChunkyTriMesh&) = delete; - ChunkyTriMesh& operator=(const ChunkyTriMesh&) = delete; - - /// Returns the chunk indices which overlap the input rectable. - template - void forEachChunksOverlappingRect(const Rect& rect, Function&& function) const - { - // Traverse tree - for (std::size_t i = 0; i < mNodes.size(); ) - { - const ChunkyTriMeshNode* node = &mNodes[i]; - const bool overlap = checkOverlapRect(rect, node->mBounds); - const bool isLeafNode = node->mOffset >= 0; - - if (isLeafNode && overlap) - function(i); - - if (overlap || isLeafNode) - i++; - else - { - const auto escapeIndex = -node->mOffset; - i += static_cast(escapeIndex); - } - } - } - - Chunk getChunk(const std::size_t chunkId) const - { - const auto& node = mNodes[chunkId]; - return Chunk { - mIndices.data() + node.mOffset * 3, - mAreaTypes.data() + node.mOffset, - node.mSize - }; - } - - std::size_t getMaxTrisPerChunk() const - { - return mMaxTrisPerChunk; - } - - private: - std::vector mNodes; - std::vector mIndices; - std::vector mAreaTypes; - std::size_t mMaxTrisPerChunk; - }; -} - -#endif diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index 5d3f63689..70fd44c6c 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -1,5 +1,4 @@ #include "makenavmesh.hpp" -#include "chunkytrimesh.hpp" #include "debug.hpp" #include "dtstatus.hpp" #include "exceptions.hpp" @@ -179,48 +178,30 @@ namespace bool rasterizeSolidObjectsTriangles(rcContext& context, const RecastMesh& recastMesh, const rcConfig& config, rcHeightfield& solid) { - const auto& chunkyMesh = recastMesh.getChunkyTriMesh(); - std::vector areas(chunkyMesh.getMaxTrisPerChunk(), AreaType_null); const osg::Vec2f tileBoundsMin(config.bmin[0], config.bmin[2]); const osg::Vec2f tileBoundsMax(config.bmax[0], config.bmax[2]); - bool result = false; - - chunkyMesh.forEachChunksOverlappingRect(Rect {tileBoundsMin, tileBoundsMax}, - [&] (const std::size_t cid) - { - const auto chunk = chunkyMesh.getChunk(cid); - - for (std::size_t i = 0; i < chunk.mSize; ++i) - areas[i] = chunk.mAreaTypes[i]; - - rcClearUnwalkableTriangles( - &context, - config.walkableSlopeAngle, - recastMesh.getVertices().data(), - static_cast(recastMesh.getVerticesCount()), - chunk.mIndices, - static_cast(chunk.mSize), - areas.data() - ); - - const auto trianglesRasterized = rcRasterizeTriangles( - &context, - recastMesh.getVertices().data(), - static_cast(recastMesh.getVerticesCount()), - chunk.mIndices, - areas.data(), - static_cast(chunk.mSize), - solid, - config.walkableClimb - ); - - if (!trianglesRasterized) - throw NavigatorException("Failed to create rasterize triangles from recast mesh for navmesh"); - - result = true; - }); - - return result; + std::vector areas(recastMesh.getAreaTypes().begin(), recastMesh.getAreaTypes().end()); + + rcClearUnwalkableTriangles( + &context, + config.walkableSlopeAngle, + recastMesh.getVertices().data(), + static_cast(recastMesh.getVerticesCount()), + recastMesh.getIndices().data(), + static_cast(areas.size()), + areas.data() + ); + + return rcRasterizeTriangles( + &context, + recastMesh.getVertices().data(), + static_cast(recastMesh.getVerticesCount()), + recastMesh.getIndices().data(), + areas.data(), + static_cast(areas.size()), + solid, + config.walkableClimb + ); } void rasterizeWaterTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh, diff --git a/components/detournavigator/recastmesh.cpp b/components/detournavigator/recastmesh.cpp index dc56f7b93..1a9982402 100644 --- a/components/detournavigator/recastmesh.cpp +++ b/components/detournavigator/recastmesh.cpp @@ -6,14 +6,13 @@ namespace DetourNavigator { RecastMesh::RecastMesh(std::size_t generation, std::size_t revision, std::vector indices, std::vector vertices, - std::vector areaTypes, std::vector water, const std::size_t trianglesPerChunk) + std::vector areaTypes, std::vector water) : mGeneration(generation) , mRevision(revision) , mIndices(std::move(indices)) , mVertices(std::move(vertices)) , mAreaTypes(std::move(areaTypes)) , mWater(std::move(water)) - , mChunkyTriMesh(mVertices, mIndices, mAreaTypes, trianglesPerChunk) { if (getTrianglesCount() != mAreaTypes.size()) throw InvalidArgument("Number of flags doesn't match number of triangles: triangles=" diff --git a/components/detournavigator/recastmesh.hpp b/components/detournavigator/recastmesh.hpp index 746422ac8..1961d518d 100644 --- a/components/detournavigator/recastmesh.hpp +++ b/components/detournavigator/recastmesh.hpp @@ -2,7 +2,6 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESH_H #include "areatype.hpp" -#include "chunkytrimesh.hpp" #include "bounds.hpp" #include @@ -28,7 +27,7 @@ namespace DetourNavigator }; RecastMesh(std::size_t generation, std::size_t revision, std::vector indices, std::vector vertices, - std::vector areaTypes, std::vector water, const std::size_t trianglesPerChunk); + std::vector areaTypes, std::vector water); std::size_t getGeneration() const { @@ -70,11 +69,6 @@ namespace DetourNavigator return mIndices.size() / 3; } - const ChunkyTriMesh& getChunkyTriMesh() const - { - return mChunkyTriMesh; - } - const Bounds& getBounds() const { return mBounds; @@ -87,7 +81,6 @@ namespace DetourNavigator std::vector mVertices; std::vector mAreaTypes; std::vector mWater; - ChunkyTriMesh mChunkyTriMesh; Bounds mBounds; }; diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index 3c6364028..7e06c9229 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -1,5 +1,4 @@ #include "recastmeshbuilder.hpp" -#include "chunkytrimesh.hpp" #include "debug.hpp" #include "settings.hpp" #include "settingsutils.hpp" @@ -157,8 +156,7 @@ namespace DetourNavigator { optimizeRecastMesh(mIndices, mVertices); std::sort(mWater.begin(), mWater.end()); - return std::make_shared(generation, revision, mIndices, mVertices, mAreaTypes, - mWater, mSettings.get().mTrianglesPerChunk); + return std::make_shared(generation, revision, mIndices, mVertices, mAreaTypes, mWater); } void RecastMeshBuilder::reset() diff --git a/components/detournavigator/settings.cpp b/components/detournavigator/settings.cpp index 977b80cf5..0c4d0f838 100644 --- a/components/detournavigator/settings.cpp +++ b/components/detournavigator/settings.cpp @@ -33,7 +33,6 @@ namespace DetourNavigator navigatorSettings.mMaxNavMeshTilesCacheSize = static_cast(::Settings::Manager::getInt("max nav mesh tiles cache size", "Navigator")); navigatorSettings.mMaxPolygonPathSize = static_cast(::Settings::Manager::getInt("max polygon path size", "Navigator")); navigatorSettings.mMaxSmoothPathSize = static_cast(::Settings::Manager::getInt("max smooth path size", "Navigator")); - navigatorSettings.mTrianglesPerChunk = static_cast(::Settings::Manager::getInt("triangles per chunk", "Navigator")); navigatorSettings.mEnableWriteRecastMeshToFile = ::Settings::Manager::getBool("enable write recast mesh to file", "Navigator"); navigatorSettings.mEnableWriteNavMeshToFile = ::Settings::Manager::getBool("enable write nav mesh to file", "Navigator"); navigatorSettings.mRecastMeshPathPrefix = ::Settings::Manager::getString("recast mesh path prefix", "Navigator"); diff --git a/components/detournavigator/settings.hpp b/components/detournavigator/settings.hpp index d73087b21..ece16e35a 100644 --- a/components/detournavigator/settings.hpp +++ b/components/detournavigator/settings.hpp @@ -35,7 +35,6 @@ namespace DetourNavigator std::size_t mMaxNavMeshTilesCacheSize = 0; std::size_t mMaxPolygonPathSize = 0; std::size_t mMaxSmoothPathSize = 0; - std::size_t mTrianglesPerChunk = 0; std::string mRecastMeshPathPrefix; std::string mNavMeshPathPrefix; std::chrono::milliseconds mMinUpdateInterval; diff --git a/docs/source/reference/modding/settings/navigator.rst b/docs/source/reference/modding/settings/navigator.rst index fcef549d0..b9485c3e9 100644 --- a/docs/source/reference/modding/settings/navigator.rst +++ b/docs/source/reference/modding/settings/navigator.rst @@ -231,15 +231,6 @@ max smooth path size Maximum size of smoothed path. -triangles per chunk -------------------- - -:Type: integer -:Range: > 0 -:Default: 256 - -Maximum number of triangles in each node of mesh AABB tree. - Expert Recastnavigation related settings **************************************** diff --git a/files/settings-default.cfg b/files/settings-default.cfg index c20820e68..ea678c70f 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -875,9 +875,6 @@ max polygon path size = 1024 # Maximum size of smoothed path (value > 0) max smooth path size = 1024 -# Maximum number of triangles in each node of mesh AABB tree (value > 0) -triangles per chunk = 256 - # Write recast mesh to file in .obj format for each use to update nav mesh (true, false) enable write recast mesh to file = false From 865ef56a09aa739bdf42a7129ebd2c0d144f7bb8 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 12:58:57 +0200 Subject: [PATCH 15/37] Replace include by RecastMesh forward declaration To reduce dependency between navigator interface and implementation. --- components/detournavigator/navigator.hpp | 1 - components/detournavigator/recastmeshtiles.hpp | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index d08bfa640..edf597348 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -6,7 +6,6 @@ #include "settings.hpp" #include "objectid.hpp" #include "navmeshcacheitem.hpp" -#include "recastmesh.hpp" #include "recastmeshtiles.hpp" namespace ESM diff --git a/components/detournavigator/recastmeshtiles.hpp b/components/detournavigator/recastmeshtiles.hpp index 68e30ba63..03059c744 100644 --- a/components/detournavigator/recastmeshtiles.hpp +++ b/components/detournavigator/recastmeshtiles.hpp @@ -2,13 +2,14 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESHTILE_H #include "tileposition.hpp" -#include "recastmesh.hpp" #include #include namespace DetourNavigator { + class RecastMesh; + using RecastMeshTiles = std::map>; } From 231780a51d43d96a3a62f9c8b90565201a3c9b35 Mon Sep 17 00:00:00 2001 From: fredzio Date: Tue, 4 May 2021 22:18:30 +0200 Subject: [PATCH 16/37] Simplify the bullet detection. This way we don't need to explicitly pass all possible variables to the try_compile stuff --- cmake/CheckBulletPrecision.cmake | 34 +++++--------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/cmake/CheckBulletPrecision.cmake b/cmake/CheckBulletPrecision.cmake index 4700f1651..77409f932 100644 --- a/cmake/CheckBulletPrecision.cmake +++ b/cmake/CheckBulletPrecision.cmake @@ -14,37 +14,13 @@ int main(int argc, char** argv) } ") -file(WRITE ${TMP_ROOT}/CMakeLists.txt -" -cmake_minimum_required(VERSION 3.1.0) -project(checkbullet) - -# First, try BulletConfig-float64.cmake which comes with Debian derivatives. -find_package(Bullet CONFIGS BulletConfig-float64.cmake QUIET COMPONENTS BulletCollision LinearMath) -if (BULLET_FOUND) - # Fix the relative include: - set(BULLET_INCLUDE_DIRS \"\$\{BULLET_ROOT_DIR\}/\$\{BULLET_INCLUDE_DIRS\}\") -else() - find_package(Bullet REQUIRED COMPONENTS BulletCollision LinearMath) -endif() -string(REGEX MATCHALL \"((optimized|debug);)?[^;]*(BulletCollision|LinearMath)[^;]*\" BULLET_LIBRARIES \"$\{BULLET_LIBRARIES\}\") - -add_executable(checkbullet checkbullet.cpp) -target_compile_definitions(checkbullet PUBLIC BT_USE_DOUBLE_PRECISION) -target_include_directories(checkbullet PUBLIC \$\{BULLET_INCLUDE_DIRS\}) -target_link_libraries(checkbullet \$\{BULLET_LIBRARIES\}) -") - -if (DEFINED BULLET_ROOT) - set(ROOT "-DBULLET_ROOT=${BULLET_ROOT}") -endif() - message(STATUS "Checking if Bullet uses double precision") try_compile(RESULT_VAR - ${CMAKE_BINARY_DIR}/temp - ${TMP_ROOT} - checkbullet - CMAKE_FLAGS "${ROOT}" + ${TMP_ROOT}/temp + ${TMP_ROOT}/checkbullet.cpp + COMPILE_DEFINITIONS "-DBT_USE_DOUBLE_PRECISION" + LINK_LIBRARIES ${BULLET_LIBRARIES} + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${BULLET_INCLUDE_DIRS}" ) set(HAS_DOUBLE_PRECISION_BULLET ${RESULT_VAR}) From 87ada56edd9d5d5b0a9e6a8dcfd06eb09b161746 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 20:58:01 +0000 Subject: [PATCH 17/37] Various fixes for niftest --- components/nif/niffile.cpp | 12 +++++------ components/nif/nifstream.cpp | 2 +- components/nif/nifstream.hpp | 41 ++++++++++++++++++++---------------- 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 3e226b35e..864a388e8 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -212,7 +212,7 @@ void NIFFile::parse(Files::IStreamPtr stream) userVer = nif.getUInt(); // Number of records - unsigned int recNum = nif.getUInt(); + const std::size_t recNum = nif.getUInt(); records.resize(recNum); // Bethesda stream header @@ -251,7 +251,7 @@ void NIFFile::parse(Files::IStreamPtr stream) std::vector recSizes; // Currently unused nif.getUInts(recSizes, recNum); } - unsigned int stringNum = nif.getUInt(); + const std::size_t stringNum = nif.getUInt(); nif.getUInt(); // Max string length if (stringNum) nif.getSizedStrings(strings, stringNum); @@ -264,7 +264,7 @@ void NIFFile::parse(Files::IStreamPtr stream) } const bool hasRecordSeparators = ver >= NIFStream::generateVersion(10,0,0,0) && ver < NIFStream::generateVersion(10,2,0,0); - for (unsigned int i = 0; i < recNum; i++) + for (std::size_t i = 0; i < recNum; i++) { Record *r = nullptr; @@ -308,14 +308,14 @@ void NIFFile::parse(Files::IStreamPtr stream) r->read(&nif); } - unsigned int rootNum = nif.getUInt(); + const std::size_t rootNum = nif.getUInt(); roots.resize(rootNum); //Determine which records are roots - for (unsigned int i = 0; i < rootNum; i++) + for (std::size_t i = 0; i < rootNum; i++) { int idx = nif.getInt(); - if (idx >= 0 && idx < int(records.size())) + if (idx >= 0 && static_cast(idx) < records.size()) { roots[i] = records[idx]; } diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index 07c9c917c..6129a1739 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -7,7 +7,7 @@ namespace Nif osg::Quat NIFStream::getQuaternion() { float f[4]; - readLittleEndianBufferOfType<4, float>(inp, (float*)&f); + readLittleEndianBufferOfType<4, float>(inp, f); osg::Quat quat; quat.w() = f[0]; quat.x() = f[1]; diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 4d221b867..b6bf01ce5 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -22,31 +24,32 @@ namespace Nif class NIFFile; -/* - readLittleEndianBufferOfType: This template should only be used with arithmetic types -*/ -template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) +template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) { + static_assert(std::is_arithmetic_v, "Buffer element type is not arithmetic"); pIStream->read((char*)dest, numInstances * sizeof(T)); + if (pIStream->bad()) + throw std::runtime_error("Failed to read little endian typed (" + std::string(typeid(T).name()) + ") buffer of " + + std::to_string(numInstances) + " instances"); if constexpr (Misc::IS_BIG_ENDIAN) - for (uint32_t i = 0; i < numInstances; i++) + for (std::size_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); } -/* - readLittleEndianDynamicBufferOfType: This template should only be used with arithmetic types -*/ -template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, uint32_t numInstances) +template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, std::size_t numInstances) { + static_assert(std::is_arithmetic_v, "Buffer element type is not arithmetic"); pIStream->read((char*)dest, numInstances * sizeof(T)); + if (pIStream->bad()) + throw std::runtime_error("Failed to read little endian dynamic buffer of " + std::to_string(numInstances) + " instances"); if constexpr (Misc::IS_BIG_ENDIAN) - for (uint32_t i = 0; i < numInstances; i++) + for (std::size_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); } template type inline readLittleEndianType(Files::IStreamPtr &pIStream) { type val; - readLittleEndianBufferOfType<1, type>(pIStream, (type*)&val); + readLittleEndianBufferOfType<1, type>(pIStream, &val); return val; } @@ -96,21 +99,21 @@ public: osg::Vec2f getVector2() { osg::Vec2f vec; - readLittleEndianBufferOfType<2,float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<2,float>(inp, vec._v); return vec; } osg::Vec3f getVector3() { osg::Vec3f vec; - readLittleEndianBufferOfType<3, float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<3, float>(inp, vec._v); return vec; } osg::Vec4f getVector4() { osg::Vec4f vec; - readLittleEndianBufferOfType<4, float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<4, float>(inp, vec._v); return vec; } @@ -142,11 +145,11 @@ public: ///Read in a string of the given length std::string getSizedString(size_t length) { - std::vector str(length + 1, 0); - + std::string str(length, '\0'); inp->read(str.data(), length); - - return str.data(); + if (inp->bad()) + throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars"); + return str; } ///Read in a string of the length specified in the file std::string getSizedString() @@ -167,6 +170,8 @@ public: { std::string result; std::getline(*inp, result); + if (inp->bad()) + throw std::runtime_error("Failed to read version string"); return result; } From e94181b2b26e15d27b8cb255db262ede3126f0bf Mon Sep 17 00:00:00 2001 From: psi29a Date: Tue, 4 May 2021 21:03:14 +0000 Subject: [PATCH 18/37] Merge branch 'constexpr' into 'master' Sprinkle a couple of constexpr found by VS See merge request OpenMW/openmw!800 (cherry picked from commit 5e8ea624bc85acebf457592dd10b790124ecf6ef) 5704b2ac Sprinkle a couple of constexpr found by VS --- components/esm/loadland.cpp | 6 +++--- components/terrain/quadtreeworld.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 2aa8f21db..38596628f 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -161,9 +161,9 @@ namespace ESM { // Generate WNAM record signed char wnam[LAND_GLOBAL_MAP_LOD_SIZE]; - float max = std::numeric_limits::max(); - float min = std::numeric_limits::min(); - float vertMult = static_cast(ESM::Land::LAND_SIZE - 1) / LAND_GLOBAL_MAP_LOD_SIZE_SQRT; + constexpr float max = std::numeric_limits::max(); + constexpr float min = std::numeric_limits::min(); + constexpr float vertMult = static_cast(ESM::Land::LAND_SIZE - 1) / LAND_GLOBAL_MAP_LOD_SIZE_SQRT; for (int row = 0; row < LAND_GLOBAL_MAP_LOD_SIZE_SQRT; ++row) { for (int col = 0; col < LAND_GLOBAL_MAP_LOD_SIZE_SQRT; ++col) diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index 70b44935c..e9f580556 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -212,8 +212,8 @@ public: { // We arrived at a leaf. // Since the tree is used for LOD level selection instead of culling, we do not need to load the actual height data here. - float minZ = -std::numeric_limits::max(); - float maxZ = std::numeric_limits::max(); + constexpr float minZ = -std::numeric_limits::max(); + constexpr float maxZ = std::numeric_limits::max(); float cellWorldSize = mStorage->getCellWorldSize(); osg::BoundingBox boundingBox(osg::Vec3f((center.x()-halfSize)*cellWorldSize, (center.y()-halfSize)*cellWorldSize, minZ), osg::Vec3f((center.x()+halfSize)*cellWorldSize, (center.y()+halfSize)*cellWorldSize, maxZ)); From b10a817f7ec3e8e50a600679b8a1f435f39eefb6 Mon Sep 17 00:00:00 2001 From: psi29a Date: Tue, 4 May 2021 21:07:59 +0000 Subject: [PATCH 19/37] Merge branch 'useuless_launcher' into 'master' Remove some useless includes from the launcher See merge request OpenMW/openmw!775 (cherry picked from commit a84bd643b334eb6ac715681c497184ac22212ced) d3fff8cf Remove some useless includes from the launcher --- apps/launcher/advancedpage.cpp | 2 -- apps/launcher/advancedpage.hpp | 1 - apps/launcher/datafilespage.cpp | 2 -- apps/launcher/datafilespage.hpp | 1 - apps/launcher/graphicspage.hpp | 2 -- apps/launcher/main.cpp | 2 -- apps/launcher/maindialog.cpp | 3 --- apps/launcher/maindialog.hpp | 2 -- apps/launcher/playpage.hpp | 2 -- apps/launcher/sdlinit.cpp | 1 - apps/launcher/settingspage.cpp | 1 - apps/launcher/settingspage.hpp | 3 --- apps/launcher/utils/cellnameloader.hpp | 1 - apps/launcher/utils/lineedit.hpp | 1 - apps/launcher/utils/profilescombobox.cpp | 1 - 15 files changed, 25 deletions(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 91e3842fa..4ba732234 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -3,10 +3,8 @@ #include #include -#include #include #include -#include #include #include #include diff --git a/apps/launcher/advancedpage.hpp b/apps/launcher/advancedpage.hpp index a373fae43..93b818dbb 100644 --- a/apps/launcher/advancedpage.hpp +++ b/apps/launcher/advancedpage.hpp @@ -1,7 +1,6 @@ #ifndef ADVANCEDPAGE_H #define ADVANCEDPAGE_H -#include #include #include diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 81544b094..956483a3f 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -14,7 +13,6 @@ #include #include -#include #include #include diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index 3d200e6d2..5a7a6dc6e 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -6,7 +6,6 @@ #include -#include #include class QSortFilterProxyModel; diff --git a/apps/launcher/graphicspage.hpp b/apps/launcher/graphicspage.hpp index 35f711500..7801e6475 100644 --- a/apps/launcher/graphicspage.hpp +++ b/apps/launcher/graphicspage.hpp @@ -1,8 +1,6 @@ #ifndef GRAPHICSPAGE_H #define GRAPHICSPAGE_H -#include - #include "ui_graphicspage.h" #include diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index f15abafce..9c9acb4a1 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -1,10 +1,8 @@ #include -#include #include #include #include -#include #ifdef MAC_OS_X_VERSION_MIN_REQUIRED #undef MAC_OS_X_VERSION_MIN_REQUIRED diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 215258bcd..692415309 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -5,15 +5,12 @@ #include #include -#include #include #include #include #include #include -#include - #include "playpage.hpp" #include "graphicspage.hpp" #include "datafilespage.hpp" diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index de7423330..80e014e28 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -1,8 +1,6 @@ #ifndef MAINDIALOG_H #define MAINDIALOG_H -#include -#include #ifndef Q_MOC_RUN #include diff --git a/apps/launcher/playpage.hpp b/apps/launcher/playpage.hpp index b0bd3ee27..8f414dc6a 100644 --- a/apps/launcher/playpage.hpp +++ b/apps/launcher/playpage.hpp @@ -1,8 +1,6 @@ #ifndef PLAYPAGE_H #define PLAYPAGE_H -#include - #include "ui_playpage.h" class QComboBox; diff --git a/apps/launcher/sdlinit.cpp b/apps/launcher/sdlinit.cpp index 1fe1fd4c2..4717fb281 100644 --- a/apps/launcher/sdlinit.cpp +++ b/apps/launcher/sdlinit.cpp @@ -1,7 +1,6 @@ #include #include -#include bool initSDL() { diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 59d7cfd25..ca7fd028a 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include diff --git a/apps/launcher/settingspage.hpp b/apps/launcher/settingspage.hpp index 97b099dd6..df7c0e8eb 100644 --- a/apps/launcher/settingspage.hpp +++ b/apps/launcher/settingspage.hpp @@ -1,9 +1,6 @@ #ifndef SETTINGSPAGE_HPP #define SETTINGSPAGE_HPP -#include -#include - #include #include "ui_settingspage.h" diff --git a/apps/launcher/utils/cellnameloader.hpp b/apps/launcher/utils/cellnameloader.hpp index c58d09226..899ff75ad 100644 --- a/apps/launcher/utils/cellnameloader.hpp +++ b/apps/launcher/utils/cellnameloader.hpp @@ -1,7 +1,6 @@ #ifndef OPENMW_CELLNAMELOADER_H #define OPENMW_CELLNAMELOADER_H -#include #include #include diff --git a/apps/launcher/utils/lineedit.hpp b/apps/launcher/utils/lineedit.hpp index da28e858c..89de39588 100644 --- a/apps/launcher/utils/lineedit.hpp +++ b/apps/launcher/utils/lineedit.hpp @@ -11,7 +11,6 @@ #define LINEEDIT_H #include -#include #include #include diff --git a/apps/launcher/utils/profilescombobox.cpp b/apps/launcher/utils/profilescombobox.cpp index 462c2ebc2..af349ddff 100644 --- a/apps/launcher/utils/profilescombobox.cpp +++ b/apps/launcher/utils/profilescombobox.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include From ad7aff4cee6ead291bc4612231bc30035947f479 Mon Sep 17 00:00:00 2001 From: tess <2687892-TescoShoppah@users.noreply.gitlab.com> Date: Tue, 4 May 2021 22:22:13 +0000 Subject: [PATCH 20/37] Minor fix in launcher's advanced settings tab --- files/ui/advancedpage.ui | 222 +++++++++++++++++++-------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index b6ec20634..8c3dea4b3 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -6,7 +6,7 @@ 0 0 - 617 + 732 487 @@ -273,6 +273,30 @@ + + + + <html><head/><body><p>By default, the fog becomes thicker proportionally to your distance from the clipping plane set at the clipping distance, which causes distortion at the edges of the screen. +This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV.</p></body></html> + + + Radial fog + + + + + + + <html><head/><body><p>Normally environment map reflections aren't affected by lighting, which makes environment-mapped (and thus bump-mapped objects) glow in the dark. +Morrowind Code Patch includes an option to remedy that by doing environment-mapping before applying lighting, this is the equivalent of that option. +Affected objects will use shaders. +</p></body></html> + + + Bump/reflect map local lighting + + + @@ -283,6 +307,16 @@ + + + + <html><head/><body><p>Load per-group KF-files and skeleton files from Animations folder</p></body></html> + + + Use additional animation sources + + + @@ -297,7 +331,7 @@ legacy - + @@ -313,16 +347,6 @@ - - - - <html><head/><body><p>Makes NPCs and player movement more smooth. Recommended to use with "turn to movement direction" enabled.</p></body></html> - - - Smooth movement - - - @@ -333,26 +357,6 @@ - - - - <html><head/><body><p>See 'auto use object normal maps'. Affects terrain.</p></body></html> - - - Auto use terrain normal maps - - - - - - - <html><head/><body><p>If a file with pattern 'terrain specular map pattern' exists, use that file as a 'diffuse specular' map. The texture must contain the layer colour in the RGB channel (as usual), and a specular multiplier in the alpha channel.</p></body></html> - - - Auto use terrain specular maps - - - @@ -363,51 +367,6 @@ - - - - <html><head/><body><p>Use casting animations for magic items, just as for spells.</p></body></html> - - - Use magic item animation - - - - - - - <html><head/><body><p>Load per-group KF-files and skeleton files from Animations folder</p></body></html> - - - Use additional animation sources - - - - - - - <html><head/><body><p>If this option is enabled, normal maps are automatically recognized and used if they are named appropriately -(see 'normal map pattern', e.g. for a base texture foo.dds, the normal map texture would have to be named foo_n.dds). -If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file (.nif or .osg file). Affects objects.</p></body></html> - - - Auto use object normal maps - - - - - - - <html><head/><body><p>Normally environment map reflections aren't affected by lighting, which makes environment-mapped (and thus bump-mapped objects) glow in the dark. -Morrowind Code Patch includes an option to remedy that by doing environment-mapping before applying lighting, this is the equivalent of that option. -Affected objects will use shaders. -</p></body></html> - - - Bump/reflect map local lighting - - - @@ -432,6 +391,16 @@ Affected objects will use shaders. + + + + <html><head/><body><p>See 'auto use object normal maps'. Affects terrain.</p></body></html> + + + Auto use terrain normal maps + + + @@ -446,50 +415,81 @@ If this option is disabled, normal maps are only used if they are explicitly lis - - + + - <html><head/><body><p>By default, the fog becomes thicker proportionally to your distance from the clipping plane set at the clipping distance, which causes distortion at the edges of the screen. -This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV.</p></body></html> + <html><head/><body><p>If a file with pattern 'terrain specular map pattern' exists, use that file as a 'diffuse specular' map. The texture must contain the layer colour in the RGB channel (as usual), and a specular multiplier in the alpha channel.</p></body></html> - Radial fog + Auto use terrain specular maps - - - - - - 20 - - - - - false - + + - <html><head/><body><p>Render holstered weapons (with quivers and scabbards), requires modded assets.</p></body></html> + <html><head/><body><p>Makes NPCs and player movement more smooth. Recommended to use with "turn to movement direction" enabled.</p></body></html> - Weapon sheathing + Smooth movement - - - - false + + + + <html><head/><body><p>Use casting animations for magic items, just as for spells.</p></body></html> + + Use magic item animation + + + + + - <html><head/><body><p>Render holstered shield, requires modded assets.</p></body></html> + <html><head/><body><p>If this option is enabled, normal maps are automatically recognized and used if they are named appropriately +(see 'normal map pattern', e.g. for a base texture foo.dds, the normal map texture would have to be named foo_n.dds). +If this option is disabled, normal maps are only used if they are explicitly listed within the mesh file (.nif or .osg file). Affects objects.</p></body></html> - Shield sheathing + Auto use object normal maps + + + + 20 + + + + + false + + + <html><head/><body><p>Render holstered weapons (with quivers and scabbards), requires modded assets.</p></body></html> + + + Weapon sheathing + + + + + + + false + + + <html><head/><body><p>Render holstered shield, requires modded assets.</p></body></html> + + + Shield sheathing + + + + + @@ -516,12 +516,12 @@ This setting makes the fog use the actual eye point distance (or so called Eucli - - Audio Device - Select your preferred audio device. + + Audio Device + @@ -554,12 +554,12 @@ This setting makes the fog use the actual eye point distance (or so called Eucli - - HRTF - This setting controls HRTF, which simulates 3D sound on stereo systems. + + HRTF + @@ -602,12 +602,12 @@ This setting makes the fog use the actual eye point distance (or so called Eucli - - HRTF Profile - Select your preferred HRTF profile. + + HRTF Profile + From 903ce446348061926329f144fc01fa178f1cc249 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 5 May 2021 01:20:18 +0200 Subject: [PATCH 21/37] Revert "Various fixes for niftest" This reverts commit 87ada56edd9d5d5b0a9e6a8dcfd06eb09b161746. --- components/nif/niffile.cpp | 12 +++++------ components/nif/nifstream.cpp | 2 +- components/nif/nifstream.hpp | 41 ++++++++++++++++-------------------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 864a388e8..3e226b35e 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -212,7 +212,7 @@ void NIFFile::parse(Files::IStreamPtr stream) userVer = nif.getUInt(); // Number of records - const std::size_t recNum = nif.getUInt(); + unsigned int recNum = nif.getUInt(); records.resize(recNum); // Bethesda stream header @@ -251,7 +251,7 @@ void NIFFile::parse(Files::IStreamPtr stream) std::vector recSizes; // Currently unused nif.getUInts(recSizes, recNum); } - const std::size_t stringNum = nif.getUInt(); + unsigned int stringNum = nif.getUInt(); nif.getUInt(); // Max string length if (stringNum) nif.getSizedStrings(strings, stringNum); @@ -264,7 +264,7 @@ void NIFFile::parse(Files::IStreamPtr stream) } const bool hasRecordSeparators = ver >= NIFStream::generateVersion(10,0,0,0) && ver < NIFStream::generateVersion(10,2,0,0); - for (std::size_t i = 0; i < recNum; i++) + for (unsigned int i = 0; i < recNum; i++) { Record *r = nullptr; @@ -308,14 +308,14 @@ void NIFFile::parse(Files::IStreamPtr stream) r->read(&nif); } - const std::size_t rootNum = nif.getUInt(); + unsigned int rootNum = nif.getUInt(); roots.resize(rootNum); //Determine which records are roots - for (std::size_t i = 0; i < rootNum; i++) + for (unsigned int i = 0; i < rootNum; i++) { int idx = nif.getInt(); - if (idx >= 0 && static_cast(idx) < records.size()) + if (idx >= 0 && idx < int(records.size())) { roots[i] = records[idx]; } diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index 6129a1739..07c9c917c 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -7,7 +7,7 @@ namespace Nif osg::Quat NIFStream::getQuaternion() { float f[4]; - readLittleEndianBufferOfType<4, float>(inp, f); + readLittleEndianBufferOfType<4, float>(inp, (float*)&f); osg::Quat quat; quat.w() = f[0]; quat.x() = f[1]; diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index b6bf01ce5..4d221b867 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -7,8 +7,6 @@ #include #include #include -#include -#include #include #include @@ -24,32 +22,31 @@ namespace Nif class NIFFile; -template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) +/* + readLittleEndianBufferOfType: This template should only be used with arithmetic types +*/ +template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) { - static_assert(std::is_arithmetic_v, "Buffer element type is not arithmetic"); pIStream->read((char*)dest, numInstances * sizeof(T)); - if (pIStream->bad()) - throw std::runtime_error("Failed to read little endian typed (" + std::string(typeid(T).name()) + ") buffer of " - + std::to_string(numInstances) + " instances"); if constexpr (Misc::IS_BIG_ENDIAN) - for (std::size_t i = 0; i < numInstances; i++) + for (uint32_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); } -template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, std::size_t numInstances) +/* + readLittleEndianDynamicBufferOfType: This template should only be used with arithmetic types +*/ +template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, uint32_t numInstances) { - static_assert(std::is_arithmetic_v, "Buffer element type is not arithmetic"); pIStream->read((char*)dest, numInstances * sizeof(T)); - if (pIStream->bad()) - throw std::runtime_error("Failed to read little endian dynamic buffer of " + std::to_string(numInstances) + " instances"); if constexpr (Misc::IS_BIG_ENDIAN) - for (std::size_t i = 0; i < numInstances; i++) + for (uint32_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); } template type inline readLittleEndianType(Files::IStreamPtr &pIStream) { type val; - readLittleEndianBufferOfType<1, type>(pIStream, &val); + readLittleEndianBufferOfType<1, type>(pIStream, (type*)&val); return val; } @@ -99,21 +96,21 @@ public: osg::Vec2f getVector2() { osg::Vec2f vec; - readLittleEndianBufferOfType<2,float>(inp, vec._v); + readLittleEndianBufferOfType<2,float>(inp, (float*)&vec._v[0]); return vec; } osg::Vec3f getVector3() { osg::Vec3f vec; - readLittleEndianBufferOfType<3, float>(inp, vec._v); + readLittleEndianBufferOfType<3, float>(inp, (float*)&vec._v[0]); return vec; } osg::Vec4f getVector4() { osg::Vec4f vec; - readLittleEndianBufferOfType<4, float>(inp, vec._v); + readLittleEndianBufferOfType<4, float>(inp, (float*)&vec._v[0]); return vec; } @@ -145,11 +142,11 @@ public: ///Read in a string of the given length std::string getSizedString(size_t length) { - std::string str(length, '\0'); + std::vector str(length + 1, 0); + inp->read(str.data(), length); - if (inp->bad()) - throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars"); - return str; + + return str.data(); } ///Read in a string of the length specified in the file std::string getSizedString() @@ -170,8 +167,6 @@ public: { std::string result; std::getline(*inp, result); - if (inp->bad()) - throw std::runtime_error("Failed to read version string"); return result; } From f4cfade14b8830d516bf45eb20523aa17960faa1 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 3 May 2021 21:30:31 +0200 Subject: [PATCH 22/37] Use std::size_t to iterate --- components/nif/niffile.cpp | 10 +++++----- components/nif/nifstream.hpp | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 3e226b35e..221f1d1f3 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -212,7 +212,7 @@ void NIFFile::parse(Files::IStreamPtr stream) userVer = nif.getUInt(); // Number of records - unsigned int recNum = nif.getUInt(); + const std::size_t recNum = nif.getUInt(); records.resize(recNum); // Bethesda stream header @@ -251,7 +251,7 @@ void NIFFile::parse(Files::IStreamPtr stream) std::vector recSizes; // Currently unused nif.getUInts(recSizes, recNum); } - unsigned int stringNum = nif.getUInt(); + const std::size_t stringNum = nif.getUInt(); nif.getUInt(); // Max string length if (stringNum) nif.getSizedStrings(strings, stringNum); @@ -264,7 +264,7 @@ void NIFFile::parse(Files::IStreamPtr stream) } const bool hasRecordSeparators = ver >= NIFStream::generateVersion(10,0,0,0) && ver < NIFStream::generateVersion(10,2,0,0); - for (unsigned int i = 0; i < recNum; i++) + for (std::size_t i = 0; i < recNum; i++) { Record *r = nullptr; @@ -308,11 +308,11 @@ void NIFFile::parse(Files::IStreamPtr stream) r->read(&nif); } - unsigned int rootNum = nif.getUInt(); + const std::size_t rootNum = nif.getUInt(); roots.resize(rootNum); //Determine which records are roots - for (unsigned int i = 0; i < rootNum; i++) + for (std::size_t i = 0; i < rootNum; i++) { int idx = nif.getInt(); if (idx >= 0 && idx < int(records.size())) diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 4d221b867..cee98dd83 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -25,22 +25,22 @@ class NIFFile; /* readLittleEndianBufferOfType: This template should only be used with arithmetic types */ -template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) +template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) { pIStream->read((char*)dest, numInstances * sizeof(T)); if constexpr (Misc::IS_BIG_ENDIAN) - for (uint32_t i = 0; i < numInstances; i++) + for (std::size_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); } /* readLittleEndianDynamicBufferOfType: This template should only be used with arithmetic types */ -template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, uint32_t numInstances) +template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, std::size_t numInstances) { pIStream->read((char*)dest, numInstances * sizeof(T)); if constexpr (Misc::IS_BIG_ENDIAN) - for (uint32_t i = 0; i < numInstances; i++) + for (std::size_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); } template type inline readLittleEndianType(Files::IStreamPtr &pIStream) From 3e4abb9f049c66c08c23797190b5c2bc44f2862e Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 3 May 2021 21:32:38 +0200 Subject: [PATCH 23/37] Avoid copy from vector to string Read directly into a string. --- components/nif/nifstream.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index cee98dd83..1c4407afd 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -142,11 +142,9 @@ public: ///Read in a string of the given length std::string getSizedString(size_t length) { - std::vector str(length + 1, 0); - + std::string str(length, '\0'); inp->read(str.data(), length); - - return str.data(); + return str; } ///Read in a string of the length specified in the file std::string getSizedString() From 1c08bc0b15ffc713018dd7de5aaa90dcf8f7e92f Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 3 May 2021 21:41:47 +0200 Subject: [PATCH 24/37] Handle std::istream bad state after read --- components/nif/nifstream.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 1c4407afd..4d77b7326 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,9 @@ class NIFFile; template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) { pIStream->read((char*)dest, numInstances * sizeof(T)); + if (pIStream->bad()) + throw std::runtime_error("Failed to read little endian typed (" + std::string(typeid(T).name()) + ") buffer of " + + std::to_string(numInstances) + " instances"); if constexpr (Misc::IS_BIG_ENDIAN) for (std::size_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); @@ -39,6 +43,8 @@ template inline void readLittleEndianBuff template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, std::size_t numInstances) { pIStream->read((char*)dest, numInstances * sizeof(T)); + if (pIStream->bad()) + throw std::runtime_error("Failed to read little endian dynamic buffer of " + std::to_string(numInstances) + " instances"); if constexpr (Misc::IS_BIG_ENDIAN) for (std::size_t i = 0; i < numInstances; i++) Misc::swapEndiannessInplace(dest[i]); @@ -144,6 +150,8 @@ public: { std::string str(length, '\0'); inp->read(str.data(), length); + if (inp->bad()) + throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars"); return str; } ///Read in a string of the length specified in the file @@ -165,6 +173,8 @@ public: { std::string result; std::getline(*inp, result); + if (inp->bad()) + throw std::runtime_error("Failed to read version string"); return result; } From bf2f15342bfee7e1bec19ff9abdb1999a4575f74 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 01:09:29 +0200 Subject: [PATCH 25/37] Compare positive int as std::size_t If records.size() is greater than max int comparison is invalid. --- components/nif/niffile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 221f1d1f3..864a388e8 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -315,7 +315,7 @@ void NIFFile::parse(Files::IStreamPtr stream) for (std::size_t i = 0; i < rootNum; i++) { int idx = nif.getInt(); - if (idx >= 0 && idx < int(records.size())) + if (idx >= 0 && static_cast(idx) < records.size()) { roots[i] = records[idx]; } From d9e7c2fb42fb8e62323f609a1c4ac8f40b8a4a88 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 13:21:47 +0200 Subject: [PATCH 26/37] Replace comment by static assert --- components/nif/nifstream.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 4d77b7326..ad0ba5da8 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -23,11 +24,9 @@ namespace Nif class NIFFile; -/* - readLittleEndianBufferOfType: This template should only be used with arithmetic types -*/ template inline void readLittleEndianBufferOfType(Files::IStreamPtr &pIStream, T* dest) { + static_assert(std::is_arithmetic_v, "Buffer element type is not arithmetic"); pIStream->read((char*)dest, numInstances * sizeof(T)); if (pIStream->bad()) throw std::runtime_error("Failed to read little endian typed (" + std::string(typeid(T).name()) + ") buffer of " @@ -37,11 +36,9 @@ template inline void readLittleEndianBuff Misc::swapEndiannessInplace(dest[i]); } -/* - readLittleEndianDynamicBufferOfType: This template should only be used with arithmetic types -*/ template inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr &pIStream, T* dest, std::size_t numInstances) { + static_assert(std::is_arithmetic_v, "Buffer element type is not arithmetic"); pIStream->read((char*)dest, numInstances * sizeof(T)); if (pIStream->bad()) throw std::runtime_error("Failed to read little endian dynamic buffer of " + std::to_string(numInstances) + " instances"); From d5e28d7269e3ed33b43d56dbbc0b05eae6a00a79 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 4 May 2021 13:18:44 +0200 Subject: [PATCH 27/37] Remove redundant casts --- components/nif/nifstream.cpp | 2 +- components/nif/nifstream.hpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/components/nif/nifstream.cpp b/components/nif/nifstream.cpp index 07c9c917c..6129a1739 100644 --- a/components/nif/nifstream.cpp +++ b/components/nif/nifstream.cpp @@ -7,7 +7,7 @@ namespace Nif osg::Quat NIFStream::getQuaternion() { float f[4]; - readLittleEndianBufferOfType<4, float>(inp, (float*)&f); + readLittleEndianBufferOfType<4, float>(inp, f); osg::Quat quat; quat.w() = f[0]; quat.x() = f[1]; diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index ad0ba5da8..b6bf01ce5 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -49,7 +49,7 @@ template inline void readLittleEndianDynamicBufferOfType(Files::ISt template type inline readLittleEndianType(Files::IStreamPtr &pIStream) { type val; - readLittleEndianBufferOfType<1, type>(pIStream, (type*)&val); + readLittleEndianBufferOfType<1, type>(pIStream, &val); return val; } @@ -99,21 +99,21 @@ public: osg::Vec2f getVector2() { osg::Vec2f vec; - readLittleEndianBufferOfType<2,float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<2,float>(inp, vec._v); return vec; } osg::Vec3f getVector3() { osg::Vec3f vec; - readLittleEndianBufferOfType<3, float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<3, float>(inp, vec._v); return vec; } osg::Vec4f getVector4() { osg::Vec4f vec; - readLittleEndianBufferOfType<4, float>(inp, (float*)&vec._v[0]); + readLittleEndianBufferOfType<4, float>(inp, vec._v); return vec; } From 19f0b80983a46d08f0d84981b55d1f608b4fd606 Mon Sep 17 00:00:00 2001 From: Dobrohotov Alexei Date: Wed, 5 May 2021 02:26:32 +0300 Subject: [PATCH 28/37] Improve null root handling --- components/nif/niffile.cpp | 2 +- components/nifbullet/bulletnifloader.cpp | 10 ++++++---- components/nifosg/nifloader.cpp | 8 +++++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 864a388e8..08301ce47 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -322,7 +322,7 @@ void NIFFile::parse(Files::IStreamPtr stream) else { roots[i] = nullptr; - warn("Null Root found"); + warn("Root " + std::to_string(i + 1) + " does not point to a record: index " + std::to_string(idx)); } } diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 72c740af3..6ae175939 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -121,12 +121,14 @@ osg::ref_ptr BulletNifLoader::load(const Nif::File& nif) mAvoidStaticMesh.reset(); const size_t numRoots = nif.numRoots(); - std::vector roots; + std::vector roots; for (size_t i = 0; i < numRoots; ++i) { - Nif::Record* r = nif.getRoot(i); - assert(r != nullptr); - if (Nif::Node* node = dynamic_cast(r)) + const Nif::Record* r = nif.getRoot(i); + if (!r) + continue; + const Nif::Node* node = dynamic_cast(r); + if (node) roots.emplace_back(node); } const std::string filename = nif.getFilename(); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 49d52074a..f7d6fd3ed 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -254,8 +254,7 @@ namespace NifOsg for (size_t i = 0; i < numRoots; ++i) { const Nif::Record *r = nif->getRoot(i); - assert(r != nullptr); - if (r->recType == Nif::RC_NiSequenceStreamHelper) + if (r && r->recType == Nif::RC_NiSequenceStreamHelper) { seq = static_cast(r); break; @@ -312,7 +311,10 @@ namespace NifOsg for (size_t i = 0; i < numRoots; ++i) { const Nif::Record* r = nif->getRoot(i); - if (const Nif::Node* nifNode = dynamic_cast(r)) + if (!r) + continue; + const Nif::Node* nifNode = dynamic_cast(r); + if (nifNode) roots.emplace_back(nifNode); } if (roots.empty()) From d547d0dc60981bc3d55138a613e94ee8983a5390 Mon Sep 17 00:00:00 2001 From: psi29a Date: Wed, 5 May 2021 07:32:08 +0000 Subject: [PATCH 29/37] Add #5800 to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c50054a74..ba8081dae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -100,6 +100,7 @@ Bug #5739: Saving and loading the save a second or two before hitting the ground doesn't count fall damage Bug #5758: Paralyzed actors behavior is inconsistent with vanilla Bug #5762: Movement solver is insufficiently robust + BUG #5800: Equipping a CE enchanted ring deselects an already equipped and selected enchanted ring from the spell menu Bug #5807: Video decoding crash on ARM Bug #5821: NPCs from mods getting removed if mod order was changed Bug #5835: OpenMW doesn't accept negative values for NPC's hello, alarm, fight, and flee From 4f5d697e2b04bd5f0eba792879a33d60a383d7ae Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 5 May 2021 10:36:34 +0200 Subject: [PATCH 30/37] Do not fail when unable to detect the FFMPEG version, like windows. --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c3c17ddcf..104140107 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,16 +261,16 @@ if(FFmpeg_FOUND) set(FFVER_OK FALSE) endif() endif() + + if(NOT FFVER_OK AND NOT APPLE) # unable to detect on version on MacOS < 11.0 + message(FATAL_ERROR "FFmpeg version is too old, 3.2 is required" ) + endif() endif() if(NOT FFmpeg_FOUND) message(FATAL_ERROR "FFmpeg was not found" ) endif() -if(NOT FFVER_OK) - message(FATAL_ERROR "FFmpeg version is too old, 3.2 is required" ) -endif() - if(WIN32) message("Can not detect FFmpeg version, at least the 3.2 is required" ) endif() From a1bc10888c7f1d00227d07c87b10454409c842bb Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 5 May 2021 11:46:59 +0200 Subject: [PATCH 31/37] add implicit dependancy fontconfig for macos --- CI/before_install.osx.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CI/before_install.osx.sh b/CI/before_install.osx.sh index 51bcb9a59..15c5012b8 100755 --- a/CI/before_install.osx.sh +++ b/CI/before_install.osx.sh @@ -17,3 +17,6 @@ qmake --version curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-8f5ef6e.zip -o ~/openmw-deps.zip unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null + +# additional libraries +brew install fontconfig \ No newline at end of file From 4129cc244c8bafb2542b2b899f6c185e7c96c690 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 5 May 2021 13:35:39 +0200 Subject: [PATCH 32/37] allow macos11xcode12 to fail for now; but not macos10.15xcode11; add support for macos10.14_xcode10; make sure fontconfig does not update other stuff --- .gitlab-ci.yml | 10 +++++++++- CI/before_install.osx.sh | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c7a1a403f..ea3b40b90 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -147,6 +147,7 @@ Debian_Clang_tests: macOS11_Xcode12: extends: .MacOS image: macos-11-xcode-12 + allow_failure: true cache: key: macOS11_Xcode12.v1 variables: @@ -155,12 +156,19 @@ macOS11_Xcode12: macOS10.15_Xcode11: extends: .MacOS image: macos-10.15-xcode-11 - allow_failure: true cache: key: macOS10.15_Xcode11.v1 variables: CCACHE_SIZE: 3G +macOS10.14_Xcode10: + extends: .MacOS + image: macos-10.14-xcode-10 + cache: + key: macOS10.14_Xcode10.v1 + variables: + CCACHE_SIZE: 3G + variables: &engine-targets targets: "openmw,openmw-essimporter,openmw-iniimporter,openmw-launcher,openmw-wizard" package: "Engine" diff --git a/CI/before_install.osx.sh b/CI/before_install.osx.sh index 15c5012b8..ec19c7321 100755 --- a/CI/before_install.osx.sh +++ b/CI/before_install.osx.sh @@ -19,4 +19,4 @@ curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-8f5ef6 unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null # additional libraries -brew install fontconfig \ No newline at end of file +[ -z "${TRAVIS}" ] && HOMEBREW_NO_AUTO_UPDATE=1 brew install fontconfig \ No newline at end of file From 885ff36b01e777f83baaf02c945762390704a242 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Wed, 5 May 2021 11:45:59 +0000 Subject: [PATCH 33/37] Don't install recommended packages in Debian's CI --- CI/install_debian_deps.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CI/install_debian_deps.sh b/CI/install_debian_deps.sh index 490fad0da..2f905314b 100755 --- a/CI/install_debian_deps.sh +++ b/CI/install_debian_deps.sh @@ -22,12 +22,12 @@ declare -rA GROUPED_DEPS=( libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt5opengl5-dev libopenal-dev libunshield-dev libtinyxml-dev libbullet-dev liblz4-dev libpng-dev libjpeg-dev + ca-certificates " # TODO: add librecastnavigation-dev when debian is ready # These dependencies can alternatively be built and linked statically. [openmw-deps-dynamic]="libmygui-dev libopenscenegraph-dev" - [coverity]="curl" # Pre-requisites for building MyGUI and OSG for static linking. @@ -64,4 +64,4 @@ export APT_CACHE_DIR="${PWD}/apt-cache" set -x mkdir -pv "$APT_CACHE_DIR" apt-get update -yq -apt-get -q -o dir::cache::archives="$APT_CACHE_DIR" install -y "${deps[@]}" +apt-get -q -o dir::cache::archives="$APT_CACHE_DIR" install -y --no-install-recommends "${deps[@]}" From 3618eabaf0ec7abb8082a5e740d56c6ad045515d Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Wed, 5 May 2021 14:42:54 +0200 Subject: [PATCH 34/37] remove macos10.14 support from gitlab; brew is broken --- .gitlab-ci.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ea3b40b90..20b233c66 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -161,14 +161,6 @@ macOS10.15_Xcode11: variables: CCACHE_SIZE: 3G -macOS10.14_Xcode10: - extends: .MacOS - image: macos-10.14-xcode-10 - cache: - key: macOS10.14_Xcode10.v1 - variables: - CCACHE_SIZE: 3G - variables: &engine-targets targets: "openmw,openmw-essimporter,openmw-iniimporter,openmw-launcher,openmw-wizard" package: "Engine" From 00de540a31f4bf64c0302b9b2b77c1666dc28612 Mon Sep 17 00:00:00 2001 From: fredzio Date: Wed, 5 May 2021 20:27:22 +0200 Subject: [PATCH 35/37] Remove unused function. --- apps/openmw/mwworld/store.cpp | 11 ----------- apps/openmw/mwworld/store.hpp | 4 ---- 2 files changed, 15 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 9d6552106..94795b841 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -186,17 +186,6 @@ namespace MWWorld return ptr; } template - const T *Store::findRandom(const std::string &id) const - { - const T *ptr = searchRandom(id); - if(ptr == nullptr) - { - const std::string msg = T::getRecordType() + " starting with '" + id + "' not found"; - throw std::runtime_error(msg); - } - return ptr; - } - template RecordId Store::load(ESM::ESMReader &esm) { T record; diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 9cb1c7473..e37152431 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -179,10 +179,6 @@ namespace MWWorld const T *find(const std::string &id) const; - /** Returns a random record that starts with the named ID. An exception is thrown if none - * are found. */ - const T *findRandom(const std::string &id) const; - iterator begin() const; iterator end() const; From e378159ea862994d0f3381a1067631e4400f6bdb Mon Sep 17 00:00:00 2001 From: CedricMocquillon Date: Sat, 1 May 2021 23:21:21 +0200 Subject: [PATCH 36/37] Use O(log(n)) search instead of O(n) --- components/vfs/filesystemarchive.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/components/vfs/filesystemarchive.cpp b/components/vfs/filesystemarchive.cpp index 17f3891ec..6eef4b93a 100644 --- a/components/vfs/filesystemarchive.cpp +++ b/components/vfs/filesystemarchive.cpp @@ -55,12 +55,7 @@ namespace VFS bool FileSystemArchive::contains(const std::string& file, char (*normalize_function)(char)) const { - for (const auto& it : mIndex) - { - if(it.first == file) - return true; - } - return false; + return mIndex.find(file) != mIndex.end(); } std::string FileSystemArchive::getDescription() const From e99b61d362d6a9802c81a4427f7d10d6ef56f091 Mon Sep 17 00:00:00 2001 From: fredzio Date: Wed, 5 May 2021 20:28:46 +0200 Subject: [PATCH 37/37] Simplify the code --- apps/openmw/mwworld/store.cpp | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 94795b841..fb66b0a1d 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -8,28 +8,11 @@ #include #include +#include #include namespace { - template - class GetRecords - { - const std::string mFind; - std::vector *mRecords; - - public: - GetRecords(const std::string &str, std::vector *records) - : mFind(Misc::StringUtils::lowerCase(str)), mRecords(records) - { } - - void operator()(const T *item) - { - if(Misc::StringUtils::ciCompareLen(mFind, item->mId, mFind.size()) == 0) - mRecords->push_back(item); - } - }; - struct Compare { bool operator()(const ESM::Land *x, const ESM::Land *y) { @@ -169,7 +152,11 @@ namespace MWWorld const T *Store::searchRandom(const std::string &id) const { std::vector results; - std::for_each(mShared.begin(), mShared.end(), GetRecords(id, &results)); + std::copy_if(mShared.begin(), mShared.end(), std::back_inserter(results), + [&id](const T* item) + { + return Misc::StringUtils::ciCompareLen(id, item->mId, id.size()) == 0; + }); if(!results.empty()) return results[Misc::Rng::rollDice(results.size())]; return nullptr;