Rendering Textures in OpenGL ES 2.0 with VBO/IBO (IPhone) - iphone

I'm trying to render a simple quad with a texture using a vertex buffer object and an index buffer object. I haven't seen any solutions for how to do this with an IBO using glDrawElements. In any case, all that appears to happen is that the quad is textured using only the upper left hand pixel of the texture image.
This is how initialize an entity that will be rendered:
void Entity::init(){
// create triangle verticies
numVerticies = 20;
verticies = new GLfloat[numVerticies];
// 3 verts, 2 tex coords
verticies[0] = -1.0f; verticies[1] = -1.0f; verticies[2] = 0.0f; verticies[3] = 0.0f; verticies[4] = 0.0f;
verticies[5] = 1.0f; verticies[6] = 1.0f; verticies[7] = 0.0f; verticies[8] = 1.0f; verticies[9] = 1.0f;
verticies[10] = -1.0f; verticies[11] = 1.0f; verticies[12] = 0.0f; verticies[13] = 0.0f; verticies[14] = 1.0f;
verticies[15] = 1.0f; verticies[16] = -1.0f; verticies[17] = 0.0f; verticies[18] = 1.0f; verticies[19] = 0.0f;
// create face indicies
numIndicies = 6;
indicies = new GLushort[numIndicies];
indicies[0] = 0; indicies[1] = 1; indicies[2] = 2;
indicies[3] = 0; indicies[4] = 3; indicies[5] = 1;
// generate buffers for geometry
glGenBuffers(2, geometryBuffer);
// buffer the data to the vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, geometryBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticies) * numVerticies, verticies, GL_STATIC_DRAW);
// buffer the data to the index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryBuffer[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies) * numIndicies, indicies, GL_STATIC_DRAW);
rotation = 0.0f;
// load a texure object
std::string path = [[[NSBundle mainBundle] bundlePath] UTF8String];
path += "/test.png";
NSString *fileName = [NSString stringWithUTF8String:path.c_str()];
NSError *error;
GLKTextureInfo *texture = [GLKTextureLoader textureWithContentsOfFile:fileName options:nil error:&error];
if(error || texture == nil){
NSLog(#"Error loading texture %#\n", error);
}
// get the texture id
tex = [texture name];
}
And this is how I render the object ( I should mention that I call glUseProgram before calling this method):
void Entity::render(GLint uniformPos, GLint uniformTex, GLKMatrix4 projection){
GLKMatrix4 modelViewProjection = GLKMatrix4Multiply(projection, modelView);
// bind and enable enable verticies
glBindBuffer(GL_ARRAY_BUFFER, geometryBuffer[0]);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(0));
// enable tex coords
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(12));
// bind the index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometryBuffer[1]);
// bind the texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
// render with uniforms
glUniform1i(uniformTex, 0);
glUniformMatrix4fv(uniformPos, 1, 0, modelViewProjection.m);
glDrawElements(GL_TRIANGLES, numIndicies, GL_UNSIGNED_SHORT, 0);
// disable attributes and buffers
glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
So I figured this out.
This:
// enable tex coords
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(12));
Needs to be this:
GLint texCoordLoc = glGetAttributeLocation(program, texCoordAttributeName);
glEnableVertexAttribArray(texCoordLoc);
glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), BUFFER_OFFSET(12));

Related

OpenGL ES 2.0 Multiple Instances of Textured Object

