Saturday, March 01, 2008

XNA Line Thickness

I've been searching for a method to display a thick line in XNA. There isn't a method in XNA as OpenGL's glLineWidth. So you have to construct you own line from triangles. I've found and tried this method. The line were rounded at each edge, and the whole scene looked pretty impressive. The problem was that my application had to render thousands of lines, and doing rounded edges and indexed triangles wasn't very performant. I wanted something much more simple, without rounded edges, but considering line joints. I developed a really simple and performant method to do this. The idea was to take a line strip (the array of Vector3[]) and build a triangle strip, which is the most performant method for rendering, and store it in a vertex buffer. This method is almost as performant as drawing simple lines!
I think that the code is pretty self explaining:

triangleCount =-2;
private List<VertexPositionColor> GetTriangleStrip(Vector3[] points, float thickness)
{
Vector3 lastPoint = Vector3.Zero;
List<VertexPositionColor> list = new List&ltVertexPositionColor>();
for (int i=0;i<points.Length;i++)
{
if (i == 0) { lastPoint = points[i]; continue; }
//the direction of the current line
Vector3 direction = lastPoint - points[i];
direction.Normalize();
//the perpendiculat to the current line
Vector3 normal = Vector3.Cross(direction, Vector3.UnitZ);
normal.Normalize();
Vector3 p1 = lastPoint + normal * thickness; triangleCount++;
Vector3 p2 = lastPoint - normal * thickness; triangleCount++;
Vector3 p3 = points[i] + normal * thickness; triangleCount++;
Vector3 p4 = points[i] - normal * thickness; triangleCount++;
list.Add(new VertexPositionColor(p1, Color.Black));
list.Add(new VertexPositionColor(p2, Color.Black));
list.Add(new VertexPositionColor(p3, Color.Black));
list.Add(new VertexPositionColor(p4, Color.Black));
lastPoint = points[i];
}
return list;
}
Then you just have to store the list in a vertex buffer and render it as a triangle strip with "triangleCount" primirives.

4 comments:

Matt Bettcher said...

Great technique. I would like to add one small observation if I may - to achieve a closed line you must either have the first and last vertex the same or add some code to create the last segment on the line.

Unknown said...

Hi Mihai Ciureanu ,
your method is very nice .. but i am unable to impliment it with my BoundingBox edges , right now i have indices of my Box and using
graphicsDevice.DrawUserIndexedPrimitives(
PrimitiveType.LineList,
verts,
0,
8,
indices,
0,
indices.Length / 2);
to render it.

could you please tell me how to impliment it in this case .

code will be more helpfull to me

much thanks
Raj

Ruirize said...

Performant is not a word.

Anonymous said...

My brother suggested I may like this website. He used to be totally right.
This submit truly made my day. You can not
imagine simply how a lot time I had spent for this info!
Thank you!

Feel free to visit my website :: best diet plans for women