Reputation: 657
I think a little background will help before I get into my question. What I'm doing is creating my own small 2D physics library in xna, for fun nonetheless. This is also my first independent xna project, and my first time working with the 3D tools, so I may be doing things all wacky. Anyway, I'm currently making a triangle class in which the constructor takes three arbitrary points in the form of Vector2s
. In the constructor I have to put these points in clockwise order (so they're not culled) and then find the texture coordinates they should correspond to (since I'm using VertexPositionTextures
as my vertices). What I've got works, but it seems very long and complicated. I'm looking for any ways to shorten/simplify the code, which is this:
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 };
}
Upvotes: 0
Views: 454
Reputation: 56809
To put the 3 points in clockwise order, you can use counter-clockwise test (or left-turn test) to check the direction of the 3 points.
Pseudocode from 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)
If the 3 points are counter-clockwise, you can just swap the last 2 points to make the 3 points clockwise order.
Upvotes: 4