1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-31 10:36:44 +00:00

Merge remote-tracking branch 'remotes/origin/master' into openmw-vr

This commit is contained in:
madsbuvi 2021-02-07 19:17:43 +01:00
commit 66d2912fcd
22 changed files with 225 additions and 236 deletions

View file

@ -215,6 +215,7 @@ Programmers
Yohaulticetl
Yuri Krupenin
zelurker
Noah Gooder
Documentation
-------------

View file

@ -98,6 +98,8 @@
Bug #5758: Paralyzed actors behavior is inconsistent with vanilla
Bug #5762: Movement solver is insufficiently robust
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
Bug #5836: OpenMW dialogue/greeting/voice filter doesn't accept negative Ai values for NPC's hello, alarm, fight, and flee
Feature #390: 3rd person look "over the shoulder"
Feature #1536: Show more information about level on menu
Feature #2386: Distant Statics in the form of Object Paging
@ -130,6 +132,7 @@
Feature #5813: Instanced groundcover support
Task #5480: Drop Qt4 support
Task #5520: Improve cell name autocompleter implementation
Task #5844: Update 'toggle sneak' documentation
0.46.0
------

View file

@ -316,7 +316,7 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
case SelectWrapper::Function_AiSetting:
return mActor.getClass().getCreatureStats (mActor).getAiSetting (
(MWMechanics::CreatureStats::AiSetting)select.getArgument()).getModified();
(MWMechanics::CreatureStats::AiSetting)select.getArgument()).getModified(false);
case SelectWrapper::Function_PcAttribute:

View file

@ -951,29 +951,29 @@ namespace MWMechanics
if (actor.getClass().hasInventoryStore(actor))
actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Poison);
}
else if (effects.get(ESM::MagicEffect::CureParalyzation).getModifier() > 0)
if (effects.get(ESM::MagicEffect::CureParalyzation).getModifier() > 0)
{
creatureStats.getActiveSpells().purgeEffect(ESM::MagicEffect::Paralyze);
creatureStats.getSpells().purgeEffect(ESM::MagicEffect::Paralyze);
if (actor.getClass().hasInventoryStore(actor))
actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Paralyze);
}
else if (effects.get(ESM::MagicEffect::CureCommonDisease).getModifier() > 0)
if (effects.get(ESM::MagicEffect::CureCommonDisease).getModifier() > 0)
{
creatureStats.getSpells().purgeCommonDisease();
}
else if (effects.get(ESM::MagicEffect::CureBlightDisease).getModifier() > 0)
if (effects.get(ESM::MagicEffect::CureBlightDisease).getModifier() > 0)
{
creatureStats.getSpells().purgeBlightDisease();
}
else if (effects.get(ESM::MagicEffect::CureCorprusDisease).getModifier() > 0)
if (effects.get(ESM::MagicEffect::CureCorprusDisease).getModifier() > 0)
{
creatureStats.getActiveSpells().purgeCorprusDisease();
creatureStats.getSpells().purgeCorprusDisease();
if (actor.getClass().hasInventoryStore(actor))
actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Corprus, true);
}
else if (effects.get(ESM::MagicEffect::RemoveCurse).getModifier() > 0)
if (effects.get(ESM::MagicEffect::RemoveCurse).getModifier() > 0)
{
creatureStats.getSpells().purgeCurses();
}

View file

@ -18,8 +18,10 @@ namespace MWMechanics
}
template<typename T>
T Stat<T>::getModified() const
T Stat<T>::getModified(bool capped) const
{
if(!capped)
return mModified;
return std::max(static_cast<T>(0), mModified);
}

View file

@ -28,7 +28,7 @@ namespace MWMechanics
const T& getBase() const;
T getModified() const;
T getModified(bool capped = true) const;
T getCurrentModified() const;
T getModifier() const;
T getCurrentModifier() const;

View file

@ -184,6 +184,9 @@ namespace MWRender
osg::ref_ptr<osg::Texture2D> dummyTexture = new osg::Texture2D();
dummyTexture->setInternalFormat(GL_RED);
dummyTexture->setTextureSize(1, 1);
// This might clash with a shadow map, so make sure it doesn't cast shadows
dummyTexture->setShadowComparison(true);
dummyTexture->setShadowCompareFunc(osg::Texture::ShadowCompareFunc::ALWAYS);
stateset->setTextureAttributeAndModes(7, dummyTexture, osg::StateAttribute::ON);
stateset->setTextureAttribute(7, noBlendAlphaEnv, osg::StateAttribute::ON);
stateset->addUniform(new osg::Uniform("noAlpha", true));

