Back to RCT TID home


Each track piece in RCT can be described as having a starting pitch and roll, an ending pitch and roll and an X,Y,Z displacement, as well as an 'amount of curvature' (none, +/- 45 degrees, +/- 90 degrees, 180 degrees) The track pieces are constrained to start (and end) on a 'sub-grid' which is half the dimension of the land grid in RCT. The horizontal and vertical dimensions have different scaling in RCT. There is no 'starting orientation' information inherent in the track piece.

A few months ago, I made a large table which used track code (0..255) as rows and the above items as columns. I used a one-byte code for the pitch, roll, etc to keep the table at a reasonable size and complexity. Since the track pieces must be aligned with the sub-grid, the use of integers is much preferable to floating point numbers. The track pieces can be combined by keeping track of the location and orientation of the pieces (the curvature and displacement is rotated depending on the orientation). I used the table in a program to read a TD4 file and confirm that it made a complete circuit...the last piece would end at the beginning of the first piece. I also determined the X/Y/Z space required by the track. But I wasn't ready to make my own coaster simulator program.

Now UltraCoaster is available and NoLimits may be available soon. I asked Ole Lange if he would be interested in a converter from RCT to NoLimits but he was not interested at that time. I decided to go ahead and try UC. I had added two columns to the table (start and end curvature magnitude) to facilitate a conversion to NoLimits but that information is not used in UC so I've removed those columns. Note that the creator of UltraCoaster is not involved in any way with this convertor so don't bug him about it!

Some track elements such as loops are not amenable to implent as single curves. That requires that the 'table' have a variable number of rows for each track piece. I decided to abandon the use of a table and use the rows as parameters in procedure calls, all within a conditional execution block. I had to abandon the use of integers for the displacement values - it became too cumbersome. So the data was changed to use floats and code was added to constrain the floats to the sub grid. The grid also had to be halved so pieces are now pinned to one-quarter of the RCT grid lines. I used cubic splines (described below) to draw the track segments. The result, after much work and debugging, was version 1.0 of the TD4viewer which merely displayed the tracks as simple lines (viewable from any angle).

I then bought UltraCoaster and investigated the track file structure. It is fairly simple. A short header is followed by control point structures. The point location is followed by three cosine/sine pairs for the rotation about Y, rotation about Z and track roll. There is a track type specifier and then (except for the first point) a structure of t-steps. I modified the track segment structure used internally in my program to facilitate conversion of the UC track data. So the program can read TD4 or RCD files (there is limited ability to read NoLimits files as well). I also provided the ability to convert from my track segment structures to the RCD format. Version 1.1 of TD4viewer has this ability.

There was a bug with calculating the slopes on diagnonal RCT pieces (needed a square root of two correction) and a minor bug with the drawing of supports on the TD4viewer screen for tracks which do not start at ground level. Those have been corrected and a couple of features added in version 1.2 (color information is maintained and consecutive linear track elements are combined into one segment). There are quite a few details addressed as well, but they aren't really interesting. The biggest deficiency in the program is the quality of conversion of inversion elements and the transition of banking. It is not simple to improve either of these features. I have no specific plans to address them at this time.

3D Curves

UC, NoLimits and TD4viewer use cubic splines to draw the curved track.This is a technique to draw a line between two points, with direction vectors at each point. Consider the 'S' curve track. The direction vector is the same at the start and end points, but there is a lateral displacement between the points. A 'parametric' curve is used. That means that we temporarily forget about the X,Y,Z variables and just think about some arbitrary variable, which we call 't'. Then we arbitrarily decide that a cubic equation { f(t) = At3 + Bt2 + Ct + D }would look nice between the two points (P0, P1) which we want to connect. Also arbitrarily, we decide to let t range from zero (at P0) to one (at P1).We can refer to the direction vectors at the two points as V0 & V1. Now, suprisingly, we have enough information to determine the constant values A, B, C and D. When t = zero, the equation reduces to f(0) = D. Consequently, D '=' P0. Similarly, f(1) = A + B + C + D '=' P1. The derivative of the equation above {f'(t) = 3At2 + 2Bt + C } will give the direction of the curve at any point. We can calculate f'(0) = C '=' V0 and f'(1) = 3A + 2B + C '=' V1. Now we have four equations for the four unknowns.

Actually, we have to calculate three sets of A, B, C & D. One for X, one for Y, and one for Z. Now you can finally draw a 'curve'. The 'curve' will consist of straight line segments between the two points. Use a loop with the value of t ranging from zero to one in as many steps as you want. The more points you use, the smoother the curve and the longer it takes to draw. For each value of t, use the 'X' set of A, B, C, D to determine the X value of the curve, Similarly, calculate the Y and Z values. Then, simply draw a straight line from the last drawn point to the new coordinates.

There is a variation on this scheme called Bezier curves (which is used in NoLimits). It is based on the same parametric equation but the calculation of points is speeded up. Extra points are defined which enable the computer to perform division by two to interpolate the curve in 'half' each time. After a curve has been halved enough times, it becomes a similar set of connected straight line segments as determined in the simple method described above. The only difference as far as the point description is concerned is that the bezier points are specified rather than the vectors. The Bezier points are related to the vectors as follows: B0 = P0 + 3V0.