diff --git a/data/uking_functions.csv b/data/uking_functions.csv index ba833e2f..2d49b81f 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -95407,20 +95407,20 @@ Address,Quality,Size,Name 0x00000071012b086c,O,000112,_ZN4ksys4phys17RigidBodySetParamD0Ev 0x00000071012b08dc,O,000460,_ZN4ksys4phys17RigidBodySetParam5parseEN3agl3utl16ResParameterListEPN4sead4HeapE 0x00000071012b0aa8,O,000008,_ZNK4ksys4phys17RigidBodySetParam17getNumRigidBodiesEv -0x00000071012b0ab0,U,000992,CharacterPrismShape::make -0x00000071012b0e90,U,000240, -0x00000071012b0f80,U,000012, -0x00000071012b0f8c,U,000068,CharacterPrismShape::dtor -0x00000071012b0fd0,U,000068,CharacterPrismShape::dtord -0x00000071012b1014,U,000008, -0x00000071012b101c,U,000016,CharacterPrismShape::getVol -0x00000071012b102c,U,000016,CharacterPrismShape::getShape -0x00000071012b103c,U,000016,CharacterPrismShape::getShape_0 -0x00000071012b104c,U,000016,CharacterPrismShape::updateShape -0x00000071012b105c,U,000444,CharacterPrismShape::setScale -0x00000071012b1218,U,000204,CharacterPrismShape::rtti1 -0x00000071012b12e4,U,000092,CharacterPrismShape::rtti2 -0x00000071012b1340,U,000008,CharacterPrismShape::getType +0x00000071012b0ab0,O,000992,_ZN4ksys4phys19CharacterPrismShape4makeERKNS0_24CharacterPrismShapeParamEPN4sead4HeapE +0x00000071012b0e90,O,000240,_ZNK4ksys4phys19CharacterPrismShape5cloneEPN4sead4HeapE +0x00000071012b0f80,O,000012,_ZNK4ksys4phys19CharacterPrismShape15getMaterialMaskEv +0x00000071012b0f8c,O,000068,_ZN4ksys4phys19CharacterPrismShapeD1Ev +0x00000071012b0fd0,O,000068,_ZN4ksys4phys19CharacterPrismShapeD0Ev +0x00000071012b1014,O,000008,_ZN4ksys4phys19CharacterPrismShape15setMaterialMaskERKNS0_12MaterialMaskE +0x00000071012b101c,O,000016,_ZNK4ksys4phys19CharacterPrismShape9getVolumeEv +0x00000071012b102c,O,000016,_ZN4ksys4phys19CharacterPrismShape13getHavokShapeEv +0x00000071012b103c,O,000016,_ZNK4ksys4phys19CharacterPrismShape13getHavokShapeEv +0x00000071012b104c,O,000016,_ZN4ksys4phys19CharacterPrismShape16updateHavokShapeEv +0x00000071012b105c,O,000444,_ZN4ksys4phys19CharacterPrismShape8setScaleEf +0x00000071012b1218,O,000204,_ZNK4ksys4phys19CharacterPrismShape27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x00000071012b12e4,O,000092,_ZNK4ksys4phys19CharacterPrismShape18getRuntimeTypeInfoEv +0x00000071012b1340,O,000008,_ZNK4ksys4phys19CharacterPrismShape7getTypeEv 0x00000071012b1348,O,000096,_ZN4ksys4phys25TeraMeshRigidBodyResourceD1Ev 0x00000071012b13a8,O,000096,_ZThn32_N4ksys4phys25TeraMeshRigidBodyResourceD1Ev 0x00000071012b1408,O,000104,_ZN4ksys4phys25TeraMeshRigidBodyResourceD0Ev diff --git a/lib/hkStubs/CMakeLists.txt b/lib/hkStubs/CMakeLists.txt index 44473760..616d12a2 100644 --- a/lib/hkStubs/CMakeLists.txt +++ b/lib/hkStubs/CMakeLists.txt @@ -96,6 +96,7 @@ add_library(hkStubs OBJECT Havok/Common/Serialize/Util/hkRootLevelContainer.h Havok/Geometry/Collide/Shapes/hkcdShape.h + Havok/Geometry/Internal/Types/hkcdVertex.h Havok/Physics/Constraint/Atom/hkpConstraintAtom.h Havok/Physics/Constraint/Data/hkpConstraintData.h diff --git a/lib/hkStubs/Havok/Geometry/Internal/Types/hkcdVertex.h b/lib/hkStubs/Havok/Geometry/Internal/Types/hkcdVertex.h new file mode 100644 index 00000000..ddae5b0d --- /dev/null +++ b/lib/hkStubs/Havok/Geometry/Internal/Types/hkcdVertex.h @@ -0,0 +1,5 @@ +#pragma once + +#include "Havok/Common/Base/Math/hkMath.h" + +class hkcdVertex : public hkVector4f {}; diff --git a/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.cpp b/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.cpp index ab2e87e0..1e58d6d8 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.cpp @@ -1 +1,181 @@ #include "KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h" +#include +#include +#include +#include "KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h" +#include "KingSystem/Physics/physConversions.h" + +namespace ksys::phys { + +void CharacterPrismShape::setMaterialMask(const MaterialMask& mask) { + mShape->setMaterialMask(mask); +} + +const MaterialMask& CharacterPrismShape::getMaterialMask() const { + return mShape->getMaterialMask(); +} + +static const sead::Vector3f& sOrigin = sead::Vector3f::zero; + +CharacterPrismShape* CharacterPrismShape::make(const CharacterPrismShapeParam& param, + sead::Heap* heap) { + PolytopeShapeParam polytope_shape_param; + polytope_shape_param.vertex_num = SHAPE_VERTEX_NUM; + polytope_shape_param.common.material = param.common.material; + polytope_shape_param.common.sub_material = param.common.sub_material; + polytope_shape_param.common.floor_code = param.common.floor_code; + polytope_shape_param.common.wall_code = param.common.wall_code; + polytope_shape_param.common.item_code_disable_stick = param.common.item_code_disable_stick; + + auto* polytope_shape = PolytopeShape::make(polytope_shape_param, heap); + + /* + * Set all vertices. + */ + + // Set first vertex + polytope_shape->setVertex(0, sOrigin + param.offset); + + for (int i = 0, vertex_idx = 1; i < RING_VERTEX_NUM; i++, vertex_idx += 2) { + float ring_x = param.radius * sin((float)i * (float)M_PI_4); + float ring_z = param.radius * cos((float)i * (float)M_PI_4); + + // First ring + polytope_shape->setVertex(vertex_idx, sead::Vector3f(ring_x, param.ring0_distance, ring_z) + + param.offset); + + // Second ring + polytope_shape->setVertex( + vertex_idx + 1, sead::Vector3f(ring_x, param.ring1_distance, ring_z) + param.offset); + } + + // Set last vertex + polytope_shape->setVertex(SHAPE_VERTEX_NUM - 1, + param.end_vertex_distance * sead::Vector3f::ey + param.offset); + + polytope_shape->updateHavokShape(); + + /* + * Set all vertices again, but move the bottom so that it lies at y=0. + * This is undone if `CharacterPrismShape::setScale` is called. + */ + + // Get lowest vertex + hkcdVertex supporting_vertex; + polytope_shape->getVerticesShape()->getSupportingVertex(hkVector4f(0.0f, -1.0f, 0.0f), + supporting_vertex); + // Get y-value of the lowest point of collision + float min_vertex_y = + supporting_vertex[1] + 0.0f - polytope_shape->getVerticesShape()->getRadius(); + + // Set first vertex + // Move to lie at y=0 + polytope_shape->setVertex(0, sOrigin + param.offset - min_vertex_y * sead::Vector3f::ey); + + for (int i = 0, vertex_idx = 1; i < RING_VERTEX_NUM; i++, vertex_idx += 2) { + float ring_x = param.radius * sin((float)i * (float)M_PI_4); + float ring_z = param.radius * cos((float)i * (float)M_PI_4); + + // First ring + polytope_shape->setVertex(vertex_idx, sead::Vector3f(ring_x, param.ring0_distance, ring_z) + + param.offset - min_vertex_y * sead::Vector3f::ey); + + // Second ring + polytope_shape->setVertex( + vertex_idx + 1, sead::Vector3f(ring_x, param.ring1_distance, ring_z) + param.offset); + } + + // Set last vertex + polytope_shape->setVertex(SHAPE_VERTEX_NUM - 1, + param.end_vertex_distance * sead::Vector3f::ey + param.offset); + + polytope_shape->updateHavokShape(); + + auto* shape = new (heap) CharacterPrismShape; + shape->mShape = polytope_shape; + shape->mRadius = param.radius; + shape->mRing0Distance = param.ring0_distance; + shape->mRing1Distance = param.ring1_distance; + shape->mEndVertexDistance = param.end_vertex_distance; + shape->mOffset.e = param.offset.e; + shape->mScale = 1.0f; + return shape; +} + +CharacterPrismShape* CharacterPrismShape::clone(sead::Heap* heap) const { + CharacterPrismShapeParam param; + param.radius = mRadius; + param.end_vertex_distance = mEndVertexDistance; + param.ring1_distance = mRing1Distance; + param.ring0_distance = mRing0Distance; + param.offset = mOffset; + param.common.material = mShape->getMaterialMask().getMaterial(); + param.common.sub_material = mShape->getMaterialMask().getSubMaterialName(); + param.common.floor_code = mShape->getMaterialMask().getFloorCode(); + param.common.wall_code = mShape->getMaterialMask().getWallCode(); + auto data = mShape->getMaterialMask().getData(); + param.common.item_code_disable_stick = data.getCustomFlag(MaterialMaskData::CustomFlag::_0); + return make(param, heap); +} + +float CharacterPrismShape::getVolume() const { + return mShape->getVolume(); +} + +hkpShape* CharacterPrismShape::getHavokShape() { + // For some reason, this non-const function is calling the const function `getHavokShapeConst`. + return const_cast(mShape->getHavokShapeConst()); +} + +const hkpShape* CharacterPrismShape::getHavokShape() const { + return mShape->getHavokShapeConst(); +} + +const hkpShape* CharacterPrismShape::updateHavokShape() { + return mShape->updateHavokShape(); +} + +void CharacterPrismShape::setScale(float scale) { + // `mScale` is scaled relatively by `scale`, but vertices are scaled absolutely. + // Using `CharacterPrismShape::setScale` more than once will put `mScale` out of sync with + // the actual scale. + mScale *= scale; + + float volume = getVolume(); + + auto scaled_offset = mOffset * scale; + float scaled_end_vertex_distance = mEndVertexDistance * scale; + float scaled_radius = mRadius * scale; + float ring_y0 = mRing0Distance * scale; + float ring_y1 = mRing1Distance * scale; + + // Set first vertex + mShape->setVertex(0, sOrigin + scaled_offset); + + for (int i = 0, vertex_idx = 1; i < RING_VERTEX_NUM; i++, vertex_idx += 2) { + // For some reason `sin` is used for x and `cos` is used for z. + float ring_x = scaled_radius * sin((float)i * (float)M_PI_4); + float ring_z = scaled_radius * cos((float)i * (float)M_PI_4); + + // First ring + mShape->setVertex(vertex_idx, sead::Vector3f{ring_x, ring_y0, ring_z} + scaled_offset); + + // Second ring + mShape->setVertex(vertex_idx + 1, sead::Vector3f{ring_x, ring_y1, ring_z} + scaled_offset); + } + + // Set last vertex + mShape->setVertex(SHAPE_VERTEX_NUM - 1, + scaled_end_vertex_distance * sead::Vector3f::ey + scaled_offset); + + mShape->setVolume(scale * scale * scale * volume); +} + +CharacterPrismShape::~CharacterPrismShape() { + if (mShape) { + delete mShape; + mShape = nullptr; + } +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h b/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h index 63e4b238..1724835b 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/CharacterPrism/physCharacterPrismShape.h @@ -9,25 +9,49 @@ class PolytopeShape; struct CharacterPrismShapeParam { float radius = 0.35; - sead::Vector3f translate_0 = {0.5, 1.5, 1.8}; - sead::Vector3f translate_1 = sead::Vector3f::zero; + float ring0_distance = 0.5; + float ring1_distance = 1.5; + float end_vertex_distance = 1.8; + sead::Vector3f offset = sead::Vector3f::zero; CommonShapeParam common; }; +/// A "stretched bipyramid" shape with a top and bottom vertex and two rings of eight vertices +/// between them. class CharacterPrismShape : public Shape { SEAD_RTTI_OVERRIDE(CharacterPrismShape, Shape) + public: + ~CharacterPrismShape() override; + static CharacterPrismShape* make(const CharacterPrismShapeParam& param, sead::Heap* heap); CharacterPrismShape* clone(sead::Heap* heap) const; void setMaterialMask(const MaterialMask& mask); const MaterialMask& getMaterialMask() const; + ShapeType getType() const override { return ShapeType::CharacterPrism; } + float getVolume() const override; + hkpShape* getHavokShape() override; + const hkpShape* getHavokShape() const override; + const hkpShape* updateHavokShape() override; + void setScale(float scale) override; + PolytopeShape* getUnderlyingShape() const { return mShape; } private: + static constexpr int RING_VERTEX_NUM = 8; + static constexpr int SHAPE_VERTEX_NUM = RING_VERTEX_NUM * 2 + 2; + /// The underlying shape for this character prism shape. PolytopeShape* mShape{}; + + float mRadius; + float mRing0Distance; + float mRing1Distance; + float mEndVertexDistance; + sead::Vector3f mOffset; + float mScale; }; } // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h index bc7a64f2..3a62e7a6 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeShape.h @@ -57,6 +57,8 @@ public: void setMaterialMask(const MaterialMask& mask); const MaterialMask& getMaterialMask() const { return mMaterialMask; } + const hkpConvexVerticesShape* getVerticesShape() const { return mHavokShape; } + private: bool init(const PolytopeShapeParam& param, sead::Heap* heap); diff --git a/src/KingSystem/Physics/RigidBody/Shape/physShapeParamObj.cpp b/src/KingSystem/Physics/RigidBody/Shape/physShapeParamObj.cpp index 2daebe8c..90a04023 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/physShapeParamObj.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/physShapeParamObj.cpp @@ -104,8 +104,10 @@ void ShapeParamObj::getPolytope(PolytopeShapeParam* param) const { void ShapeParamObj::getCharacterPrism(CharacterPrismShapeParam* param) const { param->radius = *radius; - param->translate_0 = *translate_0; - param->translate_1 = *translate_1; + param->ring0_distance = translate_0->x; + param->ring1_distance = translate_0->y; + param->end_vertex_distance = translate_0->z; + param->offset = *translate_1; getCommon(¶m->common); } diff --git a/src/KingSystem/Physics/physMaterialMask.h b/src/KingSystem/Physics/physMaterialMask.h index ba4bedba..33e3b466 100644 --- a/src/KingSystem/Physics/physMaterialMask.h +++ b/src/KingSystem/Physics/physMaterialMask.h @@ -41,6 +41,10 @@ union MaterialMaskData { raw |= 1 << (decltype(custom_flags)::StartBit() + custom_flag); } + bool getCustomFlag(CustomFlag custom_flag) const { + return (raw & 1 << (decltype(custom_flags)::StartBit() + custom_flag)) != 0; + } + u32 raw; util::BitField<0, 6, u32> material; util::BitField<6, 4, int, u32> sub_material;