View file

@ -241,7 +241,7 @@ namespace MWScript
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push(ptr.getClass().getCreatureStats (ptr).getAiSetting (mIndex).getModified());
runtime.push(ptr.getClass().getCreatureStats (ptr).getAiSetting (mIndex).getModified(false));
}
};
template<class R>
@ -276,9 +276,7 @@ namespace MWScript
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWMechanics::Stat<int> stat = ptr.getClass().getCreatureStats(ptr).getAiSetting(mIndex);
stat.setModified(value, 0);
ptr.getClass().getCreatureStats(ptr).setAiSetting(mIndex, stat);
ptr.getClass().getCreatureStats(ptr).setAiSetting(mIndex, value);
ptr.getClass().setBaseAISetting(ptr.getCellRef().getRefId(), mIndex, value);
}
};

View file

@ -68,7 +68,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshKeySize;
const std::size_t maxSize = navMeshDataSize + 2 * navMeshKeySize;
const std::size_t maxSize = navMeshDataSize + navMeshKeySize;
NavMeshTilesCache cache(maxSize);
const auto result = cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, mOffMeshConnections,
@ -81,7 +81,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshKeySize;
const std::size_t maxSize = 2 * (navMeshDataSize + 2 * navMeshKeySize);
const std::size_t maxSize = 2 * (navMeshDataSize + navMeshKeySize);
NavMeshTilesCache cache(maxSize);
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
NavMeshData anotherNavMeshData {anotherData, 1};
@ -97,7 +97,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshKeySize;
const std::size_t maxSize = navMeshDataSize + 2 * navMeshKeySize;
const std::size_t maxSize = navMeshDataSize + navMeshKeySize;
NavMeshTilesCache cache(maxSize);
cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, mOffMeshConnections, std::move(mNavMeshData));
@ -142,7 +142,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshWithWaterKeySize;
const std::size_t maxSize = navMeshDataSize + 2 * navMeshKeySize;
const std::size_t maxSize = navMeshDataSize + navMeshKeySize;
NavMeshTilesCache cache(maxSize);
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
@ -163,7 +163,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshKeySize;
const std::size_t maxSize = navMeshDataSize + 2 * navMeshKeySize;
const std::size_t maxSize = navMeshDataSize + navMeshKeySize;
NavMeshTilesCache cache(maxSize);
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
@ -182,7 +182,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshWithWaterKeySize;
const std::size_t maxSize = 2 * (navMeshDataSize + 2 * navMeshKeySize);
const std::size_t maxSize = 2 * (navMeshDataSize + navMeshKeySize);
NavMeshTilesCache cache(maxSize);
const std::vector<RecastMesh::Water> leastRecentlySetWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
@ -214,7 +214,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshWithWaterKeySize;
const std::size_t maxSize = 2 * (navMeshDataSize + 2 * navMeshKeySize);
const std::size_t maxSize = 2 * (navMeshDataSize + navMeshKeySize);
NavMeshTilesCache cache(maxSize);
const std::vector<RecastMesh::Water> leastRecentlyUsedWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
@ -258,7 +258,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshKeySize;
const std::size_t maxSize = 2 * (navMeshDataSize + 2 * navMeshKeySize);
const std::size_t maxSize = 2 * (navMeshDataSize + navMeshKeySize);
NavMeshTilesCache cache(maxSize);
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
@ -277,7 +277,7 @@ namespace
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize1 = cRecastMeshKeySize;
const std::size_t navMeshKeySize2 = cRecastMeshWithWaterKeySize;
const std::size_t maxSize = 2 * navMeshDataSize + 2 * navMeshKeySize1 + 2 * navMeshKeySize2;
const std::size_t maxSize = 2 * navMeshDataSize + navMeshKeySize1 + navMeshKeySize2;
NavMeshTilesCache cache(maxSize);
const std::vector<RecastMesh::Water> anotherWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
@ -306,7 +306,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshKeySize;
const std::size_t maxSize = navMeshDataSize + 2 * navMeshKeySize;
const std::size_t maxSize = navMeshDataSize + navMeshKeySize;
NavMeshTilesCache cache(maxSize);
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
@ -330,7 +330,7 @@ namespace
{
const std::size_t navMeshDataSize = 1;
const std::size_t navMeshKeySize = cRecastMeshKeySize;
const std::size_t maxSize = navMeshDataSize + 2 * navMeshKeySize;
const std::size_t maxSize = navMeshDataSize + navMeshKeySize;
NavMeshTilesCache cache(maxSize);
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};

