Search code examples
javascripthtmlaframe

How to move a glTF model in the direction it is facing in A-frame?


I have a gltf model of my robot loaded in A-frame scene version 1.0.4. So far I can turn the robot about its x,y, z axes, but when I try to move it forward it still moves in its initial direction rather than the direction it's facing. I want to be able to control its movements with my keyboard without using any external libraries. I believe I have to use Quaternions, but I haven't figured out how to use them yet. Here is my A-frame code so far.

<a-scene id="myScene">
  <a-entity environment="preset:forest;"></a-entity>

 <a-entity gltf-model="#humanoid" id="robot" position="0 20 0" rotation="0 0          0" 
   scale="0.0001 0.0001 0.0001" static-body>
 </a-entity>
</a-scene>

And here is my script

const robot = document.getElementById('robot');

const update = () => {
   if (keys.forward) {
       let {x,y,z} = robot.object3D.position;
       let ry = robot.object3D.rotation.y;
       z += Math.cos(ry * Math.PI/180)/12;
       x += Math.sin(ry * Math.PI/180)/12;
       robot.object3D.position.set(x, y, z); 
}
   else if (keys.backwards) {
       let {x, y, z} = robot.object3D.position;
       let ry = robot.object3D.rotation.y;
       z -= Math.cos(ry * Math.PI/180)/10;
       x -= Math.sin(ry * Math.PI/180)/10;
       robot.object3D.position.set(x, y, z);   
}
 if (keys.turnLeft) {
       let {x, y, z} = robot.getAttribute('rotation');
       y += 0.25;
       robot.setAttribute('rotation',{x,y,z});
}
    else if (keys.turnRight) {
        let {x, y, z} = robot.getAttribute('rotation');
        y -= 0.25;
        robot.setAttribute('rotation',{x,y,z});
}
}


Solution

  • let ry = robot.object3D.rotation.y;
    z += Math.cos(ry * Math.PI/180)/12;
    

    Although a-frame uses degrees for rotation, threejs uses radians, so there is no need to convert them again:

    const robot = document.querySelector("a-box")
    document.body.addEventListener("keydown", (evt) => {
       if (evt.key === 's') {
           let {x,y,z} = robot.object3D.position;
           let ry = robot.object3D.rotation.y;
           z += Math.cos(ry)/12;
           x += Math.sin(ry)/12;
           robot.object3D.position.set(x, y, z); 
        } else if (evt.key === 'w') {
           let {x, y, z} = robot.object3D.position;
           let ry = robot.object3D.rotation.y;
           console.log(ry)
           z -= Math.cos(ry)/10;
           x -= Math.sin(ry)/10;
           robot.object3D.position.set(x, y, z);   
         }
         if (evt.key === 'a') {
           let {x, y, z} = robot.getAttribute('rotation');
           y += 1;
           robot.setAttribute('rotation',{x,y,z});
         } else if (evt.key === 'd') {
           let {x, y, z} = robot.getAttribute('rotation');
           y -= 1;
           robot.setAttribute('rotation',{x: x,y: y,z: z});
         }
    })
    <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
    <a-scene>
      <a-box position="-1 0.5 -3" rotation="0 0 0" color="#4CC3D9">
        <a-sphere radius="0.5" position="0 0 -1"></a-sphere>
      </a-box>
      <a-entity camera position="0 1.6 0"></a-entity>
    </a-scene>


    Same with getWorldDirection:

    const robot = document.querySelector("a-box")
    const direction = new THREE.Vector3();
    document.body.addEventListener("keydown", (evt) => {
       if (evt.key === 's') {
         // get robot direction
         robot.object3D.getWorldDirection(direction);
         // add a "speed" value
         direction.multiplyScalar(0.1)
         // add the new vector to the actual position
         robot.object3D.position.add(direction)
        } else if (evt.key === 'w') {
         robot.object3D.getWorldDirection(direction);
         direction.multiplyScalar(-0.1)
         robot.object3D.position.add(direction) 
        }
        if (evt.key === 'a') {
         let {x, y, z} = robot.getAttribute('rotation');
         y=y+1
         robot.setAttribute('rotation',{x,y,z});
        } else if (evt.key === 'd') {
         let {x, y, z} = robot.getAttribute('rotation');
         y=y-1
         robot.setAttribute('rotation',{x: x,y: y,z: z});
        }
    })
    <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
    <a-scene>
      <a-box position="-1 0.5 -3" rotation="0 0 0" color="#4CC3D9">
        <a-sphere radius="0.5" position="0 0 -1"></a-sphere>
      </a-box>
      <a-entity camera position="0 1.6 0"></a-entity>
    </a-scene>