TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
track4.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : track4.cpp
4 created : Sat May 18 12:46:26 CEST 2002
5 copyright : (C) 2002-2026 by Eric EspiƩ, Bernhard Wymann
6 email : berniw@bluewin.ch
7
8 ***************************************************************************/
9
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
23
24#include <stdlib.h>
25#include <math.h>
26#include <stdio.h>
27#include <stdarg.h>
28#include <limits>
29
30#include <tgf.h>
31#include <robottools.h>
32#include <track.h>
33#include <portability.h>
34#include "trackinc.h"
35
37
38#define TSTX(x) do { \
39 if (xmin > (x)) xmin = (x); \
40 if (xmax < (x)) xmax = (x); \
41 } while (0)
42
43#define TSTY(y) do { \
44 if (ymin > (y)) ymin = (y); \
45 if (ymax < (y)) ymax = (y); \
46 } while (0)
47
48#define TSTZ(z) do { \
49 if (zmin > (z)) zmin = (z); \
50 if (zmax < (z)) zmax = (z); \
51 } while (0)
52
53/*
54 * Sides global variables
55 */
56static const char* SectSide[2] = { TRK_SECT_RSIDE, TRK_SECT_LSIDE };
57static const char* SectBorder[2] = { TRK_SECT_RBORDER, TRK_SECT_LBORDER };
58static const char* SectBarrier[2] = { TRK_SECT_RBARRIER, TRK_SECT_LBARRIER };
59
60static const char* ValStyle[] = { TRK_VAL_PLAN, TRK_VAL_CURB, TRK_VAL_WALL, TRK_VAL_FENCE, TRK_VAL_FENCE }; // TODO: TRK_VAL_FENCE 2 times, remove?
61
62
72static void formatTrackPath(char* buffer, const int size, const char* format, ...)
73{
74 va_list args;
75 int len;
76
77 if (size <= 0) {
78 GfFatal("Track parameter path buffer has invalid size\n");
79 exit(1);
80 }
81
82 va_start(args, format);
83 len = vsnprintf(buffer, size, format, args);
84 va_end(args);
85
86 if ((len < 0) || (len >= size)) {
87 buffer[0] = '\0';
88 GfFatal("Track parameter path too long\n");
89 exit(1);
90 }
91}
92
93/* track->seg is the final generated segment in the circular ring. */
94static tTrackSeg* findFirstSegmentByName(const tTrack* track, const char* name)
95{
96 tTrackSeg* segment = track->seg->next;
97 for (int i = 0; i < track->nseg; i++) {
98 if (strcmp(name, segment->name) == 0) {
99 return segment;
100 }
101 segment = segment->next;
102 }
103 return NULL;
104}
105
106
107static tTrackSeg* findLastSegmentByName(const tTrack* track, const char* name)
108{
109 tTrackSeg* segment = track->seg;
110 for (int i = 0; i < track->nseg; i++) {
111 if (strcmp(name, segment->name) == 0) {
112 return segment;
113 }
114 segment = segment->prev;
115 }
116 return NULL;
117}
118
119
122static int sideBankType[2];
123static const char* sideMaterial[2];
125
126static int envIndex;
127
130static int borderStyle[2];
131static const char* borderMaterial[2];
133
136static int barrierStyle[2];
137static const char* barrierMaterial[2];
139
141
142// Function prototypes
143static void initSideForTurn(
144 const int turntype,
145 tTrackSeg* const curBorder,
146 const tTrackSeg* const curSeg,
147 const int side,
148 const int bankingtype,
149 const tdble startwidth,
150 const tdble endwidth,
151 const tdble maxwidth
152);
153
154static void initSideForStraight(
155 tTrackSeg* const curBorder,
156 const tTrackSeg* const curSeg,
157 const int side,
158 const int bankingtype,
159 const tdble startwidth,
160 const tdble endwidth
161);
162
164 tTrackSeg* const curSeg,
165 const int side,
166 const int lefttype,
167 const int righttype,
168 const int bankingtype,
169 const tdble startwidth,
170 const tdble endwidth,
171 tTrackSurface* surface,
172 const tdble borderheight,
173 const int borderstyle
174);
175
176
187static tTrackSurface* getTrackSurface(void* trackHandle, tTrack* theTrack, const char* material)
188{
189 const int BUFSIZE = 256;
190 char path[BUFSIZE];
191 tTrackSurface* curSurf;
192
193 // Search within existing surfaces
194 curSurf = theTrack->surfaces;
195 while (curSurf) {
196 if (strcmp(curSurf->material, material) == 0) {
197 return curSurf;
198 }
199 curSurf = curSurf->next;
200 }
201
202 // Create a new surface
203 curSurf = (tTrackSurface*)malloc(sizeof(tTrackSurface));
204 if (!curSurf) {
205 GfFatal("AddTrackSurface: Memory allocation failed\n");
206 exit(1);
207 }
208
209 curSurf->material = material;
210 formatTrackPath(path, BUFSIZE, "%s/%s", TRK_SECT_SURFACES, material);
211 curSurf->kFriction = GfParmGetNum(trackHandle, path, TRK_ATT_FRICTION, (char*)NULL, 0.8f);
212 curSurf->kRollRes = GfParmGetNum(trackHandle, path, TRK_ATT_ROLLRES, (char*)NULL, 0.001f);
213 curSurf->kRoughness = GfParmGetNum(trackHandle, path, TRK_ATT_ROUGHT, (char*)NULL, 0.0f) / 2.0f;
214 curSurf->kRoughWaveLen = 2.0 * PI / GfParmGetNum(trackHandle, path, TRK_ATT_ROUGHTWL, (char*)NULL, 1.0f);
215 curSurf->kDammage = GfParmGetNum(trackHandle, path, TRK_ATT_DAMMAGE, (char*)NULL, 10.0f);
216 curSurf->kRebound = GfParmGetNum(trackHandle, path, TRK_ATT_REBOUND, (char*)NULL, 0.5f);
217
218 curSurf->next = theTrack->surfaces;
219 theTrack->surfaces = curSurf;
220
221 return curSurf;
222}
223
224
230static void readDefaultSideParameters(void* trackHandle, tTrack* theTrack)
231{
232 int side;
233 const char* style;
234 const int BUFSIZE = 256;
235 char path[BUFSIZE];
236
237 // Side: right and left (see SectSide, SectBorder, SectBarrier)
238 for (side = 0; side < 2; side++) {
239 // Side parameters
240 formatTrackPath(path, BUFSIZE, "%s/%s", TRK_SECT_MAIN, SectSide[side]);
241 sideMaterial[side] = GfParmGetStr(trackHandle, path, TRK_ATT_SURF, TRK_VAL_GRASS);
242 sideSurface[side] = getTrackSurface(trackHandle, theTrack, sideMaterial[side]);
243 sideEndWidth[side] = GfParmGetNum(trackHandle, path, TRK_ATT_WIDTH, (char*)NULL, 0.0);
244
245 // Banking of sides
246 if (strcmp(TRK_VAL_LEVEL, GfParmGetStr(trackHandle, path, TRK_ATT_BANKTYPE, TRK_VAL_LEVEL)) == 0) {
247 sideBankType[side] = 0;
248 }
249 else {
250 sideBankType[side] = 1;
251 }
252
253 // Border parameters
254 formatTrackPath(path, BUFSIZE, "%s/%s", TRK_SECT_MAIN, SectBorder[side]);
255 borderMaterial[side] = GfParmGetStr(trackHandle, path, TRK_ATT_SURF, TRK_VAL_GRASS);
256 borderSurface[side] = getTrackSurface(trackHandle, theTrack, borderMaterial[side]);
257 borderWidth[side] = GfParmGetNum(trackHandle, path, TRK_ATT_WIDTH, (char*)NULL, 0.0);
258 borderHeight[side] = GfParmGetNum(trackHandle, path, TRK_ATT_HEIGHT, (char*)NULL, 0.0);
259 style = GfParmGetStr(trackHandle, path, TRK_ATT_STYLE, TRK_VAL_PLAN);
260
261 if (strcmp(style, TRK_VAL_PLAN) == 0) {
262 borderStyle[side] = TR_PLAN;
263 }
264 else if (strcmp(style, TRK_VAL_CURB) == 0) {
265 borderStyle[side] = TR_CURB;
266 }
267 else {
268 borderStyle[side] = TR_WALL;
269 }
270
271 // Barrier parameters
272 formatTrackPath(path, BUFSIZE, "%s/%s", TRK_SECT_MAIN, SectBarrier[side]);
273 barrierMaterial[side] = GfParmGetStr(trackHandle, path, TRK_ATT_SURF, TRK_VAL_BARRIER);
274 barrierSurface[side] = getTrackSurface(trackHandle, theTrack, barrierMaterial[side]);
275 barrierHeight[side] = GfParmGetNum(trackHandle, path, TRK_ATT_HEIGHT, (char*)NULL, 0.6f);
276 style = GfParmGetStr(trackHandle, path, TRK_ATT_STYLE, TRK_VAL_FENCE);
277 if (strcmp(style, TRK_VAL_FENCE) == 0) {
278 barrierStyle[side] = TR_FENCE;
279 barrierWidth[side] = 0;
280 }
281 else {
282 barrierStyle[side] = TR_WALL;
283 barrierWidth[side] = GfParmGetNum(trackHandle, path, TRK_ATT_WIDTH, (char*)NULL, 0.5);
284 }
285 }
286}
287
288
297static void addSides(tTrackSeg* curSeg, void* trackHandle, tTrack* theTrack, int curStep, int steps)
298{
299 tTrackSeg* mSeg;
300 tTrackBarrier* curBarrier;
301 tdble w, sw, ew, bw;
302 int side;
303 const char* style;
304 tdble Kew;
305 const int BUFSIZE = 256;
306 char path[BUFSIZE];
307 char path2[BUFSIZE];
308 char* segName;
309
310 mSeg = curSeg;
311
312 formatTrackPath(path, BUFSIZE, "%s/%s", TRK_SECT_MAIN, TRK_LST_SEGMENTS);
313 segName = GfParmListGetCurEltName(trackHandle, path);
314 formatTrackPath(path, BUFSIZE, "%s/%s/%s", TRK_SECT_MAIN, TRK_LST_SEGMENTS, segName);
315
316 for (side = 0; side < 2; side++) {
317 curSeg = mSeg;
318
319 if (curStep == 0) {
320 // Initialize on the first step
321 // Side parameters
322 formatTrackPath(path2, BUFSIZE, "%s/%s", path, SectSide[side]);
323 sw = GfParmGetNum(trackHandle, path2, TRK_ATT_SWIDTH, (char*)NULL, sideEndWidth[side]);
324 w = GfParmGetNum(trackHandle, path2, TRK_ATT_WIDTH, (char*)NULL, sw);
325 ew = GfParmGetNum(trackHandle, path2, TRK_ATT_EWIDTH, (char*)NULL, w);
326
327 sideStartWidth[side] = sw;
328 sideEndWidth[side] = ew;
329 sideMaterial[side] = GfParmGetStr(trackHandle, path2, TRK_ATT_SURF, sideMaterial[side]);
330 sideSurface[side] = getTrackSurface(trackHandle, theTrack, sideMaterial[side]);
331
332 // Border parameters
333 formatTrackPath(path2, BUFSIZE, "%s/%s", path, SectBorder[side]);
334 bw = GfParmGetNum(trackHandle, path2, TRK_ATT_WIDTH, (char*)NULL, borderWidth[side]);
335 borderWidth[side] = bw;
336 borderHeight[side] = GfParmGetNum(trackHandle, path2, TRK_ATT_HEIGHT, (char*)NULL, borderHeight[side]);
337 borderMaterial[side] = GfParmGetStr(trackHandle, path2, TRK_ATT_SURF, borderMaterial[side]);
338 borderSurface[side] = getTrackSurface(trackHandle, theTrack, borderMaterial[side]);
339 style = GfParmGetStr(trackHandle, path2, TRK_ATT_STYLE, ValStyle[borderStyle[side]]);
340
341 if (strcmp(style, TRK_VAL_PLAN) == 0) {
342 borderStyle[side] = TR_PLAN;
343 }
344 else if (strcmp(style, TRK_VAL_CURB) == 0) {
345 borderStyle[side] = TR_CURB;
346 }
347 else {
348 borderStyle[side] = TR_WALL;
349 }
350
351 // Barrier parameters
352 formatTrackPath(path2, BUFSIZE, "%s/%s", path, SectBarrier[side]);
353 barrierMaterial[side] = GfParmGetStr(trackHandle, path2, TRK_ATT_SURF, barrierMaterial[side]);
354 barrierSurface[side] = getTrackSurface(trackHandle, theTrack, barrierMaterial[side]);
355 barrierHeight[side] = GfParmGetNum(trackHandle, path2, TRK_ATT_HEIGHT, (char*)NULL, barrierHeight[side]);
356 style = GfParmGetStr(trackHandle, path2, TRK_ATT_STYLE, ValStyle[barrierStyle[side]]);
357
358 if (strcmp(style, TRK_VAL_FENCE) == 0) {
359 barrierStyle[side] = TR_FENCE;
360 barrierWidth[side] = 0;
361 }
362 else {
363 barrierStyle[side] = TR_WALL;
364 barrierWidth[side] = GfParmGetNum(trackHandle, path2, TRK_ATT_WIDTH, (char*)NULL, barrierWidth[side]);
365 }
366 }
367 else {
368 // Reset sw, ew, bw for steps after initialization
369 sw = sideStartWidth[side];
370 ew = sideEndWidth[side];
371 bw = borderWidth[side];
372 }
373
374 // Calculate parameters considering the current step
375 Kew = (ew - sw) / (tdble)steps;
376 ew = sw + (tdble)(curStep + 1) * Kew;
377 sw = sw + (tdble)(curStep)*Kew;
378
379 // Add borders
380 if (bw > 0.0f) {
381 curSeg = commonSideInit(curSeg, side, TR_LBORDER, TR_RBORDER, sideBankType[side], bw, bw,
382 borderSurface[side], borderHeight[side], borderStyle[side]);
383 }
384
385 // Add sides
386 if ((sw > 0.0f) || (ew > 0.0f)) {
387 commonSideInit(curSeg, side, TR_LSIDE, TR_RSIDE, sideBankType[side], sw, ew,
388 sideSurface[side], 0.0f, TR_PLAN);
389 }
390
391 // Add barriers
392 curBarrier = (tTrackBarrier*)malloc(sizeof(tTrackBarrier));
393 if (!curBarrier) {
394 GfFatal("AddSides: memory allocation error");
395 exit(1);
396 }
397 curBarrier->style = barrierStyle[side];
398 curBarrier->width = barrierWidth[side];
399 curBarrier->height = barrierHeight[side];
400 curBarrier->surface = barrierSurface[side];
401
402 // Compute normal of barrier for side collisions.
403 tTrackSeg* bseg = mSeg;
404 int bstart, bend;
405 float bsign;
406
407 if (side == TR_SIDE_LFT) {
408 bstart = TR_SL;
409 bend = TR_EL;
410 bsign = -1.0f;
411 }
412 else {
413 bstart = TR_SR;
414 bend = TR_ER;
415 bsign = 1.0f;
416 }
417
418 while (bseg->side[side] != NULL) {
419 bseg = bseg->side[side];
420 }
421
422 vec2f n(
423 -(bseg->vertex[bend].y - bseg->vertex[bstart].y) * bsign,
424 (bseg->vertex[bend].x - bseg->vertex[bstart].x) * bsign
425 );
426
427 n.normalize();
428 curBarrier->normal = n;
429
430 mSeg->barrier[side] = curBarrier;
431 }
432}
433
434
439static void normSeg(tTrackSeg* curSeg)
440{
441 curSeg->vertex[TR_SR].x -= xmin;
442 curSeg->vertex[TR_SR].y -= ymin;
443 curSeg->vertex[TR_SR].z -= zmin;
444 curSeg->vertex[TR_SL].x -= xmin;
445 curSeg->vertex[TR_SL].y -= ymin;
446 curSeg->vertex[TR_SL].z -= zmin;
447 curSeg->vertex[TR_ER].x -= xmin;
448 curSeg->vertex[TR_ER].y -= ymin;
449 curSeg->vertex[TR_ER].z -= zmin;
450 curSeg->vertex[TR_EL].x -= xmin;
451 curSeg->vertex[TR_EL].y -= ymin;
452 curSeg->vertex[TR_EL].z -= zmin;
453 curSeg->center.x -= xmin;
454 curSeg->center.y -= ymin;
455}
456
457
458static void CreateSegRing(void* TrackHandle, tTrack* theTrack, int ext)
459{
460 int j;
461 int segread, curindex;
462 tdble radius, radiusend = 0, dradius;
463 tdble innerradius;
464 tdble arc;
466 tTrackSeg* curSeg;
467 tTrackSeg* root;
468 tdble alf;
469 tdble xr, yr, newxr, newyr;
470 tdble xl, yl, newxl, newyl;
471 tdble cenx, ceny;
472 tdble width, wi2;
473 tdble x1, x2, y1, y2;
474 tdble al, alfl;
475 tdble zsl, zsr, zel, zer, zs, ze;
476 tdble bankings, bankinge, dz; //dzl, dzr;
477 tdble etgt, stgt;
478 tdble etgtl, stgtl;
479 tdble etgtr, stgtr;
480 tdble stepslg = 0;
481 int steps, curStep;
482 const char* segtype = (char*)NULL;
483 const char* material;
484 tTrackSurface* surface;
485 const char* segName;
486 int type;
487 const char* profil;
488 tdble totLength;
489
490 tdble tl, dtl, T1l, T2l;
491 tdble tr, dtr, T1r, T2r;
492 tdble curzel, curzer, curArc, curLength, curzsl, curzsr;
493 tdble grade;
494
495 void* segNameHash = NULL;
496 const int BUFSIZE = 256;
497 char path[BUFSIZE];
498
499#define MAX_TMP_INTS 256
500 int mi[MAX_TMP_INTS];
501 int ind = 0;
502
503 radius = arc = length = alf = xr = yr = newxr = newyr = xl = yl = 0;
504 zel = zer = etgtl = etgtr = newxl = newyl = 0;
505 type = 0;
506
507 width = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_WIDTH, (char*)NULL, 15.0);
508 wi2 = width / 2.0;
509
510 grade = -100000.0;
511 root = (tTrackSeg*)NULL;
512 totLength = 0;
513
514 formatTrackPath(path, BUFSIZE, "%s/%s", TRK_SECT_MAIN, TRK_LST_SEGMENTS);
515 yl = width;
516 zsl = zsr = zel = zer = zs = ze = 0.0;
517 stgt = etgt = 0.0;
518 stgtl = etgtl = 0.0;
519 stgtr = etgtr = 0.0;
520
521 /* Main Track */
523 surface = getTrackSurface(TrackHandle, theTrack, material);
524 envIndex = 0;
526
527 if (ext) {
528 segNameHash = GfHashCreate(GF_HASH_TYPE_STR);
529 }
530
531 segread = 0;
532 curindex = 0;
534 do {
535 segtype = GfParmGetCurStr(TrackHandle, path, TRK_ATT_TYPE, NULL);
536 if (segtype == 0) {
537 continue;
538 }
539 segread++;
540
541 zsl = zel;
542 zsr = zer;
543 TSTZ(zsl);
544 TSTZ(zsr);
545
546 /* Turn Marks */
547 if (ext) {
548 const char* marks = GfParmGetCurStr(TrackHandle, path, TRK_ATT_MARKS, NULL);
549 ind = 0;
550 if (marks) {
551 char* tmpmarks = strdup(marks);
552 char* s = strtok(tmpmarks, ";");
553 while ((s != NULL) && (ind < MAX_TMP_INTS)) {
554 mi[ind] = (int)strtol(s, NULL, 0);
555 ind++;
556 s = strtok(NULL, ";");
557 }
558 free(tmpmarks);
559 }
560 }
561
562 /* surface change */
563 material = GfParmGetCurStr(TrackHandle, path, TRK_ATT_SURF, material);
564 surface = getTrackSurface(TrackHandle, theTrack, material);
565 envIndex = (int)GfParmGetCurNum(TrackHandle, path, TRK_ATT_ENVIND, (char*)NULL, (float)(envIndex + 1)) - 1;
566
567 /* get segment type and length */
568 segName = GfParmListGetCurEltName(TrackHandle, path);
569 if (strcmp(segtype, TRK_VAL_STR) == 0) {
570 /* straight */
571 length = GfParmGetCurNum(TrackHandle, path, TRK_ATT_LG, (char*)NULL, 0);
572 type = TR_STR;
573 radius = radiusend = 0;
574 }
575 else if (strcmp(segtype, TRK_VAL_LFT) == 0) {
576 /* left curve */
577 radius = GfParmGetCurNum(TrackHandle, path, TRK_ATT_RADIUS, (char*)NULL, 0);
578 radiusend = GfParmGetCurNum(TrackHandle, path, TRK_ATT_RADIUSEND, (char*)NULL, radius);
579 arc = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ARC, (char*)NULL, 0);
580 type = TR_LFT;
581 length = (radius + radiusend) / 2.0 * arc;
582 }
583 else if (strcmp(segtype, TRK_VAL_RGT) == 0) {
584 /* right curve */
585 radius = GfParmGetCurNum(TrackHandle, path, TRK_ATT_RADIUS, (char*)NULL, 0);
586 radiusend = GfParmGetCurNum(TrackHandle, path, TRK_ATT_RADIUSEND, (char*)NULL, radius);
587 arc = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ARC, (char*)NULL, 0);
588 type = TR_RGT;
589 length = (radius + radiusend) / 2.0 * arc;
590 }
591 else {
592 GfFatal("Unknown track segment type \"%s\" in segment \"%s\"\n", segtype, segName);
593 exit(1);
594 }
595 if (ext) {
596 if (GfHashGetStr(segNameHash, segName)) {
597 printf(">>>>>>>>> DUPLICATED SEGMENT NAME \"%s\" PLEASE CHANGE IT !!!!\n", segName);
598 exit(1);
599 }
600 GfHashAddStr(segNameHash, segName, segName);
601 }
602
603 /* elevation and banking */
604 zsl = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZSL, (char*)NULL, zsl);
605 zsr = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZSR, (char*)NULL, zsr);
606 zel = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZEL, (char*)NULL, zel);
607 zer = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZER, (char*)NULL, zer);
608 ze = zs = -100000.0;
609 ze = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZE, (char*)NULL, ze);
610 zs = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZS, (char*)NULL, zs);
611 grade = GfParmGetCurNum(TrackHandle, path, TRK_ATT_GRADE, (char*)NULL, grade);
612 if (zs != -100000.0) {
613 zsr = zsl = zs;
614 }
615 else {
616 zs = (zsl + zsr) / 2.0;
617 }
618 if (ze != -100000.0) {
619 zer = zel = ze;
620 }
621 else if (grade != -100000.0) {
622 ze = zs + length * grade;
623 }
624 else {
625 ze = (zel + zer) / 2.0;
626 }
627 bankings = atan2(zsl - zsr, width);
628 bankinge = atan2(zel - zer, width);
629 bankings = GfParmGetCurNum(TrackHandle, path, TRK_ATT_BKS, (char*)NULL, bankings);
630 bankinge = GfParmGetCurNum(TrackHandle, path, TRK_ATT_BKE, (char*)NULL, bankinge);
631 dz = tan(bankings) * width / 2.0;
632 zsl = zs + dz;
633 zsr = zs - dz;
634 dz = tan(bankinge) * width / 2.0;
635 zel = ze + dz;
636 zer = ze - dz;
637
638 TSTZ(zsl);
639 TSTZ(zsr);
640
641 /* Get segment profil */
643 stgtl = etgtl;
644 stgtr = etgtr;
645 if (strcmp(profil, TRK_VAL_SPLINE) == 0) {
646 steps = (int)GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFSTEPS, (char*)NULL, 1.0);
647 if (steps == 1) {
648 stepslg = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFSTEPSLEN, (char*)NULL, GlobalStepLen);
649 if (stepslg) {
650 steps = (int)(length / stepslg) + 1;
651 }
652 else {
653 steps = 1;
654 }
655 }
656 stgtl = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTSL, (char*)NULL, stgtl);
657 etgtl = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTEL, (char*)NULL, etgtl);
658 stgtr = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTSR, (char*)NULL, stgtr);
659 etgtr = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTER, (char*)NULL, etgtr);
660 stgt = etgt = -100000.0;
661 stgt = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTS, (char*)NULL, stgt);
662 etgt = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTE, (char*)NULL, etgt);
663 if (stgt != -100000.0) {
664 stgtl = stgtr = stgt;
665 }
666 if (etgt != -100000.0) {
667 etgtl = etgtr = etgt;
668 }
669 }
670 else {
671 steps = 1;
672 stgtl = etgtl = (zel - zsl) / length;
673 stgtr = etgtr = (zer - zsr) / length;
674 }
675 GfParmSetCurNum(TrackHandle, path, TRK_ATT_ID, (char*)NULL, (tdble)curindex);
676
677 //dzl = zel - zsl;
678 //dzr = zer - zsr;
679 T1l = stgtl * length;
680 T2l = etgtl * length;
681 tl = 0.0;
682 dtl = 1.0 / (tdble)steps;
683 T1r = stgtr * length;
684 T2r = etgtr * length;
685 tr = 0.0;
686 dtr = 1.0 / (tdble)steps;
687
688 curStep = 0;
689 curzel = zsl;
690 curzer = zsr;
691 curArc = arc / (tdble)steps;
692 curLength = length / (tdble)steps;
693 dradius = (radiusend - radius) / (tdble)steps;
694 if (radiusend != radius) {
695 /* Compute the correct curLength... */
696 if (steps != 1) {
697 dradius = (radiusend - radius) / (tdble)(steps - 1);
698 tdble tmpAngle = 0;
699 tdble tmpRadius = radius;
700 for (curStep = 0; curStep < steps; curStep++) {
701 tmpAngle += curLength / tmpRadius;
702 tmpRadius += dradius;
703 }
704 curLength *= arc / tmpAngle;
705 }
706 }
707 curStep = 0;
708
709 while (curStep < steps) {
710
711 tl += dtl;
712 tr += dtr;
713
714 curzsl = curzel;
715 curzel = TrackSpline(zsl, zel, T1l, T2l, tl);
716
717 curzsr = curzer;
718 curzer = TrackSpline(zsr, zer, T1r, T2r, tr);
719
720 if (dradius != 0) {
721 curArc = curLength / radius;
722 }
723
724 /* allocate a new segment */
725 curSeg = (tTrackSeg*)calloc(1, sizeof(tTrackSeg));
726 if (root == NULL) {
727 root = curSeg;
728 curSeg->next = curSeg;
729 curSeg->prev = curSeg;
730 }
731 else {
732 curSeg->next = root->next;
733 curSeg->next->prev = curSeg;
734 curSeg->prev = root;
735 root->next = curSeg;
736 root = curSeg;
737 }
738 curSeg->type2 = TR_MAIN;
739 curSeg->name = segName;
740 curSeg->id = curindex;
741 curSeg->width = curSeg->startWidth = curSeg->endWidth = width;
742 curSeg->surface = surface;
743 curSeg->envIndex = envIndex;
744 curSeg->lgfromstart = totLength;
745
746 if (ext && ind) {
747 int* mrks = (int*)calloc(ind, sizeof(int));
748 tSegExt* segExt = (tSegExt*)calloc(1, sizeof(tSegExt));
749
750 memcpy(mrks, mi, ind * sizeof(int));
751 segExt->nbMarks = ind;
752 segExt->marks = mrks;
753 curSeg->ext = segExt;
754 ind = 0;
755 }
756
757
758 switch (type) {
759 case TR_STR:
760 /* straight */
761 curSeg->type = TR_STR;
762 curSeg->length = curLength;
763
764 newxr = xr + curLength * cos(alf); /* find end coordinates */
765 newyr = yr + curLength * sin(alf);
766 newxl = xl + curLength * cos(alf);
767 newyl = yl + curLength * sin(alf);
768
769 curSeg->vertex[TR_SR].x = xr;
770 curSeg->vertex[TR_SR].y = yr;
771 curSeg->vertex[TR_SR].z = curzsr;
772
773 curSeg->vertex[TR_SL].x = xl;
774 curSeg->vertex[TR_SL].y = yl;
775 curSeg->vertex[TR_SL].z = curzsl;
776
777 curSeg->vertex[TR_ER].x = newxr;
778 curSeg->vertex[TR_ER].y = newyr;
779 curSeg->vertex[TR_ER].z = curzer;
780
781 curSeg->vertex[TR_EL].x = newxl;
782 curSeg->vertex[TR_EL].y = newyl;
783 curSeg->vertex[TR_EL].z = curzel;
784
785 curSeg->angle[TR_ZS] = alf;
786 curSeg->angle[TR_ZE] = alf;
787 curSeg->angle[TR_YR] = atan2(curSeg->vertex[TR_ER].z - curSeg->vertex[TR_SR].z, curLength);
788 curSeg->angle[TR_YL] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_SL].z, curLength);
789 curSeg->angle[TR_XS] = atan2(curSeg->vertex[TR_SL].z - curSeg->vertex[TR_SR].z, width);
790 curSeg->angle[TR_XE] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_ER].z, width);
791
792 curSeg->Kzl = tan(curSeg->angle[TR_YR]);
793 curSeg->Kzw = (curSeg->angle[TR_XE] - curSeg->angle[TR_XS]) / curLength;
794 curSeg->Kyl = 0;
795
796 curSeg->rgtSideNormal.x = -sin(alf);
797 curSeg->rgtSideNormal.y = cos(alf);
798
799 TSTX(newxr); TSTX(newxl);
800 TSTY(newyr); TSTY(newyl);
801
802 break;
803
804 case TR_LFT:
805 /* left curve */
806 curSeg->type = TR_LFT;
807 curSeg->radius = radius;
808 curSeg->radiusr = radius + wi2;
809 curSeg->radiusl = radius - wi2;
810 curSeg->arc = curArc;
811 curSeg->length = curLength;
812
813 innerradius = radius - wi2; /* left side aligned */
814 cenx = xl - innerradius * sin(alf); /* compute center location: */
815 ceny = yl + innerradius * cos(alf);
816 curSeg->center.x = cenx;
817 curSeg->center.y = ceny;
818
819 curSeg->angle[TR_ZS] = alf;
820 curSeg->angle[TR_CS] = alf - PI / 2.0;
821 alf += curArc;
822 curSeg->angle[TR_ZE] = alf;
823
824 newxl = cenx + innerradius * sin(alf); /* location of end */
825 newyl = ceny - innerradius * cos(alf);
826 newxr = cenx + (innerradius + width) * sin(alf); /* location of end */
827 newyr = ceny - (innerradius + width) * cos(alf);
828
829 curSeg->vertex[TR_SR].x = xr;
830 curSeg->vertex[TR_SR].y = yr;
831 curSeg->vertex[TR_SR].z = curzsr;
832
833 curSeg->vertex[TR_SL].x = xl;
834 curSeg->vertex[TR_SL].y = yl;
835 curSeg->vertex[TR_SL].z = curzsl;
836
837 curSeg->vertex[TR_ER].x = newxr;
838 curSeg->vertex[TR_ER].y = newyr;
839 curSeg->vertex[TR_ER].z = curzer;
840
841 curSeg->vertex[TR_EL].x = newxl;
842 curSeg->vertex[TR_EL].y = newyl;
843 curSeg->vertex[TR_EL].z = curzel;
844
845 curSeg->angle[TR_YR] = atan2(curSeg->vertex[TR_ER].z - curSeg->vertex[TR_SR].z, curArc * (innerradius + width));
846 curSeg->angle[TR_YL] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_SL].z, curArc * innerradius);
847 curSeg->angle[TR_XS] = atan2(curSeg->vertex[TR_SL].z - curSeg->vertex[TR_SR].z, width);
848 curSeg->angle[TR_XE] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_ER].z, width);
849
850 curSeg->Kzl = tan(curSeg->angle[TR_YR]) * (innerradius + width);
851 curSeg->Kzw = (curSeg->angle[TR_XE] - curSeg->angle[TR_XS]) / curArc;
852 curSeg->Kyl = 0;
853
854 /* to find the boundary */
855 al = curArc / 36.0;
856 alfl = curSeg->angle[TR_CS];
857
858 for (j = 0; j < 36; j++) {
859 alfl += al;
860 x1 = curSeg->center.x + (innerradius)*cos(alfl); /* location of end */
861 y1 = curSeg->center.y + (innerradius)*sin(alfl);
862 x2 = curSeg->center.x + (innerradius + width) * cos(alfl); /* location of end */
863 y2 = curSeg->center.y + (innerradius + width) * sin(alfl);
864 TSTX(x1); TSTX(x2);
865 TSTY(y1); TSTY(y2);
866 }
867
868 break;
869
870 case TR_RGT:
871 /* right curve */
872 curSeg->type = TR_RGT;
873 curSeg->radius = radius;
874 curSeg->radiusr = radius - wi2;
875 curSeg->radiusl = radius + wi2;
876 curSeg->arc = curArc;
877 curSeg->length = curLength;
878
879 innerradius = radius - wi2; /* right side aligned */
880 cenx = xr + innerradius * sin(alf); /* compute center location */
881 ceny = yr - innerradius * cos(alf);
882 curSeg->center.x = cenx;
883 curSeg->center.y = ceny;
884
885 curSeg->angle[TR_ZS] = alf;
886 curSeg->angle[TR_CS] = alf + PI / 2.0;
887 alf -= curSeg->arc;
888 curSeg->angle[TR_ZE] = alf;
889
890 newxl = cenx - (innerradius + width) * sin(alf); /* location of end */
891 newyl = ceny + (innerradius + width) * cos(alf);
892 newxr = cenx - innerradius * sin(alf); /* location of end */
893 newyr = ceny + innerradius * cos(alf);
894
895 curSeg->vertex[TR_SR].x = xr;
896 curSeg->vertex[TR_SR].y = yr;
897 curSeg->vertex[TR_SR].z = curzsr;
898
899 curSeg->vertex[TR_SL].x = xl;
900 curSeg->vertex[TR_SL].y = yl;
901 curSeg->vertex[TR_SL].z = curzsl;
902
903 curSeg->vertex[TR_ER].x = newxr;
904 curSeg->vertex[TR_ER].y = newyr;
905 curSeg->vertex[TR_ER].z = curzer;
906
907 curSeg->vertex[TR_EL].x = newxl;
908 curSeg->vertex[TR_EL].y = newyl;
909 curSeg->vertex[TR_EL].z = curzel;
910
911 curSeg->angle[TR_YR] = atan2(curSeg->vertex[TR_ER].z - curSeg->vertex[TR_SR].z, curArc * innerradius);
912 curSeg->angle[TR_YL] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_SL].z, curArc * (innerradius + width));
913 curSeg->angle[TR_XS] = atan2(curSeg->vertex[TR_SL].z - curSeg->vertex[TR_SR].z, width);
914 curSeg->angle[TR_XE] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_ER].z, width);
915
916 curSeg->Kzl = tan(curSeg->angle[TR_YR]) * innerradius;
917 curSeg->Kzw = (curSeg->angle[TR_XE] - curSeg->angle[TR_XS]) / curArc;
918 curSeg->Kyl = 0;
919
920 /* to find the boundaries */
921 al = curSeg->arc / 36.0;
922 alfl = curSeg->angle[TR_CS];
923
924 for (j = 0; j < 36; j++) {
925 alfl -= al;
926 x1 = curSeg->center.x + (innerradius + width) * cos(alfl); /* location of end */
927 y1 = curSeg->center.y + (innerradius + width) * sin(alfl);
928 x2 = curSeg->center.x + innerradius * cos(alfl); /* location of end */
929 y2 = curSeg->center.y + innerradius * sin(alfl);
930 TSTX(x1); TSTX(x2);
931 TSTY(y1); TSTY(y2);
932 }
933 break;
934
935 }
936
937 addSides(curSeg, TrackHandle, theTrack, curStep, steps);
938
939 totLength += curSeg->length;
940 xr = newxr;
941 yr = newyr;
942 xl = newxl;
943 yl = newyl;
944 curindex++;
945 curStep++;
946 if (type != TR_STR) {
947 /* printf("radius = %f arc = %f steps %d, length %f, stepslg %f\n", radius, RAD2DEG(curArc), steps, length, curLength); */
948 radius += dradius;
949 }
950 }
951
952 } while (GfParmListSeekNext(TrackHandle, path) == 0);
953
954 if (ext) {
955 GfHashRelease(segNameHash, NULL);
956 }
957
958 /* printf("\n"); */
959
960
961 theTrack->seg = root;
962 theTrack->length = totLength;
963 theTrack->nseg = curindex;
964}
965
966
967
968
969/*
970 * Read version 4 track segments
971 */
972static void
974{
975 tTrackGeoreference& geo = track->georeference;
976 memset(&geo, 0, sizeof(geo));
977 // Avoid <cmath>: its float overloads change the legacy geometry arithmetic.
978 // On MSVC, adding that header changed existing sin/cos calls from double
979 // results to float results, shifting Mogyorod's closure by about 32 cm and
980 // splitting its pit wall into overlapping collision objects.
981 // A future regression test should load a small large-radius, subdivided
982 // track through the separately compiled loader and compare road endpoints
983 // with fixed, known-good coordinates (not the same formulas recomputed in
984 // the test). Including track4.cpp after Google Test headers is insufficient:
985 // those headers can already expose <cmath> overloads, unlike production.
986 // Verify the test catches this bug by temporarily reintroducing <cmath> in
987 // the loader: it should fail, then pass again after removing that include.
988 const tdble missing = std::numeric_limits<tdble>::quiet_NaN();
989 const tdble maxFinite = (std::numeric_limits<tdble>::max)();
990 const tdble lat = GfParmGetNum(handle, TRK_SECT_GEOREFERENCE, TRK_ATT_GEO_LATITUDE, "deg", missing);
991 const tdble lon = GfParmGetNum(handle, TRK_SECT_GEOREFERENCE, TRK_ATT_GEO_LONGITUDE, "deg", missing);
992 const tdble alt = GfParmGetNum(handle, TRK_SECT_GEOREFERENCE, TRK_ATT_GEO_ALTITUDE, "m", missing);
993 const tdble heading = GfParmGetNum(handle, TRK_SECT_GEOREFERENCE, TRK_ATT_GEO_HEADING, "deg", missing);
994 if (fabs(lat) <= 90.0 && fabs(lon) <= 180.0) {
995 geo.latitude = lat;
996 geo.longitude = lon;
997 geo.hasLocation = 1;
998 } else if (lat == lat || lon == lon) {
999 GfError("Track Georeference: invalid or incomplete latitude/longitude\n");
1000 }
1001 if (fabs(alt) <= maxFinite) {
1002 geo.altitude = alt;
1003 geo.hasAltitude = 1;
1004 } else if (alt == alt) {
1005 GfError("Track Georeference: invalid altitude\n");
1006 }
1007 if (fabs(heading) <= maxFinite) {
1008 double degrees = fmod((double)heading, 360.0);
1009 if (degrees < 0.0) degrees += 360.0;
1010 geo.heading = (tdble)(degrees * PI / 180.0);
1011 geo.hasHeading = 1;
1012 } else if (heading == heading) {
1013 GfError("Track Georeference: invalid heading\n");
1014 }
1015}
1016
1017void
1018ReadTrack4(tTrack* theTrack, void* TrackHandle, tRoadCam** camList, int ext)
1019{
1020 int i;
1021 tTrackSeg* curSeg = NULL, * mSeg;
1022 tTrackSeg* curSeg2;
1023 tTrackSeg* pitEntrySeg = NULL;
1024 tTrackSeg* pitExitSeg = NULL;
1025 tTrackSeg* pitStart = NULL;
1026 tTrackSeg* pitEnd = NULL;
1027 tTrackSeg* curPitSeg = NULL;
1028 tTrackPitInfo* pits;
1029 const char* segName;
1030 int segId;
1031 tRoadCam* curCam;
1032 tTrkLocPos trkPos;
1033 int found = 0;
1034 const char* paramVal;
1035 const int BUFSIZE = 256;
1036 char path2[BUFSIZE];
1037 int changeSeg;
1038 tdble offset = 0;
1039 tdble toStart;
1040
1041 xmin = xmax = ymin = ymax = zmin = zmax = 0.0;
1043
1045
1047 if (!theTrack->seg) {
1048 GfFatal("Track definition contains no valid segments\n");
1049 exit(1);
1050 }
1051
1052 /* PITS */
1053 pits = &(theTrack->pits);
1054 formatTrackPath(path2, BUFSIZE, "%s/%s", TRK_SECT_MAIN, TRK_SECT_PITS);
1055 segName = GfParmGetStr(TrackHandle, path2, TRK_ATT_ENTRY, NULL);
1056
1057 if (segName != 0) {
1058 pitEntrySeg = findFirstSegmentByName(theTrack, segName);
1059
1060 /* Pits Exit */
1061 segName = GfParmGetStr(TrackHandle, path2, TRK_ATT_EXIT, NULL);
1062 if (segName != 0) {
1063 pitExitSeg = findLastSegmentByName(theTrack, segName);
1064 }
1065
1066 /* Pits Start */
1067 segName = GfParmGetStr(TrackHandle, path2, TRK_ATT_START, NULL);
1068 if (segName != 0) {
1069 pitStart = findFirstSegmentByName(theTrack, segName);
1070 }
1071
1072 /* Pits End */
1073 segName = GfParmGetStr(TrackHandle, path2, TRK_ATT_END, NULL);
1074 if (segName != 0) {
1075 pitEnd = findLastSegmentByName(theTrack, segName);
1076 }
1077 paramVal = GfParmGetStr(TrackHandle, path2, TRK_ATT_SIDE, "right");
1078 if (strcmp(paramVal, "right") == 0) {
1079 pits->side = TR_RGT;
1080 }
1081 else {
1082 pits->side = TR_LFT;
1083 }
1084 pits->speedLimit = GfParmGetNum(TrackHandle, path2, TRK_ATT_SPD_LIM, (char*)NULL, 25.0);
1085 if ((pitEntrySeg != NULL) && (pitExitSeg != NULL) && (pitStart != NULL) && (pitEnd != NULL)) {
1086 pits->pitEntry = pitEntrySeg;
1087 pits->pitExit = pitExitSeg;
1088 pits->pitStart = pitStart;
1089 pits->pitEnd = pitEnd;
1090 pitEntrySeg->raceInfo |= TR_PITENTRY;
1091 pitExitSeg->raceInfo |= TR_PITEXIT;
1092 pits->len = GfParmGetNum(TrackHandle, path2, TRK_ATT_LEN, (char*)NULL, 15.0);
1093 pits->width = GfParmGetNum(TrackHandle, path2, TRK_ATT_WIDTH, (char*)NULL, 5.0);
1094 found = 1;
1095 }
1096 else {
1097 found = 0;
1098 }
1099 }
1100
1101 if (found) {
1102 pits->type = TR_PIT_ON_TRACK_SIDE;
1103 pits->nPitSeg = 0;
1104 if (pitStart->lgfromstart > pitEnd->lgfromstart) {
1105 pits->nMaxPits = (int)((theTrack->length - pitStart->lgfromstart +
1106 pitEnd->lgfromstart + pitEnd->length + pits->len / 2.0) / pits->len);
1107 }
1108 else {
1109 pits->nMaxPits = (int)((pitEnd->lgfromstart + pitEnd->length
1110 - pitStart->lgfromstart + pits->len / 2.0) / pits->len);
1111 }
1112 pits->driversPits = (tTrackOwnPit*)calloc(pits->nMaxPits, sizeof(tTrackOwnPit));
1113
1114 mSeg = pitStart->prev;
1115 changeSeg = 1;
1116 toStart = 0;
1117 i = 0;
1118 while (i < pits->nMaxPits) {
1119 pits->driversPits[i].pos.type = TR_LPOS_MAIN;
1120 if (changeSeg) {
1121 changeSeg = 0;
1122 offset = 0;
1123 mSeg = mSeg->next;
1124 if (toStart >= mSeg->length) {
1125 toStart -= mSeg->length;
1126 changeSeg = 1;
1127 continue;
1128 }
1129 switch (pits->side) {
1130 case TR_RGT:
1131 curPitSeg = mSeg->rside;
1132 if (curPitSeg->rside) {
1133 offset = curPitSeg->width;
1134 curPitSeg = curPitSeg->rside;
1135 }
1136 break;
1137 case TR_LFT:
1138 curPitSeg = mSeg->lside;
1139 if (curPitSeg->lside) {
1140 offset = curPitSeg->width;
1141 curPitSeg = curPitSeg->lside;
1142 }
1143 break;
1144 }
1145 }
1146
1147 pits->driversPits[i].pos.seg = mSeg;
1148 pits->driversPits[i].pos.toStart = toStart + pits->len / 2.0;
1149 switch (pits->side) {
1150 case TR_RGT:
1151 pits->driversPits[i].pos.toRight = -offset - RtTrackGetWidth(curPitSeg, toStart) + pits->width / 2.0;
1152 pits->driversPits[i].pos.toLeft = mSeg->width - pits->driversPits[i].pos.toRight;
1153 pits->driversPits[i].pos.toMiddle = mSeg->width / 2.0 - pits->driversPits[i].pos.toRight;
1154 break;
1155 case TR_LFT:
1156 pits->driversPits[i].pos.toLeft = -offset - RtTrackGetWidth(curPitSeg, toStart) + pits->width / 2.0;
1157 pits->driversPits[i].pos.toRight = mSeg->width - pits->driversPits[i].pos.toLeft;
1158 pits->driversPits[i].pos.toMiddle = mSeg->width / 2.0 - pits->driversPits[i].pos.toLeft;
1159 break;
1160 }
1161 toStart += pits->len;
1162 if (toStart >= mSeg->length) {
1163 toStart -= mSeg->length;
1164 changeSeg = 1;
1165 }
1166 i++;
1167 }
1168
1169 for (mSeg = pitStart->prev; mSeg != pitEnd->next->next; mSeg = mSeg->next) {
1170 curSeg2 = NULL;
1171 switch (pits->side) {
1172 case TR_RGT:
1173 curSeg = mSeg->rside;
1174 curSeg2 = curSeg->rside;
1175 if ((mSeg != pitStart->prev) && (mSeg != pitEnd->next)) {
1176 mSeg->barrier[0]->style = TR_PITBUILDING;
1177 }
1178 break;
1179 case TR_LFT:
1180 curSeg = mSeg->lside;
1181 curSeg2 = curSeg->lside;
1182 if ((mSeg != pitStart->prev) && (mSeg != pitEnd->next)) {
1183 mSeg->barrier[1]->style = TR_PITBUILDING;
1184 }
1185 break;
1186 }
1187 if ((mSeg != pitStart->prev) && (mSeg != pitEnd->next)) {
1188 curSeg->raceInfo |= TR_PIT | TR_SPEEDLIMIT;
1189 if (curSeg2) {
1190 curSeg2->raceInfo |= TR_PIT | TR_SPEEDLIMIT;
1191 }
1192 }
1193 else if (mSeg == pitStart->prev) {
1194 curSeg->raceInfo |= TR_PITSTART;
1195 if (curSeg2) {
1196 curSeg2->raceInfo |= TR_PITSTART;
1197 }
1198 }
1199 else if (mSeg == pitEnd->next) {
1200 curSeg->raceInfo |= TR_PITEND;
1201 if (curSeg2) {
1202 curSeg2->raceInfo |= TR_PITEND;
1203 }
1204 }
1205 }
1206 }
1207
1208 /*
1209 * camera definitions
1210 */
1212 do {
1213 curCam = (tRoadCam*)calloc(1, sizeof(tRoadCam));
1214 if (!curCam) {
1215 GfFatal("ReadTrack4: Memory allocation error\n");
1216 exit(1);
1217 }
1218 if (*camList == NULL) {
1219 *camList = curCam;
1220 curCam->next = curCam;
1221 }
1222 else {
1223 curCam->next = (*camList)->next;
1224 (*camList)->next = curCam;
1225 *camList = curCam;
1226 }
1229 if (segName == 0) {
1230 GfFatal("Bad Track Definition: in Camera %s %s is missing\n", curCam->name, TRK_ATT_SEGMENT);
1231 exit(1);
1232 }
1233 formatTrackPath(path2, BUFSIZE, "%s/%s/%s", TRK_SECT_MAIN, TRK_LST_SEGMENTS, segName);
1234 segId = (int)GfParmGetNum(TrackHandle, path2, TRK_ATT_ID, (char*)NULL, 0);
1235 curSeg = theTrack->seg;
1236 for (i = 0; i < theTrack->nseg; i++) {
1237 if (curSeg->id == segId) {
1238 break;
1239 }
1240 curSeg = curSeg->next;
1241 }
1242
1243 trkPos.seg = curSeg;
1246 TrackLocal2Global(&trkPos, &(curCam->pos.x), &(curCam->pos.y));
1247 curCam->pos.z = TrackHeightL(&trkPos) + GfParmGetCurNum(TrackHandle, TRK_SECT_CAM, TRK_ATT_HEIGHT, (char*)NULL, 0);
1248
1250 if (segName == 0) {
1251 GfFatal("Bad Track Definition: in Camera %s %s is missing\n", curCam->name, TRK_ATT_CAM_FOV);
1252 exit(1);
1253 }
1254 formatTrackPath(path2, BUFSIZE, "%s/%s/%s", TRK_SECT_MAIN, TRK_LST_SEGMENTS, segName);
1255 segId = (int)GfParmGetNum(TrackHandle, path2, TRK_ATT_ID, (char*)NULL, 0);
1256 curSeg = theTrack->seg;
1257 for (i = 0; i < theTrack->nseg; i++) {
1258 if (curSeg->id == segId) {
1259 break;
1260 }
1261 curSeg = curSeg->next;
1262 }
1264 if (segName == 0) {
1265 GfFatal("Bad Track Definition: in Camera %s %s is missing\n", curCam->name, TRK_ATT_CAM_FOVE);
1266 exit(1);
1267 }
1268 formatTrackPath(path2, BUFSIZE, "%s/%s/%s", TRK_SECT_MAIN, TRK_LST_SEGMENTS, segName);
1269 segId = (int)GfParmGetNum(TrackHandle, path2, TRK_ATT_ID, (char*)NULL, 0);
1270
1271 do {
1272 curSeg->cam = curCam;
1273 curSeg = curSeg->next;
1274 } while (curSeg->id != segId);
1276 }
1277
1278 /* Update the coord to be positives */
1279 theTrack->min.x = 0;
1280 theTrack->min.y = 0;
1281 theTrack->min.z = 0;
1282 theTrack->max.x = xmax - xmin;
1283 theTrack->max.y = ymax - ymin;
1284 theTrack->max.z = zmax - zmin;
1285
1286 curSeg = theTrack->seg;
1287 for (i = 0; i < theTrack->nseg; i++) { /* read the segment data: */
1288 if ((curSeg->lgfromstart + curSeg->length) > (theTrack->length - 50.0)) {
1289 curSeg->raceInfo |= TR_LAST;
1290 }
1291 else if (curSeg->lgfromstart < 50.0) {
1292 curSeg->raceInfo |= TR_START;
1293 }
1294 else {
1295 curSeg->raceInfo |= TR_NORMAL;
1296 }
1297 normSeg(curSeg);
1298 if (curSeg->lside) {
1299 normSeg(curSeg->lside);
1300 if (curSeg->lside->lside) {
1301 normSeg(curSeg->lside->lside);
1302 }
1303 }
1304 if (curSeg->rside) {
1305 normSeg(curSeg->rside);
1306 if (curSeg->rside->rside) {
1307 normSeg(curSeg->rside->rside);
1308 }
1309 }
1310 curSeg = curSeg->next;
1311 }
1312
1313
1314 if (*camList != NULL) {
1315 curCam = *camList;
1316 do {
1317 curCam = curCam->next;
1318 curCam->pos.x -= xmin;
1319 curCam->pos.y -= ymin;
1320 curCam->pos.z -= zmin;
1321 } while (curCam != *camList);
1322 }
1323}
1324
1325
1333static void updateMinMaxForTurn(const tTrackSeg* const curBorder, const tdble radius, const tdble sign, const tdble z)
1334{
1335 tdble al, alfl, x, y;
1336 int j;
1337
1338 // to find the boundary (global min/max, approximation)
1339 al = curBorder->arc / 36.0 * sign;
1340 alfl = curBorder->angle[TR_CS];
1341
1342 for (j = 0; j < 36; j++) {
1343 alfl += al;
1344 x = curBorder->center.x + radius * cos(alfl); // location of end
1345 y = curBorder->center.y + radius * sin(alfl);
1346 TSTX(x);
1347 TSTY(y);
1348 }
1349 TSTZ(z);
1350}
1351
1352
1359static void initAnglesAndGradients(tTrackSeg* const curBorder, const tdble startwidth, const tdble endwidth) {
1360 curBorder->angle[TR_YR] = atan2(curBorder->vertex[TR_ER].z - curBorder->vertex[TR_SR].z,
1361 curBorder->arc * curBorder->radiusr);
1362 curBorder->angle[TR_YL] = atan2(curBorder->vertex[TR_EL].z - curBorder->vertex[TR_SL].z,
1363 curBorder->arc * curBorder->radiusl);
1364
1365 curBorder->Kzl = tan(curBorder->angle[TR_YR]) * curBorder->radiusr;
1366 curBorder->Kzw = (curBorder->angle[TR_XE] - curBorder->angle[TR_XS]) / curBorder->arc;
1367 curBorder->Kyl = (endwidth - startwidth) / curBorder->arc;
1368}
1369
1370
1385 const int turntype,
1386 tTrackSeg* const curBorder,
1387 const tTrackSeg* const curSeg,
1388 const int side,
1389 const int bankingtype,
1390 const tdble startwidth,
1391 const tdble endwidth,
1392 const tdble maxwidth
1393)
1394{
1395 tdble sign, z;
1396
1397 if (turntype == TR_LFT) {
1398 sign = 1.0f;
1399 }
1400 else {
1401 sign = -1.0f;
1402 }
1403
1404 curBorder->center.x = curSeg->center.x;
1405 curBorder->center.y = curSeg->center.y;
1406
1407 // Combining code for case 0 (TRK_SECT_RSIDE) and 1 (TRK_SECT_LSIDE)?
1408 // Tried it, but the setup code is then as long as the copy and less readable because of the additional 8 variables
1409 switch (side) {
1410 case 1:
1411 curBorder->radius = curSeg->radiusl - sign * startwidth / 2.0;
1412 curBorder->radiusr = curSeg->radiusl;
1413 curBorder->radiusl = curSeg->radiusl - sign * maxwidth;
1414 curBorder->arc = curSeg->arc;
1415 curBorder->length = curBorder->radius * curBorder->arc;
1416
1417 curBorder->vertex[TR_SL].x = curBorder->vertex[TR_SR].x - sign * startwidth * cos(curBorder->angle[TR_CS]);
1418 curBorder->vertex[TR_SL].y = curBorder->vertex[TR_SR].y - sign * startwidth * sin(curBorder->angle[TR_CS]);
1419 curBorder->vertex[TR_SL].z = curBorder->vertex[TR_SR].z + (tdble)bankingtype * startwidth * tan(curSeg->angle[TR_XS]);
1420 curBorder->vertex[TR_EL].x = curBorder->vertex[TR_ER].x - sign * endwidth * cos(curBorder->angle[TR_CS] + sign * curBorder->arc);
1421 curBorder->vertex[TR_EL].y = curBorder->vertex[TR_ER].y - sign * endwidth * sin(curBorder->angle[TR_CS] + sign * curBorder->arc);
1422 z = curBorder->vertex[TR_EL].z = curBorder->vertex[TR_ER].z + (tdble)bankingtype * endwidth * tan(curSeg->angle[TR_XE]);
1423
1424 initAnglesAndGradients(curBorder, startwidth, endwidth);
1425 updateMinMaxForTurn(curBorder, curBorder->radiusl, sign, z);
1426 break;
1427
1428 case 0:
1429 curBorder->radius = curSeg->radiusr + sign * startwidth / 2.0;
1430 curBorder->radiusl = curSeg->radiusr;
1431 curBorder->radiusr = curSeg->radiusr + sign * maxwidth;
1432 curBorder->arc = curSeg->arc;
1433 curBorder->length = curBorder->radius * curBorder->arc;
1434
1435 curBorder->vertex[TR_SR].x = curBorder->vertex[TR_SL].x + sign * startwidth * cos(curBorder->angle[TR_CS]);
1436 curBorder->vertex[TR_SR].y = curBorder->vertex[TR_SL].y + sign * startwidth * sin(curBorder->angle[TR_CS]);
1437 curBorder->vertex[TR_SR].z = curBorder->vertex[TR_SL].z - (tdble)bankingtype * startwidth * tan(curSeg->angle[TR_XS]);
1438 curBorder->vertex[TR_ER].x = curBorder->vertex[TR_EL].x + sign * endwidth * cos(curBorder->angle[TR_CS] + sign * curBorder->arc);
1439 curBorder->vertex[TR_ER].y = curBorder->vertex[TR_EL].y + sign * endwidth * sin(curBorder->angle[TR_CS] + sign * curBorder->arc);
1440 z = curBorder->vertex[TR_ER].z = curBorder->vertex[TR_EL].z - (tdble)bankingtype * endwidth * tan(curSeg->angle[TR_XE]);
1441
1442 initAnglesAndGradients(curBorder, startwidth, endwidth);
1443 updateMinMaxForTurn(curBorder, curBorder->radiusr, sign, z);
1444 break;
1445 }
1446}
1447
1448
1461 tTrackSeg* const curBorder,
1462 const tTrackSeg* const curSeg,
1463 const int side,
1464 const int bankingtype,
1465 const tdble startwidth,
1466 const tdble endwidth
1467)
1468{
1469 tdble z, x, y;
1470 x = y = z = 0.0f;
1471
1472 switch (side) {
1473 case 1:
1474 curBorder->vertex[TR_SL].x = curBorder->vertex[TR_SR].x + startwidth * curSeg->rgtSideNormal.x;
1475 curBorder->vertex[TR_SL].y = curBorder->vertex[TR_SR].y + startwidth * curSeg->rgtSideNormal.y;
1476 curBorder->vertex[TR_SL].z = curBorder->vertex[TR_SR].z + (tdble)bankingtype * startwidth * tan(curSeg->angle[TR_XS]);
1477 x = curBorder->vertex[TR_EL].x = curBorder->vertex[TR_ER].x + endwidth * curSeg->rgtSideNormal.x;
1478 y = curBorder->vertex[TR_EL].y = curBorder->vertex[TR_ER].y + endwidth * curSeg->rgtSideNormal.y;
1479 z = curBorder->vertex[TR_EL].z = curBorder->vertex[TR_ER].z + (tdble)bankingtype * endwidth * tan(curSeg->angle[TR_XE]);
1480 break;
1481 case 0:
1482 curBorder->vertex[TR_SR].x = curBorder->vertex[TR_SL].x - startwidth * curSeg->rgtSideNormal.x;
1483 curBorder->vertex[TR_SR].y = curBorder->vertex[TR_SL].y - startwidth * curSeg->rgtSideNormal.y;
1484 curBorder->vertex[TR_SR].z = curBorder->vertex[TR_SL].z - (tdble)bankingtype * startwidth * tan(curSeg->angle[TR_XS]);
1485 x = curBorder->vertex[TR_ER].x = curBorder->vertex[TR_EL].x - endwidth * curSeg->rgtSideNormal.x;
1486 y = curBorder->vertex[TR_ER].y = curBorder->vertex[TR_EL].y - endwidth * curSeg->rgtSideNormal.y;
1487 z = curBorder->vertex[TR_ER].z = curBorder->vertex[TR_EL].z - (tdble)bankingtype * endwidth * tan(curSeg->angle[TR_XE]);
1488 break;
1489 }
1490
1491 curBorder->angle[TR_YR] = atan2(curBorder->vertex[TR_ER].z - curBorder->vertex[TR_SR].z, curBorder->length);
1492 curBorder->angle[TR_YL] = atan2(curBorder->vertex[TR_EL].z - curBorder->vertex[TR_SL].z, curBorder->length);
1493
1494 curBorder->Kzl = tan(curBorder->angle[TR_YR]);
1495 curBorder->Kzw = (curBorder->angle[TR_XE] - curBorder->angle[TR_XS]) / curBorder->length;
1496 curBorder->Kyl = (endwidth - startwidth) / curBorder->length;
1497
1498 curBorder->rgtSideNormal.x = curSeg->rgtSideNormal.x;
1499 curBorder->rgtSideNormal.y = curSeg->rgtSideNormal.y;
1500
1501 TSTX(x);
1502 TSTY(y);
1503 TSTZ(z);
1504}
1505
1506
1523 tTrackSeg* const curSeg,
1524 const int side,
1525 const int lefttype,
1526 const int righttype,
1527 const int bankingtype,
1528 const tdble startwidth,
1529 const tdble endwidth,
1530 tTrackSurface* surface,
1531 const tdble borderheight,
1532 const int borderstyle
1533)
1534{
1535 tTrackSeg* curBorder = (tTrackSeg*)calloc(1, sizeof(tTrackSeg));
1536 if (side == 1) {
1537 curSeg->lside = curBorder;
1538 curBorder->vertex[TR_SR] = curSeg->vertex[TR_SL];
1539 curBorder->vertex[TR_ER] = curSeg->vertex[TR_EL];
1540 curBorder->type2 = lefttype;
1541 }
1542 else {
1543 curSeg->rside = curBorder;
1544 curBorder->vertex[TR_SL] = curSeg->vertex[TR_SR];
1545 curBorder->vertex[TR_EL] = curSeg->vertex[TR_ER];
1546 curBorder->type2 = righttype;
1547 }
1548
1549 curBorder->startWidth = startwidth;
1550 curBorder->endWidth = endwidth;
1551 curBorder->width = MIN(startwidth, endwidth);
1552 tdble maxWidth = MAX(startwidth, endwidth);
1553
1554 curBorder->type = curSeg->type;
1555 curBorder->surface = surface;
1556 curBorder->height = borderheight;
1557 curBorder->style = borderstyle;
1558 curBorder->envIndex = envIndex; // TODO: Global?
1559 curBorder->angle[TR_XS] = curSeg->angle[TR_XS] * (tdble)bankingtype;
1560 curBorder->angle[TR_XE] = curSeg->angle[TR_XE] * (tdble)bankingtype;
1561 curBorder->angle[TR_ZS] = curSeg->angle[TR_ZS];
1562 curBorder->angle[TR_ZE] = curSeg->angle[TR_ZE];
1563 curBorder->angle[TR_CS] = curSeg->angle[TR_CS];
1564
1565 switch (curSeg->type) {
1566 case TR_STR:
1567 curBorder->length = curSeg->length;
1568 initSideForStraight(curBorder, curSeg, side, bankingtype, startwidth, endwidth);
1569 break;
1570 case TR_LFT:
1571 initSideForTurn(TR_LFT, curBorder, curSeg, side, bankingtype, startwidth, endwidth, maxWidth);
1572 break;
1573 case TR_RGT:
1574 initSideForTurn(TR_RGT, curBorder, curSeg, side, bankingtype, startwidth, endwidth, maxWidth);
1575 break;
1576 }
1577
1578 return curBorder;
1579}
static Vector y[4]
Definition Convex.cpp:56
static const double PI
const T sign(const T &x)
Scalar length(const Quaternion &q)
Definition Quaternion.h:193
void normalize(void)
Definition v2_t.h:247
float tdble
Floating point type used in TORCS.
Definition tgf.h:47
void GfHashRelease(void *hash, tfHashFree hashFree)
Release a hash table.
Definition hash.cpp:353
int GfHashAddStr(void *hash, const char *key, const void *data)
Add an element with a string key to a hash table.
Definition hash.cpp:170
const void * GfHashGetStr(void *hash, const char *key)
Get the user data associated with a string key.
Definition hash.cpp:245
void * GfHashCreate(int type)
Create a new hash table.
Definition hash.cpp:98
const char * GfParmGetStr(void *parmHandle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle.
Definition params.cpp:2453
tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle.
Definition params.cpp:2534
char * GfParmListGetCurEltName(void *handle, const char *path)
Get current subsection name of the parameter set handle during subsection iteration.
Definition params.cpp:2410
int GfParmListSeekNext(void *handle, const char *path)
Advance to the next immediate subsection.
Definition params.cpp:2323
int GfParmListSeekFirst(void *handle, const char *path)
Select the first immediate subsection of a section.
Definition params.cpp:2286
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.
Definition params.cpp:2834
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.
Definition params.cpp:2578
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.
Definition params.cpp:2496
struct trackSeg tTrackSeg
Track segment (tTrackSeg) The segments can be straights (type TR_STR): (the track goes from the right...
tdble RtTrackGetWidth(tTrackSeg *seg, tdble toStart)
Get the track width at the specified point.
Definition rttrack.cpp:59
v2t< float > vec2f
Definition linalg_t.h:36
struct RoadCam * next
Definition track.h:247
char * name
Definition track.h:245
t3Dd pos
Definition track.h:246
int * marks
marks array
Definition track.h:254
int nbMarks
turn marks
Definition track.h:253
tTrkLocPos pos
Center of the pit position.
Definition track.h:457
tdble y
y coordinate
Definition tgf.h:116
tdble z
z coordinate
Definition tgf.h:117
tdble x
x coordinate
Definition tgf.h:115
Optional v4 geographic reference at the main road centre at the start of the first segment (seg->next...
Definition track.h:519
tdble heading
Radians clockwise from true north, [0, 2*pi)
Definition track.h:523
tdble altitude
Metres above mean sea level at reference road centre.
Definition track.h:522
int hasLocation
Both latitude and longitude are available.
Definition track.h:524
tdble longitude
Degrees east, [-180, 180].
Definition track.h:521
tdble latitude
Degrees north, [-90, 90].
Definition track.h:520
Track structure.
Definition track.h:533
Pits Info Structure.
Definition track.h:469
tTrackSeg * pitStart
Pit lane segment.
Definition track.h:487
tTrackSeg * pitEntry
Pit lane segment.
Definition track.h:486
int nPitSeg
actual number of pits
Definition track.h:478
tTrackOwnPit * driversPits
List of pits by driver.
Definition track.h:490
tTrackSeg * pitExit
Pit lane segment.
Definition track.h:489
int side
Pits side:
Definition track.h:479
tdble len
Lenght of each pit stop.
Definition track.h:483
tTrackSeg * pitEnd
Pit lane segment.
Definition track.h:488
tdble speedLimit
Speed limit between pitStart and pitEnd.
Definition track.h:485
int type
Type of Pit:
Definition track.h:470
int nMaxPits
number max of pits
Definition track.h:477
tdble width
Width of each pit stop.
Definition track.h:484
Location on the track in local coordinates.
Definition track.h:434
tdble toMiddle
Distance (+ to left, - to right) relative to the middle of segment.
Definition track.h:448
tdble toLeft
Distance (- to left, + to right) relative to left side of segment.
Definition track.h:449
tdble toRight
Distance (+ to left, - to right) relative to the right side of segment.
Definition track.h:447
tTrackSeg * seg
Track segment.
Definition track.h:435
int type
Type of description:
Definition track.h:436
tdble toStart
Distance to start of segment (or arc if turn)
Definition track.h:446
tdble width
Barrier width.
Definition track.h:278
tdble height
Barrier height.
Definition track.h:279
tTrackSurface * surface
Barrier surface.
Definition track.h:280
vec2f normal
Definition track.h:281
int style
Barrier style.
Definition track.h:277
int type
Geometrical type:
Definition track.h:297
tTrackSurface * surface
Segment surface.
Definition track.h:409
tdble height
Max height for curbs.
Definition track.h:380
tSegExt * ext
Definition track.h:407
t3Dd vertex[4]
Coordinates of the 4 corners of the segment.
Definition track.h:342
tdble radiusr
Radius in meters of the right side of the track (>0)
Definition track.h:338
unsigned int raceInfo
Type of segment regarding the race: Mask value in:
Definition track.h:382
int envIndex
Definition track.h:378
tdble radius
Radius in meters of the middle of the track (>0)
Definition track.h:337
tdble arc
Arc in rad of the curve (>0)
Definition track.h:340
tdble angle[7]
Definition track.h:354
tdble lgfromstart
Length of beginning of segment from starting line.
Definition track.h:336
int id
Segment number.
Definition track.h:295
t3Dd center
Center of the curve.
Definition track.h:341
tdble Kyl
Definition track.h:376
const char * name
Segment name.
Definition track.h:294
tdble length
Length in meters of the middle of the track.
Definition track.h:332
tdble radiusl
Radius in meters of the left side of the track (>0)
Definition track.h:339
tdble Kzw
Definition track.h:374
tRoadCam * cam
Definition track.h:411
struct trackSeg * rside
Definition track.h:421
tTrackBarrier * barrier[2]
Segment barriers.
Definition track.h:410
struct trackSeg * next
Next segment.
Definition track.h:412
tdble startWidth
Width of the beginning of the segment.
Definition track.h:334
struct trackSeg * prev
Previous segment.
Definition track.h:413
int style
Border and barrier segments style:
Definition track.h:319
struct trackSeg * side[2]
Definition track.h:422
t3Dd rgtSideNormal
Definition track.h:377
tdble width
Width of the segment (if constant width)
Definition track.h:333
tdble Kzl
Definition track.h:373
int type2
Position type:
Definition track.h:306
struct trackSeg * lside
Definition track.h:421
tdble endWidth
Width of the end of the segment.
Definition track.h:335
tdble kRebound
Coefficient of energy restitution.
Definition track.h:265
tdble kDammage
Dammages in case of collision.
Definition track.h:269
tdble kFriction
Coefficient of friction.
Definition track.h:264
tdble kRollRes
Rolling resistance.
Definition track.h:266
const char * material
Type of material used.
Definition track.h:262
struct trackSurface * next
Next surface in list.
Definition track.h:260
tdble kRoughWaveLen
Wave length in m of the surface.
Definition track.h:268
tdble kRoughness
Roughtness in m of the surface (wave height)
Definition track.h:267
#define MIN(x, y)
Definition tgf.h:56
#define GF_HASH_TYPE_STR
String key based hash table.
Definition tgf.h:605
static void GfFatal(const char *fmt,...)
Definition tgf.h:338
#define MAX(x, y)
Definition tgf.h:52
#define GfError
Definition tgf.h:350
static int barrierStyle[2]
Definition track3.cpp:83
static tdble borderHeight[2]
Definition track3.cpp:76
#define MAX_TMP_INTS
static tTrackSurface * borderSurface[2]
Definition track3.cpp:79
static const char * barrierMaterial[2]
Definition track3.cpp:84
static tdble borderWidth[2]
Definition track3.cpp:75
static tdble barrierWidth[2]
Definition track3.cpp:81
static tTrackSurface * barrierSurface[2]
Definition track3.cpp:85
static tdble ymin
Definition track3.cpp:30
static const char * sideMaterial[2]
Definition track3.cpp:69
static const char * ValStyle[4]
Definition track3.cpp:63
static int envIndex
Definition track3.cpp:73
static tdble sideStartWidth[2]
Definition track3.cpp:67
static tdble sideEndWidth[2]
Definition track3.cpp:66
static tdble ymax
Definition track3.cpp:30
static tdble zmin
Definition track3.cpp:30
static int sideBankType[2]
Definition track3.cpp:68
static tdble barrierHeight[2]
Definition track3.cpp:82
static tTrackSurface * sideSurface[2]
Definition track3.cpp:70
static tdble zmax
Definition track3.cpp:30
static tdble GlobalStepLen
Definition track3.cpp:87
static tdble xmin
Definition track3.cpp:30
static const char * borderMaterial[2]
Definition track3.cpp:78
static int borderStyle[2]
Definition track3.cpp:77
static tdble xmax
Definition track3.cpp:30
static tTrackSurface * getTrackSurface(void *trackHandle, tTrack *theTrack, const char *material)
Gets surface properties based on the material.
Definition track4.cpp:187
#define TSTZ(z)
Definition track4.cpp:48
static tTrackSeg * findFirstSegmentByName(const tTrack *track, const char *name)
Definition track4.cpp:94
static const char * SectBarrier[2]
Definition track4.cpp:58
static tTrackSeg * findLastSegmentByName(const tTrack *track, const char *name)
Definition track4.cpp:107
static void readGeoreference(tTrack *track, void *handle)
Definition track4.cpp:973
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.
Definition track4.cpp:1460
static const char * SectBorder[2]
Definition track4.cpp:57
static void formatTrackPath(char *buffer, const int size, const char *format,...)
Format a track parameter path and fail if it would be truncated.
Definition track4.cpp:72
static const char * SectSide[2]
Definition track4.cpp:56
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).
Definition track4.cpp:1333
void ReadTrack4(tTrack *theTrack, void *TrackHandle, tRoadCam **camList, int ext)
Definition track4.cpp:1018
static void readDefaultSideParameters(void *trackHandle, tTrack *theTrack)
Reads default side/border track segment parameters.
Definition track4.cpp:230
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.
Definition track4.cpp:1522
#define TSTX(x)
Definition track4.cpp:38
static void CreateSegRing(void *TrackHandle, tTrack *theTrack, int ext)
Definition track4.cpp:458
static void initAnglesAndGradients(tTrackSeg *const curBorder, const tdble startwidth, const tdble endwidth)
Set up border segment angles and gradients.
Definition track4.cpp:1359
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.
Definition track4.cpp:297
static void normSeg(tTrackSeg *curSeg)
Segment coordinate normalization, track is moved to the origin of the coordinate system.
Definition track4.cpp:439
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.
Definition track4.cpp:1384
#define TSTY(y)
Definition track4.cpp:43
static void * TrackHandle
Definition track.cpp:33
static tTrack * theTrack
Definition track.cpp:31
#define TRK_VAL_SPLINE
Definition track.h:237
#define TRK_ATT_ENTRY
Definition track.h:189
#define TRK_ATT_CAM_FOV
Definition track.h:222
#define TRK_ATT_DAMMAGE
Definition track.h:126
#define TRK_VAL_STR
Definition track.h:157
#define TRK_ATT_GEO_HEADING
Definition track.h:57
#define TRK_ATT_STYLE
Definition track.h:206
#define TRK_ATT_ID
Definition track.h:174
#define TRK_SECT_GEOREFERENCE
Definition track.h:53
#define TRK_ATT_SWIDTH
Definition track.h:204
#define TR_XS
X Start angle.
Definition track.h:368
#define TRK_ATT_BKS
Definition track.h:172
#define TRK_ATT_PROFTGTEL
Definition track.h:181
#define TRK_ATT_ZSR
Definition track.h:168
#define TRK_ATT_WIDTH
Definition track.h:45
#define TR_START
Segment after start line.
Definition track.h:395
#define TRK_ATT_BANKTYPE
Definition track.h:208
struct TrackOwnPit tTrackOwnPit
Driver's pit.
#define TRK_VAL_GRASS
Definition track.h:231
#define TR_RSIDE
Right side segment (outer segment)
Definition track.h:315
#define TRK_ATT_PROFTGTER
Definition track.h:183
#define TRK_ATT_PROFSTEPS
Definition track.h:176
#define TR_CS
Center start angle.
Definition track.h:370
#define TRK_SECT_LBORDER
Definition track.h:199
#define TR_LAST
Segment before start line.
Definition track.h:394
#define TRK_ATT_PROFTGTSL
Definition track.h:180
#define TR_PITEND
Car pit End.
Definition track.h:402
#define TRK_VAL_BARRIER
Definition track.h:234
#define TRK_VAL_WALL
Definition track.h:211
#define TRK_VAL_CURB
Definition track.h:212
#define TRK_LST_SEGMENTS
Definition track.h:151
#define TRK_ATT_END
Definition track.h:192
#define TR_PITSTART
Car pit Star.
Definition track.h:401
#define TRK_VAL_RGT
Definition track.h:159
#define TRK_SECT_RBORDER
Definition track.h:200
#define TR_YR
Y Right angle.
Definition track.h:367
#define TRK_ATT_SURF
Definition track.h:46
#define TR_MAIN
Main track segment (ie road part)
Definition track.h:313
#define TRK_ATT_EXIT
Definition track.h:190
#define TRK_ATT_PROFTGTS
Definition track.h:178
struct trackSurface tTrackSurface
Surface.
#define TRK_ATT_ENVIND
Definition track.h:661
#define TRK_ATT_LG
Definition track.h:161
#define TR_FENCE
Fence (no width) (barrier only)
Definition track.h:329
#define TRK_ATT_RADIUSEND
Definition track.h:163
#define TRK_ATT_START
Definition track.h:191
#define TRK_SECT_MAIN
Definition track.h:150
#define TR_SPEEDLIMIT
Segment where the speed is limited.
Definition track.h:397
#define TRK_ATT_ROUGHTWL
Definition track.h:125
#define TR_LFT
Left curve.
Definition track.h:303
#define TRK_VAL_LEVEL
Definition track.h:240
#define TRK_ATT_SPD_LIM
Definition track.h:195
#define TRK_SECT_SURFACES
Definition track.h:119
#define TRK_SECT_LBARRIER
Definition track.h:201
#define TRK_ATT_ROLLRES
Definition track.h:123
#define TRK_ATT_ROUGHT
Definition track.h:124
#define TR_XE
X End angle.
Definition track.h:369
#define TR_EL
End-Left corner.
Definition track.h:351
#define TRK_ATT_REBOUND
Definition track.h:127
#define TRK_ATT_PROFSTEPSLEN
Definition track.h:177
#define TR_ZE
Z End angle.
Definition track.h:365
#define TRK_ATT_ZE
Definition track.h:166
#define TRK_ATT_LEN
Definition track.h:194
#define TRK_ATT_ZS
Definition track.h:165
#define TRK_VAL_FENCE
Definition track.h:213
struct RoadCam tRoadCam
road camera
#define TR_RBORDER
Right border segment (inner segment)
Definition track.h:317
#define TRK_ATT_PROFIL
Definition track.h:175
#define TRK_SECT_RSIDE
Definition track.h:198
#define TRK_VAL_LFT
Definition track.h:158
#define TR_NORMAL
Normal segment.
Definition track.h:393
#define TRK_ATT_HEIGHT
Definition track.h:207
#define TR_YL
Y Left angle.
Definition track.h:366
#define TRK_ATT_RADIUS
Definition track.h:162
#define TRK_ATT_FRICTION
Definition track.h:122
#define TRK_ATT_ZEL
Definition track.h:169
#define TRK_ATT_GEO_LATITUDE
Definition track.h:54
#define TRK_ATT_SIDE
Definition track.h:193
#define TRK_SECT_PITS
Definition track.h:187
#define TRK_ATT_ZSL
Definition track.h:167
#define TR_PITEXIT
Segment where the pit lane cross the main track.
Definition track.h:399
#define TR_LBORDER
Left border segment (inner segment)
Definition track.h:316
#define TRK_ATT_ZER
Definition track.h:170
struct SegExt tSegExt
Extended track segment.
#define TR_LPOS_MAIN
Relative to the main segment, mostly used for racing on the main track.
Definition track.h:442
#define TRK_VAL_ASPHALT
Definition track.h:225
#define TRK_ATT_PROFTGTSR
Definition track.h:182
#define TR_PIT_ON_TRACK_SIDE
The pits are on the track side.
Definition track.h:475
#define TRK_ATT_MARKS
Definition track.h:184
#define TRK_ATT_TORIGHT
Definition track.h:219
struct trackBarrier tTrackBarrier
Barrier.
#define TRK_ATT_GEO_ALTITUDE
Definition track.h:56
#define TR_PITENTRY
Segment where the pit lane cross the main track.
Definition track.h:398
#define TRK_ATT_PROFTGTE
Definition track.h:179
#define TRK_ATT_SEGMENT
Definition track.h:218
#define TRK_ATT_TOSTART
Definition track.h:220
#define TR_SIDE_LFT
Definition track.h:418
#define TR_STR
Straight.
Definition track.h:304
#define TRK_ATT_EWIDTH
Definition track.h:205
#define TR_ER
End_Right corner.
Definition track.h:352
#define TRK_SECT_LSIDE
Definition track.h:197
#define TR_PLAN
Flat (border only)
Definition track.h:326
#define TR_LSIDE
Left side segment (outer segment)
Definition track.h:314
#define TRK_SECT_CAM
Definition track.h:216
#define TR_CURB
Curb (border only)
Definition track.h:327
#define TR_SL
Start-Left corner.
Definition track.h:349
#define TRK_ATT_TYPE
Definition track.h:152
#define TRK_ATT_BKE
Definition track.h:173
#define TRK_ATT_CAM_FOVE
Definition track.h:223
#define TR_PIT
Car pit.
Definition track.h:400
#define TR_RGT
Right curve.
Definition track.h:302
#define TRK_VAL_PLAN
Definition track.h:210
#define TR_PITBUILDING
Pit building wall (barrier only)
Definition track.h:330
#define TR_ZS
Rotation angles of the track in rad anti-clockwise: Index in:
Definition track.h:364
#define TRK_ATT_GRADE
Definition track.h:171
#define TRK_ATT_GEO_LONGITUDE
Definition track.h:55
#define TRK_ATT_ARC
Definition track.h:164
#define TR_WALL
Wall (barrier only)
Definition track.h:328
#define TR_SR
Start-Right corner.
Definition track.h:350
#define TRK_SECT_RBARRIER
Definition track.h:202
tdble TrackSpline(tdble p0, tdble p1, tdble t0, tdble t1, tdble t)
Definition trackutil.cpp:79
void TrackLocal2Global(tTrkLocPos *p, tdble *X, tdble *Y)
Definition trackutil.cpp:29
tdble TrackHeightL(tTrkLocPos *p)
Definition trackutil.cpp:55
int track(tModInfo *modInfo)
Definition trackitf.cpp:85