Figuring out how to render the roads correctly in OpenSAGE turned out to be a little more challenging than expected. This is the eighth post in a series describing the journey. Last time, we started rendering crossings and found the formulas for calculating the rectangles in world coordinates based on the parameters RoadWidth
and RoadWidthInTexture
.
Texture coordinates
Now we need to find the coordinates of these rectangles in the road texture, just as we did for the straight roads in part 4.
Let's start by dividing the whole texture into a 3x3 grid. The center of the T crossing is located at the center of tile [2, 3], and the center of the X crossing is located at the center of tile [3, 3]. In texture space, they are located at [3/6, 5/6] and [5/6, 5/6] respectively. However, as we found out in part 4, the engine approximates 1/6 as 1.666
, truncating all decimal places after the third. This also happens for the center of tile two, which is not 0.5
, but 0.498 (3 * 1.666)
.
We also already know that the default road width of 0.25
is scaled with the factor RoadWidthInTexture
. Now we only need the lengths of the small extruding stubs. By measuring some textures of different sizes, we can find out that it is 0.004
regardless of RoadWidthInTexture
.
Using the variables
Name | Abbreviation | Value |
---|---|---|
Half tile width | htw |
0.166 |
Half road width | hrw |
0.25 * RoadWidthInTexture / 2 |
Length to incoming road | lti |
0.25 / 2 + 0.004 |
this gives us the following texture coordinates for the T- and X-crossing:
Crossing type | Left | Top | Right | Bottom |
---|---|---|---|---|
T | 5 * htw - hrw |
3 * htw - lti |
5 * htw + lti |
3 * htw + lti |
X | 5 * htw - lti |
5 * htw - lti |
5 * htw + lti |
5 * htw - lti |
Unfortunately the two Y crossings are a little less straight forward and require some hardcoded numbers (this time, width and height are given instead of right and bottom coordinates):
Crossing type | Left | Top | Width | Height |
---|---|---|---|---|
Symmetric Y | 3 * htw - 0.2 |
0.504 - 0.135 |
0.4 |
0.270 |
Asymmetric Y | 0.395 - hrw |
0.645 |
1.2 * 0.25 + hrw |
0.335 |
Using these coordinates, we can now render the crossings, but it doesn't look quite right yet:
The crossing texture and the straight road segment textures overlap because the segments all start directly at the node position.
Connection points
We need to move the end points of the incoming road segments outwards to the positions labeled A-M in the image above.
The following table lists the vectors that need to be added to the node positions to get to these connection points (Up
, Down
, Left
, Right
, DownLeft
and DownRight
being unit vectors pointing in the respective directions and Width
and Height
referring to the rectangles we calculated in the last post).
Crossing type | Position | Vector from |
---|---|---|
Symmetric Y | A | Up * (0.269 * Height) |
Symmetric Y | B | DownRight * (0.547 * RoadWidth) |
Symmetric Y | C | DownLeft * (0.547 * RoadWidth) |
T | D | Up * (Height / 2) |
T | E | Right * (Width - HalfRoadWidth) |
T | F | Down * (Height / 2) |
Asymmetric Y | G | Up * 0.2 * Height |
Asymmetric Y | H | Down * 0.8 * Height |
Asymmetric Y | I | DownRight * (1.047f * RoadWidth) |
X | J | Left * (Width / 2) |
X | K | Up * (Height / 2) |
X | L | Right * (Width / 2) |
X | M | Down * (Height / 2) |
And now, finally, the crossings are done:
In the next post we'll tackle the curves.