Search code examples
three.jsmixamo

ThreeJS : How to get the angle between2 object


  • I have an Avatar at a given Position (v0) and Rotation (r0)
  • I have an Object at a givent Position (v1)

I looking for the angle to rotate the avatar toward v1. I need the angle I don't want to use lookAt() function

// Get the Avatar Position
let v0 = new THREE.Vector3();
avatar.getWorldPosition(v0)

// Get the Object Position
let v1 = new THREE.Vector3();
obj.getWorldPosition(v0)

// Get the direction v0 to v1
let dir0 = new THREE.Vector3();
dir0.subVectors( v0, v1 ).normalize();

// Get the direction of avatar (where it look at)
let dir2 = new THREE.Vector3();
avatar.getWorldDirection(dir2)

// Get the angle between the 2 direction
let radians =  dir0.angleTo(dir2)

It doesn't work !

  • The this.mesh.lookAt(v1.setY(0)) works and rotate correctly the mesh
  • But the angle computation didn't work because of avatar.getWorldDirection
  • BTW, since everything is on the same plane I don't need 3D (only 2D)
  • BTW, The avatar (Mixamo) seems to face backward

I need that angle to trigger some animation (if angle > 90 then trigger 90, if angle > 180 then turnback animation...)


Solution

  • Your code has a few mistakes. obj.getWorldPosition(v0) is going to overwrite the v0 values retrieved with avatar.getWorldPosition(v0), so when you subtract v0 - v1 you'll get a vector with a magnitude of 0.

    Looking at the documentation of Vector3.angleTo(), it says all you need to do is input the positions, without any subtraction necessary:

    let posAvatar = new THREE.Vector3();
    avatar.getWorldPosition(posAvatar);
    
    
    let posObj = new THREE.Vector3();
    obj.getWorldPosition(posObj);
    
    const angleRadians = posAvatar.angleTo(posObj);
    
    // convert from radians to degrees
    const angleDeg = THREE.MathUtils.radToDeg(angleRadians);
    

    Keep in mind, both objects will need to be on the same plane for this 2D angle to be accurate.

    Update:

    This approach uses the Javascript Math.atan2() method to calculate the absolute y-axis rotation from your avatar's vantage point towards the obj. This also only uses the x,z positions so any height variations are ignored.

    let posAvatar = new THREE.Vector3();
    avatar.getWorldPosition(posAvatar);
    
    let posObj = new THREE.Vector3();
    obj.getWorldPosition(posObj);
    
    const xDist = posObj.x - posAvatar.x;
    const zDist = posObj.z - posAvatar.z;
    const angle = Math.atan2(zDist, xDist) * 180 / Math.PI;
    
    avatar.rotation.y = angle;
    

    Your avatar might be facing a different axis, so you can just add 90 or 180 degrees to the final angle value.