From 02d9c26289327878ec9cf213c70aee799d889808 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 14 Dec 2025 22:17:29 +0300 Subject: [PATCH] Reserve capacity for node NIF collections --- components/nif/node.cpp | 89 +++++++++++++++++++---------------------- components/nif/node.hpp | 1 + 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/components/nif/node.cpp b/components/nif/node.cpp index 086d1969ae..7a91392d5d 100644 --- a/components/nif/node.cpp +++ b/components/nif/node.cpp @@ -63,6 +63,16 @@ namespace namespace Nif { + namespace + { + void readBSDistantObjectInstanceTransform(NIFStream& stream, osg::Matrixf& value) + { + std::array mat; + stream.readArray(mat); + value.set(mat.data()); + } + } + void BoundingVolume::read(NIFStream* nif) { nif->read(mType); @@ -200,12 +210,13 @@ namespace Nif { if (nif->getVersion() < NIFStream::generateVersion(10, 0, 1, 0)) return; + std::uint32_t numNames = 0; if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5)) - mNames.resize(nif->get()); + numNames = nif->get(); else if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 3)) - mNames.resize(nif->get()); - nif->readVector(mNames, mNames.size()); - nif->readVector(mExtra, mNames.size()); + numNames = nif->get(); + nif->readVector(mNames, numNames); + nif->readVector(mExtra, numNames); if (nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5)) nif->read(mActive); if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS) @@ -371,9 +382,7 @@ namespace Nif { NiTriShape::read(nif); - mSegments.resize(nif->get()); - for (SegmentData& segment : mSegments) - segment.read(nif); + nif->readVectorOfRecords(mSegments); } void BSLODTriShape::read(NIFStream* nif) @@ -540,17 +549,19 @@ namespace Nif mAlphaProperty.read(nif); mVertDesc.read(nif); + size_t numTriangleIndices; if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4) - mTriangles.resize(nif->get() * 3); + numTriangleIndices = nif->get() * 3; else - mTriangles.resize(nif->get() * 3); - mVertData.resize(nif->get()); + numTriangleIndices = nif->get() * 3; + nif->read(mNumVertices); + mVertData.reserve(mNumVertices); nif->read(mDataSize); if (mDataSize > 0) { - for (auto& vertex : mVertData) - vertex.read(nif, mVertDesc.mFlags); - nif->readVector(mTriangles, mTriangles.size()); + for (uint16_t i = 0; i < mNumVertices; ++i) + mVertData.emplace_back().read(nif, mVertDesc.mFlags); + nif->readVector(mTriangles, numTriangleIndices); } if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE) @@ -558,9 +569,9 @@ namespace Nif nif->read(mParticleDataSize); if (mParticleDataSize > 0) { - nif->readVector(mParticleVerts, mVertData.size() * 3); - nif->readVector(mParticleNormals, mVertData.size() * 3); - nif->readVector(mParticleTriangles, mTriangles.size()); + nif->readVector(mParticleVerts, mNumVertices * 3); + nif->readVector(mParticleNormals, mNumVertices * 3); + nif->readVector(mParticleTriangles, numTriangleIndices); } } } @@ -582,8 +593,8 @@ namespace Nif nif->read(mDynamicDataSize); // nifly style. - // Consider complaining if mDynamicDataSize * 16 != mVertData.size()? - nif->readVector(mDynamicData, mVertData.size()); + // Consider complaining if mDynamicDataSize * 16 != mNumVertices? + nif->readVector(mDynamicData, mNumVertices); } void BSMeshLODTriShape::read(NIFStream* nif) @@ -606,9 +617,7 @@ namespace Nif nif->read(mStartIndex); nif->read(mNumPrimitives); nif->read(mParentArrayIndex); - mSubSegments.resize(nif->get()); - for (SubSegment& subsegment : mSubSegments) - subsegment.read(nif); + nif->readVectorOfRecords(mSubSegments); } void BSSubIndexTriShape::SubSegmentDataRecord::read(NIFStream* nif) @@ -622,22 +631,19 @@ namespace Nif { uint32_t numArrayIndices; nif->read(numArrayIndices); - mDataRecords.resize(nif->get()); + const uint32_t numRecords = nif->get(); nif->readVector(mArrayIndices, numArrayIndices); - for (SubSegmentDataRecord& dataRecord : mDataRecords) - dataRecord.read(nif); + nif->readVectorOfRecords(numRecords, mDataRecords); mSSFFile = nif->getSizedString(nif->get()); } void BSSubIndexTriShape::Segmentation::read(NIFStream* nif) { nif->read(mNumPrimitives); - mSegments.resize(nif->get()); + const uint32_t numSegments = nif->get(); nif->read(mNumTotalSegments); - for (Segment& segment : mSegments) - segment.read(nif); - - if (mSegments.size() < mNumTotalSegments) + nif->readVectorOfRecords(numSegments, mSegments); + if (numSegments < mNumTotalSegments) mSubSegmentData.read(nif); } @@ -646,11 +652,7 @@ namespace Nif BSTriShape::read(nif); if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE) - { - mSegments.resize(nif->get()); - for (BSSegmentedTriShape::SegmentData& segment : mSegments) - segment.read(nif); - } + nif->readVectorOfRecords(mSegments); else if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4 && mDataSize > 0) mSegmentation.read(nif); } @@ -752,30 +754,23 @@ namespace Nif { mResourceID.read(nif); nif->skip(12 * nif->get()); // Unknown data - mTransforms.resize(nif->get()); - for (osg::Matrixf& transform : mTransforms) - { - std::array mat; - nif->readArray(mat); - transform.set(mat.data()); - } + nif->readVectorOfRecords(readBSDistantObjectInstanceTransform, mTransforms); } void BSShaderTextureArray::read(NIFStream* nif) { nif->skip(1); // Unknown - mTextureArrays.resize(nif->get()); - for (std::vector& textureArray : mTextureArrays) - nif->getSizedStrings(textureArray, nif->get()); + const uint32_t numArrays = nif->get(); + mTextureArrays.reserve(numArrays); + for (uint32_t i = 0; i < numArrays; ++i) + nif->getSizedStrings(mTextureArrays.emplace_back(), nif->get()); } void BSDistantObjectInstancedNode::read(NIFStream* nif) { BSMultiBoundNode::read(nif); - mInstances.resize(nif->get()); - for (BSDistantObjectInstance& instance : mInstances) - instance.read(nif); + nif->readVectorOfRecords(mInstances); for (BSShaderTextureArray& textureArray : mShaderTextureArrays) textureArray.read(nif); } diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 86a75bb287..c2d92c7f88 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -385,6 +385,7 @@ namespace Nif NiAlphaPropertyPtr mAlphaProperty; BSVertexDesc mVertDesc; uint32_t mDataSize; + uint16_t mNumVertices; std::vector mVertData; std::vector mTriangles; uint32_t mParticleDataSize;