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:
commit
66d2912fcd
22 changed files with 225 additions and 236 deletions
|
@ -215,6 +215,7 @@ Programmers
|
|||
Yohaulticetl
|
||||
Yuri Krupenin
|
||||
zelurker
|
||||
Noah Gooder
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
|
|
@ -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
|
||||
------
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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()}};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -394,6 +394,7 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer)
|
|||
"NavMesh CacheSize",
|
||||
"NavMesh UsedTiles",
|
||||
"NavMesh CachedTiles",
|
||||
"NavMesh CacheHitRate",
|
||||
"",
|
||||
"Mechanics Actors",
|
||||
"Mechanics Objects",
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
----------
|
||||
|
|
Loading…
Reference in a new issue