So I've spent a few hours on the forums and experimenting. It seems that in SFML2, the general consensus is that if you want to draw lines, pass a vertex array to draw(). And if you want to draw lines with thickness, use rotated rectangles.
I think using rotated rectangles is bad for several reasons.
- If someone is drawing a large graph (which is what I'm doing), then using vertex arrays makes it very easy. But if I want these lines to have thickness, then I have to come up with a completely different method of drawing them since I can no longer simply pass my vertex array to draw().
- To draw a rotated rectangle to represent a line with thickness (assuming you're drawing a line between two points) requires a call to atan2 (to get the angle) and sqrt (to get the distance between points which will be the length of the rectangle). You also have to adjust the position of the rectangle slightly so the the starting point is not on the corner of the rectangle, but rather the middle of one end.
- Let's look at the large graph drawing case again. Most likely, the graph is stored as nodes with adjacency lists of some sort. In other words, there are no edge objects at all. So to have the lines drawn with thickness, there are two things the programmer can do: (1) The programmer can create and store somewhere edge objects for every pair of connected nodes so that these edge objects (rotated rectangles) are ready for drawing (angle and size are set upon creation and updated whenever a node is moved). (2) Create all the edges temporarily during the draw. The first way requires keeping track of more objects while the second way is slower because the size and angle of the rectangles must be calculated for all pairs of nodes every loop even if the nodes haven't moved.
If the draw() function could take a vertex array and a thickness, that would make things much cleaner and faster.
Here is what I've been using (ht = half thickness; n1/n2 = node 1/2)
float dx = n2->x - n1->x;
float dy = n2->y - n1->y;
float rot = atan2(dy, dx) * RADTODEG;
rect.setSize(sf::Vector2f(std::sqrt(std::abs(dx)*std::abs(dx) + std::abs(dy)*std::abs(dy)), ht*2));
rect.setOrigin(0, ht);
rect.setPosition(n1->x, n1->y);
rect.setRotation(rot);
This code must be run whenever a node in an edge is moved (which is a lot since I'm building a graph editor for creating a navigation mesh).
It just seems strange that if a user wants a line with adjustable thickness (a pretty reasonable request), that this graphics package makes them basically hack it out themselves.
Finally, OpenGL has function calls for drawing lines with thickness:
glLineWidth(width);
glBegin(GL_LINES);
glVertex2i(x1, y1);
glVertex2i(x2, y2);
glEnd();
I figure somewhere you're calling these OpenGL functions when you draw vertex arrays. So why not just allow thickness as well? I've read several threads where people discuss problems with how their particular implementation of lines with thickness behave (since everybody does it themselves, all slightly differently). But OpenGL's documentation suggests glLineWidth plays very nicely in different situations, including with and without anti-aliasing:
http://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml