Rendering a texture-filled polygon

Forums Programming cocos2d support (graphics engine) Rendering a texture-filled polygon

This topic contains 66 replies, has 25 voices, and was last updated by  toby10101 6 months, 4 weeks ago.

Viewing 25 posts - 1 through 25 (of 67 total)
Author Posts
Author Posts
July 23, 2010 at 5:44 am #223435

asinesio
Participant
@asinesio

For my current project, I’m essentially looking for a way to do a texture-filled polygon. The texture should not stretch or warp, but it should repeat to fill the entire polygon. The polygon may be concave or convex.

Basically, I want the same thing that ccDrawPoly() does, but instead of just an outline, it would fill with a repeating texture. I’m an openGL noob, so keep that in mind.

Think of creating a polygon in Photoshop then clicking the paint bucket to fill it with a pattern.

So far, I’ve tried the following approaches with very little success.

1) Modified CCTexture2D and adding a “drawInPolygon” method, like this:

- (void) drawInPolygon: (CGPoint *) poli points: (int) points
{
GLfloat coordinates[] = { 0.0f, _maxT,
_maxS, _maxT,
0.0f, 0.0f,
_maxS, 0.0f };

glBindTexture(GL_TEXTURE_2D, _name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glVertexPointer(2, GL_FLOAT, 0, poli);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glDrawArrays(GL_TRIANGLE_FAN, 0, points);
}

This has led to the texture being stretched and rotated… and looking awful, and it also requires that the polygon is convex, so I’ve even got a library that makes a polygon convex by triangulation.

2) Implementing a CCRibbon object as a child of my node that has the vertices.

This kinda works, but it looks ugly.

3) CCRenderTexture, which doesn’t work because the levels I’m creating are well over 5000 px wide and it seems silly to create huge textures in memory when it’s just made up of one smaller texture repeated and clipped.

Does anyone have any advice for me? Am I missing something obvious here, like maybe just setting the background to be a huge CCSprite that has GL_REPEAT in its texture options and clipping it somehow?

I’ve searched these forums for a few days now and haven’t really had a lot of luck.

Any help you could provide would be greatly appreciated!

July 23, 2010 at 5:52 am #291450

asinesio
Participant
@asinesio

Here’s an example of what I’m trying to do. Levels in my game are filled polygons of any size.

Free image hosting powered by PostImage.org

July 23, 2010 at 12:21 pm #291451

bradparks
Participant
@bradparks

i haven’t done anything like this, but remembered this old post where @rolando and @Riq were talking about it… and @Riq mentioned that distortion would be something that could b e worked out by modifying the texture coordinates….

http://www.cocos2d-iphone.org/forum/topic/2459

July 23, 2010 at 12:37 pm #291452

asinesio
Participant
@asinesio

@bradparks… Thank you.

It has to be with how I am doing the texture coordinates. I’ll take a closer look there.

If anyone else has advice, I’d love to hear it. :)

July 23, 2010 at 2:09 pm #291453

araker
Moderator
@araker

First of all, you need a triangle strip instead of a fan. A fan can only be used if a polygon has one central point, like a circle or a cone. Triangle strips need to be wind counter clockwise as far as I know. So in your case

GLfloat	 coordinates[] = {  _maxS,	_maxT,
0, _maxT,
_maxS, 0.0f,
0.0f, 0.0f };

Also make sure that your vertex coordinates have the same layout as your texture coordinates, else the texture will look twisted.

July 24, 2010 at 4:10 pm #291454

asinesio
Participant
@asinesio

@araker – thanks for the advice.

I’ve made some further progress. At a high level, here’s what I’m doing now:

1) Extend CCNode<CCTextureNode>

2) Split the polygon into triangles using the algorithm above.

3) In the setTexture method, configure the texture with GL_REPEAT.

4) Use the vertex coordinates as the texture coordinates.

5) Render everything using glDrawArrays(GL_TRIANGLES).

Now, the textures look right — they aren’t warped or stretched.