View file

@ -68,4 +68,19 @@ inline std::ostream& operator <<(std::ostream& stream, BroadphaseNativeTypes val
}
}
inline bool operator <(const btVector3& lhs, const btVector3& rhs)
{
return std::tie(lhs.x(), lhs.y(), lhs.z()) < std::tie(rhs.x(), rhs.y(), rhs.z());
}
inline bool operator <(const btMatrix3x3& lhs, const btMatrix3x3& rhs)
{
return std::tie(lhs[0], lhs[1], lhs[2]) < std::tie(rhs[0], rhs[1], rhs[2]);
}
inline bool operator <(const btTransform& lhs, const btTransform& rhs)
{
return std::tie(lhs.getBasis(), lhs.getOrigin()) < std::tie(rhs.getBasis(), rhs.getOrigin());
}
#endif

View file

@ -9,57 +9,29 @@ namespace DetourNavigator
{
namespace
{
inline std::vector<unsigned char> makeNavMeshKey(const RecastMesh& recastMesh,
const std::vector<OffMeshConnection>& offMeshConnections)
inline std::size_t getSize(const RecastMesh& recastMesh,
const std::vector<OffMeshConnection>& offMeshConnections)
{
const std::size_t indicesSize = recastMesh.getIndices().size() * sizeof(int);
const std::size_t verticesSize = recastMesh.getVertices().size() * sizeof(float);
const std::size_t areaTypesSize = recastMesh.getAreaTypes().size() * sizeof(AreaType);
const std::size_t waterSize = recastMesh.getWater().size() * sizeof(RecastMesh::Water);
const std::size_t offMeshConnectionsSize = offMeshConnections.size() * sizeof(OffMeshConnection);
std::vector<unsigned char> result(indicesSize + verticesSize + areaTypesSize + waterSize + offMeshConnectionsSize);
unsigned char* dst = result.data();
if (indicesSize > 0)
{
std::memcpy(dst, recastMesh.getIndices().data(), indicesSize);
dst += indicesSize;
}
if (verticesSize > 0)
{
std::memcpy(dst, recastMesh.getVertices().data(), verticesSize);
dst += verticesSize;
}
if (areaTypesSize > 0)
{
std::memcpy(dst, recastMesh.getAreaTypes().data(), areaTypesSize);
dst += areaTypesSize;
}
if (waterSize > 0)
{
std::memcpy(dst, recastMesh.getWater().data(), waterSize);
dst += waterSize;
}
if (offMeshConnectionsSize > 0)
std::memcpy(dst, offMeshConnections.data(), offMeshConnectionsSize);
return result;
return indicesSize + verticesSize + areaTypesSize + waterSize + offMeshConnectionsSize;
}
}
NavMeshTilesCache::NavMeshTilesCache(const std::size_t maxNavMeshDataSize)
: mMaxNavMeshDataSize(maxNavMeshDataSize), mUsedNavMeshDataSize(0), mFreeNavMeshDataSize(0) {}
: mMaxNavMeshDataSize(maxNavMeshDataSize), mUsedNavMeshDataSize(0), mFreeNavMeshDataSize(0),
mHitCount(0), mGetCount(0) {}
NavMeshTilesCache::Value NavMeshTilesCache::get(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile,
const RecastMesh& recastMesh, const std::vector<OffMeshConnection>& offMeshConnections)
{
const std::lock_guard<std::mutex> lock(mMutex);
++mGetCount;
const auto agentValues = mValues.find(agentHalfExtents);
if (agentValues == mValues.end())
return Value();
@ -68,12 +40,14 @@ namespace DetourNavigator
if (tileValues == agentValues->second.end())
return Value();
const auto tile = tileValues->second.mMap.find(RecastMeshKeyView(recastMesh, offMeshConnections));
const auto tile = tileValues->second.mMap.find(NavMeshKeyView(recastMesh, offMeshConnections));
if (tile == tileValues->second.mMap.end())
return Value();
acquireItemUnsafe(tile->second);
++mHitCount;
return Value(*this, tile->second);
}
@ -81,26 +55,22 @@ namespace DetourNavigator
const RecastMesh& recastMesh, const std::vector<OffMeshConnection>& offMeshConnections,
NavMeshData&& value)
{
const auto navMeshSize = static_cast<std::size_t>(value.mSize);
const auto itemSize = static_cast<std::size_t>(value.mSize) + getSize(recastMesh, offMeshConnections);
const std::lock_guard<std::mutex> lock(mMutex);
if (navMeshSize > mMaxNavMeshDataSize)
return Value();
if (navMeshSize > mFreeNavMeshDataSize + (mMaxNavMeshDataSize - mUsedNavMeshDataSize))
return Value();
auto navMeshKey = makeNavMeshKey(recastMesh, offMeshConnections);
const auto itemSize = navMeshSize + 2 * navMeshKey.size();
if (itemSize > mFreeNavMeshDataSize + (mMaxNavMeshDataSize - mUsedNavMeshDataSize))
return Value();
while (!mFreeItems.empty() && mUsedNavMeshDataSize + itemSize > mMaxNavMeshDataSize)
removeLeastRecentlyUsed();
const auto iterator = mFreeItems.emplace(mFreeItems.end(), agentHalfExtents, changedTile, std::move(navMeshKey));
NavMeshKey navMeshKey {
RecastMeshData {recastMesh.getIndices(), recastMesh.getVertices(), recastMesh.getAreaTypes(), recastMesh.getWater()},
offMeshConnections
};
const auto iterator = mFreeItems.emplace(mFreeItems.end(), agentHalfExtents, changedTile, std::move(navMeshKey), itemSize);
const auto emplaced = mValues[agentHalfExtents][changedTile].mMap.emplace(iterator->mNavMeshKey, iterator);
if (!emplaced.second)
@ -123,17 +93,22 @@ namespace DetourNavigator
std::size_t navMeshCacheSize = 0;
std::size_t usedNavMeshTiles = 0;
std::size_t cachedNavMeshTiles = 0;
std::size_t hitCount = 0;
std::size_t getCount = 0;
{
const std::lock_guard<std::mutex> lock(mMutex);
navMeshCacheSize = mUsedNavMeshDataSize;
usedNavMeshTiles = mBusyItems.size();
cachedNavMeshTiles = mFreeItems.size();
hitCount = mHitCount;
getCount = mGetCount;
}
stats.setAttribute(frameNumber, "NavMesh CacheSize", navMeshCacheSize);
stats.setAttribute(frameNumber, "NavMesh UsedTiles", usedNavMeshTiles);
stats.setAttribute(frameNumber, "NavMesh CachedTiles", cachedNavMeshTiles);
stats.setAttribute(frameNumber, "NavMesh CacheHitRate", static_cast<double>(hitCount) / getCount * 100.0);
}
void NavMeshTilesCache::removeLeastRecentlyUsed()
@ -152,8 +127,8 @@ namespace DetourNavigator
if (value == tileValues->second.mMap.end())
return;
mUsedNavMeshDataSize -= getSize(item);
mFreeNavMeshDataSize -= getSize(item);
mUsedNavMeshDataSize -= item.mSize;
mFreeNavMeshDataSize -= item.mSize;
tileValues->second.mMap.erase(value);
mFreeItems.pop_back();
@ -174,7 +149,7 @@ namespace DetourNavigator
return;
mBusyItems.splice(mBusyItems.end(), mFreeItems, iterator);
mFreeNavMeshDataSize -= getSize(*iterator);
mFreeNavMeshDataSize -= iterator->mSize;
}
void NavMeshTilesCache::releaseItem(ItemIterator iterator)
@ -185,71 +160,6 @@ namespace DetourNavigator
const std::lock_guard<std::mutex> lock(mMutex);
mFreeItems.splice(mFreeItems.begin(), mBusyItems, iterator);
mFreeNavMeshDataSize += getSize(*iterator);
}
namespace
{
struct CompareBytes
{
const unsigned char* mRhsIt;
const unsigned char* const mRhsEnd;
template <class T>
int operator ()(const std::vector<T>& lhs)
{
const auto lhsBegin = reinterpret_cast<const char*>(lhs.data());
const auto lhsEnd = reinterpret_cast<const char*>(lhs.data() + lhs.size());
const auto lhsSize = static_cast<std::ptrdiff_t>(lhsEnd - lhsBegin);
const auto rhsSize = static_cast<std::ptrdiff_t>(mRhsEnd - mRhsIt);
if (lhsBegin == nullptr || mRhsIt == nullptr)
{
if (lhsSize < rhsSize)
return -1;
else if (lhsSize > rhsSize)
return 1;
else
return 0;
}
const auto size = std::min(lhsSize, rhsSize);
if (const auto result = std::memcmp(lhsBegin, mRhsIt, size))
return result;
if (lhsSize > rhsSize)
return 1;
mRhsIt += size;
return 0;
}
};
}
int NavMeshTilesCache::RecastMeshKeyView::compare(const std::vector<unsigned char>& other) const
{
CompareBytes compareBytes {other.data(), other.data() + other.size()};
if (const auto result = compareBytes(mRecastMesh.get().getIndices()))
return result;
if (const auto result = compareBytes(mRecastMesh.get().getVertices()))
return result;
if (const auto result = compareBytes(mRecastMesh.get().getAreaTypes()))
return result;
if (const auto result = compareBytes(mRecastMesh.get().getWater()))
return result;
if (const auto result = compareBytes(mOffMeshConnections.get()))
return result;
if (compareBytes.mRhsIt < compareBytes.mRhsEnd)
return -1;
return 0;
mFreeNavMeshDataSize += iterator->mSize;
}
}

