Cube squeezed while rotating, using GLKit

So I am trying to draw and rotate a cube using GLKit on an iPad. My problem is that as the cube rotates it seems as the aspect ratio changes with it, squeezing it as it rotates. To be more precise, the face of the cube on the starting position has a ratio of 1/2 (width/height). Lets say A is the base of the cube and B is the height(we do not care about the depth right now, although the effect I am explaining occurs there as well). So at the starting position A/B=1/2. As it turns clockwise it gets squeezed, side A decreases and side B increases, so after a 90 degrees clockwise rotation(anticlockwise has the same effect) the ratio A/B is 2/1.
Some code…

The cube vertices:

+ (void)initialize {
    if (!initialized) {
        vertices[0] = GLKVector3Make(-0.5, -0.5,  0.5); // Left  bottom front
        vertices[1] = GLKVector3Make( 0.5, -0.5,  0.5); // Right bottom front
        vertices[2] = GLKVector3Make( 0.5,  0.5,  0.5); // Right top    front
        vertices[3] = GLKVector3Make(-0.5,  0.5,  0.5); // Left  top    front
        vertices[4] = GLKVector3Make(-0.5, -0.5, -0.5); // Left  bottom back
        vertices[5] = GLKVector3Make( 0.5, -0.5, -0.5); // Right bottom back
        vertices[6] = GLKVector3Make( 0.5,  0.5, -0.5); // Right top    back
        vertices[7] = GLKVector3Make(-0.5,  0.5, -0.5); // Left  top    back
        
        colors[0] = GLKVector4Make(1.0, 0.0, 0.0, 1.0); // Red
        colors[1] = GLKVector4Make(0.0, 1.0, 0.0, 1.0); // Green
        colors[2] = GLKVector4Make(0.0, 0.0, 1.0, 1.0); // Blue
        colors[3] = GLKVector4Make(0.0, 0.0, 0.0, 1.0); // Black
        colors[4] = GLKVector4Make(0.0, 0.0, 1.0, 1.0); // Blue
        colors[5] = GLKVector4Make(0.0, 0.0, 0.0, 1.0); // Black
        colors[6] = GLKVector4Make(1.0, 0.0, 0.0, 1.0); // Red
        colors[7] = GLKVector4Make(0.0, 1.0, 0.0, 1.0); // Green
        
        int vertexIndices[36] = {
            // Front
            0, 1, 2,
            0, 2, 3,
            // Right
            1, 5, 6,
            1, 6, 2,
            // Back
            5, 4, 7,
            5, 7, 6,
            // Left
            4, 0, 3,
            4, 3, 7,
            // Top
            3, 2, 6,
            3, 6, 7,
            // Bottom
            4, 5, 1,
            4, 1, 0,
        };
        
        for (int i = 0; i < 36; i++) {
            triangleVertices[i] = vertices[vertexIndices[i]];
            triangleColors[i] = colors[vertexIndices[i]];
        }
        
        effect = [[GLKBaseEffect alloc] init];
    }
}

and the method that draws the cube in every frame:

- (void)draw
{
    GLKQuaternion glkq=GLKQuaternionMake(-_quat.y,_quat.x,_quat.z,_quat.w);
    GLKMatrix4 rotationMatrix=GLKMatrix4MakeWithQuaternion (glkq);
    
    GLKMatrix4 scaleMatrix     = GLKMatrix4MakeScale(0.5, 1. ,0.3);
    GLKMatrix4 translateMatrix = GLKMatrix4MakeTranslation(0., 0., 0.);
    
    GLKMatrix4 modelMatrix =GLKMatrix4Multiply(translateMatrix,GLKMatrix4Multiply(scaleMatrix,rotationMatrix));
    
    GLKMatrix4 viewMatrix = GLKMatrix4MakeLookAt(0, 0, 5, 0, 0, 0, 0, 1 , 0);
    effect.transform.modelviewMatrix = GLKMatrix4Multiply(viewMatrix, modelMatrix);
    
    effect.transform.projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0f), 3./4., 3, -5);
    
    [effect prepareToDraw];
    
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices);
    
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, triangleColors);
    
    glDrawArrays(GL_TRIANGLES, 0, 36);
    
    glDisableVertexAttribArray(GLKVertexAttribPosition);
    glDisableVertexAttribArray(GLKVertexAttribColor);
}

I cannot figure out what I am doing wrong here though I am under the impression that it is the call to

    effect.transform.projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0f), 3./4., 3, -5);

that creates a wrong perspective. Anyhow if you could point me out what might be going wrong I would be grateful.

i have this problem too. i believe its because the view port isnt square and it causes the normalized coordinates to distort to reach their new positions. its nothing you did wrong :slight_smile: just gotta find a fix for it…

Well, I thought that defining the aspect ratio in

effect.transform.projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0f), 3./4., 3, -5);

to 3/4 should set the view port accordingly… I cannot understand what is happening and unfortunately I do not have the time to dive into opengl right now. This code is a tweaked example I found online since what I want to do is(well… should be) fairly simple. I believe that there is something conceptually wrong with my code. Meaning that one of these calls that produce all this matrices that, multiplied, transform to the final object is not doing what I think it is doing… Anyhow if someone with more experience could point us towards somewhere it would be nice…

I don’t know GLKit, but for regular OpenGL on a PC: If you want to distort/scale your object by .5(x), 1(y), .3(z) in object coordinates, then you should switch the order of your rotate and scale matrices. The one farthest on the right happens in the undisturbed object coordinates, the next one happens in disturbed object coordinates. So when you rotate and then distort, the distortion will be different at the object for different rotations. Hopefully your screen aspect is taken care of by your viewport transform, that comes after projection.

Basic principle: matrices multiplying from the right (where your vertices are) translate or rotate or distort from the object’s perspective. Matrices on the left are from your eye’s perspective. Stuff in the middle has to be thought of from the perspective of a transformed eye, by matrices left of the perspective, or the perspective of a transformed object (by the matrices on the right).

Roaoul, thanks very much man! The problem was exactly what you mentioned. The cube was first rotated and then scaled (in every frame). So the call that works is

effect.transform.modelviewMatrix = GLKMatrix4Multiply(viewMatrix,GLKMatrix4Multiply(translateMatrix,GLKMatrix4Multiply(rotationMatrix,scaleMatrix)));

I feel actually a bit embarrassed not seeing this… Thanks again.

What you’ve pulled off is awesome. Don’t feel embarrassed. OpenGL does that to me all the time: see my post on “Lost Hello Triangle”. :stuck_out_tongue: Welcome to the club!