Неявное объявление функции "glBindVertexArrayOES" недействительно в c99

Итак, я создаю приложение для мониторинга системы для iPhone и iPad. Каждый раз, когда я пытаюсь скомпилировать приложение, я получаю сообщение об ошибке "Неявное объявление функции" glBindVertexArrayOES недействительно в c99 "

#import "AMUtils.h"
#import "AppDelegate.h"
#import "GLCommon.h"
#import "GLLineGraph.h"
#import "GLDataLine.h"

@interface GLDataLine()
@property (nonatomic, weak) GLLineGraph     *graph;

@property (nonatomic, assign) GLuint        glVertexArrayDataLine;
@property (nonatomic, assign) GLuint        glBufferDataLine;
@property (nonatomic, assign) VertexData_t  *dataLineData;
@property (nonatomic, assign) NSUInteger    dataLineDataSize;
@property (nonatomic, assign) GLuint        dataLineDataValidSize;  /* Valid buffer index count */
@property (nonatomic, assign) GLuint        dataLineDataCurrIdx;    /* Current index to be written new values to */
@property (nonatomic, assign) GLfloat       dataLineDataNextX;      /* Each added data element gets it own unique X position */
/* dataLineData is a circular array and so in order to utilize GL_LINE_STRIP without creating an
 * impression of GL_LINE_LOOP we declare 2 matrixes.
 * The first translates 0 - dataLineDataCurrIdx verticies.
 * The second translates dataLineDataCurrIdx+1 - dataLineDataValidSize-1 verticies. */
@property (nonatomic, assign) GLKVector3    dataLinePosition1;
@property (nonatomic, assign) GLKVector3    dataLinePosition2;

@property (nonatomic, assign) GLuint        glVertexArrayLineLegend;
@property (nonatomic, assign) GLuint        glBufferLineLegend;
@property (nonatomic, strong) GLKTextureInfo *lineLegendTextTexture;
@property (nonatomic, strong) GLKTextureInfo *lineLegendIconTexture;

@property (nonatomic, assign) GLfloat       zoom;

- (void)setupVBO;
- (void)renderDataLine;
- (void)tearDownGL;
@end

@implementation GLDataLine
@synthesize color;

@synthesize graph;

@synthesize glVertexArrayDataLine=_glVertexArrayDataLine;
@synthesize glBufferDataLine=_glBufferDataLine;
@synthesize dataLineData=_dataLineData;
@synthesize dataLineDataSize=_dataLineDataSize;
@synthesize dataLineDataValidSize=_dataLineDataValidSize;
@synthesize dataLineDataCurrIdx=_dataLineDataCurrIdx;
@synthesize dataLineDataNextX=_dataLineDataNextX;
@synthesize dataLinePosition1=_dataLinePosition1;
@synthesize dataLinePosition2=_dataLinePosition2;

@synthesize glVertexArrayLineLegend=_glVertexArrayLineLegend;
@synthesize glBufferLineLegend=_glBufferLineLegend;
@synthesize lineLegendTextTexture;
@synthesize lineLegendIconTexture;

@synthesize zoom;

static const GLfloat kDataLineShiftSize     = 0.25;

static const VertexData_t lineLegendData[] = {
    {{ 0.0, 0.0, kModelZ }, { 0.0, 0.0 }},
    {{ 1.0, 0.0, kModelZ }, { 1.0, 0.0 }},
    {{ 0.0, 1.0, kModelZ }, { 0.0, 1.0 }},
    {{ 1.0, 1.0, kModelZ }, { 1.0, 1.0 }}
};

#pragma mark - public

- (id)initWithColor:(UIColor*)aColor forGraph:(GLLineGraph*)aGraph
{
    if (self = [super init])
    {
        self.color = aColor;
        self.graph = aGraph;
        self.dataLineDataValidSize = 0;
        self.dataLineDataCurrIdx = 0;

        self.dataLineDataSize = (self.graph.graphRight - self.graph.graphLeft) / kDataLineShiftSize;
        _dataLineData = malloc(self.dataLineDataSize * sizeof(VertexData_t));

        self.zoom = 1.0;

        [self resetLineData];

        [self setupVBO];
    }
    return self;
}

- (void)dealloc
{
    [self tearDownGL];

    free(_dataLineData);
}

