OpenGL ES EXC_BAD_ACCESS на glDrawArrays - PullRequest
9 голосов
/ 27 мая 2011

У меня проблема с рендерингом в OpenGL ES 1.1 для создаваемой игры для iPhone.

Короче, я рендерил 3 вещи:

  1. Фон (отлично работает)
  2. Количество сферических объектов (отлично работает)
  3. Простая окружность линии, которая меняет размер (здесь у меня проблема).

В основном, я получаю ошибку EXC_BAD_ACCESS, когда я вызываю drawArrays на круге. Я протестировал код в базовом шаблоне iPhone OpenGL, и он прекрасно работает, поэтому я не могу точно отследить, почему он здесь не работает. Может ли кто-нибудь указать мне правильный путь?

Вот код drawCircle, используемый для визуализации круга.

- (void) drawCircles
{
if (!m_circleEffects.empty())
{
    int segments = 24;
    for (int i = 0; i < m_circleEffects.size(); i++)
    {
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(m_circleEffects[i].position.x, m_circleEffects[i].position.y, 0);

        float radius;
        if(m_circleEffects[i].isPulseOutward)
            radius = cos(m_circleEffects[i].frameCounter * M_PI / 720);
        else
            radius = sin(m_circleEffects[i].frameCounter * M_PI / 720);

        GLfloat circlePoints[segments * 3];                    
        int count = 0;

        for (GLfloat i = 0; i < 360.0f; i += (360.0f / segments))
        {
            circlePoints[count++] = (cos(i * M_PI / 180) * radius);
            circlePoints[count++] = (sin(i * M_PI / 180) * radius);
            circlePoints[count++] = z + 1;
        }

        glEnableClientState(GL_VERTEX_ARRAY);  
        glVertexPointer(3, GL_FLOAT, 0, circlePoints);                       
        glDrawArrays(GL_LINE_LOOP, 0, segments);   
        glDisableClientState(GL_VERTEX_ARRAY);
    }      
    m_circleEffects.clear();
}
}

И следующий мой другой код рендеринга. Вызывается до вышеуказанного кода в цикле выполнения. Все в следующем, кажется, работает хорошо.

- (void)passInVisualsToUse:(vector<Visual>)visuals
{
frameCounter += 0.2;
if (frameCounter >= 360)
    frameCounter -= 360;

glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);

glDepthMask(GL_FALSE);

glBindTexture(GL_TEXTURE_2D, m_backgroundTexture);

glDrawTexfOES(0, 0, 0, 480, 320);
glDepthMask(GL_TRUE);

vector<Visual>::const_iterator visual = visuals.begin();
for (int visualIndex = 0;
     visual != visuals.end();
     ++visual, ++visualIndex)
{        

    if (visual->ObjectType == 1)
        glBindTexture(GL_TEXTURE_2D, m_oneTexture);
    else if (visual->ObjectType == 2)
        glBindTexture(GL_TEXTURE_2D, m_twoTexture);
    else if (visual->ObjectType == 3)
        glBindTexture(GL_TEXTURE_2D, m_threeTexture);
    else
        glBindTexture(GL_TEXTURE_2D, m_fourTexture);

    // Set the viewport transform.
    vec3 position = visual->Position;

    // Set the light position.
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(position.x, position.y, position.z);
    float rotationAngle = visual->RotationAngle;
    glRotatef(rotationAngle, 0, 1, 0);

    float scale = visual->Scale;   

    if (visual->ShouldThrob)
    {
        float scaleFactor = scale + sin(frameCounter) / 25;
        glScalef(scaleFactor, scaleFactor, scale);

        BOOL isPulseOutward;
        if (visual->isPulseOutward)
            isPulseOutward = YES;
        else
            isPulseOutward = NO;

        CircleEffect toAdd;
        toAdd.position = position;
        toAdd.frameCounter = frameCounter;
        toAdd.isPulseOutward = isPulseOutward;
        m_circleEffects.push_back(toAdd);
    }
    else
        glScalef(scale, scale, scale);

    // Set the projection transform.
    float h = (float)screenSize.size.height / (float)screenSize.size.width;

    mat4 projection = mat4::Ortho(xleft, xright, h * xleft, h * xright, znear, zfar);

    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(projection.Pointer());

    // Draw the surface.
    int stride = sizeof(vec3) + sizeof(vec3) + sizeof(vec2);
    const GLvoid* texCoordOffset = (const GLvoid*) (2 * sizeof(vec3));
    const Drawable& drawable = m_drawables[visualIndex];
    glBindBuffer(GL_ARRAY_BUFFER, drawable.VertexBuffer);
    glVertexPointer(3, GL_FLOAT, stride, 0);
    const GLvoid* normalOffset = (const GLvoid*) sizeof(vec3);
    glNormalPointer(GL_FLOAT, stride, normalOffset);
    glTexCoordPointer(2, GL_FLOAT, stride, texCoordOffset);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drawable.IndexBuffer);
    glDrawElements(GL_TRIANGLES, drawable.IndexCount, GL_UNSIGNED_SHORT, 0);
}


glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
}

Соответствующие буферы были настроены в другом месте, и, как уже упоминалось, второй код все прекрасно работает.

По сути, я получаю EXC_BAD_ACCESS для кода drawArrays в верхнем фрагменте кода. У кого-нибудь есть идеи почему?

Спасибо

Ответы [ 3 ]

10 голосов
/ 27 мая 2011

Я предполагаю, что у состояния GL есть еще ограниченный массив, который не должен быть.

Если это работает само по себе, тогда этот метод может подойти. Но предыдущий метод, возможно, не вернул состояние к тому, каким оно должно быть или что-то.

2 голосов
/ 15 августа 2011

Этот вид сбоя также происходит при попытке сделать низкоуровневые вызовы OpenGL из графических библиотек или движков, например, Cocos2D.Например, Cocos2D устанавливает несколько включенных состояний GL: GL_TEXTURE_COORD_ARRAY, GL_VERTEX_ARRAY, GL_COLOR_ARRAY.В этом примере, если ваш код не использует текстурирование, он потерпит крах, если вы не отключите GL_TEXTURE_COORD_ARRAY.

Спасибо v01d за подсказку!

0 голосов
/ 11 сентября 2016

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

glBindBuffer(GL_ARRAY_BUFFER, 0)
...