Can't limit the camera pitch angle between [-90º, 90º] in OpenGL using vectors!

后端 未结 3 753
终归单人心
终归单人心 2021-01-15 14:19

I\'m having a big problem limiting the camera pitch angle (between -90º and 90º) with the code below. This is somewhat a follow up to this question.

The problem, it

相关标签:
3条回答
  • 2021-01-15 14:38

    Problem 1 : The code belew "// Makes sure all vectors are perpendicular all the time" makes sure that your UP camera vector is actually up (with respect to WORLD_SKY_VECTOR). So :

    • When you look completely down, "up" does not mean a lot. In your case, your camera_up shoud be towards North, not thowards the sky
    • When you keep turning, past that point, the camera rotates to keep its up towarks the sky.

    Look down at your chest. The top of your head is actually down. If you want to look at the same thing, from the same point, but with the top of your head up, you'd have to rotate it (not humanly feasible, sadly)

    Problem 2 : Same as above. CrossProduct(Reference, WORLD_SKY_VECTOR) gives cross(up,down) which does not mean anything, just try on paper.

    If you want to be able to look "upside down" :

    • Compute your view direction vector. You know reliably that because you have your orientation and your pitch.
    • Compute your right vector. It's the same, but with an orientation of 90° more, and a 0 pitch ( camera is always horizontal, i.e. you don't bend your head)
    • Compute your up vector as cross(right,front).

    So :

    yaw += whatever;
    pitch += whatever;
    FrontVector = SphericalToCartesian(yaw, pitch);
    RightVector = SphericalToCartesian(yaw + PI/2.0f, 0.0);
    UpVector = cross(RightVector, FrontVector);
    

    with SphericalToCartesian beeing something like if (pitch=0,yaw=0) means looking to south:

    x = cos(pitch) * sin(yaw)
    y = sin(pitch)
    z = cos(pitch) * cos(yaw)
    
    0 讨论(0)
  • 2021-01-15 14:46

    After while I come up with a solution which is pretty simple and straightforward. Like it was said many times in the answers and comments, the problem lies when the forward vector (my Reference) is looking straight up or down, which means this vector is parallel to WORLD_SKY_VECTOR and that's reason it gets all messy.

    My thought behind this solution is that when I'm looking straight down (or up) and I want to rotate left or right, this is actually a roll rotation around the forward vector. Why not execute a roll movement when the pitch angle is at -90º or 90º instead?

    Putting that together, I solved the problem by simply replacing the yaw/heading rotation with the following code:

    if(angle.y != 0.0f) {
        if(abs(accumPitchAngle) == 90.0f) {
            RightVector = RotateArbitraryAxis(RightVector, Reference, -angle.y);
            UpVector = Vector3D::CrossProduct(RightVector, Reference);
        } else {
            Reference = RotateArbitraryAxis(Reference, WORLD_SKY_VECTOR, angle.y);
            RightVector = Vector3D::CrossProduct(Reference, WORLD_SKY_VECTOR);
            UpVector = Vector3D::CrossProduct(RightVector, Reference);
        }
    }
    

    This seems a fairly simple and straightforward working solution, I'll probably be marking my answer as accepted unless someone points out any strong problem against this implementation that I may not be considering. I'll wait a few hours before doing it, so that the previous answers reach some sort of conclusion.

    0 讨论(0)
  • 2021-01-15 14:49

    You can't take the cross product of two parallel vectors. I think that's where it's failing, i.e. when accumPitchAngle is ±90°.

    You might want to limit it to -89.999° ~ +89.999°.

    Edit: To start from the beginning, you want to convert pitch & yaw into a forward vector and an up vector for gluLookAt(), right? Then I suggest:

    1) Use yaw (and yaw only) to create a right vector that is parallel to the ground.
    2) Cross right and WORLD_SKY_VECTOR to get a forward vector that is correct in yaw but not in pitch.
    3) Rotate forward around right through pitch degrees to get a forward vector that is correct in both pitch and yaw. (I think you've got this far.)
    4) Cross forward and right to get a camera up vector that will work in all cases.

    0 讨论(0)
提交回复
热议问题