123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- // 'physicsEngineComponents.ts' injects methods and properties into Scene and AbstractMesh
- // these tests only check that Scene and AbstractMesh have the expected methods.
- /**
- * Describes the test suite.
- */
- describe('Babylon physicsComponents', () => {
- let engine: BABYLON.Engine;
- let scene: BABYLON.Scene;
- let gravityVector: BABYLON.Vector3;
- let noGravityVector: BABYLON.Vector3;
- let physicsPlugin: BABYLON.AmmoJSPlugin; // only testing Ammo for now
- /**
- * Loads the dependencies.
- */
- before(function(done) {
- this.timeout(180000);
- (BABYLONDEVTOOLS).Loader
- .useDist()
- .testMode()
- .load(function() {
- // Force apply promise polyfill for consistent behavior between chrome headless, IE11, and other browsers.
- BABYLON.PromisePolyfill.Apply(true);
- done();
- });
- });
- /**
- * Create a new engine and scene before each test.
- */
- beforeEach(function(done) {
- engine = new BABYLON.NullEngine({
- renderHeight: 256,
- renderWidth: 256,
- textureSize: 256,
- deterministicLockstep: false,
- lockstepMaxSteps: 1
- });
- scene = new BABYLON.Scene(engine);
- gravityVector = new BABYLON.Vector3(0, -9.81, 0);
- noGravityVector = BABYLON.Vector3.Zero();
- physicsPlugin = new BABYLON.AmmoJSPlugin(); // only testing Ammo for now
- done();
- });
- describe('#exercise the functions "physicsEngineComponents"', () => {
- it('enables and disables the scene\'s physics engine', () => {
- // scene starts off without a physics engine
- let physicsEngine = scene.getPhysicsEngine();
- expect(physicsEngine).to.be.undefined;
- // specify an engine, and ask again
- scene.enablePhysics(gravityVector, physicsPlugin);
- physicsEngine = scene.getPhysicsEngine();
- expect(physicsEngine).to.be.an('object'); // an iPhysicsEngine
- // good, we have an plugin plugged in. let's ask for it's name
- let name = physicsEngine.getPhysicsPluginName();
- expect(name).to.equal('AmmoJSPlugin');
- // we can get the entire plugin back, which should be identical to physicsPlugin
- let myPhysicsPlugin = physicsEngine.getPhysicsPlugin();
- expect(myPhysicsPlugin).to.be.an('object'); // an iPhysicsEnginePlugin
- expect(myPhysicsPlugin.name).to.equal('AmmoJSPlugin');
- // disable the scene physicsEngine, and see whether still there
- scene.disablePhysicsEngine();
- physicsEngine = scene.getPhysicsEngine();
- expect(physicsEngine).to.be.null; // note that physicsEngine is now null, not undefined
- });
- it('set and get timestep parameters', () => {
- expect(scene.isPhysicsEnabled()).to.be.false;
- scene.enablePhysics(gravityVector, physicsPlugin);
- expect(scene.isPhysicsEnabled()).to.be.true;
- // quick test to see if our physicsPlugin is really an IPhysicsEnginePlugin
- let timestep = physicsPlugin.getTimeStep();
- expect(timestep).to.be.a('number');
- expect(timestep).to.be.closeTo(1 / 60, 0.0001); // default is 1/60th of a second
- // let's slow down the timestep to 1/30
- physicsPlugin.setTimeStep(1 / 30);
- timestep = physicsPlugin.getTimeStep();
- expect(timestep).to.be.closeTo(1 / 30, 0.0001);
- });
- it('sets up and disposes of an imposter on a mesh', () => {
- scene.enablePhysics(gravityVector, physicsPlugin);
- // The built-in 'sphere' shape. Params: name, subdivs, size, scene
- let sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
- sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1, restitution: 0.9 }, scene);
- expect(sphere.physicsImpostor).to.be.an('object');
- let sphereMass = sphere.physicsImpostor.mass;
- expect(sphereMass).to.equal(1); // no surprise, we created it with mass: 1
- // make sure it has a unique ID
- expect(sphere.physicsImpostor.uniqueId).to.be.a('number');
- // if we create another sphere, it should have a different ID
- let sphere2 = BABYLON.Mesh.CreateSphere("sphere2", 16, 2, scene);
- sphere2.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1, restitution: 0.9 }, scene);
- expect(sphere.physicsImpostor.uniqueId).to.not.equal(sphere2.physicsImpostor.uniqueId);
- });
- });
- // test 'Scene.onBeforePhysicsObservable' and 'Scene.onAfterPhysicsObservable' callbacks
- describe('observables should fire before and after', function() {
- var obWasCalled = false;
- // only going to test onBefore for now
- it('onBefore should trigger as soon as I animate', function(done) {
- scene.enablePhysics(gravityVector, physicsPlugin);
- scene.onBeforePhysicsObservable.add(function(observer: any) {
- expect(obWasCalled).to.be.false;
- obWasCalled = true;
- done();
- });
- expect(obWasCalled).to.be.false;
- scene.animate(); // rather than call hidden _advancePhysicsEngineStep
- expect(obWasCalled).to.be.true;
- });
- });
- // previous tests were on injected properties of Scene.
- // now test 'applyImpulse' which is an injected property of AbstractMesh
- describe('applyImpulse should move a mesh', function() {
- it('should move if an impulse is applied', function() {
- scene.enablePhysics(noGravityVector, physicsPlugin); // NO gravity
- let getGravity = scene.getPhysicsEngine().gravity;
- expect(getGravity).to.deep.equal(BABYLON.Vector3.Zero());
- let sphere = BABYLON.MeshBuilder.CreateSphere("mySphere", { diameter: 1 }, scene); // use MeshBuilder instead of Mesh
- sphere.physicsImpostor = new BABYLON.PhysicsImpostor(sphere, BABYLON.PhysicsImpostor.SphereImpostor, { mass: 1, restitution: 0.9 }, scene);
- let getPosition = sphere.position;
- expect(getPosition).to.deep.equal(BABYLON.Vector3.Zero());
- let linearVelocity = sphere.physicsImpostor.getLinearVelocity();
- expect(linearVelocity).to.deep.equal(BABYLON.Vector3.Zero());
- let angularVelocity = sphere.physicsImpostor.getAngularVelocity();
- expect(linearVelocity).to.deep.equal(BABYLON.Vector3.Zero());
- //////////////////////////////`/////////////////////
- // so far, so good. let's run the physics engine. nothing should change.
- scene.animate();
- getPosition = sphere.position;
- expect(getPosition).to.deep.equal(BABYLON.Vector3.Zero());
- linearVelocity = sphere.physicsImpostor.getLinearVelocity();
- expect(linearVelocity).to.deep.equal(BABYLON.Vector3.Zero());
- angularVelocity = sphere.physicsImpostor.getAngularVelocity();
- expect(linearVelocity).to.deep.equal(BABYLON.Vector3.Zero());
- ///////////////////////////////////////////////////
- // now give an impulse, and run the physics engine again. the sphere should start moving.
- let force = new BABYLON.Vector3(10, 0, 0);
- let contact = new BABYLON.Vector3(-1, 0, 0); // we know sphere has diameter 1. so kick straight down x axis.
- sphere.applyImpulse(force, contact); // give the sphere its kick
- scene.animate(); // and run the physics engine
- getPosition = sphere.position;
- expect(getPosition.x).to.be.greaterThan(0); // moved about 0.01, I'm clueless how that was calculated
- expect(getPosition.y).to.be.equal(0);
- expect(getPosition.z).to.be.equal(0);
- linearVelocity = sphere.physicsImpostor.getLinearVelocity();
- expect(linearVelocity.x).to.be.closeTo(10, 0.001); // mass of 1, whack of 10, sounds right
- expect(linearVelocity.y).to.be.equal(0);
- expect(linearVelocity.z).to.be.equal(0);
- // we whacked it right along the axis, so don't expect any angular velocity
- angularVelocity = sphere.physicsImpostor.getAngularVelocity()
- console.log(angularVelocity);
- expect(angularVelocity).to.deep.equal(BABYLON.Vector3.Zero());
- });
- });
- })
|