glTFValidation.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import { Tools } from "@babylonjs/core/Misc/tools.js";
  2. function validateAsync(data, rootUrl, fileName, getExternalResource) {
  3. const options = {
  4. externalResourceFunction: getExternalResource,
  5. };
  6. if (fileName) {
  7. options.uri = rootUrl === "file:" ? fileName : rootUrl + fileName;
  8. }
  9. return ArrayBuffer.isView(data) ? GLTFValidator.validateBytes(data, options) : GLTFValidator.validateString(data, options);
  10. }
  11. /**
  12. * The worker function that gets converted to a blob url to pass into a worker.
  13. */
  14. function workerFunc() {
  15. const pendingExternalResources = [];
  16. onmessage = (message) => {
  17. const data = message.data;
  18. switch (data.id) {
  19. case "init": {
  20. importScripts(data.url);
  21. break;
  22. }
  23. case "validate": {
  24. validateAsync(data.data, data.rootUrl, data.fileName, (uri) => new Promise((resolve, reject) => {
  25. const index = pendingExternalResources.length;
  26. pendingExternalResources.push({ resolve, reject });
  27. postMessage({ id: "getExternalResource", index: index, uri: uri });
  28. })).then((value) => {
  29. postMessage({ id: "validate.resolve", value: value });
  30. }, (reason) => {
  31. postMessage({ id: "validate.reject", reason: reason });
  32. });
  33. break;
  34. }
  35. case "getExternalResource.resolve": {
  36. pendingExternalResources[data.index].resolve(data.value);
  37. break;
  38. }
  39. case "getExternalResource.reject": {
  40. pendingExternalResources[data.index].reject(data.reason);
  41. break;
  42. }
  43. }
  44. };
  45. }
  46. /**
  47. * glTF validation
  48. */
  49. export class GLTFValidation {
  50. /**
  51. * Validate a glTF asset using the glTF-Validator.
  52. * @param data The JSON of a glTF or the array buffer of a binary glTF
  53. * @param rootUrl The root url for the glTF
  54. * @param fileName The file name for the glTF
  55. * @param getExternalResource The callback to get external resources for the glTF validator
  56. * @returns A promise that resolves with the glTF validation results once complete
  57. */
  58. static ValidateAsync(data, rootUrl, fileName, getExternalResource) {
  59. if (typeof Worker === "function") {
  60. return new Promise((resolve, reject) => {
  61. const workerContent = `${validateAsync}(${workerFunc})()`;
  62. const workerBlobUrl = URL.createObjectURL(new Blob([workerContent], { type: "application/javascript" }));
  63. const worker = new Worker(workerBlobUrl);
  64. const onError = (error) => {
  65. worker.removeEventListener("error", onError);
  66. worker.removeEventListener("message", onMessage);
  67. reject(error);
  68. };
  69. const onMessage = (message) => {
  70. const data = message.data;
  71. switch (data.id) {
  72. case "getExternalResource": {
  73. getExternalResource(data.uri).then((value) => {
  74. worker.postMessage({ id: "getExternalResource.resolve", index: data.index, value: value }, [value.buffer]);
  75. }, (reason) => {
  76. worker.postMessage({ id: "getExternalResource.reject", index: data.index, reason: reason });
  77. });
  78. break;
  79. }
  80. case "validate.resolve": {
  81. worker.removeEventListener("error", onError);
  82. worker.removeEventListener("message", onMessage);
  83. resolve(data.value);
  84. worker.terminate();
  85. break;
  86. }
  87. case "validate.reject": {
  88. worker.removeEventListener("error", onError);
  89. worker.removeEventListener("message", onMessage);
  90. reject(data.reason);
  91. worker.terminate();
  92. }
  93. }
  94. };
  95. worker.addEventListener("error", onError);
  96. worker.addEventListener("message", onMessage);
  97. worker.postMessage({ id: "init", url: Tools.GetBabylonScriptURL(this.Configuration.url) });
  98. if (ArrayBuffer.isView(data)) {
  99. // Slice the data to avoid copying the whole array buffer.
  100. const slicedData = data.slice();
  101. worker.postMessage({ id: "validate", data: slicedData, rootUrl: rootUrl, fileName: fileName }, [slicedData.buffer]);
  102. }
  103. else {
  104. worker.postMessage({ id: "validate", data: data, rootUrl: rootUrl, fileName: fileName });
  105. }
  106. });
  107. }
  108. else {
  109. if (!this._LoadScriptPromise) {
  110. this._LoadScriptPromise = Tools.LoadBabylonScriptAsync(this.Configuration.url);
  111. }
  112. return this._LoadScriptPromise.then(() => {
  113. return validateAsync(data, rootUrl, fileName, getExternalResource);
  114. });
  115. }
  116. }
  117. }
  118. /**
  119. * The configuration. Defaults to `{ url: "https://cdn.babylonjs.com/gltf_validator.js" }`.
  120. */
  121. GLTFValidation.Configuration = {
  122. url: `${Tools._DefaultCdnUrl}/gltf_validator.js`,
  123. };
  124. //# sourceMappingURL=glTFValidation.js.map