Skip to content

Exporting Track On CSV

1 to 6 of 6

Hello, I'm trying to export a roller coaster into Blender using the CSV export. The coaster I have built contains multiple segments separated by switch tracks. When I export, it selects one of the Track segments to export. Is there a way to change which track segment it will export?

The only thing u can do is to export this switch track seperately and make an single piece of track and make an single object.

Posted July 1, 2025· Edited July 2, 2025

Hello, I am not sure about being able to choose a switch track segment & export it to CSV. I found with a quick try-out that any track between two switch tracks is not exported. Though I did not check thoroughly...

You could use a script to measure e.g. a bogie of a train of your coaster and then just let the coaster run for a lap. Write the measured data to the messages window, and finally copy/paste it into a CSV file yourself.

Save the script below as "WriteTrackCoords.nlvm", and attach it to your coaster. It writes something similar to the messages window as you would get when exporting a CSV.
You can adjust this parameter in the script to adjust the distance between points as you'd do for CSV export:

private float distanceBetweenPoints = 0.5f; // Adjust this number to your liking.;

Hope this helps!
Perhaps someone else knows more sophisticated way without having to use a script...?

The script:

import com.nolimitscoaster.*;
import nlvm.lang.*;
import nlvm.math3d.*;

public class WriteTrackCoords extends Script {
    private Coaster coaster;
    private Train train;
    private float distanceBetweenPoints = 0.5f; // Adjust this number to your liking.

    public bool onInit() {
        coaster = sim.getCoasterForEntityId(getParentEntityId());
        if (coaster == null) {
            System.err.println("Script not attached to a coaster. Exiting.");
            return false;
        }

        train = coaster.getTrainAt(0);
        if (train == null) {
            System.err.println("Coaster [" + coaster.getName() + "] has no trains. Exiting.");
            return false;
        }

        measureBogie();
        writeHeadline();
        writeMeasurement();
        storedPosOut = posOut.dup();
        return true;
    }
    
    public void onNextFrame(float tick) {
        measureBogie();
        if (posOut.distance(storedPosOut) >= Math.abs(distanceBetweenPoints)) {
            writeMeasurement();
            storedPosOut = posOut.dup();
        }
    }

    private Vector3f frontOut = new Vector3f();
    private Vector3f topOut = new Vector3f();
    private Vector3f rightOut = new Vector3f();
    private Vector3f posOut = new Vector3f();
    private Vector3f storedPosOut = new Vector3f();
    private void measureBogie() {
        train.getBogieOrientationAndPosition(0, frontOut, topOut, rightOut, posOut);
    }

    private void writeHeadline() {
        StringBuilder headline = new StringBuilder();

        headline.append("No.\t");
        headline.append("PosX\t");
        headline.append("PosY\t");
        headline.append("PosZ\t");
        headline.append("FrontX\t");
        headline.append("FrontY\t");
        headline.append("FrontZ\t");
        headline.append("RightX\t");
        headline.append("RightY\t");
        headline.append("RightZ\t");
        headline.append("UpX\t");
        headline.append("UpY\t");
        headline.append("UpZ");
        System.out.println(headline);
    }
 
    private int num = 1;
    private void writeMeasurement() {
        StringBuilder line = new StringBuilder();

        line.append(num + "\t");
        line.append(posOut.x + "\t");
        line.append(posOut.y + "\t");
        line.append(posOut.z + "\t");
        line.append(frontOut.x + "\t");
        line.append(frontOut.y + "\t");
        line.append(frontOut.z + "\t");
        line.append(topOut.x + "\t");
        line.append(topOut.y + "\t");
        line.append(topOut.z + "\t");
        line.append(rightOut.x + "\t");
        line.append(rightOut.y + "\t");
        line.append(rightOut.z);
        System.out.println(line);
        num ++;
    }
}

The written result (example):

No. PosX PosY PosZ FrontX FrontY FrontZ RightX RightY RightZ UpX UpY UpZ
1 64.26366 2.5 -5.182514E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.17077E-9 1.892211E-9 -2.17077E-9 1.0
2 64.7713 2.5 -5.278569E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.299317E-9 1.892211E-9 -2.299317E-9 1.0
3 65.28258 2.5 -5.375313E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.432075E-9 1.892211E-9 -2.432075E-9 1.0
4 65.79778 2.5 -5.4728E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.569163E-9 1.892211E-9 -2.569163E-9 1.0
5 66.30961 2.5 -5.56965E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.708614E-9 1.892211E-9 -2.708614E-9 1.0

Thanks for the help, next time I’ll try NoLimits Explorers script. What I did is make a copy of the coaster see which segment exported and deleted it. But still thanks for the help.

NoLimits Explorers posted on June 30th, 2025

Hello, I am not sure about being able to choose a switch track segment & export it to CSV. I found with a quick try-out that any track between two switch tracks is not exported. Though I did not check thoroughly...

