Search code examples
javaandroidkotlinopenglopengl-es

OpenGL : How to rotate (roll) the camera?


The pitch and the heading work perfectly :

fun onDrawFrame(pitch: Float, roll: Float, heading: Float) {
    val lookAtX = cos(pitch) * cos(heading)
    val lookAtY = -sin(pitch)
    val lookAtZ = cos(pitch) * sin(heading)

    val upX = 0.0F
    val upY = 1.0F
    val upZ = 0.0F

    Matrix.setLookAtM(cameraPositionMatrix, 0, 0.0F, 0.0F, 0.0F, lookAtX.toFloat(), lookAtY.toFloat(), lookAtZ.toFloat(), upX.toFloat(), upY.toFloat(), upZ.toFloat())

    ...
}

But how can I rotate (roll) the camera? I guess I need to rotate the UP vector based on the roll angle around the "line of sight", but it's more complex than I thought.

Does anyone know the formula to calculate the cartesian coordinates of a point A(Xa, Ya, Za) after a rotation of an angle δ (in radians) around an axis B(Xb, Yb, Zb)C(Xc, Yc, Zc)?

This question concerns both setLookAtM (OpenGL ES) and gluLookAt (OpenGL)


Solution

  • What you want can easily be achieved with Rx * Ry * Rz * T where Rx/y/z are the respective rotation matrices to rotate around the x, y or z axis, respectively, followed by the (negative) camera translation, which in your case is just (0, 0, 0).

    You could compute it manually by doing the trigonometry by hand and computing the direction and up vectors for lookat by hand, but there's also the route via rotateM, effectively achieving the same:

    fun onDrawFrame(pitch: Float, roll: Float, heading: Float) {
      Matrix.setIdentityM(cameraPositionMatrix, 0)
      Matrix.rotateM(cameraPositionMatrix, 0, pitch, 1, 0, 0);
      Matrix.rotateM(cameraPositionMatrix, 0, heading, 0, 1, 0);
      Matrix.rotateM(cameraPositionMatrix, 0, roll, 0, 0, 1);
    }