GLKView嵌套的子视图帧大小和边界大小不正确

时间:2013-04-27 22:28:06

标签: nested frame subview bounds glkview

以下是我根据Xcode 4.5中的OpenGL Game示例项目编写的“GLKView Subview”应用程序示例。它创建了一个GLKView子视图,其委托设置为文件所有者的GLKViewController,因此两个OpenGL ES 2视图都由一个控制器控制:

http://d-h.st/7R1

这是一个屏幕截图,我已经将子视图的背景设为红色以供对比:

http://d-h.st/om4

我很兴奋,我有一种简单的方法可以在一个GLKViewController和EAGLContext(用于共享纹理等)下添加多个GLKView,直到我意识到帧大小被打破:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    NSLog(@"My view frame: %@", NSStringFromCGRect(view.bounds));

    float aspect = fabsf(view.bounds.size.width / view.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);

    self.effect.transform.projectionMatrix = projectionMatrix;

    GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);
    baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);

    // Compute the model view matrix for the object rendered with GLKit
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f);
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);

    self.effect.transform.modelviewMatrix = modelViewMatrix;

    // Compute the model view matrix for the object rendered with ES2
    modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f);
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);

    _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);

    _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);

    if(view == self.view)
    {
        glClearColor(0.65f, 0.65f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glBindVertexArrayOES(_vertexArray);

        // Render the object with GLKit
        [self.effect prepareToDraw];

        glDrawArrays(GL_TRIANGLES, 0, 36);

        // Render the object again with ES2
        glUseProgram(_program);

        glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
        glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);

        glDrawArrays(GL_TRIANGLES, 0, 36);

        [self.subview display];
    }
    else
    {
        glClearColor(1.0f, 0.65f, 0.65f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glBindVertexArrayOES(_vertexArray);

        // Render the object with GLKit
        [self.effect prepareToDraw];

        glDrawArrays(GL_TRIANGLES, 0, 36);

        // Render the object again with ES2
        glUseProgram(_program);

        glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
        glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);

        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
}

使用iPhone 4在iOS模拟器中输出“Retina:

2013-04-27 15:50:56.149 GLKView Subview[48136:11903] My view frame: {{0, 0}, {568, 320}}
2013-04-27 15:50:56.152 GLKView Subview[48136:11903] My view frame: {{0, 0}, {248, 100}}

子视图的帧应该是{100,100},但由于某种原因它出现在{248,100}。我已经尝试了所有我能想到的东西,甚至将它嵌入到UIView中,认为如果主GLKView是它的父级,它的autoresize约束可能会被设置错误。正如你所看到的,UIView的大小是正确的,但是孩子GLKView的大小是不正确的。

作为开发人员,这似乎是首先要尝试的,但Apple通常还有其他想法。如果没有自动调整大小,GLKView对于适用于任何设备大小的自由形式布局都是无用的。

我设法让多个GLKViewControllers共享一个EAGLContext作为不同项目中的子控制器。但是我不明白为什么每次我们想要在屏幕上添加GLKView时都要承担创建GLKViewController的责任。我的猜测是当GLKViewController是GLKView的委托而不是它自己的视图时会感到困惑。

我还设法通过使用glViewport()手动使我的视图工作,并且在失去两天GLKView问题后,我可能会建议将这条路线传递给任何阅读此内容的人(同时获得跨平台优势)。

我希望有一个简单的解释/修复,即使它只是“你必须为每个GLKView制作一个GLKViewController”。提前感谢任何能够让它工作的人。如果没有,也许这个 bug 功能的一个例子可以帮助某人。

1 个答案:

答案 0 :(得分:0)

我找到了解决方法。只需使用示例项目,但关闭GLKView及其黑色父UIView的自动调整大小调整中最右边的红色条。

说明:由于纵横比不同于3.5"到4"在iPhone显示屏上,自动调整功能会尝试满足正确的边距约束,从而水平拉伸视图。通过告诉它保持左边距和宽度,但不是右边距,它可以在主视图中正确定位和调整视图。

仍然有一些不稳定的事情,因为如果你在黑色UIView中嵌入另一个白色UIView并设置其所有大小和边距限制,它会在其黑色父UIView中正确自动调整,而如果检查所有约束,GLKView将无法执行此操作。 GLKView似乎仍然针对根UIView进行自动调整,现在看来这是一个bug。它可能与将GLKView委托设置为File&#39的所有者有关。我已提交 Apple Bug ID#13777142 ,如果您想提交自己的错误报告,可以参考。

P.S。如果我将每个GLKView嵌入到自己的the other posts on Stack Overflow say to do GLKViewController中,我就不会看到这些问题。