View file

@ -27,6 +27,89 @@ namespace DetourNavigator
int mSize;
};
struct RecastMeshData
{
std::vector<int> mIndices;
std::vector<float> mVertices;
std::vector<AreaType> mAreaTypes;
std::vector<RecastMesh::Water> mWater;
};
inline bool operator <(const RecastMeshData& lhs, const RecastMeshData& rhs)
{
return std::tie(lhs.mIndices, lhs.mVertices, lhs.mAreaTypes, lhs.mWater)
< std::tie(rhs.mIndices, rhs.mVertices, rhs.mAreaTypes, rhs.mWater);
}
inline bool operator <(const RecastMeshData& lhs, const RecastMesh& rhs)
{
return std::tie(lhs.mIndices, lhs.mVertices, lhs.mAreaTypes, lhs.mWater)
< std::tie(rhs.getIndices(), rhs.getVertices(), rhs.getAreaTypes(), rhs.getWater());
}
inline bool operator <(const RecastMesh& lhs, const RecastMeshData& rhs)
{
return std::tie(lhs.getIndices(), lhs.getVertices(), lhs.getAreaTypes(), lhs.getWater())
< std::tie(rhs.mIndices, rhs.mVertices, rhs.mAreaTypes, rhs.mWater);
}
struct NavMeshKey
{
RecastMeshData mRecastMesh;
std::vector<OffMeshConnection> mOffMeshConnections;
};
inline bool operator <(const NavMeshKey& lhs, const NavMeshKey& rhs)
{
return std::tie(lhs.mRecastMesh, lhs.mOffMeshConnections)
< std::tie(rhs.mRecastMesh, rhs.mOffMeshConnections);
}
struct NavMeshKeyRef
{
std::reference_wrapper<const NavMeshKey> mRef;
explicit NavMeshKeyRef(const NavMeshKey& ref) : mRef(ref) {}
};
inline bool operator <(const NavMeshKeyRef& lhs, const NavMeshKeyRef& rhs)
{
return lhs.mRef.get() < rhs.mRef.get();
}
struct NavMeshKeyView
{
std::reference_wrapper<const RecastMesh> mRecastMesh;
std::reference_wrapper<const std::vector<OffMeshConnection>> mOffMeshConnections;
NavMeshKeyView(const RecastMesh& recastMesh, const std::vector<OffMeshConnection>& offMeshConnections)
: mRecastMesh(recastMesh), mOffMeshConnections(offMeshConnections) {}
};
inline bool operator <(const NavMeshKeyView& lhs, const NavMeshKey& rhs)
{
return std::tie(lhs.mRecastMesh.get(), lhs.mOffMeshConnections.get())
< std::tie(rhs.mRecastMesh, rhs.mOffMeshConnections);
}
inline bool operator <(const NavMeshKey& lhs, const NavMeshKeyView& rhs)
{
return std::tie(lhs.mRecastMesh, lhs.mOffMeshConnections)
< std::tie(rhs.mRecastMesh.get(), rhs.mOffMeshConnections.get());
}
template <class R>
inline bool operator <(const NavMeshKeyRef& lhs, const R& rhs)
{
return lhs.mRef.get() < rhs;
}
template <class L>
inline bool operator <(const L& lhs, const NavMeshKeyRef& rhs)
{
return lhs < rhs.mRef.get();
}
class NavMeshTilesCache
{
public:
@ -35,14 +118,16 @@ namespace DetourNavigator
std::atomic<std::int64_t> mUseCount;
osg::Vec3f mAgentHalfExtents;
TilePosition mChangedTile;
std::vector<unsigned char> mNavMeshKey;
NavMeshKey mNavMeshKey;
NavMeshData mNavMeshData;
std::size_t mSize;
Item(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile, std::vector<unsigned char>&& navMeshKey)
Item(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile, NavMeshKey&& navMeshKey, std::size_t size)
: mUseCount(0)
, mAgentHalfExtents(agentHalfExtents)
, mChangedTile(changedTile)
, mNavMeshKey(std::move(navMeshKey))
, mNavMeshKey(navMeshKey)
, mSize(size)
{}
};
@ -115,85 +200,17 @@ namespace DetourNavigator
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
private:
class KeyView
{
public:
KeyView() = default;
virtual ~KeyView() = default;
KeyView(const std::vector<unsigned char>& value)
: mValue(&value) {}
const std::vector<unsigned char>& getValue() const
{
assert(mValue);
return *mValue;
}
virtual int compare(const std::vector<unsigned char>& other) const
{
assert(mValue);
const auto valueSize = mValue->size();
const auto otherSize = other.size();
if (const auto result = std::memcmp(mValue->data(), other.data(), std::min(valueSize, otherSize)))
return result;
if (valueSize < otherSize)
return -1;
if (valueSize > otherSize)
return 1;
return 0;
}
virtual bool isLess(const KeyView& other) const
{
assert(mValue);
return other.compare(*mValue) > 0;
}
friend bool operator <(const KeyView& lhs, const KeyView& rhs)
{
return lhs.isLess(rhs);
}
private:
const std::vector<unsigned char>* mValue = nullptr;
};
class RecastMeshKeyView : public KeyView
{
public:
RecastMeshKeyView(const RecastMesh& recastMesh, const std::vector<OffMeshConnection>& offMeshConnections)
: mRecastMesh(recastMesh), mOffMeshConnections(offMeshConnections) {}
int compare(const std::vector<unsigned char>& other) const override;
bool isLess(const KeyView& other) const override
{
return compare(other.getValue()) < 0;
}
virtual ~RecastMeshKeyView() = default;
private:
std::reference_wrapper<const RecastMesh> mRecastMesh;
std::reference_wrapper<const std::vector<OffMeshConnection>> mOffMeshConnections;
};
struct TileMap
{
std::map<KeyView, ItemIterator> mMap;
std::map<NavMeshKeyRef, ItemIterator, std::less<>> mMap;
};
mutable std::mutex mMutex;
std::size_t mMaxNavMeshDataSize;
std::size_t mUsedNavMeshDataSize;
std::size_t mFreeNavMeshDataSize;
std::size_t mHitCount;
std::size_t mGetCount;
std::list<Item> mBusyItems;
std::list<Item> mFreeItems;
std::map<osg::Vec3f, std::map<TilePosition, TileMap>> mValues;
@ -203,11 +220,6 @@ namespace DetourNavigator
void acquireItemUnsafe(ItemIterator iterator);
void releaseItem(ItemIterator iterator);
static std::size_t getSize(const Item& item)
{
return static_cast<std::size_t>(item.mNavMeshData.mSize) + 2 * item.mNavMeshKey.size();
}
};
}

