Reserve capacity for data NIF collections

This commit is contained in:
Alexei Kotov 2025-12-14 20:04:01 +03:00
parent 137382b424
commit ea506019dc
2 changed files with 81 additions and 70 deletions

View File

@ -17,6 +17,24 @@ namespace Nif
stream.read(weight); stream.read(weight);
} }
void readNiTriShapeDataMatchGroup(NIFStream& stream, std::vector<unsigned short>& value)
{
stream.readVector(value, stream.get<uint16_t>());
}
struct ReadNiGeometryDataUVSet
{
uint16_t mNumVertices;
void operator()(NIFStream& stream, std::vector<osg::Vec2f>& value) const
{
stream.readVector(value, mNumVertices);
// Flip the texture coordinates to convert them to the OpenGL convention of bottom-left image origin
for (osg::Vec2f& uv : value)
uv.y() = 1.f - uv.y();
}
};
struct ReadNiSkinDataBoneInfo struct ReadNiSkinDataBoneInfo
{ {
bool mHasVertexWeights; bool mHasVertexWeights;
@ -46,6 +64,27 @@ namespace Nif
stream.readVector(value.mVertices, mNumVerts); stream.readVector(value.mVertices, mNumVerts);
} }
}; };
struct ReadNiAdditionalGeometryDataDataBlock
{
bool mBSPacked;
void operator()(NIFStream& stream, NiAdditionalGeometryData::DataBlock& value) const
{
stream.read(value.mValid);
if (!value.mValid)
return;
stream.read(value.mBlockSize);
stream.readVector(value.mBlockOffsets, stream.get<uint32_t>());
stream.readVector(value.mDataSizes, stream.get<uint32_t>());
stream.readVector(value.mData, value.mDataSizes.size() * value.mBlockSize);
if (!mBSPacked)
return;
stream.read(value.mShaderIndex);
stream.read(value.mTotalSize);
}
};
} }
void NiGeometryData::read(NIFStream* nif) void NiGeometryData::read(NIFStream* nif)
@ -118,14 +157,8 @@ namespace Nif
if (hasData) if (hasData)
{ {
mUVList.resize(numUVs); const ReadNiGeometryDataUVSet readUVSet{ .mNumVertices = mNumVertices };
for (std::vector<osg::Vec2f>& list : mUVList) nif->readVectorOfRecords(numUVs, readUVSet, mUVList);
{
nif->readVector(list, mNumVertices);
// flip the texture coordinates to convert them to the OpenGL convention of bottom-left image origin
for (osg::Vec2f& uv : list)
uv.y() = 1.f - uv.y();
}
} }
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0)) if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0))
@ -152,9 +185,7 @@ namespace Nif
if (nif->getVersion() > NIFFile::NIFVersion::VER_OB_OLD && !nif->get<bool>()) if (nif->getVersion() > NIFFile::NIFVersion::VER_OB_OLD && !nif->get<bool>())
numIndices = 0; numIndices = 0;
nif->readVector(mTriangles, numIndices); nif->readVector(mTriangles, numIndices);
mMatchGroups.resize(nif->get<uint16_t>()); nif->readVectorOfRecords<uint16_t>(readNiTriShapeDataMatchGroup, mMatchGroups);
for (auto& group : mMatchGroups)
nif->readVector(group, nif->get<uint16_t>());
} }
void NiTriStripsData::read(NIFStream* nif) void NiTriStripsData::read(NIFStream* nif)
@ -165,11 +196,12 @@ namespace Nif
nif->read(numStrips); nif->read(numStrips);
std::vector<uint16_t> lengths; std::vector<uint16_t> lengths;
nif->readVector(lengths, numStrips); nif->readVector(lengths, numStrips);
if (nif->getVersion() > NIFFile::NIFVersion::VER_OB_OLD && !nif->get<bool>()) if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD || nif->get<bool>())
numStrips = 0; {
mStrips.resize(numStrips); mStrips.reserve(numStrips);
for (int i = 0; i < numStrips; i++) for (size_t i = 0; i < numStrips; ++i)
nif->readVector(mStrips[i], lengths[i]); nif->readVector(mStrips.emplace_back(), lengths[i]);
}
} }
void NiLinesData::read(NIFStream* nif) void NiLinesData::read(NIFStream* nif)
@ -403,19 +435,20 @@ namespace Nif
mPartitions.post(nif); mPartitions.post(nif);
} }
void BSSkinBoneData::BoneInfo::read(NIFStream* nif)
{
nif->read(mBoundSphere);
nif->read(mTransform);
}
void BSSkinBoneData::read(NIFStream* nif) void BSSkinBoneData::read(NIFStream* nif)
{ {
mBones.resize(nif->get<uint32_t>()); nif->readVectorOfRecords<uint32_t>(mBones);
for (BoneInfo& bone : mBones)
{
nif->read(bone.mBoundSphere);
nif->read(bone.mTransform);
}
} }
void NiSkinPartition::read(NIFStream* nif) void NiSkinPartition::read(NIFStream* nif)
{ {
mPartitions.resize(nif->get<uint32_t>()); const uint32_t numPartitions = nif->get<uint32_t>();
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE) if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
{ {
@ -423,13 +456,13 @@ namespace Nif
nif->read(mVertexSize); nif->read(mVertexSize);
mVertexDesc.read(nif); mVertexDesc.read(nif);
mVertexData.resize(mDataSize / mVertexSize); uint32_t numVertices = mDataSize / mVertexSize;
for (auto& vertexData : mVertexData) mVertexData.reserve(numVertices);
vertexData.read(nif, mVertexDesc.mFlags); for (uint32_t i = 0; i < numVertices; ++i)
mVertexData.emplace_back().read(nif, mVertexDesc.mFlags);
} }
for (auto& partition : mPartitions) nif->readVectorOfRecords(numPartitions, mPartitions);
partition.read(nif);
} }
void NiSkinPartition::Partition::read(NIFStream* nif) void NiSkinPartition::Partition::read(NIFStream* nif)
@ -452,9 +485,9 @@ namespace Nif
{ {
if (numStrips) if (numStrips)
{ {
mStrips.resize(numStrips); mStrips.reserve(numStrips);
for (size_t i = 0; i < numStrips; i++) for (size_t i = 0; i < numStrips; ++i)
nif->readVector(mStrips[i], stripLengths[i]); nif->readVector(mStrips.emplace_back(), stripLengths[i]);
} }
else else
nif->readVector(mTriangles, numTriangles * 3); nif->readVector(mTriangles, numTriangles * 3);
@ -524,17 +557,15 @@ namespace Nif
void NiPalette::read(NIFStream* nif) void NiPalette::read(NIFStream* nif)
{ {
bool useAlpha = nif->get<uint8_t>() != 0; const bool useAlpha = nif->get<uint8_t>() != 0;
uint32_t alphaMask = useAlpha ? 0 : 0xFF000000; const uint32_t alphaMask = useAlpha ? 0 : 0xFF000000;
const uint32_t numEntries = nif->get<uint32_t>();
uint32_t numEntries;
nif->read(numEntries);
// Fill the entire palette with black even if there isn't enough entries.
mColors.resize(numEntries > 256 ? numEntries : 256);
for (uint32_t i = 0; i < numEntries; i++) for (uint32_t i = 0; i < numEntries; i++)
{ {
nif->read(mColors[i]); const uint32_t color = nif->get<uint32_t>();
mColors[i] |= alphaMask; // Indices past 255 are always unused
if (i < 256)
mColors[i] = color | alphaMask;
} }
} }
@ -566,12 +597,10 @@ namespace Nif
void NiAdditionalGeometryData::read(NIFStream* nif) void NiAdditionalGeometryData::read(NIFStream* nif)
{ {
nif->read(mNumVertices); nif->read(mNumVertices);
mBlockInfos.resize(nif->get<uint32_t>()); nif->readVectorOfRecords<uint32_t>(mBlockInfos);
for (DataStream& info : mBlockInfos) const ReadNiAdditionalGeometryDataDataBlock readDataBlock{ .mBSPacked
info.read(nif); = recType == RC_BSPackedAdditionalGeometryData };
mBlocks.resize(nif->get<uint32_t>()); nif->readVectorOfRecords<uint32_t>(readDataBlock, mBlocks);
for (DataBlock& block : mBlocks)
block.read(nif, recType == RC_BSPackedAdditionalGeometryData);
} }
void NiAdditionalGeometryData::DataStream::read(NIFStream* nif) void NiAdditionalGeometryData::DataStream::read(NIFStream* nif)
@ -585,22 +614,6 @@ namespace Nif
nif->read(mFlags); nif->read(mFlags);
} }
void NiAdditionalGeometryData::DataBlock::read(NIFStream* nif, bool bsPacked)
{
nif->read(mValid);
if (!mValid)
return;
nif->read(mBlockSize);
nif->readVector(mBlockOffsets, nif->get<uint32_t>());
nif->readVector(mDataSizes, nif->get<uint32_t>());
nif->readVector(mData, mDataSizes.size() * mBlockSize);
if (bsPacked)
{
nif->read(mShaderIndex);
nif->read(mTotalSize);
}
}
void BSMultiBound::read(NIFStream* nif) void BSMultiBound::read(NIFStream* nif)
{ {
mData.read(nif); mData.read(nif);
@ -646,9 +659,7 @@ namespace Nif
void BSAnimNotes::read(NIFStream* nif) void BSAnimNotes::read(NIFStream* nif)
{ {
mList.resize(nif->get<uint16_t>()); nif->readVectorOfRecords<uint16_t>(mList);
for (auto& note : mList)
note.read(nif);
} }
void BSAnimNotes::post(Reader& nif) void BSAnimNotes::post(Reader& nif)

View File

@ -266,6 +266,8 @@ namespace Nif
{ {
osg::BoundingSpheref mBoundSphere; osg::BoundingSpheref mBoundSphere;
NiTransform mTransform; NiTransform mTransform;
void read(NIFStream* nif);
}; };
std::vector<BoneInfo> mBones; std::vector<BoneInfo> mBones;
@ -293,8 +295,8 @@ namespace Nif
}; };
std::vector<Partition> mPartitions; std::vector<Partition> mPartitions;
unsigned int mDataSize; uint32_t mDataSize;
unsigned int mVertexSize; uint32_t mVertexSize;
BSVertexDesc mVertexDesc; BSVertexDesc mVertexDesc;
std::vector<BSVertexData> mVertexData; std::vector<BSVertexData> mVertexData;
@ -348,7 +350,7 @@ namespace Nif
struct NiPalette : public Record struct NiPalette : public Record
{ {
// 32-bit RGBA colors that correspond to 8-bit indices // 32-bit RGBA colors that correspond to 8-bit indices
std::vector<uint32_t> mColors; std::array<uint32_t, 256> mColors{};
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
@ -406,8 +408,6 @@ namespace Nif
std::vector<char> mData; std::vector<char> mData;
uint32_t mShaderIndex; uint32_t mShaderIndex;
uint32_t mTotalSize; uint32_t mTotalSize;
void read(NIFStream* nif, bool bsPacked);
}; };
uint16_t mNumVertices; uint16_t mNumVertices;