Mar 312012
 

Prerequisites

This is the third part to a four part series about simulating a soft body physics in Box2d. Before continuing, you should read and understand the following tutorials.

1. Quick Tip: Mixing OpenGL and Cocos2d (Triangle Fan)
2. Soft Body Physics with Box2d and Cocos2d Part 1/4
3. Soft Body Physics with Box2d and Cocos2d Part 2/4

The next step is to texture map the circle polygon. But before texture mapping the circle we have created in part 2 of the tutorial, let’s get some basics out of the way and texture map a simple shape in OpenGL. I will save the actual texture mapping of the soft body physics object for the final installment of the tutorial in part 4.

Texture Mapping Basics

The idea behind texture mapping is fairly straight forward. For each vertex of a polygon, we map that vertex to a coordinate on the texture. In the image above, the polygon is a square constructed with a triangle strip and has 4 vertices. We map each vertex of the square to a coordinate on the texture. We store the texture coordinates into an array called a texture coordinate array. Once we have the vertex array (for the vertices of the polygon) and the texture coordinate array, we send those off to OpenGL.

A Few Things to Remember

1. Texture coordinates must in the range of 0 to 1, with the origin at (0, 0).
2. On iOS (and hence when texture is loaded in Cocos2d), the texture is vertically flipped about the x-axis.
3. The width and height of an OpenGL texture must be in powers of 2.

To solve the #2 above, we’re going to simply flip the mapping like in the image below so that the top maps to the bottom and bottom maps to the top.

Let’s Code!

We will be loading the texture using Cocos2d. We then define the vertices for the square (triangle strip), vertices for the texture coordinates and then send them off to OpenGL. Here is MyNode.h and MyNode.m. Instantiate an instance of MyNode in HelloWorldLayer and add it to the layer. When you run it, you should see an image of Kirby on the screen mapped to the square polygon. The code is commented so you should be able to easily follow it.

#import "CCNode.h"
 
typedef struct {
    GLfloat x;
    GLfloat y;
} Vertex2D;
 
static inline Vertex2D Vertex2DMake(GLfloat inX, GLfloat inY) {
    Vertex2D ret;
    ret.x = inX;
    ret.y = inY;
    return ret;
}
 
@interface MyNode : CCNode {
    Vertex2D vertices[4];   // For the polygon
    Vertex2D textCoords[4]; // For the texture
 
    CCTexture2D *texture;
}
@end
#import "cocos2d.h"
#import "MyNode.h"
 
@implementation MyNode
 
- (id) init {
    self = [super init];
 
    // Load the texture
    texture = [[CCTextureCache sharedTextureCache] addImage:@"Kirby.png"];        
 
    GLfloat size = [texture pixelsWide]/2;
 
    // Vertices for the square (we'll be using a triangle strip)
    vertices[0] = Vertex2DMake(-size, size);
    vertices[1] = Vertex2DMake(size, size);
    vertices[2] = Vertex2DMake(-size, -size);
    vertices[3] = Vertex2DMake(size, -size);
 
    // Because the texture is flipped about its x-axis,
    // we flip the y coordinates to correct this.
    textCoords[0] = Vertex2DMake(0, 0);
    textCoords[1] = Vertex2DMake(1, 0);
    textCoords[2] = Vertex2DMake(0, 1);
    textCoords[3] = Vertex2DMake(1, 1);
 
    // If you use the mapping below, then the image will
    // be flipped. To correct this, use the coordinates
    // above, or save the image in a flipped state so it
    // will be unflipped when mapped!
    /*
    textCoords[0] = Vertex2DMake(0, 1);
    textCoords[1] = Vertex2DMake(1, 1);
    textCoords[2] = Vertex2DMake(0, 0);
    textCoords[3] = Vertex2DMake(1, 0);
     */
 
    return self;
}
 
- (void) draw {
    // Following two states must be enabled for texture mapping
    glEnable(GL_TEXTURE_2D);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
    glDisableClientState(GL_COLOR_ARRAY);
 
    // Bind the OpenGL texture
    glBindTexture(GL_TEXTURE_2D, [texture name]);
 
    // The vertices for the polygon
    glVertexPointer(2, GL_FLOAT, 0, vertices);
    // The vertices for the texture
    glTexCoordPointer(2, GL_FLOAT, 0, textCoords);
    // Send it off to OpenGL
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 
    // Re-enable states
    glEnableClientState(GL_COLOR_ARRAY);
}
@end

Source and Video

You can download the source code for the tutorial here.

Soft Body Physics with Box2d and Cocos2d Part 1/4
Soft Body Physics with Box2d and Cocos2d Part 2/4
Soft Body Physics with Box2d and Cocos2d Part 4/4

If you enjoyed this post, make sure you subscribe to my RSS feed!
 Posted by at 11:59 am

  4 Responses to “Soft Body Physics With Box2d (and Cocos2d) Part 3/4”

  1. [...] 1. Quick Tip: Mixing OpenGL and Cocos2d (Triangle Fan) 2. Soft Body Physics with Box2d and Cocos2d Part 1/4 3. Soft Body Physics with Box2d and Cocos2d Part 2/4 4. Soft Body Physics with Box2d and Cocos2d Part 3/4 [...]

  2. [...] Body Physics with Box2d and Cocos2d Part 2/4 Soft Body Physics with Box2d and Cocos2d Part 3/4 Soft Body Physics with Box2d and Cocos2d Part [...]

  3. [...] Body Physics with Box2d and Cocos2d Part 1/4 Soft Body Physics with Box2d and Cocos2d Part 3/4 Soft Body Physics with Box2d and Cocos2d Part [...]

  4. Hello,
    What would be an equivalent code for cocos2d 2.0 and opengl es 2.0? Specifically the draw method.

    Thanks

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>