View file

@ -5,6 +5,8 @@
#include <osg/Vec3f>
#include <tuple>
namespace DetourNavigator
{
struct OffMeshConnection
@ -13,6 +15,11 @@ namespace DetourNavigator
osg::Vec3f mEnd;
AreaType mAreaType;
};
inline bool operator<(const OffMeshConnection& lhs, const OffMeshConnection& rhs)
{
return std::tie(lhs.mStart, lhs.mEnd, lhs.mAreaType) < std::tie(rhs.mStart, rhs.mEnd, rhs.mAreaType);
}
}
#endif

View file

@ -85,6 +85,8 @@ namespace DetourNavigator
std::for_each(byId.first, byId.second, [&] (const auto& v) { result.push_back(v.second); });
});
std::sort(result.begin(), result.end());
return result;
}

View file

@ -5,9 +5,12 @@
#include "chunkytrimesh.hpp"
#include "bounds.hpp"
#include <components/bullethelpers/operators.hpp>
#include <memory>
#include <string>
#include <vector>
#include <tuple>
#include <osg/Vec3f>
@ -87,6 +90,17 @@ namespace DetourNavigator
ChunkyTriMesh mChunkyTriMesh;
Bounds mBounds;
};
inline bool operator<(const RecastMesh::Water& lhs, const RecastMesh::Water& rhs)
{
return std::tie(lhs.mCellSize, lhs.mTransform) < std::tie(rhs.mCellSize, rhs.mTransform);
}
inline bool operator <(const RecastMesh& lhs, const RecastMesh& rhs)
{
return std::tie(lhs.getIndices(), lhs.getVertices(), lhs.getAreaTypes(), lhs.getWater())
< std::tie(rhs.getIndices(), rhs.getVertices(), rhs.getAreaTypes(), rhs.getWater());
}
}
#endif

