Search code examples
opengl-esprojection

GLKit projection


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. What I mean can be seen in the three images that follow where the cube is rotating counterclockwise for 90 degrees. Although at the beginning(first image) the ratio width/height of the cube is approx. 1/2 which I have set by

GLKMatrix4 scaleMatrix=GLKMatrix4MakeScale(0.5, 1., 0.3);

as it turns it gets "squeezed" to end up after a pi/2 turn,with the side that was the base (before the turn) to be double the height(third image). I believe my mistake is in the arguments I pass to GLKMatrix4MakePerspectivebut as I am not very comfortable with all the calls to openGL methods and what each does I put also some parts of my code that I believe could have some connection to that, after the images.

enter image description here enter image description here enter image description here

- (void)draw{
//just a quaternion that rotates the cube
GLKQuaternion glkq=GLKQuaternionMake(_quat.x,_quat.y,_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 am not sure if you maybe need some other parts of the code to tell me what I doing wrong here...


Solution

  • Matrix multiplication as a series of geometric transformations works from right to left and is not commutative. That is, given a rotation matrix R and scale matrix S, the product S x R means "rotate by R and then scale by S", which is a different result from "scale by S and then rotate by R" (as given by the product R x S).

    You're scaling after rotating: instead of squishing a cube into a rectangular prism and then rotating it, you're rotating a cube and then squishing the resulting image. Reverse your multiplication of scaleMatrix and rotationMatrix and you should see the result you expect.

    (Also, your translateMatrix specifies a translation of zero, so multiplying it into the model view matrix does nothing. If it was nonzero, though, in what order should you multiply it into your model view matrix?)