ksys/phys: Add MaterialMask

This commit is contained in:
Léo Lam 2021-12-30 00:39:17 +01:00
parent 75a270118a
commit eb16cbaf55
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
9 changed files with 223 additions and 45 deletions

View File

@ -79484,20 +79484,20 @@ Address,Quality,Size,Name
0x0000007100e9d484,U,000092, 0x0000007100e9d484,U,000092,
0x0000007100e9d4e0,U,000004,nullsub_4024 0x0000007100e9d4e0,U,000004,nullsub_4024
0x0000007100e9d4e4,U,000004,nullsub_4025 0x0000007100e9d4e4,U,000004,nullsub_4025
0x0000007100e9d4e8,U,000028,Struct9::ctor 0x0000007100e9d4e8,O,000028,_ZN4ksys4phys12MaterialMaskC1Ev
0x0000007100e9d504,U,000028, 0x0000007100e9d504,O,000028,_ZN4ksys4phys12MaterialMaskC1ENS0_16MaterialMaskDataE
0x0000007100e9d520,U,000080, 0x0000007100e9d520,O,000080,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialENS0_9FloorCodeENS0_8WallCodeEb
0x0000007100e9d570,U,000176, 0x0000007100e9d570,O,000176,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialEPKcNS0_9FloorCodeENS0_8WallCodeEb
0x0000007100e9d620,U,000032, 0x0000007100e9d620,O,000032,_ZN4ksys4phys12MaterialMask17getSubMaterialIdxENS0_8MaterialERKN4sead14SafeStringBaseIcEE
0x0000007100e9d640,U,000172, 0x0000007100e9d640,O,000172,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialEiNS0_9FloorCodeENS0_8WallCodeEb
0x0000007100e9d6ec,U,000048, 0x0000007100e9d6ec,O,000048,_ZN4ksys4phys12MaterialMask18getSubMaterialNameENS0_8MaterialEi
0x0000007100e9d71c,U,000004,nullsub_4026 0x0000007100e9d71c,O,000004,_ZN4ksys4phys12MaterialMaskD1Ev
0x0000007100e9d720,U,000004,j__ZdlPv_942 0x0000007100e9d720,O,000004,_ZN4ksys4phys12MaterialMaskD0Ev
0x0000007100e9d724,U,000032, 0x0000007100e9d724,O,000032,_ZNK4ksys4phys12MaterialMask15getMaterialNameEv
0x0000007100e9d744,U,000092,getLastSurface 0x0000007100e9d744,O,000092,_ZNK4ksys4phys12MaterialMask18getSubMaterialNameEv
0x0000007100e9d7a0,U,000028, 0x0000007100e9d7a0,O,000028,_ZN4ksys4phys12MaterialMask18getNumSubMaterialsENS0_8MaterialE
0x0000007100e9d7bc,U,000048, 0x0000007100e9d7bc,O,000048,_ZN4ksys4phys12MaterialMask18getSubMaterialNameEii
0x0000007100e9d7ec,U,000036, 0x0000007100e9d7ec,O,000036,_ZN4ksys4phys12MaterialMask11setMaterialENS0_8MaterialE
0x0000007100e9d810,U,000160, 0x0000007100e9d810,U,000160,
0x0000007100e9d8b0,U,000536, 0x0000007100e9d8b0,U,000536,
0x0000007100e9dac8,U,000296, 0x0000007100e9dac8,U,000296,

Can't render this file because it is too large.

View File

