Thank you, Patrice.
Very strange, i just checked using the new meta #group 1, and without doing anything else, i got this result (see the video).
Sorry but that's too little info for me. I haven't got the model you're showing in the movie and that's why I can't guess what's wrong with what I'm seeing.

_________________________________
Anyway, I've got rotation working correctly using trig and matrix math.
In mobj.h immediately below the existing
void billBoard(...) function, copy the following three new functions:
__forceinline float dotVec3(float v1[], float v2[]) {
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
}
__forceinline void mtxTranslate(float* m, float x, float y, float z) // Translate existing matrix by x, y, and z
{
m[12] += m[0] * x + m[4] * y + m[8] * z;
m[13] += m[1] * x + m[5] * y + m[9] * z;
m[14] += m[2] * x + m[6] * y + m[10] * z;
}
void mtxRotate(float* m, float x, float y, float z, float deg) // Rotate existing matrix by angle in degrees around x, or y, or z
{
#define d2r .0174533f
float rad = deg * d2r, s = sin(rad), c = cos(rad), t = 1 - c;
float v1[] = { x * x * t + c, x * y * t + z * s, x * z * t - y * s };
float v2[] = { y * x * t - z * s, y * y * t + c, y * z * t + x * s };
float v3[] = { z * x * t + y * s, z * y * t - x * s, z * z * t + c };
for (int i = 0; i < 3; i++) {
float v4[] = { m[0 + i], m[4 + i], m[8 + i] };
m[0 + i] = dotVec3(v4, v1);
m[4 + i] = dotVec3(v4, v2);
m[8 + i] = dotVec3(v4, v3);
}
#undef d2r
}
and, instead of yours, use the following rotation code
in both Mobj_DrawUsingProgrammablePipeline() and Mobj_DrawUsingFixedFuncPipeline():
........
// Test rotation // MLL 06-11-2018:
if ((pMaterial->rotate[0] != 0.0f) && gP.nRotation) {
float m[16];
glPushMatrix();
pMaterial->rotangle += pMaterial->rotate[0];
glGetFloatv(GL_MODELVIEW_MATRIX, m);
mtxTranslate(m, pMesh->centerPoint[0], pMesh->centerPoint[1], pMesh->centerPoint[2]);
if (pMaterial->rotate[1]) mtxRotate(m, pMaterial->rotate[1], 0, 0, pMaterial->rotangle);
if (pMaterial->rotate[2]) mtxRotate(m, 0, pMaterial->rotate[2], 0, pMaterial->rotangle);
if (pMaterial->rotate[3]) mtxRotate(m, 0, 0, pMaterial->rotate[3], pMaterial->rotangle);
mtxTranslate(m, -pMesh->centerPoint[0], -pMesh->centerPoint[1], -pMesh->centerPoint[2]);
glLoadMatrixf(m);
}
........
The code looks somewhat heavy but alas, 3D rotations have never been easy.
Put more spheres in the other quadrants and test if they also behave correctly. Note that rotation preserves the mesh dimensions correctly only when the pMaterial->rotate[1,2,3] values are strictly 1.0f or 0.0f, e.g.
#rotate 5, 1, 0, 1. If the array values are other than those two, the mesh exhibits strange scaling effects. But I think you may find them amusing and probably useful too in some of your future implementations.