My circle is not entirely round

Hi,

i want to draw a circle using vertices. I am almost done but I cant figure out why it is not finishing the circle properly.

`
public static void DrawCircle(this SpriteBatch batch, float radius, Color color, ref Matrix transformMatrix)
{
var vertices = new List();
for(int i = 0; i < 360; i++)
{
var heading = MathHelper.ToRadians(i);

            vertices.Add(new VertexPositionColor(new Vector3((float)Math.Cos(heading) * radius, (float)Math.Sin(heading) * radius, 0f), color));
        }

        var effect = new BasicEffect(batch.GraphicsDevice);

        effect.View = transformMatrix;
        effect.Projection = Matrix.CreateOrthographicOffCenter(0, batch.GraphicsDevice.Viewport.Width, batch.GraphicsDevice.Viewport.Height, 0, 0, -1);

        foreach(var pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();

            batch.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineStrip, vertices.ToArray(), 0, vertices.Count -1);
        }
    }

`

This is the result, as you can see on the right side there is a little bit missing.
image

try:

vertices.add(vertices[0]);
var effect = new BasicEffect(batch.GraphicsDevice);

or

i<= 360

The <= change should work because you need that first vertex twice, and 360 degrees is the same as 0 degrees.

Yep the <= worked. Thanks :slight_smile:

@johmarjac
If I may propose something, you can get much better performance by using a quaternion or a complex number.
First calculate a quaternion/complex of one degree and a vector of UnitX * radius.
then inside the for loop rotate the vector by the quaternion/complex on each step.
Here is how I draw my debug circles:

in your case it will be simpler because you are using a LineStrip.
you can try something like this:

Complex rotation = Complex.FromAngle((float)(Math.PI * 2.0 / 360)); // sin,cos here…
Vector2 hand = new Vector2(radius, 0);
for(int i = 0; i <= 360; i++)
{
hand = Complex.Multiply(ref hand, ref rotation); // only multiplications here…
vertices.Add(new VertexPositionColor(new Vector3(hand, 0f), color));
}

2 Likes

Thank you,

I am very new to all this kind of stuff, I am not known to using Quaternions or Complexes, but I am going to have a look because I just noticed that my frame rate dropped by 30 when creating only 200 circles… thats odd. :smiley:

Same here. There’s a test that draws 450 circles and the old code with Cos/Sin was taking more
time to draw than the actual benchmark.

You can get the Complex class from my github from the link above,
or you can use the Quaternion class of monogame in a similar manner with some minor changes.
The quaternion.transform will do a couple more multiplication that you don’t really need in 2D but I bet it’s still faster than calling sin/cos on each step.

In a previous project many years ago, I adjusted the step angle based on the radius of the circle. Smaller circles needed fewer steps to maintain a smooth circular shape, whereas larger circles needed smaller step angles to produce more line segments to maintain the smooth shape. It was still far less than fixed 360 lines you are using for each circle, no matter the radius.

1 Like