A Road Generator that will generate a road mesh. It is created for use in the Unity Game Engine.
Warning!: This project is unfinished. You can download and view the project but it might not contain proper documentation and/or fully work.
Using this Road Generator you can easily create a road for your games. The road will be created by specifying the following data:
- a set of points,
- a profile,
- a material; The generator will create a smoothed and parametized road mesh that will go through the points. The road will have the profile and material as you specified.
I implemented the tangents (as seen in the image above) using the following algoritme I wrote:
public Vector3 GetTanget(int index, bool to)
{
int prevIndex = PreviousIndex(index),
nextIndex = NextIndex(index);
Vector3 direction = (points[nextIndex] - points[prevIndex]).normalized;
float tangetMultiplier = 1f;
if (to)
{
tangetMultiplier = -smoothing;
tangetMultiplier *= (points[prevIndex] - points[index]).magnitude / 3;
}
else
{
tangetMultiplier = smoothing;
tangetMultiplier *= (points[nextIndex] - points[index]).magnitude / 3;
}
return direction * tangetMultiplier;
}
After you created your road shape you can create the mesh. The mesh is shown in the picute below:
You can also see that I used a road profile which is how the road is generated in the width of the road. You can use any amount of points in this profile.
One big part of the mesh generation is parametrizing the roads points. This means that each point has the same length to the next point.
public Vector3[] GetParametizedPoints(int pointCount)
{
int detailCount = pointCount;
Vector3 previousPoint;
float length = 0f;
float calcLength = 0f;
float[] lengthAt = new float[detailCount];
for (int i = 0; i < detailCount; i++)
{
Vector3 point = GetPosition(i / (float) (detailCount));
if (i > 0)
calcLength += (point - previousPoint).magnitude;
if (i == detailCount - 1)
length = calcLength;
lengthAt[i] = calcLength;
previousPoint = point;
}
Vector3[] pPoints = new Vector3[pointCount];
int pointer = 0;
float cProgress = 0f;
for (int i = 0; i < detailCount - 1; i++)
{
int ni = i + 1;
float lProgress1 = lengthAt[i] / length,
lProgress2 = lengthAt[ni] / length;
float oProgress1 = i / (float) (detailCount - 1),
oProgress2 = ni / (float) (detailCount - 1);
while (cProgress < lProgress2 && pointer < pointCount)
{
float lerpPosition = Mathf.InverseLerp(lProgress1, lProgress2, cProgress),
actualProgress = Mathf.Lerp(oProgress1, oProgress2, lerpPosition);
pPoints[pointer] = GetPosition(actualProgress);
pointer++;
cProgress = pointer / (float) (pointCount);
}
}
return pPoints.Select(p => transform.TransformPoint(p)).ToArray();
}
All source code is available in the download