babylon.physicsComponents.tests.ts 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // 'physicsEngineComponents.ts' injects methods and properties into Scene and AbstractMesh
  2. // these tests only check that Scene and AbstractMesh have the expected methods.
  3. /**
  4. * Describes the test suite.
  5. */
  6. describe('Babylon physicsComponents', () => {
  7. let engine: BABYLON.Engine;
  8. let scene: BABYLON.Scene;
  9. let gravityVector: BABYLON.Vector3;
  10. let noGravityVector: BABYLON.Vector3;
  11. let physicsPlugin: BABYLON.AmmoJSPlugin; // only testing Ammo for now
  12. /**
  13. * Loads the dependencies.
  14. */
  15. before(function(done) {
  16. this.timeout(180000);
  17. (BABYLONDEVTOOLS).Loader
  18. .useDist()
  19. .testMode()
  20. .load(function() {
  21. // Force apply promise polyfill for consistent behavior between chrome headless, IE11, and other browsers.
  22. BABYLON.PromisePolyfill.Apply(true);
  23. done();
  24. });
  25. });
  26. /**
  27. * Create a new engine and scene before each test.
  28. */
  29. beforeEach(function(done) {
  30. engine = new BABYLON.NullEngine({
  31. renderHeight: 256,
  32. renderWidth: 256,
  33. textureSize: 256,
  34. deterministicLockstep: false,
  35. lockstepMaxSteps: 1
  36. });
  37. scene = new BABYLON.Scene(engine);
  38. gravityVector = new BABYLON.Vector3(0, -9.81, 0);
  39. noGravityVector = BABYLON.Vector3.Zero();
  40. physicsPlugin = new BABYLON.AmmoJSPlugin(); // only testing Ammo for now
  41. done();
  42. });
  43. describe('#exercise the functions "physicsEngineComponents"', () => {
  44. it('enables and disables the scene\'s physics engine', () => {
  45. // scene starts off without a physics engine
  46. let physicsEngine = scene.getPhysicsEngine();
  47. expect(physicsEngine).to.be.undefined;
  48. // specify an engine, and ask again
  49. scene.enablePhysics(gravityVector, physicsPlugin);
  50. physicsEngine = scene.getPhysicsEngine();
  51. expect(physicsEngine).to.be.an('object'); // an iPhysicsEngine
  52. // good, we have an plugin plugged in. let's ask for it's name
  53. let name = physicsEngine.getPhysicsPluginName();
  54. expect(name).to.equal('AmmoJSPlugin');
  55. // we can get the entire plugin back, which should be identical to physicsPlugin
  56. let myPhysicsPlugin = physicsEngine.getPhysicsPlugin();
  57. expect(myPhysicsPlugin).to.be.an('object'); // an iPhysicsEnginePlugin
  58. expect(myPhysicsPlugin.name).to.equal('AmmoJSPlugin');
  59. // disable the scene physicsEngine, and see whether still there
  60. scene.disablePhysicsEngine();
  61. physicsEngine = scene.getPhysicsEngine();
  62. expect(physicsEngine).to.be.null; // note that physicsEngine is now null, not undefined
  63. });
  64. it('set and get timestep parameters', () => {
  65. expect(scene.isPhysicsEnabled()).to.be.false;
  66. scene.enablePhysics(gravityVector, physicsPlugin);
  67. expect(scene.isPhysicsEnabled()).to.be.true;
  68. // quick test to see if our physicsPlugin is really an IPhysicsEnginePlugin
  69. let timestep = physicsPlugin.getTimeStep();
  70. expect(timestep).to.be.a('number');
  71. expect(timestep).to.be.closeTo(1 / 60, 0.0001); // default is 1/60th of a second
  72. // let's slow down the timestep to 1/30
  73. physicsPlugin.setTimeStep(1 / 30);
  74. timestep = physicsPlugin.getTimeStep();
  75. expect(timestep).to.be.closeTo(1 / 30, 0.0001);
  76. });
  77. it('sets up and disposes of an imposter on a mesh', () => {
  78. scene.enablePhysics(gravityVector, physicsPlugin);
  79. // The built-in 'sphere' shape. Params: name, subdivs, size, scene
  80. let sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
  81. sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1, restitution: 0.9 }, scene);
  82. expect(sphere.physicsImpostor).to.be.an('object');
  83. let sphereMass = sphere.physicsImpostor.mass;
  84. expect(sphereMass).to.equal(1); // no surprise, we created it with mass: 1
  85. // make sure it has a unique ID
  86. expect(sphere.physicsImpostor.uniqueId).to.be.a('number');
  87. // if we create another sphere, it should have a different ID
  88. let sphere2 = BABYLON.Mesh.CreateSphere("sphere2", 16, 2, scene);
  89. sphere2.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1, restitution: 0.9 }, scene);
  90. expect(sphere.physicsImpostor.uniqueId).to.not.equal(sphere2.physicsImpostor.uniqueId);
  91. });
  92. });
  93. // test 'Scene.onBeforePhysicsObservable' and 'Scene.onAfterPhysicsObservable' callbacks
  94. describe('observables should fire before and after', function() {
  95. var obWasCalled = false;
  96. // only going to test onBefore for now
  97. it('onBefore should trigger as soon as I animate', function(done) {
  98. scene.enablePhysics(gravityVector, physicsPlugin);
  99. scene.onBeforePhysicsObservable.add(function(observer: any) {
  100. expect(obWasCalled).to.be.false;
  101. obWasCalled = true;
  102. done();
  103. });
  104. expect(obWasCalled).to.be.false;
  105. scene.animate(); // rather than call hidden _advancePhysicsEngineStep
  106. expect(obWasCalled).to.be.true;
  107. });
  108. });
  109. // previous tests were on injected properties of Scene.
  110. // now test 'applyImpulse' which is an injected property of AbstractMesh
  111. describe('applyImpulse should move a mesh', function() {
  112. it('should move if an impulse is applied', function() {
  113. scene.enablePhysics(noGravityVector, physicsPlugin); // NO gravity
  114. let getGravity = scene.getPhysicsEngine().gravity;
  115. expect(getGravity).to.deep.equal(BABYLON.Vector3.Zero());
  116. let sphere = BABYLON.MeshBuilder.CreateSphere("mySphere", { diameter: 1 }, scene); // use MeshBuilder instead of Mesh
  117. sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1, restitution: 0.9 }, scene);
  118. let getPosition = sphere.position;
  119. expect(getPosition).to.deep.equal(BABYLON.Vector3.Zero());
  120. let linearVelocity = sphere.physicsImpostor.getLinearVelocity();
  121. expect(linearVelocity).to.deep.equal(BABYLON.Vector3.Zero());
  122. let angularVelocity = sphere.physicsImpostor.getAngularVelocity();
  123. expect(linearVelocity).to.deep.equal(BABYLON.Vector3.Zero());
  124. //////////////////////////////`/////////////////////
  125. // so far, so good. let's run the physics engine. nothing should change.
  126. scene.animate();
  127. getPosition = sphere.position;
  128. expect(getPosition).to.deep.equal(BABYLON.Vector3.Zero());
  129. linearVelocity = sphere.physicsImpostor.getLinearVelocity();
  130. expect(linearVelocity).to.deep.equal(BABYLON.Vector3.Zero());
  131. angularVelocity = sphere.physicsImpostor.getAngularVelocity();
  132. expect(linearVelocity).to.deep.equal(BABYLON.Vector3.Zero());
  133. ///////////////////////////////////////////////////
  134. // now give an impulse, and run the physics engine again. the sphere should start moving.
  135. let force = new BABYLON.Vector3(10, 0, 0);
  136. let contact = new BABYLON.Vector3(-1, 0, 0); // we know sphere has diameter 1. so kick straight down x axis.
  137. sphere.applyImpulse(force, contact); // give the sphere its kick
  138. scene.animate(); // and run the physics engine
  139. getPosition = sphere.position;
  140. expect(getPosition.x).to.be.greaterThan(0); // moved about 0.01, I'm clueless how that was calculated
  141. expect(getPosition.y).to.be.equal(0);
  142. expect(getPosition.z).to.be.equal(0);
  143. linearVelocity = sphere.physicsImpostor.getLinearVelocity();
  144. expect(linearVelocity.x).to.be.closeTo(10, 0.001); // mass of 1, whack of 10, sounds right
  145. expect(linearVelocity.y).to.be.equal(0);
  146. expect(linearVelocity.z).to.be.equal(0);
  147. // we whacked it right along the axis, so don't expect any angular velocity
  148. angularVelocity = sphere.physicsImpostor.getAngularVelocity()
  149. console.log(angularVelocity);
  150. expect(angularVelocity).to.deep.equal(BABYLON.Vector3.Zero());
  151. });
  152. });
  153. })