TORCS  1.3.9
The Open Racing Car Simulator
track3.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  file : track3.cpp
4  created : Fri Aug 31 20:32:33 /etc/localtime 2001
5  copyright : (C) 2001 by Eric Espie
6  email : eric.espie@torcs.org
7  version : $Id$
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 #include <stdlib.h>
21 #include <math.h>
22 #include <stdio.h>
23 
24 #include <tgf.h>
25 #include <robottools.h>
26 #include <track.h>
27 #include <portability.h>
28 #include "trackinc.h"
29 
31 
32 #define TSTX(x) \
33  if (xmin > (x)) xmin = (x); \
34  if (xmax < (x)) xmax = (x);
35 
36 #define TSTY(y) \
37  if (ymin > (y)) ymin = (y); \
38  if (ymax < (y)) ymax = (y);
39 
40 #define TSTZ(z) \
41  if (zmin > (z)) zmin = (z); \
42  if (zmax < (z)) zmax = (z);
43 
44 /*
45  * Sides global variables
46  */
47 static const char *KeySideSurface[2] = {TRK_ATT_RSSURF, TRK_ATT_LSSURF};
48 static const char *KeySideWidth[2] = {TRK_ATT_RSW, TRK_ATT_LSW};
49 static const char *KeySideStartWidth[2] = {TRK_ATT_RSWS, TRK_ATT_LSWS};
50 static const char *KeySideEndWidth[2] = {TRK_ATT_RSWE, TRK_ATT_LSWE};
51 static const char *KeySideBankType[2] = {TRK_ATT_RST, TRK_ATT_LST};
52 
53 static const char *KeyBorderSurface[2] = {TRK_ATT_RBSURF, TRK_ATT_LBSURF};
54 static const char *KeyBorderWidth[2] = {TRK_ATT_RBW, TRK_ATT_LBW};
55 static const char *KeyBorderStyle[2] = {TRK_ATT_RBS, TRK_ATT_LBS};
56 static const char *KeyBorderHeight[2] = {TRK_ATT_RBH, TRK_ATT_LBH};
57 
59 static const char *KeyBarrierWidth[2] = {TRK_ATT_RBAW, TRK_ATT_LBAW};
60 static const char *KeyBarrierStyle[2] = {TRK_ATT_RBAS, TRK_ATT_LBAS};
61 static const char *KeyBarrierHeight[2] = {TRK_ATT_RBAH, TRK_ATT_LBAH};
62 
64 
65 
66 static tdble sideEndWidth[2];
68 static int sideBankType[2];
69 static const char *sideMaterial[2];
71 
72 
73 static int envIndex;
74 
75 static tdble borderWidth[2];
76 static tdble borderHeight[2];
77 static int borderStyle[2];
78 static const char *borderMaterial[2];
80 
81 static tdble barrierWidth[2];
82 static tdble barrierHeight[2];
83 static int barrierStyle[2];
84 static const char *barrierMaterial[2];
86 
87 static tdble GlobalStepLen = 0;
88 
89 static tTrackSurface*
90 AddTrackSurface(void *TrackHandle, tTrack *theTrack, const char *material)
91 {
92  const int BUFSIZE = 256;
93  char path[BUFSIZE];
94  tTrackSurface *curSurf;
95 
96  /* search within existing surfaces */
97  curSurf = theTrack->surfaces;
98  while (curSurf) {
99  if (strcmp(curSurf->material, material) == 0) {
100  return curSurf;
101  }
102  curSurf = curSurf->next;
103  }
104 
105  /* Create a new surface */
106  curSurf = (tTrackSurface*)malloc(sizeof(tTrackSurface));
107  if (!curSurf) {
108  GfFatal("AddTrackSurface: Memory allocation failed\n");
109  }
110 
111  curSurf->material = material;
112  snprintf(path, BUFSIZE, "%s/%s/%s", TRK_SECT_SURFACES, TRK_LST_SURF, material);
113  curSurf->kFriction = GfParmGetNum(TrackHandle, path, TRK_ATT_FRICTION, (char*)NULL, 0.8f);
114  curSurf->kRollRes = GfParmGetNum(TrackHandle, path, TRK_ATT_ROLLRES, (char*)NULL, 0.001f);
115  curSurf->kRoughness = GfParmGetNum(TrackHandle, path, TRK_ATT_ROUGHT, (char*)NULL, 0.0f) / 2.0f;
116  curSurf->kRoughWaveLen = 2.0 * PI / GfParmGetNum(TrackHandle, path, TRK_ATT_ROUGHTWL, (char*)NULL, 1.0f);
117  curSurf->kDammage = GfParmGetNum(TrackHandle, path, TRK_ATT_DAMMAGE, (char*)NULL, 10.0f);
118  curSurf->kRebound = GfParmGetNum(TrackHandle, path, TRK_ATT_REBOUND, (char*)NULL, 1.0f);
119 
120  curSurf->next = theTrack->surfaces;
121  theTrack->surfaces = curSurf;
122 
123  return curSurf;
124 }
125 
126 
127 static void
129 {
130  int side;
131 
132  for (side = 0; side < 2; side++) {
135  sideEndWidth[side] = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, KeySideWidth[side], (char*)NULL, 0.0);
136 
137  /* banking of borders */
139  sideBankType[side] = 0;
140  } else {
141  sideBankType[side] = 1;
142  }
143 
146  borderWidth[side] = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, KeyBorderWidth[side], (char*)NULL, 0.0);
147  borderHeight[side] = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, KeyBorderHeight[side], (char*)NULL, 0.0);
148  const char* style = GfParmGetStr(TrackHandle, TRK_SECT_MAIN, KeyBorderStyle[side], TRK_VAL_PLAN);
149 
150  if (strcmp(style, TRK_VAL_PLAN) == 0) {
151  borderStyle[side] = TR_PLAN;
152  } else if (strcmp(style, TRK_VAL_CURB) == 0) {
153  borderStyle[side] = TR_CURB;
154  } else {
155  borderStyle[side] = TR_WALL;
156  }
157 
158  /* Barrier parameters */
161  barrierHeight[side] = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, KeyBarrierHeight[side], (char*)NULL, 1.0);
163 
164  if (strcmp(style, TRK_VAL_FENCE) == 0) {
165  barrierStyle[side] = TR_FENCE;
166  barrierWidth[side] = 0;
167  } else {
168  barrierStyle[side] = TR_WALL;
169  barrierWidth[side] = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, KeyBarrierWidth[side], (char*)NULL, 0.5);
170  }
171  }
172 }
173 
174 
175 static void
176 AddSides(tTrackSeg *curSeg, void *TrackHandle, tTrack *theTrack, int curStep, int steps)
177 {
178  tTrackSeg *curSide;
179  tTrackSeg *mSeg;
180  tTrackSeg *curBorder;
181  tTrackBarrier *curBarrier;
182  tdble x, y, z;
183  tdble al, alfl;
184  int j;
185  tdble x1, x2, y1, y2;
186  tdble sw, ew, bw;
187  tdble minWidth;
188  tdble maxWidth;
189  int type;
190  int side;
191  tdble Kew;
192  const int BUFSIZE = 256;
193  char path[BUFSIZE];
194 
195  x = y = z = 0;
196  mSeg = curSeg;
197 
198  snprintf(path, BUFSIZE, "%s/%s", TRK_SECT_MAIN, TRK_LST_SEG);
199  for (side = 0; side < 2; side++) {
200  curSeg = mSeg;
201  if (curStep == 0) {
202  /* Side parameters */
203  sw = GfParmGetCurNum(TrackHandle, path, KeySideStartWidth[side], (char*)NULL, sideEndWidth[side]);
204  ew = GfParmGetCurNum(TrackHandle, path, KeySideEndWidth[side], (char*)NULL, sw);
205  sideStartWidth[side] = sw;
206  sideEndWidth[side] = ew;
209 
210  /* Border parameters */
211  bw = GfParmGetCurNum(TrackHandle, path, KeyBorderWidth[side], (char*)NULL, borderWidth[side]);
212  borderWidth[side] = bw;
213  borderHeight[side] = GfParmGetCurNum(TrackHandle, path, KeyBorderHeight[side], (char*)NULL, 0.0);
216  const char* style = GfParmGetCurStr(TrackHandle, path, KeyBorderStyle[side], ValStyle[borderStyle[side]]);
217  if (strcmp(style, TRK_VAL_PLAN) == 0) {
218  borderStyle[side] = TR_PLAN;
219  } else if (strcmp(style, TRK_VAL_CURB) == 0) {
220  borderStyle[side] = TR_CURB;
221  } else {
222  borderStyle[side] = TR_WALL;
223  }
224 
225  /* Barrier parameters */
230  if (strcmp(style, TRK_VAL_FENCE) == 0) {
231  barrierStyle[side] = TR_FENCE;
232  barrierWidth[side] = 0;
233  } else {
234  barrierStyle[side] = TR_WALL;
235  barrierWidth[side] = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, KeyBarrierWidth[side], (char*)NULL, barrierWidth[side]);
236  }
237  } else {
238  sw = sideStartWidth[side];
239  ew = sideEndWidth[side];
240  bw = borderWidth[side];
241  }
242  Kew = (ew - sw) / (tdble)steps;
243  ew = sw + (tdble)(curStep+1) * Kew;
244  sw = sw + (tdble)(curStep) * Kew;
245 
246  /* Borders */
247  if (bw != 0.0) {
248  curBorder = (tTrackSeg*)calloc(1, sizeof(tTrackSeg));
249  if (side == 1) {
250  curSeg->lside = curBorder;
251  curBorder->vertex[TR_SR] = curSeg->vertex[TR_SL];
252  curBorder->vertex[TR_ER] = curSeg->vertex[TR_EL];
253  curBorder->type2 = TR_LBORDER;
254  } else {
255  curSeg->rside = curBorder;
256  curBorder->vertex[TR_SL] = curSeg->vertex[TR_SR];
257  curBorder->vertex[TR_EL] = curSeg->vertex[TR_ER];
258  curBorder->type2 = TR_RBORDER;
259  }
260 
261  type = sideBankType[side];
262  curBorder->startWidth = bw;
263  curBorder->endWidth = bw;
264  curBorder->width = bw;
265  curBorder->type = curSeg->type;
266  curBorder->surface = borderSurface[side];
267  curBorder->height = borderHeight[side];
268  curBorder->style = borderStyle[side];
269  curBorder->envIndex = envIndex;
270  curBorder->angle[TR_XS] = curSeg->angle[TR_XS] * (tdble)type;
271  curBorder->angle[TR_XE] = curSeg->angle[TR_XE] * (tdble)type;
272  curBorder->angle[TR_ZS] = curSeg->angle[TR_ZS];
273  curBorder->angle[TR_ZE] = curSeg->angle[TR_ZE];
274  curBorder->angle[TR_CS] = curSeg->angle[TR_CS];
275 
276  switch(curSeg->type) {
277  case TR_STR:
278  curBorder->length = curSeg->length;
279 
280  switch(side) {
281  case 1:
282  curBorder->vertex[TR_SL].x = curBorder->vertex[TR_SR].x + bw * curSeg->rgtSideNormal.x;
283  curBorder->vertex[TR_SL].y = curBorder->vertex[TR_SR].y + bw * curSeg->rgtSideNormal.y;
284  curBorder->vertex[TR_SL].z = curBorder->vertex[TR_SR].z + (tdble)type * bw * tan(curSeg->angle[TR_XS]);
285  x = curBorder->vertex[TR_EL].x = curBorder->vertex[TR_ER].x + bw * curSeg->rgtSideNormal.x;
286  y = curBorder->vertex[TR_EL].y = curBorder->vertex[TR_ER].y + bw * curSeg->rgtSideNormal.y;
287  z = curBorder->vertex[TR_EL].z = curBorder->vertex[TR_ER].z + (tdble)type * bw * tan(curSeg->angle[TR_XE]);
288  break;
289  case 0:
290  curBorder->vertex[TR_SR].x = curBorder->vertex[TR_SL].x - bw * curSeg->rgtSideNormal.x;
291  curBorder->vertex[TR_SR].y = curBorder->vertex[TR_SL].y - bw * curSeg->rgtSideNormal.y;
292  curBorder->vertex[TR_SR].z = curBorder->vertex[TR_SL].z - (tdble)type * bw * tan(curSeg->angle[TR_XS]);
293  x = curBorder->vertex[TR_ER].x = curBorder->vertex[TR_EL].x - bw * curSeg->rgtSideNormal.x;
294  y = curBorder->vertex[TR_ER].y = curBorder->vertex[TR_EL].y - bw * curSeg->rgtSideNormal.y;
295  z = curBorder->vertex[TR_ER].z = curBorder->vertex[TR_EL].z - (tdble)type * bw * tan(curSeg->angle[TR_XE]);
296  break;
297  }
298  curBorder->angle[TR_YR] = atan2(curBorder->vertex[TR_ER].z - curBorder->vertex[TR_SR].z, curBorder->length);
299  curBorder->angle[TR_YL] = atan2(curBorder->vertex[TR_EL].z - curBorder->vertex[TR_SL].z, curBorder->length);
300 
301  curBorder->Kzl = tan(curBorder->angle[TR_YR]);
302  curBorder->Kzw = (curBorder->angle[TR_XE] - curBorder->angle[TR_XS]) / curBorder->length;
303  curBorder->Kyl = 0;
304 
305  curBorder->rgtSideNormal.x = curSeg->rgtSideNormal.x;
306  curBorder->rgtSideNormal.y = curSeg->rgtSideNormal.y;
307 
308  TSTX(x);
309  TSTY(y);
310  TSTZ(z);
311  break;
312 
313  case TR_LFT:
314  curBorder->center.x = curSeg->center.x;
315  curBorder->center.y = curSeg->center.y;
316 
317  switch(side) {
318  case 1:
319  curBorder->radius = curSeg->radiusl - bw / 2.0;
320  curBorder->radiusr = curSeg->radiusl;
321  curBorder->radiusl = curSeg->radiusl - bw;
322  curBorder->arc = curSeg->arc;
323  curBorder->length = curBorder->radius * curBorder->arc;
324 
325  curBorder->vertex[TR_SL].x = curBorder->vertex[TR_SR].x - bw * cos(curBorder->angle[TR_CS]);
326  curBorder->vertex[TR_SL].y = curBorder->vertex[TR_SR].y - bw * sin(curBorder->angle[TR_CS]);
327  curBorder->vertex[TR_SL].z = curBorder->vertex[TR_SR].z + (tdble)type * bw * tan(curSeg->angle[TR_XS]);
328  curBorder->vertex[TR_EL].x = curBorder->vertex[TR_ER].x - bw * cos(curBorder->angle[TR_CS] + curBorder->arc);
329  curBorder->vertex[TR_EL].y = curBorder->vertex[TR_ER].y - (tdble)type * bw * sin(curBorder->angle[TR_CS] + curBorder->arc);
330  z = curBorder->vertex[TR_EL].z = curBorder->vertex[TR_ER].z + bw * tan(curSeg->angle[TR_XE]);
331 
332  curBorder->angle[TR_YR] = atan2(curBorder->vertex[TR_ER].z - curBorder->vertex[TR_SR].z,
333  curBorder->arc * curBorder->radiusr);
334  curBorder->angle[TR_YL] = atan2(curBorder->vertex[TR_EL].z - curBorder->vertex[TR_SL].z,
335  curBorder->arc * curBorder->radiusl);
336 
337  curBorder->Kzl = tan(curBorder->angle[TR_YR]) * curBorder->radiusr;
338  curBorder->Kzw = (curBorder->angle[TR_XE] - curBorder->angle[TR_XS]) / curBorder->arc;
339  curBorder->Kyl = 0;
340 
341  /* to find the boundary */
342  al = (curBorder->angle[TR_ZE] - curBorder->angle[TR_ZS])/36.0;
343  alfl = curBorder->angle[TR_ZS];
344 
345  for (j = 0; j < 36; j++) {
346  alfl += al;
347  x1 = curBorder->center.x + (curBorder->radiusl) * sin(alfl); /* location of end */
348  y1 = curBorder->center.y - (curBorder->radiusl) * cos(alfl);
349  TSTX(x1);
350  TSTY(y1);
351  }
352  TSTZ(z);
353  break;
354 
355  case 0:
356  curBorder->radius = curSeg->radiusr + bw / 2.0;
357  curBorder->radiusl = curSeg->radiusr;
358  curBorder->radiusr = curSeg->radiusr + bw;
359  curBorder->arc = curSeg->arc;
360  curBorder->length = curBorder->radius * curBorder->arc;
361 
362  curBorder->vertex[TR_SR].x = curBorder->vertex[TR_SL].x + bw * cos(curBorder->angle[TR_CS]);
363  curBorder->vertex[TR_SR].y = curBorder->vertex[TR_SL].y + bw * sin(curBorder->angle[TR_CS]);
364  curBorder->vertex[TR_SR].z = curBorder->vertex[TR_SL].z - (tdble)type * bw * tan(curSeg->angle[TR_XS]);
365  curBorder->vertex[TR_ER].x = curBorder->vertex[TR_EL].x + bw * cos(curBorder->angle[TR_CS] + curBorder->arc);
366  curBorder->vertex[TR_ER].y = curBorder->vertex[TR_EL].y + bw * sin(curBorder->angle[TR_CS] + curBorder->arc);
367  z = curBorder->vertex[TR_ER].z = curBorder->vertex[TR_EL].z - (tdble)type * bw * tan(curSeg->angle[TR_XE]);
368 
369  curBorder->angle[TR_YR] = atan2(curBorder->vertex[TR_ER].z - curBorder->vertex[TR_SR].z,
370  curBorder->arc * curBorder->radiusr);
371  curBorder->angle[TR_YL] = atan2(curBorder->vertex[TR_EL].z - curBorder->vertex[TR_SL].z,
372  curBorder->arc * curBorder->radiusl);
373 
374  curBorder->Kzl = tan(curBorder->angle[TR_YR]) * (curBorder->radiusr);
375  curBorder->Kzw = (curBorder->angle[TR_XE] - curBorder->angle[TR_XS]) / curBorder->arc;
376  curBorder->Kyl = 0;
377 
378  /* to find the boundary */
379  al = (curBorder->angle[TR_ZE] - curBorder->angle[TR_ZS])/36.0;
380  alfl = curBorder->angle[TR_ZS];
381 
382  for (j = 0; j < 36; j++) {
383  alfl += al;
384  x2 = curBorder->center.x + (curBorder->radiusr) * sin(alfl); /* location of end */
385  y2 = curBorder->center.y - (curBorder->radiusr) * cos(alfl);
386  TSTX(x2);
387  TSTY(y2);
388  }
389  TSTZ(z);
390  break;
391 
392  }
393  break;
394  case TR_RGT:
395  curBorder->center.x = curSeg->center.x;
396  curBorder->center.y = curSeg->center.y;
397 
398  switch(side) {
399  case 1:
400  curBorder->radius = curSeg->radiusl + bw / 2.0;
401  curBorder->radiusr = curSeg->radiusl;
402  curBorder->radiusl = curSeg->radiusl + bw;
403  curBorder->arc = curSeg->arc;
404  curBorder->length = curBorder->radius * curBorder->arc;
405 
406  curBorder->vertex[TR_SL].x = curBorder->vertex[TR_SR].x + bw * cos(curBorder->angle[TR_CS]);
407  curBorder->vertex[TR_SL].y = curBorder->vertex[TR_SR].y + bw * sin(curBorder->angle[TR_CS]);
408  curBorder->vertex[TR_SL].z = curBorder->vertex[TR_SR].z + (tdble)type * bw * tan(curSeg->angle[TR_XS]);
409  curBorder->vertex[TR_EL].x = curBorder->vertex[TR_ER].x + bw * cos(curBorder->angle[TR_CS] - curBorder->arc);
410  curBorder->vertex[TR_EL].y = curBorder->vertex[TR_ER].y + bw * sin(curBorder->angle[TR_CS] - curBorder->arc);
411  z = curBorder->vertex[TR_EL].z = curBorder->vertex[TR_ER].z + (tdble)type * bw * tan(curSeg->angle[TR_XE]);
412 
413  curBorder->angle[TR_YR] = atan2(curBorder->vertex[TR_ER].z - curBorder->vertex[TR_SR].z,
414  curBorder->arc * curBorder->radiusr);
415  curBorder->angle[TR_YL] = atan2(curBorder->vertex[TR_EL].z - curBorder->vertex[TR_SL].z,
416  curBorder->arc * curBorder->radiusl);
417 
418  curBorder->Kzl = tan(curBorder->angle[TR_YR]) * curBorder->radiusr;
419  curBorder->Kzw = (curBorder->angle[TR_XE] - curBorder->angle[TR_XS]) / curBorder->arc;
420  curBorder->Kyl = 0;
421 
422  /* to find the boundary */
423  al = (curBorder->angle[TR_ZE] - curBorder->angle[TR_ZS])/36.0;
424  alfl = curBorder->angle[TR_ZS];
425 
426  for (j = 0; j < 36; j++) {
427  alfl += al;
428  x1 = curBorder->center.x - (curBorder->radiusl) * sin(alfl); /* location of end */
429  y1 = curBorder->center.y + (curBorder->radiusl) * cos(alfl);
430  TSTX(x1);
431  TSTY(y1);
432  }
433  TSTZ(z);
434  break;
435 
436  case 0:
437  curBorder->radius = curSeg->radiusr - bw / 2.0;
438  curBorder->radiusl = curSeg->radiusr;
439  curBorder->radiusr = curSeg->radiusr - bw;
440  curBorder->arc = curSeg->arc;
441  curBorder->length = curBorder->radius * curBorder->arc;
442 
443  curBorder->vertex[TR_SR].x = curBorder->vertex[TR_SL].x - bw * cos(curBorder->angle[TR_CS]);
444  curBorder->vertex[TR_SR].y = curBorder->vertex[TR_SL].y - bw * sin(curBorder->angle[TR_CS]);
445  curBorder->vertex[TR_SR].z = curBorder->vertex[TR_SL].z - (tdble)type * bw * tan(curSeg->angle[TR_XS]);
446  curBorder->vertex[TR_ER].x = curBorder->vertex[TR_EL].x - bw * cos(curBorder->angle[TR_CS] - curBorder->arc);
447  curBorder->vertex[TR_ER].y = curBorder->vertex[TR_EL].y - bw * sin(curBorder->angle[TR_CS] - curBorder->arc);
448  z = curBorder->vertex[TR_ER].z = curBorder->vertex[TR_EL].z - (tdble)type * bw * tan(curSeg->angle[TR_XE]);
449 
450  curBorder->angle[TR_YR] = atan2(curBorder->vertex[TR_ER].z - curBorder->vertex[TR_SR].z,
451  curBorder->arc * curBorder->radiusr);
452  curBorder->angle[TR_YL] = atan2(curBorder->vertex[TR_EL].z - curBorder->vertex[TR_SL].z,
453  curBorder->arc * curBorder->radiusl);
454 
455  curBorder->Kzl = tan(curBorder->angle[TR_YR]) * (curBorder->radiusr);
456  curBorder->Kzw = (curBorder->angle[TR_XE] - curBorder->angle[TR_XS]) / curBorder->arc;
457  curBorder->Kyl = 0;
458 
459  /* to find the boundary */
460  al = (curBorder->angle[TR_ZE] - curBorder->angle[TR_ZS])/36.0;
461  alfl = curBorder->angle[TR_ZS];
462 
463  for (j = 0; j < 36; j++) {
464  alfl += al;
465  x2 = curBorder->center.x - (curBorder->radiusr) * sin(alfl); /* location of end */
466  y2 = curBorder->center.y - (curBorder->radiusr) * cos(alfl);
467  TSTX(x2);
468  TSTY(y2);
469  }
470  TSTZ(z);
471  break;
472  }
473  break;
474  }
475 
476  curSeg = curBorder;
477  }
478 
479 
480  /* Sides */
481  if ((sw != 0.0) || (ew != 0)) {
482  curSide = (tTrackSeg*)calloc(1, sizeof(tTrackSeg));
483  if (side == 1) {
484  curSeg->lside = curSide;
485  curSide->vertex[TR_SR] = curSeg->vertex[TR_SL];
486  curSide->vertex[TR_ER] = curSeg->vertex[TR_EL];
487  curSide->type2 = TR_LSIDE;
488  } else {
489  curSeg->rside = curSide;
490  curSide->vertex[TR_SL] = curSeg->vertex[TR_SR];
491  curSide->vertex[TR_EL] = curSeg->vertex[TR_ER];
492  curSide->type2 = TR_RSIDE;
493  }
494 
495  type = sideBankType[side];
496  curSide->startWidth = sw;
497  curSide->endWidth = ew;
498  curSide->width = minWidth = MIN(sw, ew);
499  maxWidth = MAX(sw, ew);
500  curSide->type = curSeg->type;
501  curSide->surface = sideSurface[side];
502  curSide->envIndex = envIndex;
503  curSide->angle[TR_XS] = curSeg->angle[TR_XS] * (tdble)type;
504  curSide->angle[TR_XE] = curSeg->angle[TR_XE] * (tdble)type;
505  curSide->angle[TR_ZS] = curSeg->angle[TR_ZS];
506  curSide->angle[TR_ZE] = curSeg->angle[TR_ZE];
507  curSide->angle[TR_CS] = curSeg->angle[TR_CS];
508 
509  switch(curSeg->type) {
510  case TR_STR:
511  curSide->length = curSeg->length;
512 
513  switch(side) {
514  case 1:
515  curSide->vertex[TR_SL].x = curSide->vertex[TR_SR].x + sw * curSeg->rgtSideNormal.x;
516  curSide->vertex[TR_SL].y = curSide->vertex[TR_SR].y + sw * curSeg->rgtSideNormal.y;
517  curSide->vertex[TR_SL].z = curSide->vertex[TR_SR].z + (tdble)type * sw * tan(curSeg->angle[TR_XS]);
518  x = curSide->vertex[TR_EL].x = curSide->vertex[TR_ER].x + ew * curSeg->rgtSideNormal.x;
519  y = curSide->vertex[TR_EL].y = curSide->vertex[TR_ER].y + ew * curSeg->rgtSideNormal.y;
520  z = curSide->vertex[TR_EL].z = curSide->vertex[TR_ER].z + (tdble)type * ew * tan(curSeg->angle[TR_XE]);
521  break;
522  case 0:
523  curSide->vertex[TR_SR].x = curSide->vertex[TR_SL].x - sw * curSeg->rgtSideNormal.x;
524  curSide->vertex[TR_SR].y = curSide->vertex[TR_SL].y - sw * curSeg->rgtSideNormal.y;
525  curSide->vertex[TR_SR].z = curSide->vertex[TR_SL].z - (tdble)type * sw * tan(curSeg->angle[TR_XS]);
526  x = curSide->vertex[TR_ER].x = curSide->vertex[TR_EL].x - ew * curSeg->rgtSideNormal.x;
527  y = curSide->vertex[TR_ER].y = curSide->vertex[TR_EL].y - ew * curSeg->rgtSideNormal.y;
528  z = curSide->vertex[TR_ER].z = curSide->vertex[TR_EL].z - (tdble)type * ew * tan(curSeg->angle[TR_XE]);
529  break;
530  }
531  curSide->angle[TR_YR] = atan2(curSide->vertex[TR_ER].z - curSide->vertex[TR_SR].z, curSide->length);
532  curSide->angle[TR_YL] = atan2(curSide->vertex[TR_EL].z - curSide->vertex[TR_SL].z, curSide->length);
533 
534  curSide->Kzl = tan(curSide->angle[TR_YR]);
535  curSide->Kzw = (curSide->angle[TR_XE] - curSide->angle[TR_XS]) / curSide->length;
536  curSide->Kyl = (ew - sw) / curSide->length;
537 
538  curSide->rgtSideNormal.x = curSeg->rgtSideNormal.x;
539  curSide->rgtSideNormal.y = curSeg->rgtSideNormal.y;
540 
541  TSTX(x);
542  TSTY(y);
543  TSTZ(z);
544  break;
545 
546  case TR_LFT:
547  curSide->center.x = curSeg->center.x;
548  curSide->center.y = curSeg->center.y;
549 
550  switch(side) {
551  case 1:
552  curSide->radius = curSeg->radiusl - sw / 2.0;
553  curSide->radiusr = curSeg->radiusl;
554  curSide->radiusl = curSeg->radiusl - maxWidth;
555  curSide->arc = curSeg->arc;
556  curSide->length = curSide->radius * curSide->arc;
557 
558  curSide->vertex[TR_SL].x = curSide->vertex[TR_SR].x - sw * cos(curSide->angle[TR_CS]);
559  curSide->vertex[TR_SL].y = curSide->vertex[TR_SR].y - sw * sin(curSide->angle[TR_CS]);
560  curSide->vertex[TR_SL].z = curSide->vertex[TR_SR].z + (tdble)type * sw * tan(curSeg->angle[TR_XS]);
561  curSide->vertex[TR_EL].x = curSide->vertex[TR_ER].x - ew * cos(curSide->angle[TR_CS] + curSide->arc);
562  curSide->vertex[TR_EL].y = curSide->vertex[TR_ER].y - ew * sin(curSide->angle[TR_CS] + curSide->arc);
563  z = curSide->vertex[TR_EL].z = curSide->vertex[TR_ER].z + (tdble)type * ew * tan(curSeg->angle[TR_XE]);
564 
565  curSide->angle[TR_YR] = atan2(curSide->vertex[TR_ER].z - curSide->vertex[TR_SR].z,
566  curSide->arc * curSide->radiusr);
567  curSide->angle[TR_YL] = atan2(curSide->vertex[TR_EL].z - curSide->vertex[TR_SL].z,
568  curSide->arc * curSide->radiusl);
569 
570  curSide->Kzl = tan(curSide->angle[TR_YR]) * curSide->radiusr;
571  curSide->Kzw = (curSide->angle[TR_XE] - curSide->angle[TR_XS]) / curSide->arc;
572  curSide->Kyl = (ew - sw) / curSide->arc;
573 
574  /* to find the boundary */
575  al = (curSide->angle[TR_ZE] - curSide->angle[TR_ZS])/36.0;
576  alfl = curSide->angle[TR_ZS];
577 
578  for (j = 0; j < 36; j++) {
579  alfl += al;
580  x1 = curSide->center.x + (curSide->radiusl) * sin(alfl); /* location of end */
581  y1 = curSide->center.y - (curSide->radiusl) * cos(alfl);
582  TSTX(x1);
583  TSTY(y1);
584  }
585  TSTZ(z);
586  break;
587 
588  case 0:
589  curSide->radius = curSeg->radiusr + sw / 2.0;
590  curSide->radiusl = curSeg->radiusr;
591  curSide->radiusr = curSeg->radiusr + maxWidth;
592  curSide->arc = curSeg->arc;
593  curSide->length = curSide->radius * curSide->arc;
594 
595  curSide->vertex[TR_SR].x = curSide->vertex[TR_SL].x + sw * cos(curSide->angle[TR_CS]);
596  curSide->vertex[TR_SR].y = curSide->vertex[TR_SL].y + sw * sin(curSide->angle[TR_CS]);
597  curSide->vertex[TR_SR].z = curSide->vertex[TR_SL].z - (tdble)type * sw * tan(curSeg->angle[TR_XS]);
598  curSide->vertex[TR_ER].x = curSide->vertex[TR_EL].x + ew * cos(curSide->angle[TR_CS] + curSide->arc);
599  curSide->vertex[TR_ER].y = curSide->vertex[TR_EL].y + ew * sin(curSide->angle[TR_CS] + curSide->arc);
600  z = curSide->vertex[TR_ER].z = curSide->vertex[TR_EL].z - (tdble)type * ew * tan(curSeg->angle[TR_XE]);
601 
602  curSide->angle[TR_YR] = atan2(curSide->vertex[TR_ER].z - curSide->vertex[TR_SR].z,
603  curSide->arc * curSide->radiusr);
604  curSide->angle[TR_YL] = atan2(curSide->vertex[TR_EL].z - curSide->vertex[TR_SL].z,
605  curSide->arc * curSide->radiusl);
606 
607  curSide->Kzl = tan(curSide->angle[TR_YR]) * (curSide->radiusr);
608  curSide->Kzw = (curSide->angle[TR_XE] - curSide->angle[TR_XS]) / curSide->arc;
609  curSide->Kyl = (ew - sw) / curSide->arc;
610 
611  /* to find the boundary */
612  al = (curSide->angle[TR_ZE] - curSide->angle[TR_ZS])/36.0;
613  alfl = curSide->angle[TR_ZS];
614 
615  for (j = 0; j < 36; j++) {
616  alfl += al;
617  x2 = curSide->center.x + (curSide->radiusr) * sin(alfl); /* location of end */
618  y2 = curSide->center.y - (curSide->radiusr) * cos(alfl);
619  TSTX(x2);
620  TSTY(y2);
621  }
622  TSTZ(z);
623  break;
624 
625  }
626  break;
627  case TR_RGT:
628  curSide->center.x = curSeg->center.x;
629  curSide->center.y = curSeg->center.y;
630 
631  switch(side) {
632  case 1:
633  curSide->radius = curSeg->radiusl + sw / 2.0;
634  curSide->radiusr = curSeg->radiusl;
635  curSide->radiusl = curSeg->radiusl + maxWidth;
636  curSide->arc = curSeg->arc;
637  curSide->length = curSide->radius * curSide->arc;
638 
639  curSide->vertex[TR_SL].x = curSide->vertex[TR_SR].x + sw * cos(curSide->angle[TR_CS]);
640  curSide->vertex[TR_SL].y = curSide->vertex[TR_SR].y + sw * sin(curSide->angle[TR_CS]);
641  curSide->vertex[TR_SL].z = curSide->vertex[TR_SR].z + (tdble)type * sw * tan(curSeg->angle[TR_XS]);
642  curSide->vertex[TR_EL].x = curSide->vertex[TR_ER].x + ew * cos(curSide->angle[TR_CS] - curSide->arc);
643  curSide->vertex[TR_EL].y = curSide->vertex[TR_ER].y + ew * sin(curSide->angle[TR_CS] - curSide->arc);
644  z = curSide->vertex[TR_EL].z = curSide->vertex[TR_ER].z + (tdble)type * ew * tan(curSeg->angle[TR_XE]);
645 
646  curSide->angle[TR_YR] = atan2(curSide->vertex[TR_ER].z - curSide->vertex[TR_SR].z,
647  curSide->arc * curSide->radiusr);
648  curSide->angle[TR_YL] = atan2(curSide->vertex[TR_EL].z - curSide->vertex[TR_SL].z,
649  curSide->arc * curSide->radiusl);
650 
651  curSide->Kzl = tan(curSide->angle[TR_YR]) * curSide->radiusr;
652  curSide->Kzw = (curSide->angle[TR_XE] - curSide->angle[TR_XS]) / curSide->arc;
653  curSide->Kyl = (ew - sw) / curSide->arc;
654 
655  /* to find the boundary */
656  al = (curSide->angle[TR_ZE] - curSide->angle[TR_ZS])/36.0;
657  alfl = curSide->angle[TR_ZS];
658 
659  for (j = 0; j < 36; j++) {
660  alfl += al;
661  x1 = curSide->center.x - (curSide->radiusl) * sin(alfl); /* location of end */
662  y1 = curSide->center.y + (curSide->radiusl) * cos(alfl);
663  TSTX(x1);
664  TSTY(y1);
665  }
666  TSTZ(z);
667  break;
668 
669  case 0:
670  curSide->radius = curSeg->radiusr - sw / 2.0;
671  curSide->radiusl = curSeg->radiusr;
672  curSide->radiusr = curSeg->radiusr - maxWidth;
673  curSide->arc = curSeg->arc;
674  curSide->length = curSide->radius * curSide->arc;
675 
676  curSide->vertex[TR_SR].x = curSide->vertex[TR_SL].x - sw * cos(curSide->angle[TR_CS]);
677  curSide->vertex[TR_SR].y = curSide->vertex[TR_SL].y - sw * sin(curSide->angle[TR_CS]);
678  curSide->vertex[TR_SR].z = curSide->vertex[TR_SL].z - (tdble)type * sw * tan(curSeg->angle[TR_XS]);
679  curSide->vertex[TR_ER].x = curSide->vertex[TR_EL].x - ew * cos(curSide->angle[TR_CS] - curSide->arc);
680  curSide->vertex[TR_ER].y = curSide->vertex[TR_EL].y - ew * sin(curSide->angle[TR_CS] - curSide->arc);
681  z = curSide->vertex[TR_ER].z = curSide->vertex[TR_EL].z - (tdble)type * ew * tan(curSeg->angle[TR_XE]);
682 
683  curSide->angle[TR_YR] = atan2(curSide->vertex[TR_ER].z - curSide->vertex[TR_SR].z,
684  curSide->arc * curSide->radiusr);
685  curSide->angle[TR_YL] = atan2(curSide->vertex[TR_EL].z - curSide->vertex[TR_SL].z,
686  curSide->arc * curSide->radiusl);
687 
688  curSide->Kzl = tan(curSide->angle[TR_YR]) * (curSide->radiusr);
689  curSide->Kzw = (curSide->angle[TR_XE] - curSide->angle[TR_XS]) / curSide->arc;
690  curSide->Kyl = (ew - sw) / curSide->arc;
691 
692  /* to find the boundary */
693  al = (curSide->angle[TR_ZE] - curSide->angle[TR_ZS])/36.0;
694  alfl = curSide->angle[TR_ZS];
695 
696  for (j = 0; j < 36; j++) {
697  alfl += al;
698  x2 = curSide->center.x - (curSide->radiusr) * sin(alfl); /* location of end */
699  y2 = curSide->center.y - (curSide->radiusr) * cos(alfl);
700  TSTX(x2);
701  TSTY(y2);
702  }
703  TSTZ(z);
704  break;
705  }
706  break;
707  }
708  }
709 
710  /* Barrier */
711  curBarrier = (tTrackBarrier*)malloc(sizeof(tTrackBarrier));
712  if (!curBarrier) {
713  GfFatal("AddSides: memory allocation error");
714  }
715  curBarrier->style = barrierStyle[side];
716  curBarrier->width = barrierWidth[side];
717  curBarrier->height = barrierHeight[side];
718  curBarrier->surface = barrierSurface[side];
719 
720  // Compute normal of barrier for side collisions.
721  tTrackSeg *bseg = mSeg;
722  int bstart, bend;
723  float bsign;
724 
725  if (side == TR_SIDE_LFT) {
726  bstart = TR_SL;
727  bend = TR_EL;
728  bsign = -1.0f;
729  } else {
730  bstart = TR_SR;
731  bend = TR_ER;
732  bsign = 1.0f;
733  }
734 
735  while (bseg->side[side] != NULL) {
736  bseg = bseg->side[side];
737  }
738 
739  vec2f n(
740  -(bseg->vertex[bend].y - bseg->vertex[bstart].y)*bsign,
741  (bseg->vertex[bend].x - bseg->vertex[bstart].x)*bsign
742  );
743 
744  n.normalize();
745  curBarrier->normal = n;
746 
747  mSeg->barrier[side] = curBarrier;
748  }
749 }
750 
751 
752 static void
754 {
755  curSeg->vertex[TR_SR].x -= xmin;
756  curSeg->vertex[TR_SR].y -= ymin;
757  curSeg->vertex[TR_SR].z -= zmin;
758  curSeg->vertex[TR_SL].x -= xmin;
759  curSeg->vertex[TR_SL].y -= ymin;
760  curSeg->vertex[TR_SL].z -= zmin;
761  curSeg->vertex[TR_ER].x -= xmin;
762  curSeg->vertex[TR_ER].y -= ymin;
763  curSeg->vertex[TR_ER].z -= zmin;
764  curSeg->vertex[TR_EL].x -= xmin;
765  curSeg->vertex[TR_EL].y -= ymin;
766  curSeg->vertex[TR_EL].z -= zmin;
767  curSeg->center.x -= xmin;
768  curSeg->center.y -= ymin;
769 }
770 
771 static void
773 {
774  int j;
775  int segread, curindex;
776  tdble radius, radiusend = 0, dradius;
777  tdble innerradius;
778  tdble arc;
779  tdble length;
780  tTrackSeg *curSeg;
781  tTrackSeg *root;
782  tdble alf;
783  tdble xr, yr, newxr, newyr;
784  tdble xl, yl, newxl, newyl;
785  tdble cenx, ceny;
786  tdble width, wi2;
787  tdble x1, x2, y1, y2;
788  tdble al, alfl;
789  tdble zsl, zsr, zel, zer, zs, ze;
790  tdble bankings, bankinge, dz; // dzl, dzr;
791  tdble etgt, stgt;
792  tdble etgtl, stgtl;
793  tdble etgtr, stgtr;
794  tdble stepslg = 0;
795  int steps, curStep;
796  tTrackSurface *surface;
797  char *segName;
798  int type;
799  const char *profil;
800  tdble totLength;
801 
802  tdble tl, dtl, T1l, T2l;
803  tdble tr, dtr, T1r, T2r;
804  tdble curzel, curzer, curArc, curLength, curzsl, curzsr;
805  tdble grade;
806 
807  const int BUFSIZE = 256;
808  char path[BUFSIZE];
809 #define MAX_TMP_INTS 256
810  int mi[MAX_TMP_INTS];
811  int ind = 0;
812 
813  radius = arc = length = alf = xr = yr = newxr = newyr = xl = yl = 0;
814  zel = zer = etgtl = etgtr = newxl = newyl = 0;
815  type = 0;
816 
817  width = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_WIDTH, (char*)NULL, 15.0);
818  wi2 = width / 2.0;
819 
820  grade = -100000.0;
821  root = (tTrackSeg*)NULL;
822  totLength = 0;
823 
824  snprintf(path, BUFSIZE, "%s/%s", TRK_SECT_MAIN, TRK_LST_SEG);
825  if (start == NULL) {
826  xr = xl = 0.0;
827  yr = 0.0;
828  yl = width;
829  alf = 0.0;
830  zsl = zsr = zel = zer = zs = ze = 0.0;
831  stgt = etgt = 0.0;
832  stgtl = etgtl = 0.0;
833  stgtr = etgtr = 0.0;
834  } else {
836  const char* segtype = GfParmGetCurStr(TrackHandle, path, TRK_ATT_TYPE, "");
837  if (strcmp(segtype, TRK_VAL_STR) == 0) {
838 
839  } else if (strcmp(segtype, TRK_VAL_LFT) == 0) {
840 
841  } else if (strcmp(segtype, TRK_VAL_RGT) == 0) {
842  xr = start->vertex[TR_SR].x;
843  yr = start->vertex[TR_SR].y;
844  zsl = zsr = zel = zer = zs = ze = start->vertex[TR_SR].z;
845  alf = start->angle[TR_ZS];
846  xl = xr - width * sin(alf);
847  yl = yr + width * cos(alf);
848  stgt = etgt = 0.0;
849  stgtl = etgtl = 0.0;
850  stgtr = etgtr = 0.0;
851  }
852  }
853 
854 
855  /* Main Track */
857  surface = AddTrackSurface(TrackHandle, theTrack, material);
858  envIndex = 0;
859 
861 
862  segread = 0;
863  curindex = 0;
865  do {
866  const char* segtype = GfParmGetCurStr(TrackHandle, path, TRK_ATT_TYPE, NULL);
867  if (segtype == 0) {
868  continue;
869  }
870  segread++;
871 
872  zsl = zel;
873  zsr = zer;
874  TSTZ(zsl);
875  TSTZ(zsr);
876 
877  /* Turn Marks */
878  if (ext) {
879  const char *marks = GfParmGetCurStr(TrackHandle, path, TRK_ATT_MARKS, NULL);
880  ind = 0;
881  if (marks) {
882  char* tmpmarks = strdup(marks);
883  char *s = strtok(tmpmarks, ";");
884  while ((s != NULL) && (ind < MAX_TMP_INTS)) {
885  mi[ind] = (int)strtol(s, NULL, 0);
886  ind++;
887  s = strtok(NULL, ";");
888  }
889  free(tmpmarks);
890  }
891  }
892 
893  /* surface change */
894  material = GfParmGetCurStr(TrackHandle, path, TRK_ATT_SURF, material);
895  surface = AddTrackSurface(TrackHandle, theTrack, material);
896  envIndex = (int)GfParmGetCurNum(TrackHandle, path, TRK_ATT_ENVIND, (char*)NULL, (float) (envIndex+1)) - 1;
897 
898  /* get segment type and lenght */
899  if (strcmp(segtype, TRK_VAL_STR) == 0) {
900  /* straight */
901  length = GfParmGetCurNum(TrackHandle, path, TRK_ATT_LG, (char*)NULL, 0);
902  type = TR_STR;
903  radius = radiusend = 0;
904  } else if (strcmp(segtype, TRK_VAL_LFT) == 0) {
905  /* left curve */
906  radius = GfParmGetCurNum(TrackHandle, path, TRK_ATT_RADIUS, (char*)NULL, 0);
907  radiusend = GfParmGetCurNum(TrackHandle, path, TRK_ATT_RADIUSEND, (char*)NULL, radius);
908  arc = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ARC, (char*)NULL, 0);
909  type = TR_LFT;
910  length = (radius + radiusend) / 2.0 * arc;
911  } else if (strcmp(segtype, TRK_VAL_RGT) == 0) {
912  /* right curve */
913  radius = GfParmGetCurNum(TrackHandle, path, TRK_ATT_RADIUS, (char*)NULL, 0);
914  radiusend = GfParmGetCurNum(TrackHandle, path, TRK_ATT_RADIUSEND, (char*)NULL, radius);
915  arc = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ARC, (char*)NULL, 0);
916  type = TR_RGT;
917  length = (radius + radiusend) / 2.0 * arc;
918  }
919 
920  segName = GfParmListGetCurEltName(TrackHandle, path);
921 
922  /* elevation and banking */
923  zsl = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZSL, (char*)NULL, zsl);
924  zsr = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZSR, (char*)NULL, zsr);
925  zel = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZEL, (char*)NULL, zel);
926  zer = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZER, (char*)NULL, zer);
927  ze = zs = -100000.0;
928  ze = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZE, (char*)NULL, ze);
929  zs = GfParmGetCurNum(TrackHandle, path, TRK_ATT_ZS, (char*)NULL, zs);
930  grade = GfParmGetCurNum(TrackHandle, path, TRK_ATT_GRADE, (char*)NULL, grade);
931  if (zs != -100000.0) {
932  zsr = zsl = zs;
933  } else {
934  zs = (zsl + zsr) / 2.0;
935  }
936  if (ze != -100000.0) {
937  zer = zel = ze;
938  } else if (grade != -100000.0) {
939  ze = zs + length * grade;
940  } else {
941  ze = (zel + zer) / 2.0;
942  }
943  bankings = atan2(zsl - zsr, width);
944  bankinge = atan2(zel - zer, width);
945  bankings = GfParmGetCurNum(TrackHandle, path, TRK_ATT_BKS, (char*)NULL, bankings);
946  bankinge = GfParmGetCurNum(TrackHandle, path, TRK_ATT_BKE, (char*)NULL, bankinge);
947  dz = tan(bankings) * width / 2.0;
948  zsl = zs + dz;
949  zsr = zs - dz;
950  dz = tan(bankinge) * width / 2.0;
951  zel = ze + dz;
952  zer = ze - dz;
953 
954  TSTZ(zsl);
955  TSTZ(zsr);
956 
957  /* Get segment profil */
959  stgtl = etgtl;
960  stgtr = etgtr;
961  if (strcmp(profil, TRK_VAL_SPLINE) == 0) {
962  steps = (int)GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFSTEPS, (char*)NULL, 1.0);
963  if (steps == 1) {
964  stepslg = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFSTEPSLEN, (char*)NULL, GlobalStepLen);
965  if (stepslg) {
966  steps = (int)(length / stepslg) + 1;
967  } else {
968  steps = 1;
969  }
970  }
971  stgtl = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTSL, (char*)NULL, stgtl);
972  etgtl = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTEL, (char*)NULL, etgtl);
973  stgtr = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTSR, (char*)NULL, stgtr);
974  etgtr = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTER, (char*)NULL, etgtr);
975  stgt = etgt = -100000.0;
976  stgt = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTS, (char*)NULL, stgt);
977  etgt = GfParmGetCurNum(TrackHandle, path, TRK_ATT_PROFTGTE, (char*)NULL, etgt);
978  if (stgt != -100000.0) {
979  stgtl = stgtr = stgt;
980  }
981  if (etgt != -100000.0) {
982  etgtl = etgtr = etgt;
983  }
984  } else {
985  steps = 1;
986  stgtl = etgtl = (zel - zsl) / length;
987  stgtr = etgtr = (zer - zsr) / length;
988  }
989  GfParmSetCurNum(TrackHandle, path, TRK_ATT_ID, (char*)NULL, (tdble)curindex);
990 
991  //dzl = zel - zsl;
992  //dzr = zer - zsr;
993  T1l = stgtl * length;
994  T2l = etgtl * length;
995  tl = 0.0;
996  dtl = 1.0 / (tdble)steps;
997  T1r = stgtr * length;
998  T2r = etgtr * length;
999  tr = 0.0;
1000  dtr = 1.0 / (tdble)steps;
1001 
1002  curStep = 0;
1003  curzel = zsl;
1004  curzer = zsr;
1005  curArc = arc / (tdble)steps;
1006  curLength = length / (tdble)steps;
1007  dradius = (radiusend - radius) / (tdble)steps;
1008  if (radiusend != radius) {
1009  /* Compute the correct curLength... */
1010  if (steps != 1) {
1011  dradius = (radiusend - radius) / (tdble)(steps - 1);
1012  tdble tmpAngle = 0;
1013  tdble tmpRadius = radius;
1014  for (curStep = 0; curStep < steps; curStep++) {
1015  tmpAngle += curLength / tmpRadius;
1016  tmpRadius += dradius;
1017  }
1018  curLength *= arc / tmpAngle;
1019  }
1020  }
1021  curStep = 0;
1022 
1023  while (curStep < steps) {
1024 
1025  tl += dtl;
1026  tr += dtr;
1027 
1028  curzsl = curzel;
1029  curzel = TrackSpline(zsl, zel, T1l, T2l, tl);
1030 
1031  curzsr = curzer;
1032  curzer = TrackSpline(zsr, zer, T1r, T2r, tr);
1033 
1034  if (dradius != 0) {
1035  curArc = curLength / radius;
1036  }
1037 
1038  /* allocate a new segment */
1039  curSeg = (tTrackSeg*)calloc(1, sizeof(tTrackSeg));
1040  if (root == NULL) {
1041  root = curSeg;
1042  curSeg->next = curSeg;
1043  curSeg->prev = curSeg;
1044  } else {
1045  curSeg->next = root->next;
1046  curSeg->next->prev = curSeg;
1047  curSeg->prev = root;
1048  root->next = curSeg;
1049  root = curSeg;
1050  }
1051  curSeg->type2 = TR_MAIN;
1052  curSeg->name = segName;
1053  curSeg->id = curindex;
1054  curSeg->width = curSeg->startWidth = curSeg->endWidth = width;
1055  curSeg->surface = surface;
1056  curSeg->envIndex = envIndex;
1057  curSeg->lgfromstart = totLength;
1058 
1059  if (ext && ind) {
1060  int *mrks = (int*)calloc(ind, sizeof(int));
1061  tSegExt *segExt = (tSegExt*)calloc(1, sizeof(tSegExt));
1062 
1063  memcpy(mrks, mi, ind*sizeof(int));
1064  segExt->nbMarks = ind;
1065  segExt->marks = mrks;
1066  curSeg->ext = segExt;
1067  ind = 0;
1068  }
1069 
1070 
1071  switch (type) {
1072  case TR_STR:
1073  /* straight */
1074  curSeg->type = TR_STR;
1075  curSeg->length = curLength;
1076 
1077  newxr = xr + curLength * cos(alf); /* find end coordinates */
1078  newyr = yr + curLength * sin(alf);
1079  newxl = xl + curLength * cos(alf);
1080  newyl = yl + curLength * sin(alf);
1081 
1082  curSeg->vertex[TR_SR].x = xr;
1083  curSeg->vertex[TR_SR].y = yr;
1084  curSeg->vertex[TR_SR].z = curzsr;
1085 
1086  curSeg->vertex[TR_SL].x = xl;
1087  curSeg->vertex[TR_SL].y = yl;
1088  curSeg->vertex[TR_SL].z = curzsl;
1089 
1090  curSeg->vertex[TR_ER].x = newxr;
1091  curSeg->vertex[TR_ER].y = newyr;
1092  curSeg->vertex[TR_ER].z = curzer;
1093 
1094  curSeg->vertex[TR_EL].x = newxl;
1095  curSeg->vertex[TR_EL].y = newyl;
1096  curSeg->vertex[TR_EL].z = curzel;
1097 
1098  curSeg->angle[TR_ZS] = alf;
1099  curSeg->angle[TR_ZE] = alf;
1100  curSeg->angle[TR_YR] = atan2(curSeg->vertex[TR_ER].z - curSeg->vertex[TR_SR].z, curLength);
1101  curSeg->angle[TR_YL] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_SL].z, curLength);
1102  curSeg->angle[TR_XS] = atan2(curSeg->vertex[TR_SL].z - curSeg->vertex[TR_SR].z, width);
1103  curSeg->angle[TR_XE] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_ER].z, width);
1104 
1105  curSeg->Kzl = tan(curSeg->angle[TR_YR]);
1106  curSeg->Kzw = (curSeg->angle[TR_XE] - curSeg->angle[TR_XS]) / curLength;
1107  curSeg->Kyl = 0;
1108 
1109  curSeg->rgtSideNormal.x = -sin(alf);
1110  curSeg->rgtSideNormal.y = cos(alf);
1111 
1112  TSTX(newxr); TSTX(newxl);
1113  TSTY(newyr); TSTY(newyl);
1114 
1115  break;
1116 
1117  case TR_LFT:
1118  /* left curve */
1119  curSeg->type = TR_LFT;
1120  curSeg->radius = radius;
1121  curSeg->radiusr = radius + wi2;
1122  curSeg->radiusl = radius - wi2;
1123  curSeg->arc = curArc;
1124  curSeg->length = curLength;
1125 
1126  innerradius = radius - wi2; /* left side aligned */
1127  cenx = xl - innerradius * sin(alf); /* compute center location: */
1128  ceny = yl + innerradius * cos(alf);
1129  curSeg->center.x = cenx;
1130  curSeg->center.y = ceny;
1131 
1132  curSeg->angle[TR_ZS] = alf;
1133  curSeg->angle[TR_CS] = alf - PI / 2.0;
1134  alf += curArc;
1135  curSeg->angle[TR_ZE] = alf;
1136 
1137  newxl = cenx + innerradius * sin(alf); /* location of end */
1138  newyl = ceny - innerradius * cos(alf);
1139  newxr = cenx + (innerradius + width) * sin(alf); /* location of end */
1140  newyr = ceny - (innerradius + width) * cos(alf);
1141 
1142  curSeg->vertex[TR_SR].x = xr;
1143  curSeg->vertex[TR_SR].y = yr;
1144  curSeg->vertex[TR_SR].z = curzsr;
1145 
1146  curSeg->vertex[TR_SL].x = xl;
1147  curSeg->vertex[TR_SL].y = yl;
1148  curSeg->vertex[TR_SL].z = curzsl;
1149 
1150  curSeg->vertex[TR_ER].x = newxr;
1151  curSeg->vertex[TR_ER].y = newyr;
1152  curSeg->vertex[TR_ER].z = curzer;
1153 
1154  curSeg->vertex[TR_EL].x = newxl;
1155  curSeg->vertex[TR_EL].y = newyl;
1156  curSeg->vertex[TR_EL].z = curzel;
1157 
1158  curSeg->angle[TR_YR] = atan2(curSeg->vertex[TR_ER].z - curSeg->vertex[TR_SR].z, curArc * (innerradius + width));
1159  curSeg->angle[TR_YL] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_SL].z, curArc * innerradius);
1160  curSeg->angle[TR_XS] = atan2(curSeg->vertex[TR_SL].z - curSeg->vertex[TR_SR].z, width);
1161  curSeg->angle[TR_XE] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_ER].z, width);
1162 
1163  curSeg->Kzl = tan(curSeg->angle[TR_YR]) * (innerradius + width);
1164  curSeg->Kzw = (curSeg->angle[TR_XE] - curSeg->angle[TR_XS]) / curArc;
1165  curSeg->Kyl = 0;
1166 
1167  /* to find the boundary */
1168  al = (curSeg->angle[TR_ZE] - curSeg->angle[TR_ZS])/36.0;
1169  alfl = curSeg->angle[TR_ZS];
1170 
1171  for (j = 0; j < 36; j++) {
1172  alfl += al;
1173  x1 = curSeg->center.x + (innerradius) * sin(alfl); /* location of end */
1174  y1 = curSeg->center.y - (innerradius) * cos(alfl);
1175  x2 = curSeg->center.x + (innerradius + width) * sin(alfl); /* location of end */
1176  y2 = curSeg->center.y - (innerradius + width) * cos(alfl);
1177  TSTX(x1); TSTX(x2);
1178  TSTY(y1); TSTY(y2);
1179  }
1180 
1181  break;
1182 
1183  case TR_RGT:
1184  /* right curve */
1185  curSeg->type = TR_RGT;
1186  curSeg->radius = radius;
1187  curSeg->radiusr = radius - wi2;
1188  curSeg->radiusl = radius + wi2;
1189  curSeg->arc = curArc;
1190  curSeg->length = curLength;
1191 
1192  innerradius = radius - wi2; /* right side aligned */
1193  cenx = xr + innerradius * sin(alf); /* compute center location */
1194  ceny = yr - innerradius * cos(alf);
1195  curSeg->center.x = cenx;
1196  curSeg->center.y = ceny;
1197 
1198  curSeg->angle[TR_ZS] = alf;
1199  curSeg->angle[TR_CS] = alf + PI / 2.0;
1200  alf -= curSeg->arc;
1201  curSeg->angle[TR_ZE] = alf;
1202 
1203  newxl = cenx - (innerradius + width) * sin(alf); /* location of end */
1204  newyl = ceny + (innerradius + width) * cos(alf);
1205  newxr = cenx - innerradius * sin(alf); /* location of end */
1206  newyr = ceny + innerradius * cos(alf);
1207 
1208  curSeg->vertex[TR_SR].x = xr;
1209  curSeg->vertex[TR_SR].y = yr;
1210  curSeg->vertex[TR_SR].z = curzsr;
1211 
1212  curSeg->vertex[TR_SL].x = xl;
1213  curSeg->vertex[TR_SL].y = yl;
1214  curSeg->vertex[TR_SL].z = curzsl;
1215 
1216  curSeg->vertex[TR_ER].x = newxr;
1217  curSeg->vertex[TR_ER].y = newyr;
1218  curSeg->vertex[TR_ER].z = curzer;
1219 
1220  curSeg->vertex[TR_EL].x = newxl;
1221  curSeg->vertex[TR_EL].y = newyl;
1222  curSeg->vertex[TR_EL].z = curzel;
1223 
1224  curSeg->angle[TR_YR] = atan2(curSeg->vertex[TR_ER].z - curSeg->vertex[TR_SR].z, curArc * innerradius);
1225  curSeg->angle[TR_YL] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_SL].z, curArc * (innerradius + width));
1226  curSeg->angle[TR_XS] = atan2(curSeg->vertex[TR_SL].z - curSeg->vertex[TR_SR].z, width);
1227  curSeg->angle[TR_XE] = atan2(curSeg->vertex[TR_EL].z - curSeg->vertex[TR_ER].z, width);
1228 
1229  curSeg->Kzl = tan(curSeg->angle[TR_YR]) * innerradius;
1230  curSeg->Kzw = (curSeg->angle[TR_XE] - curSeg->angle[TR_XS]) / curArc;
1231  curSeg->Kyl = 0;
1232 
1233  /* to find the boundaries */
1234  al = (curSeg->angle[TR_ZE] - curSeg->angle[TR_ZS])/36.0;
1235  alfl = curSeg->angle[TR_ZS];
1236 
1237  for (j = 0; j < 36; j++) {
1238  alfl += al;
1239  x1 = curSeg->center.x - (innerradius + width) * sin(alfl); /* location of end */
1240  y1 = curSeg->center.y + (innerradius + width) * cos(alfl);
1241  x2 = curSeg->center.x - innerradius * sin(alfl); /* location of end */
1242  y2 = curSeg->center.y + innerradius * cos(alfl);
1243  TSTX(x1); TSTX(x2);
1244  TSTY(y1); TSTY(y2);
1245  }
1246  break;
1247 
1248  }
1249 
1250  AddSides(curSeg, TrackHandle, theTrack, curStep, steps);
1251 
1252  totLength += curSeg->length;
1253  xr = newxr;
1254  yr = newyr;
1255  xl = newxl;
1256  yl = newyl;
1257  curindex++;
1258  curStep++;
1259  if (type != TR_STR) {
1260  /* printf("radius = %f arc = %f steps %d, length %f, stepslg %f\n", radius, RAD2DEG(curArc), steps, length, curLength); */
1261  radius += dradius;
1262  }
1263  }
1264 
1265  } while (GfParmListSeekNext(TrackHandle, path) == 0);
1266 
1267  theTrack->seg = root;
1268  theTrack->length = totLength;
1269  theTrack->nseg = curindex;
1270 }
1271 
1272 
1273 
1274 
1275 /*
1276  * Read version 3 track segments
1277  */
1278 void
1279 ReadTrack3(tTrack *theTrack, void *TrackHandle, tRoadCam **camList, int ext)
1280 {
1281  int i;
1282  tTrackSeg *curSeg = NULL, *mSeg;
1283  tTrackSeg *curSeg2;
1284  tTrackSeg *pitEntrySeg = NULL;
1285  tTrackSeg *pitExitSeg = NULL;
1286  tTrackSeg *pitStart = NULL;
1287  tTrackSeg *pitEnd = NULL;
1288  tTrackSeg *curPitSeg = NULL;
1289  tTrackPitInfo *pits;
1290  const char *segName;
1291  int segId;
1292  tRoadCam *curCam;
1293  tTrkLocPos trkPos;
1294  int found = 0;
1295  const char *paramVal;
1296  const char *pitType;
1297  const int BUFSIZE = 256;
1298  char path[BUFSIZE];
1299  char path2[BUFSIZE];
1300  int changeSeg;
1301  tdble offset = 0;
1302  tdble toStart;
1303 
1304  xmin = xmax = ymin = ymax = zmin = zmax = 0.0;
1305 
1307 
1308  CreateSegRing3(TrackHandle, theTrack, (tTrackSeg*)NULL, (tTrackSeg*)NULL, ext);
1309 
1310  pits = &(theTrack->pits);
1312 
1313 
1314  if (strcmp(pitType, TRK_VAL_PIT_TYPE_NONE) != 0) {
1316  if (segName != 0) {
1317  snprintf(path, BUFSIZE, "%s/%s/%s", TRK_SECT_MAIN, TRK_LST_SEG, segName);
1318  segId = (int)GfParmGetNum(TrackHandle, path, TRK_ATT_ID, (char*)NULL, -1);
1319  pitEntrySeg = theTrack->seg;
1320  found = 0;
1321  for(i = 0; i < theTrack->nseg; i++) {
1322  if (pitEntrySeg->id == segId) {
1323  found = 1;
1324  } else if (found) {
1325  pitEntrySeg = pitEntrySeg->next;
1326  break;
1327  }
1328  pitEntrySeg = pitEntrySeg->prev;
1329  }
1330  if (!found) {
1331  pitEntrySeg = NULL;
1332  }
1333  }
1334 
1336  if (segName != 0) {
1337  pitExitSeg = theTrack->seg->next;
1338  found = 0;
1339  for(i = 0; i < theTrack->nseg; i++) {
1340  /* set the flag on the last segment of pit_exit */
1341  if (!strcmp(segName, pitExitSeg->name)) {
1342  found = 1;
1343  } else if (found) {
1344  pitExitSeg = pitExitSeg->prev;
1345  break;
1346  }
1347  pitExitSeg = pitExitSeg->next;
1348  }
1349  if (!found) {
1350  pitExitSeg = NULL;
1351  }
1352  }
1353 
1355  if (segName != 0) {
1356  pitStart = theTrack->seg;
1357  found = 0;
1358  for(i = 0; i < theTrack->nseg; i++) {
1359  if (!strcmp(segName, pitStart->name)) {
1360  found = 1;
1361  } else if (found) {
1362  pitStart = pitStart->next;
1363  break;
1364  }
1365  pitStart = pitStart->prev;
1366  }
1367  if (!found) {
1368  pitStart = NULL;
1369  }
1370 
1371  }
1373  if (segName != 0) {
1374  pitEnd = theTrack->seg->next;
1375  found = 0;
1376  for(i = 0; i < theTrack->nseg; i++) {
1377  if (!strcmp(segName, pitEnd->name)) {
1378  found = 1;
1379  } else if (found) {
1380  pitEnd = pitEnd->prev;
1381  break;
1382  }
1383  pitEnd = pitEnd->next;
1384  }
1385  if (!found) {
1386  pitEnd = NULL;
1387  }
1388  }
1389  paramVal = GfParmGetStr(TrackHandle, TRK_SECT_MAIN, TRK_ATT_PIT_SIDE, "right");
1390  if (strcmp(paramVal, "right") == 0) {
1391  pits->side = TR_RGT;
1392  } else {
1393  pits->side = TR_LFT;
1394  }
1395  pits->speedLimit = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_SPD_LIM, (char*)NULL, 25.0);
1396  if ((pitEntrySeg != NULL) && (pitExitSeg != NULL) && (pitStart != NULL) && (pitEnd != NULL)) {
1397  pits->pitEntry = pitEntrySeg;
1398  pits->pitExit = pitExitSeg;
1399  pits->pitStart = pitStart;
1400  pits->pitEnd = pitEnd;
1401  pitEntrySeg->raceInfo |= TR_PITENTRY;
1402  pitExitSeg->raceInfo |= TR_PITEXIT;
1403  pits->len = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_PIT_LEN, (char*)NULL, 15.0);
1404  pits->width = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_PIT_WIDTH, (char*)NULL, 5.0);
1405  found = 1;
1406  } else {
1407  found = 0;
1408  }
1409  }
1410 
1411  if (found && (strcmp(pitType, TRK_VAL_PIT_TYPE_SIDE) == 0)) {
1412  pits->type = TR_PIT_ON_TRACK_SIDE;
1413  pits->nPitSeg = 0;
1414  if (pitStart->lgfromstart > pitEnd->lgfromstart) {
1415  pits->nMaxPits = (int)((theTrack->length - pitStart->lgfromstart +
1416  pitEnd->lgfromstart + pitEnd->length + pits->len / 2.0) / pits->len);
1417  } else {
1418  pits->nMaxPits = (int)((- pitStart->lgfromstart + pitEnd->lgfromstart +
1419  pitEnd->length + pits->len / 2.0) / pits->len);
1420  }
1421  pits->driversPits = (tTrackOwnPit*)calloc(pits->nMaxPits, sizeof(tTrackOwnPit));
1422 
1423  mSeg = pits->pitStart->prev;
1424  changeSeg = 1;
1425  toStart = 0;
1426  i = 0;
1427  while (i < pits->nMaxPits) {
1428  pits->driversPits[i].pos.type = TR_LPOS_MAIN;
1429  if (changeSeg) {
1430  changeSeg = 0;
1431  offset = 0;
1432  mSeg = mSeg->next;
1433  switch (pits->side) {
1434  case TR_RGT:
1435  curPitSeg = mSeg->rside;
1436  if (curPitSeg->rside) {
1437  offset = curPitSeg->width;
1438  curPitSeg = curPitSeg->rside;
1439  }
1440  break;
1441  case TR_LFT:
1442  curPitSeg = mSeg->lside;
1443  if (curPitSeg->lside) {
1444  offset = curPitSeg->width;
1445  curPitSeg = curPitSeg->lside;
1446  }
1447  break;
1448  }
1449  if (toStart >= mSeg->length) {
1450  toStart -= mSeg->length;
1451  changeSeg = 1;
1452  continue;
1453  }
1454  }
1455  pits->driversPits[i].pos.seg = mSeg;
1456  pits->driversPits[i].pos.toStart = toStart + pits->len / 2.0;
1457  switch (pits->side) {
1458  case TR_RGT:
1459  pits->driversPits[i].pos.toRight = -offset - RtTrackGetWidth(curPitSeg, toStart) + pits->width / 2.0;
1460  pits->driversPits[i].pos.toLeft = mSeg->width - pits->driversPits[i].pos.toRight;
1461  pits->driversPits[i].pos.toMiddle = mSeg->width / 2.0 - pits->driversPits[i].pos.toRight;
1462  break;
1463  case TR_LFT:
1464  pits->driversPits[i].pos.toLeft = -offset - RtTrackGetWidth(curPitSeg, toStart) + pits->width / 2.0;
1465  pits->driversPits[i].pos.toRight = mSeg->width - pits->driversPits[i].pos.toLeft;
1466  pits->driversPits[i].pos.toMiddle = mSeg->width / 2.0 - pits->driversPits[i].pos.toLeft;
1467  break;
1468  }
1469  toStart += pits->len;
1470  if (toStart >= mSeg->length) {
1471  toStart -= mSeg->length;
1472  changeSeg = 1;
1473  }
1474  i++;
1475  }
1476 
1477  for (mSeg = pitStart->prev; mSeg != pitEnd->next->next; mSeg = mSeg->next) {
1478  curSeg2 = NULL;
1479  switch(pits->side) {
1480  case TR_RGT:
1481  curSeg = mSeg->rside;
1482  curSeg2 = curSeg->rside;
1483  if ((mSeg != pitStart->prev) && (mSeg != pitEnd->next)) {
1484  mSeg->barrier[0]->style = TR_PITBUILDING;
1485  }
1486  break;
1487  case TR_LFT:
1488  curSeg = mSeg->lside;
1489  curSeg2 = curSeg->lside;
1490  if ((mSeg != pitStart->prev) && (mSeg != pitEnd->next)) {
1491  mSeg->barrier[1]->style = TR_PITBUILDING;
1492  }
1493  break;
1494  }
1495  if ((mSeg != pitStart->prev) && (mSeg != pitEnd->next)) {
1496  curSeg->raceInfo |= TR_PIT | TR_SPEEDLIMIT;
1497  if (curSeg2) {
1498  curSeg2->raceInfo |= TR_PIT | TR_SPEEDLIMIT;
1499  }
1500  } else if (mSeg == pitStart->prev) {
1501  curSeg->raceInfo |= TR_PITSTART;
1502  if (curSeg2) {
1503  curSeg2->raceInfo |= TR_PITSTART;
1504  }
1505  } else if (mSeg == pitEnd->next) {
1506  curSeg->raceInfo |= TR_PITEND;
1507  if (curSeg2) {
1508  curSeg2->raceInfo |= TR_PITEND;
1509  }
1510  }
1511  }
1512 
1513  }
1514 
1515  /*
1516  * camera definitions
1517  */
1518  snprintf(path, BUFSIZE, "%s/%s", TRK_SECT_CAM, TRK_LST_CAM);
1519  if (GfParmListSeekFirst(TrackHandle, path) == 0) {
1520  do {
1521  curCam = (tRoadCam*)calloc(1, sizeof(tRoadCam));
1522  if (!curCam) {
1523  GfFatal("ReadTrack3: Memory allocation error");
1524  }
1525  if (*camList == NULL) {
1526  *camList = curCam;
1527  curCam->next = curCam;
1528  } else {
1529  curCam->next = (*camList)->next;
1530  (*camList)->next = curCam;
1531  *camList = curCam;
1532  }
1533  curCam->name = GfParmListGetCurEltName(TrackHandle, path);
1534  segName = GfParmGetCurStr(TrackHandle, path, TRK_ATT_SEGMENT, NULL);
1535  if (segName == 0) {
1536  GfFatal("Bad Track Definition: in Camera %s %s is missing\n", curCam->name, TRK_ATT_SEGMENT);
1537  }
1538  snprintf(path2, BUFSIZE, "%s/%s/%s", TRK_SECT_MAIN, TRK_LST_SEG, segName);
1539  segId = (int)GfParmGetNum(TrackHandle, path2, TRK_ATT_ID, (char*)NULL, 0);
1540  curSeg = theTrack->seg;
1541  for(i=0; i<theTrack->nseg; i++) {
1542  if (curSeg->id == segId) {
1543  break;
1544  }
1545  curSeg = curSeg->next;
1546  }
1547 
1548  trkPos.seg = curSeg;
1549  trkPos.toRight = GfParmGetCurNum(TrackHandle, path, TRK_ATT_TORIGHT, (char*)NULL, 0);
1550  trkPos.toStart = GfParmGetCurNum(TrackHandle, path, TRK_ATT_TOSTART, (char*)NULL, 0);
1551  TrackLocal2Global(&trkPos, &(curCam->pos.x), &(curCam->pos.y));
1552  curCam->pos.z = TrackHeightL(&trkPos) + GfParmGetCurNum(TrackHandle, path, TRK_ATT_HEIGHT, (char*)NULL, 0);
1553 
1554  segName = GfParmGetCurStr(TrackHandle, path, TRK_ATT_CAM_FOV, NULL);
1555  if (segName == 0) {
1556  GfFatal("Bad Track Definition: in Camera %s %s is missing\n", curCam->name, TRK_ATT_CAM_FOV);
1557  }
1558  snprintf(path2, BUFSIZE, "%s/%s/%s", TRK_SECT_MAIN, TRK_LST_SEG, segName);
1559  segId = (int)GfParmGetNum(TrackHandle, path2, TRK_ATT_ID, (char*)NULL, 0);
1560  curSeg = theTrack->seg;
1561  for(i=0; i<theTrack->nseg; i++) {
1562  if (curSeg->id == segId) {
1563  break;
1564  }
1565  curSeg = curSeg->next;
1566  }
1567  segName = GfParmGetCurStr(TrackHandle, path, TRK_ATT_CAM_FOVE, NULL);
1568  if (segName == 0) {
1569  GfFatal("Bad Track Definition: in Camera %s %s is missing\n", curCam->name, TRK_ATT_CAM_FOVE);
1570  }
1571  snprintf(path2, BUFSIZE, "%s/%s/%s", TRK_SECT_MAIN, TRK_LST_SEG, segName);
1572  segId = (int)GfParmGetNum(TrackHandle, path2, TRK_ATT_ID, (char*)NULL, 0);
1573 
1574  do {
1575  curSeg->cam = curCam;
1576  curSeg = curSeg->next;
1577  } while (curSeg->id != segId);
1578  } while (GfParmListSeekNext(TrackHandle, path) == 0);
1579  }
1580 
1581  /* Update the coord to be positives */
1582  theTrack->min.x = 0;
1583  theTrack->min.y = 0;
1584  theTrack->min.z = 0;
1585  theTrack->max.x = xmax - xmin;
1586  theTrack->max.y = ymax - ymin;
1587  theTrack->max.z = zmax - zmin;
1588 
1589  curSeg = theTrack->seg;
1590  for(i=0; i<theTrack->nseg; i++) { /* read the segment data: */
1591  if ((curSeg->lgfromstart + curSeg->length) > (theTrack->length - 50.0)) {
1592  curSeg->raceInfo |= TR_LAST;
1593  } else if (curSeg->lgfromstart < 50.0) {
1594  curSeg->raceInfo |= TR_START;
1595  } else {
1596  curSeg->raceInfo |= TR_NORMAL;
1597  }
1598  normSeg(curSeg);
1599  if (curSeg->lside) {
1600  normSeg(curSeg->lside);
1601  if (curSeg->lside->lside) {
1602  normSeg(curSeg->lside->lside);
1603  }
1604  }
1605  if (curSeg->rside) {
1606  normSeg(curSeg->rside);
1607  if (curSeg->rside->rside) {
1608  normSeg(curSeg->rside->rside);
1609  }
1610  }
1611  curSeg = curSeg->next;
1612  }
1613 
1614 
1615  if (*camList != NULL) {
1616  curCam = *camList;
1617  do {
1618  curCam = curCam->next;
1619  curCam->pos.x -= xmin;
1620  curCam->pos.y -= ymin;
1621  curCam->pos.z -= zmin;
1622  } while (curCam != *camList);
1623  }
1624 }
1625 
1626 
1627 
1628 
static const char * KeyBorderWidth[2]
Definition: track3.cpp:54
int nMaxPits
number max of pits
Definition: track.h:462
#define TRK_ATT_LSW
Definition: track.h:634
tdble kRoughness
Roughtness in m of the surface (wave height)
Definition: track.h:250
#define TRK_ATT_LG
Definition: track.h:147
tdble angle[7]
Definition: track.h:337
#define TR_PITBUILDING
Pit building wall (barrier only)
Definition: track.h:313
tdble Kyl
Definition: track.h:359
#define TRK_ATT_PIT_END
Definition: track.h:623
#define TR_SR
Start-Right corner.
Definition: track.h:333
static tdble ymax
Definition: track3.cpp:30
#define TRK_ATT_RADIUSEND
Definition: track.h:149
#define TRK_ATT_RBS
Definition: track.h:647
tTrackSeg * pitEnd
Pit lane segment.
Definition: track.h:473
#define TRK_ATT_RADIUS
Definition: track.h:148
static const char * barrierMaterial[2]
Definition: track3.cpp:84
static tdble borderWidth[2]
Definition: track3.cpp:75
static void GfFatal(const char *fmt,...)
Definition: tgf.h:339
static void AddSides(tTrackSeg *curSeg, void *TrackHandle, tTrack *theTrack, int curStep, int steps)
Definition: track3.cpp:176
tTrackOwnPit * driversPits
List of pits by driver.
Definition: track.h:475
int type
Geometrical type:
Definition: track.h:280
t3Dd center
Center of the curve.
Definition: track.h:324
#define TRK_ATT_TOSTART
Definition: track.h:207
int * marks
marks array
Definition: track.h:237
static void CreateSegRing3(void *TrackHandle, tTrack *theTrack, tTrackSeg *start, tTrackSeg *end, int ext)
Definition: track3.cpp:772
#define TRK_SECT_CAM
Definition: track.h:203
#define TR_PIT
Car pit.
Definition: track.h:383
#define TR_ER
End_Right corner.
Definition: track.h:335
#define TRK_ATT_RSWE
Definition: track.h:641
#define TRK_ATT_TYPE
Definition: track.h:138
tdble toRight
Distance (+ to left, - to right) relative to the right side of segment.
Definition: track.h:432
static int barrierStyle[2]
Definition: track3.cpp:83
#define TRK_VAL_WALL
Definition: track.h:198
#define TR_SPEEDLIMIT
Segment where the speed is limited.
Definition: track.h:380
#define TR_LSIDE
Left side segment (outer segment)
Definition: track.h:297
#define TRK_VAL_PLAN
Definition: track.h:197
int GfParmListSeekNext(void *handle, const char *path)
Go the the next subsection element in the parameter set handle.
Definition: params.cpp:2184
#define TRK_ATT_LSWE
Definition: track.h:636
static tdble barrierWidth[2]
Definition: track3.cpp:81
#define TRK_ATT_RSW
Definition: track.h:639
#define TR_STR
Straight.
Definition: track.h:287
#define TR_ZS
Rotation angles of the track in rad anti-clockwise: Index in:
Definition: track.h:347
tdble width
Width of the segment (if constant width)
Definition: track.h:316
struct trackSurface * next
Next surface in list.
Definition: track.h:243
#define TRK_ATT_RBW
Definition: track.h:648
static tTrack * theTrack
Definition: track.cpp:32
Location on the track in local coordinates.
Definition: track.h:418
#define TRK_ATT_SPD_LIM
Definition: track.h:182
#define TRK_ATT_ROUGHTWL
Definition: track.h:112
#define TRK_ATT_PROFTGTS
Definition: track.h:164
#define TRK_ATT_RST
Definition: track.h:638
int side
Pits side:
Definition: track.h:464
#define TR_PIT_ON_TRACK_SIDE
The pits are on the track side.
Definition: track.h:460
#define MAX_TMP_INTS
static const char * borderMaterial[2]
Definition: track3.cpp:78
#define TSTX(x)
Definition: track3.cpp:32
unsigned int raceInfo
Type of segment regarding the race: Mask value in:
Definition: track.h:365
#define TRK_VAL_PIT_TYPE_SIDE
Definition: track.h:666
void TrackLocal2Global(tTrkLocPos *p, tdble *X, tdble *Y)
Definition: trackutil.cpp:29
#define TR_NORMAL
Normal segment.
Definition: track.h:376
#define TR_SL
Start-Left corner.
Definition: track.h:332
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:2435
Robots Tools.
#define TRK_ATT_LST
Definition: track.h:633
#define TRK_ATT_PROFSTEPSLEN
Definition: track.h:163
Track structure.
Definition: track.h:502
t3Dd rgtSideNormal
Definition: track.h:360
#define TRK_ATT_ROUGHT
Definition: track.h:111
#define TRK_ATT_FRICTION
Definition: track.h:109
static tdble xmax
Definition: track3.cpp:30
#define TR_CS
Center start angle.
Definition: track.h:353
tdble Kzw
Definition: track.h:357
#define TRK_ATT_ID
Definition: track.h:160
#define TRK_LST_SURF
Definition: track.h:618
static const char * KeyBarrierStyle[2]
Definition: track3.cpp:60
vec2f normal
Definition: track.h:264
static const char * KeyBarrierSurface[2]
Definition: track3.cpp:58
#define TRK_VAL_LFT
Definition: track.h:144
#define TRK_LST_CAM
Definition: track.h:619
#define TRK_ATT_LBAH
Definition: track.h:656
#define TRK_ATT_LBAS
Definition: track.h:654
static const char * KeyBorderSurface[2]
Definition: track3.cpp:53
tdble lgfromstart
Length of beginning of segment from starting line.
Definition: track.h:319
const double PI
PI.
Definition: tgf.h:69
tdble endWidth
Width of the end of the segment.
Definition: track.h:318
#define TRK_VAL_BARRIER
Definition: track.h:217
#define TR_YL
Y Left angle.
Definition: track.h:349
static tdble xmin
Definition: track3.cpp:30
#define TR_SIDE_LFT
Definition: track.h:403
tdble length
Length in meters of the middle of the track.
Definition: track.h:315
tdble startWidth
Width of the beginning of the segment.
Definition: track.h:317
#define TRK_ATT_ENVIND
Definition: track.h:630
#define TRK_VAL_RGT
Definition: track.h:145
#define TRK_VAL_FENCE
Definition: track.h:200
#define TRK_ATT_RBH
Definition: track.h:649
int nPitSeg
actual number of pits
Definition: track.h:463
tdble kRebound
Coefficient of energy restitution.
Definition: track.h:248
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:2311
#define TRK_ATT_PROFTGTEL
Definition: track.h:167
tTrackSeg * pitEntry
Pit lane segment.
Definition: track.h:471
#define TRK_ATT_LSWS
Definition: track.h:635
#define TR_PITENTRY
Segment where the pit lane cross the main track.
Definition: track.h:381
#define TR_FENCE
Fence (no width) (barrier only)
Definition: track.h:312
static const char * KeyBarrierWidth[2]
Definition: track3.cpp:59
static const char * KeySideWidth[2]
Definition: track3.cpp:48
static tTrackSurface * barrierSurface[2]
Definition: track3.cpp:85
static const char * KeySideBankType[2]
Definition: track3.cpp:51
static tdble zmin
Definition: track3.cpp:30
char * GfParmListGetCurEltName(void *handle, const char *path)
Get current subsection name of the parameter set handle during subsection iteration.
Definition: params.cpp:2268
tdble toMiddle
Distance (+ to left, - to right) relative to the middle of segment.
Definition: track.h:433
#define TRK_VAL_PIT_TYPE_NONE
Definition: track.h:665
char * name
Definition: track.h:228
int envIndex
Definition: track.h:361
static tTrackSurface * borderSurface[2]
Definition: track3.cpp:79
tdble length
main track length
Definition: track.h:512
tdble speedLimit
Speed limit between pitStart and pitEnd.
Definition: track.h:470
int type
Type of description:
Definition: track.h:421
static const char * KeySideEndWidth[2]
Definition: track3.cpp:50
#define TRK_ATT_ARC
Definition: track.h:150
static tdble zmax
Definition: track3.cpp:30
tTrkLocPos pos
Center of the pit position.
Definition: track.h:442
#define TR_RBORDER
Right border segment (inner segment)
Definition: track.h:300
int GfParmListSeekFirst(void *handle, const char *path)
Go the the first subsection element in the parameter set handle.
Definition: params.cpp:2148
const char * material
Type of material used.
Definition: track.h:245
#define TRK_ATT_DAMMAGE
Definition: track.h:113
#define TRK_ATT_PROFTGTSL
Definition: track.h:166
#define TR_LPOS_MAIN
Relative to the main segment, mostly used for racing on the main track.
Definition: track.h:427
static const char * sideMaterial[2]
Definition: track3.cpp:69
t3Dd max
Definition: track.h:519
#define TRK_ATT_CAM_FOVE
Definition: track.h:210
tTrackBarrier * barrier[2]
Segment barriers.
Definition: track.h:395
tTrackSurface * surface
Barrier surface.
Definition: track.h:263
const char * name
Segment name.
Definition: track.h:277
static const char * KeyBorderStyle[2]
Definition: track3.cpp:55
#define TRK_ATT_PROFTGTER
Definition: track.h:169
#define TR_LAST
Segment before start line.
Definition: track.h:377
#define TRK_ATT_RBSURF
Definition: track.h:650
#define TRK_ATT_MARKS
Definition: track.h:170
#define TSTZ(z)
Definition: track3.cpp:40
tdble toLeft
Distance (- to left, + to right) relative to left side of segment.
Definition: track.h:434
road camera
Definition: track.h:226
#define TR_LFT
Left curve.
Definition: track.h:286
#define TRK_VAL_STR
Definition: track.h:143
#define TR_PITEXIT
Segment where the pit lane cross the main track.
Definition: track.h:382
#define TRK_ATT_PROFSTEPS
Definition: track.h:162
Scalar length(const Quaternion &q)
Definition: Quaternion.h:193
#define TRK_ATT_PIT_SIDE
Definition: track.h:625
#define TR_RSIDE
Right side segment (outer segment)
Definition: track.h:298
#define TRK_ATT_RBASURF
Definition: track.h:663
tdble radiusr
Radius in meters of the right side of the track (>0)
Definition: track.h:321
static void normSeg(tTrackSeg *curSeg)
Definition: track3.cpp:753
Driver&#39;s pit.
Definition: track.h:440
float tdble
Floating point type used in TORCS.
Definition: tgf.h:48
#define TRK_ATT_SEGMENT
Definition: track.h:205
static tdble borderHeight[2]
Definition: track3.cpp:76
tdble TrackHeightL(tTrkLocPos *p)
Definition: trackutil.cpp:55
tdble radiusl
Radius in meters of the left side of the track (>0)
Definition: track.h:322
static tdble ymin
Definition: track3.cpp:30
#define TRK_ATT_LBSURF
Definition: track.h:646
int nseg
Number of segments.
Definition: track.h:510
Definition: Endpoint.h:36
#define TR_CURB
Curb (border only)
Definition: track.h:310
#define TRK_ATT_RBAW
Definition: track.h:660
#define TR_YR
Y Right angle.
Definition: track.h:350
static void * TrackHandle
Definition: track.cpp:34
struct trackSeg * side[2]
Definition: track.h:407
Barrier.
Definition: track.h:259
The Gaming Framework API.
void ReadTrack3(tTrack *theTrack, void *TrackHandle, tRoadCam **camList, int ext)
Definition: track3.cpp:1279
#define TRK_SECT_SURFACES
Definition: track.h:106
#define TR_PITEND
Car pit End.
Definition: track.h:385
#define TRK_ATT_PROFTGTSR
Definition: track.h:168
#define TRK_ATT_PIT_WIDTH
Definition: track.h:627
#define TRK_VAL_LEVEL
Definition: track.h:223
tdble arc
Arc in rad of the curve (>0)
Definition: track.h:323
#define TR_ZE
Z End angle.
Definition: track.h:348
#define TR_LBORDER
Left border segment (inner segment)
Definition: track.h:299
Surface.
Definition: track.h:242
tTrackSeg * pitExit
Pit lane segment.
Definition: track.h:474
tdble height
Barrier height.
Definition: track.h:262
int style
Barrier style.
Definition: track.h:260
#define TR_XS
X Start angle.
Definition: track.h:351
tdble radius
Radius in meters of the middle of the track (>0)
Definition: track.h:320
static int sideBankType[2]
Definition: track3.cpp:68
#define TRK_ATT_RSSURF
Definition: track.h:642
#define TRK_VAL_CURB
Definition: track.h:199
tdble y
y coordinate
Definition: tgf.h:117
tdble z
z coordinate
Definition: tgf.h:118
t3Dd vertex[4]
Coordinates of the 4 corners of the segment.
Definition: track.h:325
#define TRK_ATT_PIT_TYPE
Definition: track.h:624
int type2
Position type:
Definition: track.h:289
#define TRK_ATT_PIT_EXIT
Definition: track.h:621
#define TRK_ATT_LBS
Definition: track.h:643
#define TRK_ATT_ZE
Definition: track.h:152
static tTrackSurface * sideSurface[2]
Definition: track3.cpp:70
void normalize(void)
Definition: v2_t.h:247
static const char * ValStyle[4]
Definition: track3.cpp:63
tdble kRollRes
Rolling resistance.
Definition: track.h:249
tdble TrackSpline(tdble p0, tdble p1, tdble t0, tdble t1, tdble t)
Definition: trackutil.cpp:79
static int borderStyle[2]
Definition: track3.cpp:77
#define TRK_ATT_PIT_ENTRY
Definition: track.h:620
tdble height
Max height for curbs.
Definition: track.h:363
#define TRK_ATT_ZSR
Definition: track.h:154
tTrackSeg * seg
Track segment.
Definition: track.h:420
#define TRK_VAL_ASPHALT
Definition: track.h:212
#define TRK_ATT_RBAH
Definition: track.h:661
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:2392
tdble width
Width of each pit stop.
Definition: track.h:469
#define TSTY(y)
Definition: track3.cpp:36
tdble RtTrackGetWidth(tTrackSeg *seg, tdble toStart)
Get the track width at the specified point.
Definition: rttrack.cpp:58
#define TR_EL
End-Left corner.
Definition: track.h:334
struct trackSeg * lside
Definition: track.h:406
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:2679
Track segment (tTrackSeg) The segments can be straights (type TR_STR): (the track goes from the right...
Definition: track.h:276
#define TRK_ATT_ZER
Definition: track.h:156
static Vector y[4]
Definition: Convex.cpp:56
tSegExt * ext
Definition: track.h:392
Pits Info Structure.
Definition: track.h:453
t3Dd min
Definition: track.h:518
#define TR_START
Segment after start line.
Definition: track.h:378
#define TR_RGT
Right curve.
Definition: track.h:285
tdble len
Lenght of each pit stop.
Definition: track.h:468
#define TR_XE
X End angle.
Definition: track.h:352
tdble toStart
Distance to start of segment (or arc if turn)
Definition: track.h:431
struct trackSeg * prev
Previous segment.
Definition: track.h:398
#define TRK_ATT_ZS
Definition: track.h:151
tTrackSurface * surface
Segment surface.
Definition: track.h:394
tdble kDammage
Dammages in case of collision.
Definition: track.h:252
tTrackSeg * pitStart
Pit lane segment.
Definition: track.h:472
#define TRK_ATT_HEIGHT
Definition: track.h:208
struct trackSeg * next
Next segment.
Definition: track.h:397
#define TRK_ATT_PIT_LEN
Definition: track.h:626
#define TRK_ATT_RSWS
Definition: track.h:640
#define TRK_ATT_WIDTH
Definition: track.h:45
#define TRK_ATT_TORIGHT
Definition: track.h:206
static tdble GlobalStepLen
Definition: track3.cpp:87
#define TR_MAIN
Main track segment (ie road part)
Definition: track.h:296
static tdble barrierHeight[2]
Definition: track3.cpp:82
#define TRK_VAL_GRASS
Definition: track.h:214
#define TRK_ATT_LBH
Definition: track.h:645
Definition: Endpoint.h:36
tTrackSurface * surfaces
Segment surface list.
Definition: track.h:516
struct RoadCam * next
Definition: track.h:230
t3Dd pos
Definition: track.h:229
#define TRK_ATT_ZEL
Definition: track.h:155
static void InitSides(void *TrackHandle, tTrack *theTrack)
Definition: track3.cpp:128
#define TRK_ATT_BKE
Definition: track.h:159
#define TRK_ATT_REBOUND
Definition: track.h:114
struct trackSeg * rside
Definition: track.h:406
static tdble sideStartWidth[2]
Definition: track3.cpp:67
#define TRK_VAL_SPLINE
Definition: track.h:220
#define TRK_ATT_SURF
Definition: track.h:46
static const char * KeyBorderHeight[2]
Definition: track3.cpp:56
int style
Border and barrier segments style:
Definition: track.h:302
#define TRK_ATT_BKS
Definition: track.h:158
static tTrackSurface * AddTrackSurface(void *TrackHandle, tTrack *theTrack, const char *material)
Definition: track3.cpp:90
#define TRK_LST_SEG
Definition: track.h:629
Track Structure and Track Loader Module Definition.
#define TRK_ATT_LBAW
Definition: track.h:655
static const char * KeySideSurface[2]
Definition: track3.cpp:47
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:2354
static const char * KeyBarrierHeight[2]
Definition: track3.cpp:61
Extended track segment.
Definition: track.h:234
#define TRK_ATT_LSSURF
Definition: track.h:637
tRoadCam * cam
Definition: track.h:396
#define TR_PLAN
Flat (border only)
Definition: track.h:309
tTrackSeg * seg
Main track.
Definition: track.h:515
#define TRK_ATT_ROLLRES
Definition: track.h:110
#define TRK_ATT_GRADE
Definition: track.h:157
#define TRK_ATT_LBASURF
Definition: track.h:658
tTrackPitInfo pits
Pits information.
Definition: track.h:514
#define TRK_ATT_PIT_START
Definition: track.h:622
#define TRK_ATT_LBW
Definition: track.h:644
tdble kFriction
Coefficient of friction.
Definition: track.h:247
tdble Kzl
Definition: track.h:356
tdble kRoughWaveLen
Wave length in m of the surface.
Definition: track.h:251
tdble x
x coordinate
Definition: tgf.h:116
#define TRK_SECT_MAIN
Definition: track.h:136
#define TRK_ATT_PROFTGTE
Definition: track.h:165
static tdble sideEndWidth[2]
Definition: track3.cpp:66
#define TRK_ATT_RBAS
Definition: track.h:659
int nbMarks
turn marks
Definition: track.h:236
int id
Segment number.
Definition: track.h:278
#define TRK_ATT_ZSL
Definition: track.h:153
#define TR_PITSTART
Car pit Star.
Definition: track.h:384
int type
Type of Pit:
Definition: track.h:455
#define TRK_ATT_PROFIL
Definition: track.h:161
#define TRK_ATT_CAM_FOV
Definition: track.h:209
static int envIndex
Definition: track3.cpp:73
static const char * KeySideStartWidth[2]
Definition: track3.cpp:49
tdble width
Barrier width.
Definition: track.h:261
#define TR_WALL
Wall (barrier only)
Definition: track.h:311