0

I'm making an open world project with threejs and ammojs physics engine. I did all the setup correctly, the collision works properly, the only problem I face, is I'm unable to move the object I want to, with my joystick (from nipple js). Below is the following code for the object and the joystick control.

function createPlayer() { 
 let pos = {x: 0, y: 0, z: 0};
 let quat = {x: 0, y: 0, z: 0, w: 1};
 let scale = {x: 5, y: 10, z: 5};
 let mass = 0;
 let player = new THREE.Mesh(new THREE.BoxBufferGeometry(), new THREE.MeshBasicMaterial({color: 0x2d2d2d,
 }));
scene.add( player );
player.scale.set(scale.x,scale.y,scale.z);
player.position.set(0,5,0);
player.castShadow = true;
player.receiveShadow = true;

 scene.add(player); 
let transform = new Ammo.btTransform();
                transform.setIdentity();
                transform.setOrigin( new Ammo.btVector3( pos.x, pos.y, pos.z ) );
                transform.setRotation( new Ammo.btQuaternion( quat.x, quat.y, quat.z, quat.w ) );
                let motionState = new Ammo.btDefaultMotionState( transform );

                let colShape = new Ammo.btBoxShape( new Ammo.btVector3( scale.x , scale.y , scale.z  ) );
                colShape.setMargin( 0.05 );

                let localInertia = new Ammo.btVector3( 0, 0, 0 );
                colShape.calculateLocalInertia( mass, localInertia );

                let rbInfo = new Ammo.btRigidBodyConstructionInfo( mass, motionState, colShape, localInertia );
                let body = new Ammo.btRigidBody( rbInfo );


                
                physicsWorld.addRigidBody( body, colGroupPlane, colGroupRedBall );
                
                
let fwdValue = 0;
let bkdValue = 0;
let rgtValue = 0;
let lftValue = 0;
let tempVector = new THREE.Vector3();
let upVector = new THREE.Vector3(0, 1, 0);
let joyManager;

function updatePlayer(){
  // move the player
  const angle = controls.getAzimuthalAngle()
  
    if (fwdValue > 0) {
        tempVector
          .set(0, 0, -fwdValue)
          .applyAxisAngle(upVector, angle)
        player.position.addScaledVector(
          tempVector,
          1
        )
      }
  
      if (bkdValue > 0) {
        tempVector
          .set(0, 0, bkdValue)
          .applyAxisAngle(upVector, angle)
        player.position.addScaledVector(
          tempVector,
          1
        )
      }

      if (lftValue > 0) {
        tempVector
          .set(-lftValue, 0, 0)
          .applyAxisAngle(upVector, angle)
        player.position.addScaledVector(
          tempVector,
          1
        )
      }

      if (rgtValue > 0) {
        tempVector
          .set(rgtValue, 0, 0)
          .applyAxisAngle(upVector, angle)
        player.position.addScaledVector(
          tempVector,
          1
        )
      }
  
  player.updateMatrixWorld()
  
  //controls.target.set( mesh.position.x, mesh.position.y, mesh.position.z );
  // reposition camera
  camera.position.sub(controls.target)
  controls.target.copy(player.position)
  camera.position.add(player.position)
 
}

function addJoystick(){
   const options = {
        zone: document.getElementById('joystickWrapper1'),
        size: 120,
        multitouch: true,
        maxNumberOfNipples: 2,
        mode: 'static',
        restJoystick: true,
        shape: 'circle',
        // position: { top: 20, left: 20 },
        position: { top: '0', left: '0' },
        dynamicPage: true,
      }
   
   
  joyManager = nipplejs.create(options);
  
joyManager['0'].on('move', function (evt, data) {
        const forward = data.vector.y
        const turn = data.vector.x

        if (forward > 0) {
          fwdValue = Math.abs(forward)
          bkdValue = 0
        } else if (forward < 0) {
          fwdValue = 0
          bkdValue = Math.abs(forward)
        }

        if (turn > 0) {
          lftValue = 0
          rgtValue = Math.abs(turn)
        } else if (turn < 0) {
          lftValue = Math.abs(turn)
          rgtValue = 0
        }
      })

     joyManager['0'].on('end', function (evt) {
        bkdValue = 0
        fwdValue = 0
        lftValue = 0
        rgtValue = 0
      })
  
}
addJoystick();
            }
            
Raul Saucedo
  • 1,614
  • 1
  • 4
  • 13
It's Joker
  • 65
  • 10

2 Answers2

1

For player-controlled movement in Ammo.js, I found the best approach was to explicitly set a Linear Velocity, rather than trying to update position directly.

See this answer for an example:

https://stackoverflow.com/a/66425136/15086095

You can even go with one more level of indirection, and apply a force (which will result in acceleration & hence velocity & change in position) rather than trying to control either velocity or position directly.

In general, in my experiences, working with forces and/or velocities is much easier when working with a physics engine, rather than explicitly setting object positions.

However, if you do want to set position directly, this answer to the same question may help you: https://stackoverflow.com/a/66425203/15086095

0

Using set linear velocity method to move the object in the below example it's a ball directly fetching value from joystick and using it to move the sphere ball

let fwdValue = 0;

let bkdValue = 0;

let rgtValue = 0;

let lftValue = 0;

function moveBall() {

  let scalingFactor = 6;
  
  let moveX = rgtValue - lftValue;
  let moveZ = bkdValue - fwdValue;
  let moveY = 0;

  if (moveX == 0 && moveY == 0 && moveZ == 0) return;

  let resultantImpulse = new Ammo.btVector3(moveX, moveY, moveZ)
  resultantImpulse.op_mul(scalingFactor);

  let physicsBody = ballObject.userData.physicsBody;
  physicsBody.setLinearVelocity(resultantImpulse);

}

Problem solved ✔️

It's Joker
  • 65
  • 10