智慧水务管理系统 - 精河县供水工程综合管理平台

GltfBufferViewLoader.js 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import Check from "../Core/Check.js";
  2. import Frozen from "../Core/Frozen.js";
  3. import defined from "../Core/defined.js";
  4. import hasExtension from "./hasExtension.js";
  5. import { MeshoptDecoder } from "meshoptimizer";
  6. import ResourceLoader from "./ResourceLoader.js";
  7. import ResourceLoaderState from "./ResourceLoaderState.js";
  8. /**
  9. * Loads a glTF buffer view.
  10. * <p>
  11. * Implements the {@link ResourceLoader} interface.
  12. * </p>
  13. *
  14. * @private
  15. */
  16. class GltfBufferViewLoader extends ResourceLoader {
  17. /**
  18. * @param {object} options Object with the following properties:
  19. * @param {ResourceCache} options.resourceCache The {@link ResourceCache} (to avoid circular dependencies).
  20. * @param {object} options.gltf The glTF JSON.
  21. * @param {number} options.bufferViewId The buffer view ID.
  22. * @param {Resource} options.gltfResource The {@link Resource} containing the glTF.
  23. * @param {Resource} options.baseResource The {@link Resource} that paths in the glTF JSON are relative to.
  24. * @param {string} [options.cacheKey] The cache key of the resource.
  25. */
  26. constructor(options) {
  27. super();
  28. options = options ?? Frozen.EMPTY_OBJECT;
  29. const resourceCache = options.resourceCache;
  30. const gltf = options.gltf;
  31. const bufferViewId = options.bufferViewId;
  32. const gltfResource = options.gltfResource;
  33. const baseResource = options.baseResource;
  34. const cacheKey = options.cacheKey;
  35. //>>includeStart('debug', pragmas.debug);
  36. Check.typeOf.func("options.resourceCache", resourceCache);
  37. Check.typeOf.object("options.gltf", gltf);
  38. Check.typeOf.number("options.bufferViewId", bufferViewId);
  39. Check.typeOf.object("options.gltfResource", gltfResource);
  40. Check.typeOf.object("options.baseResource", baseResource);
  41. //>>includeEnd('debug');
  42. const bufferView = gltf.bufferViews[bufferViewId];
  43. let bufferId = bufferView.buffer;
  44. let byteOffset = bufferView.byteOffset;
  45. let byteLength = bufferView.byteLength;
  46. let hasMeshopt = false;
  47. let meshoptByteStride;
  48. let meshoptCount;
  49. let meshoptMode;
  50. let meshoptFilter;
  51. if (hasExtension(bufferView, "EXT_meshopt_compression")) {
  52. const meshopt = bufferView.extensions.EXT_meshopt_compression;
  53. bufferId = meshopt.buffer;
  54. byteOffset = meshopt.byteOffset ?? 0;
  55. byteLength = meshopt.byteLength;
  56. hasMeshopt = true;
  57. meshoptByteStride = meshopt.byteStride;
  58. meshoptCount = meshopt.count;
  59. meshoptMode = meshopt.mode;
  60. meshoptFilter = meshopt.filter ?? "NONE";
  61. }
  62. const buffer = gltf.buffers[bufferId];
  63. this._hasMeshopt = hasMeshopt;
  64. this._meshoptByteStride = meshoptByteStride;
  65. this._meshoptCount = meshoptCount;
  66. this._meshoptMode = meshoptMode;
  67. this._meshoptFilter = meshoptFilter;
  68. this._resourceCache = resourceCache;
  69. this._gltfResource = gltfResource;
  70. this._baseResource = baseResource;
  71. this._buffer = buffer;
  72. this._bufferId = bufferId;
  73. this._byteOffset = byteOffset;
  74. this._byteLength = byteLength;
  75. this._cacheKey = cacheKey;
  76. this._bufferLoader = undefined;
  77. this._typedArray = undefined;
  78. this._state = ResourceLoaderState.UNLOADED;
  79. this._promise = undefined;
  80. }
  81. /**
  82. * The cache key of the resource.
  83. *
  84. *
  85. * @type {string}
  86. * @readonly
  87. * @private
  88. */
  89. get cacheKey() {
  90. return this._cacheKey;
  91. }
  92. /**
  93. * The typed array containing buffer view data.
  94. *
  95. *
  96. * @type {Uint8Array}
  97. * @readonly
  98. * @private
  99. */
  100. get typedArray() {
  101. return this._typedArray;
  102. }
  103. /**
  104. * Loads the resource.
  105. * @returns {Promise<GltfBufferViewLoader>} A promise which resolves to the loader when the resource loading is completed.
  106. * @private
  107. */
  108. async load() {
  109. if (defined(this._promise)) {
  110. return this._promise;
  111. }
  112. this._state = ResourceLoaderState.LOADING;
  113. this._promise = loadResources(this);
  114. return this._promise;
  115. }
  116. /**
  117. * Unloads the resource.
  118. * @private
  119. */
  120. unload() {
  121. if (defined(this._bufferLoader) && !this._bufferLoader.isDestroyed()) {
  122. this._resourceCache.unload(this._bufferLoader);
  123. }
  124. this._bufferLoader = undefined;
  125. this._typedArray = undefined;
  126. }
  127. }
  128. /**
  129. * Load the resources associated with the loader.
  130. * @private
  131. * @param {GltfBufferViewLoader} loader
  132. * @returns {Promise<GltfBufferViewLoader>}
  133. */
  134. async function loadResources(loader) {
  135. try {
  136. const bufferLoader = getBufferLoader(loader);
  137. loader._bufferLoader = bufferLoader;
  138. await bufferLoader.load();
  139. if (loader.isDestroyed()) {
  140. return;
  141. }
  142. const bufferTypedArray = bufferLoader.typedArray;
  143. const bufferViewTypedArray = new Uint8Array(
  144. bufferTypedArray.buffer,
  145. bufferTypedArray.byteOffset + loader._byteOffset,
  146. loader._byteLength,
  147. );
  148. // Unload the buffer
  149. loader.unload();
  150. loader._typedArray = bufferViewTypedArray;
  151. if (loader._hasMeshopt) {
  152. const count = loader._meshoptCount;
  153. const byteStride = loader._meshoptByteStride;
  154. const result = new Uint8Array(count * byteStride);
  155. MeshoptDecoder.decodeGltfBuffer(
  156. result,
  157. count,
  158. byteStride,
  159. loader._typedArray,
  160. loader._meshoptMode,
  161. loader._meshoptFilter,
  162. );
  163. loader._typedArray = result;
  164. }
  165. loader._state = ResourceLoaderState.READY;
  166. return loader;
  167. } catch (error) {
  168. if (loader.isDestroyed()) {
  169. return;
  170. }
  171. loader.unload();
  172. loader._state = ResourceLoaderState.FAILED;
  173. const errorMessage = "Failed to load buffer view";
  174. throw loader.getError(errorMessage, error);
  175. }
  176. }
  177. /**
  178. * Get the buffer loader for the specified buffer view loader.
  179. * Attempts to retrieve from the resource cache first. If a buffer loader is
  180. * not found, creates a new buffer loader and adds it to the resource cache.
  181. * @private
  182. * @param {GltfBufferViewLoader} bufferViewLoader The loader.
  183. * @returns {BufferLoader} The buffer loader.
  184. */
  185. function getBufferLoader(bufferViewLoader) {
  186. const resourceCache = bufferViewLoader._resourceCache;
  187. const buffer = bufferViewLoader._buffer;
  188. if (defined(buffer.uri)) {
  189. const baseResource = bufferViewLoader._baseResource;
  190. const resource = baseResource.getDerivedResource({
  191. url: buffer.uri,
  192. });
  193. return resourceCache.getExternalBufferLoader({
  194. resource: resource,
  195. });
  196. }
  197. const source = buffer.extras?._pipeline?.source;
  198. return resourceCache.getEmbeddedBufferLoader({
  199. parentResource: bufferViewLoader._gltfResource,
  200. bufferId: bufferViewLoader._bufferId,
  201. typedArray: source,
  202. });
  203. }
  204. export default GltfBufferViewLoader;