[SOLVED] How to use ammo, engine only?

Hello, im learning playcanvas engine and trying to use physics.
I think that im loading ammo just fine, but rigidbodies doesnt work.
I feel like im missing some simple thing, but still cant find out by myself.

Heres the code im using.

function wasmSupported() {
    try {
        if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
            const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
            if (module instanceof WebAssembly.Module)
                return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
        }
    } catch (e) { }
    return false;
}
function loadScriptAsync(url, doneCallback) {
    var tag = document.createElement('script');
    tag.onload = function () {
        doneCallback();
    };
    tag.onerror = function () {
        throw new Error('failed to load ' + url);
    };
    tag.async = true;
    tag.src = url;
    document.head.appendChild(tag);
}

function loadWasmModuleAsync(moduleName, jsUrl, binaryUrl, doneCallback) {
    loadScriptAsync(jsUrl, function () {
        var lib = window[moduleName];
        window[moduleName + 'Lib'] = lib;
        lib({
            locateFile: function () {
                return binaryUrl;
            }
        }).then(function (instance) {
            window[moduleName] = instance;
			console.log("ammo loaded?")
            doneCallback();

        });
    });
}

function loadAmmo()
{
	if(wasmSupported())
	{
		loadWasmModuleAsync('Ammo',"./ammo.wasm.js","./ammo.wasm.wasm", init)
	}
}
loadAmmo()
function init()
{
	const canvas = document.getElementById("canvas")
	const app = new pc.Application(canvas)
	app.systems.rigidbody.addBody
	app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW)
	app.setCanvasResolution(pc.RESOLUTION_AUTO)
	
	window.addEventListener('resize', () => app.resizeCanvas())
	
	const bola = new pc.Entity('chao')
	bola.addComponent('model',{
		type: 'sphere'
	})
	bola.setPosition(0,2,0)
	bola.addComponent("rigidbody",{
		type : pc.BODYTYPE_DYNAMIC,
		mass : 10
	})
	
	app.root.addChild(bola)
	bola.rigidbody.activate()

	console.log(bola.rigidbody.isActive())

	const floor = new pc.Entity('chao')
	floor.addComponent('model',{
		type: 'box'
	})
	floor.addComponent("rigidbody")
	app.root.addChild(floor)
	
	const luz = new pc.Entity('light')
	luz.addComponent('light')
	app.root.addChild(luz)
	
	const cam = new pc.Entity('camera')
	cam.addComponent('camera',{
		clearColor: new pc.Color(0.1,0.1,0.1)
	})
	app.root.addChild(cam)
	cam.setPosition(0,1,5)
	cam.lookAt(floor)
	
	app.on('update', dt =>{
		
	})
	app.start()
}

Heres my directory.

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          05/02/2022    12:23        1895438 ammo.js
-a---          05/02/2022    12:23         391789 ammo.wasm.js
-a---          05/02/2022    12:23         659433 ammo.wasm.wasm
-a---          05/02/2022    13:21           2497 fisica.js
-a---          05/02/2022    12:41            733 game.js
-a---          05/02/2022    12:58            482 index.html
-a---          05/02/2022    01:22            141 jsconfig.json
-a---          26/10/1985    05:15        1141086 playcanvas.d.ts
-a---          26/10/1985    05:15        2296300 playcanvas.js

I get no errors on console and console.log("ammo loaded?"), line 34, runs just fine so i think Ammo got loaded.
console.log(bola.rigidbody.isActive()) returns false and the ball doesnt falls.

I got the ammo stuff from here: https://github.com/playcanvas/engine/tree/dev/examples/src/lib/ammo

Hi, @ussaohelcim and welcome,

If you apply force i.e entity.rigidbody.applyForce(force), is there any errors in the console?

Here is an example of Ammo loading, engine only:

There are no errors in console, like i said before.
Apply forces doesnt work.

Iā€™m using this example to learn, and i cant find any differences.

I will try to run your example in a bit, I have a working example, can you try this?

<html>

  <script src="https://code.playcanvas.com/playcanvas-latest.js"></script>

  <body>

    <canvas id="application-canvas"></canvas>

    <a id="logo" href="https://playcanvas.com/" target="_blank"><img src="http://static.playcanvas.com/images/logo/PLAY_FLAT_ORANGE3_SMALL.png" /></a>

  </body>

  <script>

