ImplicitAvailabilityBitstream.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import Check from "../Core/Check.js";
  2. import defined from "../Core/defined.js";
  3. import defaultValue from "../Core/defaultValue.js";
  4. import DeveloperError from "../Core/DeveloperError.js";
  5. import RuntimeError from "../Core/RuntimeError.js";
  6. /**
  7. * An availability bitstream for use in an {@link ImplicitSubtree}. This handles
  8. * both Uint8Array bitstreams and constant values.
  9. *
  10. * @alias ImplicitAvailabilityBitstream
  11. * @constructor
  12. *
  13. * @param {object} options An object with the following properties:
  14. * @param {number} options.lengthBits The length of the bitstream in bits
  15. * @param {boolean} [options.constant] A single boolean value indicating the value of all the bits in the bitstream if they are all the same
  16. * @param {Uint8Array} [options.bitstream] An array of bytes storing the bitstream in binary
  17. * @param {number} [options.availableCount] A number indicating how many 1 bits are found in the bitstream
  18. * @param {boolean} [options.computeAvailableCountEnabled=false] If true, and options.availableCount is undefined, the availableCount will be computed from the bitstream.
  19. * @private
  20. * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
  21. */
  22. function ImplicitAvailabilityBitstream(options) {
  23. const lengthBits = options.lengthBits;
  24. let availableCount = options.availableCount;
  25. //>>includeStart('debug', pragmas.debug);
  26. Check.typeOf.number("options.lengthBits", lengthBits);
  27. //>>includeEnd('debug');
  28. const constant = options.constant;
  29. const bitstream = options.bitstream;
  30. if (defined(constant)) {
  31. // if defined, constant must be 1 which means all tiles are available
  32. availableCount = lengthBits;
  33. } else {
  34. const expectedLength = Math.ceil(lengthBits / 8);
  35. if (bitstream.length !== expectedLength) {
  36. throw new RuntimeError(
  37. `Availability bitstream must be exactly ${expectedLength} bytes long to store ${lengthBits} bits. Actual bitstream was ${bitstream.length} bytes long.`
  38. );
  39. }
  40. // Only compute the available count if requested, as this involves looping
  41. // over the bitstream.
  42. const computeAvailableCountEnabled = defaultValue(
  43. options.computeAvailableCountEnabled,
  44. false
  45. );
  46. if (!defined(availableCount) && computeAvailableCountEnabled) {
  47. availableCount = count1Bits(bitstream, lengthBits);
  48. }
  49. }
  50. this._lengthBits = lengthBits;
  51. this._availableCount = availableCount;
  52. this._constant = constant;
  53. this._bitstream = bitstream;
  54. }
  55. /**
  56. * Count the number of bits with value 1 in the bitstream. This is used for
  57. * computing availableCount if not precomputed
  58. *
  59. * @param {Uint8Array} bitstream The bitstream typed array
  60. * @param {number} lengthBits How many bits are in the bitstream
  61. * @private
  62. */
  63. function count1Bits(bitstream, lengthBits) {
  64. let count = 0;
  65. for (let i = 0; i < lengthBits; i++) {
  66. const byteIndex = i >> 3;
  67. const bitIndex = i % 8;
  68. count += (bitstream[byteIndex] >> bitIndex) & 1;
  69. }
  70. return count;
  71. }
  72. Object.defineProperties(ImplicitAvailabilityBitstream.prototype, {
  73. /**
  74. * The length of the bitstream in bits.
  75. *
  76. * @memberof ImplicitAvailabilityBitstream.prototype
  77. *
  78. * @type {number}
  79. * @readonly
  80. * @private
  81. */
  82. lengthBits: {
  83. get: function () {
  84. return this._lengthBits;
  85. },
  86. },
  87. /**
  88. * The number of bits in the bitstream with value <code>1</code>.
  89. *
  90. * @memberof ImplicitAvailabilityBitstream.prototype
  91. *
  92. * @type {number}
  93. * @readonly
  94. * @private
  95. */
  96. availableCount: {
  97. get: function () {
  98. return this._availableCount;
  99. },
  100. },
  101. });
  102. /**
  103. * Get a bit from the availability bitstream as a Boolean. If the bitstream
  104. * is a constant, the constant value is returned instead.
  105. *
  106. * @param {number} index The integer index of the bit.
  107. * @returns {boolean} The value of the bit
  108. * @private
  109. */
  110. ImplicitAvailabilityBitstream.prototype.getBit = function (index) {
  111. //>>includeStart('debug', pragmas.debug);
  112. if (index < 0 || index >= this._lengthBits) {
  113. throw new DeveloperError("Bit index out of bounds.");
  114. }
  115. //>>includeEnd('debug');
  116. if (defined(this._constant)) {
  117. return this._constant;
  118. }
  119. // byteIndex is floor(index / 8)
  120. const byteIndex = index >> 3;
  121. const bitIndex = index % 8;
  122. return ((this._bitstream[byteIndex] >> bitIndex) & 1) === 1;
  123. };
  124. export default ImplicitAvailabilityBitstream;