Неправильный размер кадра вложенного подвида GLKView и размер границ

Вот пример приложения «GLKView Subview», которое я написал на основе примера проекта OpenGL Game в Xcode 4.5. Он создает подпредставление GLKView с его делегатом, установленным в GLKViewController владельца файла, так что оба представления OpenGL ES 2 управляются одним контроллером:

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

Вот скриншот, я подкрасил фон подвида красным для контраста:

http://d-h.st/om4

Я был взволнован тем, что у меня был простой способ добавить несколько GLKView под один GLKViewController и EAGLContext (для обмена текстурами и т. д.), пока я не понял, что размер кадра разбит:

- (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);
    }
}

Вывод в iOS Simulator с iPhone 4" 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 был его родителем. Как вы можете видеть, размер UIView правильный, но размер дочернего GLKView не соответствует размеру.

Как разработчик, это казалось первым, что нужно попробовать, но у Apple обычно другие идеи. Без автоматического изменения размера GLKView бесполезен для макетов произвольной формы, которые работают с любым размером устройства.

Мне удалось заставить несколько GLKViewController, совместно использующих один EAGLContext, работать как дочерние контроллеры в другом проекте. Но я не понимаю, почему мы должны нести груз создания GLKViewController каждый раз, когда мы хотим добавить GLKView на экран. Я предполагаю, что GLKViewController путается, когда он является делегатом для GLKView, который не является его собственным представлением.

Мне также удалось заставить мои представления работать вручную, просто используя glViewport(), и после потери двух дней из-за проблем с GLKView я, вероятно, порекомендовал бы пойти по этому пути всем, кто читает это (также получая преимущества кроссплатформенности).

Я надеюсь, что есть простое объяснение/исправление, даже если это просто «вам нужно создать GLKViewController для каждого GLKView». Заранее спасибо всем, кому удастся заставить его работать. Если нет, возможно, кому-то поможет пример этой функции bug.


person Zack Morris    schedule 27.04.2013    source источник


Ответы (1)


Я нашел обходной путь. Просто используйте пример проекта, но отключите крайнюю правую красную полосу в настройке Autosizing как для GLKView, так и для его черного родительского UIView.

Объяснение: поскольку соотношение сторон экрана iPhone с диагональю от 3,5 до 4 дюймов отличается, автомасштабирование пытается соответствовать ограничению правого поля, которое растягивает представления по горизонтали. Указав ему поддерживать левое поле и ширину, но НЕ правое поле, он правильно позиционирует и размер представлений в основном представлении.

Тем не менее, происходит что-то странное, потому что, если вы встроите другой белый UIView внутрь черного UIView и установите все его ограничения по размеру и полям, он автоматически автоматически подстроится в своем черном родительском UIView, в то время как GLKView не сможет сделайте это, если вы проверите все его ограничения. Похоже, что GLKView по-прежнему автоматически подстраивается под корневой UIView, что на данный момент кажется ошибкой. Это может быть как-то связано с установкой делегата GLKView на владельца файла. Я отправил Apple Bug ID# 13777142, на который вы можете ссылаться, если хотите отправить свой собственный отчет об ошибке.

P.S. Я не вижу этих проблем, если встраиваю каждый GLKView в свой собственный GLKViewController, например другие сообщения при переполнении стека говорят делать.

person Zack Morris    schedule 30.04.2013