View file

@ -155,6 +155,7 @@ namespace DetourNavigator
std::shared_ptr<RecastMesh> RecastMeshBuilder::create(std::size_t generation, std::size_t revision)
{
optimizeRecastMesh(mIndices, mVertices);
std::sort(mWater.begin(), mWater.end());
return std::make_shared<RecastMesh>(generation, revision, mIndices, mVertices, mAreaTypes,
mWater, mSettings.get().mTrianglesPerChunk);
}

View file

@ -2,6 +2,8 @@
#define COMPONENTS_MISC_ENDIANNESS_H
#include <cstdint>
#include <cstring>
#include <type_traits>
namespace Misc
{
@ -15,20 +17,26 @@ namespace Misc
if constexpr (sizeof(T) == 2)
{
uint16_t& v16 = *reinterpret_cast<uint16_t*>(&v);
uint16_t v16;
std::memcpy(&v16, &v, sizeof(T));
v16 = (v16 >> 8) | (v16 << 8);
std::memcpy(&v, &v16, sizeof(T));
}
if constexpr (sizeof(T) == 4)
{
uint32_t& v32 = *reinterpret_cast<uint32_t*>(&v);
v32 = (v32 >> 24) | ((v32 >> 8) & 0xff00) | ((v32 & 0xff00) << 8) || v32 << 24;
uint32_t v32;
std::memcpy(&v32, &v, sizeof(T));
v32 = (v32 >> 24) | ((v32 >> 8) & 0xff00) | ((v32 & 0xff00) << 8) | v32 << 24;
std::memcpy(&v, &v32, sizeof(T));
}
if constexpr (sizeof(T) == 8)
{
uint64_t& v64 = *reinterpret_cast<uint64_t*>(&v);
uint64_t v64;
std::memcpy(&v64, &v, sizeof(T));
v64 = (v64 >> 56) | ((v64 & 0x00ff'0000'0000'0000) >> 40) | ((v64 & 0x0000'ff00'0000'0000) >> 24)
| ((v64 & 0x0000'00ff'0000'0000) >> 8) | ((v64 & 0x0000'0000'ff00'0000) << 8)
| ((v64 & 0x0000'0000'00ff'0000) << 24) | ((v64 & 0x0000'0000'0000'ff00) << 40) | (v64 << 56);
std::memcpy(&v, &v64, sizeof(T));
}
}