I am using Blender to create a 3D cow and obtain the correct vertices (optimized afterwards to remove duplicates). I have created a Cow Class to be able to draw multiple instances of this cow on screen.
Cow 1 is drawn at (-2,0,-10) and Cow 2 is drawn at (2,0,-10). When I render cow 1 only I see Cow 1 at (-2,0,-10). When I render either both cows or only cow 2 (comment render cow 1 out), I only get cow 2 (do not see cow 1) at (2,0,-10). I am making a game where I will have many enemies running around and I need to be able to draw multiple instances of these objects and render them independently at different locations. Can anyone tell me what I am doing wrong? Thanks
//
// Cow.m
//
#import "Cow.h"
#import "cow_verts.h"
#implementation Cow
- (id)initWithContext:(EAGLContext *)aContext {
context = aContext;
effect = [[GLKBaseEffect alloc] init];
[EAGLContext setCurrentContext:context];
sharedResourceManager = [ResourceManager sharedResourceManager];
UIImage *textureImage = [UIImage imageNamed:#"cowUV.png"];
texture = [sharedResourceManager addTexture:textureImage];
position = GLKVector3Make(0,0,0);
rotation = GLKVector3Make(0,0,0);
scale = GLKVector3Make(1,1,1);
[self setupGL];
return self;
}
- (void)setupGL {
glGenVertexArraysOES(1, &_vao);
glBindVertexArrayOES(_vao);
glGenBuffers(1, &_dynamicVBO);
glBindBuffer(GL_ARRAY_BUFFER, _dynamicVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(CowDynamicVertexData), CowDynamicVertexData, GL_DYNAMIC_DRAW);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(dynamicVertexData), (void *)offsetof(dynamicVertexData, position));
glEnableVertexAttribArray(GLKVertexAttribPosition);
glGenBuffers(1, &_staticVBO);
glBindBuffer(GL_ARRAY_BUFFER, _staticVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(CowStaticVertexData), CowStaticVertexData, GL_STATIC_DRAW);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(staticVertexData), (void *)offsetof(staticVertexData, texCoord));
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(CowIndices), CowIndices, GL_STATIC_DRAW);
glBindVertexArrayOES(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
- (void)updateWithDelta:(float)aDelta {
float aspect = fabsf([[UIScreen mainScreen] bounds].size.width/ [[UIScreen mainScreen] bounds].size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 4.0f, 20.0f);
effect.transform.projectionMatrix = projectionMatrix;
rotation.y += 90 * aDelta;
}
- (void)render {
[EAGLContext setCurrentContext:context];
glClearColor(0, 1, 1, 1);
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
GLKMatrix4 xRotationMatrix = GLKMatrix4MakeXRotation(GLKMathDegreesToRadians(rotation.x));
GLKMatrix4 yRotationMatrix = GLKMatrix4MakeYRotation(GLKMathDegreesToRadians(rotation.y));
GLKMatrix4 zRotationMatrix = GLKMatrix4MakeZRotation(GLKMathDegreesToRadians(rotation.z));
GLKMatrix4 scaleMatrix = GLKMatrix4MakeScale(scale.x, scale.y, scale.z);
GLKMatrix4 translateMatrix = GLKMatrix4MakeTranslation(position.x, position.y, position.z);
GLKMatrix4 modelMatrix = GLKMatrix4Multiply(translateMatrix,
GLKMatrix4Multiply(scaleMatrix,
GLKMatrix4Multiply(zRotationMatrix,
GLKMatrix4Multiply(yRotationMatrix,
xRotationMatrix))));
effect.transform.modelviewMatrix = modelMatrix;
//GLKMatrix4 viewMatrix = GLKMatrix4MakeLookAt(0, 0, 3, 0, 0, 0, 0, 1, 0);
//effect.transform.modelviewMatrix = GLKMatrix4Multiply(viewMatrix, modelMatrix);
effect.texture2d0.name = texture.name;
effect.texture2d0.target = texture.target;
effect.texture2d0.envMode = GLKTextureEnvModeReplace;
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glBindVertexArrayOES(_vao);
[effect prepareToDraw];
glDrawElements(GL_TRIANGLES, sizeof(CowIndices)/sizeof(CowIndices[0]), GL_UNSIGNED_INT, (void *)0);
glBindVertexArrayOES(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
}
#end
//
// Cow.h
//
#interface Cow : NSObject {
EAGLContext *context;
GLuint _vao;
GLuint _staticVBO;
GLuint _dynamicVBO;
GLuint _indexBuffer;
GLKTextureInfo *texture;
GLKBaseEffect *effect;
GLKVector3 position;
GLKVector3 rotation;
GLKVector3 scale;
ResourceManager *sharedResourceManager;
}
- (id)initWithContext:(EAGLContext *)aContext;
- (void)updateWithDelta:(float)aDelta;
- (void)render;
#end
//
// Scene which creates these objects and calls the functions
//
#import "Cow.h"
#implementation GameScene {
NSMutableArray *cows;
}
- (id)init {
if(self = [super init]) {
sharedDirector = [Director sharedDirector];
[EAGLContext setCurrentContext:[sharedDirector context]];
cows = [[NSMutableArray alloc] init];
AbstractEnemy *cow1 = [[Cow alloc] initWithContext:[sharedDirector context]];
cow1.position = GLKVector3Make(-2, 0, -10);
[cows addObject:cow1];
AbstractEnemy *cow2 = [[Cow alloc] initWithContext:[sharedDirector context]];
cow2.position = GLKVector3Make(2, 0, -10);
[cows addObject:cow2];
AbstractEnemy *cow3 = [[Cow alloc] initWithContext:[sharedDirector context]];
cow3.position = GLKVector3Make(0, 0, -15);
[cows addObject:cow3];
}
return self;
}
- (void)updateWithDelta:(GLfloat)aDelta {
for (int i = 0; i < cows.count; i++)
{
[cows[i] updateWithDelta:aDelta];
}
}
- (void)render {
for (int i = 0; i < cows.count; i++)
{
[cows[i] render];
}
}
#end
From the code you gave, you are calling a glClear() every time before you draw the cow. With all those clear calls, only the last cow you draw will be visible.
Move this call into the scene's render function so you only clear the scene once at the start of each frame.

