You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/components/nif/node.hpp

531 lines
13 KiB
C++

#ifndef OPENMW_COMPONENTS_NIF_NODE_HPP
#define OPENMW_COMPONENTS_NIF_NODE_HPP
#include <array>
#include <unordered_map>
#include <osg/Plane>
#include "base.hpp"
class btCollisionShape;
namespace Nif
{
struct NiNode;
struct BoundingVolume
{
enum Type : uint32_t
{
BASE_BV = 0xFFFFFFFF,
SPHERE_BV = 0,
BOX_BV = 1,
CAPSULE_BV = 2,
LOZENGE_BV = 3,
UNION_BV = 4,
HALFSPACE_BV = 5
};
struct NiBoxBV
{
osg::Vec3f mCenter;
Matrix3 mAxes;
osg::Vec3f mExtents;
};
struct NiCapsuleBV
{
osg::Vec3f mCenter, mAxis;
float mExtent{ 0.f }, mRadius{ 0.f };
};
struct NiLozengeBV
{
float mRadius{ 0.f }, mExtent0{ 0.f }, mExtent1{ 0.f };
osg::Vec3f mCenter, mAxis0, mAxis1;
};
struct NiHalfSpaceBV
{
osg::Plane mPlane;
osg::Vec3f mOrigin;
};
uint32_t mType{ BASE_BV };
osg::BoundingSpheref mSphere;
NiBoxBV mBox;
NiCapsuleBV mCapsule;
NiLozengeBV mLozenge;
std::vector<BoundingVolume> mChildren;
NiHalfSpaceBV mHalfSpace;
void read(NIFStream* nif);
};
struct NiSequenceStreamHelper : NiObjectNET
{
};
// NiAVObject is an object that is a part of the main NIF tree. It has
// a parent node (unless it's the root) and transformation relative to its parent.
struct NiAVObject : NiObjectNET
{
enum Flags
{
Flag_Hidden = 0x0001,
Flag_MeshCollision = 0x0002,
Flag_BBoxCollision = 0x0004,
Flag_ActiveCollision = 0x0020
};
// Node flags. Interpretation depends on the record type.
uint32_t mFlags;
NiTransform mTransform;
osg::Vec3f mVelocity;
NiPropertyList mProperties;
BoundingVolume mBounds;
NiCollisionObjectPtr mCollision;
// Parent nodes for the node. Only types derived from NiNode can be parents.
std::vector<NiNode*> mParents;
bool mIsBone{ false };
void read(NIFStream* nif) override;
void post(Reader& nif) override;
void setBone();
bool isHidden() const { return mFlags & Flag_Hidden; }
bool hasMeshCollision() const { return mFlags & Flag_MeshCollision; }
bool hasBBoxCollision() const { return mFlags & Flag_BBoxCollision; }
bool collisionActive() const { return mFlags & Flag_ActiveCollision; }
};
struct NiNode : NiAVObject
{
enum BSAnimFlags
{
AnimFlag_AutoPlay = 0x0020
};
enum BSParticleFlags
{
ParticleFlag_AutoPlay = 0x0020,
ParticleFlag_LocalSpace = 0x0080
};
NiAVObjectList mChildren;
NiAVObjectList mEffects;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct NiGeometry : NiAVObject
{
/* Possible flags:
0x40 - mesh has no vertex normals ?
Only flags included in 0x47 (ie. 0x01, 0x02, 0x04 and 0x40) have
been observed so far.
*/
struct MaterialData
{
std::vector<std::string> mNames;
std::vector<int> mExtra;
int32_t mActive{ -1 };
bool mNeedsUpdate{ false };
void read(NIFStream* nif);
};
NiGeometryDataPtr mData;
NiSkinInstancePtr mSkin;
MaterialData mMaterial;
BSShaderPropertyPtr mShaderProperty;
NiAlphaPropertyPtr mAlphaProperty;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
virtual std::unique_ptr<btCollisionShape> getCollisionShape() const
{
throw std::runtime_error("NiGeometry::getCollisionShape() called on base class");
}
};
// Abstract triangle-based geometry
struct NiTriBasedGeom : NiGeometry
{
};
struct NiTriShape : NiTriBasedGeom
{
std::unique_ptr<btCollisionShape> getCollisionShape() const override;
};
struct BSSegmentedTriShape : NiTriShape
{
struct SegmentData
{
uint8_t mFlags;
uint32_t mStartIndex;
uint32_t mNumTriangles;
void read(NIFStream* nif);
};
std::vector<SegmentData> mSegments;
void read(NIFStream* nif);
};
struct NiTriStrips : NiTriBasedGeom
{
std::unique_ptr<btCollisionShape> getCollisionShape() const override;
};
struct NiLines : NiTriBasedGeom
{
std::unique_ptr<btCollisionShape> getCollisionShape() const override;
};
struct NiParticles : NiGeometry
{
std::unique_ptr<btCollisionShape> getCollisionShape() const override;
};
struct BSLODTriShape : NiTriShape
{
std::array<uint32_t, 3> mLOD;
void read(NIFStream* nif) override;
};
struct NiCamera : NiAVObject
{
uint16_t mCameraFlags{ 0 };
// Camera frustum
float mLeft, mRight, mTop, mBottom, mNearDist, mFarDist;
bool mOrthographic{ false };
// Viewport
float mVLeft, mVRight, mVTop, mVBottom;
float mLODAdjust;
NiAVObjectPtr mScene;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
// A node used as the base to switch between child nodes, such as for LOD levels.
struct NiSwitchNode : NiNode
{
uint16_t mSwitchFlags;
uint32_t mInitialIndex;
void read(NIFStream* nif) override;
};
struct NiLODNode : NiSwitchNode
{
struct LODRange
{
float mMinRange;
float mMaxRange;
};
osg::Vec3f mLODCenter;
std::vector<LODRange> mLODLevels;
void read(NIFStream* nif) override;
};
struct NiFltAnimationNode : NiSwitchNode
{
enum Flags
{
Flag_Swing = 0x40
};
float mDuration;
void read(NIFStream* nif) override;
bool swing() const { return mFlags & Flag_Swing; }
};
// Abstract
struct NiAccumulator : Record
{
void read(NIFStream* nif) override {}
};
// Node children sorters
struct NiClusterAccumulator : NiAccumulator
{
};
struct NiAlphaAccumulator : NiClusterAccumulator
{
};
struct NiSortAdjustNode : NiNode
{
enum class SortingMode : uint32_t
{
Inherit,
Off,
Subsort,
};
SortingMode mMode;
NiAccumulatorPtr mSubSorter;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct NiBillboardNode : NiNode
{
int mMode;
void read(NIFStream* nif) override;
};
struct NiDefaultAVObjectPalette : Record
{
NiAVObjectPtr mScene;
std::unordered_map<std::string, NiAVObjectPtr> mObjects;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct BSTreeNode : NiNode
{
NiAVObjectList mBones1, mBones2;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct BSMultiBoundNode : NiNode
{
enum class BSCPCullingType : uint32_t
{
Normal,
AllPass,
AllFail,
IgnoreMultiBounds,
ForceMultiBoundsNoUpdate,
};
BSMultiBoundPtr mMultiBound;
BSCPCullingType mCullingType;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct BSVertexDesc
{
uint8_t mVertexDataSize;
uint8_t mDynamicVertexSize;
uint8_t mUV1Offset;
uint8_t mUV2Offset;
uint8_t mNormalOffset;
uint8_t mTangentOffset;
uint8_t mColorOffset;
uint8_t mSkinningDataOffset;
uint8_t mLandscapeDataOffset;
uint8_t mEyeDataOffset;
uint16_t 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::Vec4f mVertex; // Bitangent X is stored in the fourth component
std::array<Misc::float16_t, 4> mHalfVertex; // Ditto
std::array<Misc::float16_t, 2> mUV;
std::array<char, 4> mNormal; // Bitangent Y is stored in the fourth component
std::array<char, 4> mTangent; // Bitangent Z is stored in the fourth component
std::array<char, 4> mVertColor;
std::array<Misc::float16_t, 4> mBoneWeights;
std::array<char, 4> mBoneIndices;
float mEyeData;
void read(NIFStream* nif, uint16_t flags);
};
struct BSTriShape : NiAVObject
{
osg::BoundingSpheref mBoundingSphere;
std::array<float, 6> mBoundMinMax;
RecordPtrT<Record> mSkin;
BSShaderPropertyPtr mShaderProperty;
NiAlphaPropertyPtr mAlphaProperty;
BSVertexDesc mVertDesc;
uint32_t mDataSize;
std::vector<BSVertexData> mVertData;
std::vector<unsigned short> mTriangles;
uint32_t mParticleDataSize;
std::vector<Misc::float16_t> mParticleVerts;
std::vector<Misc::float16_t> mParticleNormals;
std::vector<unsigned short> mParticleTriangles;
void read(NIFStream* nif) override;
void post(Reader& nif) override;
};
struct BSDynamicTriShape : BSTriShape
{
uint32_t mDynamicDataSize;
std::vector<osg::Vec4f> mDynamicData;
void read(NIFStream* nif) override;
};
struct BSMeshLODTriShape : BSTriShape
{
std::array<uint32_t, 3> mLOD;
void read(NIFStream* nif) override;
};
struct BSSubIndexTriShape : BSTriShape
{
struct SubSegment
{
uint32_t mStartIndex;
uint32_t mNumPrimitives;
uint32_t mArrayIndex;
void read(NIFStream* nif);
};
struct Segment
{
uint32_t mStartIndex;
uint32_t mNumPrimitives;
uint32_t mParentArrayIndex;
std::vector<SubSegment> mSubSegments;
void read(NIFStream* nif);
};
struct SubSegmentDataRecord
{
uint32_t mUserSlotID;
uint32_t mMaterial;
std::vector<float> mExtraData;
void read(NIFStream* nif);
};
struct SubSegmentData
{
std::vector<uint32_t> mArrayIndices;
std::vector<SubSegmentDataRecord> mDataRecords;
std::string mSSFFile;
void read(NIFStream* nif);
};
struct Segmentation
{
uint32_t mNumPrimitives;
uint32_t mNumTotalSegments;
std::vector<Segment> mSegments;
SubSegmentData mSubSegmentData;
void read(NIFStream* nif);
};
std::vector<BSSegmentedTriShape::SegmentData> mSegments; // SSE
Segmentation mSegmentation; // FO4
void read(NIFStream* nif) override;
};
struct BSValueNode : NiNode
{
enum Flags
{
Flag_BillboardWorldZ = 0x1,
Flag_UsePlayerAdjust = 0x2,
};
uint32_t mValue;
uint8_t mValueFlags;
void read(NIFStream* nif) override;
};
struct BSOrderedNode : NiNode
{
osg::Vec4f mAlphaSortBound;
bool mStaticBound;
void read(NIFStream* nif) override;
};
struct BSRangeNode : NiNode
{
uint8_t mMin, mMax;
uint8_t mCurrent;
void read(NIFStream* nif) override;
};
struct BSResourceID
{
uint32_t mFileHash;
std::array<char, 4> mExtension;
uint32_t mDirectoryHash;
void read(NIFStream* nif);
};
struct BSDistantObjectInstance
{
BSResourceID mResourceID;
std::vector<osg::Matrixf> mTransforms;
void read(NIFStream* nif);
};
struct BSShaderTextureArray
{
std::vector<std::vector<std::string>> mTextureArrays;
void read(NIFStream* nif);
};
struct BSDistantObjectInstancedNode : BSMultiBoundNode
{
std::vector<BSDistantObjectInstance> mInstances;
std::array<BSShaderTextureArray, 3> mShaderTextureArrays;
void read(NIFStream* nif) override;
};
}
#endif