4
$\begingroup$

I am implementing a trackball, i.e. a camera orbiting about a fixed point, in my case the origin. When I do left click with the mouse and start moving it, I compute delta values for the angles of a sphere centered at the origin given the displacement in x and y directions of the mouse. My implementation is as follows

void SimplePerspectiveCamera::
mouseMove(const double& mouseX, const double& mouseY)
{
    if(m_setPan)
    {
        float sensitivity = 0.0075f;
        float newX = (mouseX - m_prevX) * sensitivity;
        float newY = (mouseY - m_prevY) * sensitivity;
        // TODO: Understand if it is necessary to reset the up vector to (0,1,0)
        m_up = Vector(0.0f, 1.0f, 0.0f);
        setLookAt(m_lookAt + Vector(-newX, newY, 0.0f));
        setPosition(m_position + Vector(-newX, newY, 0.0f));
        m_prevX = mouseX;
        m_prevY = mouseY;
    }
    if(m_setRotate)
    {
        float sensitivity = 0.005f;
        float newPhi = (mouseX - m_prevX) * sensitivity;
        float newTheta = (mouseY - m_prevY) * sensitivity;
        // Transform to spherical coordinates to use mouse move as deltas for
        // the angles.
        float r = m_position.norm();
        float theta = std::acos(m_position.y / r);
        float phi = std::atan(m_position.x / m_position.z);

        theta += newTheta;
        phi += newPhi;

        m_up = Vector(0.0f, 1.0f, 0.0f);
        Vector newPosition(r*std::sin(theta)*std::sin(phi), r*std::cos(theta),
                r*std::sin(theta)*std::cos(phi));
        setPosition(newPosition);
        m_prevX = mouseX;
        m_prevY = mouseY;
    }
}

What I was expecting is to be able to rotate the camera around the cube in the scene so that I can see all around it. My code almost achieves this, but I don't understand why after rotating a certain amount the camera jumps to the exact opposite side of the cube.

You can check what weird swap I am talking about this link

What am I missing so that the rotation around the object goes all the way around it?

$\endgroup$
4
  • $\begingroup$ The question lacks some basic explanation about what is being asked. What exactly are you trying to do? From your video, what seems to be happening is that when the rotation crosses a certain point, the rotation instantly snaps back/forward by 180 degrees. (That is, the colors aren't being swapped, you're seeing the back of the cube instead.) $\endgroup$
    – yuriks
    Commented Aug 25, 2015 at 4:39
  • $\begingroup$ I assume that the m_setPan path isn't used here? Also, why does your rotation code modify position? (And I don't see it setting a rotation anywhere.) $\endgroup$
    – yuriks
    Commented Aug 25, 2015 at 4:49
  • $\begingroup$ You assume correct. What I'm doing is to orbit the camera over a sphere centered at the origin, therefore given the displacement in (x,y) of the mouse, I compute the spherical coords of the position of the camera on that sphere, once I have placed the camera I update the view-matrix (done inside setPosition()) $\endgroup$
    – BRabbit27
    Commented Aug 25, 2015 at 4:53
  • 1
    $\begingroup$ Just as a note, this is the kind of thing that can be most easily debugged by printing the m_position, theta and phi values to the screen on every update and observing their values as you drag the cube around. This should make it easy to observe any singularities or abnormalities that could be causing the problem. $\endgroup$
    – yuriks
    Commented Aug 25, 2015 at 5:06

1 Answer 1

6
$\begingroup$

It is likely that your specific problem arises from a singularity in atan when m_position.z goes to 0. Rather than try to debug that, I'll point out that you don't need to transform your camera position into an angle to then modify it: rather, just create a rotation from your newPhi and newTheta angles, in the form of a rotation matrix or quaternion, and then apply it to your vector, directly rotating it without doing the perilous round-trip to an angle.

$\endgroup$
2
  • 1
    $\begingroup$ or use atan2 which is there to deal with all quadrants correctly $\endgroup$ Commented Aug 25, 2015 at 7:53
  • 2
    $\begingroup$ @ratchetfreak Yes, but in general, solution that avoid trigonometry or angles tend to be more robust and elegant. $\endgroup$
    – yuriks
    Commented Aug 25, 2015 at 10:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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