So I am building a system monitoring app for iPhone and iPad. Anytime I try to compile the application I am getting an error that says "Implicit Declaration of function 'glBindVertexArrayOES' is invalid in 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's 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's 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;
This is the next line of code which gives me an error
glBindVertexArrayOES(self.glVertexArrayLineLegend);
Then this is the rest of the code
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.
*/
{
This next line also throws up the same c99 error
glGenVertexArraysOES(1, &_glVertexArrayDataLine);
And the other code is as follows:
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)
{
And the final c99 error comes here in this next line:
glDeleteVertexArraysOES(1, &_glVertexArrayDataLine);
And this is the last piece of code after that:
}
if (self.glVertexArrayLineLegend)
{
glDeleteVertexArraysOES(1, &_glVertexArrayLineLegend);
}
GL_CHECK_ERROR();
}
@end
So as you can guess I have no clue how this issue is to be solved. Im hoping someone here can help? Many thanks in advance!
This is usually solved by importing the appropriate OpenGLES
header, i.e.:
#import <OpenGLES/ES2/glext.h>
or
#import <OpenGLES/ES1/glext.h>
Depending on which version of OpenGL you're using.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With