View file

@ -86,7 +86,17 @@ public:
return osg::ref_ptr<BulletShape>();
osg::ref_ptr<BulletShape> shape (new BulletShape);
shape->mCollisionShape = new TriangleMeshShape(mTriangleMesh.release(), true);
btBvhTriangleMeshShape* triangleMeshShape = new TriangleMeshShape(mTriangleMesh.release(), true);
btVector3 aabbMin = triangleMeshShape->getLocalAabbMin();
btVector3 aabbMax = triangleMeshShape->getLocalAabbMax();
shape->mCollisionBox.extents[0] = (aabbMax[0] - aabbMin[0]) / 2.0f;
shape->mCollisionBox.extents[1] = (aabbMax[1] - aabbMin[1]) / 2.0f;
shape->mCollisionBox.extents[2] = (aabbMax[2] - aabbMin[2]) / 2.0f;
shape->mCollisionBox.center = osg::Vec3f( (aabbMax[0] + aabbMin[0]) / 2.0f,
(aabbMax[1] + aabbMin[1]) / 2.0f,
(aabbMax[2] + aabbMin[2]) / 2.0f );
shape->mCollisionShape = triangleMeshShape;
return shape;
}

View file

@ -394,6 +394,7 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer)
"NavMesh CacheSize",
"NavMesh UsedTiles",
"NavMesh CachedTiles",
"NavMesh CacheHitRate",
"",
"Mechanics Actors",
"Mechanics Objects",

