I have an iPhone app in the making with GLKit. I load vertices in from a .obj file from Blender, and then I attempt to draw the vertices. It's the first time I've tried to do so using glDrawElements
. I chose this because then I only need as many vertices as there are vertices in my object, and I can just render one triangle strip with the indices of those vertices.
Here is a simplified version of what I'm trying to do, which just highlights the fact that I'm trying to draw outside of the ViewController, the entire source code for this simplified version is here
#import "Character.h"
@interface Character()
{
GLuint _vertexBuffer;
GLuint _indexBuffer;
GLuint _vertexArray;
}
@property(nonatomic, weak) GLKBaseEffect *effect;
@end
typedef struct {
float Position[3];
float Color[4];
} Vertex;
const Vertex Vertices[] = {
{{1, -1, 0}, {1, 0, 0, 1}},
{{1, 1, 0}, {0, 1, 0, 1}},
{{-1, 1, 0}, {0, 0, 1, 1}},
{{-1, -1, 0}, {0, 0, 0, 1}}
};
const GLushort Indices[] = {
0, 1, 2,
2, 3, 0
};
@implementation Character
- (id)initWithEffect:(GLKBaseEffect *)effect
{
if (self = [super init])
{
self.effect = effect;
[self setupGL];
}
return self;
}
- (void)setupGL
{
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Position));
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Color));
glBindVertexArrayOES(0);
}
- (void)teardownGL
{
glDeleteBuffers(1, &_vertexBuffer);
glDeleteBuffers(1, &_indexBuffer);
}
- (void)render
{
self.effect.transform.modelviewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, self.position.x, self.position.y, self.position.z);
self.effect.transform.modelviewMatrix = GLKMatrix4Rotate(self.effect.transform.modelviewMatrix, self.rotation, 0.0f, 0.0f, 1.0f);
[self.effect prepareToDraw];
glBindVertexArrayOES(_vertexArray);
glDrawElements(GL_TRIANGLES, sizeof(Indices) / sizeof(Indices[0]), GL_UNSIGNED_SHORT, (const GLvoid*)0);
}
@end
Here is how the character is initialized in viewDidLoad
of the ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
GLKView *view = (GLKView *)self.view;
view.context = self.context;
[self setupGL];
character = [[Character alloc] initWithEffect:self.effect];
character.position = GLKVector3Make(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2, 0.0f);
}
And here is how the calls to the character's render method are made:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[character render];
}