Texture Mapping - Cocos2d/OpenGL ES 1.0

This lightning is really affecting my game's performance because I am constantly adding and removing the lightning, but also each lighting strike is composed of 3 anti aliased lines using:
void ccDrawSmoothLine(CGPoint pos1, CGPoint pos2, float width)
{
GLfloat lineVertices[12], curc[4];
GLint ir, ig, ib, ia;
CGPoint dir, tan;
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_VERTEX_ARRAY,
// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
//glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
pos1.x *= CC_CONTENT_SCALE_FACTOR();
pos1.y *= CC_CONTENT_SCALE_FACTOR();
pos2.x *= CC_CONTENT_SCALE_FACTOR();
pos2.y *= CC_CONTENT_SCALE_FACTOR();
width *= CC_CONTENT_SCALE_FACTOR();
width = width*2;
dir.x = pos2.x - pos1.x;
dir.y = pos2.y - pos1.y;
float len = sqrtf(dir.x*dir.x+dir.y*dir.y);
if(len<0.00001)
return;
dir.x = dir.x/len;
dir.y = dir.y/len;
tan.x = -width*dir.y;
tan.y = width*dir.x;
lineVertices[0] = pos1.x + tan.x;
lineVertices[1] = pos1.y + tan.y;
lineVertices[2] = pos2.x + tan.x;
lineVertices[3] = pos2.y + tan.y;
lineVertices[4] = pos1.x;
lineVertices[5] = pos1.y;
lineVertices[6] = pos2.x;
lineVertices[7] = pos2.y;
lineVertices[8] = pos1.x - tan.x;
lineVertices[9] = pos1.y - tan.y;
lineVertices[10] = pos2.x - tan.x;
lineVertices[11] = pos2.y - tan.y;
glGetFloatv(GL_CURRENT_COLOR,curc);
ir = 255.0*curc[0];
ig = 255.0*curc[1];
ib = 255.0*curc[2];
ia = 255.0*curc[3];
const GLubyte lineColors[] = {
ir, ig, ib, 0,
ir, ig, ib, 0,
ir, ig, ib, ia,
ir, ig, ib, ia,
ir, ig, ib, 0,
ir, ig, ib, 0,
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, lineVertices);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, lineColors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
glDisableClientState(GL_COLOR_ARRAY);
// restore default state
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
}
My FPS will drop to about 40, then shoot back up to 60. I've read that texture mapping the line could improve my game's performance.
I have been trying to figure this out for several weeks now, with no luck. Can someone PLEASE help me with this?
This is my current ccDrawLines and draw method
-(void) draw
{
numPoints_ = 0;
glColor4ub(_color.r, _color.g, _color.b, _opacity);
if (_opacity != 255)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
drawLightning(_strikePoint2, _strikePoint, _displacement, _minDisplacement, _seed, lightningPoints_, &numPoints_);
ccDrawLines(lightningPoints_, numPoints_, texture);
if (_opacity != 255)
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
glColor4f(1.0, 1.0, 1.0, 1.0);
}
void ccDrawLines( CGPoint* points, uint numberOfPoints, CCTexture2D* texture )
{
//layout of points [0] = origin, [1] = destination and so on
ccVertex2F vertices[numberOfPoints];
if (CC_CONTENT_SCALE_FACTOR() != 1 )
{
for (int i = 0; i < numberOfPoints; i++)
{
vertices[i].x = points[i].x * CC_CONTENT_SCALE_FACTOR();
vertices[i].y= points[i].y * CC_CONTENT_SCALE_FACTOR();
}
glVertexPointer(2, GL_FLOAT, 0, vertices);
}
else glVertexPointer(2, GL_FLOAT, 0, points);
ccTex2F texCoords[numberOfPoints];
float width = texture.pixelsWide;
float height = texture.pixelsHigh;
if (CC_CONTENT_SCALE_FACTOR() != 1 )
{
for (int i = 0; i < numberOfPoints; i++)
{
texCoords[i].u = (vertices[i].x * CC_CONTENT_SCALE_FACTOR()) / width;
texCoords[i].v = (vertices[i].y * CC_CONTENT_SCALE_FACTOR()) / height;
}
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
}
else glTexCoordPointer(2, GL_FLOAT, 0, points);
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_VERTEX_ARRAY,
// Unneeded states: GL_TEXTURE_2D, GL_TEXTURE_COORD_ARRAY, GL_COLOR_ARRAY
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, [texture name]);
glDisableClientState(GL_COLOR_ARRAY);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, numberOfPoints);
// restore default state
glEnableClientState(GL_COLOR_ARRAY);
glPopMatrix();
}
The texture is just a 32x32 .png file with a small blue dot.
If you look at ccDrawLines I have added the code to texture map the line. The problem with it is, gaps in the line, multiple lines being drawn, and it looks horrible.
EDIT:
I decided not to texture map the line and use ccDrawSmoothLine.
All I did was allocate the lightning in my gamelayer's init
lightningStrike_ = [Lightning lightningWithStrikePoint:ccp(-100, -100) strikePoint2:ccp(-100, -100)];
[self addChild:lightningStrike_ z:1];
Then, I created an instance method to set the _strikePoint and _strikePoint2 properties and call the strikeRandom method.
-(Lightning *)lightningStrike:(CGPoint)p end:(CGPoint)p2
{
lightningStrike_.strikePoint = ccp(p.x, p.y);
lightningStrike_.strikePoint2 = ccp(p2.x, p2.y);
[lightningStrike_ strikeRandom];
return lightningStrike_;
}
Usage:
[self lightningStrike:ccp(100, 100) end:ccp(100, 100)];
This fixed the FPS drop. After 24 hours I will answer and accept my own answer.
EDIT: I decided not to texture map the line and use ccDrawSmoothLine.
All I did was allocate the lightning in my gamelayer's init
lightningStrike_ = [Lightning lightningWithStrikePoint:ccp(-100, -100) strikePoint2:ccp(-100, -100)];
[self addChild:lightningStrike_ z:1];
Then, I created an instance method to set the _strikePoint and _strikePoint2 properties and call the strikeRandom method.
-(Lightning *)lightningStrike:(CGPoint)p end:(CGPoint)p2
{
    lightningStrike_.strikePoint = ccp(p.x, p.y);
    lightningStrike_.strikePoint2 = ccp(p2.x, p2.y);
    [lightningStrike_ strikeRandom];
    return lightningStrike_;
}
Usage:
[self lightningStrike:ccp(100, 100) end:ccp(100, 100)];
This fixed the FPS drop. After 24 hours I will answer and accept my own answer.

