From 0890d161e5d22a4572a2ca128c6aff6af5ab8ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 20 Mar 2022 18:27:06 +0100 Subject: [PATCH] ksys/phys: Add most remaining parts of RayCast One last function remaining (0x0000007100fc4844) but it looks obnoxious so I'll leave it for later. --- data/uking_functions.csv | 10 +- lib/hkStubs/CMakeLists.txt | 4 + .../Havok/Common/Base/Types/hkBaseDefs.h | 2 + .../hkpSampledHeightFieldBaseCinfo.h | 24 +++ .../hkpSampledHeightFieldShape.h | 153 +++++++++++++++++ .../hkpBvCompressedMeshShape.h | 154 ++++++++++++++++++ .../ShapeUtils/ShapeKeyPath/hkpShapeKeyPath.h | 77 +++++++++ src/KingSystem/Physics/CMakeLists.txt | 2 + .../RigidBody/physRigidBodyFromResource.cpp | 10 +- .../StaticCompound/physStaticCompoundUtil.cpp | 1 + .../StaticCompound/physStaticCompoundUtil.h | 35 ++++ src/KingSystem/Physics/System/physRayCast.cpp | 117 ++++++++++++- src/KingSystem/Physics/System/physRayCast.h | 31 ++-- src/KingSystem/Physics/physMaterialMask.h | 14 +- 14 files changed, 596 insertions(+), 38 deletions(-) create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldBaseCinfo.h create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldShape.h create mode 100644 lib/hkStubs/Havok/Physics2012/Internal/Collide/BvCompressedMesh/hkpBvCompressedMeshShape.h create mode 100644 lib/hkStubs/Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeKeyPath/hkpShapeKeyPath.h create mode 100644 src/KingSystem/Physics/StaticCompound/physStaticCompoundUtil.cpp create mode 100644 src/KingSystem/Physics/StaticCompound/physStaticCompoundUtil.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index fc665250..816314b2 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -84038,14 +84038,14 @@ Address,Quality,Size,Name 0x0000007100fc3b1c,O,000648,_ZN4ksys4phys7RayCast16worldRayCastImplEP21hkpWorldRayCastOutputNS0_16ContactLayerTypeE 0x0000007100fc3da4,O,000360,_ZN4ksys4phys7RayCast12shapeRayCastEPNS0_9RigidBodyE 0x0000007100fc3f0c,O,000828,_ZN4ksys4phys7RayCast16shapeRayCastImplEP21hkpWorldRayCastOutputPNS0_9RigidBodyE -0x0000007100fc4248,U,000360,phys::RayCast::phantomRayCast -0x0000007100fc43b0,U,000640,phys::RaycastQuery::phantomRayCastImpl -0x0000007100fc4630,U,000236,phys::RaycastQuery::staticCompoundStuff +0x0000007100fc4248,O,000360,_ZN4ksys4phys7RayCast14phantomRayCastEPNS0_7PhantomE +0x0000007100fc43b0,O,000640,_ZN4ksys4phys7RayCast18phantomRayCastImplEP21hkpWorldRayCastOutputPNS0_7PhantomE +0x0000007100fc4630,O,000236,_ZN4ksys4phys7RayCast30updateStaticCompoundObjectInfoERK21hkpWorldRayCastOutput 0x0000007100fc471c,O,000072,_ZNK4ksys4phys7RayCast14getHitPositionEPN4sead7Vector3IfEE -0x0000007100fc4764,U,000268,phys::RaycastQuery::x_2 +0x0000007100fc4764,O,000268,_ZNK4ksys4phys7RayCast20getHitTriangleNormalEPN4sead7Vector3IfEEPK8hkpShapej 0x0000007100fc4870,O,000028,_ZNK4ksys4phys7RayCast12getHitNormalEPN4sead7Vector3IfEE 0x0000007100fc488c,U,000840,phys::RaycastQuery::x_0 -0x0000007100fc4bd4,U,000032,phys::RaycastQuery::x_1 +0x0000007100fc4bd4,O,000032,_ZNK4ksys4phys7RayCast20getHitTriangleNormalEPN4sead7Vector3IfEE 0x0000007100fc4bf4,O,000004,_ZN4ksys4phys15RayHitCollectorD1Ev 0x0000007100fc4bf8,O,000080,_ZN4ksys4phys15RayHitCollectorD0Ev 0x0000007100fc4c48,m,000456,_ZN4ksys4phys15RayHitCollector9addRayHitERK9hkpCdBodyRK30hkpShapeRayCastCollectorOutput diff --git a/lib/hkStubs/CMakeLists.txt b/lib/hkStubs/CMakeLists.txt index 9ebd6815..b76110f4 100644 --- a/lib/hkStubs/CMakeLists.txt +++ b/lib/hkStubs/CMakeLists.txt @@ -140,6 +140,8 @@ add_library(hkStubs OBJECT Havok/Physics2012/Collide/Shape/HeightField/hkpHeightFieldShape.h Havok/Physics2012/Collide/Shape/HeightField/hkpSphereRepShape.h Havok/Physics2012/Collide/Shape/HeightField/Plane/hkpPlaneShape.h + Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldBaseCinfo.h + Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldShape.h Havok/Physics2012/Collide/Shape/Query/hkpRayShapeCollectionFilter.h Havok/Physics2012/Collide/Shape/Query/hkpShapeRayCastCollectorOutput.h Havok/Physics2012/Collide/Shape/Query/hkpShapeRayCastInput.h @@ -199,12 +201,14 @@ add_library(hkStubs OBJECT Havok/Physics2012/Dynamics/World/Simulation/hkpSimulation.h Havok/Physics2012/Dynamics/World/Util/hkpWorldConstraintUtil.h + Havok/Physics2012/Internal/Collide/BvCompressedMesh/hkpBvCompressedMeshShape.h Havok/Physics2012/Internal/Collide/Mopp/Code/hkpMoppCode.h Havok/Physics2012/Internal/Collide/StaticCompound/hkpShapeKeyTable.h Havok/Physics2012/Internal/Collide/StaticCompound/hkpStaticCompoundShape.h Havok/Physics2012/Internal/Solver/Contact/hkpSimpleContactConstraintDataInfo.h Havok/Physics2012/Utilities/CharacterControl/CharacterRigidBody/hkpCharacterRigidBody.h + Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeKeyPath/hkpShapeKeyPath.h Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeScaling/hkpShapeScalingUtility.h Havok/Physics2012/Utilities/Dynamics/ScaleSystem/hkpSystemScalingUtility.h Havok/Physics2012/Utilities/Serialize/hkpPhysicsData.h diff --git a/lib/hkStubs/Havok/Common/Base/Types/hkBaseDefs.h b/lib/hkStubs/Havok/Common/Base/Types/hkBaseDefs.h index 6b3f87da..dc0db329 100644 --- a/lib/hkStubs/Havok/Common/Base/Types/hkBaseDefs.h +++ b/lib/hkStubs/Havok/Common/Base/Types/hkBaseDefs.h @@ -7,3 +7,5 @@ #define HK_VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) #define HK_RESTRICT __restrict + +#define HK_MAX_NUM_THREADS 12 diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldBaseCinfo.h b/lib/hkStubs/Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldBaseCinfo.h new file mode 100644 index 00000000..42a25fa5 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldBaseCinfo.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +class hkpSampledHeightFieldBaseCinfo { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpSampledHeightFieldBaseCinfo) + + hkpSampledHeightFieldBaseCinfo() { + m_scale.set(1.0f, 1.0f, 1.0f); + m_xRes = 2; + m_zRes = 2; + m_minHeight = 0.0f; + m_maxHeight = -1.0f; + m_useProjectionBasedHeight = false; + } + + hkVector4 m_scale; + hkInt32 m_xRes; + hkInt32 m_zRes; + hkReal m_minHeight; + hkReal m_maxHeight; + hkBool m_useProjectionBasedHeight; +}; diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldShape.h b/lib/hkStubs/Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldShape.h new file mode 100644 index 00000000..d293856b --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Shape/HeightField/SampledHeightField/hkpSampledHeightFieldShape.h @@ -0,0 +1,153 @@ +#pragma once + +#include +#include +#include +#include + +class hkpSampledHeightFieldShape : public hkpHeightFieldShape { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpHeightFieldShape) + HK_DECLARE_REFLECTION() + HKCD_DECLARE_SHAPE_TYPE(hkcdShapeType::SAMPLED_HEIGHT_FIELD) + + enum HeightFieldType { + /// hkpStorageSampledHeightFieldShape, stores values as hkReals + HEIGHTFIELD_STORAGE = 0, + /// hkpCompressedSampledHeightFieldShape, stores values as hkUint16s + HEIGHTFIELD_COMPRESSED, + HEIGHTFIELD_USER, + HEIGHTFIELD_MAX_ID + }; + + explicit hkpSampledHeightFieldShape(const hkpSampledHeightFieldBaseCinfo& ci, + HeightFieldType type = HEIGHTFIELD_USER); + + hkpSampledHeightFieldShape() + : hkpHeightFieldShape(HKCD_SHAPE_TYPE_FROM_CLASS(hkpSampledHeightFieldShape)) {} + + explicit hkpSampledHeightFieldShape(hkFinishLoadedObjectFlag flag); + + ~hkpSampledHeightFieldShape() override; + + void getCinfo(hkpSampledHeightFieldBaseCinfo& cinfo) const; + + HK_FORCE_INLINE hkReal getHeightAt(int x, int z) const; + + HK_FORCE_INLINE hkBool getTriangleFlip() const; + + void buildCoarseMinMaxTree(int coarseness = 3); + + virtual void getCoarseMinMax(int level, int x, int z, hkVector4& minOut, + hkVector4& maxOut) const; + + void setMinMaxTreeCoarseness(int coarseness); + + void getAabb(const hkTransform& localToWorld, hkReal tolerance, hkAabb& out) const override; + + void collideSpheres(const CollideSpheresInput& input, + SphereCollisionOutput* outputArray) const override; + + void castSphere(const hkpSphereCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const override; + + hkBool castRay(const hkpShapeRayCastInput& input, hkpShapeRayCastOutput& output) const override; + + void castRayWithCollector(const hkpShapeRayCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const override; + + virtual hkReal getHeightAtImpl(int x, int z) const; + virtual hkBool getTriangleFlipImpl() const; + + using RayCastInternalFunc = void (hkpSampledHeightFieldShape::*)(const hkpShapeRayCastInput&, + const hkpCdBody&, + hkpRayHitCollector&) const; + static RayCastInternalFunc s_rayCastFunc; + + void castRayDefault(const hkpShapeRayCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const; + void castRayDda(const hkpShapeRayCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const; + void castRayCoarseTree(const hkpShapeRayCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const; + + using SphereCastInternalFunc = void (hkpSampledHeightFieldShape::*)(const hkpSphereCastInput&, + const hkpCdBody&, + hkpRayHitCollector&) const; + static SphereCastInternalFunc s_sphereCastFunc; + + void castSphereDefault(const hkpSphereCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const; + void castSphereDda(const hkpSphereCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const; + void castSphereCoarseTree(const hkpSphereCastInput& input, const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const; + +protected: + void castRayDdaInternal(const hkpShapeRayCastInput& input, const hkpCdBody& cdBody, + hkBool reportPenetratingStartPosition, hkReal maxExtraPenetration, + hkpRayHitCollector& collector) const; + + void castRayCoarseTreeInternal(const hkVector4& from, const hkVector4& to, + const hkpCdBody& cdBody, hkpRayHitCollector& collector) const; + + HK_FORCE_INLINE void _getHeightAndNormalAt(int xPos, int zPos, hkReal subX, hkReal subZ, + hkVector4& normalOut, hkReal& heightOut, + int& triangleIndexOut) const; + + HK_FORCE_INLINE void calcMinMax(int coarseness, int x, int z, hkReal& minheightOut, + hkReal& maxheightOut) const; + + struct AABBStackElement { + hkAabb aabb; + int level; + int x; + int z; + }; + + HK_FORCE_INLINE void findStartCell(AABBStackElement& startOut, const hkVector4& from, + const hkVector4& to) const; + + HK_FORCE_INLINE void rayTriangleQuadCheck(const struct hkcdRay& ray, hkAabb& aabb, int x, int z, + const hkVector4Comparison& flipSelect, + const hkpCdBody& cdBody, + hkpRayHitCollector& collector) const; + +public: + struct CoarseMinMaxLevel { + HK_DECLARE_CLASS_ALLOCATOR(CoarseMinMaxLevel) + HK_DECLARE_REFLECTION() + + CoarseMinMaxLevel() {} + explicit CoarseMinMaxLevel(hkFinishLoadedObjectFlag f) : m_minMaxData(f) {} + CoarseMinMaxLevel(const CoarseMinMaxLevel& l) : m_xRes(l.m_xRes), m_zRes(l.m_zRes) { + m_minMaxData = l.m_minMaxData; + } + + hkArray m_minMaxData; + int m_xRes; + int m_zRes; + }; + hkArray m_coarseTreeData; + + void getHeightAndNormalAt(int xPos, int zPos, hkReal subX, hkReal subZ, hkVector4& normalOut, + hkReal& heightOut, int& triangleIndexOut) const; + + int m_coarseness; + hkReal m_raycastMinY; + hkReal m_raycastMaxY; + + int m_xRes; + int m_zRes; + + hkReal m_heightCenter; + + hkBool m_useProjectionBasedHeight; + + hkEnum m_heightfieldType; + + hkVector4 m_intToFloatScale; + hkVector4 m_floatToIntScale; + hkVector4 m_floatToIntOffsetFloorCorrected; + hkVector4 m_extents; +}; diff --git a/lib/hkStubs/Havok/Physics2012/Internal/Collide/BvCompressedMesh/hkpBvCompressedMeshShape.h b/lib/hkStubs/Havok/Physics2012/Internal/Collide/BvCompressedMesh/hkpBvCompressedMeshShape.h new file mode 100644 index 00000000..dc63c265 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Internal/Collide/BvCompressedMesh/hkpBvCompressedMeshShape.h @@ -0,0 +1,154 @@ +#pragma once + +#include +#include +#include +#include + +struct hkGeometry; +class hkpBvCompressedMeshShapeCinfo; + +class hkpBvCompressedMeshShape : public hkpBvTreeShape, public hkpShapeContainer { +public: + enum PerPrimitiveDataMode { + PER_PRIMITIVE_DATA_NONE, + PER_PRIMITIVE_DATA_8_BIT, + PER_PRIMITIVE_DATA_PALETTE, + PER_PRIMITIVE_DATA_STRING_PALETTE, + }; + + enum PrimitiveType { + PRIMITIVE_TYPE_BOX, + PRIMITIVE_TYPE_HULL, + PRIMITIVE_TYPE_SPHERE, + PRIMITIVE_TYPE_CAPSULE, + PRIMITIVE_TYPE_CYLINDER, + }; + + enum Config { +#if HK_POINTER_SIZE == 8 +#ifdef HK_REAL_IS_DOUBLE + NUM_BYTES_FOR_TREE = 224, +#else + NUM_BYTES_FOR_TREE = 160, +#endif +#else +#ifdef HK_REAL_IS_DOUBLE + NUM_BYTES_FOR_TREE = 224, +#else + NUM_BYTES_FOR_TREE = 144, +#endif +#endif + + MAX_NUM_VERTICES_PER_HULL = 255, + + MAX_NUM_PRIMITIVES = 1 << 23 + }; + +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpBvCompressedMeshShape) + HK_DECLARE_REFLECTION() + HKCD_DECLARE_SHAPE_TYPE(hkcdShapeType::BV_COMPRESSED_MESH) + + explicit hkpBvCompressedMeshShape(const hkpBvCompressedMeshShapeCinfo& cInfo); + explicit hkpBvCompressedMeshShape(hkFinishLoadedObjectFlag flag); + HK_FORCE_INLINE hkpBvCompressedMeshShape() {} + + ~hkpBvCompressedMeshShape() override; + + HK_FORCE_INLINE hkReal getConvexRadius() const; + + hkUint32 getPrimitiveUserData(hkpShapeKey key) const; + hkStringPtr getPrimitiveUserString(hkpShapeKey key) const; + + HK_FORCE_INLINE PerPrimitiveDataMode getCollisionFilterInfoMode() const; + HK_FORCE_INLINE PerPrimitiveDataMode getUserDataMode() const; + HK_FORCE_INLINE hkArray& accessCollisionFilterInfoPalette(); + HK_FORCE_INLINE hkArray& accessUserDataPalette(); + HK_FORCE_INLINE hkArray& accessUserStringPalette(); + + void convertToGeometry(hkGeometry& geometryOut, const hkArray* inclKeys = nullptr, + const hkArray* exclKeys = nullptr) const; + + const hkpShapeContainer* getContainer() const override { return this; } + + int calcSizeForSpu(const CalcSizeForSpuInput& input, int spuBufferSizeLeft) const override; + + void getAabb(const hkTransform& localToWorld, hkReal tolerance, hkAabb& out) const override; + + hkBool castRay(const hkpShapeRayCastInput& input, + hkpShapeRayCastOutput& results) const override; + + void castRayWithCollector(const hkpShapeRayCastInput& input, const hkpCdBody& body, + hkpRayHitCollector& collector) const override; + + void queryAabb(const hkAabb& aabb, hkArray& hits) const override; + + hkUint32 queryAabbImpl(const hkAabb& aabb, hkpShapeKey* hits, int maxNumKeys) const override; + + void castAabbImpl(const hkAabb& from, hkVector4Parameter to, + hkpAabbCastCollector& collector) const override; + + int getNumChildShapes() const override; + + hkpShapeKey getFirstKey() const override; + + hkpShapeKey getNextKey(hkpShapeKey oldKey) const override; + + const hkpShape* getChildShape(hkpShapeKey key, hkpShapeBuffer& buffer) const override; + + hkUint32 getCollisionFilterInfo(hkpShapeKey key) const override; + +protected: + hkReal m_convexRadius; + hkEnum m_weldingType; + hkBool m_hasPerPrimitiveCollisionFilterInfo; + hkBool m_hasPerPrimitiveUserData; + hkArray m_collisionFilterInfoPalette; + hkArray m_userDataPalette; + hkArray m_userStringPalette; + alignas(16) hkUint8 m_tree[NUM_BYTES_FOR_TREE]; + + friend struct hkpBvCompressedMeshShape_Internals; + +public: + alignas(16) static hkVector4 g_vertexBufferPool[HK_MAX_NUM_THREADS][MAX_NUM_VERTICES_PER_HULL]; +}; + +inline hkReal hkpBvCompressedMeshShape::getConvexRadius() const { + return m_convexRadius; +} + +inline hkpBvCompressedMeshShape::PerPrimitiveDataMode +hkpBvCompressedMeshShape::getCollisionFilterInfoMode() const { + return m_hasPerPrimitiveCollisionFilterInfo ? + (m_collisionFilterInfoPalette.getSize() ? PER_PRIMITIVE_DATA_PALETTE : + PER_PRIMITIVE_DATA_8_BIT) : + PER_PRIMITIVE_DATA_NONE; +} + +inline hkpBvCompressedMeshShape::PerPrimitiveDataMode +hkpBvCompressedMeshShape::getUserDataMode() const { + if (!m_hasPerPrimitiveUserData) + return PER_PRIMITIVE_DATA_NONE; + + if (m_userDataPalette.getSize() > 0) + return PER_PRIMITIVE_DATA_PALETTE; + + if (m_userStringPalette.getSize() > 0) + return PER_PRIMITIVE_DATA_STRING_PALETTE; + + return PER_PRIMITIVE_DATA_8_BIT; +} + +inline hkArray& hkpBvCompressedMeshShape::accessCollisionFilterInfoPalette() { + return m_collisionFilterInfoPalette; +} + +inline hkArray& hkpBvCompressedMeshShape::accessUserDataPalette() { + return m_userDataPalette; +} + +inline hkArray& hkpBvCompressedMeshShape::accessUserStringPalette() { + return m_userStringPalette; +} diff --git a/lib/hkStubs/Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeKeyPath/hkpShapeKeyPath.h b/lib/hkStubs/Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeKeyPath/hkpShapeKeyPath.h new file mode 100644 index 00000000..8b7c6e0a --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeKeyPath/hkpShapeKeyPath.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include + +class hkpContactPointEvent; +struct hkpRootCdPoint; +struct hkpShapeRayBundleCastOutput; +struct hkpWorldRayCastOutput; + +class hkpShapeKeyPath { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpShapeKeyPath) + + class Iterator; + + hkpShapeKeyPath(const hkpContactPointEvent& event, int bodyIdx); + explicit hkpShapeKeyPath(const hkpWorldRayCastOutput& output); + hkpShapeKeyPath(const hkpShape* shape, const hkpShapeRayCastOutput& output); + + hkpShapeKey getShapeKey(int keyIndex) const; + + Iterator getIterator() const; + + void getShapes(int maxShapesOut, hkpShapeBuffer* buffers, const hkpShape** shapesOut, + int& numShapesOut); + + class Iterator { + public: + HK_DECLARE_CLASS_ALLOCATOR(Iterator) + + friend class hkpShapeKeyPath; + + /// Returns nullptr if the iterator is invalid. + const hkpShape* getShape() const; + + /// @warning This can invalidate the shape. + void next(); + + hkBool isValid() const; + + private: + Iterator(const hkpShapeKeyPath* path, const hkpShape* rootShape); + void nextImpl(hkpShapeBuffer* buf); + + const hkpShapeKeyPath* m_path; + const hkpShape* m_currentShape; + int m_currentKeyIdx; + hkBool m_isValid; + hkpShapeBuffer m_tempBuffer; + }; + +private: + void init(const hkpShape* shape, const hkpShapeKey* keys, int maxKeys); + + const hkpShape* m_rootShape; + const hkpShapeKey* m_keys; + int m_numKeys; + hkBool m_isOrderLeafToRoot; +}; + +inline hkpShapeKeyPath::Iterator hkpShapeKeyPath::getIterator() const { + return {this, m_rootShape}; +} + +inline const hkpShape* hkpShapeKeyPath::Iterator::getShape() const { + return m_currentShape; +} + +inline void hkpShapeKeyPath::Iterator::next() { + return nextImpl(&m_tempBuffer); +} + +inline hkBool hkpShapeKeyPath::Iterator::isValid() const { + return m_isValid; +} diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index 8abe2816..a3e2aaf1 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -96,6 +96,8 @@ target_sources(uking PRIVATE StaticCompound/physStaticCompoundBodyGroup.h StaticCompound/physStaticCompoundInfo.cpp StaticCompound/physStaticCompoundInfo.h + StaticCompound/physStaticCompoundUtil.cpp + StaticCompound/physStaticCompoundUtil.h SupportBone/physSupportBoneParam.cpp SupportBone/physSupportBoneParam.h diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.cpp b/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.cpp index e828d98f..397cee6b 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.cpp @@ -5,6 +5,7 @@ #include #include #include "KingSystem/Physics/RigidBody/physRigidBodyParam.h" +#include "KingSystem/Physics/StaticCompound/physStaticCompoundUtil.h" #include "KingSystem/Physics/physConversions.h" #include "KingSystem/Physics/physMaterialMask.h" @@ -81,18 +82,13 @@ bool RigidBodyFromResource::isMaterial(Material material) const { return found_child_shape_with_material; } -// FIXME: move this to the appropriate header -// 0x0000007100fd0a1c -u32 getCollisionFilterInfoFromCollidable(u32* material_mask, u32* collision_filter_info, - const hkpCollidable* collidable, const u32* unk); - u32 RigidBodyFromResource::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask; auto* collidable = getHkBody()->getCollidable(); if (unk != nullptr) { - return getCollisionFilterInfoFromCollidable(&masks->material_mask, - &masks->collision_filter_info, collidable, unk); + return getCollisionFilterInfoFromCollidable(masks, &masks->collision_filter_info, + *collidable, unk); } masks->material_mask = collidable->getShape()->getUserData(); masks->collision_filter_info = collidable->getCollisionFilterInfo(); diff --git a/src/KingSystem/Physics/StaticCompound/physStaticCompoundUtil.cpp b/src/KingSystem/Physics/StaticCompound/physStaticCompoundUtil.cpp new file mode 100644 index 00000000..72d1bcbb --- /dev/null +++ b/src/KingSystem/Physics/StaticCompound/physStaticCompoundUtil.cpp @@ -0,0 +1 @@ +#include "KingSystem/Physics/StaticCompound/physStaticCompoundUtil.h" diff --git a/src/KingSystem/Physics/StaticCompound/physStaticCompoundUtil.h b/src/KingSystem/Physics/StaticCompound/physStaticCompoundUtil.h new file mode 100644 index 00000000..0aef6607 --- /dev/null +++ b/src/KingSystem/Physics/StaticCompound/physStaticCompoundUtil.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +class hkpCollidable; +class hkpShape; + +namespace ksys::map { +class Object; +} + +namespace ksys::phys { + +class BodyGroup; +struct RigidBodyCollisionMasks; + +// 0x0000007100fd0810 +u32 getMaterialMaskFromShape(const hkpShape& shape, const u32* shape_key, + const sead::Vector3f& position); + +// 0x0000007100fd086c +bool getMaterialMaskFromCollidable(RigidBodyCollisionMasks* p_masks, u32* p_collision_filter_info, + const hkpShape& shape, const u32* shape_key); + +// 0x0000007100fd09d0 +void getBodyGroupAndObjectFromSCShape(BodyGroup** p_body_group, map::Object** p_object, + const hkpShape& shape, const u32* shape_key); + +// 0x0000007100fd0a1c +u32 getCollisionFilterInfoFromCollidable(RigidBodyCollisionMasks* p_masks, + u32* p_collision_filter_info, + const hkpCollidable& collidable, const u32* shape_key); + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physRayCast.cpp b/src/KingSystem/Physics/System/physRayCast.cpp index 0983d15f..338bfe12 100644 --- a/src/KingSystem/Physics/System/physRayCast.cpp +++ b/src/KingSystem/Physics/System/physRayCast.cpp @@ -9,11 +9,15 @@ #include #include #include +#include #include +#include #include #include "KingSystem/Physics/RigidBody/physRigidBody.h" +#include "KingSystem/Physics/StaticCompound/physStaticCompoundUtil.h" #include "KingSystem/Physics/System/physEntityContactListener.h" #include "KingSystem/Physics/System/physGroupFilter.h" +#include "KingSystem/Physics/System/physPhantom.h" #include "KingSystem/Physics/System/physSystem.h" #include "KingSystem/Physics/physConversions.h" #include "KingSystem/Physics/physLayerMaskBuilder.h" @@ -95,8 +99,8 @@ void RayCast::resetCastResult() { mHitCollidable = {}; mHitShapeKey = {}; mHasHitSpecifiedRigidBody = false; - _58 = {}; - _60 = {}; + mHitBodyGroup = {}; + mHitMapObject = {}; _70 = {}; } @@ -232,7 +236,7 @@ bool RayCast::postCast(const hkpWorldRayCastOutput& output) { mHasHit = output.hasHit(); if (mHasHit) { updateHitInformation(output); - getActorInfoMaybe(output); + updateStaticCompoundObjectInfo(output); } _98 = false; _70 = 1; @@ -337,14 +341,113 @@ void RayCast::shapeRayCastImpl(hkpWorldRayCastOutput* output, RigidBody* body) { } } +bool RayCast::phantomRayCast(Phantom* phantom) { + hkpWorldRayCastOutput output; + preCast(); + phantomRayCastImpl(&output, phantom); + return postCast(output); +} + +void RayCast::phantomRayCastImpl(hkpWorldRayCastOutput* output, Phantom* phantom) { + hkpWorldRayCastInput input; + auto layer_type = phantom->getLayerType(); + fillCastInput(input, layer_type); + + ScopedWorldLock lock{layer_type, "raycast", 0, OnlyLockIfNeeded::Yes}; + + if (mNormalCheckingMode == NormalCheckingMode::DoNotCheck) { + if (mIgnoredGroups.size() > 0 || int(mIgnoredGroundHit) != GroundHit::Ignore) { + RayHitCollector collector{output, layer_type, + mIgnoredGroups.size() > 0 ? &mIgnoredGroups : nullptr, + mIgnoredGroundHit}; + phantom->getHavokPhantom()->castRay(input, collector); + } else { + phantom->getHavokPhantom()->castRay(input, *output); + } + + } else { + sead::Vector3f ray_line = mTo - mFrom; + ray_line.normalize(); + + auto* groups = mIgnoredGroups.size() > 0 ? &mIgnoredGroups : nullptr; + NormalCheckingRayHitCollector collector(output, ray_line, mNormalCheckingMode, layer_type, + groups, mIgnoredGroundHit); + phantom->getHavokPhantom()->castRay(input, collector); + } +} + +void RayCast::updateStaticCompoundObjectInfo(const hkpWorldRayCastOutput& output) { + hkpShapeKeyPath path{output}; + auto iterator = path.getIterator(); + + sead::Vector3f hit_position; + getHitPosition(&hit_position); + + if (iterator.isValid()) { + const auto& shape = *iterator.getShape(); + const u32 raw_material = getMaterialMaskFromShape(shape, output.m_shapeKeys, hit_position); + + mMaterialMask.set(raw_material); + if (raw_material == u32(-1)) + mMaterialMask.reset(); + + if (_99) { + getBodyGroupAndObjectFromSCShape(&mHitBodyGroup, &mHitMapObject, shape, + output.m_shapeKeys); + } + } else { + mMaterialMask.reset(); + } +} + void RayCast::getHitPosition(sead::Vector3f* position) const { *position = ((1 - mHitFraction) * mFrom) + (mHitFraction * mTo); } +static void calculateTriangleNormal(sead::Vector3f* normal, const hkpTriangleShape* triangle) { + const auto va = toVec3(triangle->getVertex<0>()); + const auto vb = toVec3(triangle->getVertex<1>()); + const auto vc = toVec3(triangle->getVertex<2>()); + normal->setCross(vb - va, vc - va); +} + +bool RayCast::getHitTriangleNormal(sead::Vector3f* normal, const hkpShape* hit_shape, + u32 shape_key) const { + if (hit_shape->getType() != hkcdShapeType::STATIC_COMPOUND) { + if (hit_shape->getType() != hkcdShapeType::BV_COMPRESSED_MESH) + return false; + + auto* bv_mesh = static_cast(hit_shape); + + hkpShapeBuffer buffer; + hit_shape = bv_mesh->getChildShape(shape_key, buffer); + if (hit_shape->getType() != hkcdShapeType::TRIANGLE) + return false; + + calculateTriangleNormal(normal, static_cast(hit_shape)); + return true; + } + + auto* sc = static_cast(hit_shape); + int instance_id; + sc->decomposeShapeKey(shape_key, instance_id, shape_key); + return instance_id >= 0 && + getHitTriangleNormal(normal, sc->getInstances()[instance_id].getShape(), shape_key); +} + void RayCast::getHitNormal(sead::Vector3f* normal) const { *normal = mHitNormal; } +bool RayCast::getHitTriangleNormal(sead::Vector3f* normal) const { + if (!mHasHit) + return false; + + const u32 shape_key = mHitShapeKey; + const hkpShape* shape = mHitCollidable->getShape(); + return getHitTriangleNormal(normal, shape, shape_key); +} + RayHitCollector::~RayHitCollector() = default; bool RayHitCollector::isIgnoredGroup(const hkpCdBody& cdBody, @@ -471,9 +574,9 @@ bool NormalCheckingRayHitCollector::checkNormal( hkVector4f CminusA; CminusA.setSub(vertexC, vertexA); - hkVector4f triangle_line; - triangle_line.setCross(BminusA, CminusA); - triangle_line.normalize<3>(); + hkVector4f triangle_normal; + triangle_normal.setCross(BminusA, CminusA); + triangle_normal.normalize<3>(); const auto body_rotation = cdBody.getRootCollidable()->getTransform().getRotation(); @@ -495,7 +598,7 @@ bool NormalCheckingRayHitCollector::checkNormal( hkVector4f rotated_normal; rotated_normal.setRotatedDir(rotation, hitInfo.m_normal); - return checkDot(mMode, triangle_line.dot<3>(rotated_normal)); + return checkDot(mMode, triangle_normal.dot<3>(rotated_normal)); } } // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physRayCast.h b/src/KingSystem/Physics/System/physRayCast.h index bd11a64f..2557e957 100644 --- a/src/KingSystem/Physics/System/physRayCast.h +++ b/src/KingSystem/Physics/System/physRayCast.h @@ -10,15 +10,22 @@ #include "KingSystem/Physics/physMaterialMask.h" class hkpCollidable; +class hkpShape; struct hkpShapeRayCastInput; struct hkpShapeRayCastOutput; struct hkpWorldRayCastInput; struct hkpWorldRayCastOutput; +namespace ksys::map { +class Object; +} + namespace ksys::phys { struct ActorInfo; +class BodyGroup; class LayerMaskBuilder; +class Phantom; class RigidBody; class SystemGroupHandler; @@ -70,17 +77,16 @@ public: bool worldRayCast(ContactLayerType layer_type); bool shapeRayCast(RigidBody* rigid_body); - // 0x0000007100fc4248 - bool phantomRayCast(void* unk); + bool phantomRayCast(Phantom* phantom); void getHitPosition(sead::Vector3f* position) const; + bool getHitTriangleNormal(sead::Vector3f* normal, const hkpShape* hit_shape, + u32 shape_key) const; void getHitNormal(sead::Vector3f* normal) const; // TODO: rename // 0x0000007100fc4844 - void getUnkVectors(sead::Vector3f* unk1, sead::Vector3f* unk2, void* unk3) const; - - // 0x0000007100fc4bd4 - bool x_1(sead::Vector3f* out) const; + void getUnkVectors(sead::Vector3f* unk1, sead::Vector3f* unk2, sead::Vector3f* unk3) const; + bool getHitTriangleNormal(sead::Vector3f* normal) const; protected: auto& getLayerMask(ContactLayerType type) { return mLayerMasks[int(type)]; } @@ -88,14 +94,9 @@ protected: void worldRayCastImpl(hkpWorldRayCastOutput* output, ContactLayerType layer_type); void shapeRayCastImpl(hkpWorldRayCastOutput* output, RigidBody* body); - // 0x0000007100fc43b0 - void phantomRayCastImpl(hkpWorldRayCastOutput* output); + void phantomRayCastImpl(hkpWorldRayCastOutput* output, Phantom* phantom); - // 0x0000007100fc4630 - const ActorInfo* getActorInfoMaybe(const hkpShapeRayCastOutput& output); - - // 0x0000007100fc4764 - bool x_2(sead::Vector3f* out, void* unk1, int unk2) const; + void updateStaticCompoundObjectInfo(const hkpWorldRayCastOutput& output); void fillCastInput(hkpWorldRayCastInput& input, ContactLayerType layer_type); void fillCastInput(hkpShapeRayCastInput& input, ContactLayerType layer_type); @@ -116,8 +117,8 @@ protected: const hkpCollidable* mHitCollidable; u32 mHitShapeKey; bool mHasHitSpecifiedRigidBody; - void* _58{}; - void* _60; + BodyGroup* mHitBodyGroup{}; + map::Object* mHitMapObject; sead::SafeArray mLayerMasks{}; sead::Atomic _70; NormalCheckingMode mNormalCheckingMode; diff --git a/src/KingSystem/Physics/physMaterialMask.h b/src/KingSystem/Physics/physMaterialMask.h index 69e72c11..ba4bedba 100644 --- a/src/KingSystem/Physics/physMaterialMask.h +++ b/src/KingSystem/Physics/physMaterialMask.h @@ -68,14 +68,12 @@ public: virtual ~MaterialMask(); MaterialMask& operator=(const MaterialMask& other) { - mData = other.mData; - mSubMaterialNameCache = nullptr; + set(other.mData); return *this; } MaterialMask& operator=(MaterialMaskData data) { - mData = data; - mSubMaterialNameCache = nullptr; + set(data); return *this; } @@ -91,6 +89,14 @@ public: const char* getMaterialName() const; const char* getSubMaterialName() const; + void set(MaterialMaskData data) { + mData = data; + mSubMaterialNameCache = nullptr; + } + + void set(u32 data) { set(MaterialMaskData{data}); } + void reset() { set(0); } + void setMaterial(Material mat); static int getSubMaterialIdx(Material mat, const sead::SafeString& submat_name);