The issue I’m seeing, though, is that when the object moves (by the parent layer moving, causing the level to scroll) the texture starts moving and wiggling very rapidly.

I know it has to be something with the texture coordinates and the texture matrix, but nothing I’m doing seems to make any difference.

Here’s my draw method. areaTrianglePoints and textureCoordinates are copies of the same data (triangles).

-(void) draw {
glDisableClientState(GL_COLOR_ARRAY);
glBindTexture(GL_TEXTURE_2D, self.texture.name);
glMatrixMode(GL_TEXTURE); /* enter texture matrix mode */
glPushMatrix();
glLoadIdentity();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glVertexPointer(2, GL_FLOAT, 0, areaTrianglePoints);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates);
glDrawArrays(GL_TRIANGLES, 0, areaTrianglePointCount);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW); /* back to modelview mode */
glEnableClientState(GL_COLOR_ARRAY);

}

What am I missing? I’m so close I can taste it.

July 24, 2010 at 5:01 pm #291455

araker
Moderator
@araker

All the things you draw, are drawn in modelview, so remove the matrix mode lines. Since you don’t translate or rotate anything, pushing and popping isn’t necessary, remove those as well. Same goes for the load identity.

July 24, 2010 at 5:24 pm #291456

asinesio
Participant
@asinesio

@araker — thank you.

I’ve made those changes. It’s still showing the same behavior (the texture moves rapidly/wiggles when the level scrolls), which is consistent with what you’re saying.

Maybe I have to offset the texture coordinates by the amount the level scrolls?

That seems weird though.

July 24, 2010 at 6:14 pm #291457

araker
Moderator
@araker

If the texture looks good initially, you probably don’t have any texture coordinate problems anymore. I’m not sure about the offset, you could read this topic, it has a few good links about using GL_REPEAT.

July 26, 2010 at 5:19 am #291458

asinesio
Participant
@asinesio

Figured it out, and naturally, it stems from my noobishness of OpenGL texture coordinates.

You can’t just use the vertex points as the texture coordinates.

Instead I added a calculate function that divides the vertex points by the size of the texture.

Win.

-(void) calculateTextureCoordinates {
for (int j = 0; j < areaTrianglePointCount; j++) {
textureCoordinates[j] = ccpMult(areaTrianglePoints[j], 1.0f/texture.pixelsWide);
}
}

-(void) draw {
glBindTexture(GL_TEXTURE_2D, self.texture.name);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glVertexPointer(2, GL_FLOAT, 0, areaTrianglePoints);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates);

glDrawArrays(GL_TRIANGLES, 0, areaTrianglePointCount);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glEnableClientState(GL_COLOR_ARRAY);
}

Whew.

@araker — thanks for all your help. I think I would have given up a long time ago without it.

November 9, 2010 at 9:22 am #291459

Eladleb
Participant
@eladleb

Hi asinesio,

The draw and calc methond you provided worked perfectly for me!

Thanks for posting the solution.

Elad.

March 6, 2011 at 2:58 pm #291460

xspecial
@xspecial

@asinesio or @Eladleb, can you post the source please?

Thanks

March 25, 2011 at 1:18 am #291461

rpmobile
@rpmobile

I would also love to see any complete examples of this. Still trying to wrap my head around the various links.

Thanks in advance!

March 25, 2011 at 7:34 pm #291462

Eladleb
Participant
@eladleb

Hi guys.

I hope this little post will help you advance with your games:

There are a few steps to rendering a texture to a polygon:

1. Have the polygon x,y coords (easy).

2. Triangulate the polygon – In order to draw a texture, the graphics card need to have sets of triangles which will compose the complete texture.

This sounds tricky (and it is..) but Jhon W. Ratcliff has already done fantastic it for you:

Jhon W. Ratcliff

- It’s c++, it works with objective c under cocoa nicely. Add his files to your project.

This is a working method to use the triangulator (Don’t forget to create the triangulator in your init method):

((Triangulator*)triTriangles)->reset();

// Adding points to the polygon (from the normal coords you have)
for (int i = 0; i < nCurrNumOfPoints; ++i)
{
((Triangulator*)triTriangles)->addPoint(arrAllPoints.x, arrAllPoints.y, 0);
}

