Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/SubShapeID.h
9913 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
JPH_NAMESPACE_BEGIN
8
9
/// @brief A sub shape id contains a path to an element (usually a triangle or other primitive type) of a compound shape
10
///
11
/// 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.
12
///
13
/// For example:
14
/// * We have a CompoundShape A with 5 child shapes (identify sub shape using 3 bits AAA)
15
/// * One of its child shapes is CompoundShape B which has 3 child shapes (identify sub shape using 2 bits BB)
16
/// * 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).
17
///
18
/// The bit pattern of the sub shape ID to identify a triangle in MeshShape C will then be CCCCCCCBBAAA.
19
///
20
/// 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.
21
/// This can be a problem when caching sub shape IDs from one frame to the next. See comments at ContactListener::OnContactPersisted / OnContactRemoved.
22
class SubShapeID
23
{
24
public:
25
JPH_OVERRIDE_NEW_DELETE
26
27
/// Underlying storage type
28
using Type = uint32;
29
30
/// Type that is bigger than the underlying storage type for operations that would otherwise overflow
31
using BiggerType = uint64;
32
33
static_assert(sizeof(BiggerType) > sizeof(Type), "The calculation below assumes BiggerType is a bigger type than Type");
34
35
/// How many bits we can store in this ID
36
static constexpr uint MaxBits = 8 * sizeof(Type);
37
38
/// Constructor
39
SubShapeID() = default;
40
41
/// Get the next id in the chain of ids (pops parents before children)
42
Type PopID(uint inBits, SubShapeID &outRemainder) const
43
{
44
Type mask_bits = Type((BiggerType(1) << inBits) - 1);
45
Type 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 == 0xffffffff
46
Type v = mValue & mask_bits;
47
outRemainder = SubShapeID(Type(BiggerType(mValue) >> inBits) | fill_bits);
48
return v;
49
}
50
51
/// Get the value of the path to the sub shape ID
52
inline Type GetValue() const
53
{
54
return mValue;
55
}
56
57
/// Set the value of the sub shape ID (use with care!)
58
inline void SetValue(Type inValue)
59
{
60
mValue = inValue;
61
}
62
63
/// Check if there is any bits of subshape ID left.
64
/// Note that this is not a 100% guarantee as the subshape ID could consist of all 1 bits. Use for asserts only.
65
inline bool IsEmpty() const
66
{
67
return mValue == cEmpty;
68
}
69
70
/// Check equal
71
inline bool operator == (const SubShapeID &inRHS) const
72
{
73
return mValue == inRHS.mValue;
74
}
75
76
/// Check not-equal
77
inline bool operator != (const SubShapeID &inRHS) const
78
{
79
return mValue != inRHS.mValue;
80
}
81
82
private:
83
friend class SubShapeIDCreator;
84
85
/// An empty SubShapeID has all bits set
86
static constexpr Type cEmpty = ~Type(0);
87
88
/// Constructor
89
explicit SubShapeID(const Type &inValue) : mValue(inValue) { }
90
91
/// Adds an id at a particular position in the chain
92
/// (this should really only be called by the SubShapeIDCreator)
93
void PushID(Type inValue, uint inFirstBit, uint inBits)
94
{
95
// First clear the bits
96
mValue &= ~(Type((BiggerType(1) << inBits) - 1) << inFirstBit);
97
98
// Then set them to the new value
99
mValue |= inValue << inFirstBit;
100
}
101
102
Type mValue = cEmpty;
103
};
104
105
/// A sub shape id creator can be used to create a new sub shape id by recursing through the shape
106
/// hierarchy and pushing new ID's onto the chain
107
class SubShapeIDCreator
108
{
109
public:
110
/// Add a new id to the chain of id's and return it
111
SubShapeIDCreator PushID(uint inValue, uint inBits) const
112
{
113
JPH_ASSERT(inValue < (SubShapeID::BiggerType(1) << inBits));
114
SubShapeIDCreator copy = *this;
115
copy.mID.PushID(inValue, mCurrentBit, inBits);
116
copy.mCurrentBit += inBits;
117
JPH_ASSERT(copy.mCurrentBit <= SubShapeID::MaxBits);
118
return copy;
119
}
120
121
// Get the resulting sub shape ID
122
const SubShapeID & GetID() const
123
{
124
return mID;
125
}
126
127
/// Get the number of bits that have been written to the sub shape ID so far
128
inline uint GetNumBitsWritten() const
129
{
130
return mCurrentBit;
131
}
132
133
private:
134
SubShapeID mID;
135
uint mCurrentBit = 0;
136
};
137
138
JPH_NAMESPACE_END
139
140