Merge branch 'master' into lighting

pull/541/head
Bret Curtis 6 years ago committed by GitHub
commit 10643a10f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -58,6 +58,7 @@
Bug #4948: Footstep sounds while levitating on ground level
Bug #4963: Enchant skill progress is incorrect
Bug #4965: Global light attenuation settings setup is lacking
Bug #4969: "Miss" sound plays for any actor
Feature #2229: Improve pathfinding AI
Feature #3442: Default values for fallbacks from ini file
Feature #3610: Option to invert X axis

@ -376,7 +376,8 @@ namespace MWClass
if (!successful)
{
// Missed
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "miss", 1.0f, 1.0f);
if (!attacker.isEmpty() && attacker == MWMechanics::getPlayer())
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "miss", 1.0f, 1.0f);
return;
}

@ -710,7 +710,8 @@ namespace MWClass
if (!successful)
{
// Missed
sndMgr->playSound3D(ptr, "miss", 1.0f, 1.0f);
if (!attacker.isEmpty() && attacker == MWMechanics::getPlayer())
sndMgr->playSound3D(ptr, "miss", 1.0f, 1.0f);
return;
}

@ -126,8 +126,12 @@ namespace DetourNavigator
try
{
if (auto job = getNextJob())
if (!processJob(*job))
{
const auto processed = processJob(*job);
unlockTile(job->mAgentHalfExtents, job->mChangedTile);
if (!processed)
repost(std::move(*job));
}
}
catch (const std::exception& e)
{
@ -178,19 +182,47 @@ namespace DetourNavigator
boost::optional<AsyncNavMeshUpdater::Job> AsyncNavMeshUpdater::getNextJob()
{
std::unique_lock<std::mutex> lock(mMutex);
if (!mHasJob.wait_for(lock, std::chrono::milliseconds(10), [&] { return !mJobs.empty(); }))
const auto threadId = std::this_thread::get_id();
auto& threadQueue = mThreadsQueues[threadId];
while (true)
{
mFirstStart.lock()->reset();
mDone.notify_all();
return boost::none;
const auto hasJob = [&] { return !mJobs.empty() || !threadQueue.mPushed.empty(); };
if (!mHasJob.wait_for(lock, std::chrono::milliseconds(10), hasJob))
{
mFirstStart.lock()->reset();
mDone.notify_all();
return boost::none;
}
Log(Debug::Debug) << "Got " << mJobs.size() << " navigator jobs and "
<< threadQueue.mJobs.size() << " thread jobs";
auto job = threadQueue.mJobs.empty()
? getJob(mJobs, mPushed)
: getJob(threadQueue.mJobs, threadQueue.mPushed);
const auto owner = lockTile(job.mAgentHalfExtents, job.mChangedTile);
if (owner == threadId)
return job;
postThreadJob(std::move(job), mThreadsQueues[owner]);
}
Log(Debug::Debug) << "Got " << mJobs.size() << " navigator jobs";
const auto job = mJobs.top();
mJobs.pop();
const auto pushed = mPushed.find(job.mAgentHalfExtents);
pushed->second.erase(job.mChangedTile);
if (pushed->second.empty())
mPushed.erase(pushed);
}
AsyncNavMeshUpdater::Job AsyncNavMeshUpdater::getJob(Jobs& jobs, Pushed& pushed)
{
auto job = jobs.top();
jobs.pop();
const auto it = pushed.find(job.mAgentHalfExtents);
it->second.erase(job.mChangedTile);
if (it->second.empty())
pushed.erase(it);
return job;
}
@ -239,4 +271,60 @@ namespace DetourNavigator
mHasJob.notify_all();
}
}
void AsyncNavMeshUpdater::postThreadJob(Job&& job, Queue& queue)
{
if (queue.mPushed[job.mAgentHalfExtents].insert(job.mChangedTile).second)
{
queue.mJobs.push(std::move(job));
mHasJob.notify_all();
}
}
std::thread::id AsyncNavMeshUpdater::lockTile(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile)
{
if (mSettings.get().mAsyncNavMeshUpdaterThreads <= 1)
return std::this_thread::get_id();
auto locked = mProcessingTiles.lock();
auto agent = locked->find(agentHalfExtents);
if (agent == locked->end())
{
const auto threadId = std::this_thread::get_id();
locked->emplace(agentHalfExtents, std::map<TilePosition, std::thread::id>({{changedTile, threadId}}));
return threadId;
}
auto tile = agent->second.find(changedTile);
if (tile == agent->second.end())
{
const auto threadId = std::this_thread::get_id();
agent->second.emplace(changedTile, threadId);
return threadId;
}
return tile->second;
}
void AsyncNavMeshUpdater::unlockTile(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile)
{
if (mSettings.get().mAsyncNavMeshUpdaterThreads <= 1)
return;
auto locked = mProcessingTiles.lock();
auto agent = locked->find(agentHalfExtents);
if (agent == locked->end())
return;
auto tile = agent->second.find(changedTile);
if (tile == agent->second.end())
return;
agent->second.erase(tile);
if (agent->second.empty())
locked->erase(agent);
}
}

