mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-04 03:40:14 +00:00
Merge branch 'loadBsTriShape' into 'master'
Load BSTriShape NIF nodes See merge request OpenMW/openmw!3099
This commit is contained in:
commit
81f8d16982
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)
|
||||
{
|
||||
unsigned int num = nif->getUInt();
|
||||
data.resize(num);
|
||||
for (auto& partition : data)
|
||||
nif->read(mPartitionNum);
|
||||
mPartitions.resize(mPartitionNum);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -426,6 +438,12 @@ namespace Nif
|
||||
nif->getChar(); // LOD level
|
||||
nif->getBoolean(); // Global VB
|
||||
}
|
||||
|
||||
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_SSE)
|
||||
{
|
||||
mVertexDesc.read(nif);
|
||||
nif->readVector(trueTriangles, numTriangles * 3);
|
||||
}
|
||||
}
|
||||
|
||||
void NiMorphData::read(NIFStream* nif)
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "nifkey.hpp"
|
||||
#include "niftypes.hpp" // Transformation
|
||||
#include "recordptr.hpp"
|
||||
#include <components/nif/node.hpp>
|
||||
|
||||
namespace Nif
|
||||
{
|
||||
@ -218,10 +219,18 @@ namespace Nif
|
||||
std::vector<float> weights;
|
||||
std::vector<std::vector<unsigned short>> strips;
|
||||
std::vector<unsigned short> triangles;
|
||||
std::vector<unsigned short> trueTriangles;
|
||||
std::vector<char> boneIndices;
|
||||
BSVertexDesc mVertexDesc;
|
||||
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;
|
||||
};
|
||||
|
@ -191,6 +191,7 @@ namespace Nif
|
||||
{ "BSMultiBoundOBB", &construct<BSMultiBoundOBB, RC_BSMultiBoundOBB> },
|
||||
{ "BSMultiBoundSphere", &construct<BSMultiBoundSphere, RC_BSMultiBoundSphere> },
|
||||
{ "BSInvMarker", &construct<BSInvMarker, RC_BSInvMarker> },
|
||||
{ "BSTriShape", &construct<BSTriShape, RC_BSTriShape> },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,9 @@ namespace Nif
|
||||
{
|
||||
BETHVER_FO3 = 34, // Fallout 3
|
||||
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
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <components/files/istreamptr.hpp>
|
||||
#include <components/misc/endianness.hpp>
|
||||
#include <components/misc/float16.hpp>
|
||||
|
||||
#include <osg/Quat>
|
||||
#include <osg/Vec3f>
|
||||
@ -24,10 +25,16 @@ namespace Nif
|
||||
|
||||
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>
|
||||
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));
|
||||
if (pIStream->bad())
|
||||
throw std::runtime_error("Failed to read little endian typed (" + std::string(typeid(T).name())
|
||||
@ -40,7 +47,7 @@ namespace Nif
|
||||
template <typename T>
|
||||
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));
|
||||
if (pIStream->bad())
|
||||
throw std::runtime_error(
|
||||
@ -81,6 +88,8 @@ namespace Nif
|
||||
data = readLittleEndianType<T>(inp);
|
||||
}
|
||||
|
||||
void read(osg::Vec3f& data) { readLittleEndianBufferOfType<3, float>(inp, data._v); }
|
||||
|
||||
template <class T>
|
||||
T get()
|
||||
{
|
||||
@ -125,6 +134,7 @@ namespace Nif
|
||||
return vec;
|
||||
}
|
||||
|
||||
// DEPRECATED: Use read() whenever relevant
|
||||
osg::Vec3f getVector3()
|
||||
{
|
||||
osg::Vec3f vec;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "node.hpp"
|
||||
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
#include "data.hpp"
|
||||
#include "exception.hpp"
|
||||
@ -18,8 +19,7 @@ namespace Nif
|
||||
break;
|
||||
case SPHERE_BV:
|
||||
{
|
||||
sphere.center = nif->getVector3();
|
||||
sphere.radius = nif->getFloat();
|
||||
sphere.read(nif);
|
||||
break;
|
||||
}
|
||||
case BOX_BV:
|
||||
@ -334,4 +334,153 @@ namespace Nif
|
||||
NiNode::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
|
||||
#define OPENMW_COMPONENTS_NIF_NODE_HPP
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <osg/Plane>
|
||||
@ -29,6 +30,7 @@ namespace Nif
|
||||
{
|
||||
osg::Vec3f center;
|
||||
float radius{ 0.f };
|
||||
void read(NIFStream* nif);
|
||||
};
|
||||
|
||||
struct NiBoxBV
|
||||
@ -300,5 +302,80 @@ namespace Nif
|
||||
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
|
||||
#endif
|
||||
|
@ -163,6 +163,7 @@ namespace Nif
|
||||
RC_BSMultiBoundOBB,
|
||||
RC_BSMultiBoundSphere,
|
||||
RC_BSInvMarker,
|
||||
RC_BSTriShape,
|
||||
};
|
||||
|
||||
/// Base class for all records
|
||||
|
Loading…
x
Reference in New Issue
Block a user