优化公式以从任意点创建三角形

时间:2012-06-25 07:32:11

标签: c# windows-phone-7 optimization xna

在我提出问题之前,我认为一些背景知识会有所帮助。我正在做的是在xna中创建我自己的小型2D物理库,尽管如此。这也是我的第一个独立的xna项目,也是我第一次使用3D工具,所以我可能会做一些古怪的事情。无论如何,我目前正在创建一个三角形类,其中构造函数以Vector2s的形式采用三个任意点。在构造函数中,我必须按顺时针顺序放置这些点(因此它们不会被剔除),然后找到它们应该对应的纹理坐标(因为我使用VertexPositionTextures作为我的顶点)。我有什么作品,但似乎很长很复杂。我正在寻找缩短/简化代码的方法,这就是:

public PTriangle(Vector2 a, Vector2 b, Vector2 c)
    : base()
{
    //set up vertices
    VertexPositionTexture[] vertices = new VertexPositionTexture[3];

        //center vertices around origin
    Vector2 center = new Vector2((a.X + b.X + c.X) / 3, (a.Y + b.Y + c.Y) / 3);
    Vector2 newA = a - center;
    Vector2 newB = b - center;
    Vector2 newC = c - center;

        //get angle of each vertex (clockwise from -x axis)
    double angleA = MathHelper.Pi - Math.Atan((double)(newA.Y / newA.X));
    double angleB = MathHelper.Pi - Math.Atan((double)(newB.Y / newB.X));
    double angleC = MathHelper.Pi - Math.Atan((double)(newC.Y / newC.X));
    if (newA.X < 0)
    {
        if (newA.Y < 0)
        {
            angleA += MathHelper.Pi;
        }
        else
        {
            angleA -= MathHelper.Pi;
        }
    }
    if (newB.X < 0)
    {
        if (newB.Y < 0)
        {
            angleB += MathHelper.Pi;
        }
        else
        {
             angleB -= MathHelper.Pi;
        }
    }
    if (newC.X < 0)
    {
        if (newC.Y < 0)
        {
            angleC += MathHelper.Pi;
        }
        else
        {
            angleC -= MathHelper.Pi;
        }
    }

        //order vertices by angle
    Vector2[] newVertices = new Vector2[3];
    if (angleA < angleB && angleA < angleC)
    {
        newVertices[0] = newA;
        if (angleB < angleC)
        {
            newVertices[1] = newB;
            newVertices[2] = newC;
        }
        else
        {
            newVertices[1] = newC;
            newVertices[2] = newB;
        }
    }
    else if (angleB < angleA && angleB < angleC)
    {
        newVertices[0] = newB;
        if (angleA < angleC)
        {
            newVertices[1] = newA;
            newVertices[2] = newC;
        }
        else
        {
            newVertices[1] = newC;
            newVertices[2] = newA;
        }
    }
    else
    {
        newVertices[0] = newC;
        if (angleA < angleB)
        {
            newVertices[1] = newA;
            newVertices[2] = newB;
        }
        else
        {
            newVertices[1] = newB;
            newVertices[2] = newA;
        }
    }

        //set positions of vertices
    vertices[0].Position = new Vector3(newVertices[0] + center, 0);
    vertices[1].Position = new Vector3(newVertices[1] + center, 0);
    vertices[2].Position = new Vector3(newVertices[2] + center, 0);

        //get width and height of triangle
    float minX = 0;
    float minY = 0;
    float maxX = 0;
    float maxY = 0;
    foreach (Vector2 vertex in newVertices)
    {
        if (vertex.X < minX)
        {
            minX = vertex.X;
        }
        else if (vertex.X > maxX)
        {
            maxX = vertex.X;
        }
        if (vertex.Y < minY)
        {
            minY = vertex.Y;
        }
        else if (vertex.Y > maxY)
        {
            maxY = vertex.Y;
        }
    }
    float width = maxX - minX;
    float height = maxY - minY;

        //shift triangle so fits in quadrant IV, and set texture coordinates
    for (int index = 0; index < newVertices.Length; ++index)
    {
        newVertices[index].X -= minX;
        newVertices[index].Y -= minY;

        vertices[index].TextureCoordinate = new Vector2(
            newVertices[index].X / width,
            1 - (newVertices[index].Y / height));
    }

    this.Vertices = vertices;

    //set up indices
    this.Indices = new short[] { 0, 1, 2 };
}

1 个答案:

答案 0 :(得分:4)

要按顺时针顺序放置3个点,可以使用逆时针测试(或左转测试)来检查3个点的方向。

来自Wikipedia

的伪代码
# Three points are a counter-clockwise turn if ccw > 0, clockwise if
# ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
# gives the signed area of the triangle formed by p1, p2 and p3.
function ccw(p1, p2, p3):
    return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)

如果3点是逆时针方向,你可以交换最后2点,使顺时针顺序为3点。