tags:

views:

394

answers:

2

I am trying to make a few effects in a C+GL game. So far I draw all my sprites as a quad, and it works.

However, I am trying to make a large ring appear at times, with a texture following that ring, as it takes less memory than a quad with the ring texture inside. The type of ring I want to make is not a round-shaped GL mesh ring (the "tube" type) but a "paper" 2D ring. That way I can modify the "width" of the ring, getting more of the effect than a simple quad+ring texture. So far all my attempts have been...kind of ridiculous, as I don't understand GL's coordinates too well (and I can't really understand the available documentation...I am just a designer with no coder help or background. A n00b, basically).

glBegin(GL_POLYGON);
for(i = 0;i < 360; i += 10){
  glTexCoord2f(0, 0);
  glVertex2f(Cos(i)*(H-10),Sin(i)*H);
  glTexCoord2f(0, HP);
  glVertex2f(Sin(i)*(H-10),Cos(i)*(H-10));
  glTexCoord2f(WP, HP);
  glVertex2f(Cos(i)*H,Sin(i)*(H-10));
  glTexCoord2f(WP, 0);
  glVertex2f(Sin(i)*H,Cos(i)*H);
} 
glEnd();

This is my last attempt, and it seems to generate a "sunburst" from the right edge of the circle instead of a ring. It's an amusing effect but definitely not what I want. Other results included the circle looking exactly the same as the quad textured (aka drawing a sprite literally) or something that looked like a pop-art filter, by working on this train of thought.

Seems like my logic here is entirely flawed, so, what would be the easiest way to obtain such a ring? No need to reply in code, just some guidance for a non-math-skilled user...

Edit: A different way to word what I want, would be a sequence of rotated rectangles connected to each other, forming a low-resolution ring.

A: 

The post here on the OpenGL forums seems to do what you want. An overview of the approach:

If you want a circle filed with a texture, you can use triangle fan. First, draw the vertex at the center of the circle. Then draw the vertex on the contour of the circle, use cos(angle)*radius for x and sin(angle)*radius for y. Since texture coordinates s and t are in the range [0 1] => s = (cos(angle)+1.0)*0.5 and t = (sin(angle)+1.0)*0.5 . The texture coordinate for the vertex at the center of the circle is (0.5,0.5).

GLvoid draw_circle(const GLfloat radius,const GLuint num_vertex)
{
  GLfloat vertex[4]; 
  GLfloat texcoord[2];

  const GLfloat delta_angle = 2.0*M_PI/num_vertex;

  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D,texID);
  glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
  glBegin(GL_TRIANGLE_FAN);

  //draw the vertex at the center of the circle
  texcoord[0] = 0.5;
  texcoord[1] = 0.5;
  glTexCoord2fv(texcoord);

  vertex[0] = vertex[1] = vertex[2] = 0.0;
  vertex[3] = 1.0;        
  glVertex4fv(vertex);

  for(int i = 0; i < num_vertex ; i++)
  {
    texcoord[0] = (std::cos(delta_angle*i) + 1.0)*0.5;
    texcoord[1] = (std::sin(delta_angle*i) + 1.0)*0.5;
    glTexCoord2fv(texcoord);

    vertex[0] = std::cos(delta_angle*i) * radius;
    vertex[1] = std::sin(delta_angle*i) * radius;
    vertex[2] = 0.0;
    vertex[3] = 1.0;
    glVertex4fv(vertex);
  }

  texcoord[0] = (1.0 + 1.0)*0.5;
  texcoord[1] = (0.0 + 1.0)*0.5;
  glTexCoord2fv(texcoord);

  vertex[0] = 1.0 * radius;
  vertex[1] = 0.0 * radius;
  vertex[2] = 0.0;
  vertex[3] = 1.0;
  glVertex4fv(vertex);
  glEnd();

  glDisable(GL_TEXTURE_2D);

}
Gabriel Isenberg
Unfortunately, no, that draws the texture literally and is a circle (no chance to alter the ring's width, only its size). Also the texture is drawn "literally". I should point that the texture I am using is rectangular (like a lightning bolt) and not a literal ring. What I want to do is repeat the "lightning" several times in a line of variable width, giving the illusion of a ring.Maybe I should explain it like that on the question?
plonkplonk
More clarity is always a plus! :D
Gabriel Isenberg
+1  A: 

So you want an annulus? That is, the area between two circles with the same center but different radii? I'd try a quad strip like this:

glBegin(GL_QUAD_STRIP);
for(i = 0; i <= 360; i += 10){
  glTexCoord2f(WP*i/360, 0);
  glVertex2f(Cos(i)*(H-10),Sin(i)*(H-10));
  glTexCoord2f(WP*i/360, HP);
  glVertex2f(Cos(i)*H,Sin(i)*H);
} 
glEnd();

Each quad is a 10-degree sector of the ring. Note that if you want to draw N quads in a strip, it takes 2*(N+1) points, so we draw a total of 2*(36+1) = 74 points.

Derek Ledbetter
Yes! This is exactly what I want! Thank you very much!I can see my error with textures as well...thanks again, really!
plonkplonk