SubShapeID.h 3.1 KB

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