1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 09:35:28 +00:00

Modernize NiSkinPartition

This commit is contained in:
Alexei Kotov 2023-09-05 23:19:35 +03:00
parent 6ac271d5c0
commit 0154bb78df
3 changed files with 51 additions and 69 deletions

View File

@ -397,8 +397,7 @@ namespace Nif
void NiSkinPartition::read(NIFStream* nif) void NiSkinPartition::read(NIFStream* nif)
{ {
nif->read(mPartitionNum); mPartitions.resize(nif->get<uint32_t>());
mPartitions.resize(mPartitionNum);
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE) if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
{ {
@ -417,89 +416,72 @@ namespace Nif
void NiSkinPartition::Partition::read(NIFStream* nif) void NiSkinPartition::Partition::read(NIFStream* nif)
{ {
size_t numVertices = nif->getUShort(); uint16_t numVertices, numTriangles, numBones, numStrips, bonesPerVertex;
size_t numTriangles = nif->getUShort(); nif->read(numVertices);
size_t numBones = nif->getUShort(); nif->read(numTriangles);
size_t numStrips = nif->getUShort(); nif->read(numBones);
size_t bonesPerVertex = nif->getUShort(); nif->read(numStrips);
nif->readVector(bones, numBones); nif->read(bonesPerVertex);
nif->readVector(mBones, numBones);
bool hasVertexMap = true; bool hasVertexMap = true;
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
hasVertexMap = nif->getBoolean(); nif->read(hasVertexMap);
if (hasVertexMap) if (hasVertexMap)
nif->readVector(vertexMap, numVertices); nif->readVector(mVertexMap, numVertices);
bool hasVertexWeights = true; bool hasVertexWeights = true;
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
hasVertexWeights = nif->getBoolean(); nif->read(hasVertexWeights);
if (hasVertexWeights) if (hasVertexWeights)
nif->readVector(weights, numVertices * bonesPerVertex); nif->readVector(mWeights, numVertices * bonesPerVertex);
std::vector<unsigned short> stripLengths; std::vector<unsigned short> stripLengths;
nif->readVector(stripLengths, numStrips); nif->readVector(stripLengths, numStrips);
bool hasFaces = true; bool hasFaces = true;
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
hasFaces = nif->getBoolean(); nif->read(hasFaces);
if (hasFaces) if (hasFaces)
{ {
if (numStrips) if (numStrips)
{ {
strips.resize(numStrips); mStrips.resize(numStrips);
for (size_t i = 0; i < numStrips; i++) for (size_t i = 0; i < numStrips; i++)
nif->readVector(strips[i], stripLengths[i]); nif->readVector(mStrips[i], stripLengths[i]);
} }
else else
nif->readVector(triangles, numTriangles * 3); nif->readVector(mTriangles, numTriangles * 3);
} }
bool hasBoneIndices = nif->getChar() != 0; if (nif->get<uint8_t>() != 0)
if (hasBoneIndices) nif->readVector(mBoneIndices, numVertices * bonesPerVertex);
nif->readVector(boneIndices, numVertices * bonesPerVertex);
if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3) if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3)
{ {
nif->getChar(); // LOD level nif->read(mLODLevel);
nif->getBoolean(); // Global VB nif->read(mGlobalVB);
} }
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE) if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
{ {
mVertexDesc.read(nif); mVertexDesc.read(nif);
nif->readVector(trueTriangles, numTriangles * 3); nif->readVector(mTrueTriangles, numTriangles * 3);
}
else if (!mVertexMap.empty())
{
if (!mStrips.empty())
{
mTrueStrips = mStrips;
for (auto& strip : mTrueStrips)
for (auto& index : strip)
index = mVertexMap[index];
}
else if (!mTriangles.empty())
{
mTrueTriangles = mTriangles;
for (unsigned short& index : mTrueTriangles)
index = mVertexMap[index];
}
} }
}
std::vector<unsigned short> NiSkinPartition::Partition::getTrueTriangles() const
{
if (!trueTriangles.empty())
return trueTriangles;
std::vector<unsigned short> remappedTriangles;
if (vertexMap.empty() || triangles.empty())
return remappedTriangles;
remappedTriangles = triangles;
for (unsigned short& index : remappedTriangles)
index = vertexMap[index];
return remappedTriangles;
}
std::vector<std::vector<unsigned short>> NiSkinPartition::Partition::getTrueStrips() const
{
if (!trueTriangles.empty())
return {};
std::vector<std::vector<unsigned short>> remappedStrips;
if (vertexMap.empty() || strips.empty())
return remappedStrips;
remappedStrips = strips;
for (auto& strip : remappedStrips)
for (auto& index : strip)
index = vertexMap[index];
return remappedStrips;
} }
void NiMorphData::read(NIFStream* nif) void NiMorphData::read(NIFStream* nif)

View File

@ -289,20 +289,20 @@ namespace Nif
{ {
struct Partition struct Partition
{ {
std::vector<unsigned short> bones; std::vector<unsigned short> mBones;
std::vector<unsigned short> vertexMap; std::vector<unsigned short> mVertexMap;
std::vector<float> weights; std::vector<float> mWeights;
std::vector<std::vector<unsigned short>> strips; std::vector<std::vector<unsigned short>> mStrips;
std::vector<unsigned short> triangles; std::vector<unsigned short> mTriangles;
std::vector<unsigned short> trueTriangles; std::vector<char> mBoneIndices;
std::vector<char> boneIndices;
BSVertexDesc mVertexDesc; BSVertexDesc mVertexDesc;
std::vector<unsigned short> mTrueTriangles;
std::vector<std::vector<unsigned short>> mTrueStrips;
uint8_t mLODLevel;
bool mGlobalVB;
void read(NIFStream* nif); void read(NIFStream* nif);
std::vector<unsigned short> getTrueTriangles() const;
std::vector<std::vector<unsigned short>> getTrueStrips() const;
}; };
unsigned int mPartitionNum;
std::vector<Partition> mPartitions; std::vector<Partition> mPartitions;
unsigned int mDataSize; unsigned int mDataSize;

View File

@ -1403,18 +1403,18 @@ namespace NifOsg
hasPartitions = partitions != nullptr; hasPartitions = partitions != nullptr;
if (hasPartitions) if (hasPartitions)
{ {
std::vector<unsigned short> trueTriangles;
for (const Nif::NiSkinPartition::Partition& partition : partitions->mPartitions) for (const Nif::NiSkinPartition::Partition& partition : partitions->mPartitions)
{ {
trueTriangles = partition.getTrueTriangles(); const std::vector<unsigned short>& trueTriangles = partition.mTrueTriangles;
if (!trueTriangles.empty()) if (!trueTriangles.empty())
{ {
geometry->addPrimitiveSet(new osg::DrawElementsUShort( geometry->addPrimitiveSet(new osg::DrawElementsUShort(
osg::PrimitiveSet::TRIANGLES, trueTriangles.size(), trueTriangles.data())); osg::PrimitiveSet::TRIANGLES, trueTriangles.size(), trueTriangles.data()));
} }
const std::vector<std::vector<unsigned short>> trueStrips = partition.getTrueStrips(); for (const auto& strip : partition.mTrueStrips)
for (const auto& strip : trueStrips)
{ {
if (strip.size() < 3)
continue;
geometry->addPrimitiveSet(new osg::DrawElementsUShort( geometry->addPrimitiveSet(new osg::DrawElementsUShort(
osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(), strip.data())); osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(), strip.data()));
} }