1
  • 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...)

Jean-Philippe Encausse
  • 1,491
  • 2
  • 22
  • 40

1 Answers1

0

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.

M -
  • 26,908
  • 11
  • 49
  • 81
  • Yes it was a typo for the first. – Jean-Philippe Encausse Nov 02 '22 at 16:36
  • I tried the angleTo from 2 positions then set mesh.rotation.y += radian but multiple call still perform rotation in loop. The radian is the same. How do you set the radian ? – Jean-Philippe Encausse Nov 02 '22 at 16:47
  • Just set the rotation to its absolute value: `mesh.rotation.y = radian;`, without the `+=` symbol. The `+=` symbol would keep adding and adding more rotations if the calculation is performed multiple times in a loop. – M - Nov 02 '22 at 16:50
  • Very weird I still get 9 to 18 deg if I turn aroud the avatar where it should be way more – Jean-Philippe Encausse Nov 02 '22 at 17:03
  • Hmm... after thinking about it some more, I think taking this `.angleTo()` approach is probably flawed. The angle between two points doesn't mean that's the y-axis rotation. For example, the angle between two points can be 90 degrees, but its final rotation could be 180 degrees. I'll think about it some more later today and see if I can update my answer. – M - Nov 02 '22 at 17:17
  • @Jean-PhilippeEncausse Just added an update to my answer, it should give you an absolute y-axis rotation for your avatar. – M - Nov 02 '22 at 17:38
  • I don't understand how it works, but it seems to works !!! with radians = Math.atan2(xDist, zDist) – Jean-Philippe Encausse Nov 02 '22 at 22:58
  • 1
    BTW, the little quick and dirty result : https://www.youtube.com/watch?v=Q7mbBU26Q_o – Jean-Philippe Encausse Nov 04 '22 at 00:44