@ -48,6 +48,8 @@ target_sources(uking PRIVATE
System/physGroupFilter.h System/physGroupFilter.h
System/physInstanceSet.cpp System/physInstanceSet.cpp
System/physInstanceSet.h System/physInstanceSet.h
System/physMaterialMask.cpp
System/physMaterialMask.h
System/physMaterialTable.cpp System/physMaterialTable.cpp
System/physMaterialTable.h System/physMaterialTable.h
System/physMemSystem.cpp System/physMemSystem.cpp

View File

@ -13,32 +13,26 @@ CapsuleBody* CapsuleShape::init(sead::Heap* heap) {
auto* hk_shape = auto* hk_shape =
new (ptr) hkpCapsuleShape(hkVector4(vertex_a.x, vertex_a.y, vertex_a.z), new (ptr) hkpCapsuleShape(hkVector4(vertex_a.x, vertex_a.y, vertex_a.z),
hkVector4(vertex_b.x, vertex_b.y, vertex_b.z), radius); hkVector4(vertex_b.x, vertex_b.y, vertex_b.z), radius);
auto* body = new (heap) CapsuleBody(vertex_a, vertex_b, radius, _20, _28, _30, _34, hk_shape); auto* body = new (heap) CapsuleBody(vertex_a, vertex_b, radius, material, sub_material,
floor_code, wall_code, hk_shape);
if (_38) { if (_38) {
body->unk.shape_type = 1 << 23; body->material_mask.getData().flag_23 = true;
} }
body->unk._10 = nullptr; body->material_mask.clearSubMaterialNameCache();
hk_shape->setUserData(body->unk.shape_type); hk_shape->setUserData(body->material_mask.getRawData());
return body; return body;
} }
CapsuleBody* CapsuleBody::clone(sead::Heap* heap) { CapsuleBody* CapsuleBody::clone(sead::Heap* heap) {
CapsuleShape shape; CapsuleShape shape;
shape._20 = 0;
shape._28 = sead::SafeString::cEmptyString.cstr();
shape._30 = 0;
shape._34 = 0;
shape._38 = false;
shape.radius = radius; shape.radius = radius;
shape.vertex_a = vertex_a; shape.vertex_a = vertex_a;
shape.vertex_b = vertex_b; shape.vertex_b = vertex_b;
CapsuleBody* body = shape.init(heap); CapsuleBody* body = shape.init(heap);
body->unk.shape_type = unk.shape_type; body->material_mask = material_mask;
body->unk._10 = nullptr;
if (body->shape != nullptr) if (body->shape != nullptr)
body->shape->setUserData(unk.shape_type); body->shape->setUserData(material_mask.getRawData());
return body; return body;
} }

View File

