Merge branch 'lordofthenifs' into 'master'

Load a bunch of Bethesda Havok NIF records

See merge request OpenMW/openmw!1392
android-ndk22
psi29a 3 years ago
commit 03e88b8e27

@ -143,6 +143,15 @@ static std::map<std::string,RecordFactoryEntry> makeFactory()
factory["bhkCollisionObject"] = {&construct <bhkCollisionObject> , RC_bhkCollisionObject };
factory["BSDismemberSkinInstance"] = {&construct <BSDismemberSkinInstance> , RC_BSDismemberSkinInstance };
factory["NiControllerManager"] = {&construct <NiControllerManager> , RC_NiControllerManager };
factory["bhkMoppBvTreeShape"] = {&construct <bhkMoppBvTreeShape> , RC_bhkMoppBvTreeShape };
factory["bhkNiTriStripsShape"] = {&construct <bhkNiTriStripsShape> , RC_bhkNiTriStripsShape };
factory["bhkPackedNiTriStripsShape"] = {&construct <bhkPackedNiTriStripsShape> , RC_bhkPackedNiTriStripsShape };
factory["hkPackedNiTriStripsData"] = {&construct <hkPackedNiTriStripsData> , RC_hkPackedNiTriStripsData };
factory["bhkConvexVerticesShape"] = {&construct <bhkConvexVerticesShape> , RC_bhkConvexVerticesShape };
factory["bhkBoxShape"] = {&construct <bhkBoxShape> , RC_bhkBoxShape };
factory["bhkListShape"] = {&construct <bhkListShape> , RC_bhkListShape };
factory["bhkRigidBody"] = {&construct <bhkRigidBody> , RC_bhkRigidBody };
factory["bhkRigidBodyT"] = {&construct <bhkRigidBody> , RC_bhkRigidBodyT };
return factory;
}

