mirror of https://github.com/zeldaret/botw.git
ksys/phys: Clarify EntityCollisionMask structure and names
This commit is contained in:
parent
30368facc0
commit
20be3a197a
|
@ -610,7 +610,7 @@ bool RigidBody::isGroundCollisionEnabled() const {
|
|||
|
||||
bool enabled = false;
|
||||
enabled |= info.ground_col_mode != GroundCollisionMode::IgnoreGround;
|
||||
enabled |= info.unk30;
|
||||
enabled |= info.is_ragdoll;
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
@ -636,7 +636,7 @@ bool RigidBody::isWaterCollisionEnabled() const {
|
|||
|
||||
bool enabled = false;
|
||||
// unk30 enables all collisions?
|
||||
enabled |= info.unk30;
|
||||
enabled |= info.is_ragdoll;
|
||||
enabled |= info.water_col_mode != WaterCollisionMode::IgnoreWater;
|
||||
return enabled;
|
||||
}
|
||||
|
|
|
@ -344,7 +344,7 @@ RigidBodyT* RigidBodyFromShape::make(const Shape& shape, RigidBodyInstanceParam*
|
|||
const u32 idx = group_handler ? group_handler->getIndex() : 0;
|
||||
collision_filter_info = [&] {
|
||||
EntityCollisionMask info{collision_filter_info};
|
||||
info.group_handler_index.SetUnsafe(idx);
|
||||
info.regular.group_handler_index.SetUnsafe(idx);
|
||||
return info.raw;
|
||||
}();
|
||||
} else {
|
||||
|
|
|
@ -28,9 +28,9 @@ bool ClosestPointQuery::isSuccess() const {
|
|||
|
||||
void ClosestPointQuery::setLayerMasksAndBodyCollisionFilterInfo(const LayerMaskBuilder& builder) {
|
||||
EntityCollisionMask mask;
|
||||
mask.data.query_custom_receiver_layer_mask =
|
||||
mask.regular.query_custom_receiver_layer_mask =
|
||||
builder.getMasks()[int(ContactLayerType::Entity)].layers;
|
||||
mask.data.layer = ContactLayer::EntityQueryCustomReceiver;
|
||||
mask.regular.layer = ContactLayer::EntityQueryCustomReceiver;
|
||||
mBody->setCollisionFilterInfo(mask.raw);
|
||||
|
||||
setLayerMasks(builder);
|
||||
|
|
|
@ -112,27 +112,30 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const {
|
|||
const EntityCollisionMask a{infoA};
|
||||
const EntityCollisionMask b{infoB};
|
||||
|
||||
constexpr auto GroupHandlerIdxMask = decltype(a.group_handler_index)::GetMask();
|
||||
constexpr auto GroupHandlerIdxShift = decltype(a.group_handler_index)::StartBit();
|
||||
|
||||
if (!EntityCollisionMask(infoA | infoB).is_ground_hit_mask) {
|
||||
if (a.unk30 && b.unk30) {
|
||||
constexpr auto GroupHandlerIdxMask = decltype(a.regular.group_handler_index)::GetMask();
|
||||
constexpr auto GroupHandlerIdxShift = decltype(a.regular.group_handler_index)::StartBit();
|
||||
|
||||
if (a.is_ragdoll && b.is_ragdoll) {
|
||||
if (((infoA ^ infoB) & GroupHandlerIdxMask) != 0) {
|
||||
if (testHandler(a.group_handler_index) || testHandler(b.group_handler_index))
|
||||
if (testHandler(a.regular.group_handler_index) ||
|
||||
testHandler(b.regular.group_handler_index)) {
|
||||
return false;
|
||||
}
|
||||
} else if ((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift != 0) {
|
||||
if (a.data.unk5 == b.data.unk10 || b.data.unk5 == a.data.unk10)
|
||||
if (a.regular.ragdoll_bone_index == b.regular.ragdoll_bone_index2 ||
|
||||
b.regular.ragdoll_bone_index == a.regular.ragdoll_bone_index2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.data.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.data.layer.Value());
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.regular.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.regular.layer.Value());
|
||||
|
||||
if (layerA != ContactLayer::EntityQueryCustomReceiver &&
|
||||
layerB != ContactLayer::EntityQueryCustomReceiver) {
|
||||
if (!a.unk30 && !b.unk30) {
|
||||
if (!a.is_ragdoll && !b.is_ragdoll) {
|
||||
if (!shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
|
@ -140,8 +143,10 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const {
|
|||
}
|
||||
|
||||
if (((infoA ^ infoB) & GroupHandlerIdxMask) != 0) {
|
||||
if (testHandler(a.group_handler_index) || testHandler(b.group_handler_index))
|
||||
if (testHandler(a.regular.group_handler_index) ||
|
||||
testHandler(b.regular.group_handler_index)) {
|
||||
return false;
|
||||
}
|
||||
} else if (((infoA & GroupHandlerIdxMask) >> GroupHandlerIdxShift) > 15) {
|
||||
return false;
|
||||
}
|
||||
|
@ -154,9 +159,9 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const {
|
|||
}
|
||||
|
||||
if (layerA == ContactLayer::EntityQueryCustomReceiver)
|
||||
return a.data.query_custom_receiver_layer_mask & (1 << layerB);
|
||||
return a.regular.query_custom_receiver_layer_mask & (1 << layerB);
|
||||
else
|
||||
return b.data.query_custom_receiver_layer_mask & (1 << layerA);
|
||||
return b.regular.query_custom_receiver_layer_mask & (1 << layerA);
|
||||
}
|
||||
|
||||
if (a.is_ground_hit_mask && b.is_ground_hit_mask) {
|
||||
|
@ -176,37 +181,37 @@ hkBool EntityGroupFilter::testCollisionForEntities(u32 infoA, u32 infoB) const {
|
|||
|
||||
if (a.is_ground_hit_mask && !b.is_ground_hit_mask) {
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.ground_hit.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.data.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.regular.layer.Value());
|
||||
entity_mask = b;
|
||||
ground_hit_mask = a;
|
||||
|
||||
if (layerB == ContactLayer::EntityQueryCustomReceiver)
|
||||
return b.data.query_custom_receiver_layer_mask & (1 << layerA);
|
||||
return b.regular.query_custom_receiver_layer_mask & (1 << layerA);
|
||||
|
||||
if (!b.unk30 && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
if (!b.is_ragdoll && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!b.unk30 && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
if (!b.is_ragdoll && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!testLayerCollision(layerA, layerB))
|
||||
return false;
|
||||
|
||||
} else /* A entity, B ground hit */ {
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.data.layer.Value());
|
||||
const auto layerA = static_cast<ContactLayer::ValueType>(a.regular.layer.Value());
|
||||
const auto layerB = static_cast<ContactLayer::ValueType>(b.ground_hit.layer.Value());
|
||||
entity_mask = a;
|
||||
ground_hit_mask = b;
|
||||
|
||||
if (layerA == ContactLayer::EntityQueryCustomReceiver)
|
||||
return a.data.query_custom_receiver_layer_mask & (1 << layerB);
|
||||
return a.regular.query_custom_receiver_layer_mask & (1 << layerB);
|
||||
|
||||
if (!a.unk30 && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
if (!a.is_ragdoll && !shouldHandleGroundCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!a.unk30 && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
if (!a.is_ragdoll && !shouldHandleWaterCollision(infoA, infoB, layerA, layerB))
|
||||
return false;
|
||||
if (!testLayerCollision(layerB, layerA))
|
||||
return false;
|
||||
}
|
||||
return !(ground_hit_mask.ground_hit.ground_hit_types & (1 << entity_mask.data.ground_hit));
|
||||
return !(ground_hit_mask.ground_hit.ground_hit_types & (1 << entity_mask.regular.ground_hit));
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::testCollisionForPhantom(u32 infoPhantom, u32 infoB) const {
|
||||
|
@ -217,7 +222,7 @@ hkBool EntityGroupFilter::testCollisionForPhantom(u32 infoPhantom, u32 infoB) co
|
|||
const EntityCollisionMask info{infoB};
|
||||
if (info.is_ground_hit_mask)
|
||||
return infoPhantomData.raw & (1 << info.ground_hit.getLayer());
|
||||
return infoPhantomData.layer_mask & (1 << info.data.layer);
|
||||
return infoPhantomData.layer_mask & (1 << info.regular.layer);
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::isCollisionEnabled(const hkpCollidable& a, const hkpCollidable& b) const {
|
||||
|
@ -336,19 +341,19 @@ hkBool EntityGroupFilter::testCollisionForRayCasting(u32 infoRayCast, u32 info)
|
|||
if (b.is_ground_hit_mask)
|
||||
return checkCollisionWithGroundHitMask(b.ground_hit, a);
|
||||
|
||||
const u32 bHandlerIdx = b.group_handler_index;
|
||||
const u32 bHandlerIdx = b.regular.group_handler_index;
|
||||
const u32 aHandlerIdx = a.group_handler_index;
|
||||
|
||||
if (aHandlerIdx == bHandlerIdx) {
|
||||
if (bHandlerIdx > 15)
|
||||
return false;
|
||||
return a.layer_mask & (1 << b.data.layer);
|
||||
return a.layer_mask & (1 << b.regular.layer);
|
||||
}
|
||||
|
||||
if (testHandler(aHandlerIdx) || testHandler(bHandlerIdx))
|
||||
return false;
|
||||
|
||||
return a.layer_mask & (1 << b.data.layer);
|
||||
return a.layer_mask & (1 << b.regular.layer);
|
||||
}
|
||||
|
||||
KSYS_ALWAYS_INLINE hkBool EntityGroupFilter::isCollisionEnabled(const hkpShapeRayCastInput& aInput,
|
||||
|
@ -420,7 +425,7 @@ u32 makeEntityCollisionMask(ContactLayer layer, u32 mask) {
|
|||
if (current.is_ground_hit_mask) {
|
||||
return makeEntityGroundHitMaskImpl<true>(layer, mask).raw;
|
||||
} else {
|
||||
current.data.layer.SetUnsafe(layer);
|
||||
current.regular.layer.SetUnsafe(layer);
|
||||
return current.raw;
|
||||
}
|
||||
}
|
||||
|
@ -430,7 +435,7 @@ u32 setEntityCollisionMaskGroundHit(GroundHit ground_hit, u32 mask) {
|
|||
if (current.is_ground_hit_mask) {
|
||||
// This shouldn't happen: this function is not supposed to be called on ground hit masks.
|
||||
} else {
|
||||
current.data.ground_hit.SetUnsafe(ground_hit);
|
||||
current.regular.ground_hit.SetUnsafe(ground_hit);
|
||||
}
|
||||
return current.raw;
|
||||
}
|
||||
|
|
|
@ -109,17 +109,17 @@ inline u32 EntitySystemGroupHandler::makeCollisionFilterInfo(u32 info, ContactLa
|
|||
EntityCollisionMask result;
|
||||
|
||||
if (layer == ContactLayer::EntityRagdoll) {
|
||||
result.data.layer.Init(layer);
|
||||
result.data.unk5.Init(current_info.data.unk5);
|
||||
result.data.unk10.Init(current_info.data.unk10);
|
||||
result.group_handler_index.Init(getIndex());
|
||||
result.data.ground_hit.Init(ground_hit);
|
||||
result.unk30 = true;
|
||||
result.regular.layer.Init(layer);
|
||||
result.regular.ragdoll_bone_index.Init(current_info.regular.ragdoll_bone_index);
|
||||
result.regular.ragdoll_bone_index2.Init(current_info.regular.ragdoll_bone_index2);
|
||||
result.regular.group_handler_index.Init(getIndex());
|
||||
result.regular.ground_hit.Init(ground_hit);
|
||||
result.is_ragdoll = true;
|
||||
} else {
|
||||
result.data.layer.Init(layer);
|
||||
result.regular.layer.Init(layer);
|
||||
result.ground_col_mode.Init(current_info.ground_col_mode);
|
||||
result.group_handler_index.Init(getIndex());
|
||||
result.data.ground_hit.Init(ground_hit);
|
||||
result.regular.group_handler_index.Init(getIndex());
|
||||
result.regular.ground_hit.Init(ground_hit);
|
||||
}
|
||||
return result.raw;
|
||||
}
|
||||
|
@ -136,9 +136,9 @@ inline u32 EntitySystemGroupHandler::makeQueryCollisionMask(u32 layer_mask, Grou
|
|||
|
||||
inline u32 EntitySystemGroupHandler::makeRagdollCollisionFilterInfo(GroundHit ground_hit) {
|
||||
EntityCollisionMask info;
|
||||
info.data.layer.Init(ContactLayer::EntityRagdoll);
|
||||
info.group_handler_index.Init(getIndex());
|
||||
info.data.ground_hit.Init(ground_hit);
|
||||
info.regular.layer.Init(ContactLayer::EntityRagdoll);
|
||||
info.regular.group_handler_index.Init(getIndex());
|
||||
info.regular.ground_hit.Init(ground_hit);
|
||||
return info.raw;
|
||||
}
|
||||
|
||||
|
@ -193,17 +193,17 @@ inline void EntityGroupFilter::setLayerCustomMask(ContactLayer layer, u32 mask)
|
|||
}
|
||||
|
||||
inline u32 EntityGroupFilter::getCollisionFilterInfoGroupHandlerIdx(u32 info) {
|
||||
return EntityCollisionMask(info).group_handler_index;
|
||||
return EntityCollisionMask(info).regular.group_handler_index;
|
||||
}
|
||||
|
||||
inline u32 EntityGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit,
|
||||
u32 unk5, u32 unk10) {
|
||||
EntityCollisionMask info;
|
||||
info.data.layer.Init(layer);
|
||||
info.data.unk5.Init(unk5);
|
||||
info.data.unk10.Init(unk10);
|
||||
info.data.ground_hit.Init(ground_hit);
|
||||
info.unk30 = true;
|
||||
info.regular.layer.Init(layer);
|
||||
info.regular.ragdoll_bone_index.Init(unk5);
|
||||
info.regular.ragdoll_bone_index2.Init(unk10);
|
||||
info.regular.ground_hit.Init(ground_hit);
|
||||
info.is_ragdoll = true;
|
||||
return info.raw;
|
||||
}
|
||||
|
||||
|
|
|
@ -210,21 +210,28 @@ enum class WaterCollisionMode {
|
|||
IgnoreWater = 1,
|
||||
};
|
||||
|
||||
/// Collision filter info / collision mask that is used for entity rigid bodies.
|
||||
/// https://docs.google.com/spreadsheets/d/e/2PACX-1vQyEL5_Wee3MI23c-nHa4dMPJDVen9TMMcrOUX7Wka9NAH1AW9bkkq7ZJHawJkSzGOqgHUYc-83t4Or/pubhtml
|
||||
union EntityCollisionMask {
|
||||
union Data {
|
||||
union RegularMask {
|
||||
ContactLayer getLayer() const { return int(layer); }
|
||||
ContactLayer getLayerSensor() const { return int(layer + FirstSensor); }
|
||||
GroundHit getGroundHit() const { return int(ground_hit); }
|
||||
|
||||
u32 raw;
|
||||
util::BitField<0, 5, u32> layer;
|
||||
// TODO: figure out what this is
|
||||
util::BitField<5, 5, u32> unk5;
|
||||
util::BitField<10, 5, u32> unk10;
|
||||
|
||||
/// Only valid for ragdoll masks.
|
||||
util::BitField<5, 5, u32> ragdoll_bone_index;
|
||||
/// Only valid for ragdoll masks.
|
||||
util::BitField<10, 5, u32> ragdoll_bone_index2;
|
||||
|
||||
/// Only valid for CustomReceiver masks.
|
||||
/// Layers to collide with for EntityQueryCustomReceiver entities.
|
||||
util::BitField<5, NumRegularEntityLayers, u32> query_custom_receiver_layer_mask;
|
||||
util::BitField<24, 1, u32> unk24;
|
||||
util::BitField<25, 1, u32> unk25;
|
||||
|
||||
/// Only valid for non-CustomReceiver masks.
|
||||
util::BitField<16, 10, u32> group_handler_index;
|
||||
util::BitField<26, 4, u32> ground_hit;
|
||||
};
|
||||
|
||||
|
@ -254,34 +261,34 @@ union EntityCollisionMask {
|
|||
|
||||
static EntityCollisionMask make(ContactLayer layer, GroundHit ground_hit) {
|
||||
EntityCollisionMask mask;
|
||||
mask.data.layer.Init(layer);
|
||||
mask.data.ground_hit.Init(ground_hit);
|
||||
mask.regular.layer.Init(layer);
|
||||
mask.regular.ground_hit.Init(ground_hit);
|
||||
return mask;
|
||||
}
|
||||
|
||||
ContactLayer getLayer() const {
|
||||
return is_ground_hit_mask ? ground_hit.getLayer() : data.getLayer();
|
||||
return is_ground_hit_mask ? ground_hit.getLayer() : regular.getLayer();
|
||||
}
|
||||
|
||||
ContactLayer getLayerSensor() const {
|
||||
return is_ground_hit_mask ? ContactLayer(ContactLayer::SensorCustomReceiver) :
|
||||
data.getLayerSensor();
|
||||
regular.getLayerSensor();
|
||||
}
|
||||
|
||||
GroundHit getGroundHit() const {
|
||||
return is_ground_hit_mask ? GroundHit::HitAll : data.getGroundHit();
|
||||
return is_ground_hit_mask ? GroundHit::HitAll : regular.getGroundHit();
|
||||
}
|
||||
|
||||
u32 raw;
|
||||
Data data;
|
||||
RegularMask regular;
|
||||
GroundHitMask ground_hit;
|
||||
/// Only valid in non-ragdoll, non-CustomReceiver mode.
|
||||
util::BitField<5, 2, GroundCollisionMode, u32> ground_col_mode;
|
||||
/// Only valid in non-ragdoll, non-CustomReceiver mode.
|
||||
util::BitField<7, 1, WaterCollisionMode, u32> water_col_mode;
|
||||
util::BitField<16, 10, u32> group_handler_index;
|
||||
/// If this flag is set, then this entity will always collide with ground or water,
|
||||
/// regardless of the configured GroundCollisionMode or WaterCollisionMode modes.
|
||||
// TODO: is this "is_ragdoll"? See EntitySystemGroupHandler::makeCollisionFilterInfo.
|
||||
util::BitField<30, 1, bool, u32> unk30;
|
||||
util::BitField<30, 1, bool, u32> is_ragdoll;
|
||||
util::BitField<31, 1, bool, u32> is_ground_hit_mask;
|
||||
};
|
||||
static_assert(sizeof(EntityCollisionMask) == sizeof(u32));
|
||||
|
|
Loading…
Reference in New Issue