- (void)addLineDataValue:(double)value
{
    GLfloat vX = self.dataLineDataNextX++;
    GLfloat vY = [AMUtils percentageValueFromMax:self.graph.graphTop-self.graph.graphBottom min:0.0 percent:value];
    BOOL bufferSizeIncreased = NO;

    if (self.dataLineDataValidSize == 0)
    {
        self.dataLineData[0].positionCoords.x = vX;
        self.dataLineData[0].positionCoords.y = vY;
        self.dataLineData[0].positionCoords.z = kModelZ;

        self.dataLineDataCurrIdx++;
        self.dataLineDataValidSize++;
        bufferSizeIncreased = YES;
    }
    else
    {
        self.dataLineData[self.dataLineDataCurrIdx].positionCoords.x = vX;
        self.dataLineData[self.dataLineDataCurrIdx].positionCoords.y = vY;
        self.dataLineData[self.dataLineDataCurrIdx].positionCoords.z = kModelZ;

        if (self.dataLineDataCurrIdx == 0)
        {
            // Previous data add wrapped the lines.
            // It best to set last value Y to current Y or otherwise the line might have a gap.
            // It is quite an ugly solution because the previous data will be lost, but I can't
            // figure anything better now.
            self.dataLineData[self.dataLineDataSize-1].positionCoords.y = vY;
        }

        self.dataLineDataCurrIdx++;

        if (self.dataLineDataValidSize < self.dataLineDataSize)
        {
            self.dataLineDataValidSize++;
            bufferSizeIncreased = YES;
        }
    }

    // Check if we need to wrap the circular data line buffer.
    if (self.dataLineDataCurrIdx >= self.dataLineDataSize)
    {
        // First we move the first data position vector to the second in order to keep the old values moving.
        // It is assumed that the old values which dataLinePosition2 was moving before this assignment
        // are already offscreen.
        self.dataLinePosition2 = self.dataLinePosition1;

        // Then re-init the first data position vector to starting position.
        GLfloat xTranslate = self.graph.graphRight;
        self.dataLinePosition1 = GLKVector3Make(xTranslate, self.graph.graphBottom, kModelZ);

        self.dataLineDataNextX = 0;
        self.dataLineDataCurrIdx = 0;
    }
    else
    {
        // Shift data line translation matrixes.
        GLKVector3 shift = GLKVector3Make(-kDataLineShiftSize, 0.0, 0.0);
        self.dataLinePosition1 = GLKVector3Add(self.dataLinePosition1, shift);
        self.dataLinePosition2 = GLKVector3Add(self.dataLinePosition2, shift);
    }

    glBindBuffer(GL_ARRAY_BUFFER, self.glBufferDataLine);

    if (bufferSizeIncreased)
    {
        glBufferData(GL_ARRAY_BUFFER,
                     self.dataLineDataValidSize * sizeof(VertexData_t),
                     _dataLineData, GL_DYNAMIC_DRAW);
    }
    else
    {
        glBufferSubData(GL_ARRAY_BUFFER, 0,
                        self.dataLineDataValidSize * sizeof(VertexData_t),
                        _dataLineData);
    }

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

- (void)addLineDataArray:(NSArray*)dataArray
{

}

- (void)resetLineData
{
    GLfloat xTranslate = self.graph.graphRight;
    self.dataLinePosition1 = GLKVector3Make(xTranslate, self.graph.graphBottom, kModelZ);
    self.dataLinePosition2 = GLKVector3Make(xTranslate, self.graph.graphBottom, kModelZ);

    self.dataLineDataValidSize = 0;
    self.dataLineDataCurrIdx = 0;
    self.dataLineDataNextX = 0;
}

- (void)setLineDataLegendText:(NSString*)text
{
    // Apparently GLKTextureInfo leaks memory if you don't delete textures explicitly.
    if (self.lineLegendTextTexture)
    {
        GLuint texture = self.lineLegendTextTexture.name;
        glDeleteTextures(1, &texture);
    }

    UIImage *tex = [GLCommon imageWithText:text font:[UIFont fontWithName:@"Verdana" size:22.0] color:self.color];
    self.lineLegendTextTexture = [GLKTextureLoader textureWithCGImage:tex.CGImage options:nil error:nil];
}

- (void)setDataLineLegendIcon:(UIImage*)image
{
    NSError *error = nil;
    self.lineLegendIconTexture = [GLKTextureLoader textureWithCGImage:image.CGImage options:nil error:&error];
    if (lineLegendIconTexture == nil)
    {
        AMLogError(@"GLKTextureLoader failed to load texture: %@", [error localizedDescription]);
    }
}

- (void)render
{
    if (self.dataLineDataValidSize == 0)
    {
        // No verticies to draw.
        return;
    }

    [self renderDataLine];
}

- (void)renderLegend:(NSUInteger)lineIndex
{
    /*
     * Icon
     */
    if (self.lineLegendIconTexture)
    {
        GLfloat x = self.graph.graphRight - 6.5 - (lineIndex * 9.0);
        GLfloat y = self.graph.graphBottom - 1.2;
        GLfloat xScale = 1.0 * (self.lineLegendIconTexture.width / self.lineLegendIconTexture.height);
        GLfloat yScale = 1.0;

Это следующая строка кода, которая дает мне ошибку

glBindVertexArrayOES(self.glVertexArrayLineLegend);

Тогда это остальная часть кода

        GLKVector3 position = GLKVector3Make(x, y, 0.0);
        GLKVector3 rotation = GLKVector3Make(0.0, 0.0, 0.0);
        GLKMatrix4 scale = GLKMatrix4MakeScale(xScale, yScale, 1.0);
        GLKMatrix4 modelMatrix = [GLCommon modelMatrixWithPosition:position rotation:rotation scale:scale];

        self.graph.effect.transform.modelviewMatrix = modelMatrix;
        self.graph.effect.texture2d0.enabled = GL_TRUE;
        self.graph.effect.texture2d0.target = GLKTextureTarget2D;
        self.graph.effect.texture2d0.name = self.lineLegendIconTexture.name;
        self.graph.effect.texture2d0.envMode = GLKTextureEnvModeReplace;
        [self.graph.effect prepareToDraw];

        glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(lineLegendData) / sizeof(VertexData_t));
    }

    /*
     * Text
     */
    if (self.lineLegendTextTexture)
    {
        GLfloat x = self.graph.graphRight - 5.0 - (lineIndex * 9.0);
        GLfloat y = self.graph.graphBottom - 1.0;
        GLfloat xScale = self.lineLegendTextTexture.width * kFontScaleMultiplierW;
        GLfloat yScale = self.lineLegendTextTexture.height * kFontScaleMultiplierH;

        glBindVertexArrayOES(self.glVertexArrayLineLegend);

        GLKVector3 position = GLKVector3Make(x, y, 0.0);
        GLKVector3 rotation = GLKVector3Make(0.0, 0.0, 0.0);
        GLKMatrix4 scale = GLKMatrix4MakeScale(xScale, yScale, 1.0);
        GLKMatrix4 modelMatrix = [GLCommon modelMatrixWithPosition:position rotation:rotation scale:scale];

        self.graph.effect.transform.modelviewMatrix = modelMatrix;
        self.graph.effect.texture2d0.enabled = GL_TRUE;
        self.graph.effect.texture2d0.target = GLKTextureTarget2D;
        self.graph.effect.texture2d0.name = self.lineLegendTextTexture.name;
        self.graph.effect.texture2d0.envMode = GLKTextureEnvModeReplace;
        [self.graph.effect prepareToDraw];

        glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(lineLegendData) / sizeof(VertexData_t));
    }
}

