Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Cube squeezed while rotating, using GLKit

Hybrid View

  1. #1
    Newbie Newbie
    Join Date
    Oct 2013
    Posts
    3

    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:
    Code :
    + (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:
    Code :
    - (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
    Code :
        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.

  2. #2
    Intern Contributor
    Join Date
    Jun 2013
    Posts
    69
    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 just gotta find a fix for it...

  3. #3
    Newbie Newbie
    Join Date
    Oct 2013
    Posts
    3
    Well, I thought that defining the aspect ratio in

    Code :
    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...

  4. #4
    Junior Member Newbie
    Join Date
    Aug 2013
    Posts
    19
    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).

  5. #5
    Newbie Newbie
    Join Date
    Oct 2013
    Posts
    3
    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
    Code :
    effect.transform.modelviewMatrix = GLKMatrix4Multiply(viewMatrix,GLKMatrix4Multiply(translateMatrix,GLKMatrix4Multiply(rotationMatrix,scaleMatrix)));
    I feel actually a bit embarrassed not seeing this... Thanks again.

  6. #6
    Junior Member Newbie
    Join Date
    Aug 2013
    Posts
    19
    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". :P Welcome to the club!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •