Draw Ellipse in OpenGL

Started by
8 comments, last by PGmeiner 22 years, 4 months ago
How can I draw circles and ellipses in OpenGL. I has tried with cosinus and sinus-calculation but the circle looks to chopped and not very smooth. Does anyone know a method to do this? Thanks Peter Gmeiner
Peter Gmeiner
Advertisement
You have the right approach using sin() and cos(). You should take note of two things:

1) the parameters to sin() and cos() are radians, not degrees. The entire circle has a range of 2*PI radians, roughly 6.28, and not 360. If you were passing in increments of 360 then that would explain the choppiness.

2) Try using more increments. For example, try using 100 angle increments, each sized 2*PI/99, instead of fewer increments. A circle drawn with 20 increments will look choppier than a circle drawn with 100.

3) If you are bothered by stair-stepping around the circle---where you can see the individual pixel steps, then you''re really worried about an aliasing problem and it has nothing to do with the circle itself. You will have to go to the OpenGL graphics forum to ask about antialiased lines.

Hope this helps!
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
float x, y,z;
for(float i = 0; i < 360; i=i+0.1)
{
x = sin(i);
y = cos(i);
z = 0;
glVertex3f(x,y,z);
}

This should work.

I came, I saw, I got programmers block.
~V''''lion
~V'lionBugle4d
Vlion,

Quick correction. You need to convert your angle parameter i into radians when you call sin(i) and cos(i). Otherwise, your circle is likely to look ragged, with no symmetry and with a border that is not a single line/curve. (I''m sure you knew this and were just careless, .)

Also, you''re fragmenting the circle into 3,600 pieces. That''s probably overkill, for two reasons. First, depending on the projected screen size of the circle, there may not be 3,600 pixels and there is no reason to draw more line segments than there are pixels in the circle. Second, if PGmeiner desires to draw many circles, or many other things, in real-time, then sacrificing a bit of smoothness for performance is acceptable.

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
A different approach might be to draw a quad and map a texture of cirle on it that is transparent except for the outline of the cirlce, ofcours you still have to scale your quad to the right size and rotate it to face the proper direction. I just thought this out, i''m sure it would work, but as to if it is faster than computing sin, cos method...i''m not sure what do you guys think?

Circle::drawCircle(int width, int height, Vector normal)
{
enableBlending;
translate(circleCenter.x, circleCenter.y, CircleCenter.z)
scale(width,height,1)
rotateToFace(normal)
drawQuad() //this draw the quad of base size
}

Or if your using transforamtions:

Circle::drawCircle(int width, int height, Vector normal)
{
enableBlending;

t= constructTransformationWithThatWillScale
to (Width, Height, 1)lookInDiractionNormal And
translateTo (circleCenter); //You really only need to
//compute this once
modelViewStack * t;
drawQuad();
};
The texture mapped polygon certainly would work. You actually don''t need a quad. A triangle will do. And it should be quite a lot faster than the line segment approach. (Actually, to be efficient, you wouldn''t want to calculate the sin''s and cos''s every time you draw the circle anyway---precompute it and store away for reuse.)

The benefit of the texture map approach is the faster drawing and the fact that you can have a pixel-perfect circle. The problem is that the circle is pixel perfect in the texture, not onscreen. If the texture resolution is not high enough, the circle may not look good. Also, if you wanted the circle to be drawn like a wire---needing an alpha layer---you may get shimmering effects around the boundary that look poor when the circle is moving relative to the camera.

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
Actually, grhodes, I meant what I said.

This is a actual routine I used.
Now, when I have it vary the color according to point number,
it shows a very interesting pattern.
It appears go through a very broken ellipse,
then after a number starts another ellipse, only rotated abit along the first ellipse, then after a numtiple of the number, rotates some more, to make a decent-looking ellipse.
So if you GL_LINE it, it looks terrible.

Anyway, it only looks good in points.

//Draws a ellpise made out of points.void DrawEllipse(){       glColor3f(1,1,1);	float x,y,z,;	int t;        glBegin(GL_POINTS);        for(t = 0; t <= 360; t +=1)	{          x = 5*sin(t);	  y = 4*cos(t);	  z = 0;	 glVertex3f(x,y,z);       }       glEnd();} 


If you do GL_LINE it, you can use it like as a ring for a planet.
It would probably look really ringy if you setup AA.

I came, I saw, I got programmers block.
~V''lion

Edited by - Vlion on December 6, 2001 3:27:34 PM
~V'lionBugle4d
quote:Original post by Vlion
Actually, grhodes, I meant what I said.


Okay, cool. So sounds like you get a good-looking, smooth ellipse with a thick border? How does this look on different graphics boards? I believe different boards may render GL_POINT different than others, and GL_POINT would certainly look different if you enable or disable GL_POINT_SMOOTH... Point size would also seem to change the appearance.

Have you compared this using GL_LINE with a circle done using radians, and the glLineWidth() command to set the border thickness > 1? I admire the ingenious use of degrees passed to sin/cos to get a nice visual effect, but the performance would still seem to be an issue...

.



Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
Parameterize the equations and use a GL_LINE_LOOP for lords sake that is the best way to do it. Here is the code with the parameterized equations.

case UNFILLED:
glBegin(GL_LINE_LOOP);
for(t = 0; t <= TWOPI; t += TWOPI/n)
glVertex2f(W * cos(t) + (float)Elip->GetPos(0).x, H * sin(t) + (float)Elip->GetPos(0).y);
glEnd();
break;
case FILLED:
glBegin(GL_POLYGON);
for(t = 0; t <= TWOPI; t += TWOPI/n)
glVertex2f(W * cos(t) + (float)Elip->GetPos(0).x, H * sin(t) + (float)Elip->GetPos(0).y);
glEnd();
break;

where H is your height and W is the width... set these two equal and you have a circle =]
nice efficient and versitile. Just how i like it


NULL
NULL
Well, basically, its a collection of points.
What controls the togetherness is the increment in the for loop.
so if I have it t+= 1, it is a ellipise visibly made out of points. If I have it t+=0.1, I have it much more together.

Now, if my algorithim has a GL_LINE, and a t += 1, a ring effect ensues. If you think Saturn`s rings, you will get the idea.

Its not really that pretty right now.

To see what I mean, the best way would be to drop my routine into a program and testbed it.

I came, I saw, I got programmers block.
~V''''lion
~V'lionBugle4d

This topic is closed to new replies.

Advertisement