3 replies to this topic

Posted 13 November 2012 - 09:02 PM

I wasn't sure whether this should go in the Math/Physics area, or here (Graphics).

I am working on a game at the moment, a 2D driving game in C using SDL2 (just pretend I'm using SDL if you aren't familiar with SDL2). At the beginning of the game, it generates a world by creating and connecting nodes in a way that resembles (kind of) roads and intersections. For testing, I am drawing a line between connected nodes, however, nobody wants to drive around on thin black lines, we want to drive on roads. So, I created an image or a road segment.

What I want to do it draw that image along the lines connecting the nodes. There are many lines, so I want to only draw images on the segments which intersect the view. I've been pondering this issue for some time, and I just can't think of an efficient solution, only brute force solutions, which would involve lots of math happening each step, which will be certain to slow things down. So far I haven't actually tried to implement anything yet since the few ideas I have suck.

Any ideas?

Question summary:

if I have a line from node[0].coord to node[1].coord how can I determine the correct places to draw a series of images on top of the line such that the entire line is covered and images touch each other at the ends? (image is only about 64x64, but line will be at least 500 pixels long)

I am working on a game at the moment, a 2D driving game in C using SDL2 (just pretend I'm using SDL if you aren't familiar with SDL2). At the beginning of the game, it generates a world by creating and connecting nodes in a way that resembles (kind of) roads and intersections. For testing, I am drawing a line between connected nodes, however, nobody wants to drive around on thin black lines, we want to drive on roads. So, I created an image or a road segment.

What I want to do it draw that image along the lines connecting the nodes. There are many lines, so I want to only draw images on the segments which intersect the view. I've been pondering this issue for some time, and I just can't think of an efficient solution, only brute force solutions, which would involve lots of math happening each step, which will be certain to slow things down. So far I haven't actually tried to implement anything yet since the few ideas I have suck.

Any ideas?

Question summary:

if I have a line from node[0].coord to node[1].coord how can I determine the correct places to draw a series of images on top of the line such that the entire line is covered and images touch each other at the ends? (image is only about 64x64, but line will be at least 500 pixels long)

Posted 13 November 2012 - 09:38 PM

I have a suspicion that anything reasonable that you do will be plenty fast enough.

The standard/obvious thing to do would be to convert your line segments to quads ahead of time, store them in some kind of spatial data structure (e.g., quad- or KD- tree, regular grid, or just arrays sorted by x and y position), do a conservative cull against your view box, and then and draw what's left with hardware texture mapping if available.

The line-segment--to-quad math, by the way, is pretty cheap. If you have a line from p1 to p2, then the tangent to the line is T=normalize(p2-p1), and the normal is N=J T, where J is the 90-degree rotation matrix (it exchanges the x and y coordinates and flips the sign of one). Then, if the road width is w, and if we define an "offset vector" by d = 0.5 w N, then you can just write the vertices as p1 + d, p1 - d, p2 + d, and p2 - d.

Back to spatial data structures: The only other thing that springs to mind is to exploit temporal coherence and the fact that your world is a graph, by storing neighbor/linkage information in the line segments, maintaining a list of the edges currently intersecting the edge of the view box, and, each frame, only doing intersection tests with those edges and their neighbors, to determine which of these line segments are entering or leaving the view. The assumption this would make is that you can never move more than the length of an edge in a frame. This is probably the fastest method, but also the least flexible, and, since you could probably get away with brute-forcing this, I can't really recommend it, even if it is the most amusing.

The standard/obvious thing to do would be to convert your line segments to quads ahead of time, store them in some kind of spatial data structure (e.g., quad- or KD- tree, regular grid, or just arrays sorted by x and y position), do a conservative cull against your view box, and then and draw what's left with hardware texture mapping if available.

The line-segment--to-quad math, by the way, is pretty cheap. If you have a line from p1 to p2, then the tangent to the line is T=normalize(p2-p1), and the normal is N=J T, where J is the 90-degree rotation matrix (it exchanges the x and y coordinates and flips the sign of one). Then, if the road width is w, and if we define an "offset vector" by d = 0.5 w N, then you can just write the vertices as p1 + d, p1 - d, p2 + d, and p2 - d.

Back to spatial data structures: The only other thing that springs to mind is to exploit temporal coherence and the fact that your world is a graph, by storing neighbor/linkage information in the line segments, maintaining a list of the edges currently intersecting the edge of the view box, and, each frame, only doing intersection tests with those edges and their neighbors, to determine which of these line segments are entering or leaving the view. The assumption this would make is that you can never move more than the length of an edge in a frame. This is probably the fastest method, but also the least flexible, and, since you could probably get away with brute-forcing this, I can't really recommend it, even if it is the most amusing.

Posted 14 November 2012 - 11:28 PM

I have a suspicion that anything reasonable that you do will be plenty fast enough.

The standard/obvious thing to do would be to convert your line segments to quads ahead of time, store them in some kind of spatial data structure (e.g., quad- or KD- tree, regular grid, or just arrays sorted by x and y position), do a conservative cull against your view box, and then and draw what's left with hardware texture mapping if available.

The line-segment--to-quad math, by the way, is pretty cheap. If you have a line from p1 to p2, then the tangent to the line is T=normalize(p2-p1), and the normal is N=J T, where J is the 90-degree rotation matrix (it exchanges the x and y coordinates and flips the sign of one). Then, if the road width is w, and if we define an "offset vector" by d = 0.5 w N, then you can just write the vertices as p1 + d, p1 - d, p2 + d, and p2 - d.

Great thanks, that was pretty much exactly what I wanted to hear.

Basically all I need to do is store normal or offset vectors in the node structure along with the node links. Seems easy enough. I'll try to get something implemented on the subway on the way to work :-P.

Back to spatial data structures: The only other thing that springs to mind is to exploit temporal coherence and the fact that your world is a graph, by storing neighbor/linkage information in the line segments, maintaining a list of the edges currently intersecting the edge of the view box, and, each frame, only doing intersection tests with those edges and their neighbors, to determine which of these line segments are entering or leaving the view. The assumption this would make is that you can never move more than the length of an edge in a frame. This is probably the fastest method, but also the least flexible, and, since you could probably get away with brute-forcing this, I can't really recommend it, even if it is the most amusing.

I considered something like that. However, there might be some problems with that approach which could be difficult to overcome, such as if a non-neighboring line crossed a line which is in view. That shouldn't happen much, but I know it will happen sometimes. However, I'm sure it is safe to assume that the user will never move farther than the length of an edge in one step, the edges should be much much longer than the players top speed or else the game wont be much fun.

I'll see what I can do and let you know what happens. thanks

Posted 29 November 2012 - 10:01 PM

Ok, I implemented something based on what you told me. Right now it looks pretty bad, but I am definitely on the right track. I'm storing offset vectors alongside the links and using those to draw images on the lines. I'm also storing rotation angles with the links to get the images oriented correctly. It basically does everything I asked for.

The biggest issue now is the speed. I went with the brute force method, checking each image to see if it is in the view and only drawing those that are close enough, and that actually keeps it running at a reasonable speed, although in my mind I know its an absurd number of comparisons per step ( I have 2000 nodes, each with up to 4 links ). I have some ideas to optimize that though.

So basically I want to say that your suggestion worked for me, thank you.

The biggest issue now is the speed. I went with the brute force method, checking each image to see if it is in the view and only drawing those that are close enough, and that actually keeps it running at a reasonable speed, although in my mind I know its an absurd number of comparisons per step ( I have 2000 nodes, each with up to 4 links ). I have some ideas to optimize that though.

So basically I want to say that your suggestion worked for me, thank you.