babylon.sceneLoader.tests.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /**
  2. * Describes the test suite.
  3. */
  4. describe('Babylon Scene Loader', function () {
  5. let subject: BABYLON.Engine;
  6. this.timeout(10000);
  7. /**
  8. * Loads the dependencies.
  9. */
  10. before(function (done) {
  11. this.timeout(180000);
  12. (BABYLONDEVTOOLS).Loader
  13. .useDist()
  14. .load(function () {
  15. // Force apply promise polyfill for consistent behavior between PhantomJS, IE11, and other browsers.
  16. BABYLON.PromisePolyfill.Apply(true);
  17. done();
  18. });
  19. });
  20. /**
  21. * Create a new engine subject before each test.
  22. */
  23. beforeEach(function () {
  24. subject = new BABYLON.NullEngine({
  25. renderHeight: 256,
  26. renderWidth: 256,
  27. textureSize: 256,
  28. deterministicLockstep: false,
  29. lockstepMaxSteps: 1
  30. });
  31. });
  32. /**
  33. * Integration tests for loading glTF assets.
  34. */
  35. describe('#glTF', () => {
  36. it('Load BoomBox', () => {
  37. const scene = new BABYLON.Scene(subject);
  38. return BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(scene => {
  39. expect(scene.meshes.length, "scene.meshes.length").to.equal(3);
  40. expect(scene.materials.length, "scene.materials.length").to.equal(1);
  41. });
  42. });
  43. it('Load BoomBox GLB', () => {
  44. const scene = new BABYLON.Scene(subject);
  45. return BABYLON.SceneLoader.AppendAsync("/Playground/scenes/", "BoomBox.glb", scene).then(scene => {
  46. expect(scene.meshes.length, "scene.meshes.length").to.equal(3);
  47. expect(scene.materials.length, "scene.materials.length").to.equal(1);
  48. });
  49. });
  50. it('Load BoomBox with ImportMesh', () => {
  51. const scene = new BABYLON.Scene(subject);
  52. return BABYLON.SceneLoader.ImportMeshAsync(null, "/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(result => {
  53. expect(result.meshes.length, "meshes.length").to.equal(scene.meshes.length);
  54. expect(result.particleSystems.length, "particleSystems.length").to.equal(0);
  55. expect(result.skeletons.length, "skeletons.length").to.equal(0);
  56. });
  57. });
  58. it('Load BoomBox with callbacks', () => {
  59. let parsedCount = 0;
  60. let meshCount = 0;
  61. let materialCount = 0;
  62. let textureCounts: { [name: string]: number } = {};
  63. let ready = false;
  64. const deferred = new BABYLON.Deferred();
  65. BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
  66. loader.onParsed = data => {
  67. parsedCount++;
  68. };
  69. loader.onMeshLoaded = mesh => {
  70. meshCount++;
  71. };
  72. loader.onMaterialLoaded = material => {
  73. materialCount++;
  74. };
  75. loader.onTextureLoaded = texture => {
  76. textureCounts[texture.name] = textureCounts[texture.name] || 0;
  77. textureCounts[texture.name]++;
  78. };
  79. loader.onComplete = () => {
  80. try {
  81. expect(ready, "ready").to.be.true;
  82. deferred.resolve();
  83. }
  84. catch (e) {
  85. deferred.reject(e);
  86. }
  87. };
  88. }, undefined, undefined, undefined, true);
  89. const scene = new BABYLON.Scene(subject);
  90. const promise = BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(() => {
  91. ready = true;
  92. expect(parsedCount, "parsedCount").to.equal(1);
  93. expect(meshCount, "meshCount").to.equal(scene.meshes.length);
  94. expect(materialCount, "materialCount").to.equal(scene.materials.length);
  95. const expectedTextureLoadCounts = {
  96. "baseColor": 1,
  97. "occlusionRoughnessMetallic": 2,
  98. "normal": 1,
  99. "emissive": 1
  100. };
  101. expect(Object.keys(textureCounts), "Object.keys(textureCounts)").to.have.lengthOf(Object.keys(expectedTextureLoadCounts).length);
  102. for (const textureName in expectedTextureLoadCounts) {
  103. expect(textureCounts, "textureCounts").to.have.property(textureName, expectedTextureLoadCounts[textureName]);
  104. }
  105. });
  106. return Promise.all([promise, deferred.promise]);
  107. });
  108. it('Load BoomBox with dispose', () => {
  109. let ready = false;
  110. let disposed = false;
  111. const deferred = new BABYLON.Deferred<void>();
  112. BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
  113. loader.onDispose = () => {
  114. disposed = true;
  115. };
  116. BABYLON.Tools.DelayAsync(50).then(() => {
  117. loader.dispose();
  118. expect(ready, "ready").to.be.false;
  119. expect(disposed, "disposed").to.be.true;
  120. deferred.resolve();
  121. }).catch(error => {
  122. deferred.reject(error);
  123. });
  124. }, undefined, undefined, undefined, true);
  125. const scene = new BABYLON.Scene(subject);
  126. BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox2.gltf", scene).then(() => {
  127. ready = true;
  128. }).catch(error => {
  129. // Cannot rely on the typical error handling of promises since the AppendAsync is not
  130. // supposed to complete because the loader is being disposed.
  131. deferred.reject(error);
  132. });
  133. return deferred.promise;
  134. });
  135. it('Load BoomBox with compileMaterials', () => {
  136. let createShaderProgramSpy: sinon.SinonSpy;
  137. const deferred = new BABYLON.Deferred();
  138. BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
  139. loader.compileMaterials = true;
  140. loader.onComplete = () => {
  141. try {
  142. expect(createShaderProgramSpy.called, "createShaderProgramSpy.called").to.be.false;
  143. deferred.resolve();
  144. }
  145. catch (e) {
  146. deferred.reject(e);
  147. }
  148. finally {
  149. createShaderProgramSpy.restore();
  150. }
  151. };
  152. }, undefined, undefined, undefined, true);
  153. const scene = new BABYLON.Scene(subject);
  154. const promise = BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(() => {
  155. createShaderProgramSpy = sinon.spy(subject, "createShaderProgram");
  156. });
  157. return Promise.all([promise, deferred.promise, scene.whenReadyAsync()]);
  158. });
  159. it('Load Alien', () => {
  160. const scene = new BABYLON.Scene(subject);
  161. return BABYLON.SceneLoader.ImportMeshAsync(null, "/Playground/scenes/Alien/", "Alien.gltf", scene).then(result => {
  162. expect(result.skeletons.length, "skeletons.length").to.equal(scene.skeletons.length);
  163. const mapping = {
  164. "AlienHead_0": "skeleton0",
  165. "Collar_0": "skeleton1",
  166. "LeftEye_0": "skeleton2",
  167. "RightEye_0": "skeleton3",
  168. "CollarClasp_0": "skeleton1",
  169. "Shirt_0": "skeleton1",
  170. "ShirtPlate_0": "skeleton1",
  171. "Teeth_0": "skeleton1",
  172. };
  173. for (const meshName in mapping) {
  174. const skeletonName = mapping[meshName];
  175. expect(scene.getMeshByName(meshName).skeleton.name, `skeleton name of mesh '${meshName}'`).to.equal(skeletonName);
  176. }
  177. });
  178. });
  179. it('Load TwoQuads', () => {
  180. const materials: { [name: string]: BABYLON.Material } = {};
  181. const deferred = new BABYLON.Deferred();
  182. BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
  183. loader.onMaterialLoaded = material => {
  184. expect(materials[material.name], `materials["${material.name}"]`).to.be.undefined;
  185. materials[material.name] = material;
  186. };
  187. loader.onComplete = () => {
  188. try {
  189. expect(materials["LOD0"].getActiveTextures().every(texture => texture.isReady()), "All textures of LOD 0 ready").to.be.true;
  190. expect(materials["LOD1"].getActiveTextures().every(texture => texture.isReady()), "All textures of LOD 1 ready").to.be.true;
  191. expect(materials["LOD2"].getActiveTextures().every(texture => texture.isReady()), "All textures of LOD 2 ready").to.be.true;
  192. deferred.resolve();
  193. }
  194. catch (e) {
  195. deferred.reject(e);
  196. }
  197. };
  198. }, undefined, undefined, undefined, true);
  199. const scene = new BABYLON.Scene(subject);
  200. const promise = BABYLON.SceneLoader.AppendAsync("/Playground/scenes/TwoQuads/", "TwoQuads.gltf", scene).then(() => {
  201. expect(Object.keys(materials), "materials").to.have.lengthOf(3);
  202. expect(materials["LOD0"].getActiveTextures(), "material LOD 0 active textures").to.have.lengthOf(1);
  203. expect(materials["LOD1"].getActiveTextures(), "material LOD 1 active textures").to.have.lengthOf(1);
  204. expect(materials["LOD2"].getActiveTextures(), "material LOD 2 active textures").to.have.lengthOf(1);
  205. expect(materials["LOD0"].getActiveTextures().some(texture => texture.isReady()), "Some textures of LOD 0 ready").to.be.false;
  206. expect(materials["LOD1"].getActiveTextures().some(texture => texture.isReady()), "Some textures of LOD 1 ready").to.be.false;
  207. expect(materials["LOD2"].getActiveTextures().every(texture => texture.isReady()), "All textures of LOD 2 ready").to.be.true;
  208. });
  209. return Promise.all([promise, deferred.promise]);
  210. });
  211. // TODO: test material instancing
  212. // TODO: test ImportMesh with specific node name
  213. // TODO: test KHR_materials_pbrSpecularGlossiness
  214. // TODO: test KHR_lights
  215. });
  216. describe('#AssetContainer', () => {
  217. it('should be loaded from BoomBox GLTF', () => {
  218. var scene = new BABYLON.Scene(subject);
  219. return BABYLON.SceneLoader.LoadAssetContainerAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene).then(container => {
  220. expect(container.meshes.length).to.eq(3);
  221. });
  222. });
  223. it('should be adding and removing objects from scene', () => {
  224. // Create a scene with some assets
  225. var scene = new BABYLON.Scene(subject);
  226. var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
  227. var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
  228. var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
  229. var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);
  230. // Move all the assets from the scene into a container
  231. var container = new BABYLON.AssetContainer(scene);
  232. var keepAssets = new BABYLON.KeepAssets();
  233. keepAssets.cameras.push(camera);
  234. container.moveAllFromScene(keepAssets);
  235. expect(scene.cameras.length).to.eq(1);
  236. expect(scene.meshes.length).to.eq(0);
  237. expect(scene.lights.length).to.eq(0);
  238. expect(container.cameras.length).to.eq(0);
  239. expect(container.meshes.length).to.eq(2);
  240. expect(container.lights.length).to.eq(1);
  241. // Add them back and then remove again
  242. container.addAllToScene();
  243. expect(scene.cameras.length).to.eq(1);
  244. expect(scene.meshes.length).to.eq(2);
  245. expect(scene.lights.length).to.eq(1);
  246. container.removeAllFromScene();
  247. expect(scene.cameras.length).to.eq(1);
  248. expect(scene.meshes.length).to.eq(0);
  249. expect(scene.lights.length).to.eq(0);
  250. });
  251. });
  252. });