I try to make a spherical billboard that follow the camera's direction. But, the result that I got is model get distorted or event twisted. If I'm using only a yaw/pitch quaternion per time, it works perfectly(but I got cylinder billboard instead, which I didn't want).
The sheep is player. The black circle is the objects that I want spherical billboard effect.
Here is the implementation.
void updateRotation(glm::vec3 cameraPosition, glm::vec3 playerPosition) {
glm::quat yaw_quat(1.0f, 0.0f, 0.0f, 0.0f), pitch_quat(1.0f, 0.0f, 0.0f, 0.0f);
//calculate yaw
glm::vec3 toProject(0.0f, 0.0f, 0.0f);
toProject = cameraPosition - playerPosition;
toProject.y = 0.0f;
glm::vec3 normailizedToProject = glm::normalize(toProject);
glm::vec3 normailizedObjLookAt(0.0f, 0.0f, 1.0f);
glm::vec3 upAxis = glm::cross(normailizedObjLookAt, normailizedToProject);
glm::vec3 normalizedUpAxis = glm::normalize(upAxis);
float dotProduct = glm::dot(normailizedObjLookAt, normailizedToProject);
if ((dotProduct < 0.99990f) && (dotProduct > -0.9999f)) {
yaw_quat = glm::angleAxis(acos(dotProduct), normalizedUpAxis);
}
//calculate pitch
toProject = glm::vec3(0.0f, 0.0f, 0.0f);
toProject = cameraPosition - playerPosition;
normailizedToProject = glm::normalize(toProject);
dotProduct = glm::dot(normailizedObjLookAt, normailizedToProject);
if ((dotProduct < 0.99990f) && (dotProduct > -0.9999f)) {
if(normailizedToProject.y < 0.0f) {
pitch_quat = glm::angleAxis(acos(dotProduct), glm::vec3(1.0f, 0.0f, 0.0f));
}
else {
pitch_quat = glm::angleAxis(acos(dotProduct), glm::vec3(-1.0f, 0.0f, 0.0f));
}
}
glm::quat rotationQuat = glm::normalize(yaw_quat * pitch_quat);
}