Tutorial on making 2-way traffic (or other) AI lines and layouts

First step for making the 2-way lines is checking out the road and surfaces.ini for impending problems with the side lines. One way for that is to load the track with some layout that already has AI lines and have a look at those. May require disabling of "Origin shift" in CSP settings > "Graphic adjustments". If the red sides follow exactly the border between the asphalt and the green or brown stuff then most probably you will have the same side lines automatically generated from the game after your attempt.
Clipboard01.jpg


Another way of checking is to confirm the names of the objects that are physics. Those have number for first symbol in the names (0 doesn't count). 1ROAD next to 1SAND when the surface "SAND" has "IS_VALID_TRACK=0" tag in "..\AssettoCorsa\system\data\surfaces.ini" or in the layout's "surfaces.ini" means the side line will be created on that border.
Clipboard02.jpg
Clipboard03.jpg


When the objects for physics are correct you need to prepare the new layout's structure. In Windows Explorer open the track's folder (fastest way - right-click or use the three dots next to the track's name in Content Manager). In there create new folder (i.e. "2way") and while empty - copy that into "ui". Then from "ui" or some of the other track's layouts select and copy the three .png and the "ui_track.json" into the empty "..ui\2way\" folder. Edit the contents of "ui_track.json" to reflect the changes in this layout. Avoid putting the new name entirely different than the other names of the track's layouts but add few words after the old name. When done editing that re-open CM and see if the new layout shows up for selecting.
Clipboard04.jpg
Clipboard05.jpg


Then proceed to creating the file structure - copy the "data" folder and map.png from some of the existing layouts and paste those into "..\<track name>\2way\". Make a copy from some of the other "models_***.ini" for that track or if there are none you need to create new in the track's folder ("..\<track name>\") and name it "models_2way.ini" to match the name of the layout's folder. If you are making new - open it and create a paragraph

[MODEL_0]
FILE=euphoria_hillside_park.kn5 ;the actual name of the kn5 model in the track's folder;
POSITION=0,0,0
ROTATION=0,0,0
Clipboard10.jpg


After that load the new traffic layout in "Practice" mode. When all of the necessary models are present the car will be functioning and positioned correctly and you will be ready for drawing the fast_lane. Notes on the car choice - large cars with longer wheelbase are more stable but the lines drawn with those have longer segments and in tight turns that sometimes becomes too obvious later with the AI cars. Drawing the line at racing pace is not necessary and two lines drawn with different cars at different pace work the same provided the lines have the same geometry. So choose a car that has small enough turning circle, smooth and broad torque band, big enough suspension travel and gripping tires to give you the best traction and stability and then drive it like a grownup. Choosing a car with weak engine allows for relaxing your feet by flooring it for long enough during the drive and that matters a lot when it takes more than 1 hour for driving the line on a long road.

Next on the list - choosing the actual route. The simpler - the better. Avoid as much as possible: overlapping the line by driving again in the same lane; crossing the paths of the AI; narrow passages between walls or near obstacles.
Find the best places for the U-turns with road tagged as "IS_VALID_TRACK=1" wide enough to accommodate the turning circle of most cars in the "street" class. On a long road or large road grid use the "map.png" file to actually draw into it the arrows to guide you where to turn and color-code those if it's multi-lane and you need to make another parallel loop. So your first stab at making the traffic is a drawing over the "map.png" and then practice run on which you confirm on track where and how to turn.

Settings of CSP and other for the time of driving the new lines - the entire "New AI behavior" module should be turned off, "Origin shift" in CSP settings > "Graphic adjustments" should be disabled. Deactivate all Python apps except Sol controls.

When all of the above is done and you feel there's enough energy left for the long haul - start the engine. By that I mean choose the starting point of the line on some straight bit with distinct object next to the side which you take as reference. YOU NEED TO STOP THE RECORDING AT THE END OF THE DRIVE JUST BEFORE YOU REACH THE STARTING POINT. This method doesn't need the first timing gate to form a "start line" and to begin and close the recording there. I use "start pits" to record the line from anywhere I fancy to anywhere I decide to stop.
Clipboard06.jpg

On multi-lane traffic it simply is the only way for creating the parallel lines. On A2B hill-climbs it's the easiest way to make the AI cross the finish line. The drawback - after completing the drive and renaming the "pit_lane.ai.candidate" to "fast_lane.ai" the game takes it's time to evaluate it upon loading which takes as long as the time to actually render the line upon exiting the session. So if the rendering needs 2 hours it will take twice that when making the line from "pit_lane.ai.candidate" and you need to interact in the middle of that wait. In conclusion - to save time you may consider the option to start the 2-way just before the timing gate as long as you don't need to pass through it again in the same direction for making another round. In that case using the standard "start recording" in the "AI" app will spare you the wait for loading the raw line and the rendering will be done upon exit of the same session. To see the location of the timing gate you have no other option but to use 3DSimED to load the relevant track's models prior to the attempt.
Clipboard12.jpg

*To make things more interesting the author in this example had the track encrypted and for that the wire-frame view is necessary. The positioning of these two gate objects would prevent making of the traffic that I've done using the "start pits".

The timing gate may not be on the map, may not be in the place that the map says it will be, or it may not be present at all. If any of this and without checking - you will waste a lot of time blindly driving around just to find out that timing doesn't work and the recording of the traffic you want is never going to happen. In case you need the gate to be somewhere else or if it simply is missing in the track you can create it by placing by the sides of the road two primitives in 3DSimED. Boxes with 1m sides are fine and the names should be "AC_TIME_0_L" and "AC_TIME_0_R" for the left and right side respectively. "Plugin Export" that as "gate.kn5" and make it load by adding a paragraph into "models_2way.ini". Now, if the track already has those objects there is a big difference whether you put the new "gate.kn5" model last in the queue or first. Put it before all others as [MODEL_0] to make it work and observe the proper sequential numbering of the next models.

But if you are like me and want to get straight to it - use the "start pits" and just drive the route that you want. Just remember the place of the start and on the second approach to it click "recording" to stop the process before you reach the starting point. After exiting that session you will find a single "pit_lane.ai.candidate" in "..\<track name>\2way\ai\" folder.
Clipboard07.jpg

Rename it to "fast_lane.ai" and load another "Practice" session. This time loading will be slowed down by the raw line that you want to render. Be patient and don't terminate "acs.exe". If you like to have the PC available for other tasks use "Alt+Tab" or "Ctrl+Alt+Del" to make the "Desktop Manager" of Windows re-gain control over the screen.

After the loading is complete you need to use "start pits" again and depending if you intend to actually use the "pit_lane.ai" or a duplicate of the "fast_lane.ai" you may want to drive the good short guiding line into and out of the pits. When that is done click "recording" to stop the process and exit the session. That's when the actual usable lines are made by the game. The good result is two new .candidate files which need to be renamed by removing the ".candidate' from the names. The initial "fast_lane.ai" needs to get out of the way and for safekeeping you may pack it into a zip.

There are two scenarios for "pit_lane.ai": 1. using the short line that only covers the pit area or 2. making a copy of "fast_lane.ai" and renaming that copy to "pit_lane.ai". That gives the opportunity to scatter the pits along the route and make the AI join more naturally for a street driving. But when you have all cars starting from the pits using the duplicate "fast_lane" has no benefits.

If you think that's all - it's not. For most of the AI to work with the line there has to be some track-specific hints. A simple template for creating such "..\content\tracks\<track name>\2way\data\ai_hints.ini" file is

[HINT_0]
START=0.001
END=0.999
VALUE=0.8

[BRAKEHINT_0]
START=0.001
END=0.999
VALUE=0.9

[MAXSPEED_0]
START=0.001
END=0.999
VALUE=160

[DANGER_0]
START=0.001
END=0.999
LEFT=0.6
RIGHT=0.6

From those paragraphs most likely [HINT_**] and [MAXSPEED_**] would be of use, the first telling the AI that each corner radius is shorter than the look-ahead estimate (i.e. factor of 0.8) and the second - not to exceed the defined speed. Hints can work in combination and be multiple of the same kind. The numbering is [HINT_0], [HINT_1], [HINT_2], etc. and the "START=***" and "END=***" determine the points on the spline in form of percentage length from the starting point. It is displayed on the "AI" app but with a long splines you might want to use the "DRS zones" app instead to avoid CPU overload.
Clipboard09.jpg

The way I find most effective for tuning the hints is to load a well-developed car in "Hotlap" mode and enable the AI (Ctrl+G and Ctrl+C) so I can watch and listen for problems. If the AI resembles human driver then that part of the course is ok. If not I take note of the positions and edit the hints. Testing of the line is not complete without a Track day with AI flood. Before judging that some line is good or bad consider this: some AI cars experience difficulties with new AI flood when spawned at speed in the highest gear and have to downshift fast without any hesitation. Instead of doing it as expected many AI just can't engage the clutch. Here's what solves this issue: unpacking of car's data and enabling the unpacked data as default by renaming "data.acd" to "data.acd1", then edit of "drivetrain.ini" to have [AUTOCLUTCH]
MIN_RPM=100
Provided there's no other problems with the car's physics that makes it go without a hiccup. Additional benefit of using the unpacked data is the option to train that AI better so it doesn't hit the walls due to cutting corners or missing the turn.

Not essential but nice to have are F3 track-side cameras. The positions and directions of those are tied to the spline length and you can't simply use the old "cameras.ini" from another layout. For making the F3 cams I'm using the "Custom Shaders Patch debug app Advanced"
Again by enabling AI and setting [MAXSPEED_0] low enough I'm able to go round the course and in one lap to position all the cameras so the cars remain in frame later on. For making the cams I usually let AI drive some wide car with less body roll - like a Hummer in case of wide roads, so with F5 and some rotation I can reach over or near the edge of the road. Thanks to LeBluem aka @Please Stop This for making the useful tool.
Additional note on the cams - since v0.99k the app offers "new auto cams" mode of recording and it works very well for making huge sets for long lines when some conditions are met: the timing gate "0" should be present and at the exact spot where the line begins, you set "min_z=0" and "max_z=1", in CSP settings disable "New AI behavior" module and disable "Use double precision physics", in "Hotlap" or "Track day" session position the cams by selecting F5 and looking at the rear quarter close to the road edge without going into some buildings and other obstructions, at height of more than 2 m above ground. To add variety to the set you can change the "IN" and "OUT" while the AI does the driving. For wide and long straight roads - bigger distances between cams, for narrows and twisties - shorter distances. If the AI speed is limited that also calls for shortening the "IN" and "OUT". If "IN" is bigger than "OUT" cams show more the front of the cars approaching, if "OUT" is bigger - more of the rears is in the shots.

Let me know if splitting the opposite lanes is interesting for you and I will add more info. And don't hold back if you see the results of the attempts exceed your expectations - share the layouts with us!
 
Last edited:
If you're making a traffic AI line for a track that already has functional cameras for racing, you can simply remap the old cameras onto the new AI line using this Python script I made (see attachment).

Code:
acai_map_cameras_to_new_ai-line.py from.ai to.ai from_cam.ini to_cam.ini [min_seglen]
    from.ai      : Old AI line which already has cameras.
    to.ai        : New AI line. Cameras will be mapped onto this line.
    from_cam.ini : Cameras.ini for the old line.
    to_cam.ini   : Name of the new camera file.
    min_seglen   : Minimum camera segment length in metres. A camera covering less than this distance gets ignored.

A camera for one segment of racing line will typically be mapped onto two parallel segements for a two-way traffic line. Unfortunately the camera switching is not perfect. When the car crosses lanes the screen tends to flicker.

By "splitting the opposite lanes", do you mean there's a way to make more than one AI spline loop? If that's the case, please share the details!
 

Attachments

  • acai_map_cameras_to_new_ai-line.py.txt
    9.4 KB · Views: 252
Last edited:
o you mean there's a way to make more than one AI spline loop?

What I mean is the preventing of AI entering the wrong lane and causing collision. AFAIK there is no way of splitting the spline into two or more working new splines. The separating of lanes is done by re-generating the side lines in a special way. And atm I'm aware of three different methods.

Thanks for the code. I know of the cam-flickering problem and that is unavoidable. The most that someone can do is to follow some of the AI cars that is not veering much.
 
Trobably a good idea to disable those two options, idk wth thats there anyway, it could make ai-line recording not work.
If i understand it right when this is on, it "guesses" new ai-line-borders based on valid surfaces from "surfaces.ini" which is just not right on some tracks.
1629807638735.png
 
Last edited:
Trobably a good idea to disable those two options, idk wth thats there anyway, it could make ai-line recording not work.
If i understand it right when this is on, it "guesses" new ai-line-borders based on valid surfaces from "surfaces.ini" which is just not right on some tracks.
View attachment 498140
I find the caching of payloads very beneficial for staring normal sessions on large tracks. For example SRP loading time with AI traffic is 1.5 min versus ~10 min if the second option is inactive. The problems with tracks physics should be resolved by proper naming of the objects. Just today I had to find the way to add to a large chunk of Quebec road an extract of the physics mesh and that allowed for almost proper re-generating of the side lines. Of course the best option is the creator to do it proper in the original and I left some feedback for him in that regard.
But in the case of drawing a new line I tend to start by entirely switching off CSP when that is possible. I mean even the large tracks that shake madly, I drive "vanilla" if they are not encrypted.
 
Ok, but this is very bad for narrow tracks, i.e. Macau. Skilled ai-line makers (not me :cool: ) do manual borders on correctly named surfaces, so that the ai behaves like they should, you can control them with those borders quite good, and these options just ignore this entirely. It can be very frustrating.

Edit: nice typo there by myself - Probably, Trobably, Troubably
 
Last edited:
bad for narrow tracks
This reminds me for one specific quirk in AI behavior - they hold onto the side lines on straight parts and onto the fast lane on corners. So depending on the type of road the making of side lines by driving two more times with AI Line Helper app can make a difference or not at all.

And another quirk - on narrow roads with 2-way the AI refuses to hold onto any of the lines and AI app reports wrong offset. It made hell of making the 2-way for Wicklow 0.9.4.
 
The script from @Sim_Misg is working splendidly and despite being someone who is not into writing code I managed to re-map few cameras.ini already with excellent results in game. And to help the others of the crowd who are not into programming here's what you need:

Python interpreter to be installed in Windows. For Windows 7 - this one, for newer Windows - the latest.
Make a new folder that's easy to navigate to. Copy in that folder the "cmd.exe" from "..\Windows\System32\" and the files needed for the job.
cams2.jpg


In the above example the "akai.py" is the script that you may find attached to the previous message. The "fast_lane.ai" is from the original one-way layout, the "fast_lane2.ai" is the traffic line, the "cameras.ini" is from the original one-way, the "cameras_2.ini" is the new one. Initially the "cameras_2.ini" you place there is in fact a copy of the "cameras.ini" from the original one-way.

Now for the "fun" part -
cams1.jpg


In the above you see the difference between the wrong syntax in the first attempt and the stats after the correct input. So, drag-dropping the files onto the cmd window is not helping much. You need to enter the file names in a particular way, names can't contain spaces and special characters and the path of the operation matters.

But the important thing is that after a few seconds you get a new set of cameras that matches the traffic line!
 
Last edited:
This reminds me for one specific quirk in AI behavior - they hold onto the side lines on straight parts and onto the fast lane on corners. So depending on the type of road the making of side lines by driving two more times with AI Line Helper app can make a difference or not at all.

And another quirk - on narrow roads with 2-way the AI refuses to hold onto any of the lines and AI app reports wrong offset. It made hell of making the 2-way for Wicklow 0.9.4.
AI holding onto side lines is likely caused by the gap between fast_lane and border line being too small. I've made test tracks with the AI line set in the middle having sufficient space to each side, and the AI would stick to the fast_lane fairly well. If border line distance to one direction is low, the AI will be pushed to the other side. If distance to both sides are low (Wicklow) the AI would show erratic behavior.

For two-way traffic layouts I've found a consistent border line distance value of 1.5 (m) to be a safe starting point. It's wide enough to accommodate most vehicles, but not wide enough to allow overtaking, so the AI would not attempt to leave its line.

A script to quickly clamp/reset border distance is attached below.
Code:
acai_reduce_ai-line_border_distance.py ai-line.ai left_lmt right_lmt min_value
    ai-line.ai : the AI file to modify
    left_lmt   : upper limit for left border distance
    right_lmt  : upper limit for right border distance
    min_value  : minimum value for left/right border distance
To set both distances to a consistent value of 1.5m, run:
    acai_reduce_ai-line_border_distance.py fast_lane.ai 1.5 1.5 1.5
 

Attachments

  • acai_reduce_ai-line_border_distance.py.txt
    3.1 KB · Views: 394
Last edited:
Wow, you've really been busy with AI ! Thanks for the sharing, it means a lot !
Just as it happens I loaded the brand new layout "theSnake_reverse_traffic" and I noticed some things that may work better and the info could be of help in this thread. Problem: when not using AI flood many of the AI remain stationary in the starting places. Also the using of each spawn with two cars is impaired. To have AI joining the line you need to change at least 2 things - replace the small "pit_lane.ai" with a duplicate of the "fast_lane.ai" and place all spawning marker objects over a surface that is tagged "IS_PITLANE=1" in the layout's "surfaces.ini". That tag should be part of a paragraph like
Code:
[SURFACE_9]
KEY=PIT
FRICTION=0.98
DAMPING=0
WAV=
WAV_PITCH=0
FF_EFFECT=NULL
DIRT_ADDITIVE=0
IS_VALID_TRACK=1
BLACK_FLAG_TIME=0
SIN_HEIGHT=0
SIN_LENGTH=0
IS_PITLANE=1
VIBRATION_GAIN=0
VIBRATION_LENGTH=0
and in this example also important is: the surface is named other than the main road; is "valid track"; is the last in the "surfaces.ini" numbering so it becomes the top in physics hierarchy if there's overlapping.
The spawning of two cars in one pit box works well only over pit surface where car's colliders get deactivated. And in the case of the fast_lane going over the pit surface you get the benefit of declogging the traffic since the faster cars move ahead in that spot.
That said if you change the 2 things that may still leave some AI in the pits. So far I managed to solve it on some occasions by moving slightly the location of the problematic spawns.
 
Last edited:
Now tips specific for making A2B layouts. Typically on the hill-climbs and down hill what you need is: 1.the AI to line up at the start and 2.to stop at the end after the finish line without leaving the road. Also it is good if 3.they can drive the course multiple times in the same session.
To achieve 1. you need the pit surface to be lined up right before the start line (first timing gate). That way in Track day mode each AI can begin no matter if it's lined up far back. The way to make this happen is to prepare an extract of the road mesh and that piece is only 1PIT physics without the game rendering its graphics. The object then can be loaded in the same model where the AC_PIT_** objects are. *Don't forget to define the "PIT" surface in surfaces.ini of the layout.
To achieve 2. you need the hint
[HINT_0]
START=0.992
END=0.999
VALUE=0
and provided you've made the line end after the last timing gate that forces the AI to stop straight on the fast_lane in the distance between 99.2% and 99.9% which should be after the finish and not leaving the road.
To achieve 3. you need to have a tag "circuit" in the layouts "ui_track.json" to be able to load Track day. Making the bit of road where the AI stops a 1PIT physics helps them not only to avoid pile-ups but to teleport back on the start quicker.
 
Last edited:
Now tips specific for making A2B layouts. Typically on the hill-climbs and down hill what you need is: 1.the AI to line up at the start and ...

To achieve 1. you need the pit surface to be lined up right before the start line (first timing gate). That way in Track day mode each AI can begin no matter if it's lined up far back. The way to make this happen is to prepare an extract of the road mesh and that piece is only 1PIT physics without the game rendering its graphics. The object then can be loaded in the same model where the AC_PIT_** objects are. *Don't forget to define the "PIT" surface in surfaces.ini of the layout.
...
Wouldn't putting AI spawn points on one lane and the pit/fast_lane on the other be easier, assuming there's enough space? After spawning each AI would steer towards the other lane and won't block anything behind it since it's already moving.
 
Last edited:
Wouldn't putting AI spawn points on one lane and the pit/fast_lane on the other be easier, assuming there's enough space? After spawning each AI would steer towards the other lane and won't block anything behind it since it's already moving.
If the road is wide using one half as pits and the other lane as regular surface is of course preferable. Looks more like what humans do IRL. But enabling pit physics under the spawns is still necessary. So for example the meshes "5ROAD_rockStore" and "4ROAD_top" on "The Snake" could do directly a better job as 1PITS_*** to have the cars moving in A2B and also in traffic. The problem now is when AI flood is off and more than 16 AI cars are selected the AC_PIT_0 is the first to get populated by two cars and the player gets a very harsh start of the session. Same happens if the 17 cars limit is exceeded in Race mode - AC_START_0 (and all other starts) can't service 2 cars.
 
If the road is wide using one half as pits and the other lane as regular surface is of course preferable. Looks more like what humans do IRL. But enabling pit physics under the spawns is still necessary. So for example the meshes "5ROAD_rockStore" and "4ROAD_top" on "The Snake" could do directly a better job as 1PITS_*** to have the cars moving in A2B and also in traffic. The problem now is when AI flood is off and more than 16 AI cars are selected the AC_PIT_0 is the first to get populated by two cars and the player gets a very harsh start of the session. Same happens if the 17 cars limit is exceeded in Race mode - AC_START_0 (and all other starts) can't service 2 cars.
So the goal of the pit surface definition was to avoid collision when sharing spawn positions. I get it now.

My original design of the The_Snake traffic was to have only 1+16 spawn positions. Given the location of the track and its length, 16 AI cars should be more than enough. With AI Flood up to 33 AIs are available in case someone really want to do it. Cars competing for spawning positions was not considered a problem because I never intended to actually have that many cars, even though I did allow it.

I think I'll switch the pit count back to 17 in the next release, and add a line in the description about how you can increase the limit to 34 with AI Flood if necessary. The layout is for offline use only anyway, there's no need to worry about modified files causing mismatch online.

Is pit surface still necessary if spawn positions are no longer shared? On many P2P tracks there's no extra space along the road to place pit zones. Since I can't put pit surface in the middle of the track, I have to put AC_START_* on regular track surface in order to spread them out. For The_Snake this is not a problem because there's plenty of open space for adding small patches of pit mesh.
 
can't put pit surface in the middle of the track
No need for that. I meant 1PIT surface for the AC_PIT_** objects. And "yes", for those spawns pits physics is necessary to increase the chances of AI joining the line. Otherwise they stay put. Having 34 spawns on The Snake could be useful exactly in AI flood "off" session since the length of the course is not so big and the AI would populate it with greater variety of cars. Flood with too many cars doesn't work very good.

Otherwise on principle - placing additional patch of extracted invisible 1PIT mesh is possible on every bit of the road.
 
Last edited:
In regards of the script that positions the side lines - works wonders also in case of varying width of the roads. Here's an example how it can bring order into the Gunja's line for SRP:
Code:
#!/usr/bin/env python3

import sys, os, string, struct, math

inPath = ""
otPath = ""
lmtLeft  = -100.0
lmtRight = -100.0
minValue = -1.5
for arg in sys.argv:
    if arg.lower().endswith(".ai") or \
       arg.lower().endswith(".ai.candidate"):
        if inPath == "":
            inPath = arg
            otPath = arg
        else:
            otPath = arg
    else:
        try:
            inputFloat = max(-95.0, float(arg))
            if   lmtLeft  < -99:
                lmtLeft  = inputFloat
            elif lmtRight < -99:
                lmtRight = inputFloat
            elif minValue < 0 and inputFloat > 0.01:
                minValue = inputFloat
        except ValueError:
            pass
if lmtLeft > -99 and lmtRight < -99:
    lmtRight = lmtLeft
if lmtLeft  < -99:
    lmtLeft  = 1.5
if lmtRight < -99:
    lmtRight = 1.5
if minValue < 0:
    minValue = 1.5
if lmtLeft  > 1.5:
    minValue = min(minValue, lmtLeft )
if lmtRight > 1.5:
    minValue = min(minValue, lmtRight)

ptCnt    = 1
lineCods = []
extraDat = []
header   = []
dataRest = []

filesize = os.stat(inPath).st_size
fileSBU  = filesize
with open(inPath, "rb") as iBuffer:
    header = iBuffer.read(4*4)
    ptCnt  = struct.unpack("4i", header)[1]
    filesize -= 4*4
    for i in range(ptCnt):    # 4 floats, one integer
        lineCodRaw = iBuffer.read(4*5)
        lineCods.append([lineCodRaw, struct.unpack("4f i", lineCodRaw)])
        filesize -= 4*5
    for i in range(ptCnt):    # 18 floats
        #extraDat.append(struct.unpack("18f", iBuffer.read(4*18)))
        extraDatePtA = iBuffer.read(4*6)
        #extraDatePtG = struct.unpack("2f", iBuffer.read(4*2))
        extraDatePtG = iBuffer.read(4*2)
        extraDatePtB = iBuffer.read(4*10)
        unpack       = struct.unpack("2f", extraDatePtG)
        extraDat.append([extraDatePtA,extraDatePtG,extraDatePtB,unpack])
        filesize -= 4*18
    dataRest = iBuffer.read(filesize)

#with open("ai-line.csv", "w") as iBuffer:
#    for i in lineCods:
#        iBuffer.write(str(i[1][4])+","+str(i[1][0])+","+str(i[1][2])+","+str(i[1][3])+"\n")

with open(otPath, "wb") as oBuffer:
    oBuffer.write(header)
    for i in range(ptCnt):
        oBuffer.write(lineCods[i][0])
    for i in range(ptCnt):
        oBuffer.write(extraDat[i][0])
        if lmtLeft  > 0.0:
            leftValue  = max(minValue, min(lmtLeft,  extraDat[i][3][0]))
        else:
            leftValue  = max(minValue, extraDat[i][3][0] + lmtLeft )
        if lmtRight > 0.0:
            rightValue = max(minValue, min(lmtRight, extraDat[i][3][1]))
        else:
            rightValue = max(minValue, extraDat[i][3][1] + lmtRight)
      
        nomPos = lineCods[i][1][3]/lineCods[ptCnt-1][1][3]
        # Write track-specific modifications here.
        if nomPos > 0.0905 and nomPos < 0.1572:
            rightValue = 4.5
        if nomPos > 0.1584 and nomPos < 0.1751:
            rightValue = 4.5
        if nomPos > 0.2532 and nomPos < 0.2974:
            rightValue = 4.5
        if nomPos > 0.2978 and nomPos < 0.3366:
            rightValue = 4.5
        #    leftValue = 7.5
        #leftValue += 0.15
      
        oBuffer.write(struct.pack("2f", leftValue, rightValue))
        oBuffer.write(extraDat[i][2])
    oBuffer.write(dataRest)

print("input: "+inPath+", output: "+otPath)
print(
    str(ptCnt)+" pts, left "+str(round(lmtLeft, 2))+" m, "+ \
    "right "+str(round(lmtRight, 2))+" m, min "+str(round(minValue, 2))+" m."
)

In the above the lines
Code:
        # Write track-specific modifications here.
        if nomPos > 0.0905 and nomPos < 0.1572:
            rightValue = 4.5
        if nomPos > 0.1584 and nomPos < 0.1751:
            rightValue = 4.5
        if nomPos > 0.2532 and nomPos < 0.2974:
            rightValue = 4.5
        if nomPos > 0.2978 and nomPos < 0.3366:
            rightValue = 4.5
are what determines which parts of the length should have the 4.5 m space to the right. Using that .py is much like the cameras script and with the values on default like the above it makes 1.5 m borders everywhere but the defined exceptions. When you need to take measurements of the lines on track I recommend using the "AI Lines Helper" app that reads them quick and correctly.
 
Last edited:
Using information I mentioned here, traffic AI line has been generated without recording.

Load the track mesh, clean up, select two loops representing the center of the two lanes.
1.png


Break up the loops at the U-turn area and connect them with U-turns.
2.png


Move all vertices ~0.5m above the ground. Export the mesh and convert.
Code:
acai_csv_to_line.py fast_lane.csv fast_lane.ai

Load the file in ksEditor, resample and save.

The new line works in-game!
Screenshot.jpg


This process should make complex/long AI line building faster since we no longer have to record everything in one run. It's possible to construct the line one section at a time.
 

Attachments

  • acai_csv_to_line.py.txt
    2.4 KB · Views: 146
  • fast_lane.ai.txt
    203.2 KB · Views: 160
  • fast_lane.csv.txt
    94.7 KB · Views: 144
Last edited:
Load the track mesh, clean up, select two loops representing the center of the two lanes.
We need to mention here that this purely mathematical method will work only on tracks that have a road loop which "started life" as an array of identical segments. If the track has it on the physical or graphical mesh - then it might save time to generate the line in Blender. But if neither are present then another approach of conjoining the road borders (non-manifold edges) will be needed. Any ideas on that?
 
Load the file in ksEditor, resample and save.

The new line works in-game!
This process should make complex/long AI line building faster since we no longer have to record everything in one run. It's possible to construct the line one section at a time.
This script for converting .csv exports to .ai could have another good use - making parts of existing .ai line work as separate lines for another layouts. Or "Frankenstein-ing" the new line out of several other old ones. "Glen Shail" comes to mind right away... But the loading in ksEditor still slowes the process considerably with the single-thread physics being a limitation that's hard to overcome.
 
Last edited:
Back
Top