Fill a fixture with a texture

General discussion about Box2D tutorials
Post Reply
notnowlewis
Posts: 8
Joined: Tue Jul 09, 2013 6:46 pm

Fill a fixture with a texture

Post by notnowlewis »

I know this is a bit off topic, but this is the best site I've found about box2d, drawing polygons, etc. so hopefully someone will know the answer to this...

I have drawn my terrain using RUBE, saved to json, and loaded it into my world in my C++ code. Now I want to fill that terrain with my texture, but I'm a little lost. If I had a fixture that was the same shape as one of my sprites, that would be easy :) But I want my terrain texture to repeat inside the terrain.

I'm using SFML, which has a Shape class [1] and a ConvexShape class [2], but I'm a total newbie when it comes to opengl and handling textures (cocos2d-x spoiled me!) and the outline of my terrain is not Convex.

Any help would be appreciated!

[1] http://www.sfml-dev.org/documentation/2 ... 1Shape.php
[2] http://www.sfml-dev.org/documentation/2 ... xShape.php
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: Fill a fixture with a texture

Post by iforce2d »

The most straightforward way I know of is to triangulate the polygon, and use automatic texture generation to repeat the texture.

Triangulation can be done with poly2tri, or other similar libraries. If you save the ground as a polygon, RUBE will do this for you so you can just draw the individual convex shapes (there is an option in the settings dialog to use poly2tri if you want to make sure all convex shapes are triangles. If you save the ground as a line/loop shape type, you can get the vertices of that to give to poly2tri. I did this in the 'alone in the park' for LD22. You can find links to that with source here: http://www.ludumdare.com/compo/ludum-da ... w&uid=7091 Take a look at the buildTriangles function in the Game class.

Automatic texture generation is a standard OpenGL feature, I think googling for that should turn up plenty of information about it.
notnowlewis
Posts: 8
Joined: Tue Jul 09, 2013 6:46 pm

Re: Fill a fixture with a texture

Post by notnowlewis »

Wow, thank you! That's the single most useful thing I've read so far! I really need to learn more low level OpenGL, I've been spoiled by cocos2d for too long...
notnowlewis
Posts: 8
Joined: Tue Jul 09, 2013 6:46 pm

Re: Fill a fixture with a texture

Post by notnowlewis »

So, after reading through your LD entry and the opengl red book, I almost have this working :)

I use poly2tri to carry out the Delaunay triangulation, and I have the following

Code: Select all

// three points and an associated box2d body
struct myTriangle {
    b2Body* m_body;
    b2Vec2 m_points[3];
};

... lots of vertex/chain shape/poly2tri code cut out here ...


    while(window.isOpen())
    {
        m_world->Step(1/60.0f, 8, 3);
        window.clear();
        glColor3f(1,1,1);
        glEnable(GL_TEXTURE_2D);
        glEnableClientState(GL_VERTEX_ARRAY);

        sf::Texture::bind(&earthImage);
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        for (size_t i = 0; i < earthTriangles.size(); i++) {
                myTriangle& tri = earthTriangles[i];
                glVertexPointer(2, GL_FLOAT, 0, tri.m_points);
                glDrawArrays(GL_TRIANGLES, 0, 3);
        }
        sf::Texture::bind(NULL);
        window.display();
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisable(GL_TEXTURE_2D);
    }
The problem I have here is that the polygon is filled, but only with the pixel at 0,0 of my texture, so instead of seeing my silly smiling face, I have a solid color.

I think it's something to do with setting texture coordinates, but I haven't quite understood that yet.

I know this is very far off topic, but I really do appreciate your help. (and put some higher amounts in your donate paypal form!)
notnowlewis
Posts: 8
Joined: Tue Jul 09, 2013 6:46 pm

Re: Fill a fixture with a texture

Post by notnowlewis »

Ok, after lots of reading I found a solution!

You have to draw each triangle in turn, setting the texture coords after each vertex so that the texture doesn't get warped. I'll end up writing a class that acts like an SFML Drawable, but is constructed with a box2d fixture and a texture, and will draw the fixture filled with the texture.
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: Fill a fixture with a texture

Post by iforce2d »

If that glTexParameter is the only thing you've added for texgen, I think maybe you've just missed the part that specifies how the coordinates should be calculated. You would need something like this:

Code: Select all

static GLint s_vector[4] = { 1, 0, 0, 0 };
static GLint t_vector[4] = { 0, 1, 0, 0 };

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeniv(GL_S, GL_OBJECT_PLANE, s_vector);

glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeniv(GL_T, GL_OBJECT_PLANE, t_vector);
This would generate texture coordinates so that textures were repeated on a 1x1 unit size across the terrain. You can change the non-zero numbers in s_vector and t_vector to scale the texture - note that making these larger will compress the texture more, slightly un-intuitively.

Ref: http://opengl.czweb.org/ch12/396-424.html
Post Reply