31#include <robottools.h>
33#include <portability.h>
39 if (xmin > (x)) xmin = (x); \
40 if (xmax < (x)) xmax = (x); \
44 if (ymin > (y)) ymin = (y); \
45 if (ymax < (y)) ymax = (y); \
49 if (zmin > (z)) zmin = (z); \
50 if (zmax < (z)) zmax = (z); \
78 GfFatal(
"Track parameter path buffer has invalid size\n");
82 va_start(args, format);
83 len = vsnprintf(buffer, size, format, args);
86 if ((len < 0) || (len >= size)) {
88 GfFatal(
"Track parameter path too long\n");
97 for (
int i = 0; i <
track->nseg; i++) {
98 if (strcmp(name, segment->
name) == 0) {
101 segment = segment->
next;
110 for (
int i = 0; i <
track->nseg; i++) {
111 if (strcmp(name, segment->
name) == 0) {
114 segment = segment->
prev;
148 const int bankingtype,
149 const tdble startwidth,
150 const tdble endwidth,
158 const int bankingtype,
159 const tdble startwidth,
168 const int bankingtype,
169 const tdble startwidth,
170 const tdble endwidth,
172 const tdble borderheight,
173 const int borderstyle
189 const int BUFSIZE = 256;
196 if (strcmp(curSurf->
material, material) == 0) {
199 curSurf = curSurf->
next;
205 GfFatal(
"AddTrackSurface: Memory allocation failed\n");
234 const int BUFSIZE = 256;
238 for (side = 0; side < 2; side++) {
305 const int BUFSIZE = 256;
316 for (side = 0; side < 2; side++) {
375 Kew = (ew - sw) / (
tdble)steps;
376 ew = sw + (
tdble)(curStep + 1) * Kew;
377 sw = sw + (
tdble)(curStep)*Kew;
386 if ((sw > 0.0f) || (ew > 0.0f)) {
394 GfFatal(
"AddSides: memory allocation error");
418 while (bseg->
side[side] != NULL) {
419 bseg = bseg->
side[side];
430 mSeg->
barrier[side] = curBarrier;
461 int segread, curindex;
462 tdble radius, radiusend = 0, dradius;
469 tdble xr, yr, newxr, newyr;
470 tdble xl, yl, newxl, newyl;
473 tdble x1, x2, y1, y2;
475 tdble zsl, zsr, zel, zer, zs, ze;
476 tdble bankings, bankinge, dz;
482 const char* segtype = (
char*)NULL;
483 const char* material;
490 tdble tl, dtl, T1l, T2l;
491 tdble tr, dtr, T1r, T2r;
492 tdble curzel, curzer, curArc, curLength, curzsl, curzsr;
495 void* segNameHash = NULL;
496 const int BUFSIZE = 256;
499#define MAX_TMP_INTS 256
503 radius = arc =
length = alf = xr = yr = newxr = newyr = xl = yl = 0;
504 zel = zer = etgtl = etgtr = newxl = newyl = 0;
516 zsl = zsr = zel = zer = zs = ze = 0.0;
551 char* tmpmarks = strdup(marks);
552 char* s = strtok(tmpmarks,
";");
554 mi[ind] = (int)strtol(s, NULL, 0);
556 s = strtok(NULL,
";");
573 radius = radiusend = 0;
581 length = (radius + radiusend) / 2.0 * arc;
589 length = (radius + radiusend) / 2.0 * arc;
592 GfFatal(
"Unknown track segment type \"%s\" in segment \"%s\"\n", segtype, segName);
597 printf(
">>>>>>>>> DUPLICATED SEGMENT NAME \"%s\" PLEASE CHANGE IT !!!!\n", segName);
612 if (zs != -100000.0) {
616 zs = (zsl + zsr) / 2.0;
618 if (ze != -100000.0) {
621 else if (grade != -100000.0) {
625 ze = (zel + zer) / 2.0;
627 bankings = atan2(zsl - zsr, width);
628 bankinge = atan2(zel - zer, width);
631 dz = tan(bankings) * width / 2.0;
634 dz = tan(bankinge) * width / 2.0;
650 steps = (int)(
length / stepslg) + 1;
660 stgt = etgt = -100000.0;
663 if (stgt != -100000.0) {
664 stgtl = stgtr = stgt;
666 if (etgt != -100000.0) {
667 etgtl = etgtr = etgt;
672 stgtl = etgtl = (zel - zsl) /
length;
673 stgtr = etgtr = (zer - zsr) /
length;
682 dtl = 1.0 / (
tdble)steps;
686 dtr = 1.0 / (
tdble)steps;
691 curArc = arc / (
tdble)steps;
693 dradius = (radiusend - radius) / (
tdble)steps;
694 if (radiusend != radius) {
697 dradius = (radiusend - radius) / (
tdble)(steps - 1);
699 tdble tmpRadius = radius;
700 for (curStep = 0; curStep < steps; curStep++) {
701 tmpAngle += curLength / tmpRadius;
702 tmpRadius += dradius;
704 curLength *= arc / tmpAngle;
709 while (curStep < steps) {
721 curArc = curLength / radius;
728 curSeg->
next = curSeg;
729 curSeg->
prev = curSeg;
739 curSeg->
name = segName;
740 curSeg->
id = curindex;
747 int* mrks = (
int*)calloc(ind,
sizeof(
int));
750 memcpy(mrks, mi, ind *
sizeof(
int));
752 segExt->
marks = mrks;
753 curSeg->
ext = segExt;
762 curSeg->
length = curLength;
764 newxr = xr + curLength * cos(alf);
765 newyr = yr + curLength * sin(alf);
766 newxl = xl + curLength * cos(alf);
767 newyl = yl + curLength * sin(alf);
808 curSeg->
radiusr = radius + wi2;
809 curSeg->
radiusl = radius - wi2;
810 curSeg->
arc = curArc;
811 curSeg->
length = curLength;
813 innerradius = radius - wi2;
814 cenx = xl - innerradius * sin(alf);
815 ceny = yl + innerradius * cos(alf);
824 newxl = cenx + innerradius * sin(alf);
825 newyl = ceny - innerradius * cos(alf);
826 newxr = cenx + (innerradius + width) * sin(alf);
827 newyr = ceny - (innerradius + width) * cos(alf);
850 curSeg->
Kzl = tan(curSeg->
angle[
TR_YR]) * (innerradius + width);
858 for (j = 0; j < 36; j++) {
860 x1 = curSeg->
center.
x + (innerradius)*cos(alfl);
861 y1 = curSeg->
center.
y + (innerradius)*sin(alfl);
862 x2 = curSeg->
center.
x + (innerradius + width) * cos(alfl);
863 y2 = curSeg->
center.
y + (innerradius + width) * sin(alfl);
874 curSeg->
radiusr = radius - wi2;
875 curSeg->
radiusl = radius + wi2;
876 curSeg->
arc = curArc;
877 curSeg->
length = curLength;
879 innerradius = radius - wi2;
880 cenx = xr + innerradius * sin(alf);
881 ceny = yr - innerradius * cos(alf);
890 newxl = cenx - (innerradius + width) * sin(alf);
891 newyl = ceny + (innerradius + width) * cos(alf);
892 newxr = cenx - innerradius * sin(alf);
893 newyr = ceny + innerradius * cos(alf);
921 al = curSeg->
arc / 36.0;
924 for (j = 0; j < 36; j++) {
926 x1 = curSeg->
center.
x + (innerradius + width) * cos(alfl);
927 y1 = curSeg->
center.
y + (innerradius + width) * sin(alfl);
928 x2 = curSeg->
center.
x + innerradius * cos(alfl);
929 y2 = curSeg->
center.
y + innerradius * sin(alfl);
939 totLength += curSeg->
length;
976 memset(&geo, 0,
sizeof(geo));
988 const tdble missing = std::numeric_limits<tdble>::quiet_NaN();
989 const tdble maxFinite = (std::numeric_limits<tdble>::max)();
994 if (fabs(lat) <= 90.0 && fabs(lon) <= 180.0) {
998 }
else if (lat == lat || lon == lon) {
999 GfError(
"Track Georeference: invalid or incomplete latitude/longitude\n");
1001 if (fabs(alt) <= maxFinite) {
1004 }
else if (alt == alt) {
1005 GfError(
"Track Georeference: invalid altitude\n");
1007 if (fabs(heading) <= maxFinite) {
1008 double degrees = fmod((
double)heading, 360.0);
1009 if (degrees < 0.0) degrees += 360.0;
1012 }
else if (heading == heading) {
1013 GfError(
"Track Georeference: invalid heading\n");
1029 const char* segName;
1034 const char* paramVal;
1035 const int BUFSIZE = 256;
1036 char path2[BUFSIZE];
1048 GfFatal(
"Track definition contains no valid segments\n");
1078 if (strcmp(paramVal,
"right") == 0) {
1085 if ((pitEntrySeg != NULL) && (pitExitSeg != NULL) && (pitStart != NULL) && (pitEnd != NULL)) {
1114 mSeg = pitStart->
prev;
1118 while (i < pits->nMaxPits) {
1124 if (toStart >= mSeg->length) {
1125 toStart -= mSeg->length;
1129 switch (pits->
side) {
1131 curPitSeg = mSeg->
rside;
1132 if (curPitSeg->
rside) {
1133 offset = curPitSeg->
width;
1134 curPitSeg = curPitSeg->
rside;
1138 curPitSeg = mSeg->
lside;
1139 if (curPitSeg->
lside) {
1140 offset = curPitSeg->
width;
1141 curPitSeg = curPitSeg->
lside;
1149 switch (pits->
side) {
1161 toStart += pits->
len;
1162 if (toStart >= mSeg->length) {
1163 toStart -= mSeg->length;
1169 for (mSeg = pitStart->
prev; mSeg != pitEnd->
next->
next; mSeg = mSeg->
next) {
1171 switch (pits->
side) {
1173 curSeg = mSeg->
rside;
1174 curSeg2 = curSeg->
rside;
1175 if ((mSeg != pitStart->
prev) && (mSeg != pitEnd->
next)) {
1180 curSeg = mSeg->
lside;
1181 curSeg2 = curSeg->
lside;
1182 if ((mSeg != pitStart->
prev) && (mSeg != pitEnd->
next)) {
1187 if ((mSeg != pitStart->
prev) && (mSeg != pitEnd->
next)) {
1193 else if (mSeg == pitStart->
prev) {
1199 else if (mSeg == pitEnd->
next) {
1215 GfFatal(
"ReadTrack4: Memory allocation error\n");
1218 if (*camList == NULL) {
1220 curCam->
next = curCam;
1224 (*camList)->
next = curCam;
1236 for (i = 0; i <
theTrack->nseg; i++) {
1237 if (curSeg->
id == segId) {
1240 curSeg = curSeg->
next;
1243 trkPos.
seg = curSeg;
1257 for (i = 0; i <
theTrack->nseg; i++) {
1258 if (curSeg->
id == segId) {
1261 curSeg = curSeg->
next;
1272 curSeg->
cam = curCam;
1273 curSeg = curSeg->
next;
1274 }
while (curSeg->
id != segId);
1287 for (i = 0; i <
theTrack->nseg; i++) {
1298 if (curSeg->
lside) {
1304 if (curSeg->
rside) {
1310 curSeg = curSeg->
next;
1314 if (*camList != NULL) {
1317 curCam = curCam->
next;
1321 }
while (curCam != *camList);
1339 al = curBorder->
arc / 36.0 *
sign;
1342 for (j = 0; j < 36; j++) {
1344 x = curBorder->
center.
x + radius * cos(alfl);
1345 y = curBorder->
center.
y + radius * sin(alfl);
1367 curBorder->
Kyl = (endwidth - startwidth) / curBorder->
arc;
1389 const int bankingtype,
1390 const tdble startwidth,
1391 const tdble endwidth,
1392 const tdble maxwidth
1397 if (turntype ==
TR_LFT) {
1414 curBorder->
arc = curSeg->
arc;
1432 curBorder->
arc = curSeg->
arc;
1464 const int bankingtype,
1465 const tdble startwidth,
1466 const tdble endwidth
1496 curBorder->
Kyl = (endwidth - startwidth) / curBorder->
length;
1526 const int righttype,
1527 const int bankingtype,
1528 const tdble startwidth,
1529 const tdble endwidth,
1531 const tdble borderheight,
1532 const int borderstyle
1537 curSeg->
lside = curBorder;
1540 curBorder->
type2 = lefttype;
1543 curSeg->
rside = curBorder;
1546 curBorder->
type2 = righttype;
1551 curBorder->
width =
MIN(startwidth, endwidth);
1552 tdble maxWidth =
MAX(startwidth, endwidth);
1556 curBorder->
height = borderheight;
1557 curBorder->
style = borderstyle;
1565 switch (curSeg->
type) {
Scalar length(const Quaternion &q)
float tdble
Floating point type used in TORCS.
void GfHashRelease(void *hash, tfHashFree hashFree)
Release a hash table.
int GfHashAddStr(void *hash, const char *key, const void *data)
Add an element with a string key to a hash table.
const void * GfHashGetStr(void *hash, const char *key)
Get the user data associated with a string key.
void * GfHashCreate(int type)
Create a new hash table.
const char * GfParmGetStr(void *parmHandle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle.
tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle.
char * GfParmListGetCurEltName(void *handle, const char *path)
Get current subsection name of the parameter set handle during subsection iteration.
int GfParmListSeekNext(void *handle, const char *path)
Advance to the next immediate subsection.
int GfParmListSeekFirst(void *handle, const char *path)
Select the first immediate subsection of a section.
int GfParmSetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
Set a numerical parameter in the parameter set handle based on subsection iteration.
tdble GfParmGetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle based on subsection iteration.
const char * GfParmGetCurStr(void *handle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle based on subsection iteration.
struct trackSeg tTrackSeg
Track segment (tTrackSeg) The segments can be straights (type TR_STR): (the track goes from the right...
tTrkLocPos pos
Center of the pit position.
Optional v4 geographic reference at the main road centre at the start of the first segment (seg->next...
tdble heading
Radians clockwise from true north, [0, 2*pi)
tdble altitude
Metres above mean sea level at reference road centre.
int hasLocation
Both latitude and longitude are available.
tdble longitude
Degrees east, [-180, 180].
tdble latitude
Degrees north, [-90, 90].
tTrackSeg * pitStart
Pit lane segment.
tTrackSeg * pitEntry
Pit lane segment.
int nPitSeg
actual number of pits
tTrackOwnPit * driversPits
List of pits by driver.
tTrackSeg * pitExit
Pit lane segment.
tdble len
Lenght of each pit stop.
tTrackSeg * pitEnd
Pit lane segment.
tdble speedLimit
Speed limit between pitStart and pitEnd.
int nMaxPits
number max of pits
tdble width
Width of each pit stop.
Location on the track in local coordinates.
tdble toMiddle
Distance (+ to left, - to right) relative to the middle of segment.
tdble toLeft
Distance (- to left, + to right) relative to left side of segment.
tdble toRight
Distance (+ to left, - to right) relative to the right side of segment.
tTrackSeg * seg
Track segment.
int type
Type of description:
tdble toStart
Distance to start of segment (or arc if turn)
tdble width
Barrier width.
tdble height
Barrier height.
tTrackSurface * surface
Barrier surface.
int type
Geometrical type:
tTrackSurface * surface
Segment surface.
tdble height
Max height for curbs.
t3Dd vertex[4]
Coordinates of the 4 corners of the segment.
tdble radiusr
Radius in meters of the right side of the track (>0)
unsigned int raceInfo
Type of segment regarding the race: Mask value in:
tdble radius
Radius in meters of the middle of the track (>0)
tdble arc
Arc in rad of the curve (>0)
tdble lgfromstart
Length of beginning of segment from starting line.
t3Dd center
Center of the curve.
const char * name
Segment name.
tdble length
Length in meters of the middle of the track.
tdble radiusl
Radius in meters of the left side of the track (>0)
tTrackBarrier * barrier[2]
Segment barriers.
struct trackSeg * next
Next segment.
tdble startWidth
Width of the beginning of the segment.
struct trackSeg * prev
Previous segment.
int style
Border and barrier segments style:
struct trackSeg * side[2]
tdble width
Width of the segment (if constant width)
tdble endWidth
Width of the end of the segment.
tdble kRebound
Coefficient of energy restitution.
tdble kDammage
Dammages in case of collision.
tdble kFriction
Coefficient of friction.
tdble kRollRes
Rolling resistance.
const char * material
Type of material used.
struct trackSurface * next
Next surface in list.
tdble kRoughWaveLen
Wave length in m of the surface.
tdble kRoughness
Roughtness in m of the surface (wave height)
#define GF_HASH_TYPE_STR
String key based hash table.
static void GfFatal(const char *fmt,...)
static int barrierStyle[2]
static tdble borderHeight[2]
static tTrackSurface * borderSurface[2]
static const char * barrierMaterial[2]
static tdble borderWidth[2]
static tdble barrierWidth[2]
static tTrackSurface * barrierSurface[2]
static const char * sideMaterial[2]
static const char * ValStyle[4]
static tdble sideStartWidth[2]
static tdble sideEndWidth[2]
static int sideBankType[2]
static tdble barrierHeight[2]
static tTrackSurface * sideSurface[2]
static tdble GlobalStepLen
static const char * borderMaterial[2]
static int borderStyle[2]
static tTrackSurface * getTrackSurface(void *trackHandle, tTrack *theTrack, const char *material)
Gets surface properties based on the material.
static tTrackSeg * findFirstSegmentByName(const tTrack *track, const char *name)
static const char * SectBarrier[2]
static tTrackSeg * findLastSegmentByName(const tTrack *track, const char *name)
static void readGeoreference(tTrack *track, void *handle)
static void initSideForStraight(tTrackSeg *const curBorder, const tTrackSeg *const curSeg, const int side, const int bankingtype, const tdble startwidth, const tdble endwidth)
Set up side and border track segments for straight segments.
static const char * SectBorder[2]
static void formatTrackPath(char *buffer, const int size, const char *format,...)
Format a track parameter path and fail if it would be truncated.
static const char * SectSide[2]
static void updateMinMaxForTurn(const tTrackSeg *const curBorder, const tdble radius, const tdble sign, const tdble z)
Update global min/max values for turns (discretized approximation).
void ReadTrack4(tTrack *theTrack, void *TrackHandle, tRoadCam **camList, int ext)
static void readDefaultSideParameters(void *trackHandle, tTrack *theTrack)
Reads default side/border track segment parameters.
static tTrackSeg * commonSideInit(tTrackSeg *const curSeg, const int side, const int lefttype, const int righttype, const int bankingtype, const tdble startwidth, const tdble endwidth, tTrackSurface *surface, const tdble borderheight, const int borderstyle)
Common side/border allocation and initialization for straights and turns.
static void CreateSegRing(void *TrackHandle, tTrack *theTrack, int ext)
static void initAnglesAndGradients(tTrackSeg *const curBorder, const tdble startwidth, const tdble endwidth)
Set up border segment angles and gradients.
static void addSides(tTrackSeg *curSeg, void *trackHandle, tTrack *theTrack, int curStep, int steps)
Adds the specified side/border/barrier segments to given main track segement.
static void normSeg(tTrackSeg *curSeg)
Segment coordinate normalization, track is moved to the origin of the coordinate system.
static void initSideForTurn(const int turntype, tTrackSeg *const curBorder, const tTrackSeg *const curSeg, const int side, const int bankingtype, const tdble startwidth, const tdble endwidth, const tdble maxwidth)
Set up side and border track segments for turns.
static void * TrackHandle
#define TRK_ATT_GEO_HEADING
#define TRK_SECT_GEOREFERENCE
#define TR_XS
X Start angle.
#define TRK_ATT_PROFTGTEL
#define TR_START
Segment after start line.
struct TrackOwnPit tTrackOwnPit
Driver's pit.
#define TR_RSIDE
Right side segment (outer segment)
#define TRK_ATT_PROFTGTER
#define TRK_ATT_PROFSTEPS
#define TR_CS
Center start angle.
#define TR_LAST
Segment before start line.
#define TRK_ATT_PROFTGTSL
#define TR_PITEND
Car pit End.
#define TR_PITSTART
Car pit Star.
#define TR_YR
Y Right angle.
#define TR_MAIN
Main track segment (ie road part)
struct trackSurface tTrackSurface
Surface.
#define TR_FENCE
Fence (no width) (barrier only)
#define TRK_ATT_RADIUSEND
#define TR_SPEEDLIMIT
Segment where the speed is limited.
#define TR_LFT
Left curve.
#define TRK_SECT_SURFACES
#define TRK_SECT_LBARRIER
#define TR_XE
X End angle.
#define TR_EL
End-Left corner.
#define TRK_ATT_PROFSTEPSLEN
#define TR_ZE
Z End angle.
struct RoadCam tRoadCam
road camera
#define TR_RBORDER
Right border segment (inner segment)
#define TR_NORMAL
Normal segment.
#define TR_YL
Y Left angle.
#define TRK_ATT_GEO_LATITUDE
#define TR_PITEXIT
Segment where the pit lane cross the main track.
#define TR_LBORDER
Left border segment (inner segment)
struct SegExt tSegExt
Extended track segment.
#define TR_LPOS_MAIN
Relative to the main segment, mostly used for racing on the main track.
#define TRK_ATT_PROFTGTSR
#define TR_PIT_ON_TRACK_SIDE
The pits are on the track side.
struct trackBarrier tTrackBarrier
Barrier.
#define TRK_ATT_GEO_ALTITUDE
#define TR_PITENTRY
Segment where the pit lane cross the main track.
#define TR_ER
End_Right corner.
#define TR_PLAN
Flat (border only)
#define TR_LSIDE
Left side segment (outer segment)
#define TR_CURB
Curb (border only)
#define TR_SL
Start-Left corner.
#define TR_RGT
Right curve.
#define TR_PITBUILDING
Pit building wall (barrier only)
#define TR_ZS
Rotation angles of the track in rad anti-clockwise: Index in:
#define TRK_ATT_GEO_LONGITUDE
#define TR_WALL
Wall (barrier only)
#define TR_SR
Start-Right corner.
#define TRK_SECT_RBARRIER
tdble TrackSpline(tdble p0, tdble p1, tdble t0, tdble t1, tdble t)
void TrackLocal2Global(tTrkLocPos *p, tdble *X, tdble *Y)
tdble TrackHeightL(tTrkLocPos *p)
int track(tModInfo *modInfo)