@ -5,6 +5,8 @@
#include <prim/seadTypedBitFlag.h> #include <prim/seadTypedBitFlag.h>
#include <thread/seadAtomic.h> #include <thread/seadAtomic.h>
#include "KingSystem/Physics/RigidBody/physRigidBody.h" #include "KingSystem/Physics/RigidBody/physRigidBody.h"
#include "KingSystem/Physics/System/physDefines.h"
#include "KingSystem/Physics/System/physMaterialMask.h"
class hkpShape; class hkpShape;
@ -18,17 +20,11 @@ struct CapsuleBody {
Modified = 1 << 0, Modified = 1 << 0,
}; };
struct Unk { CapsuleBody(const sead::Vector3f& va, const sead::Vector3f& vb, f32 r, Material material,
Unk(u32 a1, const char* a2, u32 a3, u32 a4, u32 a5); const char* sub_material, FloorCode floor_code, WallCode wall_code,
virtual ~Unk(); hkpShape* shape_)
: vertex_a(va), vertex_b(vb), radius(r),
u32 shape_type = 0; material_mask(material, sub_material, floor_code, wall_code, false), shape(shape_) {}
const char* _10;
};
CapsuleBody(const sead::Vector3f& va, const sead::Vector3f& vb, f32 r, u32 a4, const char* a5,
u32 a6, u32 a7, hkpShape* a8)
: vertex_a(va), vertex_b(vb), radius(r), unk(a4, a5, a6, a7, 0), shape(a8) {}
virtual ~CapsuleBody(); virtual ~CapsuleBody();
virtual hkpShape* getShape(); virtual hkpShape* getShape();
@ -49,7 +45,7 @@ struct CapsuleBody {
sead::TypedBitFlag<Flag, sead::Atomic<u32>> flags{}; sead::TypedBitFlag<Flag, sead::Atomic<u32>> flags{};
sead::Vector3f vertex_b; sead::Vector3f vertex_b;
f32 radius; f32 radius;
Unk unk; MaterialMask material_mask;
hkpShape* shape; hkpShape* shape;
}; };
@ -60,11 +56,11 @@ struct CapsuleShape {
sead::Vector3f vertex_b; sead::Vector3f vertex_b;
f32 radius; f32 radius;
u32 _1c; u32 _1c;
u32 _20; Material material;
const char* _28; const char* sub_material = sead::SafeString::cEmptyString.cstr();
u32 _30; FloorCode floor_code;
u32 _34; WallCode wall_code;
bool _38; bool _38 = false;
}; };
class CapsuleView : public RigidBodyParamView { class CapsuleView : public RigidBodyParamView {

View File

@ -113,6 +113,10 @@ Misc,\
GrudgeSlow GrudgeSlow
) )
constexpr bool isInvalidMaterial(Material::ValueType mat) {
return mat >= Material::size();
}
SEAD_ENUM(GroundHit, SEAD_ENUM(GroundHit,
Player,\ Player,\
Animal,\ Animal,\

View File

@ -0,0 +1,80 @@
#include "KingSystem/Physics/System/physMaterialMask.h"
#include "KingSystem/Physics/System/physMaterialTable.h"
#include "KingSystem/Physics/System/physMemSystem.h"
namespace ksys::phys {
MaterialMask::MaterialMask() = default;
MaterialMask::MaterialMask(MaterialMaskData data) : mData(data) {}
MaterialMask::MaterialMask(Material mat, FloorCode floor, WallCode wall, bool flag) {
mData.material.Init(mat);
mData.floor.Init(floor);
mData.wall.Init(wall);
mData.setFlag(flag);
}
MaterialMask::MaterialMask(Material mat, const char* submat_name, FloorCode floor, WallCode wall,
bool flag)
: mSubMaterialNameCache(submat_name) {
auto submat_idx = getSubMaterialIdx(mat, submat_name);
if (!MaterialMaskData::isValidSubMaterialIdx(submat_idx))
submat_idx = 0;
mData.raw = {};
mData.material.Init(mat);
mData.sub_material.Init(submat_idx);
mData.floor.Init(floor);
mData.wall.Init(wall);
mData.setFlag(flag);
}
MaterialMask::MaterialMask(Material mat, int submat_idx, FloorCode floor, WallCode wall, bool flag)
: mSubMaterialNameCache(getSubMaterialName(mat, submat_idx).cstr()) {
mData.raw = {};
mData.material.Init(mat);
mData.sub_material.Init(submat_idx);
mData.floor.Init(floor);
mData.wall.Init(wall);
mData.setFlag(flag);
}
MaterialMask::~MaterialMask() = default;
const char* MaterialMask::getMaterialName() const {
const Material material = getMaterial();
if (isInvalidMaterial(material.value()))
return "Incorrent"; // sic
return materialToText(material);
}
const char* MaterialMask::getSubMaterialName() const {
if (mSubMaterialNameCache != nullptr)
return mSubMaterialNameCache;
mSubMaterialNameCache = getSubMaterialName(getMaterial(), getSubMaterialIdx()).cstr();
return mSubMaterialNameCache;
}
int MaterialMask::getSubMaterialIdx(Material mat, const sead::SafeString& submat_name) {
return MemSystem::instance()->getMaterialTable()->getSubMaterialIdx(mat, submat_name);
}
const sead::SafeString& MaterialMask::getSubMaterialName(Material mat, int submat_idx) {
return MemSystem::instance()->getMaterialTable()->getSubMaterial(mat, submat_idx);
}
int MaterialMask::getNumSubMaterials(Material mat) {
return MemSystem::instance()->getMaterialTable()->getNumSubMaterials(mat);
}
const sead::SafeString& MaterialMask::getSubMaterialName(int mat, int submat_idx) {
return getSubMaterialName(Material(mat), submat_idx);
}
void MaterialMask::setMaterial(Material mat) {
mData.material = {};
mData.material.SetUnsafe(mat);
}
} // namespace ksys::phys

View File

@ -0,0 +1,85 @@
#pragma once
#include <basis/seadTypes.h>
#include <prim/seadSafeString.h>
#include "KingSystem/Physics/System/physDefines.h"
#include "KingSystem/Utils/BitField.h"
namespace ksys::phys {
union MaterialMaskData {
constexpr explicit MaterialMaskData(u32 raw_ = 0) : raw(raw_) {}
constexpr MaterialMaskData(const MaterialMaskData&) = default;
constexpr MaterialMaskData& operator=(const MaterialMaskData& other) {
raw = other.raw;
return *this;
}
static constexpr bool isValidSubMaterialIdx(int idx) {
return u32(idx) < (1 << decltype(sub_material)::NumBits());
}
void setFlag(bool b) {
if (!b)
clearFlag();
else
setFlag();
}
void setFlag() { flag = 1; }
void clearFlag() { flag = 0; }
u32 raw;
util::BitField<0, 6, u32> material;
util::BitField<6, 4, int, u32> sub_material;
util::BitField<10, 5, u32> floor;
util::BitField<15, 5, u32> wall;
// TODO: rename
util::BitField<23, 1, u32> flag_23;
// TODO: rename once we figure out what this flag is
util::BitField<31, 1, u32> flag;
};
static_assert(sizeof(MaterialMaskData) == sizeof(u32));
class MaterialMask {
public:
MaterialMask();
explicit MaterialMask(MaterialMaskData data);
MaterialMask(Material mat, FloorCode floor, WallCode wall, bool flag);
MaterialMask(Material mat, const char* submat_name, FloorCode floor, WallCode wall, bool flag);
MaterialMask(Material mat, int submat_idx, FloorCode floor, WallCode wall, bool flag);
MaterialMask(const MaterialMask& other) : mData(other.mData) {}
// XXX: this doesn't need to be virtual.
virtual ~MaterialMask();
MaterialMask& operator=(const MaterialMask& other) {
mData = other.mData;
mSubMaterialNameCache = nullptr;
return *this;
}
MaterialMaskData& getData() { return mData; }
const MaterialMaskData& getData() const { return mData; }
u32 getRawData() const { return mData.raw; }
Material getMaterial() const { return Material::ValueType(mData.material.Value()); }
int getSubMaterialIdx() const { return mData.sub_material; }
const char* getMaterialName() const;
const char* getSubMaterialName() const;
void setMaterial(Material mat);
void clearSubMaterialNameCache() { mSubMaterialNameCache = nullptr; }
static int getSubMaterialIdx(Material mat, const sead::SafeString& submat_name);
static const sead::SafeString& getSubMaterialName(Material mat, int submat_idx);
static int getNumSubMaterials(Material mat);
static const sead::SafeString& getSubMaterialName(int mat, int submat_idx);
private:
MaterialMaskData mData{};
/// Fetching the name of a sub-material from the MaterialTable is an expensive operation,
/// so it is only done once and the result is cached.
mutable const char* mSubMaterialNameCache{};
};
} // namespace ksys::phys

View File

@ -9,9 +9,11 @@ namespace ksys::phys {
class ContactMgr; class ContactMgr;
class GroupFilter; class GroupFilter;
class MaterialTable;
class RigidBody; class RigidBody;
class RigidContactPoints; class RigidContactPoints;
class RigidContactPointsEx; class RigidContactPointsEx;
class SystemData;
class SystemGroupHandler; class SystemGroupHandler;
// FIXME: obviously incomplete. Also this should be moved to its own header // FIXME: obviously incomplete. Also this should be moved to its own header
@ -28,6 +30,8 @@ public:
GroupFilter* getGroupFilter(ContactLayerType type) const; GroupFilter* getGroupFilter(ContactLayerType type) const;
ContactMgr* getContactMgr() const { return mContactMgr; } ContactMgr* getContactMgr() const { return mContactMgr; }
RigidBodyRequestMgr* getRigidBodyRequestMgr() const { return mRigidBodyRequestMgr; } RigidBodyRequestMgr* getRigidBodyRequestMgr() const { return mRigidBodyRequestMgr; }
SystemData* getSystemData() const { return mSystemData; }
MaterialTable* getMaterialTable() const { return mMaterialTable; }
RigidContactPoints* allocContactPoints(sead::Heap* heap, int num, const sead::SafeString& name, RigidContactPoints* allocContactPoints(sead::Heap* heap, int num, const sead::SafeString& name,
int a, int b, int c) const; int a, int b, int c) const;
@ -48,7 +52,11 @@ private:
void* _150; void* _150;
void* _158; void* _158;
RigidBodyRequestMgr* mRigidBodyRequestMgr; RigidBodyRequestMgr* mRigidBodyRequestMgr;
u8 _168[0x480 - 0x168]; void* _168;
void* mRigidBodyDividedMeshShapeMgr;
SystemData* mSystemData;
MaterialTable* mMaterialTable;
u8 _188[0x480 - 0x188];
}; };
KSYS_CHECK_SIZE_NX150(MemSystem, 0x480); KSYS_CHECK_SIZE_NX150(MemSystem, 0x480);

View File

@ -116,6 +116,10 @@ struct BitField {
// so that we can use this within unions // so that we can use this within unions
constexpr BitField() = default; constexpr BitField() = default;
// We declare a user-defined copy assignment operator, so the default copy constructor
// must be defaulted explicitly to avoid a deprecation warning.
constexpr BitField(const BitField&) = default;
// This constructor might be considered ambiguous: // This constructor might be considered ambiguous:
// Would it initialize the storage or just the bitfield? // Would it initialize the storage or just the bitfield?
// Hence, delete it. Use the assignment operator to set bitfield values! // Hence, delete it. Use the assignment operator to set bitfield values!
@ -132,6 +136,11 @@ struct BitField {
storage = (storage & ~GetMask()) | (static_cast<StorageType>(val) << position); storage = (storage & ~GetMask()) | (static_cast<StorageType>(val) << position);
} }
/// @warning Same as SetUnsafe, but assumes this bitfield's bits are zero.
/// This is intended to be called only once to efficiently initialise a bitfield,
/// and will break very badly if called more than once. Using Set() is preferred.
inline constexpr void Init(T val) { storage |= static_cast<StorageType>(val) << position; }
inline constexpr BitField& operator=(const BitField& other) { inline constexpr BitField& operator=(const BitField& other) {
Set(other.Value()); Set(other.Value());
return *this; return *this;