- (NSUInteger)maxDataLineElements
{
    return self.dataLineDataSize;
}

- (void)setDataLineZoom:(GLfloat)aZoom
{
    self.zoom = aZoom;
}

#pragma mark - private

- (void)setupVBO
{
    /*
     * Data line.
     */
    {

Эта следующая строка также вызывает ту же ошибку c99

        glGenVertexArraysOES(1, &_glVertexArrayDataLine);

И другой код выглядит следующим образом:

        glBindVertexArrayOES(self.glVertexArrayDataLine);

        glGenBuffers(1, &_glBufferDataLine);
        glBindBuffer(GL_ARRAY_BUFFER, self.glBufferDataLine);
        glBufferData(GL_ARRAY_BUFFER, self.dataLineDataValidSize * sizeof(VertexData_t), _dataLineData, GL_DYNAMIC_DRAW);

        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData_t),
                              NULL + offsetof(VertexData_t, positionCoords));
        glEnableVertexAttribArray(GLKVertexAttribPosition);

        GL_CHECK_ERROR();
    }

    /*
     * Line legend.
     */
    {
        glGenVertexArraysOES(1, &_glVertexArrayLineLegend);
        glBindVertexArrayOES(self.glVertexArrayLineLegend);

        glGenBuffers(1, &_glBufferLineLegend);
        glBindBuffer(GL_ARRAY_BUFFER, self.glBufferLineLegend);
        glBufferData(GL_ARRAY_BUFFER, sizeof(lineLegendData), lineLegendData, GL_STATIC_DRAW);

        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData_t),
                              NULL + offsetof(VertexData_t, positionCoords));
        glEnableVertexAttribArray(GLKVertexAttribPosition);

        glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData_t),
                              NULL + offsetof(VertexData_t, textureCoords));
        glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    }
}

