7
\$\begingroup\$

I have a spherical mesh of radius 1, centered at (0,0,0) in world coordinates. I want to rotate the sphere so that the clicked point remains under the mouse at all times. However, I cannot find an algorithm that does this. The clicked point always drifts away from the mouse. My current algorithm does the following:

Cast a ray to a sphere of radius 1. Find intersection point in world coordinates (Pa).

After the mouse is moved, cast another ray and find a new intersection point. (Pb) since both those 3D points are on a sphere of radius one, centered at the origin, they should have length = 1 but just in case I normalize them both.

Find the rotation axis by doing Pa x Pb. Normalize the resulting axis

axis = glm::cross(Pa,Pb);
axis = glm::normalize(axis);

Find the angle by doing arccosine on the dot product

float angle = glm::acos(glm::dot(Pa,Pb));  

Build a rotation matrix from the axis and angle

mat4 rotation = glm::rotate(glm::degrees(angle),axis); <-- This was the mistake glm::degrees is not needed

Multiply the existing model matrix by that calculated matrix:

modelMatrix = rotation*modelMatrix;

The rotations are correct but the clicked point does not stay under the mouse (I am checking by drawing a black square point on the sphere texture when the drag starts). If I click and drag to the right, the initially clicked point drifts to the left (lags).

diagram demonstrating drift

\$\endgroup\$
1
\$\begingroup\$

I found the culprit.

glm::degrees(angle)

I had copy pasted that line from some guy off the internet who was for some reason converting the angle to degrees. There is absolutely no need for this conversion.

According to a user on reddit: One warning about this method, your model matrix will degrade over time using this kind of technique (repeatedly multiplying with a new matrix), causing the rendered model to scale or skew. You may want to develop a function to "fix" the matrix, using a technique like converting to another format (quaternion or Euler angles) and then back to a matrix, or more directly by extracting matrix basis vectors, orthonormalizing them, and sticking the values back into the matrix.

\$\endgroup\$
  • 1
    \$\begingroup\$ Little confused - so the glm::rotate function actually takes radians, not degrees? Not sure how the last paragraph relates to the final answer. \$\endgroup\$ – Chaosed0 Jun 10 '15 at 17:53
  • \$\begingroup\$ @Chaosed0 The last paragraph serves to warn users who wish to apply this method that it's not "complete" and that it requires further work to avoid skewing/scaling the model. I don't know what glm::rotate takes because GLM is very poorly documented. \$\endgroup\$ – Jubei Jun 11 '15 at 16:32
  • \$\begingroup\$ Gotcha - just took a look at the doc for GLM, looks like a monster to use. \$\endgroup\$ – Chaosed0 Jun 11 '15 at 17:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.