function demo() {

  const canvas = document.getElementById('application-canvas');

  // Create the application and start the update loop

  const app = new pc.Application(canvas);

  app.start();

  // Set the canvas to fill the window and automatically change resolution to be the same as the canvas size

  app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);

  app.setCanvasResolution(pc.RESOLUTION_AUTO);

  window.addEventListener('resize', () => {

    app.resizeCanvas(canvas.width, canvas.height);

  });

  app.scene.ambientLight = new pc.Color(0.2, 0.2, 0.2);

  // Set the gravity for our rigid bodies

  app.systems.rigidbody.gravity.set(0, -9.81, 0);

  function createMaterial(color) {

    const material = new pc.StandardMaterial();

    material.diffuse = color;

    // we need to call material.update when we change its properties

    material.update();

    return material;

  }

  // create a few materials for our objects

  const red = createMaterial(new pc.Color(1, 0.3, 0.3));

  const gray = createMaterial(new pc.Color(0.7, 0.7, 0.7));

  // ***********    Create our floor   *******************

  const floor = new pc.Entity();

  floor.addComponent('model', {

    type: 'box',

    material: gray,

  });

  // scale it

  floor.setLocalScale(10, 1, 10);

  // add a rigidbody component so that other objects collide with it

  floor.addComponent('rigidbody', {

    type: 'static',

    restitution: 0.5,

  });

  // add a collision component

  floor.addComponent('collision', {

    type: 'box',

    halfExtents: new pc.Vec3(5, 0.5, 5),

  });

  // add the floor to the hierarchy

  app.root.addChild(floor);

  // ***********    Create lights   *******************

  // make our scene prettier by adding a directional light

  const light = new pc.Entity();

  light.addComponent('light', {

    type: 'directional',

    color: new pc.Color(1, 1, 1),

    castShadows: true,

    shadowBias: 0.2,

    shadowDistance: 16,

    normalOffsetBias: 0.05,

    shadowResolution: 2048,

  });

  // set the direction for our light

  light.setLocalEulerAngles(45, 30, 0);

  // Add the light to the hierarchy

  app.root.addChild(light);

  // ***********    Create camera    *******************

  // Create an Entity with a camera component

  const camera = new pc.Entity();

  camera.addComponent('camera', {

    clearColor: new pc.Color(0.5, 0.5, 0.8),

    farClip: 50,

  });

  // add the camera to the hierarchy

  app.root.addChild(camera);

  // Move the camera a little further away

  camera.translate(0, 10, 15);

  camera.lookAt(0, 0, 0);

  // ***********    Create templates    *******************

  // Create a template for a falling box

  // It will have a model component of type 'box'...

  const boxTemplate = new pc.Entity();

  boxTemplate.addComponent('model', {

    type: 'box',

    castShadows: true,

    material: gray,

  });

  // ...a rigidbody component of type 'dynamic' so that it is simulated

  // by the physics engine...

  boxTemplate.addComponent('rigidbody', {

    type: 'dynamic',

    mass: 50,

    restitution: 0.5,

  });

  // ... and a collision component of type 'box'

  boxTemplate.addComponent('collision', {

    type: 'box',

    halfExtents: new pc.Vec3(0.5, 0.5, 0.5),

  });

  // Create other shapes too for variety...

  // A sphere...

  const sphereTemplate = new pc.Entity();

  sphereTemplate.addComponent('model', {

    type: 'sphere',

    castShadows: true,

    material: gray,

  });

  sphereTemplate.addComponent('rigidbody', {

    type: 'dynamic',

    mass: 50,

    restitution: 0.5,

  });

  sphereTemplate.addComponent('collision', {

    type: 'sphere',

    radius: 0.5,

  });

  // A capsule...

  const capsuleTemplate = new pc.Entity();

  capsuleTemplate.addComponent('model', {

    type: 'capsule',

    castShadows: true,

    material: gray,

  });

  capsuleTemplate.addComponent('rigidbody', {

    type: 'dynamic',

    mass: 50,

    restitution: 0.5,

  });

  capsuleTemplate.addComponent('collision', {

    type: 'capsule',

    radius: 0.5,

    height: 2,

  });

  // A cylinder...

  const cylinderTemplate = new pc.Entity();

  cylinderTemplate.addComponent('model', {

    type: 'cylinder',

    castShadows: true,

    material: gray,

  });

  cylinderTemplate.addComponent('rigidbody', {

    type: 'dynamic',

    mass: 50,

    restitution: 0.5,

  });

  cylinderTemplate.addComponent('collision', {

    type: 'cylinder',

    radius: 0.5,

    height: 1,

  });

  // add all the templates to an array so that

  // we can randomly spawn them

  const templates = [boxTemplate, sphereTemplate, capsuleTemplate, cylinderTemplate];

  // disable the templates because we don't want them to be visible

  // we'll just use them to clone other Entities

  templates.forEach((template) => {

    template.enabled = false;

  });

  // ***********    Update Function   *******************

  // initialize variables for our update function

  let timer = 0;

  let count = 40;

  // Set an update function on the application's update event

  app.on('update', (dt) => {

    // create a falling box every 0.2 seconds

    if (count > 0) {

      timer -= dt;

      if (timer <= 0) {

        count--;

        timer = 0.2;

        // Clone a random template and position it above the floor

        const template = templates[Math.floor(pc.math.random(0, templates.length))];

        const clone = template.clone();

        // enable the clone because the template is disabled

        clone.enabled = true;

        app.root.addChild(clone);

        clone.rigidbody.teleport(pc.math.random(-1, 1), 10, pc.math.random(-1, 1));

      }

    }

    // Show active bodies in red and frozen bodies in gray

    app.root.findComponents('rigidbody').forEach((body) => {

      body.entity.model.material = body.isActive() ? red : gray;

    });

  });

};

// check for wasm module support

