mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-26 23:10:24 +00:00
Merge branch 'loadBsTriShape' into 'master'
Load BSTriShape NIF nodes See merge request OpenMW/openmw!3099
This commit is contained in:
commit
81f8d16982
9 changed files with 287 additions and 9 deletions
11
components/misc/float16.hpp
Normal file
11
components/misc/float16.hpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_MISC_FLOAT16_HPP
|
||||||
|
#define OPENMW_COMPONENTS_MISC_FLOAT16_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Misc
|
||||||
|
{
|
||||||
|
using float16_t = std::uint16_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -372,9 +372,21 @@ namespace Nif
|
||||||
|
|
||||||
void NiSkinPartition::read(NIFStream* nif)
|
void NiSkinPartition::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
unsigned int num = nif->getUInt();
|
nif->read(mPartitionNum);
|
||||||
data.resize(num);
|
mPartitions.resize(mPartitionNum);
|
||||||
for (auto& partition : data)
|
|
||||||
|
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
|
||||||
|
{
|
||||||
|
nif->read(mDataSize);
|
||||||
|
nif->read(mVertexSize);
|
||||||
|
mVertexDesc.read(nif);
|
||||||
|
|
||||||
|
mVertexData.resize(mDataSize / mVertexSize);
|
||||||
|
for (auto& vertexData : mVertexData)
|
||||||
|
vertexData.read(nif, mVertexDesc.mFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& partition : mPartitions)
|
||||||
partition.read(nif);
|
partition.read(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +438,12 @@ namespace Nif
|
||||||
nif->getChar(); // LOD level
|
nif->getChar(); // LOD level
|
||||||
nif->getBoolean(); // Global VB
|
nif->getBoolean(); // Global VB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
|
||||||
|
{
|
||||||
|
mVertexDesc.read(nif);
|
||||||
|
nif->readVector(trueTriangles, numTriangles * 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiMorphData::read(NIFStream* nif)
|
void NiMorphData::read(NIFStream* nif)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "nifkey.hpp"
|
#include "nifkey.hpp"
|
||||||
#include "niftypes.hpp" // Transformation
|
#include "niftypes.hpp" // Transformation
|
||||||
#include "recordptr.hpp"
|
#include "recordptr.hpp"
|
||||||
|
#include <components/nif/node.hpp>
|
||||||
|
|
||||||
namespace Nif
|
namespace Nif
|
||||||
{
|
{
|
||||||
|
@ -218,10 +219,18 @@ namespace Nif
|
||||||
std::vector<float> weights;
|
std::vector<float> weights;
|
||||||
std::vector<std::vector<unsigned short>> strips;
|
std::vector<std::vector<unsigned short>> strips;
|
||||||
std::vector<unsigned short> triangles;
|
std::vector<unsigned short> triangles;
|
||||||
|
std::vector<unsigned short> trueTriangles;
|
||||||
std::vector<char> boneIndices;
|
std::vector<char> boneIndices;
|
||||||
|
BSVertexDesc mVertexDesc;
|
||||||
void read(NIFStream* nif);
|
void read(NIFStream* nif);
|
||||||
};
|
};
|
||||||
std::vector<Partition> data;
|
unsigned int mPartitionNum;
|
||||||
|
std::vector<Partition> mPartitions;
|
||||||
|
|
||||||
|
unsigned int mDataSize;
|
||||||
|
unsigned int mVertexSize;
|
||||||
|
BSVertexDesc mVertexDesc;
|
||||||
|
std::vector<BSVertexData> mVertexData;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -191,6 +191,7 @@ namespace Nif
|
||||||
{ "BSMultiBoundOBB", &construct<BSMultiBoundOBB, RC_BSMultiBoundOBB> },
|
{ "BSMultiBoundOBB", &construct<BSMultiBoundOBB, RC_BSMultiBoundOBB> },
|
||||||
{ "BSMultiBoundSphere", &construct<BSMultiBoundSphere, RC_BSMultiBoundSphere> },
|
{ "BSMultiBoundSphere", &construct<BSMultiBoundSphere, RC_BSMultiBoundSphere> },
|
||||||
{ "BSInvMarker", &construct<BSInvMarker, RC_BSInvMarker> },
|
{ "BSInvMarker", &construct<BSInvMarker, RC_BSInvMarker> },
|
||||||
|
{ "BSTriShape", &construct<BSTriShape, RC_BSTriShape> },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,9 @@ namespace Nif
|
||||||
{
|
{
|
||||||
BETHVER_FO3 = 34, // Fallout 3
|
BETHVER_FO3 = 34, // Fallout 3
|
||||||
BETHVER_SKY = 83, // Skyrim
|
BETHVER_SKY = 83, // Skyrim
|
||||||
BETHVER_FO4 = 130 // Fallout 4
|
BETHVER_SSE = 100, // Skyrim SE
|
||||||
|
BETHVER_FO4 = 130, // Fallout 4
|
||||||
|
BETHVER_F76 = 155 // Fallout 76
|
||||||
};
|
};
|
||||||
|
|
||||||
/// File version, user version, Bethesda version
|
/// File version, user version, Bethesda version
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <components/files/istreamptr.hpp>
|
#include <components/files/istreamptr.hpp>
|
||||||
#include <components/misc/endianness.hpp>
|
#include <components/misc/endianness.hpp>
|
||||||
|
#include <components/misc/float16.hpp>
|
||||||
|
|
||||||
#include <osg/Quat>
|
#include <osg/Quat>
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
@ -24,10 +25,16 @@ namespace Nif
|
||||||
|
|
||||||
class Reader;
|
class Reader;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct is_arithmetic
|
||||||
|
: std::integral_constant<bool, std::is_arithmetic_v<T> || std::is_same<T, Misc::float16_t>::value>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <std::size_t numInstances, typename T>
|
template <std::size_t numInstances, typename T>
|
||||||
inline void readLittleEndianBufferOfType(Files::IStreamPtr& pIStream, T* dest)
|
inline void readLittleEndianBufferOfType(Files::IStreamPtr& pIStream, T* dest)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic_v<T>, "Buffer element type is not arithmetic");
|
static_assert(is_arithmetic<T>(), "Buffer element type is not arithmetic");
|
||||||
pIStream->read((char*)dest, numInstances * sizeof(T));
|
pIStream->read((char*)dest, numInstances * sizeof(T));
|
||||||
if (pIStream->bad())
|
if (pIStream->bad())
|
||||||
throw std::runtime_error("Failed to read little endian typed (" + std::string(typeid(T).name())
|
throw std::runtime_error("Failed to read little endian typed (" + std::string(typeid(T).name())
|
||||||
|
@ -40,7 +47,7 @@ namespace Nif
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr& pIStream, T* dest, std::size_t numInstances)
|
inline void readLittleEndianDynamicBufferOfType(Files::IStreamPtr& pIStream, T* dest, std::size_t numInstances)
|
||||||
{
|
{
|
||||||
static_assert(std::is_arithmetic_v<T>, "Buffer element type is not arithmetic");
|
static_assert(is_arithmetic<T>(), "Buffer element type is not arithmetic");
|
||||||
pIStream->read((char*)dest, numInstances * sizeof(T));
|
pIStream->read((char*)dest, numInstances * sizeof(T));
|
||||||
if (pIStream->bad())
|
if (pIStream->bad())
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
|
@ -81,6 +88,8 @@ namespace Nif
|
||||||
data = readLittleEndianType<T>(inp);
|
data = readLittleEndianType<T>(inp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void read(osg::Vec3f& data) { readLittleEndianBufferOfType<3, float>(inp, data._v); }
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T get()
|
T get()
|
||||||
{
|
{
|
||||||
|
@ -125,6 +134,7 @@ namespace Nif
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED: Use read() whenever relevant
|
||||||
osg::Vec3f getVector3()
|
osg::Vec3f getVector3()
|
||||||
{
|
{
|
||||||
osg::Vec3f vec;
|
osg::Vec3f vec;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
|
|
||||||
#include <components/misc/strings/algorithm.hpp>
|
#include <components/misc/strings/algorithm.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
#include "exception.hpp"
|
#include "exception.hpp"
|
||||||
|
@ -18,8 +19,7 @@ namespace Nif
|
||||||
break;
|
break;
|
||||||
case SPHERE_BV:
|
case SPHERE_BV:
|
||||||
{
|
{
|
||||||
sphere.center = nif->getVector3();
|
sphere.read(nif);
|
||||||
sphere.radius = nif->getFloat();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BOX_BV:
|
case BOX_BV:
|
||||||
|
@ -334,4 +334,153 @@ namespace Nif
|
||||||
NiNode::post(nif);
|
NiNode::post(nif);
|
||||||
mMultiBound.post(nif);
|
mMultiBound.post(nif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BSTriShape::read(NIFStream* nif)
|
||||||
|
{
|
||||||
|
Node::read(nif);
|
||||||
|
mBoundingSphere.read(nif);
|
||||||
|
|
||||||
|
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76)
|
||||||
|
{
|
||||||
|
nif->readVector(mBoundMinMax, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSkin.read(nif);
|
||||||
|
mShaderProperty.read(nif);
|
||||||
|
mAlphaProperty.read(nif);
|
||||||
|
|
||||||
|
mVertDesc.read(nif);
|
||||||
|
|
||||||
|
unsigned int triNum;
|
||||||
|
if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)
|
||||||
|
{
|
||||||
|
triNum = nif->get<unsigned short>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nif->read(triNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short vertNum;
|
||||||
|
nif->read(vertNum);
|
||||||
|
nif->read(mDataSize);
|
||||||
|
|
||||||
|
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
|
||||||
|
{
|
||||||
|
mVertData.resize(vertNum);
|
||||||
|
for (auto& vertex : mVertData)
|
||||||
|
vertex.read(nif, mVertDesc.mFlags);
|
||||||
|
}
|
||||||
|
else if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4)
|
||||||
|
{
|
||||||
|
throw Nif::Exception("FO4 BSTriShape is not supported yet: ", nif->getFile().getFilename());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDataSize > 0)
|
||||||
|
{
|
||||||
|
mTriangles.resize(triNum * 3);
|
||||||
|
nif->readVector(mTriangles, triNum * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
|
||||||
|
{
|
||||||
|
nif->read(mParticleDataSize);
|
||||||
|
if (mParticleDataSize > 0)
|
||||||
|
{
|
||||||
|
throw Nif::Exception("Unhandled Particle Data in BSTriShape: ", nif->getFile().getFilename());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSTriShape::post(Reader& nif)
|
||||||
|
{
|
||||||
|
Node::post(nif);
|
||||||
|
mSkin.post(nif);
|
||||||
|
mShaderProperty.post(nif);
|
||||||
|
mAlphaProperty.post(nif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSVertexDesc::read(NIFStream* nif)
|
||||||
|
{
|
||||||
|
uint64_t data;
|
||||||
|
nif->read(data);
|
||||||
|
mVertexDataSize = (data & 0xF) >> 0x00;
|
||||||
|
mDynamicVertexSize = (data & 0xF0) >> 0x04;
|
||||||
|
mUV1Offset = (data & 0xF00) >> 0x08;
|
||||||
|
mUV2Offset = (data & 0xF000) >> 0x0C;
|
||||||
|
mNormalOffset = (data & 0xF0000) >> 0x10;
|
||||||
|
mTangentOffset = (data & 0xF00000) >> 0x14;
|
||||||
|
mColorOffset = (data & 0xF000000) >> 0x18;
|
||||||
|
mSkinningDataOffset = (data & 0xF0000000) >> 0x1C;
|
||||||
|
mLandscapeDataOffset = (data & 0xF00000000) >> 0x20;
|
||||||
|
mEyeDataOffset = (data & 0xF000000000) >> 0x24;
|
||||||
|
mFlags = (data & 0xFFF00000000000) >> 0x2C;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NiBoundingVolume::NiSphereBV::read(NIFStream* nif)
|
||||||
|
{
|
||||||
|
nif->read(center);
|
||||||
|
nif->read(radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSVertexData::read(NIFStream* nif, uint16_t flags)
|
||||||
|
{
|
||||||
|
uint16_t vertexFlag = flags & BSVertexDesc::VertexAttribute::Vertex;
|
||||||
|
uint16_t tangentsFlag = flags & BSVertexDesc::VertexAttribute::Tangents;
|
||||||
|
uint16_t UVsFlag = flags & BSVertexDesc::VertexAttribute::UVs;
|
||||||
|
uint16_t normalsFlag = flags & BSVertexDesc::VertexAttribute::Normals;
|
||||||
|
|
||||||
|
if (vertexFlag == BSVertexDesc::VertexAttribute::Vertex)
|
||||||
|
{
|
||||||
|
nif->read(mVertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vertexFlag | tangentsFlag)
|
||||||
|
== (BSVertexDesc::VertexAttribute::Vertex | BSVertexDesc::VertexAttribute::Tangents))
|
||||||
|
{
|
||||||
|
nif->read(mBitangentX);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vertexFlag | tangentsFlag) == BSVertexDesc::VertexAttribute::Vertex)
|
||||||
|
{
|
||||||
|
nif->read(mUnusedW);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UVsFlag == BSVertexDesc::VertexAttribute::UVs)
|
||||||
|
{
|
||||||
|
nif->readArray(mUV);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalsFlag)
|
||||||
|
{
|
||||||
|
nif->readArray(mNormal);
|
||||||
|
|
||||||
|
nif->read(mBitangentY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((normalsFlag | tangentsFlag)
|
||||||
|
== (BSVertexDesc::VertexAttribute::Normals | BSVertexDesc::VertexAttribute::Tangents))
|
||||||
|
{
|
||||||
|
nif->readArray(mTangent);
|
||||||
|
|
||||||
|
nif->read(mBitangentZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & BSVertexDesc::VertexAttribute::Vertex_Colors)
|
||||||
|
{
|
||||||
|
nif->readArray(mVertColors);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & BSVertexDesc::VertexAttribute::Skinned)
|
||||||
|
{
|
||||||
|
nif->readArray(mBoneWeights);
|
||||||
|
nif->readArray(mBoneIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & BSVertexDesc::VertexAttribute::Eye_Data)
|
||||||
|
{
|
||||||
|
throw Nif::Exception("Unhandled Eye Data in BSTriShape: ", nif->getFile().getFilename());
|
||||||
|
nif->read(mEyeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef OPENMW_COMPONENTS_NIF_NODE_HPP
|
#ifndef OPENMW_COMPONENTS_NIF_NODE_HPP
|
||||||
#define OPENMW_COMPONENTS_NIF_NODE_HPP
|
#define OPENMW_COMPONENTS_NIF_NODE_HPP
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <osg/Plane>
|
#include <osg/Plane>
|
||||||
|
@ -29,6 +30,7 @@ namespace Nif
|
||||||
{
|
{
|
||||||
osg::Vec3f center;
|
osg::Vec3f center;
|
||||||
float radius{ 0.f };
|
float radius{ 0.f };
|
||||||
|
void read(NIFStream* nif);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NiBoxBV
|
struct NiBoxBV
|
||||||
|
@ -300,5 +302,80 @@ namespace Nif
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BSVertexDesc
|
||||||
|
{
|
||||||
|
unsigned char mVertexDataSize;
|
||||||
|
unsigned char mDynamicVertexSize;
|
||||||
|
unsigned char mUV1Offset;
|
||||||
|
unsigned char mUV2Offset;
|
||||||
|
unsigned char mNormalOffset;
|
||||||
|
unsigned char mTangentOffset;
|
||||||
|
unsigned char mColorOffset;
|
||||||
|
unsigned char mSkinningDataOffset;
|
||||||
|
unsigned char mLandscapeDataOffset;
|
||||||
|
unsigned char mEyeDataOffset;
|
||||||
|
unsigned short mFlags;
|
||||||
|
|
||||||
|
enum VertexAttribute
|
||||||
|
{
|
||||||
|
Vertex = 0x0001,
|
||||||
|
UVs = 0x0002,
|
||||||
|
UVs_2 = 0x0004,
|
||||||
|
Normals = 0x0008,
|
||||||
|
Tangents = 0x0010,
|
||||||
|
Vertex_Colors = 0x0020,
|
||||||
|
Skinned = 0x0040,
|
||||||
|
Land_Data = 0x0080,
|
||||||
|
Eye_Data = 0x0100,
|
||||||
|
Instance = 0x0200,
|
||||||
|
Full_Precision = 0x0400,
|
||||||
|
};
|
||||||
|
|
||||||
|
void read(NIFStream* nif);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BSVertexData
|
||||||
|
{
|
||||||
|
osg::Vec3f mVertex;
|
||||||
|
float mBitangentX;
|
||||||
|
unsigned int mUnusedW;
|
||||||
|
std::array<Misc::float16_t, 2> mUV;
|
||||||
|
|
||||||
|
std::array<char, 3> mNormal;
|
||||||
|
char mBitangentY;
|
||||||
|
std::array<char, 3> mTangent;
|
||||||
|
char mBitangentZ;
|
||||||
|
std::array<char, 4> mVertColors;
|
||||||
|
std::array<Misc::float16_t, 4> mBoneWeights;
|
||||||
|
std::array<char, 4> mBoneIndices;
|
||||||
|
float mEyeData;
|
||||||
|
|
||||||
|
void read(NIFStream* nif, uint16_t flags);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BSTriShape : Node
|
||||||
|
{
|
||||||
|
NiBoundingVolume::NiSphereBV mBoundingSphere;
|
||||||
|
std::vector<float> mBoundMinMax;
|
||||||
|
|
||||||
|
NiSkinInstancePtr mSkin;
|
||||||
|
BSShaderPropertyPtr mShaderProperty;
|
||||||
|
NiAlphaPropertyPtr mAlphaProperty;
|
||||||
|
|
||||||
|
BSVertexDesc mVertDesc;
|
||||||
|
|
||||||
|
unsigned int mDataSize;
|
||||||
|
unsigned int mParticleDataSize;
|
||||||
|
|
||||||
|
std::vector<BSVertexData> mVertData;
|
||||||
|
std::vector<unsigned short> mTriangles;
|
||||||
|
std::vector<unsigned short> mParticleTriangles;
|
||||||
|
std::vector<osg::Vec3f> mParticleVerts;
|
||||||
|
std::vector<osg::Vec3f> mParticleNormals;
|
||||||
|
|
||||||
|
void read(NIFStream* nif) override;
|
||||||
|
void post(Reader& nif) override;
|
||||||
|
};
|
||||||
|
|
||||||
} // Namespace
|
} // Namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -163,6 +163,7 @@ namespace Nif
|
||||||
RC_BSMultiBoundOBB,
|
RC_BSMultiBoundOBB,
|
||||||
RC_BSMultiBoundSphere,
|
RC_BSMultiBoundSphere,
|
||||||
RC_BSInvMarker,
|
RC_BSInvMarker,
|
||||||
|
RC_BSTriShape,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Base class for all records
|
/// Base class for all records
|
||||||
|
|
Loading…
Reference in a new issue