1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-06 22:15:37 +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 // Should always match the number of vertices
if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW) if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW)
numParticles = nif->getUShort(); nif->read(mNumParticles);
if (nif->getVersion() <= NIFStream::generateVersion(10, 0, 1, 0)) bool numRadii = 1;
std::fill(particleRadii.begin(), particleRadii.end(), nif->getFloat()); if (nif->getVersion() > NIFStream::generateVersion(10, 0, 1, 0))
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))
{ {
if (nif->getBoolean()) numRadii = mNumVertices;
nif->readVector(rotationAngles, mNumVertices); if (!nif->get<bool>() || (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > 0))
if (nif->getBoolean()) numRadii = 0;
nif->readVector(rotationAxes, mNumVertices); }
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; bool hasRotations;
nif->read(hasRotations); nif->read(hasRotations);
if (hasRotations) if (hasRotations)
nif->readVector(rotations, mNumVertices); nif->readVector(mRotations, mNumVertices);
} }
void NiPosData::read(NIFStream* nif) void NiPosData::read(NIFStream* nif)
@ -319,7 +326,7 @@ namespace Nif
if (mData.empty() || mRoot.empty()) if (mData.empty() || mRoot.empty())
throw Nif::Exception("NiSkinInstance missing root or data", nif.getFilename()); 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()); throw Nif::Exception("Mismatch in NiSkinData bone count", nif.getFilename());
for (auto& bone : mBones) for (auto& bone : mBones)
@ -344,45 +351,48 @@ namespace Nif
void NiSkinData::read(NIFStream* nif) void NiSkinData::read(NIFStream* nif)
{ {
trafo.rotation = nif->getMatrix3(); nif->read(mTransform.rotation);
trafo.pos = nif->getVector3(); nif->read(mTransform.pos);
trafo.scale = nif->getFloat(); nif->read(mTransform.scale);
int boneNum = nif->getInt();
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW
&& nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 0))
partitions.read(nif);
uint32_t numBones;
nif->read(numBones);
bool hasVertexWeights = true; bool hasVertexWeights = true;
if (nif->getVersion() > NIFStream::generateVersion(4, 2, 1, 0)) if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW)
hasVertexWeights = nif->getBoolean();
bones.resize(boneNum);
for (BoneInfo& bi : bones)
{ {
bi.trafo.rotation = nif->getMatrix3(); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 0))
bi.trafo.pos = nif->getVector3(); mPartitions.read(nif);
bi.trafo.scale = nif->getFloat();
bi.boundSphereCenter = nif->getVector3();
bi.boundSphereRadius = nif->getFloat();
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) if (!hasVertexWeights)
continue; continue;
bi.weights.resize(numVertices); bi.mWeights.resize(numVertices);
for (size_t j = 0; j < bi.weights.size(); j++) for (auto& [vertex, weight] : bi.mWeights)
{ {
bi.weights[j].vertex = nif->getUShort(); nif->read(vertex);
bi.weights[j].weight = nif->getFloat(); nif->read(weight);
} }
} }
} }
void NiSkinData::post(Reader& nif) void NiSkinData::post(Reader& nif)
{ {
partitions.post(nif); mPartitions.post(nif);
} }
void NiSkinPartition::read(NIFStream* nif) void NiSkinPartition::read(NIFStream* nif)

View file

@ -96,13 +96,14 @@ namespace Nif
struct NiParticlesData : public NiGeometryData struct NiParticlesData : public NiGeometryData
{ {
int numParticles{ 0 }; uint16_t mNumParticles{ 0 };
uint16_t mActiveCount;
int activeCount{ 0 }; std::vector<float> mRadii;
std::vector<float> mSizes;
std::vector<float> particleRadii, sizes, rotationAngles; std::vector<osg::Quat> mRotations;
std::vector<osg::Quat> rotations; std::vector<float> mRotationAngles;
std::vector<osg::Vec3f> rotationAxes; std::vector<osg::Vec3f> mRotationAxes;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
}; };
@ -267,23 +268,18 @@ namespace Nif
struct NiSkinData : public Record struct NiSkinData : public Record
{ {
struct VertWeight using VertWeight = std::pair<unsigned short, float>;
{
unsigned short vertex;
float weight;
};
struct BoneInfo struct BoneInfo
{ {
Transformation trafo; Transformation mTransform;
osg::Vec3f boundSphereCenter; osg::BoundingSpheref mBoundSphere;
float boundSphereRadius; std::vector<VertWeight> mWeights;
std::vector<VertWeight> weights;
}; };
Transformation trafo; Transformation mTransform;
std::vector<BoneInfo> bones; std::vector<BoneInfo> mBones;
NiSkinPartitionPtr partitions; NiSkinPartitionPtr mPartitions;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& 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()); auto particledata = static_cast<const Nif::NiParticlesData*>(particleNode->data.getPtr());
partsys->setQuota(particledata->numParticles); partsys->setQuota(particledata->mNumParticles);
osg::BoundingBox box; osg::BoundingBox box;
int i = 0; int i = 0;
for (const auto& particle : partctrl->particles) for (const auto& particle : partctrl->particles)
{ {
if (i++ >= particledata->activeCount) if (i++ >= particledata->mActiveCount)
break; break;
if (particle.lifespan <= 0) if (particle.lifespan <= 0)
@ -1165,8 +1165,8 @@ namespace NifOsg
created->setAlphaRange(osgParticle::rangef(1.f, 1.f)); created->setAlphaRange(osgParticle::rangef(1.f, 1.f));
float size = partctrl->size; float size = partctrl->size;
if (particle.vertex < particledata->sizes.size()) if (particle.vertex < particledata->mSizes.size())
size *= particledata->sizes[particle.vertex]; size *= particledata->mSizes[particle.vertex];
created->setSizeRange(osgParticle::rangef(size, size)); created->setSizeRange(osgParticle::rangef(size, size));
box.expandBy(osg::BoundingSphere(position, size)); box.expandBy(osg::BoundingSphere(position, size));
@ -1394,8 +1394,8 @@ namespace NifOsg
if (!skin->mData.empty()) if (!skin->mData.empty())
{ {
data = skin->mData.getPtr(); data = skin->mData.getPtr();
if (!data->partitions.empty()) if (!data->mPartitions.empty())
partitions = data->partitions.getPtr(); partitions = data->mPartitions.getPtr();
} }
if (!partitions && !skin->mPartitions.empty()) if (!partitions && !skin->mPartitions.empty())
partitions = skin->mPartitions.getPtr(); partitions = skin->mPartitions.getPtr();
@ -1556,14 +1556,9 @@ namespace NifOsg
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->name); std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->name);
SceneUtil::RigGeometry::BoneInfluence influence; SceneUtil::RigGeometry::BoneInfluence influence;
const std::vector<Nif::NiSkinData::VertWeight>& weights = data->bones[i].weights; influence.mWeights = data->mBones[i].mWeights;
for (size_t j = 0; j < weights.size(); j++) influence.mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
{ influence.mBoundSphere = data->mBones[i].mBoundSphere;
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);
map->mData.emplace_back(boneName, influence); map->mData.emplace_back(boneName, influence);
} }