How to draw a line inside the fish movement (OpenGLES in iPhone)?

Am working in a simple iPhone game application using OpenGLES framework. I facing an "EXC Bad Access" error while draw a line on the images. Here i will explain you what i did and what i tried in my project.
Step:1 I draw a Background Image used GL_TRIANGLE_STRIP. Here is my sample code,
- (void)viewDidLoad
{
[super viewDidLoad];
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
Test = NO;
Test1 = NO;
if (!self.context)
{
NSLog(#"Failed to create ES context");
}
GLKView *view = (GLKView *)self.view;
view.context = self.context;
[EAGLContext setCurrentContext:self.context];
self.effect = [[GLKBaseEffect alloc] init];
GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, 480, 0, 320, -1024, 1024);
self.effect.transform.projectionMatrix = projectionMatrix;
self.player = [[SGGSprite alloc] initWithFile:#"bg.png" effect:self.effect];
self.player.position = GLKVector2Make(self.player.contentSize.width, 460);
self.children = [NSMutableArray array];
[self.children addObject:self.player];
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
// glClearColor(1, 1, 1, 1);
// glClear(GL_COLOR_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// Condition satisfied to draw a line code given below, otherwise the background and fish image draw in else part.
if(Test1 == YES)
{
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
self.effect = [[GLKBaseEffect alloc] init];
[self.effect prepareToDraw];
const GLfloat line[] =
{
0.0f, 0.5f,
-3.0f,-1.0f,
};
GLuint bufferObjectNameArray;
glGenBuffers(1, &bufferObjectNameArray);
glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNameArray);
glBufferData(
GL_ARRAY_BUFFER, // the target buffer
sizeof(line), // the number of bytes to put into the buffer
line, // a pointer to the data being copied
GL_STATIC_DRAW); // the usage pattern of the data
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(
GLKVertexAttribPosition,
2, // number of coordinates per vertex
GL_FLOAT, // the data type of each component
GL_FALSE, // can the data be scaled
2*4,
NULL);
glDrawArrays(GL_LINES, 0, 2);
}
else
{
//SGGSprite is another class and self.children is mutable array.
for (SGGSprite * sprite in self.children)
{
[sprite render];
}
}
}
//render method in SGGSprite class to draw a fish and background image
- (void)render
{
self.effect.texture2d0.name = self.textureInfo.name;
self.effect.texture2d0.enabled = YES;
self.effect.transform.modelviewMatrix = self.modelMatrix;
[self.effect prepareToDraw];
long offset = (long)&_quad;
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
NSLog(#"TexturedVertex:%ld",offset);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
Step:2 After i draw a background image for my view am going to draw a fish images in the screen by using GL_TRIANGLE_STRIP. The fish images are always in moving. Here is my sample code,
(void)update
{
if(Test == NO)
{
self.timeSinceLastSpawn += self.timeSinceLastUpdate;
if (self.timeSinceLastSpawn > 2.0)
{
self.timeSinceLastSpawn = 0;
[self target]; // add fish image
}
for (SGGSprite * sprite in self.children)
{
[sprite update:self.timeSinceLastUpdate];
}
}
}
(void)target
{
SGGSprite * target = [[SGGSprite alloc] initWithFile:#"img2.png" effect:self.effect];
[self.children addObject:target]; // Add fish image in NSMutable array
int minY = target.contentSize.height/2;
int maxY = 320 - target.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
if(actualY <= 100)
{
actualY = 215;
}
target.position = GLKVector2Make(480 + (target.contentSize.width), actualY);
int minVelocity = 480.0/12.0;
int maxVelocity = 480.0/6.0;
int rangeVelocity = maxVelocity - minVelocity;
int actualVelocity = (arc4random() % rangeVelocity) + minVelocity;
target.moveVelocity = GLKVector2Make(-actualVelocity, 0);
}
(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
// glClearColor(1, 1, 1, 1);
// glClear(GL_COLOR_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// Condition satisfied to draw a line code given below, otherwise the background and fish image draw in else part.
if(Test1 == YES)
{
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
self.effect = [[GLKBaseEffect alloc] init];
[self.effect prepareToDraw];
const GLfloat line[] =
{
0.0f, 0.5f,
-3.0f,-1.0f,
};
GLuint bufferObjectNameArray;
glGenBuffers(1, &bufferObjectNameArray);
glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNameArray);
glBufferData(
GL_ARRAY_BUFFER, // the target buffer
sizeof(line), // the number of bytes to put into the buffer
line, // a pointer to the data being copied
GL_STATIC_DRAW); // the usage pattern of the data
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(
GLKVertexAttribPosition,
2, // number of coordinates per vertex
GL_FLOAT, // the data type of each component
GL_FALSE, // can the data be scaled
2*4,
NULL);
glDrawArrays(GL_LINES, 0, 2);
}
else
{
//SGGSprite is another class and self.children is mutable array.
for (SGGSprite * sprite in self.children)
{
[sprite render];
}
}
}
Step:3 Now i draw a Background Image and fish images in my screen. It works perfect. Now am going to draw a white line (using GL_LINE) in the screen above the fish images and background image. When i draw a line by using below code,
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
Test = YES;
Test1 = YES;
}
- (void)update
{
if(Test == NO)
{
self.timeSinceLastSpawn += self.timeSinceLastUpdate;
NSLog(#"timeSinceLastUpdate:%f",self.timeSinceLastUpdate);
if (self.timeSinceLastSpawn > 2.0)
{
self.timeSinceLastSpawn = 0;
[self target];
}
NSLog(#"Children count:%d",[self.children count]);
for (SGGSprite * sprite in self.children)
{
[sprite update:self.timeSinceLastUpdate];
}
}
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
// glClearColor(1, 1, 1, 1);
// glClear(GL_COLOR_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
// Condition satisfied to draw a line code given below, otherwise the background and fish image draw in else part.
if(Test1 == YES)
{
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
self.effect = [[GLKBaseEffect alloc] init];
[self.effect prepareToDraw];
const GLfloat line[] =
{
0.0f, 0.5f,
-3.0f,-1.0f,
};
GLuint bufferObjectNameArray;
glGenBuffers(1, &bufferObjectNameArray);
glBindBuffer(GL_ARRAY_BUFFER, bufferObjectNameArray);
glBufferData(
GL_ARRAY_BUFFER, // the target buffer
sizeof(line), // the number of bytes to put into the buffer
line, // a pointer to the data being copied
GL_STATIC_DRAW); // the usage pattern of the data
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(
GLKVertexAttribPosition,
2, // number of coordinates per vertex
GL_FLOAT, // the data type of each component
GL_FALSE, // can the data be scaled
2*4,
NULL);
glDrawArrays(GL_LINES, 0, 2);
}
else
{
//SGGSprite is another class and self.children is mutable array, Draw a fish and background image
for (SGGSprite * sprite in self.children)
{
[sprite render];
}
}
}
The app getting crash in the line "glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // ERROR -Bad excess happened here when i touch the screen"
(void)render
{
self.effect.texture2d0.name = self.textureInfo.name;
self.effect.texture2d0.enabled = YES;
self.effect.transform.modelviewMatrix = self.modelMatrix;
[self.effect prepareToDraw];
long offset = (long)&_quad;
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
NSLog(#"TexturedVertex:%ld",offset);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // ERROR comes from this line, when i touch the screen.
}
Can you please refer these code and tell what is wrong with my code? What i should do to fix this problem? Please help me. Thanks in advance.
   

Mesh creation in openGL iphone sdk

I am using this source code as my base and trying to change the code as per my requirements. I have included the following code to create a mesh on image.
-(void)populateMesh{
verticalDivisions = kVerticalDivisions;
horizontalDivisions = kHorisontalDivisions;
unsigned int verticesArrsize = (kVerticalDivisions * ((2 + kHorisontalDivisions * 2) * 3));
unsigned int textureCoordsArraySize = kVerticalDivisions * ((2 + kHorisontalDivisions * 2) * 2);
verticesArr = (GLfloat *)malloc(verticesArrsize * sizeof(GLfloat));
textureCoordsArr = (GLfloat*)malloc(textureCoordsArraySize * sizeof(GLfloat));
if (verticesArr == NULL) {
NSLog(#"verticesArr = NULL!");
}
float height = kWindowHeight/verticalDivisions;
float width = kWindowWidth/horizontalDivisions;
int i,j, count;
count = 0;
for (j=0; j<verticalDivisions; j++) {
for (i=0; i<=horizontalDivisions; i++, count+=6) { //2 vertices each time...
float currX = i * width;
float currY = j * height;
verticesArr[count] = currX;
verticesArr[count+1] = currY + height;
verticesArr[count+2] = 0.0f;
verticesArr[count+3] = currX;
verticesArr[count+4] = currY;
verticesArr[count+5] = 0.0f;
}
}
float xIncrease = 1.0f/horizontalDivisions;
float yIncrease = 1.0f/verticalDivisions;
int x,y;
//int elements;
count = 0;
for (y=0; y<verticalDivisions; y++) {
for (x=0; x<horizontalDivisions+1; x++, count+=4) {
float currX = x *xIncrease;
float currY = y * yIncrease;
textureCoordsArr[count] = (float)currX;
textureCoordsArr[count+1] = (float)currY + yIncrease;
textureCoordsArr[count+2] = (float)currX;
textureCoordsArr[count+3] = (float)currY;
}
}
// int cnt;
// int cnt = 0;
NSLog(#"expected %i vertices, and %i vertices were done",(verticalDivisions * ((2 + horizontalDivisions*2 ) * 2) ) , count );
}
Following is the drawView code.
- (void)drawView:(GLView*)view;
{
static GLfloat rot = 0.0;
glBindTexture(GL_TEXTURE_2D, texture[0]);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordsArr);
glVertexPointer(3, GL_FLOAT, 0, verticesArr);
glPushMatrix();{
int i;
for (i=0; i<verticalDivisions; i++) {
glDrawArrays(GL_TRIANGLE_STRIP, i*(horizontalDivisions*2+2), horizontalDivisions*2+2);
}
}glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
In the setup view I have called [self populateMesh]; at the end of the function.
My problem is after changing the code, a blank rather say black view is appeared on the screen. Can anyone figure out where I am doing some mistake. I am newbie for openGL and trying to manipulate images through mesh. Please help asap. Thanks in advance.
Following is the setup view code.
-(void)setupView:(GLView*)view {
const GLfloat zNear = 0.01, zFar = 1000.0, fieldOfView = 45.0;
GLfloat size;
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
size = zNear * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);
CGRect rect = view.bounds;
glFrustumf(-size, size, -size / (rect.size.width / rect.size.height), size / (rect.size.width / rect.size.height), zNear, zFar);
glViewport(0, 0, rect.size.width, rect.size.height);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_SRC_COLOR);
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
NSString *path = [[NSBundle mainBundle] pathForResource:#"texture" ofType:#"png"];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil)
NSLog(#"Do real error checking here");
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc( height * width * 4 );
CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGContextTranslateCTM (context, 0, height);
CGContextScaleCTM (context, 1.0, -1.0);
CGColorSpaceRelease( colorSpace );
CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ),image.CGImage );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(context);
free(imageData);
[image release];
[texData release];
[self populateMesh];
}
EDIT This is what I am getting as an out put. While expected is regular grid...
Guessing the mesh is cut out with zNear value. Try to change z value to -2.
verticesArr[count+2] = -2.0f;
verticesArr[count+5] = -2.0f;
By default, the camera is situated at the origin, points down the negative z-axis, and has an up-vector of (0, 1, 0).
Notice that your mesh is out of view frustum (pyramid). Check it out in OpenGL red book:
http://glprogramming.com/red/chapter03.html
The grid is not regular because of the way how vertices are ordered. Also are you sure that GL_TRIANGLE_STRIP is desired option. Maybe, GL_TRIANGLES is that what you need.
I propose simpler solution with using indices array. For example in initialization code make vertices and texture array for your grid in normal order as:
0 1 2
3 4 5
6 7 8
Update:
- (void) setup
{
vertices = (GLfloat*)malloc(rows*colums*3*sizeof(GLfloat));
texCoords = (GLfloat*)malloc(rows*columns*2*sizeof(GLfloat));
indices = (GLubyte*)malloc((rows-1)*(columns-1)*6*sizeof(GLubyte));
float xDelta = horizontalDivisions/columns;
float yDelta = verticalDivisions/rows;
for (int i=0;i<columns;i++) {
for(int j=0;j<rows; j++) {
int index = j*columns+i;
vertices[3*index+0] = i*xDelta; //x
vertices[3*index+1] = j*yDelta; //y
vertices[3*index+2] = -10; //z
texCoords[2*index+0] = i/(float)(columns-1); //x texture coordinate
texCoords[2*index+1] = j/(float)(rows-1); //y tex coordinate
}
}
for (int i=0;i<columns-1;i++) {
for(int j=0;j<rows-1; j++) {
indices[6*(j*columns+i)+0] = j*columns+i;
indices[6*(j*columns+i)+1] = j*columns+i+1;
indices[6*(j*columns+i)+2] = (j+1)*columns+i;
indices[6*(j*columns+i)+3] = j*columns+i+1;
indices[6*(j*columns+i)+4] = (j+1)*columns+i+1;
indices[6*(j*columns+i)+5] = (j+1)*columns+i;
}
}
}
- (void) dealloc {
free(vertices); free(texCoords); free(indices);
}
Practically this indices order means that tringles are rendered as following:
(013)(143)(124)(254)(346)(476)... and so on.
In render method use the following lines:
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glDrawElements(GL_TRIANGLES, 6*(columns-1)*(rows-1), GL_UNSIGNED_BYTE, indices);
Hope that will help.
This is a great tutorial on drawing a grid in 3D. It should have the code necessary to help you. I'm not sure if you are working in 3D or 2D, but even if it is 2D, it should be fairly easy to adapt to your needs. Hope that helps!

exc_bad_access when using VBO's in Cocos2d

In my iPhone application I am creating a vertex buffer as shown below:
-(id)initWithPoints:(NSArray *)polygonPoints andTexture: (CCTexture2D *) fillTexture{
self = [super init];
if(self){
int vertexCount = [polygonPoints count];
CGPoint *vertices = (CGPoint*)malloc(sizeof(CGPoint)*vertexCount);
GLushort *indices = (GLushort*)malloc(sizeof(GLushort)*2*vertexCount);
int i = 0;
for(NSValue *value in polygonPoints){
CGPoint p = [value CGPointValue];
vertices[i] = ccp(p.x, p.y);
i++;
}
for (int k = 0; k<vertexCount; k++) {
indices[k] = (GLushort)k;
}
NSLog(#"count: %i", vertexCount);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexCount*sizeof(CGPoint), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (vertexCount)*2*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
self.text = fillTexture;
}
return self;
}
And I draw it using:
-(void)draw{
glBindTexture(GL_TEXTURE_2D, self.text.name);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexPointer(2, GL_FLOAT, sizeof(CGPoint), 0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLES, 1024, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
However, I can only call glDrawElements with 1024 elements (out of ~20,000) and they render ok.
If I set it to (for example) 1025, the application crashes with EXC_BAD_ACCESS.
Obviously there's a reason the app crashes at 1024 elements, but I can't understand what it is. Any ideas would be much appreciated!