|
|
|
@ -33,13 +33,33 @@ void NiSkinInstance::post(NIFFile *nif)
|
|
|
|
|
|
|
|
|
|
void NiGeometryData::read(NIFStream *nif)
|
|
|
|
|
{
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,114))
|
|
|
|
|
nif->getInt(); // Group ID. (Almost?) always 0.
|
|
|
|
|
|
|
|
|
|
int verts = nif->getUShort();
|
|
|
|
|
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0))
|
|
|
|
|
nif->skip(2); // Keep flags and compress flags
|
|
|
|
|
|
|
|
|
|
if (nif->getBoolean())
|
|
|
|
|
nif->getVector3s(vertices, verts);
|
|
|
|
|
|
|
|
|
|
unsigned int dataFlags = 0;
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0))
|
|
|
|
|
dataFlags = nif->getUShort();
|
|
|
|
|
|
|
|
|
|
if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3)
|
|
|
|
|
nif->getUInt(); // Material CRC
|
|
|
|
|
|
|
|
|
|
if (nif->getBoolean())
|
|
|
|
|
{
|
|
|
|
|
nif->getVector3s(normals, verts);
|
|
|
|
|
if (dataFlags & 0x1000)
|
|
|
|
|
{
|
|
|
|
|
nif->getVector3s(tangents, verts);
|
|
|
|
|
nif->getVector3s(bitangents, verts);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
center = nif->getVector3();
|
|
|
|
|
radius = nif->getFloat();
|
|
|
|
@ -47,14 +67,27 @@ void NiGeometryData::read(NIFStream *nif)
|
|
|
|
|
if (nif->getBoolean())
|
|
|
|
|
nif->getVector4s(colors, verts);
|
|
|
|
|
|
|
|
|
|
// Only the first 6 bits are used as a count. I think the rest are
|
|
|
|
|
// flags of some sort.
|
|
|
|
|
unsigned int numUVs = dataFlags;
|
|
|
|
|
if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0))
|
|
|
|
|
{
|
|
|
|
|
numUVs = nif->getUShort();
|
|
|
|
|
// In Morrowind this field only corresponds to the number of UV sets.
|
|
|
|
|
// NifTools research is inaccurate.
|
|
|
|
|
int uvs = nif->getUShort();
|
|
|
|
|
if (nif->getVersion() > NIFFile::NIFVersion::VER_MW)
|
|
|
|
|
numUVs &= 0x3f;
|
|
|
|
|
}
|
|
|
|
|
if (nif->getVersion() == NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() > 0)
|
|
|
|
|
numUVs &= 0x1;
|
|
|
|
|
|
|
|
|
|
if(nif->getInt())
|
|
|
|
|
bool hasUVs = true;
|
|
|
|
|
if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW)
|
|
|
|
|
hasUVs = nif->getBoolean();
|
|
|
|
|
if (hasUVs)
|
|
|
|
|
{
|
|
|
|
|
uvlist.resize(uvs);
|
|
|
|
|
for(int i = 0;i < uvs;i++)
|
|
|
|
|
uvlist.resize(numUVs);
|
|
|
|
|
for (unsigned int i = 0; i < numUVs; i++)
|
|
|
|
|
{
|
|
|
|
|
nif->getVector2s(uvlist[i], verts);
|
|
|
|
|
// flip the texture coordinates to convert them to the OpenGL convention of bottom-left image origin
|
|
|
|
@ -64,6 +97,12 @@ void NiGeometryData::read(NIFStream *nif)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0))
|
|
|
|
|
nif->getUShort(); // Consistency flags
|
|
|
|
|
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(20,0,0,4))
|
|
|
|
|
nif->skip(4); // Additional data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NiTriShapeData::read(NIFStream *nif)
|
|
|
|
@ -75,13 +114,17 @@ void NiTriShapeData::read(NIFStream *nif)
|
|
|
|
|
// We have three times as many vertices as triangles, so this
|
|
|
|
|
// is always equal to tris*3.
|
|
|
|
|
int cnt = nif->getInt();
|
|
|
|
|
bool hasTriangles = true;
|
|
|
|
|
if (nif->getVersion() > NIFFile::NIFVersion::VER_OB_OLD)
|
|
|
|
|
hasTriangles = nif->getBoolean();
|
|
|
|
|
if (hasTriangles)
|
|
|
|
|
nif->getUShorts(triangles, cnt);
|
|
|
|
|
|
|
|
|
|
// Read the match list, which lists the vertices that are equal to
|
|
|
|
|
// vertices. We don't actually need need this for anything, so
|
|
|
|
|
// just skip it.
|
|
|
|
|
int verts = nif->getUShort();
|
|
|
|
|
for(int i=0;i < verts;i++)
|
|
|
|
|
unsigned short verts = nif->getUShort();
|
|
|
|
|
for (unsigned short i=0; i < verts; i++)
|
|
|
|
|
{
|
|
|
|
|
// Number of vertices matching vertex 'i'
|
|
|
|
|
int num = nif->getUShort();
|
|
|
|
@ -101,7 +144,11 @@ void NiTriStripsData::read(NIFStream *nif)
|
|
|
|
|
std::vector<unsigned short> lengths;
|
|
|
|
|
nif->getUShorts(lengths, numStrips);
|
|
|
|
|
|
|
|
|
|
if (!numStrips)
|
|
|
|
|
// "Has Strips" flag. Exceptionally useful.
|
|
|
|
|
bool hasStrips = false;
|
|
|
|
|
if (nif->getVersion() > NIFFile::NIFVersion::VER_OB_OLD)
|
|
|
|
|
hasStrips = nif->getBoolean();
|
|
|
|
|
if (!hasStrips || !numStrips)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
strips.resize(numStrips);
|
|
|
|
@ -140,27 +187,37 @@ void NiAutoNormalParticlesData::read(NIFStream *nif)
|
|
|
|
|
NiGeometryData::read(nif);
|
|
|
|
|
|
|
|
|
|
// Should always match the number of vertices
|
|
|
|
|
if (nif->getVersion() <= NIFFile::NIFVersion::VER_MW)
|
|
|
|
|
numParticles = nif->getUShort();
|
|
|
|
|
|
|
|
|
|
particleRadius = nif->getFloat();
|
|
|
|
|
if (nif->getVersion() <= NIFStream::generateVersion(10,0,1,0))
|
|
|
|
|
std::fill(particleRadii.begin(), particleRadii.end(), nif->getFloat());
|
|
|
|
|
else if (nif->getBoolean())
|
|
|
|
|
nif->getFloats(particleRadii, vertices.size());
|
|
|
|
|
activeCount = nif->getUShort();
|
|
|
|
|
|
|
|
|
|
if (nif->getBoolean())
|
|
|
|
|
{
|
|
|
|
|
// Particle sizes
|
|
|
|
|
if (nif->getBoolean())
|
|
|
|
|
nif->getFloats(sizes, vertices.size());
|
|
|
|
|
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10,0,1,0) && nif->getBoolean())
|
|
|
|
|
nif->getQuaternions(rotations, vertices.size());
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(20,0,0,4))
|
|
|
|
|
{
|
|
|
|
|
if (nif->getBoolean())
|
|
|
|
|
nif->getFloats(rotationAngles, vertices.size());
|
|
|
|
|
if (nif->getBoolean())
|
|
|
|
|
nif->getVector3s(rotationAxes, vertices.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NiRotatingParticlesData::read(NIFStream *nif)
|
|
|
|
|
{
|
|
|
|
|
NiAutoNormalParticlesData::read(nif);
|
|
|
|
|
|
|
|
|
|
if (nif->getBoolean())
|
|
|
|
|
{
|
|
|
|
|
// Rotation quaternions.
|
|
|
|
|
if (nif->getVersion() <= NIFStream::generateVersion(4,2,2,0) && nif->getBoolean())
|
|
|
|
|
nif->getQuaternions(rotations, vertices.size());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NiPosData::read(NIFStream *nif)
|
|
|
|
@ -188,12 +245,27 @@ void NiPixelData::read(NIFStream *nif)
|
|
|
|
|
{
|
|
|
|
|
fmt = (Format)nif->getUInt();
|
|
|
|
|
|
|
|
|
|
if (nif->getVersion() < NIFStream::generateVersion(10,4,0,2))
|
|
|
|
|
{
|
|
|
|
|
for (unsigned int i = 0; i < 4; ++i)
|
|
|
|
|
colorMask[i] = nif->getUInt();
|
|
|
|
|
bpp = nif->getUInt();
|
|
|
|
|
nif->skip(8); // "Old Fast Compare". Whatever that means.
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0))
|
|
|
|
|
pixelTiling = nif->getUInt();
|
|
|
|
|
}
|
|
|
|
|
else // TODO: see if anything from here needs to be implemented
|
|
|
|
|
{
|
|
|
|
|
bpp = nif->getChar();
|
|
|
|
|
nif->skip(4); // Renderer hint
|
|
|
|
|
nif->skip(4); // Extra data
|
|
|
|
|
nif->skip(4); // Flags
|
|
|
|
|
pixelTiling = nif->getUInt();
|
|
|
|
|
if (nif->getVersion() >= NIFStream::generateVersion(20,3,0,4))
|
|
|
|
|
sRGB = nif->getBoolean();
|
|
|
|
|
nif->skip(4*10); // Channel data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 8 bytes of "Old Fast Compare". Whatever that means.
|
|
|
|
|
nif->skip(8);
|
|
|
|
|
palette.read(nif);
|
|
|
|
|
|
|
|
|
|
numberOfMipmaps = nif->getUInt();
|
|
|
|
@ -213,8 +285,10 @@ void NiPixelData::read(NIFStream *nif)
|
|
|
|
|
|
|
|
|
|
// Read the data
|
|
|
|
|
unsigned int numPixels = nif->getUInt();
|
|
|
|
|
if (numPixels)
|
|
|
|
|
nif->getUChars(data, numPixels);
|
|
|
|
|
bool hasFaces = nif->getVersion() >= NIFStream::generateVersion(10,4,0,2);
|
|
|
|
|
unsigned int numFaces = hasFaces ? nif->getUInt() : 1;
|
|
|
|
|
if (numPixels && numFaces)
|
|
|
|
|
nif->getUChars(data, numPixels * numFaces);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NiPixelData::post(NIFFile *nif)
|
|
|
|
@ -249,6 +323,10 @@ void NiSkinData::read(NIFStream *nif)
|
|
|
|
|
if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW && nif->getVersion() <= NIFStream::generateVersion(10,1,0,0))
|
|
|
|
|
nif->skip(4); // NiSkinPartition link
|
|
|
|
|
|
|
|
|
|
// Has vertex weights flag
|
|
|
|
|
if (nif->getVersion() > NIFStream::generateVersion(4,2,1,0) && !nif->getBoolean())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bones.resize(boneNum);
|
|
|
|
|
for (BoneInfo &bi : bones)
|
|
|
|
|
{
|
|
|
|
@ -272,7 +350,7 @@ void NiMorphData::read(NIFStream *nif)
|
|
|
|
|
{
|
|
|
|
|
int morphCount = nif->getInt();
|
|
|
|
|
int vertCount = nif->getInt();
|
|
|
|
|
/*relative targets?*/nif->getChar();
|
|
|
|
|
nif->getChar(); // Relative targets, always 1
|
|
|
|
|
|
|
|
|
|
mMorphs.resize(morphCount);
|
|
|
|
|
for(int i = 0;i < morphCount;i++)
|
|
|
|
@ -290,6 +368,7 @@ void NiKeyframeData::read(NIFStream *nif)
|
|
|
|
|
if(mRotations->mInterpolationType == InterpolationType_XYZ)
|
|
|
|
|
{
|
|
|
|
|
//Chomp unused float
|
|
|
|
|
if (nif->getVersion() <= NIFStream::generateVersion(10,1,0,0))
|
|
|
|
|
nif->getFloat();
|
|
|
|
|
mXRotations = std::make_shared<FloatKeyMap>();
|
|
|
|
|
mYRotations = std::make_shared<FloatKeyMap>();
|
|
|
|
|