#ifndef OPENMW_COMPONENTS_NIF_NODE_HPP #define OPENMW_COMPONENTS_NIF_NODE_HPP #include #include #include #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 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 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 mNames; std::vector 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 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 getCollisionShape() const override; }; struct BSSegmentedTriShape : NiTriShape { struct SegmentData { uint8_t mFlags; uint32_t mStartIndex; uint32_t mNumTriangles; void read(NIFStream* nif); }; std::vector mSegments; void read(NIFStream* nif); }; struct NiTriStrips : NiTriBasedGeom { std::unique_ptr getCollisionShape() const override; }; struct NiLines : NiTriBasedGeom { std::unique_ptr getCollisionShape() const override; }; struct NiParticles : NiGeometry { std::unique_ptr getCollisionShape() const override; }; struct BSLODTriShape : NiTriShape { std::array 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 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 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 mHalfVertex; // Ditto std::array mUV; std::array mNormal; // Bitangent Y is stored in the fourth component std::array mTangent; // Bitangent Z is stored in the fourth component std::array mVertColor; std::array mBoneWeights; std::array mBoneIndices; float mEyeData; void read(NIFStream* nif, uint16_t flags); }; struct BSTriShape : NiAVObject { osg::BoundingSpheref mBoundingSphere; std::array mBoundMinMax; RecordPtrT mSkin; BSShaderPropertyPtr mShaderProperty; NiAlphaPropertyPtr mAlphaProperty; BSVertexDesc mVertDesc; uint32_t mDataSize; std::vector mVertData; std::vector mTriangles; uint32_t mParticleDataSize; std::vector mParticleVerts; std::vector mParticleNormals; std::vector mParticleTriangles; void read(NIFStream* nif) override; void post(Reader& nif) override; }; struct BSDynamicTriShape : BSTriShape { uint32_t mDynamicDataSize; std::vector mDynamicData; void read(NIFStream* nif) override; }; struct BSMeshLODTriShape : BSTriShape { std::array 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 mSubSegments; void read(NIFStream* nif); }; struct SubSegmentDataRecord { uint32_t mUserSlotID; uint32_t mMaterial; std::vector mExtraData; void read(NIFStream* nif); }; struct SubSegmentData { std::vector mArrayIndices; std::vector mDataRecords; std::string mSSFFile; void read(NIFStream* nif); }; struct Segmentation { uint32_t mNumPrimitives; uint32_t mNumTotalSegments; std::vector mSegments; SubSegmentData mSubSegmentData; void read(NIFStream* nif); }; std::vector 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 mExtension; uint32_t mDirectoryHash; void read(NIFStream* nif); }; struct BSDistantObjectInstance { BSResourceID mResourceID; std::vector mTransforms; void read(NIFStream* nif); }; struct BSShaderTextureArray { std::vector> mTextureArrays; void read(NIFStream* nif); }; struct BSDistantObjectInstancedNode : BSMultiBoundNode { std::vector mInstances; std::array mShaderTextureArrays; void read(NIFStream* nif) override; }; } #endif