Multiview shaders.
Refactor Frustum management
Rewrite shared shadow map
cull mask should respect stereo
Stereo savegame screencap
LocalMap refactoring
use the vertex buffer hint instead of the display list patch to enable/disable display lists
Character preview fixes
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`.
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.
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.
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`.
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.
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`.