So how do you implement rotation so that the axes do not rotate with the object?
It is not clear what you want to do when you rotate (and just do with any affine transformation) you move from one coordinate system to another, for example, turning the cube around its center around the X axis the local coordinate system of the cube will also be rotated, it is important to understand that any transformation is performed relative to which - then the selected coordinate system, in your case relative to the world.
Let Rx(alpha), Ry(betta), Rz(gamma) be the rotation matrices around the corresponding axes at the angles alpha, betta, gamma .
And T(v) the transfer matrix, where v is the positional transfer vector.
Then the coordinates of the vertices of the cube rotated relative to the vector v around the selected axes will be calculated by the formula
transformedVector = T(v)*Rz(gamma)*Ry(betta)*Rx(alpha)*T(-v)
or if using old openGL functions like this:
glPushMatrix(); // сохраняем в стек текущую модельную матрицу чтобы последующие пребразования затронули только куб glTranslatef(x, y, z); glRotate(alpha, ...); glTranslatef(-x, -y, -z); glPopMatrix()`
in both cases we move to the origin, rotate, and go back to our place.
And locking axes is another matter, and in the case of Euler rotation it can naturally arise.
But in order to use quaternions it is necessary to understand the transformations first.