Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XNA Draw a filled circle

In another thread on XNA, Callum Rogers wrote some code which creates a texture with the outline of a circle, but I'm trying to create a circle filled with a color. What I have to modify on this code to fill the circle with color?

public Texture2D CreateCircle(int radius)
{
    int outerRadius = radius*2 + 2; // So circle doesn't go out of bounds
    Texture2D texture = new Texture2D(GraphicsDevice, outerRadius, outerRadius);

    Color[] data = new Color[outerRadius * outerRadius];

    // Colour the entire texture transparent first.
    for (int i = 0; i < data.Length; i++)
        data[i] = Color.Transparent;

    // Work out the minimum step necessary using trigonometry + sine approximation.
    double angleStep = 1f/radius;

    for (double angle = 0; angle < Math.PI*2; angle += angleStep)
    {
        // Use the parametric definition of a circle: http://en.wikipedia.org/wiki/Circle#Cartesian_coordinates
        int x = (int)Math.Round(radius + radius * Math.Cos(angle));
        int y = (int)Math.Round(radius + radius * Math.Sin(angle));

        data[y * outerRadius + x + 1] = Color.White;
    }

    texture.SetData(data);
    return texture;
}
like image 320
programad Avatar asked Mar 19 '26 21:03

programad


2 Answers

Don't use a texture for stuff like this (especially for things being in one single color!) - also don't try to do it pixel by pixel. You've got 3D acceleration for a reason.

Just draw the circle similar to a pie using a triangle fan. You'll need the following vertices.

  • Center of the circle
  • x points on the circle's border.

The first two points will define a line between the center of the circle and its border. The third vertex will define the first polygon. Vertices 1, 3 and 4 will then define the second polygon, etc.

To get the points on the circle's border use the formulas from your example. The first angle will be 0°, the following ones multiples of (360° / points on circle). To get a full circle you'll need one additional point that matches the second point (the first point on the border).

Depending on the number of vertices on the circle you'll get different n-gons. The more vertices you use the rounder the shape will look (at some performance cost):

  • (Less than 2 vertices aren't possible as a polygon requires at least 3 vertices to be drawn.)
  • Total of 4 points (3 points on circle) will result in a triangle.
  • Total of 5 points (4 point on circle) will result in a square.
  • Total of 6 points (5 points on circle) will result in a pentagon
  • ...

Actually the XNA example for drawing primites show how to draw a circle (or n-gon) using a triangle fan.

like image 180
Mario Avatar answered Mar 21 '26 13:03

Mario


well for anyone who wants to do it pixel by pixel ... i made a solution based on the information given. In your 2d texture method add the following code to fill the circle. I'm making a game and wanted to be able to make circles different colors and sizes. So inside CreateCircle(int radius) method, add the following code after the outline has been created :

        bool finished = false;
        int firstSkip = 0;
        int lastSkip = 0;
        for (int i = 0; i <= data.Length - 1; i++)
        {
            if (finished == false)
            {
                //T = transparent W = White;
                //Find the First Batch of Colors TTTTWWWTTTT The top of the circle
                if ((data[i] == Color.White) && (firstSkip == 0))
                {
                    while (data[i + 1] == Color.White)
                    {
                        i++;
                    }
                    firstSkip = 1;
                    i++;
                }
                //Now Start Filling                       TTTTTTTTWWTTTTTTTT
                //circle in Between                       TTTTTTW--->WTTTTTT
                //transaparent blancks                    TTTTTWW--->WWTTTTT
                //                                        TTTTTTW--->WTTTTTT
                //                                        TTTTTTTTWWTTTTTTTT
                if (firstSkip == 1)
                {
                    if (data[i] == Color.White && data[i + 1] != Color.White)
                    {
                        i++;
                        while (data[i] != Color.White)
                        {
                                //Loop to check if its the last row of pixels
                                //We need to check this because of the 
                                //int outerRadius = radius * 2 + -->'2'<--;
                                for (int j = 1; j <= outerRadius; j++)
                                {
                                    if (data[i + j] != Color.White)
                                    {
                                        lastSkip++;
                                    }
                                }
                                //If its the last line of pixels, end drawing
                                if (lastSkip == outerRadius)
                                {
                                    break;
                                    finished = true;
                                }
                                else
                                {
                                    data[i] = Color.White;
                                    i++;
                                    lastSkip = 0;
                                }
                            }
                        while (data[i] == Color.White)
                        {
                            i++;
                        }
                        i--;
                    }


                }
            }
        }
        // Set the data when finished 
        //-- don't need to paste this part, already given up above
        texture.SetData(data);
        return texture;
like image 45
user1089284 Avatar answered Mar 21 '26 15:03

user1089284



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!