mirror of https://github.com/OpenMW/openmw.git
Merge branch 'nifstreamingservice' into 'master'
NIFStream rewrite/refactoring/rewhatever See merge request OpenMW/openmw!3281macos_ci_fix
commit
11ae1a1fcb
@ -1,53 +1,217 @@
|
||||
#include "nifstream.hpp"
|
||||
// For error reporting
|
||||
|
||||
#include <span>
|
||||
|
||||
#include "niffile.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Read a range of elements into a dynamic buffer per-element
|
||||
// This one should be used if the type cannot be read contiguously
|
||||
// (e.g. quaternions)
|
||||
template <class T>
|
||||
void readRange(Nif::NIFStream& stream, T* dest, size_t size)
|
||||
{
|
||||
for (T& value : std::span(dest, size))
|
||||
stream.read(value);
|
||||
}
|
||||
|
||||
// Read a range of elements into a dynamic buffer
|
||||
// This one should be used if the type can be read contiguously as an array of a different type
|
||||
// (e.g. osg::VecXf can be read as a float array of X elements)
|
||||
template <class elementType, size_t numElements, class T>
|
||||
void readAlignedRange(Files::IStreamPtr& stream, T* dest, size_t size)
|
||||
{
|
||||
static_assert(std::is_standard_layout_v<T>);
|
||||
static_assert(std::alignment_of_v<T> == std::alignment_of_v<elementType>);
|
||||
static_assert(sizeof(T) == sizeof(elementType) * numElements);
|
||||
Nif::readDynamicBufferOfType(stream, reinterpret_cast<elementType*>(dest), size * numElements);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Nif
|
||||
{
|
||||
osg::Quat NIFStream::getQuaternion()
|
||||
|
||||
unsigned int NIFStream::getVersion() const
|
||||
{
|
||||
float f[4];
|
||||
readLittleEndianBufferOfType<4, float>(inp, f);
|
||||
osg::Quat quat;
|
||||
quat.w() = f[0];
|
||||
quat.x() = f[1];
|
||||
quat.y() = f[2];
|
||||
quat.z() = f[3];
|
||||
return quat;
|
||||
return mReader.getVersion();
|
||||
}
|
||||
|
||||
Transformation NIFStream::getTrafo()
|
||||
unsigned int NIFStream::getUserVersion() const
|
||||
{
|
||||
Transformation t;
|
||||
t.pos = getVector3();
|
||||
t.rotation = getMatrix3();
|
||||
t.scale = getFloat();
|
||||
return t;
|
||||
return mReader.getUserVersion();
|
||||
}
|
||||
|
||||
/// Booleans in 4.0.0.2 (Morrowind format) and earlier are 4 byte, while in 4.1.0.0+ they're 1 byte.
|
||||
bool NIFStream::getBoolean()
|
||||
unsigned int NIFStream::getBethVersion() const
|
||||
{
|
||||
return getVersion() < generateVersion(4, 1, 0, 0) ? getInt() != 0 : getChar() != 0;
|
||||
return mReader.getBethVersion();
|
||||
}
|
||||
|
||||
/// Read in a string, either from the string table using the index or from the stream using the specified length
|
||||
std::string NIFStream::getString()
|
||||
std::string NIFStream::getSizedString(size_t length)
|
||||
{
|
||||
return getVersion() < generateVersion(20, 1, 0, 1) ? getSizedString() : file.getString(getUInt());
|
||||
std::string str(length, '\0');
|
||||
mStream->read(str.data(), length);
|
||||
if (mStream->bad())
|
||||
throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars");
|
||||
size_t end = str.find('\0');
|
||||
if (end != std::string::npos)
|
||||
str.erase(end);
|
||||
return str;
|
||||
}
|
||||
|
||||
// Convenience utility functions: get the versions of the currently read file
|
||||
unsigned int NIFStream::getVersion() const
|
||||
void NIFStream::getSizedStrings(std::vector<std::string>& vec, size_t size)
|
||||
{
|
||||
return file.getVersion();
|
||||
vec.resize(size);
|
||||
for (size_t i = 0; i < vec.size(); i++)
|
||||
vec[i] = getSizedString();
|
||||
}
|
||||
unsigned int NIFStream::getUserVersion() const
|
||||
|
||||
std::string NIFStream::getVersionString()
|
||||
{
|
||||
return file.getBethVersion();
|
||||
std::string result;
|
||||
std::getline(*mStream, result);
|
||||
if (mStream->bad())
|
||||
throw std::runtime_error("Failed to read version string");
|
||||
return result;
|
||||
}
|
||||
unsigned int NIFStream::getBethVersion() const
|
||||
|
||||
std::string NIFStream::getStringPalette()
|
||||
{
|
||||
size_t size = get<uint32_t>();
|
||||
std::string str(size, '\0');
|
||||
mStream->read(str.data(), size);
|
||||
if (mStream->bad())
|
||||
throw std::runtime_error("Failed to read string palette of " + std::to_string(size) + " chars");
|
||||
return str;
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<osg::Vec2f>(osg::Vec2f& vec)
|
||||
{
|
||||
readBufferOfType(mStream, vec._v);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<osg::Vec3f>(osg::Vec3f& vec)
|
||||
{
|
||||
readBufferOfType(mStream, vec._v);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<osg::Vec4f>(osg::Vec4f& vec)
|
||||
{
|
||||
readBufferOfType(mStream, vec._v);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<Matrix3>(Matrix3& mat)
|
||||
{
|
||||
readBufferOfType<9>(mStream, reinterpret_cast<float*>(&mat.mValues));
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<osg::Quat>(osg::Quat& quat)
|
||||
{
|
||||
std::array<float, 4> data;
|
||||
readArray(data);
|
||||
quat.w() = data[0];
|
||||
quat.x() = data[1];
|
||||
quat.y() = data[2];
|
||||
quat.z() = data[3];
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<Transformation>(Transformation& t)
|
||||
{
|
||||
read(t.pos);
|
||||
read(t.rotation);
|
||||
read(t.scale);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<bool>(bool& data)
|
||||
{
|
||||
if (getVersion() < generateVersion(4, 1, 0, 0))
|
||||
data = get<int32_t>() != 0;
|
||||
else
|
||||
data = get<int8_t>() != 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<std::string>(std::string& str)
|
||||
{
|
||||
return file.getBethVersion();
|
||||
if (getVersion() < generateVersion(20, 1, 0, 1))
|
||||
str = getSizedString();
|
||||
else
|
||||
str = mReader.getString(get<uint32_t>());
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<osg::Vec2f>(osg::Vec2f* dest, size_t size)
|
||||
{
|
||||
readAlignedRange<float, 2>(mStream, dest, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<osg::Vec3f>(osg::Vec3f* dest, size_t size)
|
||||
{
|
||||
readAlignedRange<float, 3>(mStream, dest, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<osg::Vec4f>(osg::Vec4f* dest, size_t size)
|
||||
{
|
||||
readAlignedRange<float, 4>(mStream, dest, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<Matrix3>(Matrix3* dest, size_t size)
|
||||
{
|
||||
readAlignedRange<float, 9>(mStream, dest, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<osg::Quat>(osg::Quat* dest, size_t size)
|
||||
{
|
||||
readRange(*this, dest, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<Transformation>(Transformation* dest, size_t size)
|
||||
{
|
||||
readRange(*this, dest, size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<bool>(bool* dest, size_t size)
|
||||
{
|
||||
if (getVersion() < generateVersion(4, 1, 0, 0))
|
||||
{
|
||||
for (bool& value : std::span(dest, size))
|
||||
value = get<int32_t>() != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (bool& value : std::span(dest, size))
|
||||
value = get<int8_t>() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void NIFStream::read<std::string>(std::string* dest, size_t size)
|
||||
{
|
||||
if (getVersion() < generateVersion(20, 1, 0, 1))
|
||||
{
|
||||
for (std::string& value : std::span(dest, size))
|
||||
value = getSizedString();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::string& value : std::span(dest, size))
|
||||
value = mReader.getString(get<uint32_t>());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue