1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-25 06:35:30 +00:00

Modernize NiParticlesData and NiSkinData

This commit is contained in:
Alexei Kotov 2023-09-05 01:18:37 +03:00
parent 89774716fb
commit 6ac271d5c0
3 changed files with 77 additions and 76 deletions

View File

@ -165,26 +165,33 @@ namespace Nif
// Should always match the number of vertices
if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW)
numParticles = nif->getUShort();
nif->read(mNumParticles);
if (nif->getVersion() <= NIFStream::generateVersion(10, 0, 1, 0))
std::fill(particleRadii.begin(), particleRadii.end(), nif->getFloat());
else if (nif->getBoolean())
nif->readVector(particleRadii, mNumVertices);
activeCount = nif->getUShort();
// Particle sizes
if (nif->getBoolean())
nif->readVector(sizes, mNumVertices);
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0) && nif->getBoolean())
nif->readVector(rotations, mNumVertices);
if (nif->getVersion() >= NIFStream::generateVersion(20, 0, 0, 4))
bool numRadii = 1;
if (nif->getVersion() > NIFStream::generateVersion(10, 0, 1, 0))
{
if (nif->getBoolean())
nif->readVector(rotationAngles, mNumVertices);
if (nif->getBoolean())
nif->readVector(rotationAxes, mNumVertices);
numRadii = mNumVertices;
if (!nif->get<bool>() || (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > 0))
numRadii = 0;
}
nif->readVector(mRadii, numRadii);
nif->read(mActiveCount);
if (nif->get<bool>())
nif->readVector(mSizes, mNumVertices);
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0))
{
if (nif->get<bool>())
nif->readVector(mRotations, mNumVertices);
if (nif->getVersion() >= NIFStream::generateVersion(20, 0, 0, 4))
{
if (nif->get<bool>())
nif->readVector(mRotationAngles, mNumVertices);
if (nif->get<bool>())
nif->readVector(mRotationAxes, mNumVertices);
}
}
}
@ -198,7 +205,7 @@ namespace Nif
bool hasRotations;
nif->read(hasRotations);
if (hasRotations)
nif->readVector(rotations, mNumVertices);
nif->readVector(mRotations, mNumVertices);
}
void NiPosData::read(NIFStream* nif)
@ -319,7 +326,7 @@ namespace Nif
if (mData.empty() || mRoot.empty())
throw Nif::Exception("NiSkinInstance missing root or data", nif.getFilename());
if (mBones.size() != mData->bones.size())
if (mBones.size() != mData->mBones.size())
throw Nif::Exception("Mismatch in NiSkinData bone count", nif.getFilename());
for (auto& bone : mBones)
@ -344,45 +351,48 @@ namespace Nif
void NiSkinData::read(NIFStream* nif)
{
trafo.rotation = nif->getMatrix3();
trafo.pos = nif->getVector3();
trafo.scale = nif->getFloat();
int boneNum = nif->getInt();
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW
&& nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 0))
partitions.read(nif);
nif->read(mTransform.rotation);
nif->read(mTransform.pos);
nif->read(mTransform.scale);
uint32_t numBones;
nif->read(numBones);
bool hasVertexWeights = true;
if (nif->getVersion() > NIFStream::generateVersion(4, 2, 1, 0))
hasVertexWeights = nif->getBoolean();
bones.resize(boneNum);
for (BoneInfo& bi : bones)
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW)
{
bi.trafo.rotation = nif->getMatrix3();
bi.trafo.pos = nif->getVector3();
bi.trafo.scale = nif->getFloat();
bi.boundSphereCenter = nif->getVector3();
bi.boundSphereRadius = nif->getFloat();
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 0))
mPartitions.read(nif);
size_t numVertices = nif->getUShort();
if (nif->getVersion() >= NIFStream::generateVersion(4, 2, 1, 0))
nif->read(hasVertexWeights);
}
mBones.resize(numBones);
for (BoneInfo& bi : mBones)
{
nif->read(bi.mTransform.rotation);
nif->read(bi.mTransform.pos);
nif->read(bi.mTransform.scale);
bi.mBoundSphere = osg::BoundingSpheref(nif->get<osg::Vec3f>(), nif->get<float>());
uint16_t numVertices;
nif->read(numVertices);
if (!hasVertexWeights)
continue;
bi.weights.resize(numVertices);
for (size_t j = 0; j < bi.weights.size(); j++)
bi.mWeights.resize(numVertices);
for (auto& [vertex, weight] : bi.mWeights)
{
bi.weights[j].vertex = nif->getUShort();
bi.weights[j].weight = nif->getFloat();
nif->read(vertex);
nif->read(weight);
}
}
}
void NiSkinData::post(Reader& nif)
{
partitions.post(nif);
mPartitions.post(nif);
}
void NiSkinPartition::read(NIFStream* nif)

View File

@ -96,13 +96,14 @@ namespace Nif
struct NiParticlesData : public NiGeometryData
{
int numParticles{ 0 };
uint16_t mNumParticles{ 0 };
uint16_t mActiveCount;
int activeCount{ 0 };
std::vector<float> particleRadii, sizes, rotationAngles;
std::vector<osg::Quat> rotations;
std::vector<osg::Vec3f> rotationAxes;
std::vector<float> mRadii;
std::vector<float> mSizes;
std::vector<osg::Quat> mRotations;
std::vector<float> mRotationAngles;
std::vector<osg::Vec3f> mRotationAxes;
void read(NIFStream* nif) override;
};
@ -267,23 +268,18 @@ namespace Nif
struct NiSkinData : public Record
{
struct VertWeight
{
unsigned short vertex;
float weight;
};
using VertWeight = std::pair<unsigned short, float>;
struct BoneInfo
{
Transformation trafo;
osg::Vec3f boundSphereCenter;
float boundSphereRadius;
std::vector<VertWeight> weights;
Transformation mTransform;
osg::BoundingSpheref mBoundSphere;
std::vector<VertWeight> mWeights;
};
Transformation trafo;
std::vector<BoneInfo> bones;
NiSkinPartitionPtr partitions;
Transformation mTransform;
std::vector<BoneInfo> mBones;
NiSkinPartitionPtr mPartitions;
void read(NIFStream* nif) override;
void post(Reader& nif) override;

View File

@ -1133,14 +1133,14 @@ namespace NifOsg
}
auto particledata = static_cast<const Nif::NiParticlesData*>(particleNode->data.getPtr());
partsys->setQuota(particledata->numParticles);
partsys->setQuota(particledata->mNumParticles);
osg::BoundingBox box;
int i = 0;
for (const auto& particle : partctrl->particles)
{
if (i++ >= particledata->activeCount)
if (i++ >= particledata->mActiveCount)
break;
if (particle.lifespan <= 0)
@ -1165,8 +1165,8 @@ namespace NifOsg
created->setAlphaRange(osgParticle::rangef(1.f, 1.f));
float size = partctrl->size;
if (particle.vertex < particledata->sizes.size())
size *= particledata->sizes[particle.vertex];
if (particle.vertex < particledata->mSizes.size())
size *= particledata->mSizes[particle.vertex];
created->setSizeRange(osgParticle::rangef(size, size));
box.expandBy(osg::BoundingSphere(position, size));
@ -1394,8 +1394,8 @@ namespace NifOsg
if (!skin->mData.empty())
{
data = skin->mData.getPtr();
if (!data->partitions.empty())
partitions = data->partitions.getPtr();
if (!data->mPartitions.empty())
partitions = data->mPartitions.getPtr();
}
if (!partitions && !skin->mPartitions.empty())
partitions = skin->mPartitions.getPtr();
@ -1556,14 +1556,9 @@ namespace NifOsg
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->name);
SceneUtil::RigGeometry::BoneInfluence influence;
const std::vector<Nif::NiSkinData::VertWeight>& weights = data->bones[i].weights;
for (size_t j = 0; j < weights.size(); j++)
{
influence.mWeights.emplace_back(weights[j].vertex, weights[j].weight);
}
influence.mInvBindMatrix = data->bones[i].trafo.toMatrix();
influence.mBoundSphere
= osg::BoundingSpheref(data->bones[i].boundSphereCenter, data->bones[i].boundSphereRadius);
influence.mWeights = data->mBones[i].mWeights;
influence.mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
influence.mBoundSphere = data->mBones[i].mBoundSphere;
map->mData.emplace_back(boneName, influence);
}