Search code examples
objective-ciosxcodeopengl-es-2.0texture-mapping

Why does my object not render if the Vertices are generated manually (malloc'd then initialized) but will render if statically assigned?


Ultimately I am trying to use a single image to texture a number of objects (hexagons) by supplying different texture co-ordinates to each object.
Using OpenGL ES 2.0 and GLKit I came up with a method of doing so only to discover that for some reason the objects won't render if I malloc and initialize the Vertex arrays manually. I especially don't understand why this is because the statically assigned version of the vertex arrays work just fine.

Up front here is the struct I am using:

typedef struct {
GLKVector3 position;
GLKVector4 color;
GLKVector2 texCoords;
}Vertex;

So if I do this in a hexagon's implementation, I can see the various hexagons with the texture applied:

Vertex _Vertices[] = {
{{ 0,    0,     0}, {1, 1, 1, 0}, {0.50, 0.50}},//Z
{{ 1,    0,     0}, {1, 1, 1, 0}, {1.00, 0.50}},//A
{{ 0.5, -0.866, 0}, {1, 1, 1, 0}, {0.75, 0.00}},//B
{{-0.5, -0.866, 0}, {1, 1, 1, 0}, {0.25, 0.00}},//C
{{-1,    0,     0}, {1, 1, 1, 0}, {0,    0.50}},//D
{{-0.5,  0.866, 0}, {1, 1, 1, 0}, {0.25, 1.00}},//E
{{ 0.5,  0.866, 0}, {1, 1, 1, 0}, {0.75, 1.00}} //F
};

However if I instead comment out the above declaration and add an instance variable of the same name (Vertex *Vertices instead of Vertex Vertices[] since I can't malloc to an array directly) then do the following, nothing renders:

-(void)setVertices{
_Vertices = malloc(sizeof(Vertex) * 7);

//Z
_Vertices[0].position.x = 0;
_Vertices[0].position.y = 0;
_Vertices[0].position.z = 0;
_Vertices[0].color.r = 1;
_Vertices[0].color.g = 1;
_Vertices[0].color.b = 1;
_Vertices[0].color.a = 0;
_Vertices[0].texCoords.x = 0.5;
_Vertices[0].texCoords.y = 0.5;

//A
_Vertices[1].position.x = 1;
_Vertices[1].position.y = 0;
_Vertices[1].position.z = 0;
_Vertices[1].color.r = 1;
_Vertices[1].color.g = 1;
_Vertices[1].color.b = 1;
_Vertices[1].color.a = 0;
_Vertices[1].texCoords.x = 1;
_Vertices[1].texCoords.y = 0.5;


//B
_Vertices[2].position.x = 0.5;
_Vertices[2].position.y = -0.866;
_Vertices[2].position.z = 0;
_Vertices[2].color.r = 1;
_Vertices[2].color.g = 1;
_Vertices[2].color.b = 1;
_Vertices[2].color.a = 0;
_Vertices[2].texCoords.x = 0.75;
_Vertices[2].texCoords.y = 0.00;


//C
_Vertices[3].position.x = -0.5;
_Vertices[3].position.y = -0.866;
_Vertices[3].position.z = 0;
_Vertices[3].color.r = 1;
_Vertices[3].color.g = 1;
_Vertices[3].color.b = 1;
_Vertices[3].color.a = 0;
_Vertices[3].texCoords.x = 0.25;
_Vertices[3].texCoords.y = 0;


//D
_Vertices[4].position.x = -1;
_Vertices[4].position.y = 0;
_Vertices[4].position.z = 0;
_Vertices[4].color.r = 1;
_Vertices[4].color.g = 1;
_Vertices[4].color.b = 1;
_Vertices[4].color.a = 0;
_Vertices[4].texCoords.x = 0;
_Vertices[4].texCoords.y = 0.5;


//E
_Vertices[5].position.x = -0.5;
_Vertices[5].position.y = 0.866;
_Vertices[5].position.z = 0;
_Vertices[5].color.r = 1;
_Vertices[5].color.g = 1;
_Vertices[5].color.b = 1;
_Vertices[5].color.a = 0;
_Vertices[5].texCoords.x = 0.25;
_Vertices[5].texCoords.y = 1;


//F
_Vertices[6].position.x = 0.5;
_Vertices[6].position.y = 0.866;
_Vertices[6].position.z = 0;
_Vertices[6].color.r = 1;
_Vertices[6].color.g = 1;
_Vertices[6].color.b = 1;
_Vertices[6].color.a = 0;
_Vertices[6].texCoords.x = 0.75;
_Vertices[6].texCoords.y = 1;
}

Here is my setup function:

-(void)setupGL{
self.effect = [[GLKBaseEffect alloc] init];

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

And here is my draw function:

-(void)draw{
glPushGroupMarkerEXT(0,"drawHex");
_effect.texture2d0.envMode = GLKTextureEnvModeReplace;
_effect.texture2d0.target = GLKTextureTarget2D;
_effect.texture2d0.name = _texture.name;
[self.effect prepareToDraw];
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);

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

glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, texCoords));

//draw
glDrawElements(GL_TRIANGLES, sizeof(_Indices)/sizeof(_Indices[0]),GL_UNSIGNED_BYTE, 0);
glPopGroupMarkerEXT();
}

If it matters the texture is created once outside the object and then a pointer to it is passed in. Creating the texture like this:

-(void)setTextureImage:(UIImage *)image {
NSError *error;
_hexTexture = [GLKTextureLoader textureWithCGImage:image.CGImage options:nil error:&error];
if (error) {
    NSLog(@"Error loading texture from image: %@",error);
}}

I am new to all of this and it is getting quite frustrating trying to figure out what is going on here.

In my vast searching about I saw something about 'capture opengl es frame' but it doesn't seem to be enabled for the iphone simulator in Xcode so I can't dig into it :(

I would really like to know why this is happening.

I can provide more code or explanations if it will help.

Any thoughts?


Solution

  • About glBufferData's param, sizeof(_Vertices) is not same between static and dynamic. If you wanna use dynamic, you must use sizeof(Vertex)*7 instead of sizeof(_Vertices).