Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/SubShapeID.h
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56JPH_NAMESPACE_BEGIN78/// @brief A sub shape id contains a path to an element (usually a triangle or other primitive type) of a compound shape9///10/// Each sub shape knows how many bits it needs to encode its ID, so knows how many bits to take from the sub shape ID.11///12/// For example:13/// * We have a CompoundShape A with 5 child shapes (identify sub shape using 3 bits AAA)14/// * One of its child shapes is CompoundShape B which has 3 child shapes (identify sub shape using 2 bits BB)15/// * One of its child shapes is MeshShape C which contains enough triangles to need 7 bits to identify a triangle (identify sub shape using 7 bits CCCCCCC, note that MeshShape is block based and sorts triangles spatially, you can't assume that the first triangle will have bit pattern 0000000).16///17/// The bit pattern of the sub shape ID to identify a triangle in MeshShape C will then be CCCCCCCBBAAA.18///19/// A sub shape ID will become invalid when the structure of the shape changes. For example, if a child shape is removed from a compound shape, the sub shape ID will no longer be valid.20/// This can be a problem when caching sub shape IDs from one frame to the next. See comments at ContactListener::OnContactPersisted / OnContactRemoved.21class SubShapeID22{23public:24JPH_OVERRIDE_NEW_DELETE2526/// Underlying storage type27using Type = uint32;2829/// Type that is bigger than the underlying storage type for operations that would otherwise overflow30using BiggerType = uint64;3132static_assert(sizeof(BiggerType) > sizeof(Type), "The calculation below assumes BiggerType is a bigger type than Type");3334/// How many bits we can store in this ID35static constexpr uint MaxBits = 8 * sizeof(Type);3637/// Constructor38SubShapeID() = default;3940/// Get the next id in the chain of ids (pops parents before children)41Type PopID(uint inBits, SubShapeID &outRemainder) const42{43Type mask_bits = Type((BiggerType(1) << inBits) - 1);44Type fill_bits = Type(BiggerType(cEmpty) << (MaxBits - inBits)); // Fill left side bits with 1 so that if there's no remainder all bits will be set, note that we do this using a BiggerType since on intel 0xffffffff << 32 == 0xffffffff45Type v = mValue & mask_bits;46outRemainder = SubShapeID(Type(BiggerType(mValue) >> inBits) | fill_bits);47return v;48}4950/// Get the value of the path to the sub shape ID51inline Type GetValue() const52{53return mValue;54}5556/// Set the value of the sub shape ID (use with care!)57inline void SetValue(Type inValue)58{59mValue = inValue;60}6162/// Check if there is any bits of subshape ID left.63/// Note that this is not a 100% guarantee as the subshape ID could consist of all 1 bits. Use for asserts only.64inline bool IsEmpty() const65{66return mValue == cEmpty;67}6869/// Check equal70inline bool operator == (const SubShapeID &inRHS) const71{72return mValue == inRHS.mValue;73}7475/// Check not-equal76inline bool operator != (const SubShapeID &inRHS) const77{78return mValue != inRHS.mValue;79}8081private:82friend class SubShapeIDCreator;8384/// An empty SubShapeID has all bits set85static constexpr Type cEmpty = ~Type(0);8687/// Constructor88explicit SubShapeID(const Type &inValue) : mValue(inValue) { }8990/// Adds an id at a particular position in the chain91/// (this should really only be called by the SubShapeIDCreator)92void PushID(Type inValue, uint inFirstBit, uint inBits)93{94// First clear the bits95mValue &= ~(Type((BiggerType(1) << inBits) - 1) << inFirstBit);9697// Then set them to the new value98mValue |= inValue << inFirstBit;99}100101Type mValue = cEmpty;102};103104/// A sub shape id creator can be used to create a new sub shape id by recursing through the shape105/// hierarchy and pushing new ID's onto the chain106class SubShapeIDCreator107{108public:109/// Add a new id to the chain of id's and return it110SubShapeIDCreator PushID(uint inValue, uint inBits) const111{112JPH_ASSERT(inValue < (SubShapeID::BiggerType(1) << inBits));113SubShapeIDCreator copy = *this;114copy.mID.PushID(inValue, mCurrentBit, inBits);115copy.mCurrentBit += inBits;116JPH_ASSERT(copy.mCurrentBit <= SubShapeID::MaxBits);117return copy;118}119120// Get the resulting sub shape ID121const SubShapeID & GetID() const122{123return mID;124}125126/// Get the number of bits that have been written to the sub shape ID so far127inline uint GetNumBitsWritten() const128{129return mCurrentBit;130}131132private:133SubShapeID mID;134uint mCurrentBit = 0;135};136137JPH_NAMESPACE_END138139140