OpenGL How to draw an approximate circle?

This topic is 4519 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hi, I am doing an exercise from the book "Beginning OpenGL Game Programming" by Dave Astle and Kevin Hawkins. The question asked to write a function to draw a 2D circle approximation. The origin starts at 0,0,0. The function has to accept the radius and the number of edges. Below is how I wrote the function. But when I ran it, there's only a straight white line appearing across the window, instead of an approximate circle. void DrawCircleApproximation(float radius, int numberOfSides, bool edgeOnly) { int i; double angle; if(edgeOnly) glBegin(GL_LINE_STRIP); else glBegin(GL_POLYGON); for(i = 0;i < numberOfSides;i++) { angle = (i * 2 * 3.142) / numberOfSides; glVertex3f(cosf(angle)*radius,0.0, sinf(angle)*radius); } if(edgeOnly) glVertex3f(radius,0.0,0.0); glEnd(); } What is wrong with the code above? I checked the code with the answer given in the book and they are similar.

Share on other sites
Your circle is being drawn on the XZ plane. OpenGL looks down the negative Z axis, so you're looking at the side of your circle. Try changing

to

Of course you'll have to glTranslatef with a negative z or do something comparable to move your circle past your near clip plane.

Share on other sites
I don't really like the looks of this line

angle = (i * 2 * 3.142) / numberOfSides;

too many ints, and angle is a double. I bet if you stepped through that for loop and checked angle you might get some strange values. The book does something more like this.

angle = (float)i * 2.0 * 3.142 / numberOfSides;

I've run into problems myself with creating angles based on for loop ints and have had my angles all being rounded off to the same int for the whole loop.

Share on other sites
Quote:
 Original post by Disgruntled GamerI don't really like the looks of this lineangle = (i * 2 * 3.142) / numberOfSides;too many ints, and angle is a double. I bet if you stepped through that for loop and checked angle you might get some strange values. The book does something more like this.angle = (float)i * 2.0 * 3.142 / numberOfSides;I've run into problems myself with creating angles based on for loop ints and have had my angles all being rounded off to the same int for the whole loop.

Mmm. I'm not saying you shouldn't code with precision but this is, in my opinion, too picky. It's basically just a rewrite of something that works perfectly well. Why would you go and do that for? (Besides, I tust that the compiler will clean it up for you..)

Share on other sites
Quote:
 Original post by Disgruntled GamerI don't really like the looks of this lineangle = (i * 2 * 3.142) / numberOfSides;too many ints, and angle is a double. I bet if you stepped through that for loop and checked angle you might get some strange values. The book does something more like this.angle = (float)i * 2.0 * 3.142 / numberOfSides;I've run into problems myself with creating angles based on for loop ints and have had my angles all being rounded off to the same int for the whole loop.

Actually, the x86 architecture has a dedicated opcode that performs multiplication of int and double, resulting in a double value (same for division IIRC). This might be even more efficient than a cast. If you really worry about such things, you could use some very basic maths to improve the above calculation a lot by removing redundancy:
int i;/* glVertex3f uses float arguments! */float deltaAngle = 2.0f * PI / (numberOfSides + 0.0f); /* added float conversion */float angle = 0.0f;/* accumulate angle instead of discarding the previously calculated result on each iteration */for( i = 0; i < numberOfSides; ++i, angle += deltaAngle ){    /* essentially the same as using cosf,sinf :) - NB: both sinf and cosf return float as well */    glVertex3f( sinf(angle + PI*0.5f) * radius, 0.0f, sinf(angle) * radius );}/* close the line-strip - cos(0) => 1, sin(0) => 0 */glVertex3f( radius, 0.0f, 0.0f );

Cheers,
Pat.

Share on other sites
Quote:
 Original post by Disgruntled GamerI don't really like the looks of this lineangle = (i * 2 * 3.142) / numberOfSides;too many ints, and angle is a double. I bet if you stepped through that for loop and checked angle you might get some strange values. The book does something more like this.angle = (float)i * 2.0 * 3.142 / numberOfSides;I've run into problems myself with creating angles based on for loop ints and have had my angles all being rounded off to the same int for the whole loop.

Actually I think he wants
angle = (i * 2 * 3.142) / (double) numberOfSides;
to prevent integer division.

Share on other sites
Quote:
Original post by deavik
Quote:
 Original post by Disgruntled GamerI don't really like the looks of this lineangle = (i * 2 * 3.142) / numberOfSides;too many ints, and angle is a double. I bet if you stepped through that for loop and checked angle you might get some strange values. The book does something more like this.angle = (float)i * 2.0 * 3.142 / numberOfSides;I've run into problems myself with creating angles based on for loop ints and have had my angles all being rounded off to the same int for the whole loop.

Actually I think he wants
angle = (i * 2 * 3.142) / (double) numberOfSides;
to prevent integer division.

As there's no problem with integer division in his original code, the extra cast is, although not wrong, unecessary.

Share on other sites
Quote:
 Original post by Disgruntled GamerI don't really like the looks of this lineangle = (i * 2 * 3.142) / numberOfSides;too many ints, and angle is a double. I bet if you stepped through that for loop and checked angle you might get some strange values. The book does something more like this.angle = (float)i * 2.0 * 3.142 / numberOfSides;I've run into problems myself with creating angles based on for loop ints and have had my angles all being rounded off to the same int for the whole loop.

There's nothing wrong with it.
a = i * 2;             // int = int * int (fine so long as you don't get overflow)b = a * 3.142;         // double = int * double (fine, compiler promotes int to double for calculation)c = b / numberOfSides; // double = double / int (again, compiler promotes int to double)

Share on other sites
Ok ok, I'm sorry, my float cast does nothing. It was done more out of stupidity than pickyness though. Here's a problem I had with ints and floats and why I tend to be a little too specific when I write out equations.

int n_stacks = 30;float scale_factor;for (int i=0;i<n_stacks;i++){        v = (PI / 2.0) - (PI * (i / n_stacks)); // bugged// casting either int to a float fixes the problem.	scale_factor = i / (float)n_stacks;	v = (PI / 2.0) - (PI * scale_factor); // works}

But in Wengs case his order of operations didn't cause the problem. Sorry if I caused any confusion, thanks for the feedback.

Share on other sites
Thanks guys for the replies, I have tried them out but the problem remains.

I also tried casting the integer variables to floats and the same thing happened.

I've also tried using glVertex2f instead of 3f but the problem remained the same.

Below is how I called the DrawCircleApproximationFunction.

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
return TRUE;
}

The first argument of the function is the radius. The second argument is the number of sides while the third argument determines whether to use GL_POLYGONS or GL_LINESTRIPS.

Is there anything wrong with the function calling?

1. 1
Rutin
32
2. 2
3. 3
4. 4
5. 5

• 13
• 9
• 9
• 9
• 14
• Forum Statistics

• Total Topics
633326
• Total Posts
3011373
• Who's Online (See full list)

There are no registered users currently online

×