Suppose our face is on the x-y plane, and there is a constraint that the axis of this face must be (0,1,0). I hope that when the camera moves, this face will face the camera as much as possible. It can only rotate around the axis, which is equivalent to adding an axis constraint to the sprite model.
I simply implemented the following code.
/////init
let planeGeometry;
let planeMaterial;
let planeMesh;
let rotationAngle = 0;
planeGeometry = new THREE.PlaneGeometry( 100, 100 );
planeMaterial = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } );
planeMesh = new THREE.Mesh( planeGeometry, planeMaterial );
/////handle
console.log( camera.position )
//Get the normal vector of the face in world coordinates.
const localNormals = planegeometry.attributes.normal.array;
const localNormal = new THREE.Vector3();
localNormal.fromArray( localNormals, 0 );
planemesh.updateMatrixWorld( true );
const worldNormal = localNormal.clone().applyMatrix4( planemesh.matrixWorld ).normalize();
console.log( worldNormal );
//Get the view vector of the camera looking at this face.
const cameraViewVector = new THREE.Vector3( camera.position.x, 0, camera.position.z ).normalize();
//The angle between the two vectors above cannot actually be calculated this way,
//because if the surface is not so special (on the x-y plane),
//the calculation of this angle depends on three vectors instead of two
//(here we take the shortcut of setting the y value of the view vector to 0, so it appears simpler).
const angle = cameraViewVector.angleTo( worldNormal );
const rotationAxis = new THREE.Vector3( 0, 1, 0 ).normalize();
rotationAngle += angle;
rotationAngle = rotationAngle % ( Math.PI * 2 );
console.log( angle )
console.log( rotationAngle )
const quaternion = new THREE.Quaternion().setFromAxisAngle( rotationAxis, rotationAngle );
planeMesh.setRotationFromQuaternion( quaternion );
This code works fine when I move the camera counterclockwise, and the face will follow as closely as possible, but it doesn’t work when I move the camera clockwise, because the angle calculation becomes erratic. How can I solve this problem, or is there another way to achieve what I want? Thank you everyone.