Ammo.js with Three.js

Hi,i need help with Ammo.js ,my character does not interact with objects, i want him to collide with wall and ground , also push dynamic objects(in my example there is 1 Cube)

I wanted to ask in github (ammo.js) but seems to be not active…

A bit too broad. Try to ask a more specific question.

Would you consider answering a question of form “here’s my code, it doesn’t work, tell me how to make it work”?

Try to think about some important detail in your code that doesn’t work and ask about a that.

If you post a handful of lines of code here, or make a live example on codepen or jsfiddle or some such - you’ll probably see more success.

1 Like


You are simulating the player movement and then updating the Ammo position from the Three position just before rendering. That makes no sense.

To do it properly you need to use a btKinematicCharacterController. Please search in the Bullet forum (Ammo is a port of the Bullet library to js)

Happy coding =)

1 Like

i made some progression , just need to find how to apply gravity to KinematicCharacter

Is it even possible to apply gravity to a kinematic body?

I started using ammo.js few weeks ago and my characters use dynamic bodies. It works well.

Yes, a character has setgravity(). You can do:
character.setGravity( - physicsWorld.getGravity().y() );

Yes, you can use dynamic objects for characters. Of course it will be more complicated to create the forces to control them.

i searched,there is no match for ammo.js
but i found that i need to set body. body.setCollisionFlags to 2 make it kinematic

have you tried using btKinematicCharacterController?

I suggest using cannonjs instead

is it easier ?

i use ammo.js because i have function that handles complex shapes for collision

Aaaah ok … sorry I hop u found what u needed cuz idk how ammo works

1 Like

Here you have a piece of code I did some time ago, Character.js (in a multiplayer game). If you extract some useful info from it, I’ll be happy :slight_smile:

var Character = {
	name: "Character",
	factory: createCharacter

var physics;
var models;

if ( typeof module !== 'undefined' ) {

	module.exports = Character;

	physics = require( '../physics.js' );
	models = require( '../models.js' );
	modelsLoading = require( '../modelsLoading.js' );


function createCharacter( entityId, entityParams, isClient, phase ) {

	var entity = {
		id: entityId,
		context: null,
		params: entityParams,
		tick: isClient ? clientTick : serverTick,
		finish: isClient ? clientFinish : serverFinish,
		onAdded: isClient? null : serverOnAdded,
		onRemoved: isClient ? null : serverOnRemoved,
		updateObject: {
			id: entityId,
			x: entityParams.x,
			y: entityParams.y,
			z: entityParams.z,
			qx: entityParams.qx,
			qy: entityParams.qy,
			qz: entityParams.qz,
			qw: entityParams.qw
		needsUpdate: true,

		threeObject: null,
		physicsObject: null,
		controller: null,
		numControlAxes: 4


	var Ammo;
	var ghostObject;
	var character;

	var tempVec1;
	var tempVec2;
	var tempQuat1;
	var tempQuat2;
	var tempVecBt1;
	var transformAux1;

	var context = phase.getContext( entityParams.contextId );

	( isClient ? clientInit : serverInit )();

	return entity;

	function serverInit() {

		Ammo = physics.getAmmo();

		tempVec1 = new THREE.Vector3();
		tempVec2 = new THREE.Vector3();
		tempQuat1 = new THREE.Quaternion();
		tempQuat2 = new THREE.Quaternion();
		tempVecBt1 = new Ammo.btVector3();
		tempQuatBt1 = new Ammo.btQuaternion();
		transformAux1 = new Ammo.btTransform();

		ghostObject = new Ammo.btPairCachingGhostObject();

		tempVecBt1.setValue( entityParams.x, entityParams.y, entityParams.z );
		tempQuatBt1.setValue( entityParams.qx, entityParams.qy, entityParams.qz, entityParams.qw );
		transformAux1.setOrigin( tempVecBt1 );
		transformAux1.setRotation( tempQuatBt1 );
		ghostObject.setWorldTransform( transformAux1 );

		var shape = context.createModelPhysicsShape( entity );
		ghostObject.setCollisionShape( shape );
		ghostObject.setCollisionFlags ( ghostObject.getCollisionFlags() | 16 );

		character = new Ammo.btKinematicCharacterController( ghostObject, shape, entityParams.stepHeight, 1 );
		character.setJumpSpeed( entityParams.jumpSpeed );
		character.setMaxSlope( entityParams.maxSlopeRadians );
		character.setFallSpeed( entityParams.terminalVelocity );
		character.setGravity( - context.physicsWorld.getGravity().y() );


	function clientInit() {

		models.createEntityModelVisual( entity );


	function serverTick( deltaTime ) {

		// User control

		var controller = entity.controller;
		var updateObject = entity.updateObject;

		tempQuat1.set( updateObject.qx, updateObject.qy, updateObject.qz, updateObject.qw );
		var t = ghostObject.getWorldTransform();

		// Walking

		tempVec1.set( 0, 0, 1 ).applyQuaternion( tempQuat1 ).multiplyScalar( controller.y );
		tempVec2.set( - 1, 0, 0 ).applyQuaternion( tempQuat1 ).multiplyScalar( controller.w * 0.5 ).add( tempVec1 );
		tempVec2.multiplyScalar( entityParams.walkSpeed * deltaTime );
		tempVecBt1.setValue( tempVec2.x, tempVec2.y, tempVec2.z );
		character.setWalkDirection( tempVecBt1 );

		// Rotation

		if ( controller.x !== 0 ) {

			tempVec1.set( 0, 1, 0 ).applyQuaternion( tempQuat1 );
			tempQuat2.setFromAxisAngle( tempVec1, - deltaTime * entityParams.rotationSpeed * controller.x );
			tempQuat1.multiply( tempQuat2 );
			tempQuatBt1.setValue( tempQuat1.x, tempQuat1.y, tempQuat1.z, tempQuat1.w );
			t.setRotation( tempQuatBt1 );
			// ghostObject.setWorldTransform( t );


		// Jump

		// Update entity

		var p = t.getOrigin();
		var q = t.getRotation();

		updateObject.x = p.x();
		updateObject.y = p.y();
		updateObject.z = p.z();

		updateObject.qx = q.x();
		updateObject.qy = q.y();
		updateObject.qz = q.z();
		updateObject.qw = q.w();

		entity.needsUpdate = true;


	function clientTick( deltaTime ) {


	function serverOnAdded() {

		context.physicsWorld.addCollisionObject( ghostObject, 32, -1 );

		context.physicsWorld.addAction( character );


	function serverOnRemoved() {

		context.physicsWorld.removeCollisionObject( ghostObject );

		context.physicsWorld.removeAction( character );


	function serverFinish() {
		// TODO

	function clientFinish() {

		// TODO dispose three object
		//entity.threeObject = null;


1 Like

Thank you so much !!!, this is the missing documentation in ammo.js

1 Like

just a question controller is direction or velocity of player ?

It is just the axis of the joystick, from -1 to 1. So, it is direction.

It can also mean cursors direction, etc.

what is controller.w is it z direction ?

controller.x and controller.y are one gamepad joystick, and controller.z and controller.w are the second gamepad joystick.

1 Like

A good reference is “Bullet physics 2.80 manual”, search it online :wink:

i know this manual, but there are no concrete examples of btKinematicCharacterController