OpenGL uses a coordinate system, where the positive z-axis points "out of the screen", it's y-axis points up and it's x-axis to the right. In the end, you need to transform every data to this target coordinate system. Let us call this the "OpenGL" coordinate system.
So there is a transformation between your camera coordinate system, which we will call the "camera coordinate" system, that transforms into the "OpenGL" system. Since both coordinate systems are right-handed, a simple rotation should do the trick. In your case, the difference between the "OpenGL" coordinate system and the "camera coordinate" system is just a rotation around the x-axis by 90 degrees:
$$O_{oc} = R_x(\frac{\pi}{2})$$
Here O means orientation, the index oc means "OpenGL in Camera" and R_x is the rotation matrix that represents a rotation around the x-axis. Note that our orientation is a matrix!
Now you need to know, how your camera coordinate system is oriented in the "world space" system. If you define that both systems have the same orientation if yaw=0 and pitch=0, your camera systems orientation in world space can be described by the 2 following rotations in matrix notation:
$$O_{cw} = R_z(yaw) \cdot R_x(pitch)$$
Keep in mind, that you read matrix multiplication from right to left. So you apply the pitch first by rotating around the x-axis. Afterward, you apply the yaw. Order matters, so don't exchange them.
Now you have all information together, but there is still one problem. The system dependencies are wrong. You want to transform your data from world space to "OpenGL" space. This means you need the matrix:
$$O_{wo} = O_{co} \cdot O_{wc}$$
Note that the indices are swapped! So you need to find the transformations in the opposite direction, which means you need to find the inverse matrix. Luckily, that is rather easy for the orientations. Since orientation (rotation) matrices are so-called orthogonal matrices, the inverse is just the transposed. So you could do:
$$O_{co} = O_{oc}^T$$
$$O_{wc} = O_{cw}^T$$
Another way, that might be a little bit easier to understand is, that if you have applied some rotations to an object (transformed from A to B) and you want to undo the rotations (transform back to A from B), you can do this by simply applying the rotations in the opposite direction in the opposite order. For our matrices that means:
$$\begin{matrix}
O_{oc} &=& R_x(\frac{\pi}{2})\\
O_{co} &=& R_x(-\frac{\pi}{2})
\end{matrix}$$
and
$$\begin{matrix}
O_{cw} = R_z(yaw) \cdot R_x(pitch)\\
O_{wc} = R_x(-pitch) \cdot R_z(-yaw)
\end{matrix}$$
So you get:
$$O_{wo} = R_x(-\frac{\pi}{2}) \cdot R_x(-pitch) \cdot R_z(-yaw)$$
This is the matrix, that transforms the orientations from world space to "OpenGL" space. Its rows are your Front
, Right
and Up
vectors. I am not sure about the ordering since I didn't check it explicitly, but I think the second row is the Front
vector, the first is Right
and the last is Up
. You can try to extract them, but since you need to bundle them into the same matrix later, I would say, don't do it. Keep using the matrix instead.
However, there are still some things to consider: translations. To get to the actual camera position, you need to translate your data. A quick look into the tutorial (the one you linked) just revealed that this is already explained there, so I won't repeat the derivation again. Your full transformation matrix from world to "OpenGL" space is then:
$$M_{wo} = O_{wo}\cdot\begin{bmatrix}
1&0&0&-x_{cam}\\
0&1&0&-y_{cam}\\
0&0&1&-z_{cam}\\
0&0&0&1\\
\end{bmatrix}$$
I am actually using this approach myself. Therefore I know that it works ;). You can still optimize it a little by performing the matrix multiplications by hand, but since you are doing it once per frame, it isn't too important for performance.