function wasmSupported() {

  try {

    if (typeof WebAssembly === 'object' && typeof WebAssembly.instantiate === 'function') {

      const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));

      if (module instanceof WebAssembly.Module) return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;

    }

  } catch (e) { }

  return false;

}

// load a script

function loadScriptAsync(url, doneCallback) {

  const tag = document.createElement('script');

  tag.onload = function () {

    doneCallback();

  };

  tag.onerror = function () {

    throw new Error(`failed to load ${url}`);

  };

  tag.async = true;

  tag.src = url;

  document.head.appendChild(tag);

}

// load and initialize a wasm module

function loadWasmModuleAsync(moduleName, jsUrl, binaryUrl, doneCallback) {

  loadScriptAsync(jsUrl, () => {

    const lib = window[moduleName];

    window[`${moduleName}Lib`] = lib;

    lib({

      locateFile() {

        return binaryUrl;

      },

    }).then((instance) => {

      window[moduleName] = instance;

      doneCallback();

    });

  });

}

const loadAmmo = () => new Promise((resolve) => {

  if (wasmSupported()) {

    loadWasmModuleAsync('Ammo', './ammo.wasm.js', './ammo.wasm.wasm', () => { resolve(); });

  } else {

    loadWasmModuleAsync('Ammo', './ammo.js', '', () => { resolve(); });

  }

});

loadAmmo().then(() => {

    demo();

});

  </script>

</html>

I just checked the playcanvas script to see if its loading right, and it is right. Apparently my code is running before playcanvas actually load Ammo.
image
image

Yeah, its running just fine. ill try run this way.

Okay, so I tried running your code, here were the issues:

  1. Rigidbodies did not have a collision component to them
  2. app.start() should be at the top, before adding entities to the world
  3. Specified the gravity In the scene,

Fixed version:

<html>

  <script src="https://code.playcanvas.com/playcanvas-latest.js"></script>

  <body>

    <canvas id="application-canvas"></canvas>

    <a id="logo" href="https://playcanvas.com/" target="_blank"><img src="http://static.playcanvas.com/images/logo/PLAY_FLAT_ORANGE3_SMALL.png" /></a>

  </body>

  <script>

// check for wasm module support

function init()

{

    const canvas = document.getElementById('application-canvas');

    const app = new pc.Application(canvas)

    app.systems.rigidbody.gravity.set(0, -9.81, 0);

    app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW)

    app.setCanvasResolution(pc.RESOLUTION_AUTO)

   

    window.addEventListener('resize', () => app.resizeCanvas())

   

    app.start()

    const bola = new pc.Entity('chao')

    bola.addComponent('model',{

        type: 'sphere'

    })

    bola.addComponent('collision', {

type: 'sphere',

radius: 0.5

});

    bola.addComponent('rigidbody', {

type: 'dynamic',

mass: 50,

restitution: 0.5,

});

    bola.setPosition(0,2,0)

    app.root.addChild(bola)

    const floor = new pc.Entity('chao')

    floor.addComponent('model',{

        type: 'box'

    })

    floor.addComponent("rigidbody",{type: 'static' });
    floor.addComponent("collision",{type: 'box' });
   

    app.root.addChild(floor)

   

    const luz = new pc.Entity('light')

    luz.addComponent('light')

    app.root.addChild(luz)

   

    const cam = new pc.Entity('camera')

    cam.addComponent('camera',{

        clearColor: new pc.Color(0.1,0.1,0.1)

    })

    app.root.addChild(cam)

    cam.setPosition(0,1,5)

    cam.lookAt(floor)

   

    app.on('update', dt =>{

       

    })

}

function wasmSupported() {

try {

  if (typeof WebAssembly === 'object' && typeof WebAssembly.instantiate === 'function') {

    const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));

    if (module instanceof WebAssembly.Module) return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;

  }

} catch (e) { }

return false;

}

// load a script

function loadScriptAsync(url, doneCallback) {

const tag = document.createElement('script');

tag.onload = function () {

  doneCallback();

};

tag.onerror = function () {

  throw new Error(`failed to load ${url}`);

};

tag.async = true;

tag.src = url;

document.head.appendChild(tag);

}

// load and initialize a wasm module

function loadWasmModuleAsync(moduleName, jsUrl, binaryUrl, doneCallback) {

loadScriptAsync(jsUrl, () => {

  const lib = window[moduleName];

  window[`${moduleName}Lib`] = lib;

  lib({

    locateFile() {

      return binaryUrl;

    },

  }).then((instance) => {

    window[moduleName] = instance;

    doneCallback();

  });

});

}

const loadAmmo = () => new Promise((resolve) => {

if (wasmSupported()) {

  loadWasmModuleAsync('Ammo', './ammo.wasm.js', './ammo.wasm.wasm', () => { resolve(); });

} else {

  loadWasmModuleAsync('Ammo', './ammo.js', '', () => { resolve(); });

}

});

loadAmmo().then(() => {

  init();

});

  </script>

</html>
1 Like

Thanks, my man. Its working now.
The problem was really the app.start() at the bottom and the miss of collisions components.