ksys/phys: Add RigidBodyParam

This commit is contained in:
Léo Lam
2021-04-22 15:04:39 +02:00
parent 7a2e380f2b
commit cbe711e595
6 changed files with 388 additions and 15 deletions
+2
View File
@@ -7,6 +7,8 @@ target_sources(uking PRIVATE
Ragdoll/physRagdollParam.h
RigidBody/physEdgeRigidBodyParam.cpp
RigidBody/physEdgeRigidBodyParam.h
RigidBody/physRigidBodyParam.cpp
RigidBody/physRigidBodyParam.h
SupportBone/physSupportBoneParam.cpp
SupportBone/physSupportBoneParam.h
System/physCharacterControllerParam.cpp
@@ -0,0 +1,156 @@
#include "KingSystem/Physics/RigidBody/physRigidBodyParam.h"
#include "KingSystem/Physics/System/physShapeParam.h"
namespace ksys::phys {
RigidBodyParam::RigidBodyParam() = default;
RigidBodyParam::~RigidBodyParam() = default;
RigidBodyParam::Info::Info()
: rigid_body_name("RigidBody", "rigid_body_name", this), mass(1.0, "mass", this),
volume(0.0, "volume", this), toi(false, "toi", this),
mEnableAutoAddWorld(false, "mEnableAutoAddWorld", this), navmesh("NOT_USE", "navmesh", this),
navmesh_sub_material("Others", "navmesh_sub_material", this),
inertia(sead::Vector3f::ones, "inertia", this),
center_of_mass(sead::Vector3f::zero, "center_of_mass", this),
bounding_center(sead::Vector3f::zero, "bounding_center", this),
bounding_extents(sead::Vector3f::zero, "bounding_extents", this),
contact_point_info(sead::SafeString::cEmptyString, "contact_point_info", this),
collision_info(sead::SafeString::cEmptyString, "collision_info", this),
max_linear_velocity(200.0, "max_linear_velocity", this),
linear_damping(0.0, "linear_damping", this),
max_angular_velocity_rad(200.0, "max_angular_velocity_rad", this),
angular_damping(0.05, "angular_damping", this), max_impulse(-1.0, "max_impulse", this),
col_impulse_scale(1.0, "col_impulse_scale", this),
ignore_normal_for_impulse(false, "ignore_normal_for_impulse", this),
always_character_mass_scaling(false, "always_character_mass_scaling", this),
friction_scale(1.0, "friction_scale", this),
restitution_scale(1.0, "restitution_scale", this),
water_buoyancy_scale(1.0, "water_buoyancy_scale", this),
water_flow_effective_rate(1.0, "water_flow_effective_rate", this),
magne_mass_scaling_factor(1.0, "magne_mass_scaling_factor", this),
motion_type("Fixed", "motion_type", this),
layer(sead::SafeString::cEmptyString, "layer", this),
groundhit(sead::SafeString::cEmptyString, "groundhit", this),
use_ground_hit_type_mask(false, "use_ground_hit_type_mask", this),
ground_hit_type_mask(sead::SafeString::cEmptyString, "ground_hit_type_mask", this),
receiver_type(sead::SafeString::cEmptyString, "receiver_type", this),
no_hit_ground(false, "no_hit_ground", this), no_hit_water(false, "no_hit_water", this),
no_char_standing_on(false, "no_char_standing_on", this),
contact_mask(0, "contact_mask", this),
link_matrix(sead::SafeString::cEmptyString, "link_matrix", this),
link_entity_set(sead::SafeString::cEmptyString, "link_entity_set", this),
link_entity_body(sead::SafeString::cEmptyString, "link_entity_body", this),
use_entity_shape(false, "use_entity_shape", this), shape_num(0, "shape_num", this) {}
RigidBodyParam::Info::~Info() = default;
bool RigidBodyParam::parse(const agl::utl::ResParameterList& res_list, sead::Heap* heap) {
if (!res_list)
return false;
info.applyResParameterObj(res_list.getResParameterObj(0), nullptr);
const int num_shapes = info.shape_num.ref();
if (num_shapes < 1)
return true;
shapes.allocBufferAssert(num_shapes, heap);
for (int i = 0; i < num_shapes; ++i) {
if (!shapes[i].parse(res_list.getResParameterObj(i + 1), heap))
return false;
}
return true;
}
ContactLayer RigidBodyParam::getContactLayer() const {
return contactLayerFromText(*info.layer);
}
GroundHit RigidBodyParam::getGroundHit() const {
return groundHitFromText(*info.groundhit);
}
MotionType RigidBodyParam::getMotionType() const {
return motionTypeFromText(*info.motion_type);
}
// TODO: move this to another translation unit (figure out where this belongs)
[[gnu::noinline]] static u32 orGroundHitTypeMask(u32 mask, const sead::SafeString& type) {
mask |= (0x100 << groundHitFromText(type)) & 0xffff00;
return mask;
}
namespace {
constexpr const char* navmesh_types[] = {
"NOT_USE",
"STATIC_CUTTING",
"STATIC_WALKABLE_AND_CUTTING",
"STATIC_WALKABLE_AND_CUTTING_CGO",
"STATIC_DEPENDS_ON_WALL_CODE",
"STATIC_ENEMY_ONLY",
"STATIC_NPC_ONLY",
"STATIC_LOW_CEILING",
"STATIC_GIANT_NO_ENTRY_PAINT",
"STATIC_CUTTING_CARVER",
"STATIC_AIR_WALL_FOR_HORSE",
"STATIC_FENCE_FOR_HORSE",
"STATIC_CUTTING_LARGE",
"STATIC_CURSE",
"DYNAMIC_OBSTACLE",
"DYNAMIC_SILHOUETTE_AND_OBSTACLE",
"DYNAMIC_WITHOUT_TOLERANCE",
"MATERIAL_PAINT_AND_OBSTACLE",
"MATERIAL_PAINT",
"MATERIAL_WITHOUT_TOLERANCE",
};
struct NavMeshSubMaterialInfo {
sead::SafeString name;
NavMeshSubMaterial value;
};
} // namespace
void RigidBodyParam::Info::postRead_() {
for (int i = 0; i < int(std::size(navmesh_types)); ++i) {
if (*navmesh == navmesh_types[i]) {
navmesh_val = NavMeshType(i);
break;
}
}
navmesh_sub_material_val = NavMeshSubMaterial::None;
const NavMeshSubMaterialInfo sub_material_info[] = {
{"LiftableByEnemy", NavMeshSubMaterial::LiftableByEnemy},
{"Fire", NavMeshSubMaterial::Fire},
{"Curse", NavMeshSubMaterial::Curse},
{"NPCOnly", NavMeshSubMaterial::NPCOnly},
{"GiantNoEntry", NavMeshSubMaterial::GiantNoEntry},
{"Pass", NavMeshSubMaterial::Pass},
};
for (int i = 0; i < int(std::size(sub_material_info)); ++i) {
if (*navmesh_sub_material == sub_material_info[i].name) {
navmesh_sub_material_val = sub_material_info[i].value;
break;
}
}
if (*use_ground_hit_type_mask && !ground_hit_type_mask->isEmpty()) {
ground_hit_type_mask_val = 0;
sead::FixedSafeString<64> type_str;
auto it = ground_hit_type_mask->tokenBegin(",");
const auto end = ground_hit_type_mask->tokenEnd(",");
while (end != it) {
it.getAndForward(&type_str);
if (!type_str.isEmpty())
ground_hit_type_mask_val = orGroundHitTypeMask(ground_hit_type_mask_val, type_str);
}
} else {
ground_hit_type_mask_val = 0;
}
}
} // namespace ksys::phys
@@ -0,0 +1,160 @@
#pragma once
#include <agl/Utils/aglParameter.h>
#include <agl/Utils/aglParameterList.h>
#include <agl/Utils/aglParameterObj.h>
#include <container/seadBuffer.h>
#include <prim/seadRuntimeTypeInfo.h>
#include "KingSystem/Physics/System/physDefines.h"
#include "KingSystem/Utils/Types.h"
namespace ksys::phys {
// TODO: maybe move this to NavMesh/?
enum class NavMeshType {
NOT_USE,
STATIC_CUTTING,
STATIC_WALKABLE_AND_CUTTING,
STATIC_WALKABLE_AND_CUTTING_CGO,
STATIC_DEPENDS_ON_WALL_CODE,
STATIC_ENEMY_ONLY,
STATIC_NPC_ONLY,
STATIC_LOW_CEILING,
STATIC_GIANT_NO_ENTRY_PAINT,
STATIC_CUTTING_CARVER,
STATIC_AIR_WALL_FOR_HORSE,
STATIC_FENCE_FOR_HORSE,
STATIC_CUTTING_LARGE,
STATIC_CURSE,
DYNAMIC_OBSTACLE,
DYNAMIC_SILHOUETTE_AND_OBSTACLE,
DYNAMIC_WITHOUT_TOLERANCE,
MATERIAL_PAINT_AND_OBSTACLE,
MATERIAL_PAINT,
MATERIAL_WITHOUT_TOLERANCE,
};
enum class NavMeshSubMaterial {
LiftableByEnemy = 0xf,
Fire = 0x10,
Curse = 0x11,
NPCOnly = 0x12,
GiantNoEntry = 0x13,
Pass = 0x14,
None = 0x15,
};
struct ShapeParam;
struct RigidBodyParamView {
SEAD_RTTI_BASE(RigidBodyParamView)
public:
const char* name;
u32 _10;
MotionType motion_type;
float mass;
sead::Vector3f inertia;
sead::Vector3f center_of_mass;
float linear_damping;
float angular_damping;
u8 _3c[8];
float max_linear_velocity;
float max_angular_velocity_rad;
float max_impulse;
float col_impulse_scale;
float friction_scale;
float restitution_scale;
float water_buoyancy_scale;
float water_flow_effective_rate;
float magne_mass_scaling_factor;
bool gap68;
bool toi;
bool always_character_mass_scaling;
bool gap6B[13];
ContactLayer contact_layer;
GroundHit groundhit;
u32 info_5e0;
u32 contact_mask;
u32 flags;
bool ignore_normal_for_impulse;
bool no_hit_ground;
bool no_hit_water;
bool no_char_standing_on;
};
KSYS_CHECK_SIZE_NX150(RigidBodyParamView, 0x90);
struct RigidBodyParam : agl::utl::ParameterList {
struct Info : agl::utl::ParameterObj {
Info();
~Info() override;
agl::utl::Parameter<sead::SafeString> rigid_body_name;
agl::utl::Parameter<float> mass;
agl::utl::Parameter<float> volume;
agl::utl::Parameter<bool> toi;
agl::utl::Parameter<bool> mEnableAutoAddWorld;
agl::utl::Parameter<sead::SafeString> navmesh;
agl::utl::Parameter<sead::SafeString> navmesh_sub_material;
agl::utl::Parameter<sead::Vector3f> inertia;
agl::utl::Parameter<sead::Vector3f> center_of_mass;
agl::utl::Parameter<sead::Vector3f> bounding_center;
agl::utl::Parameter<sead::Vector3f> bounding_extents;
agl::utl::Parameter<sead::SafeString> contact_point_info;
agl::utl::Parameter<sead::SafeString> collision_info;
agl::utl::Parameter<float> max_linear_velocity;
agl::utl::Parameter<float> linear_damping;
agl::utl::Parameter<float> max_angular_velocity_rad;
agl::utl::Parameter<float> angular_damping;
agl::utl::Parameter<float> max_impulse;
agl::utl::Parameter<float> col_impulse_scale;
agl::utl::Parameter<bool> ignore_normal_for_impulse;
agl::utl::Parameter<bool> always_character_mass_scaling;
agl::utl::Parameter<float> friction_scale;
agl::utl::Parameter<float> restitution_scale;
agl::utl::Parameter<float> water_buoyancy_scale;
agl::utl::Parameter<float> water_flow_effective_rate;
agl::utl::Parameter<float> magne_mass_scaling_factor;
agl::utl::Parameter<sead::SafeString> motion_type;
agl::utl::Parameter<sead::SafeString> layer;
agl::utl::Parameter<sead::SafeString> groundhit;
agl::utl::Parameter<bool> use_ground_hit_type_mask;
agl::utl::Parameter<sead::SafeString> ground_hit_type_mask;
agl::utl::Parameter<sead::SafeString> receiver_type;
agl::utl::Parameter<bool> no_hit_ground;
agl::utl::Parameter<bool> no_hit_water;
agl::utl::Parameter<bool> no_char_standing_on;
agl::utl::Parameter<u32> contact_mask;
agl::utl::Parameter<sead::SafeString> link_matrix;
agl::utl::Parameter<sead::SafeString> link_entity_set;
agl::utl::Parameter<sead::SafeString> link_entity_body;
agl::utl::Parameter<bool> use_entity_shape;
agl::utl::Parameter<int> shape_num;
NavMeshType navmesh_val = NavMeshType::NOT_USE;
NavMeshSubMaterial navmesh_sub_material_val = NavMeshSubMaterial::None;
u32 ground_hit_type_mask_val = 0;
protected:
void postRead_() override;
};
RigidBodyParam();
~RigidBodyParam() override;
RigidBodyParam(const RigidBodyParam&) = delete;
auto operator=(const RigidBodyParam&) = delete;
bool parse(const agl::utl::ResParameterList& res_list, sead::Heap* heap);
// TODO: types and names
void* createRigidBody(void* x, sead::Heap* heap, bool y);
bool getParams(RigidBodyParamView* view) const;
void* createEntityShape(void* x, void* y, sead::Heap* heap);
ContactLayer getContactLayer() const;
GroundHit getGroundHit() const;
MotionType getMotionType() const;
Info info;
sead::Buffer<ShapeParam> shapes;
};
} // namespace ksys::phys
@@ -26,6 +26,18 @@ Material materialFromText(const sead::SafeString& text) {
return 0;
}
const char* groundHitToText(GroundHit hit) {
return hit.text();
}
GroundHit groundHitFromText(const sead::SafeString& text) {
for (auto hit : GroundHit()) {
if (text == hit.text())
return hit;
}
return GroundHit::HitAll;
}
const char* floorCodeToText(FloorCode code) {
return code.text();
}
@@ -50,4 +62,15 @@ WallCode wallCodeFromText(const sead::SafeString& text) {
return 0;
}
// NON_MATCHING: duplicated branches?
MotionType motionTypeFromText(const sead::SafeString& text) {
if (text == "Dynamic")
return MotionType::Dynamic;
if (text == "Fixed")
return MotionType::Fixed;
if (text == "Keyframed")
return MotionType::Keyframed;
return MotionType::Unknown;
}
} // namespace ksys::phys
@@ -103,6 +103,26 @@ Misc,\
GrudgeSlow
)
SEAD_ENUM(GroundHit,
Player,\
Animal,\
NPC,\
Camera,\
AttackHitPlayer,\
AttackHitEnemy,\
Arrow,\
Bomb,\
Magnet,\
CameraBody,\
IK,\
Grudge,\
MovingTrolley,\
LineOfSight,\
Giant,\
HitAll,\
Ignore
)
SEAD_ENUM(FloorCode,
None,\
Return,\
@@ -132,16 +152,28 @@ NoDashUpAndNoClimb,\
IceMakerBlock
)
enum class MotionType {
Dynamic = 0,
Fixed = 1,
Keyframed = 2,
Unknown = 3,
};
const char* contactLayerToText(ContactLayer layer);
ContactLayer contactLayerFromText(const sead::SafeString& text);
const char* materialToText(Material material);
Material materialFromText(const sead::SafeString& text);
const char* groundHitToText(GroundHit hit);
GroundHit groundHitFromText(const sead::SafeString& text);
const char* floorCodeToText(FloorCode code);
FloorCode floorCodeFromText(const sead::SafeString& text);
const char* wallCodeToText(WallCode code);
WallCode wallCodeFromText(const sead::SafeString& text);
MotionType motionTypeFromText(const sead::SafeString& text);
} // namespace ksys::phys