SubShapeID.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. JPH_NAMESPACE_BEGIN
  5. /// A sub shape id contains a path to an element (usually a triangle or other primitive type) of a compound shape
  6. class SubShapeID
  7. {
  8. public:
  9. JPH_OVERRIDE_NEW_DELETE
  10. /// Underlying storage type
  11. using Type = uint32;
  12. /// Type that is bigger than the underlying storage type for operations that would otherwise overflow
  13. using BiggerType = uint64;
  14. static_assert(sizeof(BiggerType) > sizeof(Type), "The calculation below assumes BiggerType is a bigger type than Type");
  15. /// How many bits we can store in this ID
  16. static constexpr uint MaxBits = 8 * sizeof(Type);
  17. /// Constructor
  18. SubShapeID() = default;
  19. /// Get the next id in the chain of ids (pops parents before children)
  20. Type PopID(uint inBits, SubShapeID &outRemainder) const
  21. {
  22. Type mask_bits = Type((BiggerType(1) << inBits) - 1);
  23. 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
  24. Type v = mValue & mask_bits;
  25. outRemainder = SubShapeID(Type(BiggerType(mValue) >> inBits) | fill_bits);
  26. return v;
  27. }
  28. /// Get the value of the path to the sub shape ID
  29. inline Type GetValue() const
  30. {
  31. return mValue;
  32. }
  33. /// Set the value of the sub shape ID (use with care!)
  34. inline void SetValue(Type inValue)
  35. {
  36. mValue = inValue;
  37. }
  38. /// Check if there is any bits of subshape ID left.
  39. /// Note that this is not a 100% guarantee as the subshape ID could consist of all 1 bits. Use for asserts only.
  40. inline bool IsEmpty() const
  41. {
  42. return mValue == cEmpty;
  43. }
  44. /// Check equal
  45. inline bool operator == (const SubShapeID &inRHS) const
  46. {
  47. return mValue == inRHS.mValue;
  48. }
  49. /// Check not-equal
  50. inline bool operator != (const SubShapeID &inRHS) const
  51. {
  52. return mValue != inRHS.mValue;
  53. }
  54. private:
  55. friend class SubShapeIDCreator;
  56. /// An empty SubShapeID has all bits set
  57. static constexpr Type cEmpty = ~Type(0);
  58. /// Constructor
  59. explicit SubShapeID(const Type &inValue) : mValue(inValue) { }
  60. /// Adds an id at a particular position in the chain
  61. /// (this should really only be called by the SubShapeIDCreator)
  62. void PushID(Type inValue, uint inFirstBit, uint inBits)
  63. {
  64. // First clear the bits
  65. mValue &= ~(Type((BiggerType(1) << inBits) - 1) << inFirstBit);
  66. // Then set them to the new value
  67. mValue |= inValue << inFirstBit;
  68. }
  69. Type mValue = cEmpty;
  70. };
  71. /// A sub shape id creator can be used to create a new sub shape id by recursing through the shape
  72. /// hierarchy and pushing new ID's onto the chain
  73. class SubShapeIDCreator
  74. {
  75. public:
  76. /// Add a new id to the chain of id's and return it
  77. SubShapeIDCreator PushID(uint inValue, uint inBits) const
  78. {
  79. JPH_ASSERT(inValue < (SubShapeID::BiggerType(1) << inBits));
  80. SubShapeIDCreator copy = *this;
  81. copy.mID.PushID(inValue, mCurrentBit, inBits);
  82. copy.mCurrentBit += inBits;
  83. JPH_ASSERT(copy.mCurrentBit <= SubShapeID::MaxBits);
  84. return copy;
  85. }
  86. // Get the resulting sub shape ID
  87. const SubShapeID & GetID() const
  88. {
  89. return mID;
  90. }
  91. /// Get the number of bits that have been written to the sub shape ID so far
  92. inline uint GetNumBitsWritten() const
  93. {
  94. return mCurrentBit;
  95. }
  96. private:
  97. SubShapeID mID;
  98. uint mCurrentBit = 0;
  99. };
  100. JPH_NAMESPACE_END