You could use a script to measure e.g. a bogie of a train of your coaster and then just let the coaster run for a lap. Write the measured data to the messages window, and finally copy/paste it into a CSV file yourself.

Save the script below as "WriteTrackCoords.nlvm", and attach it to your coaster. It writes something similar to the messages window as you would get when exporting a CSV.
You can adjust this parameter in the script to adjust the distance between points as you'd do for CSV export:

private float distanceBetweenPoints = 0.5f; // Adjust this number to your liking.;

Hope this helps!
Perhaps someone else knows more sophisticated way without having to use a script...?

The script:

import com.nolimitscoaster.*;
import nlvm.lang.*;
import nlvm.math3d.*;

public class WriteTrackCoords extends Script {
    private Coaster coaster;
    private Train train;
    private float distanceBetweenPoints = 0.5f; // Adjust this number to your liking.

    public bool onInit() {
        coaster = sim.getCoasterForEntityId(getParentEntityId());
        if (coaster == null) {
            System.err.println("Script not attached to a coaster. Exiting.");
            return false;
        }

        train = coaster.getTrainAt(0);
        if (train == null) {
            System.err.println("Coaster [" + coaster.getName() + "] has no trains. Exiting.");
            return false;
        }

        measureBogie();
        writeHeadline();
        writeMeasurement();
        storedPosOut = posOut.dup();
        return true;
    }
    
    public void onNextFrame(float tick) {
        measureBogie();
        if (posOut.distance(storedPosOut) >= Math.abs(distanceBetweenPoints)) {
            writeMeasurement();
            storedPosOut = posOut.dup();
        }
    }

    private Vector3f frontOut = new Vector3f();
    private Vector3f topOut = new Vector3f();
    private Vector3f rightOut = new Vector3f();
    private Vector3f posOut = new Vector3f();
    private Vector3f storedPosOut = new Vector3f();
    private void measureBogie() {
        train.getBogieOrientationAndPosition(0, frontOut, topOut, rightOut, posOut);
    }

    private void writeHeadline() {
        StringBuilder headline = new StringBuilder();

        headline.append("No.\t");
        headline.append("PosX\t");
        headline.append("PosY\t");
        headline.append("PosZ\t");
        headline.append("FrontX\t");
        headline.append("FrontY\t");
        headline.append("FrontZ\t");
        headline.append("RightX\t");
        headline.append("RightY\t");
        headline.append("RightZ\t");
        headline.append("UpX\t");
        headline.append("UpY\t");
        headline.append("UpZ");
        System.out.println(headline);
    }
 
    private int num = 1;
    private void writeMeasurement() {
        StringBuilder line = new StringBuilder();

        line.append(num + "\t");
        line.append(posOut.x + "\t");
        line.append(posOut.y + "\t");
        line.append(posOut.z + "\t");
        line.append(frontOut.x + "\t");
        line.append(frontOut.y + "\t");
        line.append(frontOut.z + "\t");
        line.append(topOut.x + "\t");
        line.append(topOut.y + "\t");
        line.append(topOut.z + "\t");
        line.append(rightOut.x + "\t");
        line.append(rightOut.y + "\t");
        line.append(rightOut.z);
        System.out.println(line);
        num ++;
    }
}

The written result (example):

No. PosX PosY PosZ FrontX FrontY FrontZ RightX RightY RightZ UpX UpY UpZ
1 64.26366 2.5 -5.182514E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.17077E-9 1.892211E-9 -2.17077E-9 1.0
2 64.7713 2.5 -5.278569E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.299317E-9 1.892211E-9 -2.299317E-9 1.0
3 65.28258 2.5 -5.375313E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.432075E-9 1.892211E-9 -2.432075E-9 1.0
4 65.79778 2.5 -5.4728E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.569163E-9 1.892211E-9 -2.569163E-9 1.0
5 66.30961 2.5 -5.56965E-8 1.0 3.15369E-10 -1.892211E-9 -3.15369E-10 1.0 2.708614E-9 1.892211E-9 -2.708614E-9 1.0

This is for something else, but do you think it's possible to modify the script so that it saves a CSV of the coaster, but with all the roll points flipped 180 degrees?

This is for something else, but do you think it's possible to modify the script so that it saves a CSV of the coaster,...

There is no way to do this using a script, you'll need to purchase the professional license for this.

but with all the roll points flipped 180 degrees?

You can simply put a "-" (minus) before the roll points you want to flip.
Or something like this, in the measureBogie() method (choose which ones to invert):

    private void measureBogie() {
        train.getBogieOrientationAndPosition(0, frontOut, topOut, rightOut, posOut);
        frontOut.mul(-1);
        topOut.mul(-1);
        rightOut.mul(-1);
    }
1 to 6 of 6