* Adds comments explaining the less-than-obvious aspects.
* Adds comments explaining what to do when adding new stuff.
* Some fixes caused by those comments not historically existing.
* Add a TODO comment to something which may catch fire in the future.
Perform all request to db in a single thread to avoid blocking navmesh
generator threads due to slow write operations.
Write to db navmesh for all changes except update as it done for memory cache.
Batch multiple db operations into a single transaction to speed up writing by
not executing fsync after each insert/update query. All reads are performed in
the same transaction so they see uncommited data.
Get rid of EscapeHashX classes option 5 (attempt 2): Use boost::filesystem::path rules if the path starts with ", and consume the whole thing verbatim otherwise
Closes#5804
See merge request OpenMW/openmw!1436
Merge conflicts included:
* One setting being removed (branch had changed its type).
* One setting's description being changed (branch had changed its type).
* List of files in components/files was changed both upstream and on the
branch.
* Upstream had changed something in a file the branch deletes.
Specifications developed in PR #3206 require that groundcover content files must not be allowed to corrupt normal content files. With this PR we simply isolate our existing loading logic by instantiating a separate `ESMStore` for `Groundcover`. In addition, we remove some outdated workarounds.
In file included from /<<BUILDDIR>>/openmw-0.47.0+git202111080927~ubuntu18.04.1/components/detournavigator/findsmoothpath.cpp:1:0:
/<<BUILDDIR>>/openmw-0.47.0+git202111080927~ubuntu18.04.1/components/detournavigator/findsmoothpath.hpp:93:48: error: field ‘mSettings’ has incomplete type ‘std::reference_wrapper<const DetourNavigator::Settings>’
std::reference_wrapper<const Settings> mSettings;
^~~~~~~~~
In file included from /usr/include/c++/7/bits/move.h:54:0,
from /usr/include/c++/7/bits/nested_exception.h:40,
from /usr/include/c++/7/exception:143,
from /usr/include/c++/7/ios:39,
from /usr/include/c++/7/istream:38,
from /usr/include/c++/7/sstream:38,
from /<<BUILDDIR>>/openmw-0.47.0+git202111080927~ubuntu18.04.1/components/detournavigator/dtstatus.hpp:6,
from /<<BUILDDIR>>/openmw-0.47.0+git202111080927~ubuntu18.04.1/components/detournavigator/findsmoothpath.hpp:4,
from /<<BUILDDIR>>/openmw-0.47.0+git202111080927~ubuntu18.04.1/components/detournavigator/findsmoothpath.cpp:1:
/usr/include/c++/7/type_traits:2125:11: note: declaration of ‘class std::reference_wrapper<const DetourNavigator::Settings>’
class reference_wrapper;
This PR aims to solve all issues with `Groundcover` view distance handling in a satisfying way while preserving other optimisations that benefit other features. The main idea here is not to rely on `ViewData` updates for distance culling calculations because we can not accurately determine distance against lazily updated views. Instead, we perform an accurate measurement in a cull callback we can run every frame in `Groundcover` itself. While we do have to add some code to handle this feature, it is quite loosely coupled code that could be useful elsewhere in the future. These changes should address a performance regression @akortunov experienced.
To minimize overhead for calls when level is less than current. For example
Log(Debug::Debug) should not lock mutex when current logging level is Verbose.
This PR aims to solve `uniform block LightBufferBinding has no binding` messages @glassmancody has reportedly encountered since PR #3110 due to an apparent bug in OSG. While we do have to add a workaround here that adds a bit of clunkiness, #3216 should allow us to clean up these interactions a bit in the future.
OscillatingRecastMeshObject::update should be called with tile bounds in real
coordinates not in navmesh. But proper scaling was done only in
RecastMeshManager::getMesh and RecastMeshManager::updateObject used tile bounds
in navmesh coordinates.
Add a new function to create tile bounds with proper scaling and pass correct
value into RecastMeshManager constructor through CachedRecastMeshManager
constuctor from TileCachedRecastMeshManager member functions.
With this PR we refactor `StringUtils::replaceAll` to accept `string_view` as suggested in a code comment. In addition, while we are touching this rebuild happy file, we slim it down a bit by moving a few sparingly used functions elsewhere.
This PR removes dummy serialisers for `StateSetUpdater`, `NodeCallback` and the respective `META` macros that trigger serialisation requirement here.
`StateSetUpdater` and `NodeCallback` are just base classes that can not be used on their own, so there is no need to incorporate them into serialisation. These changes might have minor effects on derived classes that forget to override `className()`, `libraryName()` through `META`, but it makes hardly a difference to now serialise such classes as a dysfunctional `osg::Callback` instead of a dysfunctional `SceneUtil::NodeCallback`.
This PR removes unneeded `lowerCaseInPlace` calls in in a hot path of `objectpaging.cpp` that are no longer necessary after PR #3197. In addition, I have been informed that these changes should by coincidence address a compiler specific compilation error we currently experience.
We currently apply a strange algorithm to `LightManager::mStateSetCache`. For some reason this algorithm inserts hashed keys into `std::map` in a way that fails to handle hash collisions and exhibits worse lookup complexity than `std::unordered_map`. With this PR we just use `std::unordered_map` here.
This PR aims to start addressing `ESM` design issues that have silenced errors we incorporated into groundcover `ESM` loading approaches.
- We move the resolution of `parentFileIndices` from `ESMStore` to `ESMReader` as suggested in a `TODO` comment.
- We improve a highly misleading comment which downplayed the significance of `parentFileIndices`.
- We document important preconditions.
- We move a user facing error message to the highest level and improve its context.
- We remove an inappropriate `setGlobalReaderList` method. We now pass this reader list into the method that requires it.
- We remove a thoroughly pointless optimisation of `Store<ESM::LandTexture>`'s construction that has unnecessarily depended on `getGlobalReaderList`.
There should be no functional changes for `master`, but this PR should remove an issue blocking PR #3208.
With this PR we apply `lightMask` to a `Transform` node we create specifically for a light. This mask will allow us to stop traversing such nodes sooner and avoid costly processing associated with `Transform` nodes in the cull visitor.
I have been informed by @akortunov that my addition of `Groundcover::getViewDistance` is not working in some cases. Investigations revealed that some `ViewData` code interacting with my additions had been quite thoroughly optimised in a way that was not sufficiently documented and interfered with the new feature. With this PR we repair `getViewDistance` while preserving such optimisations and add a necessary comment to avoid issues in the future. In addition, we now rebuild views when the global `mViewDistance` changes.
With this PR we refactor `SceneUtil::KeyframeController` not to require `virtual osg::Callback` inheritance. I suppose such `virtual` overhead is not justified here because it negatively impacts many other classes we derive from `osg::Callback`.
With this PR we refactor a `premultiplied alpha` user string set by `characterpreview.cpp` into a more flexible mechanism allowing us to assign any state to GUI textures. We can consider these changes more future proof than the previous approach.
This PR aims to spark the retirement of a questionable pattern I have found all over our code base. I will illustrate how this pattern encourages code duplication, lacks type safety, requires documentation and can be prone to bugs.
```
std::map<std::string, Object> mMap; // Stored in all lowercase for a case-insensitive lookup
std::string lowerKey = Misc::StringUtils::lowerCase(key);
mMap.emplace(lowerKey, object);
std::string lowerKey = Misc::StringUtils::lowerCase(key);
mMap.find(lowerKey);
mMap.find(key); // Not found. Oops!
```
An alternative approach produces no such issues.
```
std::unordered_map<std::string, Object, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> mMap;
mMap.emplace(key, object);
mMap.find(key);
```
Of course, such an alternative will work for a `map` as well, but an `unordered_map` is generally preferable over a `map` with these changes because we have moved `lowerCase` into the comparison operator.
In this PR I have refactored `Animation::mNodeMap` accordingly. I have reviewed and adapted all direct and indirect usage of `Animation::mNodeMap` to ensure we do not change behaviour with this PR.
To construct serializer from given entities:
* Data source/destination - any value that has to be serialized/deserialized,
usually already existing type.
* Format - functional object to define high level serialization logic to
define specific format and data schema. Like order of fields, allocation.
* Visitor - functional object to define low level serialization logic to
operator on given data part.
* BinaryWriter - copies given value into provided buffer.
* BinaryReader - copies value into given destination from provided buffer.
* SizeAccumulator - calculates required buffer size for given data.
This PR fixes a recent regression concerning enable and disable commands with object paging. In addition, we add a necessary comment to avoid such issues in the future.
This PR fixes a crash caused by the improperly ensured lifetime of RigGeometry::mSourceGeometry. mSourceGeometry was not adequate to ensure mSourceGeometry would outlive mGeometry because we extend mGeometrys lifetime beyond this lifetime by passing mGeometry to the draw traversal instead of this.
In addition,
We add important comments.
We detect and prevent generally unsafe operations in high level code.
We add a sprinkling of const to help clarify intentions.
Currently, we use an `UnrefQueue` which supposedly aims to transfer destruction costs to another thread. The implications of this unusual pattern can not be well understood because some allocators might free resources more efficiently if they are freed by the same thread that allocated them. In addition, `UnrefQueue` complicates the validation of thread safety in our engine. Lastly, our current usage of `UnrefQueue` triggers `ref()`, `unref()` atomic operations as objects are passed into the queue. These operations could be more expensive than the actual destruction.
With this PR we thus remove `UnrefQueue`. We can expect these changes to have a minor impact at most because we free most resources elsewhere in `ResourceSystem::updateCache`.
This variable is only used in ShadowsBin constructor and it's initialized each
time before constructor call so required value can be just passed into
ShadowsBin ctor.
Make ShadowsBin default constructor private because it is required by osg even
it's not actually called.
A component to load ESM content files with limited support for record types and
selection which of them to load. Supported record types are:
ACTI, CELL, CONT, DOOR, GMST, LAND, STAT.
Currently, we disable a paging root node that we only need in exterior cells by setting its node mask to 0 when transitioning into an interior cell. Node masks are not ideal for this usage case because Node::getBound is unaware of masks. With this PR we just detach the unused node from the scene graph. _shadowedScene->getBound() in the MWShadowTechnique should return a much better value in interior cells with these changes.
We currently build a large map of a BSAFile's contents unused by Open MW. We already map archive contents in VFS. With this PR we remove the map from BSAFile and reimplement its only current use in BSATool.
We currently use a version guard to adapt to a change in the number of parameters supplied to osg::TriangleFunctor's operator() template functor. The differing parameter is unused in our code. Crucially, operator() is not an override, so we can just add a default value for the differing parameter. Such a default allows us to apply identical code to both versions of the library without regressing functionality.
This PR proposes a simple change to `RigGeometry` `dirtyGLObjects` logic.
1. We will avoid dirtying unmodified arrays.
2. We can drop an osg version guard since `Drawable::dirtyGLObjects` is not nearly as harmful as `Geometry::dirtyGLObjects`.
3. We will avoid crashes in an as yet unfinished future PR concerning `Array` sharing improvements.
To reduce amount of computations on the caller side and restrict possible
values.
* verts can't be non-int because it's a number of things.
* worldsize is initially defined as int by ESM::Land::REAL_SIZE.
* Put function to calculate heightfied shift into components to be able to
reuse by other binaries.
osg::NodeVisitor is designed to recursively call virtual apply signatures until we find an implemented signature. Encountered nodes that we do not explicitely handle will trigger additional virtual function calls. With this PR we avoid these additional virtual function calls in the particularly costly ComputeLightSpaceBounds by adding some explicit signatures.
Currently, we always traverse the scene graph an additional time with a ComputeLightSpaceBounds visitor during shadow casting. ComputeLightSpaceBounds is only useful when the shadow casting mask allows us to shrink the bounds of the rendered scene, so we guard its traversal with a check against getCastsShadowTraversalMask. In practice, this guard never works because we build the traversal mask inclusively.
With this PR we limit the getCastsShadowTraversalMask check to relevant masks. This new check allows us to skip a superfluous ComputeLightSpaceBounds traversal with most settings.
Currently, Open MW's basic file access speed is limited by a peculiar layer of virtualisation in BSAFile's interface. This PR removes such virtualisation by properly separating BSAFile from CompressedBSAFile in low level contexts.
Tests which no longer work are commented out.
Some of these don't work because they're effectively testing for the
presence of bugs in the old implementation.
Others don't work because we're no longer accidentally disabling the
boost::program_options feature where it generates an error if only part
of a token gets consumed.
These will be fixed by later commits.
We skip this during node path iterations. this is not a node we are interested in.
We avoid allocating a new mGeomToSkelMatrix per frame and avoid a ref_ptr associated with its update.
We speed up a search for the Skeleton node by adding a continue; condition prior to an expensive dynamic_cast.
We can expect marginally improved loading times with this PR. Drawable, Transform and Node counts in stats panels are expected to remain unchanged - this PR does not add new scene graph optimisations, it just increases the speed with which we apply existing ones.
1. We add explicit `NodeVisitor::apply` overrides for commonly encountered node types to avoid additional virtual function calls per node associated with the default `apply` implementation.
2. We skip pushing `StateSet`s when `_mergeAlphaBlending` is enabled or the `StateSet` contains no relevant state.
3. We add a specialised variant of `CollectLowestTransformsVisitor::addTransform` accepting `MatrixTransform` to avoid matrix copies and multiplications.
With this PR we optimise a function that is called quite often when loading new cells.
We remove avoidable dynamic_casts.
We remove an unused pair.second element.
We convert a map to an unordered_map because its ordering is irrelevant in this case.
We avoid adding the root Skeleton node to the bones' node path.
Currently, we create a new ComputeLightSpaceBounds visitor per frame. Within this visitor, we require excessive memory allocations, mainly a new osg::RefMatrix per encountered Transform node.
With this PR we reuse a single ComputeLightSpaceBounds visitor across frames and enable the createOrReuseMatrix functionality to avoid allocating new matrices every frame. osgUtil::CullVisitor internally uses the same approach.
Currently, we run culling tests against all lights in the scene during LightListCallback::pushLightState. We can avoid most of these tests by removing off-screen lights at an earlier stage. We should benchmark the cumulative time spent within LightListCallback::pushLightState before and after this PR.
With this PR we test out osg's shader define system for a somewhat harmless feature. As we can see, our code becomes more concise and efficient in this case. Most importantly, we no longer create unneeded vertex shader objects.
Firstly, this PR reintroduces commit "Recreate a special case for IntersectionVisitor on QuadTreeWorld" we forgot to reapply while reverting a revert commit. Secondly, in cases we still need to build a view for an intersection visitor, we now use the available `osgUtil::IntersectionVisitor::getReferenceEyePoint` instead of falling back to the origin position that was previously causing long rebuild times.
`handle_stateset` is not needed because `UpdateMatrixTransform` is a `NodeCallback` only allowed to be set on a `Node`. `Geode` and `Drawable` do not need explicit logic because they are both derived from `Node`.
* avoids creating empty statesets on drawables
Currently, we attempt to skip creating state on drawable nodes when this state matches the default state. This attempt is incomplete because we still create an avoidable empty stateset in the default case.
* renderingmanager.cpp
* nifloader.cpp
* nifloader.cpp
* shadervisitor.cpp