Path: blob/master/modules/jolt_physics/spaces/jolt_layers.cpp
10278 views
/**************************************************************************/1/* jolt_layers.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "jolt_layers.h"3132#include "../jolt_project_settings.h"33#include "jolt_broad_phase_layer.h"3435#include "core/error/error_macros.h"36#include "core/variant/variant.h"3738static_assert(sizeof(JPH::ObjectLayer) == 2, "Size of Jolt's object layer has changed.");39static_assert(sizeof(JPH::BroadPhaseLayer::Type) == 1, "Size of Jolt's broadphase layer has changed.");40static_assert(JoltBroadPhaseLayer::COUNT <= 8, "Maximum number of broadphase layers exceeded.");4142namespace {4344template <uint8_t TSize = JoltBroadPhaseLayer::COUNT>45class JoltBroadPhaseMatrix {46typedef JPH::BroadPhaseLayer LayerType;47typedef LayerType::Type UnderlyingType;4849public:50JoltBroadPhaseMatrix() {51using namespace JoltBroadPhaseLayer;5253allow_collision(BODY_STATIC, BODY_DYNAMIC);54allow_collision(BODY_STATIC, AREA_DETECTABLE);55allow_collision(BODY_STATIC, AREA_UNDETECTABLE);56allow_collision(BODY_STATIC_BIG, BODY_DYNAMIC);57allow_collision(BODY_STATIC_BIG, AREA_DETECTABLE);58allow_collision(BODY_STATIC_BIG, AREA_UNDETECTABLE);59allow_collision(BODY_DYNAMIC, BODY_STATIC);60allow_collision(BODY_DYNAMIC, BODY_STATIC_BIG);61allow_collision(BODY_DYNAMIC, BODY_DYNAMIC);62allow_collision(BODY_DYNAMIC, AREA_DETECTABLE);63allow_collision(BODY_DYNAMIC, AREA_UNDETECTABLE);64allow_collision(AREA_DETECTABLE, BODY_DYNAMIC);65allow_collision(AREA_DETECTABLE, BODY_STATIC);66allow_collision(AREA_DETECTABLE, BODY_STATIC_BIG);67allow_collision(AREA_DETECTABLE, AREA_DETECTABLE);68allow_collision(AREA_DETECTABLE, AREA_UNDETECTABLE);69allow_collision(AREA_UNDETECTABLE, BODY_DYNAMIC);70allow_collision(AREA_UNDETECTABLE, BODY_STATIC);71allow_collision(AREA_UNDETECTABLE, BODY_STATIC_BIG);72allow_collision(AREA_UNDETECTABLE, AREA_DETECTABLE);73}7475void allow_collision(UnderlyingType p_layer1, UnderlyingType p_layer2) { masks[p_layer1] |= uint8_t(1U << p_layer2); }76void allow_collision(LayerType p_layer1, LayerType p_layer2) { allow_collision((UnderlyingType)p_layer1, (UnderlyingType)p_layer2); }7778bool should_collide(UnderlyingType p_layer1, UnderlyingType p_layer2) const { return (masks[p_layer1] & uint8_t(1U << p_layer2)) != 0; }79bool should_collide(LayerType p_layer1, LayerType p_layer2) const { return should_collide((UnderlyingType)p_layer1, (UnderlyingType)p_layer2); }8081private:82uint8_t masks[TSize] = {};83};8485constexpr JPH::ObjectLayer encode_layers(JPH::BroadPhaseLayer p_broad_phase_layer, JPH::ObjectLayer p_object_layer) {86const uint16_t upper_bits = uint16_t((uint8_t)p_broad_phase_layer << 13U);87const uint16_t lower_bits = uint16_t(p_object_layer);88return JPH::ObjectLayer(upper_bits | lower_bits);89}9091constexpr void decode_layers(JPH::ObjectLayer p_encoded_layers, JPH::BroadPhaseLayer &r_broad_phase_layer, JPH::ObjectLayer &r_object_layer) {92r_broad_phase_layer = JPH::BroadPhaseLayer(uint8_t(p_encoded_layers >> 13U));93r_object_layer = JPH::ObjectLayer(p_encoded_layers & 0b0001'1111'1111'1111U);94}9596constexpr uint64_t encode_collision(uint32_t p_collision_layer, uint32_t p_collision_mask) {97const uint64_t upper_bits = (uint64_t)p_collision_layer << 32U;98const uint64_t lower_bits = (uint64_t)p_collision_mask;99return upper_bits | lower_bits;100}101102constexpr void decode_collision(uint64_t p_collision, uint32_t &r_collision_layer, uint32_t &r_collision_mask) {103r_collision_layer = uint32_t(p_collision >> 32U);104r_collision_mask = uint32_t(p_collision & 0xFFFFFFFFU);105}106107} // namespace108109uint32_t JoltLayers::GetNumBroadPhaseLayers() const {110return JoltBroadPhaseLayer::COUNT;111}112113JPH::BroadPhaseLayer JoltLayers::GetBroadPhaseLayer(JPH::ObjectLayer p_layer) const {114JPH::BroadPhaseLayer broad_phase_layer = JoltBroadPhaseLayer::BODY_STATIC;115JPH::ObjectLayer object_layer = 0;116decode_layers(p_layer, broad_phase_layer, object_layer);117118return broad_phase_layer;119}120121#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)122123const char *JoltLayers::GetBroadPhaseLayerName(JPH::BroadPhaseLayer p_layer) const {124switch ((JPH::BroadPhaseLayer::Type)p_layer) {125case (JPH::BroadPhaseLayer::Type)JoltBroadPhaseLayer::BODY_STATIC: {126return "BODY_STATIC";127}128case (JPH::BroadPhaseLayer::Type)JoltBroadPhaseLayer::BODY_STATIC_BIG: {129return "BODY_STATIC_BIG";130}131case (JPH::BroadPhaseLayer::Type)JoltBroadPhaseLayer::BODY_DYNAMIC: {132return "BODY_DYNAMIC";133}134case (JPH::BroadPhaseLayer::Type)JoltBroadPhaseLayer::AREA_DETECTABLE: {135return "AREA_DETECTABLE";136}137case (JPH::BroadPhaseLayer::Type)JoltBroadPhaseLayer::AREA_UNDETECTABLE: {138return "AREA_UNDETECTABLE";139}140default: {141return "UNKNOWN";142}143}144}145146#endif147148bool JoltLayers::ShouldCollide(JPH::ObjectLayer p_encoded_layer1, JPH::ObjectLayer p_encoded_layer2) const {149JPH::BroadPhaseLayer broad_phase_layer1 = JoltBroadPhaseLayer::BODY_STATIC;150uint32_t collision_layer1 = 0;151uint32_t collision_mask1 = 0;152from_object_layer(p_encoded_layer1, broad_phase_layer1, collision_layer1, collision_mask1);153154JPH::BroadPhaseLayer broad_phase_layer2 = JoltBroadPhaseLayer::BODY_STATIC;155uint32_t collision_layer2 = 0;156uint32_t collision_mask2 = 0;157from_object_layer(p_encoded_layer2, broad_phase_layer2, collision_layer2, collision_mask2);158159const bool first_scans_second = (collision_mask1 & collision_layer2) != 0;160const bool second_scans_first = (collision_mask2 & collision_layer1) != 0;161162return first_scans_second || second_scans_first;163}164165bool JoltLayers::ShouldCollide(JPH::ObjectLayer p_encoded_layer1, JPH::BroadPhaseLayer p_broad_phase_layer2) const {166static const JoltBroadPhaseMatrix matrix;167168JPH::BroadPhaseLayer broad_phase_layer1 = JoltBroadPhaseLayer::BODY_STATIC;169JPH::ObjectLayer object_layer1 = 0;170decode_layers(p_encoded_layer1, broad_phase_layer1, object_layer1);171172return matrix.should_collide(broad_phase_layer1, p_broad_phase_layer2);173}174175JPH::ObjectLayer JoltLayers::_allocate_object_layer(uint64_t p_collision) {176const JPH::ObjectLayer new_object_layer = next_object_layer++;177178collisions_by_layer.resize(new_object_layer + 1);179collisions_by_layer[new_object_layer] = p_collision;180181layers_by_collision[p_collision] = new_object_layer;182183return new_object_layer;184}185186JoltLayers::JoltLayers() {187_allocate_object_layer(0);188}189190// MinGW GCC using LTO will emit errors during linking if this is defined in the header file, implicitly or otherwise.191// Likely caused by this GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94156192JoltLayers::~JoltLayers() = default;193194JPH::ObjectLayer JoltLayers::to_object_layer(JPH::BroadPhaseLayer p_broad_phase_layer, uint32_t p_collision_layer, uint32_t p_collision_mask) {195const uint64_t collision = encode_collision(p_collision_layer, p_collision_mask);196197JPH::ObjectLayer object_layer = 0;198199HashMap<uint64_t, JPH::ObjectLayer>::Iterator iter = layers_by_collision.find(collision);200if (iter != layers_by_collision.end()) {201object_layer = iter->value;202} else {203constexpr uint16_t object_layer_count = 1U << 13U;204205ERR_FAIL_COND_V_MSG(next_object_layer == object_layer_count, 0,206vformat("Maximum number of object layers (%d) reached. "207"This means there are %d combinations of collision layers and masks."208"This should not happen under normal circumstances. Consider reporting this.",209object_layer_count, object_layer_count));210211object_layer = _allocate_object_layer(collision);212}213214return encode_layers(p_broad_phase_layer, object_layer);215}216217void JoltLayers::from_object_layer(JPH::ObjectLayer p_encoded_layer, JPH::BroadPhaseLayer &r_broad_phase_layer, uint32_t &r_collision_layer, uint32_t &r_collision_mask) const {218JPH::ObjectLayer object_layer = 0;219decode_layers(p_encoded_layer, r_broad_phase_layer, object_layer);220221const uint64_t collision = collisions_by_layer[object_layer];222decode_collision(collision, r_collision_layer, r_collision_mask);223}224225226