@ -69,6 +69,15 @@ namespace DetourNavigator
};
using Jobs = std::priority_queue<Job, std::deque<Job>>;
using Pushed = std::map<osg::Vec3f, std::set<TilePosition>>;
struct Queue
{
Jobs mJobs;
Pushed mPushed;
Queue() = default;
};
std::reference_wrapper<const Settings> mSettings;
std::reference_wrapper<TileCachedRecastMeshManager> mRecastMeshManager;
@ -82,6 +91,8 @@ namespace DetourNavigator
Misc::ScopeGuarded<TilePosition> mPlayerTile;
Misc::ScopeGuarded<boost::optional<std::chrono::steady_clock::time_point>> mFirstStart;
NavMeshTilesCache mNavMeshTilesCache;
Misc::ScopeGuarded<std::map<osg::Vec3f, std::map<TilePosition, std::thread::id>>> mProcessingTiles;
std::map<std::thread::id, Queue> mThreadsQueues;
std::vector<std::thread> mThreads;
void process() throw();
@ -90,11 +101,19 @@ namespace DetourNavigator
boost::optional<Job> getNextJob();
static Job getJob(Jobs& jobs, Pushed& pushed);
void postThreadJob(Job&& job, Queue& queue);
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
std::chrono::steady_clock::time_point setFirstStart(const std::chrono::steady_clock::time_point& value);
void repost(Job&& job);
std::thread::id lockTile(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile);
void unlockTile(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile);
};
}

@ -119,19 +119,13 @@ static const std::map<std::string,RecordFactoryEntry> factories = makeFactory();
std::string NIFFile::printVersion(unsigned int version)
{
union ver_quad
{
uint32_t full;
uint8_t quad[4];
} version_out;
version_out.full = version;
int major = (version >> 24) & 0xFF;
int minor = (version >> 16) & 0xFF;
int patch = (version >> 8) & 0xFF;
int rev = version & 0xFF;
std::stringstream stream;
stream << version_out.quad[3] << "."
<< version_out.quad[2] << "."
<< version_out.quad[1] << "."
<< version_out.quad[0];
stream << major << "." << minor << "." << patch << "." << rev;
return stream.str();
}
@ -146,7 +140,9 @@ void NIFFile::parse(Files::IStreamPtr stream)
// Get BCD version
ver = nif.getUInt();
if(ver != VER_MW)
// 4.0.0.0 is an older, practically identical version of the format.
// It's not used by Morrowind assets but Morrowind supports it.
if(ver != 0x04000000 && ver != VER_MW)
fail("Unsupported NIF version: " + printVersion(ver));
// Number of records
size_t recNum = nif.getInt();

Loading…
Cancel
Save