Advertisement

Using quaternions to update a euler based camera using glm

Started by November 08, 2021 07:04 PM
0 comments, last by pavixavi 3 years ago

I have a struct which I am passing as an argument. The idea is to take create a quaternion via `slerp` function by comparing the quaternion of a camera object and some other target `&t` orientation.

The problem is probably that I do not understand the math. The camera currently operates on euler angles (I do not have a problem with this presently). So I want to take the slerp quaternion, convert to euler, apply the transormation to the camera vectors, and then store a new quarternion based on the new euler values for use as a comparison.

Struct below with quaternion comparison function. Struggling to offer up more to describe the visual error other then the camera is freaking out significantly. Thanks.

Struct which I pass pass as argument for a `std::function` member elsewhere:

struct panning_camera_handle {

Camera* cam;

bool operator ()(glm::quat& s, const glm::quat& t) {

float dps{ 180.0f }; // degrees per second

//first calculate the distance (angular magnitude between two rotation quaternions)

float cosOmega = glm::dot(s, t);

float sinOmega = glm::sqrt(1.0f - cosOmega * cosOmega);

float omega = glm::degrees(atan2(sinOmega, cosOmega)); // the diff. angle

if (omega < 1.0f) {

// CALC QUAT TO MOVE ORIENTATION TO TARGET

auto q = glm::slerp(s, t, 1.0f); //single slerp step

cam->update_camera_vectors(q);

return true; //if angular distance is very small

} //we are done, return true.

else {

float min = dps * ejn::deltaTime * 0.001f; // min ang. displacement this cycle

if (omega < min) {

//CALC AS ABOVE

auto q = glm::slerp(s, t, 1.0f); //single slerp step

cam->update_camera_vectors(q);

return true;

}

else {

//CALC THE INCREMENT AND UPDATE CAMERA VECTORS

float tt = min / omega;

auto q = glm::slerp(s, t, tt);

cam->update_camera_vectors(q);

return false; //test for completion on next cycle

}

}

}

};

Current revision of camera function (theres been a few...) which I would like to make the transformation. Note the `orient` member which is the variable I want to use to make further comparisons in the struct above.

void enjyn_Camera::update_camera_vectors(glm::quat q) {

eul = glm::degrees(glm::eulerAngles(q));

if (eul.x > 89.0f)

eul.x = 89.0f;

if (eul.x < -89.0f)

eul.x = -89.0f;

glm::vec3 front;

front.x = cos(glm::radians(eul.y)) * cos(glm::radians(eul.x));

front.y = sin(glm::radians(eul.x));

front.z = sin(glm::radians(eul.y)) * cos(glm::radians(eul.x));

Front = Front + glm::normalize(front);

Right = glm::normalize(glm::cross(Front, WorldUp)); // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.

Up = glm::normalize(glm::cross(Right, Front));

orient = glm::quat(glm::radians(eul));

}

This topic is closed to new replies.

Advertisement