View file

@ -1544,7 +1544,13 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
}
// 1. Traverse main scene graph
osg::ref_ptr<osgUtil::StateGraph> decoratorStateGraph = cullShadowReceivingScene(&cv);
auto* shadowReceiverStateSet = vdd->getStateSet(cv.getTraversalNumber());
shadowReceiverStateSet->clear();
cv.pushStateSet(shadowReceiverStateSet);
cullShadowReceivingScene(&cv);
cv.popStateSet();
if (cv.getComputeNearFarMode()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
{
@ -1572,7 +1578,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
if (vdd->_numValidShadows>0)
{
decoratorStateGraph->setStateSet(selectStateSetForRenderingShadow(*vdd, cv.getTraversalNumber()));
prepareStateSetForRenderingShadow(*vdd, cv.getTraversalNumber());
}
// OSG_NOTICE<<"End of shadow setup Projection matrix "<<*cv.getProjectionMatrix()<<std::endl;
@ -3118,24 +3124,20 @@ bool MWShadowTechnique::assignTexGenSettings(osgUtil::CullVisitor* cv, osg::Came
return true;
}
osg::ref_ptr<osgUtil::StateGraph> MWShadowTechnique::cullShadowReceivingScene(osgUtil::CullVisitor* cv) const
void MWShadowTechnique::cullShadowReceivingScene(osgUtil::CullVisitor* cv) const
{
OSG_INFO<<"cullShadowReceivingScene()"<<std::endl;
// record the traversal mask on entry so we can reapply it later.
unsigned int traversalMask = cv->getTraversalMask();
cv->pushStateSet(_shadowRecievingPlaceholderStateSet.get());
osg::ref_ptr<osgUtil::StateGraph> decoratorStateGraph = cv->getCurrentStateGraph();
cv->setTraversalMask( traversalMask & _shadowedScene->getShadowSettings()->getReceivesShadowTraversalMask() );
_shadowedScene->osg::Group::traverse(*cv);
cv->setTraversalMask( traversalMask );
cv->popStateSet();
return decoratorStateGraph;
return;
}
void MWShadowTechnique::cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Camera* camera) const
@ -3154,9 +3156,9 @@ void MWShadowTechnique::cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Ca
return;
}
osg::StateSet* MWShadowTechnique::selectStateSetForRenderingShadow(ViewDependentData& vdd, unsigned int traversalNumber) const
osg::StateSet* MWShadowTechnique::prepareStateSetForRenderingShadow(ViewDependentData& vdd, unsigned int traversalNumber) const
{
OSG_INFO<<" selectStateSetForRenderingShadow() "<<vdd.getStateSet(traversalNumber)<<std::endl;
OSG_INFO<<" prepareStateSetForRenderingShadow() "<<vdd.getStateSet(traversalNumber)<<std::endl;
osg::ref_ptr<osg::StateSet> stateset = vdd.getStateSet(traversalNumber);

View file

@ -270,11 +270,11 @@ namespace SceneUtil {
virtual bool assignTexGenSettings(osgUtil::CullVisitor* cv, osg::Camera* camera, unsigned int textureUnit, osg::TexGen* texgen);
virtual osg::ref_ptr<osgUtil::StateGraph> cullShadowReceivingScene(osgUtil::CullVisitor* cv) const;
virtual void cullShadowReceivingScene(osgUtil::CullVisitor* cv) const;
virtual void cullShadowCastingScene(osgUtil::CullVisitor* cv, osg::Camera* camera) const;
virtual osg::StateSet* selectStateSetForRenderingShadow(ViewDependentData& vdd, unsigned int traversalNumber) const;
virtual osg::StateSet* prepareStateSetForRenderingShadow(ViewDependentData& vdd, unsigned int traversalNumber) const;
protected:
virtual ~MWShadowTechnique();

View file

@ -38,7 +38,7 @@ This setting causes the behavior of the sneak key (bound to Ctrl by default)
to toggle sneaking on and off rather than requiring the key to be held down while sneaking.
Players that spend significant time sneaking may find the character easier to control with this option enabled.
This setting can only be configured by editing the settings configuration file.
This setting can be toggled in the launcher under "Advanced" -> "Game Mechanics" -> "Toggle sneak".
always run
----------