#!/usr/bin/env python ## trk-convert - Turn a RARS .trk file into the C++ code for a Vamos track. ## This file is part of Vamos Automotive Simulator. ## Copyright (C) 2001 Sam Varner ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Many thanks to those who produced the tracks for RARS, and to the # developers who placed this project under the GPL. I owe you. # Usage: trk-convert trackfile.trk [ trackfile.cc ] # If you don't specify at output file, the code is send to standard # output. After converting, save the file as `track.cc' and # recomplie. You need the file `trk-convert-header' in the current # directory to produce the C++ file. # notes on cleanup... import sys import re from math import pi header = """ textures/sky_sides.png textures/sky_top.png textures/sky_bottom.png 1.0 0.1 1.0 0.0 0.01 100.0 textures/track2.png 200.0 0.7 0.1 5.0 20.0 0.03 2.0 textures/grass.png 10.0 12.0 0.8 0.0 40.0 200.0 0.05 2.0 textures/gravel3.png 10.0 10.0 1.0 0.8 1.0 5.0 0.0 1.0 textures/blue-tires.png 0.33 3.0 1.0 0.1 1.0 0.0 0.0 1.0 textures/rail.png 0.5 10.0 1.0 0.1 1.0 0.0 0.0 1.0 textures/wall.png 1.0 10.0 1.0 0.1 1.0 0.0 0.06 2.0 textures/blue-kerb.png 2.0 4.0 [ wall grass kerb track kerb grass rail ] [ wall track kerb track kerb grass rail ] [ wall grass kerb track kerb gravel tires ] [ wall track kerb track kerb gravel tires ] [ tires gravel kerb track kerb grass rail ] """ # Give a usage message if not enough arguments were passed or if the first # argument can't be opened as a file. help = 0 angle_type = '' progname = sys.argv [0].split ('/')[-1] trackfile = '' close = 0 argv = sys.argv [1:] argc = len (sys.argv) if argc < 2 or argc > 4: help = 1 else: if argv [0] == '-r' or argv [0] == '--radians': angle_type = 'radians' argv = argv [1:] elif argv [0] == '-d' or argv [0] == '--degrees': angle_type = 'degrees' argv = argv [1:] elif argv [0] == '-l' or argv [0] == '--length': angle_type = 'length' argv = argv [1:] elif argv [0] == '-c' or argv [0] == '--close': close = 1 argv = argv [1:] if argv: try: track = open (argv [0]) trackfile = argv [0].split ('/')[-1] except IOError: help = 1 if help: print 'Usage: trk-convert [ [ -r | --radians ] | [ -d | --degrees ]' print '| [ -l | --length ] ] trackfile.trk [ trackfile.cc ]' sys.exit (1) else: argv = argv [1:] # If an output file argument is given, redirect the prints to the file. if argv: sys.stdout = open (argv [0], 'w') # Convert feet to meters. def meters (feet): return feet * 0.3048 # exact # This regex matches a straight or curve definition. segment_regex = re.compile ('[ \t]*([-0-9\.]+)[ \t]+([0-9\.]+).*') # Thas regex matches a line with only whitespace. blank_regex = re.compile ('[ \t]*\n') print '' print '' % \ (trackfile, progname) print '' % trackfile print header # The .trk file has three sections separated by lines of whitespace. # `section' is incremented when we start to read a new section. section = 0 # The previous line read is saved so we can detect consecutive lines of # whitespace. last_line = '' # Read in the file. data = track.readlines () # Find the width of the track. width = meters (float (data [2].split() [0])) # Loop over the lines in the file. Record the information about the track. total_angle = 0.0 track = [] for line in data: # See if this line starts a new section. if blank_regex.match (line) and not blank_regex.match (last_line): section += 1 last_line = line # Ignore the first two sections. if section < 3: continue # Get the numbers from the line. match = segment_regex.match (line) if not match: continue track.append ([float (match.group (1)), float (match.group (2))]) if track [-1][0] > 0.0: total_angle += track [-1][1] elif track [-1][0] < 0.0: total_angle -= track [-1][1] # Determine the quantity used along with the radius for defining curves. total_angle = abs (total_angle) if not angle_type: if abs (total_angle - 6.28) < 0.1: angle_type = 'radians' elif abs (total_angle - 360.0) < 5.0: angle_type = 'degrees' else: angle_type = 'length' first_segment = 1 # Loop over the track information. for line in track: # Convert the ASCII representation to floats. radius = line [0] length = line [1] # Convert feet to meters. radius = meters (radius) # Straights have a radius of 0.0 if radius != 0.0: # This is a curve. # The length of a curve may be in feet or radians. Which one is used # is not explicitly stated in the file format, so we have to guess. # I'll assume that we won't see and 6 radian curves. if angle_type == 'radians': # The length is in radians. # Put the length in meters. (Length has already been converted.) length = abs (radius * length) elif angle_type == 'degrees': length = abs (radius * length * pi / 180.0) else: # The length must be a distance. Convert to meters. length = meters (length) # Some right turns have very small radii. I'm assuming that means # that the radius is measured to the right edge of the track. center_radius = radius - width / 2.0 factor = center_radius / radius radius *= factor length *= factor # Put gravel on the outside of the cuves. if radius < 0.0: print ' ' else: print ' ' print ' 5.0' else: # This is a straight. # Convert to meters. length = meters (length) print ' ' print ' 10.0' print ' %f' % length if radius != 0.0: print ' %f' % radius if first_segment: print ' [ 0.0, 25.0 ]' print ' [ 0.0, 25.0 ]' print ' [ 0.0, 8.0 ]' print ' [ 0.0, 8.0 ]' print ' 2.0' print ' 2.0' first_segment = 0 print ' ' print # Print out the end of the XML file. I'ts not a good idea to try # build_circuit before seeing how the conversion went. print ' ' if close == 1: print ' ' else: print ' ' print print ' ' print ' 10.0' print ' 700.0' print ' 1800.0' print ''