MSFT_lod.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
  2. module BABYLON.GLTF2.Extensions {
  3. interface IMSFTLOD {
  4. ids: number[];
  5. }
  6. // See https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_lod for more information about this extension.
  7. export class MSFTLOD extends GLTFLoaderExtension {
  8. /**
  9. * Specify the minimal delay between LODs in ms (default = 250)
  10. */
  11. public Delay = 250;
  12. public get name() {
  13. return "MSFT_lod";
  14. }
  15. protected _traverseNode(loader: GLTFLoader, context: string, node: IGLTFNode, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode): boolean {
  16. return this._loadExtension<IMSFTLOD>(context, node, (context, extension, onComplete) => {
  17. for (let i = extension.ids.length - 1; i >= 0; i--) {
  18. const lodNode = GLTFLoader._GetProperty(loader._gltf.nodes, extension.ids[i]);
  19. if (!lodNode) {
  20. throw new Error(context + ": Failed to find node " + extension.ids[i]);
  21. }
  22. loader._traverseNode(context, lodNode, action, parentNode);
  23. }
  24. loader._traverseNode(context, node, action, parentNode);
  25. onComplete();
  26. });
  27. }
  28. protected _loadNode(loader: GLTFLoader, context: string, node: IGLTFNode): boolean {
  29. return this._loadExtension<IMSFTLOD>(context, node, (context, extension, onComplete) => {
  30. const nodes = [node];
  31. for (let index of extension.ids) {
  32. const lodNode = GLTFLoader._GetProperty(loader._gltf.nodes, index);
  33. if (!lodNode) {
  34. throw new Error(context + ": Failed to find node " + index);
  35. }
  36. nodes.push(lodNode);
  37. }
  38. loader._addLoaderPendingData(node);
  39. this._loadNodeLOD(loader, context, nodes, nodes.length - 1, () => {
  40. loader._removeLoaderPendingData(node);
  41. onComplete();
  42. });
  43. });
  44. }
  45. private _loadNodeLOD(loader: GLTFLoader, context: string, nodes: IGLTFNode[], index: number, onComplete: () => void): void {
  46. loader._whenAction(() => {
  47. loader._loadNode(context, nodes[index]);
  48. }, () => {
  49. if (index !== nodes.length - 1) {
  50. const previousNode = nodes[index + 1];
  51. previousNode.babylonMesh.setEnabled(false);
  52. }
  53. if (index === 0) {
  54. onComplete();
  55. return;
  56. }
  57. setTimeout(() => {
  58. loader._tryCatchOnError(() => {
  59. this._loadNodeLOD(loader, context, nodes, index - 1, onComplete);
  60. });
  61. }, this.Delay);
  62. });
  63. }
  64. protected _loadMaterial(loader: GLTFLoader, context: string, material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): boolean {
  65. return this._loadExtension<IMSFTLOD>(context, material, (context, extension, onComplete) => {
  66. const materials = [material];
  67. for (let index of extension.ids) {
  68. const lodMaterial = GLTFLoader._GetProperty(loader._gltf.materials, index);
  69. if (!lodMaterial) {
  70. throw new Error(context + ": Failed to find material " + index);
  71. }
  72. materials.push(lodMaterial);
  73. }
  74. loader._addLoaderPendingData(material);
  75. this._loadMaterialLOD(loader, context, materials, materials.length - 1, assign, () => {
  76. loader._removeLoaderPendingData(material);
  77. onComplete();
  78. });
  79. });
  80. }
  81. private _loadMaterialLOD(loader: GLTFLoader, context: string, materials: IGLTFMaterial[], index: number, assign: (babylonMaterial: Material, isNew: boolean) => void, onComplete: () => void): void {
  82. loader._loadMaterial(context, materials[index], (babylonMaterial, isNew) => {
  83. if (index === materials.length - 1) {
  84. assign(babylonMaterial, isNew);
  85. // Load the next LOD when the loader is ready to render.
  86. loader._executeWhenRenderReady(() => {
  87. this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
  88. });
  89. }
  90. else {
  91. BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), () => {
  92. assign(babylonMaterial, isNew);
  93. if (index === 0) {
  94. onComplete();
  95. }
  96. else {
  97. setTimeout(() => {
  98. loader._tryCatchOnError(() => {
  99. this._loadMaterialLOD(loader, context, materials, index - 1, assign, onComplete);
  100. });
  101. }, this.Delay);
  102. }
  103. });
  104. }
  105. });
  106. }
  107. }
  108. GLTFLoader.RegisterExtension(new MSFTLOD());
  109. }