- 11,305
- Sweden
- eran0004
Something that has been bugging me for a while is how to create realistic curvature transitions. In real life when designing roads, there are two basic criteria for corners:
1. The tangent needs to be continuous (i.e. if you want to change direction you need to use a curve)
2. The curvature needs to be continuous
It's pretty easy to achieve (1) in the game, but (2) is hard. Whenever you have a curve with a constant radius and connect it to a straight (or worse, to a curve heading in the other direction) you'll get a big jump in curvature at the point where they meet. The transition between the curvatures basically represent how quickly you need to turn the wheel in order to stay on the road. When the transition is instant that means that the wheel has to be turned instantly as well - not good for road safety!
So the curvature has to change gradually, the best way to do this is with a clothoid, since the curvature of a clothoid is proportional to the curve length. That means that if a car is driving at a constant speed along the road, then the driver can turn the wheel at a constant speed when entering the corner.
The figure below illustrates the difference between a road where two constant radius curves are directly attached to each other, and one where there's a segment of linear change in curvature in between the two curves.
In the game we can't really make clothoids, but we can approximate them. The roads are basically Bézier curves, where the straights are linear Béziers (two control points) and the corners are quadratic Bézier (three control points). With the corners we have a start vector, an end vector and the vector length for each of those (those are what we draw with the curve tool). The figure below illustrates how the clothoid approximation is created: Given a target radius R of the curve and an angle v that we want the transition to cover we can calculate the vector lengths a and b.
The actual calculation is done by adding lots and lots of circle segments of constant curve length together, where each circle segment has a smaller and smaller radius, then adding their x and y coordinates together to get the coordinates for the endpoint. Then it's just a matter of trigonometry to solve for the lengths a and b. The greater the number of circle segments, the better the precision, I found that around 1000 segments provides a good balance between accuracy and speed of calculation.
I don't know how to make mods for the game, but I created a Python script that can perform these calculations.
I have only done some basic tests yet, and only for small angles (30 degrees or less) so not sure how well this holds up for greater angles. I'll make some tests in the game and report back
1. The tangent needs to be continuous (i.e. if you want to change direction you need to use a curve)
2. The curvature needs to be continuous
It's pretty easy to achieve (1) in the game, but (2) is hard. Whenever you have a curve with a constant radius and connect it to a straight (or worse, to a curve heading in the other direction) you'll get a big jump in curvature at the point where they meet. The transition between the curvatures basically represent how quickly you need to turn the wheel in order to stay on the road. When the transition is instant that means that the wheel has to be turned instantly as well - not good for road safety!
So the curvature has to change gradually, the best way to do this is with a clothoid, since the curvature of a clothoid is proportional to the curve length. That means that if a car is driving at a constant speed along the road, then the driver can turn the wheel at a constant speed when entering the corner.
The figure below illustrates the difference between a road where two constant radius curves are directly attached to each other, and one where there's a segment of linear change in curvature in between the two curves.
In the game we can't really make clothoids, but we can approximate them. The roads are basically Bézier curves, where the straights are linear Béziers (two control points) and the corners are quadratic Bézier (three control points). With the corners we have a start vector, an end vector and the vector length for each of those (those are what we draw with the curve tool). The figure below illustrates how the clothoid approximation is created: Given a target radius R of the curve and an angle v that we want the transition to cover we can calculate the vector lengths a and b.
The actual calculation is done by adding lots and lots of circle segments of constant curve length together, where each circle segment has a smaller and smaller radius, then adding their x and y coordinates together to get the coordinates for the endpoint. Then it's just a matter of trigonometry to solve for the lengths a and b. The greater the number of circle segments, the better the precision, I found that around 1000 segments provides a good balance between accuracy and speed of calculation.
I don't know how to make mods for the game, but I created a Python script that can perform these calculations.
Code:
from math import tan, sin, cos, pi, radians
def psum(n):
return n*(n+1)/2
def easing(v, R, n=1000):
vtot = radians(v)
k = 1/R
arclength = l = vtot*n/(k*psum(n))
y = 0
x = 0
startangle = 0
stopangle = 0
for i in range(1, n+1):
ki = k/n*i
vi = ki*l
Ri = 1/ki
stopangle = startangle+vi
dy = -Ri*(cos(stopangle)-cos(startangle))
dx = Ri*(sin(stopangle)-sin(startangle))
y += dy
x += dx
startangle = stopangle
a = x-y/tan(vtot)
b = y/sin(vtot)
print("a = %.1f m, b = %.1f m" %(a, b))
return a, b
I have only done some basic tests yet, and only for small angles (30 degrees or less) so not sure how well this holds up for greater angles. I'll make some tests in the game and report back
Last edited: