简体   繁体   English

XNA画一个圆圈

[英]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. 在XNA的另一个主题中, Callum Rogers编写了一些代码 ,用于创建一个带圆圈轮廓的纹理,但我正在尝试创建一个充满颜色的圆圈。 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;
}

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. 你有3D加速的原因。

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. x指向圆圈的边框。

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. 然后,顶点1,3和4将定义第二个多边形等。

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 ). 第一个角度为0°,以下为倍数(360°/ 圆圈点 )。 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. 根据圆上顶点的数量,您将获得不同的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.) (由于多边形需要绘制至少3个顶点,因此不可能有2个顶点。)
  • Total of 4 points (3 points on circle) will result in a triangle. 总共4个点(圆上3个点)将产生一个三角形。
  • Total of 5 points (4 point on circle) will result in a square. 总共5个点(圆上4个点)将产生一个正方形。
  • Total of 6 points (5 points on circle) will result in a pentagon 总共6分(圆上5分)将产生五角大楼
  • ... ...

Actually the XNA example for drawing primites show how to draw a circle (or n-gon) using a triangle fan. 实际上,绘制图像XNA示例显示了如何使用三角形扇形绘制圆(或n-gon)。

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. 在您的2D纹理方法中,添加以下代码以填充圆圈。 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 : 因此,在CreateCircle(int radius)方法中,在创建轮廓后添加以下代码:

        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;

If you need to do it from scratch (though I'm guessing there are easier ways), change the way you perform the rendering. 如果您需要从头开始(尽管我猜测有更简单的方法),请更改执行渲染的方式。 Instead of iterating through angles and plotting pixels, iterate through pixels and determine where they are relative to the circle. 而不是迭代角度和绘制像素,迭代像素并确定它们相对于圆的位置。 If they are <R , draw as fill color. 如果它们是<R ,则绘制为填充颜色。 If they are ~= R , draw as border color. 如果它们是~= R ,则绘制为边框颜色。

I know that I'm a little late, but I modified your code to fill in the center 我知道我有点晚了,但我修改了你的代码以填补中心

public static Texture2D CreateCircle(GraphicsDevice importedGraphicsDevice, int radius)
    {
        int outerRadius = radius * 2 + 2; // So circle doesn't go out of bounds
        Texture2D texture = new Texture2D(importedGraphicsDevice, 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;
        }

                    //width
        for (int i = 0; i < outerRadius; i++)
        {
            int yStart = -1;
            int yEnd = -1;


            //loop through height to find start and end to fill
            for (int j = 0; j < outerRadius; j++)
            {

                if (yStart == -1)
                {
                    if (j == outerRadius - 1)
                    {
                        //last row so there is no row below to compare to
                        break;
                    }

                    //start is indicated by Color followed by Transparent
                    if (data[i + (j * outerRadius)] == Color.White && data[i + ((j + 1) * outerRadius)] == Color.Transparent)
                    {
                        yStart = j + 1;
                        continue;
                    }
                }
                else if (data[i + (j * outerRadius)] == Color.White)
                {
                    yEnd = j;
                    break;
                }
            }

            //if we found a valid start and end position
            if (yStart != -1 && yEnd != -1)
            {
                //height
                for (int j = yStart; j < yEnd; j++)
                {
                    data[i + (j * outerRadius)] = new Color(10, 10, 10, 10);
                }
            }
        }

        texture.SetData(data);
        return texture;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM