mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-08-03 23:36:59 -04:00
Assume NIF controller data is already sorted (#8545)
This commit is contained in:
parent
c90ae89381
commit
93cb69b012
@ -247,16 +247,11 @@ namespace Nif
|
||||
|
||||
void NiVisData::read(NIFStream* nif)
|
||||
{
|
||||
mKeys = std::make_shared<std::map<float, bool>>();
|
||||
uint32_t numKeys;
|
||||
nif->read(numKeys);
|
||||
for (size_t i = 0; i < numKeys; i++)
|
||||
mKeys = std::make_shared<std::vector<std::pair<float, bool>>>(nif->get<uint32_t>());
|
||||
for (auto& [time, value] : *mKeys)
|
||||
{
|
||||
float time;
|
||||
char value;
|
||||
nif->read(time);
|
||||
nif->read(value);
|
||||
(*mKeys)[time] = (value != 0);
|
||||
value = nif->get<uint8_t>() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,8 +193,8 @@ namespace Nif
|
||||
|
||||
struct NiVisData : public Record
|
||||
{
|
||||
// TODO: investigate possible use of BoolKeyMap
|
||||
std::shared_ptr<std::map<float, bool>> mKeys;
|
||||
// This is theoretically a "flat map" sorted by time
|
||||
std::shared_ptr<std::vector<std::pair<float, bool>>> mKeys;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
#ifndef OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
||||
#define OPENMW_COMPONENTS_NIF_NIFKEY_HPP
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "exception.hpp"
|
||||
@ -46,7 +46,8 @@ namespace Nif
|
||||
template <typename T, T (NIFStream::*getValue)()>
|
||||
struct KeyMapT
|
||||
{
|
||||
using MapType = std::map<float, KeyT<T>>;
|
||||
// This is theoretically a "flat map" sorted by time
|
||||
using MapType = std::vector<std::pair<float, KeyT<T>>>;
|
||||
|
||||
using ValueType = T;
|
||||
using KeyType = KeyT<T>;
|
||||
@ -78,8 +79,12 @@ namespace Nif
|
||||
uint32_t count;
|
||||
nif->read(count);
|
||||
|
||||
if (count != 0 || morph)
|
||||
nif->read(mInterpolationType);
|
||||
if (count == 0 && !morph)
|
||||
return;
|
||||
|
||||
nif->read(mInterpolationType);
|
||||
|
||||
mKeys.reserve(count);
|
||||
|
||||
KeyType key = {};
|
||||
|
||||
@ -90,7 +95,7 @@ namespace Nif
|
||||
float time;
|
||||
nif->read(time);
|
||||
readValue(*nif, key);
|
||||
mKeys[time] = key;
|
||||
mKeys.emplace_back(time, key);
|
||||
}
|
||||
}
|
||||
else if (mInterpolationType == InterpolationType_Quadratic)
|
||||
@ -100,7 +105,7 @@ namespace Nif
|
||||
float time;
|
||||
nif->read(time);
|
||||
readQuadratic(*nif, key);
|
||||
mKeys[time] = key;
|
||||
mKeys.emplace_back(time, key);
|
||||
}
|
||||
}
|
||||
else if (mInterpolationType == InterpolationType_TCB)
|
||||
@ -115,8 +120,9 @@ namespace Nif
|
||||
nif->read(tcbKey.mBias);
|
||||
}
|
||||
generateTCBTangents(tcbKeys);
|
||||
for (TCBKey<T>& key : tcbKeys)
|
||||
mKeys[key.mTime] = KeyType{ std::move(key.mValue), std::move(key.mInTan), std::move(key.mOutTan) };
|
||||
for (TCBKey<T>& tcbKey : tcbKeys)
|
||||
mKeys.emplace_back(std::move(tcbKey.mTime),
|
||||
KeyType{ std::move(tcbKey.mValue), std::move(tcbKey.mInTan), std::move(tcbKey.mOutTan) });
|
||||
}
|
||||
else if (mInterpolationType == InterpolationType_XYZ)
|
||||
{
|
||||
@ -132,6 +138,8 @@ namespace Nif
|
||||
throw Nif::Exception("Unhandled interpolation type: " + std::to_string(mInterpolationType),
|
||||
nif->getFile().getFilename());
|
||||
}
|
||||
|
||||
// Note: NetImmerse does NOT sort keys or remove duplicates
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -676,12 +676,16 @@ namespace Nif
|
||||
|
||||
void NiPSysEmitterCtlrData::read(NIFStream* nif)
|
||||
{
|
||||
// TODO: this is not used in the official files and needs verification
|
||||
mFloatKeyList = std::make_shared<FloatKeyMap>();
|
||||
mFloatKeyList->read(nif);
|
||||
mVisKeyList = std::make_shared<BoolKeyMap>();
|
||||
uint32_t numVisKeys;
|
||||
nif->read(numVisKeys);
|
||||
for (size_t i = 0; i < numVisKeys; i++)
|
||||
mVisKeyList->mKeys[nif->get<float>()].mValue = nif->get<uint8_t>() != 0;
|
||||
mVisKeyList->mKeys.resize(nif->get<uint32_t>());
|
||||
for (auto& [time, key] : mVisKeyList->mKeys)
|
||||
{
|
||||
nif->read(time);
|
||||
key.mValue = nif->get<uint8_t>() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NiPSysCollider::read(NIFStream* nif)
|
||||
|
@ -374,7 +374,8 @@ namespace NifOsg
|
||||
if (mData->empty())
|
||||
return true;
|
||||
|
||||
auto iter = mData->upper_bound(time);
|
||||
auto iter = std::upper_bound(mData->begin(), mData->end(), time,
|
||||
[](float time, const std::pair<float, bool>& key) { return time < key.first; });
|
||||
if (iter != mData->begin())
|
||||
--iter;
|
||||
return iter->second;
|
||||
|
@ -54,7 +54,8 @@ namespace NifOsg
|
||||
return mLastHighKey;
|
||||
}
|
||||
|
||||
return mKeys->mKeys.lower_bound(time);
|
||||
return std::lower_bound(mKeys->mKeys.begin(), mKeys->mKeys.end(), time,
|
||||
[](const typename MapT::MapType::value_type& key, float t) { return key.first < t; });
|
||||
}
|
||||
|
||||
public:
|
||||
@ -99,8 +100,8 @@ namespace NifOsg
|
||||
|
||||
const typename MapT::MapType& keys = mKeys->mKeys;
|
||||
|
||||
if (time <= keys.begin()->first)
|
||||
return keys.begin()->second.mValue;
|
||||
if (time <= keys.front().first)
|
||||
return keys.front().second.mValue;
|
||||
|
||||
typename MapT::MapType::const_iterator it = retrieveKey(time);
|
||||
|
||||
@ -116,7 +117,7 @@ namespace NifOsg
|
||||
return interpolate(mLastLowKey->second, mLastHighKey->second, a, mKeys->mInterpolationType);
|
||||
}
|
||||
|
||||
return keys.rbegin()->second.mValue;
|
||||
return keys.back().second.mValue;
|
||||
}
|
||||
|
||||
bool empty() const { return !mKeys || mKeys->mKeys.empty(); }
|
||||
@ -283,7 +284,7 @@ namespace NifOsg
|
||||
class VisController : public SceneUtil::NodeCallback<VisController>, public SceneUtil::Controller
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<std::map<float, bool>> mData;
|
||||
std::shared_ptr<std::vector<std::pair<float, bool>>> mData;
|
||||
BoolInterpolator mInterpolator;
|
||||
unsigned int mMask{ 0u };
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user