- (void)renderDataLine
{
    GLfloat yScale = 1.0 / self.zoom;

    /*
     * Render the first batch starting from 0 to self.dataLineDataCurrIdx.
     */
    {
        GLfloat yScale = 1.0 / self.zoom;

        glBindVertexArrayOES(self.glVertexArrayDataLine);

        GLKVector3 position = self.dataLinePosition1;
        GLKVector3 rotation = GLKVector3Make(0.0, 0.0, 0.0);
        GLKMatrix4 scale = GLKMatrix4MakeScale(kDataLineShiftSize, yScale, 1.0);
        GLKMatrix4 modelMatrix = [GLCommon modelMatrixWithPosition:position rotation:rotation scale:scale];

        self.graph.effect.transform.modelviewMatrix = modelMatrix;
        self.graph.effect.useConstantColor = YES;
        self.graph.effect.texture2d0.enabled = NO;

        const CGFloat *components = CGColorGetComponents(self.color.CGColor);
        self.graph.effect.constantColor = GLKVector4Make(components[0], components[1], components[2], CGColorGetAlpha(self.color.CGColor));
        [self.graph.effect prepareToDraw];

        DeviceSpecificUI *ui = [AppDelegate sharedDelegate].deviceSpecificUI;
        glLineWidth(ui.GLdataLineWidth);
        glDrawArrays(GL_LINE_STRIP, 0, self.dataLineDataCurrIdx);

        GL_CHECK_ERROR();
    }

    /*
     * Render the second batch starting from self.dataLineDataCurrIdx+1 to the end.
     */
    if (self.dataLineDataValidSize > self.dataLineDataCurrIdx)
    {
        glBindVertexArrayOES(self.glVertexArrayDataLine);

        GLKVector3 position = self.dataLinePosition2;
        GLKVector3 rotation = GLKVector3Make(0.0, 0.0, 0.0);
        GLKMatrix4 scale = GLKMatrix4MakeScale(kDataLineShiftSize, yScale, 1.0);
        GLKMatrix4 modelMatrix = [GLCommon modelMatrixWithPosition:position rotation:rotation scale:scale];

        self.graph.effect.transform.modelviewMatrix = modelMatrix;
        self.graph.effect.useConstantColor = YES;
        const CGFloat *components = CGColorGetComponents(self.color.CGColor);
        self.graph.effect.constantColor = GLKVector4Make(components[0], components[1], components[2], CGColorGetAlpha(self.color.CGColor));
        self.graph.effect.texture2d0.enabled = NO;
        [self.graph.effect prepareToDraw];

        DeviceSpecificUI *ui = [AppDelegate sharedDelegate].deviceSpecificUI;
        glLineWidth(ui.GLdataLineWidth);
        glDrawArrays(GL_LINE_STRIP, self.dataLineDataCurrIdx, self.dataLineDataValidSize - self.dataLineDataCurrIdx);

        GL_CHECK_ERROR();
    }
}

- (void)tearDownGL
{
    // Apparently GLKTextureInfo leaks memory if you don't delete textures explicitly.
    if (self.lineLegendIconTexture)
    {
        GLuint texture = self.lineLegendIconTexture.name;
        glDeleteTextures(1, &texture);
    }
    if (self.lineLegendTextTexture)
    {
        GLuint texture = self.lineLegendTextTexture.name;
        glDeleteTextures(1, &texture);
    }

    if (self.glBufferDataLine)
    {
        glDeleteBuffers(1, &_glBufferDataLine);
    }
    if (self.glBufferLineLegend)
    {
        glDeleteBuffers(1, &_glBufferLineLegend);
    }

    if (self.glVertexArrayDataLine)
    {

И последняя ошибка c99 появляется здесь в следующей строке:

        glDeleteVertexArraysOES(1, &_glVertexArrayDataLine);

И это последний фрагмент кода после этого:

    }
    if (self.glVertexArrayLineLegend)
    {
        glDeleteVertexArraysOES(1, &_glVertexArrayLineLegend);
    }

    GL_CHECK_ERROR();
}

@end

Итак, как вы можете догадаться, я не знаю, как решить эту проблему. Я надеюсь, что кто-то здесь может помочь? Большое спасибо заранее!

Ответ 1

Это обычно решается путем импорта соответствующего заголовка OpenGLES, т.е.:

#import <OpenGLES/ES2/glext.h>

или

#import <OpenGLES/ES1/glext.h>

В зависимости от того, какую версию OpenGL вы используете.

Ответ 2

Я столкнулся с той же проблемой.

Самый простой способ решить эту проблему - добавить #import < OpenGLES/ES2/glext.h > строка в файле .pch.