@ -3,6 +3,150 @@
namespace Nif
{
/// Non-record data types
void bhkWorldObjCInfoProperty::read(NIFStream *nif)
{
mData = nif->getUInt();
mSize = nif->getUInt();
mCapacityAndFlags = nif->getUInt();
}
void bhkWorldObjectCInfo::read(NIFStream *nif)
{
nif->skip(4); // Unused
mPhaseType = static_cast<BroadPhaseType>(nif->getChar());
nif->skip(3); // Unused
mProperty.read(nif);
}
void HavokMaterial::read(NIFStream *nif)
{
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
nif->skip(4); // Unknown
mMaterial = nif->getUInt();
}
void HavokFilter::read(NIFStream *nif)
{
mLayer = nif->getChar();
mFlags = nif->getChar();
mGroup = nif->getUShort();
}
void hkSubPartData::read(NIFStream *nif)
{
mHavokFilter.read(nif);
mNumVertices = nif->getUInt();
mHavokMaterial.read(nif);
}
void hkpMoppCode::read(NIFStream *nif)
{
unsigned int size = nif->getUInt();
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0))
mOffset = nif->getVector4();
if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO3)
nif->getChar(); // MOPP data build type
if (size)
nif->getChars(mData, size);
}
void bhkEntityCInfo::read(NIFStream *nif)
{
mResponseType = static_cast<hkResponseType>(nif->getChar());
nif->skip(1); // Unused
mProcessContactDelay = nif->getUShort();
}
void TriangleData::read(NIFStream *nif)
{
for (int i = 0; i < 3; i++)
mTriangle[i] = nif->getUShort();
mWeldingInfo = nif->getUShort();
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
mNormal = nif->getVector3();
}
void bhkRigidBodyCInfo::read(NIFStream *nif)
{
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0))
{
nif->skip(4); // Unused
mHavokFilter.read(nif);
nif->skip(4); // Unused
if (nif->getBethVersion() != NIFFile::BethVersion::BETHVER_FO4)
{
if (nif->getBethVersion() >= 83)
nif->skip(4); // Unused
mResponseType = static_cast<hkResponseType>(nif->getChar());
nif->skip(1); // Unused
mProcessContactDelay = nif->getUShort();
}
}
if (nif->getBethVersion() < 83)
nif->skip(4); // Unused
mTranslation = nif->getVector4();
mRotation = nif->getQuaternion();
mLinearVelocity = nif->getVector4();
mAngularVelocity = nif->getVector4();
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
mInertiaTensor[i][j] = nif->getFloat();
mCenter = nif->getVector4();
mMass = nif->getFloat();
mLinearDamping = nif->getFloat();
mAngularDamping = nif->getFloat();
if (nif->getBethVersion() >= 83)
{
if (nif->getBethVersion() != NIFFile::BethVersion::BETHVER_FO4)
mTimeFactor = nif->getFloat();
mGravityFactor = nif->getFloat();
}
mFriction = nif->getFloat();
if (nif->getBethVersion() >= 83)
mRollingFrictionMult = nif->getFloat();
mRestitution = nif->getFloat();
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0))
{
mMaxLinearVelocity = nif->getFloat();
mMaxAngularVelocity = nif->getFloat();
if (nif->getBethVersion() != NIFFile::BethVersion::BETHVER_FO4)
mPenetrationDepth = nif->getFloat();
}
mMotionType = static_cast<hkMotionType>(nif->getChar());
if (nif->getBethVersion() < 83)
mDeactivatorType = static_cast<hkDeactivatorType>(nif->getChar());
else
mEnableDeactivation = nif->getBoolean();
mSolverDeactivation = static_cast<hkSolverDeactivation>(nif->getChar());
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_FO4)
{
nif->skip(1);
mPenetrationDepth = nif->getFloat();
mTimeFactor = nif->getFloat();
nif->skip(4);
mResponseType = static_cast<hkResponseType>(nif->getChar());
nif->skip(1); // Unused
mProcessContactDelay = nif->getUShort();
}
mQualityType = static_cast<hkQualityType>(nif->getChar());
if (nif->getBethVersion() >= 83)
{
mAutoRemoveLevel = nif->getChar();
mResponseModifierFlags = nif->getChar();
mNumContactPointShapeKeys = nif->getChar();
mForceCollidedOntoPPU = nif->getBoolean();
}
if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_FO4)
nif->skip(3); // Unused
else
nif->skip(12); // Unused
}
/// Record types
void bhkCollisionObject::read(NIFStream *nif)
{
NiCollisionObject::read(nif);
@ -15,13 +159,8 @@ namespace Nif
mShape.read(nif);
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
nif->skip(4); // Unknown
mFlags = nif->getUInt();
nif->skip(4); // Unused
mWorldObjectInfo.mPhaseType = nif->getChar();
nif->skip(3); // Unused
mWorldObjectInfo.mData = nif->getUInt();
mWorldObjectInfo.mSize = nif->getUInt();
mWorldObjectInfo.mCapacityAndFlags = nif->getUInt();
mHavokFilter.read(nif);
mWorldObjectInfo.read(nif);
}
void bhkWorldObject::post(NIFFile *nif)
@ -32,23 +171,143 @@ namespace Nif
void bhkEntity::read(NIFStream *nif)
{
bhkWorldObject::read(nif);
mResponseType = static_cast<hkResponseType>(nif->getChar());
nif->skip(1); // Unused
mProcessContactDelay = nif->getUShort();
mInfo.read(nif);
}
void HavokMaterial::read(NIFStream *nif)
void bhkBvTreeShape::read(NIFStream *nif)
{
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
nif->skip(4); // Unknown
mMaterial = nif->getUInt();
mShape.read(nif);
}
void hkSubPartData::read(NIFStream *nif)
void bhkBvTreeShape::post(NIFFile *nif)
{
mHavokFilter = nif->getUInt();
mNumVertices = nif->getUInt();
mShape.post(nif);
}
void bhkMoppBvTreeShape::read(NIFStream *nif)
{
bhkBvTreeShape::read(nif);
nif->skip(12); // Unused
mScale = nif->getFloat();
mMopp.read(nif);
}
void bhkNiTriStripsShape::read(NIFStream *nif)
{
mHavokMaterial.read(nif);
mRadius = nif->getFloat();
nif->skip(20); // Unused
mGrowBy = nif->getUInt();
if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,0))
mScale = nif->getVector4();
mData.read(nif);
unsigned int numFilters = nif->getUInt();
nif->getUInts(mFilters, numFilters);
}
void bhkNiTriStripsShape::post(NIFFile *nif)
{
mData.post(nif);
}
void bhkPackedNiTriStripsShape::read(NIFStream *nif)
{
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
{
mSubshapes.resize(nif->getUShort());
for (hkSubPartData& subshape : mSubshapes)
subshape.read(nif);
}
mUserData = nif->getUInt();
nif->skip(4); // Unused
mRadius = nif->getFloat();
nif->skip(4); // Unused
mScale = nif->getVector4();
nif->skip(20); // Duplicates of the two previous fields
mData.read(nif);
}
void bhkPackedNiTriStripsShape::post(NIFFile *nif)
{
mData.post(nif);
}
void hkPackedNiTriStripsData::read(NIFStream *nif)
{
unsigned int numTriangles = nif->getUInt();
mTriangles.resize(numTriangles);
for (unsigned int i = 0; i < numTriangles; i++)
mTriangles[i].read(nif);
unsigned int numVertices = nif->getUInt();
bool compressed = false;
if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS)
compressed = nif->getBoolean();
if (!compressed)
nif->getVector3s(mVertices, numVertices);
else
nif->skip(6 * numVertices); // Half-precision vectors are not currently supported
if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS)
{
mSubshapes.resize(nif->getUShort());
for (hkSubPartData& subshape : mSubshapes)
subshape.read(nif);
}
}
void bhkSphereRepShape::read(NIFStream *nif)
{
mHavokMaterial.read(nif);
}
void bhkConvexShape::read(NIFStream *nif)
{
bhkSphereRepShape::read(nif);
mRadius = nif->getFloat();
}
void bhkConvexVerticesShape::read(NIFStream *nif)
{
bhkConvexShape::read(nif);
mVerticesProperty.read(nif);
mNormalsProperty.read(nif);
unsigned int numVertices = nif->getUInt();
if (numVertices)
nif->getVector4s(mVertices, numVertices);
unsigned int numNormals = nif->getUInt();
if (numNormals)
nif->getVector4s(mNormals, numNormals);
}
void bhkBoxShape::read(NIFStream *nif)
{
bhkConvexShape::read(nif);
nif->skip(8); // Unused
mExtents = nif->getVector3();
nif->skip(4); // Unused
}
void bhkListShape::read(NIFStream *nif)
{
mSubshapes.read(nif);
mHavokMaterial.read(nif);
mChildShapeProperty.read(nif);
mChildFilterProperty.read(nif);
unsigned int numFilters = nif->getUInt();
mHavokFilters.resize(numFilters);
for (HavokFilter& filter : mHavokFilters)
filter.read(nif);
}
void bhkRigidBody::read(NIFStream *nif)
{
bhkEntity::read(nif);
mInfo.read(nif);
mConstraints.read(nif);
if (nif->getBethVersion() < 76)
mBodyFlags = nif->getUInt();
else
mBodyFlags = nif->getUShort();
}
} // Namespace