// Updating the global num of indices, later used in the draw method
indices = ((Triangulator*)triTriangles)->triangulate(tcount,1);

float f = 0;

// Getting the coords for each triangle the triagleator has found:
for (unsigned int j = 0; j < tcount * 3; ++j)
{
((Triangulator*)triTriangles)->getPoint(indices[j],arrAllTriangles[j].x , arrAllTriangles[j].y, f);
}

// Mapping the texture to the triangles (txtToLoad is a CCTexture2D):
for (unsigned int j = 0; j < tcount * 3; j++)
{
textureCoordinates[j] = ccpMult(CGPointMake(arrAllTriangles[j].x - LEFT_MARGIN,
(TOP_MARGIN - arrAllTriangles[j].y)) , 1.0f/txtToLoad.pixelsWide);
}

3. Call this function inside your draw method (This method works for me):

void ccFillPolyWithTexture( CGPoint *poli, int points, CCTexture2D* i, CGPoint* textureCoordinates)
{
// 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
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, i.name);
glVertexPointer(2, GL_FLOAT, 0, poli);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates);
glVertexPointer(2, GL_FLOAT, 0, poli);
glDrawArrays(GL_TRIANGLES, 0, points);

// Retrive the prev situation
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
}

This is a working example to call the above func:

ccFillPolyWithTexture(arrAllTriangles, tcount * 3, txtToLoad, textureCoordinates);

Good luck guys!

March 25, 2011 at 7:57 pm #291463

araker
Moderator
@araker

Thanks for sharing. A small remark, it isn’t necessary to enable the vertex, texture_coord array and texture_2d again after drawing, since they are already enabled.

March 26, 2011 at 2:59 am #291464

rpmobile
@rpmobile

Thanks so much to everyone for their help. The code samples work great!

April 4, 2011 at 10:14 am #291465

Soulghai
@soulghai

Hello.

This is not working for me.

Does someone have a working example?

April 5, 2011 at 3:28 am #291466

asinesio
Participant
@asinesio

@Soulghai You’re like the 100th person to ask about this; I didn’t think there would be this much demand for this code, so it hasn’t been working in awhile.

I’ll see if I can resurrect this little algorithm and get something working on GitHub. Feel free to PM me to remind me if I forget. :)

April 5, 2011 at 5:01 am #291467

asinesio
Participant
@asinesio

I went ahead and got this code working, and placed it out on github with a sample project. I’m calling the library “PRKit” for now.

https://github.com/asinesio/cocos2d-PRKit

Give it a try and let me know what you think.

April 5, 2011 at 12:37 pm #291468

Soulghai
@soulghai

Thank you very much! Everything works fine for me.

April 6, 2011 at 12:26 pm #291469

riq
Keymaster
@admin

@asinesio: Nice!

April 6, 2011 at 1:12 pm #291470

jptsetung
Participant
@jptsetung

Awesome, a great addition to the code snippets. Very useful in many occasions. Like generating objects procedurally for a Box2D game.

April 7, 2011 at 1:51 pm #291471

Olmeister
Participant
@olmeister

@asinesio I’ve downloaded your library.

I’ve got it running, but for some reason Im getting some weird behavior (convex & concave).

If i attempt to define anything more complicated than a triangle, I get strange renders.

A perfect box/square, (0,0)(100,0),(100,100),(0,100):

I get a triangle that takes up half of the square rendered well.

1/4 of the box is another triangle, rendered half, almost like an alpha transparency is applied. And the final 1/4 of the box is even harder to see, barely visible.

Help!

Thanks, Oliver.

April 7, 2011 at 8:00 pm #291472

Soulghai
@soulghai

Yes, I encountered the same problem with convex polygon. Any ideas?

April 11, 2011 at 11:26 am #291473

Olmeister
Participant
@olmeister

Bump, anyone?

Viewing 25 posts - 1 through 25 (of 67 total)

You must be logged in to reply to this topic.