Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL view disappears while rotating

I am using OpenGL 2.0 to draw a rectangle. Initially the viewport is such that i am looking from above and i can see my rectangle as i expected. Then i start rotating this rectangle about the x-axis. When the angle of rotation equals -90deg (or +90 deg if rotating in the other direction), the rectangle disappears. What i expect to see if the bottom surface of the rectangle when i rotate past 90deg/-90deg but instead the view disappears. It does re-appear with the total rotation angle is -270deg (or +270 deg) when the upper surface is just about ready to be shown.

How do i ensure that i can see the rectangle all along (both upper and lower surface has to be visible while rotating)?

Here' the relevant piece of code:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch * touch = [touches anyObject];
    if ([touches count] == 1) {
        CGPoint currLoc = [touch locationInView:self];
        CGPoint lastLoc = [touch previousLocationInView:self];
        CGPoint diff = CGPointMake(lastLoc.x - currLoc.x, lastLoc.y - currLoc.y);

        rotX = -1 * GLKMathDegreesToRadians(diff.y / 2.0);
        rotY = -1 * GLKMathDegreesToRadians(diff.x / 2.0);

        totalRotationX += ((rotX * 180.0f)/3.141592f);

        NSLog(@"rotX: %f, rotY: %f, totalRotationX: %f", rotX, rotY, totalRotationX);

        //rotate around x axis
        GLKVector3 xAxis = GLKMatrix4MultiplyVector3(GLKMatrix4Invert(_rotMatrix, &isInvertible), GLKVector3Make(1, 0, 0));
        _rotMatrix = GLKMatrix4Rotate(_rotMatrix, rotX, xAxis.v[0], 0, 0);
    }
}


-(void)update{
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0, 0, -6.0f);
    modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, _rotMatrix);
    self.effect.transform.modelviewMatrix = modelViewMatrix;

    float aspect = fabsf(self.bounds.size.width / self.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0, 10.0f);
    self.effect.transform.projectionMatrix = projectionMatrix;
}

- (void)setupGL {

    NSLog(@"setupGL");
    isInvertible = YES;
    totalRotationX = 0;
    [EAGLContext setCurrentContext:self.context];
    glEnable(GL_CULL_FACE);

    self.effect = [[GLKBaseEffect alloc] init];

    // New lines
    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    // Old stuff
    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

    glViewport(0, 0, self.frame.size.width, self.frame.size.height);

    // New lines (were previously in draw)
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Position));
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Color));

    _rotMatrix = GLKMatrix4Identity;

    // New line
    glBindVertexArrayOES(0);

    initialized = 1;
}

I am a newbie to OpenGL and i am using the GLKit along with OpenGL 2.0

Thanks.

like image 939
VJ Vélan Solutions Avatar asked Oct 15 '25 17:10

VJ Vélan Solutions


1 Answers

There are many causes for things not rendering in OpenGL. In this case, it was back face culling (see comments on the question). Back face culling is useful because it can ignore triangles facing away from the camera and save some rasterization/fragment processing time. Since many meshes/objects are watertight and you'd never want to see the inside anyway it's uncommon to actually want two-sided shading. This functionality starts with defining a front/back of a triangle. This is done with the order the vertices are given in (sometimes called winding direction). glFrontFace chooses the direction clockwise/counter-clockwise that defines forwards, glCullFace chooses to cull either front or back (I guess some could argue not much point in having both) and finally to enable/disable:

glEnable(GL_CULL_FACE); //discards triangles facing away from the camera
glDisable(GL_CULL_FACE); //default, two-sided rendering

Some other things I check for geometry not being visible include...

  • Is the geometry colour the same as the background. Choosing a non-black/white background can be handy here.
  • Is the geometry actually drawing within the viewing volume. Throw in a simple object (immediate mode helps) and maybe use identity projection/modelview to rule them out.
  • Is the viewing volume correct. Near/far planes too far apart (causing z-fighting) or 0.0f near planes are common issues. Also when switching to a projection matrix, drawing anything on the Z=0 plane won't be visible any more.
  • Is blending enabled and everything's transparent.
  • Is the depth buffer not being cleared and causing subsequent frames to be discarded.
  • In fixed pipeline rendering, are glTranslate/glRotate transforms being carried over from the previous frame causing objects to shoot off into the distance. Always keep a glLoadIdentity at the top of the display function.
  • Is the rendering loop structured correctly - clear/draw/swapbuffers
  • Of course there's heaps more - geometry shaders not outputting anything, vertex shaders transforming vertices to the same position (so they're all degenerate), fragment shaders calling discard when they shouldn't, VBO binding/indexing issues etc. Checking GL errors is a must but never catches all mistakes.
like image 146
jozxyqk Avatar answered Oct 18 '25 07:10

jozxyqk