@ -8,6 +8,176 @@
namespace Nif
{
/// Non-record data types
struct bhkWorldObjCInfoProperty
{
unsigned int mData;
unsigned int mSize;
unsigned int mCapacityAndFlags;
void read(NIFStream *nif);
};
enum class BroadPhaseType : uint8_t
{
BroadPhase_Invalid = 0,
BroadPhase_Entity = 1,
BroadPhase_Phantom = 2,
BroadPhase_Border = 3
};
struct bhkWorldObjectCInfo
{
BroadPhaseType mPhaseType;
bhkWorldObjCInfoProperty mProperty;
void read(NIFStream *nif);
};
struct HavokMaterial
{
unsigned int mMaterial;
void read(NIFStream *nif);
};
struct HavokFilter
{
unsigned char mLayer;
unsigned char mFlags;
unsigned short mGroup;
void read(NIFStream *nif);
};
struct hkSubPartData
{
HavokMaterial mHavokMaterial;
unsigned int mNumVertices;
HavokFilter mHavokFilter;
void read(NIFStream *nif);
};
enum class hkResponseType : uint8_t
{
Response_Invalid = 0,
Response_SimpleContact = 1,
Response_Reporting = 2,
Response_None = 3
};
struct bhkEntityCInfo
{
hkResponseType mResponseType;
unsigned short mProcessContactDelay;
void read(NIFStream *nif);
};
struct hkpMoppCode
{
osg::Vec4f mOffset;
std::vector<char> mData;
void read(NIFStream *nif);
};
struct TriangleData
{
unsigned short mTriangle[3];
unsigned short mWeldingInfo;
osg::Vec3f mNormal;
void read(NIFStream *nif);
};
enum class hkMotionType : uint8_t
{
Motion_Invalid = 0,
Motion_Dynamic = 1,
Motion_SphereInertia = 2,
Motion_SphereStabilized = 3,
Motion_BoxInertia = 4,
Motion_BoxStabilized = 5,
Motion_Keyframed = 6,
Motion_Fixed = 7,
Motion_ThinBox = 8,
Motion_Character = 9
};
enum class hkDeactivatorType : uint8_t
{
Deactivator_Invalid = 0,
Deactivator_Never = 1,
Deactivator_Spatial = 2
};
enum class hkSolverDeactivation : uint8_t
{
SolverDeactivation_Invalid = 0,
SolverDeactivation_Off = 1,
SolverDeactivation_Low = 2,
SolverDeactivation_Medium = 3,
SolverDeactivation_High = 4,
SolverDeactivation_Max = 5
};
enum class hkQualityType : uint8_t
{
Quality_Invalid = 0,
Quality_Fixed = 1,
Quality_Keyframed = 2,
Quality_Debris = 3,
Quality_Moving = 4,
Quality_Critical = 5,
Quality_Bullet = 6,
Quality_User = 7,
Quality_Character = 8,
Quality_KeyframedReport = 9
};
struct bhkRigidBodyCInfo
{
HavokFilter mHavokFilter;
hkResponseType mResponseType;
unsigned short mProcessContactDelay;
osg::Vec4f mTranslation;
osg::Quat mRotation;
osg::Vec4f mLinearVelocity;
osg::Vec4f mAngularVelocity;
float mInertiaTensor[3][4];
osg::Vec4f mCenter;
float mMass;
float mLinearDamping;
float mAngularDamping;
float mTimeFactor{1.f};
float mGravityFactor{1.f};
float mFriction;
float mRollingFrictionMult;
float mRestitution;
float mMaxLinearVelocity;
float mMaxAngularVelocity;
float mPenetrationDepth;
hkMotionType mMotionType;
hkDeactivatorType mDeactivatorType;
bool mEnableDeactivation{true};
hkSolverDeactivation mSolverDeactivation;
hkQualityType mQualityType;
unsigned char mAutoRemoveLevel;
unsigned char mResponseModifierFlags;
unsigned char mNumContactPointShapeKeys;
bool mForceCollidedOntoPPU;
void read(NIFStream *nif);
};
/// Record types
// Abstract Bethesda Havok object
struct bhkRefObject : public Record {};
// Abstract serializable Bethesda Havok object
struct bhkSerializable : public bhkRefObject {};
// Abstract narrowphase collision detection object
struct bhkShape : public bhkSerializable {};
// Abstract bhkShape collection
struct bhkShapeCollection : public bhkShape {};
// Generic collision object
struct NiCollisionObject : public Record
{
@ -28,7 +198,7 @@ struct NiCollisionObject : public Record
struct bhkCollisionObject : public NiCollisionObject
{
unsigned short mFlags;
CollisionBodyPtr mBody;
bhkWorldObjectPtr mBody;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override
@ -39,51 +209,123 @@ struct bhkCollisionObject : public NiCollisionObject
};
// Abstract Havok shape info record
struct bhkWorldObject : public Record
struct bhkWorldObject : public bhkSerializable
{
bhkShapePtr mShape;
unsigned int mFlags; // Havok layer type, collision filter flags and group
struct WorldObjectInfo
{
unsigned char mPhaseType;
unsigned int mData;
unsigned int mSize;
unsigned int mCapacityAndFlags;
};
WorldObjectInfo mWorldObjectInfo;
HavokFilter mHavokFilter;
bhkWorldObjectCInfo mWorldObjectInfo;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
};
struct bhkShape : public Record {};
// Abstract
struct bhkEntity : public bhkWorldObject
{
bhkEntityCInfo mInfo;
void read(NIFStream *nif) override;
};
enum class hkResponseType : uint8_t
// Bethesda extension of hkpBvTreeShape
// hkpBvTreeShape adds a bounding volume tree to an hkpShapeCollection
struct bhkBvTreeShape : public bhkShape
{
Response_Invalid = 0,
Response_SimpleContact = 1,
Response_Reporting = 2,
Response_None = 3
bhkShapePtr mShape;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
};
struct bhkEntity : public bhkWorldObject
// bhkBvTreeShape with Havok MOPP code
struct bhkMoppBvTreeShape : public bhkBvTreeShape
{
hkResponseType mResponseType;
unsigned short mProcessContactDelay;
float mScale;
hkpMoppCode mMopp;
void read(NIFStream *nif) override;
};
struct HavokMaterial
// Bethesda triangle strip-based Havok shape collection
struct bhkNiTriStripsShape : public bhkShape
{
unsigned int mMaterial;
void read(NIFStream *nif);
HavokMaterial mHavokMaterial;
float mRadius;
unsigned int mGrowBy;
osg::Vec4f mScale{1.f, 1.f, 1.f, 0.f};
NiTriStripsDataList mData;
std::vector<unsigned int> mFilters;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
};
struct hkSubPartData
// Bethesda packed triangle strip-based Havok shape collection
struct bhkPackedNiTriStripsShape : public bhkShapeCollection
{
std::vector<hkSubPartData> mSubshapes;
unsigned int mUserData;
float mRadius;
osg::Vec4f mScale;
hkPackedNiTriStripsDataPtr mData;
void read(NIFStream *nif) override;
void post(NIFFile *nif) override;
};
// bhkPackedNiTriStripsShape data block
struct hkPackedNiTriStripsData : public bhkShapeCollection
{
std::vector<TriangleData> mTriangles;
std::vector<osg::Vec3f> mVertices;
std::vector<hkSubPartData> mSubshapes;
void read(NIFStream *nif) override;
};
// Abstract
struct bhkSphereRepShape : public bhkShape
{
HavokMaterial mHavokMaterial;
unsigned int mNumVertices;
unsigned int mHavokFilter;
void read(NIFStream *nif);
void read(NIFStream *nif) override;
};
// Abstract
struct bhkConvexShape : public bhkSphereRepShape
{
float mRadius;
void read(NIFStream *nif) override;
};
// A convex shape built from vertices
struct bhkConvexVerticesShape : public bhkConvexShape
{
bhkWorldObjCInfoProperty mVerticesProperty;
bhkWorldObjCInfoProperty mNormalsProperty;
std::vector<osg::Vec4f> mVertices;
std::vector<osg::Vec4f> mNormals;
void read(NIFStream *nif) override;
};
// A box
struct bhkBoxShape : public bhkConvexShape
{
osg::Vec3f mExtents;
void read(NIFStream *nif) override;
};
// A list of shapes
struct bhkListShape : public bhkShapeCollection
{
bhkShapeList mSubshapes;
HavokMaterial mHavokMaterial;
bhkWorldObjCInfoProperty mChildShapeProperty;
bhkWorldObjCInfoProperty mChildFilterProperty;
std::vector<HavokFilter> mHavokFilters;
void read(NIFStream *nif) override;
};
struct bhkRigidBody : public bhkEntity
{
bhkRigidBodyCInfo mInfo;
bhkSerializableList mConstraints;
unsigned int mBodyFlags;
void read(NIFStream *nif) override;
};
} // Namespace

@ -130,7 +130,16 @@ enum RecordType
RC_NiCollisionObject,
RC_bhkCollisionObject,
RC_BSDismemberSkinInstance,
RC_NiControllerManager
RC_NiControllerManager,
RC_bhkMoppBvTreeShape,
RC_bhkNiTriStripsShape,
RC_bhkPackedNiTriStripsShape,
RC_hkPackedNiTriStripsData,
RC_bhkConvexVerticesShape,
RC_bhkBoxShape,
RC_bhkListShape,
RC_bhkRigidBody,
RC_bhkRigidBodyT
};
/// Base class for all records

@ -151,6 +151,8 @@ struct NiAlphaProperty;
struct NiCollisionObject;
struct bhkWorldObject;
struct bhkShape;
struct bhkSerializable;
struct hkPackedNiTriStripsData;
using NodePtr = RecordPtrT<Node>;
using ExtraPtr = RecordPtrT<Extra>;
@ -179,8 +181,9 @@ using NiGeometryDataPtr = RecordPtrT<NiGeometryData>;
using BSShaderPropertyPtr = RecordPtrT<BSShaderProperty>;
using NiAlphaPropertyPtr = RecordPtrT<NiAlphaProperty>;
using NiCollisionObjectPtr = RecordPtrT<NiCollisionObject>;
using CollisionBodyPtr = RecordPtrT<bhkWorldObject>;
using bhkWorldObjectPtr = RecordPtrT<bhkWorldObject>;
using bhkShapePtr = RecordPtrT<bhkShape>;
using hkPackedNiTriStripsDataPtr = RecordPtrT<hkPackedNiTriStripsData>;
using NodeList = RecordListT<Node>;
using PropertyList = RecordListT<Property>;
@ -188,6 +191,8 @@ using ExtraList = RecordListT<Extra>;
using NiSourceTextureList = RecordListT<NiSourceTexture>;
using NiFloatInterpolatorList = RecordListT<NiFloatInterpolator>;
using NiTriStripsDataList = RecordListT<NiTriStripsData>;
using bhkShapeList = RecordListT<bhkShape>;
using bhkSerializableList = RecordListT<bhkSerializable>;
} // Namespace
#endif

Loading…
Cancel
Save