TORCS  1.3.9
The Open Racing Car Simulator
grcar.cpp
Go to the documentation of this file.
1 
2 /***************************************************************************
3 
4  file : grcar.cpp
5  created : Mon Aug 21 18:24:02 CEST 2000
6  copyright : (C) 2000 by Eric Espie
7  email : torcs@free.fr
8  version : $Id$
9 
10 ***************************************************************************/
11 
12 /***************************************************************************
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  ***************************************************************************/
20 
21 #include <math.h>
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 #ifdef WIN32
27 #include <windows.h>
28 #endif
29 #include <GL/glut.h>
30 #include <plib/ssg.h>
31 
32 #include <tgfclient.h>
33 #include <track.h>
34 #include <car.h>
35 #include <graphic.h>
36 #include <robottools.h>
37 #include <portability.h>
38 
39 #include "grmain.h"
40 #include "grshadow.h"
41 #include "grskidmarks.h"
42 #include "grsmoke.h"
43 #include "grcar.h"
44 #include "grcam.h"
45 #include "grscene.h"
46 #include "grboard.h"
47 #include "grssgext.h"
48 #include "grutil.h"
49 #include "grcarlight.h"
50 
51 extern ssgEntity *grssgLoadAC3D ( const char *fname, const ssgLoaderOptions* options );
52 extern ssgEntity *grssgCarLoadAC3D ( const char *fname, const ssgLoaderOptions* options,int index );
53 extern double carTrackRatioX;
54 extern double carTrackRatioY;
55 
56 ssgBranch *CarsAnchorTmp = 0;
57 
58 
59 static int grCarIndex;
60 
61 static ssgSimpleState *brakeState = NULL;
62 static ssgSimpleState *commonState = NULL;
63 
65 {
66  // brake
67  if (brakeState == NULL) {
68  brakeState = new ssgSimpleState;
69  brakeState->ref();
70  brakeState->disable(GL_LIGHTING);
71  brakeState->disable(GL_TEXTURE_2D);
72  }
73 
74  if (commonState == NULL) {
75  commonState = new ssgSimpleState;
76  commonState->ref();
77  commonState->disable(GL_LIGHTING);
78  commonState->disable(GL_TEXTURE_2D);
79  commonState->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
80  }
81 }
82 
83 
84 
85 
86 static ssgTransform *initWheel(tCarElt *car, int wheel_index)
87 {
88  int i, j, k;
89  float alpha;
90  sgVec3 vtx;
91  sgVec4 clr;
92  sgVec3 nrm;
93  sgVec2 tex;
94  tdble b_offset = 0.0f;
95  tdble curAngle = 0.0f;
96 
97 #define BRK_BRANCH 16
98 #define BRK_ANGLE (2.0 * M_PI / (tdble)BRK_BRANCH)
99 #define BRK_OFFSET 0.2
100 
101  switch(wheel_index) {
102  case FRNT_RGT:
103  curAngle = -(M_PI / 2.0 + BRK_ANGLE);
104  b_offset = BRK_OFFSET - car->_tireWidth(wheel_index) / 2.0;
105  break;
106  case FRNT_LFT:
107  curAngle = -(M_PI / 2.0 + BRK_ANGLE);
108  b_offset = car->_tireWidth(wheel_index) / 2.0 - BRK_OFFSET;
109  break;
110  case REAR_RGT:
111  curAngle = (M_PI / 2.0 - BRK_ANGLE);
112  b_offset = BRK_OFFSET - car->_tireWidth(wheel_index) / 2.0;
113  break;
114  case REAR_LFT:
115  curAngle = (M_PI / 2.0 - BRK_ANGLE);
116  b_offset = car->_tireWidth(wheel_index) / 2.0 - BRK_OFFSET;
117  break;
118  }
119 
120  /* hub */
121  ssgVertexArray *brk_vtx = new ssgVertexArray(BRK_BRANCH + 1);
122  ssgColourArray *brk_clr = new ssgColourArray(1);
123  ssgNormalArray *brk_nrm = new ssgNormalArray(1);
124  tdble hubRadius;
125 
126  /* center */
127  vtx[0] = vtx[2] = 0.0;
128  vtx[1] = b_offset;
129  brk_vtx->add(vtx);
130 
131  hubRadius = car->_brakeDiskRadius(wheel_index) * 0.6;
132  for (i = 0; i < BRK_BRANCH; i++) {
133  alpha = (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1);
134  vtx[0] = hubRadius * cos(alpha);
135  vtx[1] = b_offset;
136  vtx[2] = hubRadius * sin(alpha);
137  brk_vtx->add(vtx);
138  }
139 
140 
141  clr[0] = clr[1] = clr[2] = 0.0;
142  clr[3] = 1.0;
143  brk_clr->add(clr);
144  nrm[0] = nrm[2] = 0.0;
145 
146  // Make normal point outside to have proper lighting.
147  switch(wheel_index) {
148  case FRNT_RGT:
149  case REAR_RGT:
150  nrm[1] = -1.0;
151  break;
152  case FRNT_LFT:
153  case REAR_LFT:
154  nrm[1] = 1.0;
155  break;
156  }
157 
158  brk_nrm->add(nrm);
159 
160  ssgVtxTable *brk = new ssgVtxTable(GL_TRIANGLE_FAN, brk_vtx, brk_nrm, NULL, brk_clr);
161  brk->setCullFace(0);
162  brk->setState(commonState);
163 
164  ssgTransform *wheel = new ssgTransform;
165  wheel->addKid(brk);
166 
167  /* Brake disk */
168  brk_vtx = new ssgVertexArray(BRK_BRANCH + 4);
169  brk_clr = new ssgColourArray(1);
170  brk_nrm = new ssgNormalArray(1);
171 
172  for (i = 0; i < (BRK_BRANCH / 2 + 2); i++) {
173  alpha = curAngle + (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1);
174  vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha);
175  vtx[1] = b_offset;
176  vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha);
177  brk_vtx->add(vtx);
178  vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha) * 0.6;
179  vtx[1] = b_offset;
180  vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha) * 0.6;
181  brk_vtx->add(vtx);
182  }
183 
184 
185  clr[0] = clr[1] = clr[2] = 0.1;
186  clr[3] = 1.0;
187  brk_clr->add(clr);
188  //nrm[0] = nrm[2] = 0.0;
189  //nrm[1] = 1.0;
190  brk_nrm->add(nrm);
191 
192  brk = new ssgVtxTable(GL_TRIANGLE_STRIP, brk_vtx, brk_nrm, NULL, brk_clr);
193  brk->setCullFace(0);
194  brk->setState(brakeState);
195  grCarInfo[grCarIndex].brkColor[wheel_index] = brk_clr;
196 
197  wheel->addKid(brk);
198 
199  /* Brake caliper */
200  brk_vtx = new ssgVertexArray(BRK_BRANCH - 4);
201  brk_clr = new ssgColourArray(1);
202  brk_nrm = new ssgNormalArray(1);
203 
204  for (i = 0; i < (BRK_BRANCH / 2 - 2); i++) {
205  alpha = - curAngle + (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1);
206  vtx[0] = (car->_brakeDiskRadius(wheel_index) + 0.02) * cos(alpha);
207  vtx[1] = b_offset;
208  vtx[2] = (car->_brakeDiskRadius(wheel_index) + 0.02) * sin(alpha);
209  brk_vtx->add(vtx);
210  vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha) * 0.6;
211  vtx[1] = b_offset;
212  vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha) * 0.6;
213  brk_vtx->add(vtx);
214  }
215 
216 
217  clr[0] = 0.2;
218  clr[1] = 0.2;
219  clr[2] = 0.2;
220  clr[3] = 1.0;
221  brk_clr->add(clr);
222  //nrm[0] = nrm[2] = 0.0;
223  //nrm[1] = 1.0;
224  brk_nrm->add(nrm);
225 
226  brk = new ssgVtxTable(GL_TRIANGLE_STRIP, brk_vtx, brk_nrm, NULL, brk_clr);
227  brk->setCullFace(0);
228  brk->setState(commonState);
229 
230  wheel->addKid(brk);
231 
232  DBG_SET_NAME(wheel, "Wheel", grCarIndex, wheel_index);
233 
234  grCarInfo[grCarIndex].wheelPos[wheel_index] = wheel;
235 
236  /* wheels */
237  ssgTransform *whrotation = new ssgTransform;
238  grCarInfo[grCarIndex].wheelRot[wheel_index] = whrotation;
239  wheel->addKid(whrotation);
240  ssgSelector *whselector = new ssgSelector;
241  whrotation->addKid(whselector);
242  grCarInfo[grCarIndex].wheelselector[wheel_index] = whselector;
243 
244  float wheelRadius = car->_rimRadius(wheel_index) + car->_tireHeight(wheel_index);
245 
246  // Create wheels for 4 speeds (stillstanding - fast --> motion blur, look at the texture).
247  for (j = 0; j < 4; j++) {
248  ssgBranch *whl_branch = new ssgBranch;
249  ssgEntity *whl3d = 0;
250 
251  // load speed-dependant 3D wheels if available and if detailed wheels are desired.
252  // wheel data files are located in the wheels directory. first set directory.
253  if (grUseDetailedWheels == DETAILED) {
254  const int bufsize = 1024;
255  char buf[bufsize];
256  const char* wheel_dir = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_WHEEL_3D_DIR, 0);
257  if (wheel_dir != 0) {
258  snprintf(buf, bufsize, "wheels/%s", wheel_dir);
259  ssgModelPath(buf);
260  ssgTexturePath(buf);
261  }
262 
263  // set basename for wheel file 0..3 gets appended
264  const char* wheel_obj = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_WHEEL_3D, 0);
265  if (wheel_obj != 0 && wheel_dir != 0) {
266  snprintf(buf, bufsize, "%s%d.acc", wheel_obj, j);
267  whl3d = grssgCarLoadAC3D(buf, NULL, car->index);
268  }
269  }
270 
271  // if we have a 3D wheel, use it. otherwise use normal generated wheel...
272  if (whl3d) {
273  // Adapt size of the wheel
274  ssgTransform *whl_size = new ssgTransform;
275  sgMat4 wheelsz;
276 
277  sgSetVec4(wheelsz[0], wheelRadius * 2, SG_ZERO, SG_ZERO, SG_ZERO) ;
278  sgSetVec4(wheelsz[1], SG_ZERO, car->_tireWidth(wheel_index), SG_ZERO, SG_ZERO) ;
279  sgSetVec4(wheelsz[2], SG_ZERO, SG_ZERO, wheelRadius * 2, SG_ZERO) ;
280  sgSetVec4(wheelsz[3], SG_ZERO, SG_ZERO, SG_ZERO, SG_ONE) ;
281 
282  whl_size->setTransform(wheelsz);
283 
284  whl_size->addKid(whl3d);
285  whl3d = whl_size;
286 
287  if (wheel_index == FRNT_RGT || wheel_index == REAR_RGT) {
288  // flip wheel around so it faces the right way
289  ssgTransform *whl_mesh_transform = new ssgTransform;
290  sgCoord wheelpos;
291  sgSetCoord(&wheelpos, 0, 0, 0, 180, 0, 0);
292  whl_mesh_transform->setTransform( &wheelpos);
293  whl_mesh_transform->addKid(whl3d);
294  whl_branch->addKid(whl_mesh_transform);
295  } else {
296  whl_branch->addKid(whl3d);
297  }
298  } else {
299  static sgVec2 toffset[4] = { {0.0, 0.5}, {0.5, 0.5}, {0.0, 0.0}, {0.5, 0.0} };
300  // TORCS's standard generated wheel
301  const int WHL_BRANCH = 16;
302 
303  /* Tread */
304  {
305  ssgVertexArray *whl_vtx = new ssgVertexArray(2 * WHL_BRANCH);
306  ssgColourArray *whl_clr = new ssgColourArray(2 * WHL_BRANCH);
307  ssgNormalArray *whl_nrm = new ssgNormalArray(1);
308 
309  whl_nrm->add(nrm);
310  clr[3] = 1.0;
311  for (i = 0; i < WHL_BRANCH; i++) {
312  alpha = (float)i * 2.0 * M_PI / (float)(WHL_BRANCH - 1);
313  vtx[0] = wheelRadius * cos(alpha);
314  vtx[2] = wheelRadius * sin(alpha);
315  vtx[1] = - car->_tireWidth(wheel_index) / 2.0;
316  whl_vtx->add(vtx);
317  vtx[1] = car->_tireWidth(wheel_index) / 2.0;
318  whl_vtx->add(vtx);
319  if (i % 2) {
320  clr[0] = clr[1] = clr[2] = 0.15;
321  } else {
322  clr[0] = clr[1] = clr[2] = 0.0;
323  }
324  whl_clr->add(clr);
325  whl_clr->add(clr);
326  }
327  ssgVtxTable *whl = new ssgVtxTable(GL_TRIANGLE_STRIP, whl_vtx, whl_nrm, NULL, whl_clr);
328  whl->setState(commonState);
329  whl->setCullFace(0);
330 
331  // stripify wheel, should improve performance
332  ssgStripify(whl);
333 
334  whl_branch->addKid(whl);
335  }
336 
337  /* Rim */
338  switch(wheel_index) {
339  case FRNT_RGT:
340  case REAR_RGT:
341  b_offset = -0.05;
342  break;
343  case FRNT_LFT:
344  case REAR_LFT:
345  b_offset = 0.05;
346  break;
347  }
348 
349  // Make inside rim very dark and take care of normals.
350  float colorfactor[2];
351  float norm_orig = nrm[1];
352 
353  if (nrm[1] > 0.0f) {
354  colorfactor[0] = 0.3f;
355  colorfactor[1] = 1.0f;
356  nrm[1] *= -1.0f;
357  } else {
358  colorfactor[0] = 1.0f;
359  colorfactor[1] = 0.3f;
360  }
361 
362  for (k = 0; k < 2; k++) {
363  ssgVertexArray *whl_vtx = new ssgVertexArray(WHL_BRANCH + 1);
364  ssgTexCoordArray *whl_tex = new ssgTexCoordArray(WHL_BRANCH + 1);
365  ssgColourArray *whl_clr = new ssgColourArray(1);
366  ssgNormalArray *whl_nrm = new ssgNormalArray(1);
367 
368  clr[0] = 0.8f*colorfactor[k];
369  clr[1] = 0.8f*colorfactor[k];
370  clr[2] = 0.8f*colorfactor[k];
371  clr[3] = 1.0f;
372 
373  whl_clr->add(clr);
374  whl_nrm->add(nrm);
375  vtx[0] = vtx[2] = 0.0;
376  vtx[1] = (float)(2 * k - 1) * car->_tireWidth(wheel_index) / 2.0 - b_offset;
377  whl_vtx->add(vtx);
378  tex[0] = 0.25 + toffset[j][0];
379  tex[1] = 0.25 + toffset[j][1];
380  whl_tex->add(tex);
381  vtx[1] = (float)(2 * k - 1) * car->_tireWidth(wheel_index) / 2.0;
382  for (i = 0; i < WHL_BRANCH; i++) {
383  alpha = (float)i * 2.0 * M_PI / (float)(WHL_BRANCH - 1);
384  vtx[0] = wheelRadius * cos(alpha);
385  vtx[2] = wheelRadius * sin(alpha);
386  whl_vtx->add(vtx);
387  tex[0] = 0.25 + 0.25 * cos(alpha) + toffset[j][0];
388  tex[1] = 0.25 + 0.25 * sin(alpha) + toffset[j][1];
389  whl_tex->add(tex);
390  }
391  ssgVtxTable *whl = new ssgVtxTable(GL_TRIANGLE_FAN, whl_vtx, whl_nrm, whl_tex, whl_clr);
392  whl->setState(grCarInfo[grCarIndex].wheelTexture);
393  whl->setCullFace(0);
394 
395  // stripify rim, should improve performance
396  ssgStripify(whl);
397 
398  whl_branch->addKid(whl);
399 
400  // Swap normal for "inside" rim face.
401  nrm[1] *= -1.0;
402  }
403 
404  nrm[1] = norm_orig;
405  }
406 
407  whselector->addKid(whl_branch);
408  }
409 
410  return wheel;
411 }
412 
413 
414 static const int GR_SHADOW_POINTS = 6;
415 
417 {
418  const int BUFSIZE = 256;
419  char buf[BUFSIZE];
420  const char *shdTexName;
421  int i;
422  float x;
423  sgVec3 vtx;
424  sgVec4 clr;
425  sgVec3 nrm;
426  sgVec2 tex;
427  ssgVertexArray *shd_vtx = new ssgVertexArray(GR_SHADOW_POINTS+1);
428  ssgColourArray *shd_clr = new ssgColourArray(1);
429  ssgNormalArray *shd_nrm = new ssgNormalArray(1);
430  ssgTexCoordArray *shd_tex = new ssgTexCoordArray(GR_SHADOW_POINTS+1);
431 
432  snprintf(buf, BUFSIZE, "cars/%s;", car->_carName);
433  grFilePath = buf;
434 
435  shdTexName = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_SHADOW_TEXTURE, "");
436 
437  grCarInfo[car->index].shadowAnchor = new ssgBranch();
438 
439  clr[0] = clr[1] = clr[2] = 1.0;
440  clr[3] = 1.0;
441  shd_clr->add(clr);
442  nrm[0] = nrm[1] = 0.0;
443  nrm[2] = 1.0;
444  shd_nrm->add(nrm);
445 
446  /* vertices */
447 #define MULT 1.1
448  vtx[2] = 0.0;
449  for (i = 0, x = car->_dimension_x * MULT / 2.0; i < GR_SHADOW_POINTS / 2; i++, x -= car->_dimension_x * MULT / (float)(GR_SHADOW_POINTS - 2) * 2.0) {
450  vtx[0] = x;
451  tex[0] = 1.0 - (float)i / (float)((GR_SHADOW_POINTS - 2) / 2.0);
452 
453  vtx[1] = -car->_dimension_y * MULT / 2.0;
454  shd_vtx->add(vtx);
455  tex[1] = 0.0;
456  shd_tex->add(tex);
457 
458  vtx[1] = car->_dimension_y * MULT / 2.0;
459  shd_vtx->add(vtx);
460  tex[1] = 1.0;
461  shd_tex->add(tex);
462 
463  };
464 
465  grCarInfo[car->index].shadowBase = new ssgVtxTableShadow(GL_TRIANGLE_STRIP, shd_vtx, shd_nrm, shd_tex, shd_clr);
466  grMipMap = 0;
467  grCarInfo[car->index].shadowBase->setState(grSsgLoadTexState(shdTexName));
468  grCarInfo[car->index].shadowCurr = (ssgVtxTableShadow *)grCarInfo[car->index].shadowBase->clone(SSG_CLONE_GEOMETRY);
469  grCarInfo[car->index].shadowAnchor->addKid(grCarInfo[car->index].shadowCurr);
470  ShadowAnchor->addKid(grCarInfo[car->index].shadowAnchor);
471  grCarInfo[car->index].shadowBase->ref();
472 }
473 
474 
475 
476 
477 void grPropagateDamage (ssgEntity* l, sgVec3 poc, sgVec3 force, int cnt)
478 {
479  //showEntityType (l);
480  if (l->isAKindOf (ssgTypeBranch())) {
481 
482  ssgBranch* br = (ssgBranch*) l;
483 
484  for (int i = 0 ; i < br -> getNumKids () ; i++ ) {
485  ssgEntity* ln = br->getKid (i);
486  grPropagateDamage(ln, poc, force, cnt+1);
487  }
488  }
489 
490  if (l->isAKindOf (ssgTypeVtxTable())) {
491  sgVec3* v;
492  int Nv;
493  ssgVtxTable* vt = (ssgVtxTable*) l;
494  Nv = vt->getNumVertices();
495  vt->getVertexList ((void**) &v);
496  tdble sigma = sgLengthVec3 (force);
497  tdble invSigma = 5.0;
498 
499  for (int i=0; i<Nv; i++) {
500  tdble r = sgDistanceSquaredVec3 (poc, v[i]);
501  tdble f = exp(-r*invSigma)*5.0;
502  v[i][0] += force[0]*f;
503  v[i][1] += force[1]*f;
504  // use sigma as a random number generator (!)
505  v[i][2] += (force[2]+0.02*sin(2.0*r + 10.0*sigma))*f;
506  //printf ("(%f %f %f)\n", v[i][0], v[i][1], v[i][2]);
507  }
508  }
509 }
510 
511 
512 void
514 {
515  const int BUFSIZE=4096;
516  char buf[BUFSIZE];
517  int index;
518  int selIndex;
519  ssgEntity *carEntity;
520  ssgSelector *LODSel;
521  ssgTransform *wheel[4];
522  int nranges;
523  int i, j;
524  void *handle;
525  const char *param;
526  int lg;
527  const int PATHSIZE=256;
528  char path[PATHSIZE];
530  sgVec3 lightPos;
531  int lightNum;
532  const char *lightType;
533  int lightTypeNum;
534 
535 
536  if (!CarsAnchorTmp) {
537  CarsAnchorTmp = new ssgBranch();
538  }
539 
540  grInitBoardCar(car);
541 
542  TRACE_GL("loadcar: start");
543 
544  ssgSetCurrentOptions ( &options ) ;
545 
546  grCarIndex = index = car->index; /* current car's index */
547  handle = car->_carHandle;
548 
549  /* Load visual attributes */
550  car->_exhaustNb = GfParmGetEltNb(handle, SECT_EXHAUST);
551  car->_exhaustNb = MIN(car->_exhaustNb, 2);
552  car->_exhaustPower = GfParmGetNum(handle, SECT_EXHAUST, PRM_POWER, NULL, 1.0);
553  for (i = 0; i < car->_exhaustNb; i++) {
554  snprintf(path, PATHSIZE, "%s/%d", SECT_EXHAUST, i + 1);
555  car->_exhaustPos[i].x = GfParmGetNum(handle, path, PRM_XPOS, NULL, -car->_dimension_x / 2.0);
556  car->_exhaustPos[i].y = -GfParmGetNum(handle, path, PRM_YPOS, NULL, car->_dimension_y / 2.0);
557  car->_exhaustPos[i].z = GfParmGetNum(handle, path, PRM_ZPOS, NULL, 0.1);
558  }
559 
560  snprintf(path, PATHSIZE, "%s/%s", SECT_GROBJECTS, SECT_LIGHT);
561  lightNum = GfParmGetEltNb(handle, path);
562  for (i = 0; i < lightNum; i++) {
563  snprintf(path, PATHSIZE, "%s/%s/%d", SECT_GROBJECTS, SECT_LIGHT, i + 1);
564  lightPos[0] = GfParmGetNum(handle, path, PRM_XPOS, NULL, 0);
565  lightPos[1] = GfParmGetNum(handle, path, PRM_YPOS, NULL, 0);
566  lightPos[2] = GfParmGetNum(handle, path, PRM_ZPOS, NULL, 0);
567  lightType = GfParmGetStr(handle, path, PRM_TYPE, "");
568  lightTypeNum = LIGHT_NO_TYPE;
569  if (!strcmp(lightType, VAL_LIGHT_HEAD1)) {
570  lightTypeNum = LIGHT_TYPE_FRONT;
571  } else if (!strcmp(lightType, VAL_LIGHT_HEAD2)) {
572  lightTypeNum = LIGHT_TYPE_FRONT2;
573  } else if (!strcmp(lightType, VAL_LIGHT_BRAKE)) {
574  lightTypeNum = LIGHT_TYPE_BRAKE;
575  } else if (!strcmp(lightType, VAL_LIGHT_BRAKE2)) {
576  lightTypeNum = LIGHT_TYPE_BRAKE2;
577  } else if (!strcmp(lightType, VAL_LIGHT_REAR)) {
578  lightTypeNum = LIGHT_TYPE_REAR;
579  }
580  grAddCarlight(car, lightTypeNum, lightPos, GfParmGetNum(handle, path, PRM_SIZE, NULL, 0.2));
581  }
582 
583  grLinkCarlights(car);
584 
585 
586  GfOut("[gr] Init(%d) car %s for driver %s index %d\n", index, car->_carName, car->_modName, car->_driverIndex);
587 
588  grFilePath = (char*)malloc(BUFSIZE);
589  lg = 0;
590  lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carName);
591  lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%d;", car->_modName, car->_driverIndex);
592  lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%s;", car->_modName, car->_carName);
593  lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s;", car->_modName);
594  lg += snprintf(grFilePath + lg, BUFSIZE - lg, "cars/%s", car->_carName);
595 
597  if (strlen(param) != 0) {
598  grGammaValue = 1.8;
599  grMipMap = 0;
601  grCarInfo[index].wheelTexture->ref();
602  }
603 
604  grCarInfo[index].envSelector = (ssgStateSelector*)grEnvSelector->clone();
605  grCarInfo[index].envSelector->ref();
606 
607  /* the base transformation of the car (rotation + translation) */
608  grCarInfo[index].carTransform = new ssgTransform;
609  DBG_SET_NAME(grCarInfo[index].carTransform, car->_modName, index, -1);
610 
611  /* Level of details */
612  grCarInfo[index].LODSelector = LODSel = new ssgSelector;
613  grCarInfo[index].carTransform->addKid(LODSel);
614  snprintf(path, PATHSIZE, "%s/%s", SECT_GROBJECTS, LST_RANGES);
615  nranges = GfParmGetEltNb(handle, path) + 1;
616  if (nranges < 2) {
617  GfOut("Error not enough levels of detail\n");
618  FREEZ(grFilePath);
619  return;
620  }
621 
622  /* First LOD */
623  ssgBranch *carBody = new ssgBranch;
624  DBG_SET_NAME(carBody, "LOD", index, 0);
625  LODSel->addKid(carBody);
626 
627  /* The car's model is under cars/<model> */
628  snprintf(buf, BUFSIZE, "cars/%s", car->_carName);
629  ssgModelPath(buf);
630  snprintf(buf, BUFSIZE, "drivers/%s/%d;drivers/%s;cars/%s", car->_modName, car->_driverIndex, car->_modName, car->_carName);
631  ssgTexturePath(buf);
632  grTexturePath = strdup(buf);
633 
634  /* loading raw car level 0*/
635  selIndex = 0; /* current selector index */
636  snprintf(buf, BUFSIZE, "%s.ac", car->_carName); /* default car name */
637  snprintf(path, PATHSIZE, "%s/%s/1", SECT_GROBJECTS, LST_RANGES);
638  param = GfParmGetStr(handle, path, PRM_CAR, buf);
639  grCarInfo[index].LODThreshold[selIndex] = GfParmGetNum(handle, path, PRM_THRESHOLD, NULL, 0.0);
640  /*carEntity = ssgLoad(param);*/
641  carEntity = grssgCarLoadAC3D(param, NULL, index);
642  grCarInfo[index].carEntity = carEntity;
643 
644  /* Set a selector on the driver */
645  char* stmp = strdup("DRIVER");
646  ssgBranch *b = (ssgBranch *)carEntity->getByName(stmp);
647  free(stmp);
648 
649  grCarInfo[index].driverSelector = new ssgSelector;
650  if (b) {
651  ssgBranch *bp = b->getParent(0);
652  bp->addKid(grCarInfo[index].driverSelector);
653  grCarInfo[index].driverSelector->addKid(b);
654  bp->removeKid(b);
655  grCarInfo[index].driverSelector->select(1);
656  grCarInfo[index].driverSelectorinsg = true;
657  } else {
658  grCarInfo[index].driverSelectorinsg = false;
659  }
660 
661 
662  DBG_SET_NAME(carEntity, "Body", index, -1);
663  carBody->addKid(carEntity);
664  /* add wheels */
665  for (i = 0; i < 4; i++){
666  wheel[i] = initWheel(car, i);
667  carBody->addKid(wheel[i]);
668  }
669  grCarInfo[index].LODSelectMask[0] = 1 << selIndex; /* car mask */
670  selIndex++;
671  grCarInfo[index].sx=carTrackRatioX;
672  grCarInfo[index].sy=carTrackRatioY;
673 
674  /* Other LODs */
675  for (i = 2; i < nranges; i++) {
676  carBody = new ssgBranch;
677  snprintf(buf, BUFSIZE, "%s/%s/%d", SECT_GROBJECTS, LST_RANGES, i);
678  param = GfParmGetStr(handle, buf, PRM_CAR, "");
679  grCarInfo[index].LODThreshold[selIndex] = GfParmGetNum(handle, buf, PRM_THRESHOLD, NULL, 0.0);
680  /* carEntity = ssgLoad(param); */
681  carEntity = grssgCarLoadAC3D(param, NULL, index);;
682  DBG_SET_NAME(carEntity, "LOD", index, i-1);
683  carBody->addKid(carEntity);
684  if (!strcmp(GfParmGetStr(handle, buf, PRM_WHEELSON, "no"), "yes")) {
685  /* add wheels */
686  for (j = 0; j < 4; j++){
687  carBody->addKid(wheel[j]);
688  }
689  }
690  LODSel->addKid(carBody);
691  grCarInfo[index].LODSelectMask[i-1] = 1 << selIndex; /* car mask */
692  selIndex++;
693  }
694  /* default range selection */
695  LODSel->select(grCarInfo[index].LODSelectMask[0]);
696 
697  CarsAnchor->addKid(grCarInfo[index].carTransform);
698 
699  //grCarInfo[index].carTransform->print(stdout, "-", 1);
700 
702  FREEZ(grFilePath);
703  options.endLoad();
704 
705  TRACE_GL("loadcar: end");
706 }
707 
708 static void
709 grDrawShadow(tCarElt *car, int visible)
710 {
711  int i;
712  ssgVtxTableShadow *shadow;
713  sgVec3 *vtx;
714 
715  if (grCarInfo[car->index].shadowAnchor->getNumKids() != 0) {
716  grCarInfo[car->index].shadowAnchor->removeKid(grCarInfo[car->index].shadowCurr);
717  }
718 
719  if (visible) {
720  shadow = (ssgVtxTableShadow *)grCarInfo[car->index].shadowBase->clone(SSG_CLONE_GEOMETRY);
721  /* shadow->setState(shadowState); */
722  shadow->setCullFace(TRUE);
723  shadow->getVertexList((void**)&vtx);
724 
725  shadow->transform(grCarInfo[car->index].carPos);
726 
727  for (i = 0; i < GR_SHADOW_POINTS; i++) {
728  vtx[i][2] = RtTrackHeightG(car->_trkPos.seg, vtx[i][0], vtx[i][1]) + 0.00;
729  }
730 
731  grCarInfo[car->index].shadowCurr = shadow;
732  grCarInfo[car->index].shadowAnchor->addKid(shadow);
733  }
734 }
735 
736 
737 
738 
740 {
741  tTrackSeg *seg;
742  tdble lg;
743 
744  seg = car->_trkPos.seg;
745  lg = seg->lgfromstart;
746 
747  switch (seg->type) {
748  case TR_STR:
749  lg += car->_trkPos.toStart;
750  break;
751  default:
752  lg += car->_trkPos.toStart * seg->radius;
753  break;
754  }
755  return lg;
756 }
757 
758 
759 
760 
761 void grDrawCar(tCarElt *car, tCarElt *curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera *curCam)
762 {
763  sgCoord wheelpos;
764  int index, i, j;
765  static float maxVel[3] = { 20.0, 40.0, 70.0 };
766  float lod;
767 
768  TRACE_GL("cggrDrawCar: start");
769 
770  index = car->index;
771  if (car->priv.collision_state.collision_count > 0) {
772  tCollisionState* collision_state = &car->priv.collision_state;
773  grPropagateDamage (grCarInfo[index].carEntity, collision_state->pos, collision_state->force, 0);
774  collision_state->collision_count = 0;
775  }
776 
778  grCarInfo[index].envAngle=RAD2DEG(car->_yaw);
779 
780  if ((car == curCar) && (dispCarFlag != 1)) {
781  grCarInfo[index].LODSelector->select(0);
782  } else {
783  lod = curCam->getLODFactor(car->_pos_X, car->_pos_Y, car->_pos_Z);
784  i = 0;
785  while (lod < grCarInfo[index].LODThreshold[i] * grLodFactorValue) {
786  i++;
787  }
788  if ((car->_state & RM_CAR_STATE_DNF) && (grCarInfo[index].LODThreshold[i] > 0.0)) {
789  i++;
790  }
791  grCarInfo[index].LODSelector->select(grCarInfo[index].LODSelectMask[i]);
792  if (dispDrvFlag) {
793  grCarInfo[index].driverSelector->select(1);
794  } else {
795  grCarInfo[index].driverSelector->select(0);
796  }
797  }
798 
799  sgCopyMat4(grCarInfo[index].carPos, car->_posMat);
800  grCarInfo[index].px=car->_pos_X;
801  grCarInfo[index].py=car->_pos_Y;
802 
803  grCarInfo[index].carTransform->setTransform(grCarInfo[index].carPos);
804 
805  if ((car == curCar) && (dispCarFlag != 1)) {
806  grDrawShadow(car, 0);
807  } else {
808  grDrawShadow(car, 1);
809  }
810 
811  grUpdateSkidmarks(car, curTime);
812  grDrawSkidmarks(car);
813  grAddSmoke(car, curTime);
814 
815  if ((car == curCar) && (dispCarFlag != 1)) {
816  grUpdateCarlight(car, curCam, 0);
817  } else {
818  grUpdateCarlight(car, curCam, 1);
819  }
820 
821  /* Env mapping selection by the position on the track */
822  grCarInfo[index].envSelector->selectStep(car->_trkPos.seg->envIndex);
823 
824  /* wheels */
825  for (i = 0; i < 4; i++) {
826  float *clr;
827 
828  sgSetCoord(&wheelpos, car->priv.wheel[i].relPos.x, car->priv.wheel[i].relPos.y, car->priv.wheel[i].relPos.z,
829  RAD2DEG(car->priv.wheel[i].relPos.az), RAD2DEG(car->priv.wheel[i].relPos.ax), 0);
830  grCarInfo[index].wheelPos[i]->setTransform(&wheelpos);
831  sgSetCoord(&wheelpos, 0, 0, 0, 0, 0, RAD2DEG(car->priv.wheel[i].relPos.ay));
832  grCarInfo[index].wheelRot[i]->setTransform(&wheelpos);
833  for (j = 0; j < 3; j++) {
834  if (fabs(car->_wheelSpinVel(i)) < maxVel[j])
835  break;
836  }
837  grCarInfo[index].wheelselector[i]->select(1<<j);
838  clr = grCarInfo[index].brkColor[i]->get(0);
839  clr[0] = 0.1 + car->_brakeTemp(i) * 1.5;
840  clr[1] = 0.1 + car->_brakeTemp(i) * 0.3;
841  clr[2] = 0.1 - car->_brakeTemp(i) * 0.3;
842  }
843 
844  /* push the car at the end of the display order */
845  CarsAnchorTmp->addKid(grCarInfo[index].carTransform);
846  CarsAnchor->removeKid(grCarInfo[index].carTransform);
847  CarsAnchor->addKid(grCarInfo[index].carTransform);
848  CarsAnchorTmp->removeKid(grCarInfo[index].carTransform);
849 
850  TRACE_GL("cggrDrawCar: end");
851 }
852 
#define REAR_LFT
rear left
Definition: car.h:41
ssgBranch * shadowAnchor
Definition: grcar.h:59
#define VAL_LIGHT_BRAKE2
Definition: car.h:677
sgVec3 force
Definition: car.h:281
#define PRM_WHEELSON
Definition: car.h:611
ssgEntity * grssgLoadAC3D(const char *fname, const ssgLoaderOptions *options)
Definition: grloadac.cpp:1149
float getLODFactor(float x, float y, float z)
Definition: grcam.cpp:144
#define RM_CAR_STATE_DNF
Car did not finish.
Definition: car.h:212
#define FRNT_LFT
front left
Definition: car.h:39
#define FRNT_RGT
front right
Definition: car.h:38
ssgStateSelector * envSelector
Definition: grcar.h:51
#define LIGHT_NO_TYPE
Definition: grcarlight.h:95
void grUpdateCarlight(tCarElt *car, class cGrPerspCamera *curCam, int disp)
Definition: grcarlight.cpp:409
static int grCarIndex
Definition: grcar.cpp:59
void grAddSmoke(tCarElt *car, double t)
Definition: grsmoke.cpp:221
int type
Geometrical type:
Definition: track.h:280
void grInitShadow(tCarElt *car)
Definition: grcar.cpp:416
static ssgLoaderOptionsEx options
Definition: grscene.cpp:165
tCollisionState collision_state
collision state
Definition: car.h:313
ssgTransform * carTransform
Definition: grcar.h:44
ssgColourArray * brkColor[4]
Definition: grcar.h:54
#define PRM_TYPE
Definition: car.h:527
tdble y
y coordinate
Definition: tgf.h:132
tdble RtTrackHeightG(tTrackSeg *seg, tdble X, tdble Y)
Returns the absolute height in meters of the road at the Global position (segment, X, Y)
Definition: rttrack.cpp:443
#define PRM_WHEEL_TEXTURE
Definition: car.h:614
#define BRK_OFFSET
#define TRACE_GL(msg)
Definition: grutil.h:28
static ssgTransform * initWheel(tCarElt *car, int wheel_index)
Definition: grcar.cpp:86
#define TR_STR
Straight.
Definition: track.h:287
#define FREEZ(x)
Definition: tgf.h:60
#define SECT_GROBJECTS
Definition: car.h:506
double carTrackRatioY
Definition: grloadac.cpp:50
#define PRM_CAR
Definition: car.h:610
Car structure (tCarElt).
Definition: car.h:455
int collision_count
Definition: car.h:279
Robots Tools.
char * grFilePath
Definition: grutil.cpp:42
EWheelDetail grUseDetailedWheels
Definition: grmain.cpp:71
virtual void transform(const sgMat4 m)
Definition: grshadow.h:23
#define REAR_RGT
rear right
Definition: car.h:40
#define PRM_POWER
Definition: car.h:594
double carTrackRatioX
Definition: grloadac.cpp:49
tdble lgfromstart
Length of beginning of segment from starting line.
Definition: track.h:319
ssgState * wheelTexture
Definition: grcar.h:56
static void grDrawShadow(tCarElt *car, int visible)
Definition: grcar.cpp:709
#define LST_RANGES
Definition: car.h:608
tdble ay
angle along y axis
Definition: tgf.h:135
#define PRM_THRESHOLD
Definition: car.h:609
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 RAD2DEG(x)
Radian to degree conversion.
Definition: tgf.h:75
The Gaming Framework API (client part).
ssgSelector * wheelselector[4]
Definition: grcar.h:55
static const int GR_SHADOW_POINTS
Definition: grcar.cpp:414
ssgEntity * grssgCarLoadAC3D(const char *fname, const ssgLoaderOptions *options, int index)
Definition: grloadac.cpp:1115
char * grTexturePath
Definition: grutil.cpp:43
void grInitCar(tCarElt *car)
Definition: grcar.cpp:513
void grInitCommonState(void)
Definition: grcar.cpp:64
#define LIGHT_TYPE_FRONT2
Definition: grcarlight.h:89
tPosd relPos
position relative to GC
Definition: car.h:250
ssgSelector * driverSelector
Definition: grcar.h:49
virtual ssgBase * clone(int clone_flags=0)
Definition: grshadow.cpp:32
#define LIGHT_TYPE_BRAKE2
Definition: grcarlight.h:93
tdble grLodFactorValue
Definition: grmain.cpp:70
float tdble
Floating point type used in TORCS.
Definition: tgf.h:48
#define GfOut
Definition: tgf.h:373
#define DBG_SET_NAME(base, name, index, subindex)
Definition: grutil.h:34
#define PRM_ZPOS
Definition: car.h:566
tdble x
x coordinate
Definition: tgf.h:131
ssgBranch * CarsAnchor
Definition: grscene.cpp:72
sgVec3 pos
Definition: car.h:280
tWheelState wheel[4]
Definition: car.h:290
#define LIGHT_TYPE_BRAKE
Definition: grcarlight.h:92
#define BRK_ANGLE
ssgVtxTableShadow * shadowBase
Definition: grcar.h:57
void grUpdateSkidmarks(tCarElt *car, double t)
update if necessary the skidmarks for a car
Graphic Module Interface Definition.
bool driverSelectorinsg
Definition: grcar.h:50
void grAddCarlight(tCarElt *car, int type, sgVec3 pos, double size)
Definition: grcarlight.cpp:358
tdble radius
Radius in meters of the middle of the track (>0)
Definition: track.h:320
ssgVtxTableShadow * shadowCurr
Definition: grcar.h:58
tPrivCar priv
private
Definition: car.h:461
#define LIGHT_TYPE_FRONT
Definition: grcarlight.h:88
Parameter header structure, a parameter can either carry a numeric or a string value, numeric value is constraint by min and max, string value by options in within.
Definition: params.cpp:63
This is the car structure.
int index
car index
Definition: car.h:457
sgMat4 carPos
Definition: grcar.h:61
#define VAL_LIGHT_REAR
Definition: car.h:679
ssgBranch * CarsAnchorTmp
Definition: grcar.cpp:56
#define PRM_XPOS
Definition: car.h:564
ssgBranch * ShadowAnchor
Definition: grscene.cpp:73
ssgTransform * wheelPos[4]
Definition: grcar.h:52
#define PRM_SHADOW_TEXTURE
Definition: car.h:615
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 distFromStart
Definition: grcar.h:63
tdble sy
Definition: grcar.h:69
Track segment (tTrackSeg) The segments can be straights (type TR_STR): (the track goes from the right...
Definition: track.h:276
tgrCarInfo * grCarInfo
Definition: grmain.cpp:66
#define _dimension_x
short cut to tInitCar::dimension.x
Definition: car.h:102
ssgEntity * carEntity
Definition: grcar.h:46
void grPropagateDamage(ssgEntity *l, sgVec3 poc, sgVec3 force, int cnt)
Definition: grcar.cpp:477
static ssgSimpleState * brakeState
Definition: grcar.cpp:61
tdble sx
Definition: grcar.h:68
tdble py
Definition: grcar.h:67
#define PRM_YPOS
Definition: car.h:565
tdble az
angle along z axis
Definition: tgf.h:136
#define LIGHT_TYPE_REAR
Definition: grcarlight.h:90
int LODSelectMask[32]
Definition: grcar.h:47
#define MULT
ssgStateSelector * grEnvSelector
Definition: grscene.cpp:59
ssgState * grSsgLoadTexState(const char *img)
Definition: grutil.cpp:219
int GfParmGetEltNb(void *handle, const char *path)
Count the number of subsections in a section in the parameter set handle.
Definition: params.cpp:2106
float grGammaValue
Definition: grutil.cpp:39
#define VAL_LIGHT_HEAD2
Definition: car.h:675
ssgTransform * wheelRot[4]
Definition: grcar.h:53
#define PRM_SIZE
Definition: car.h:528
void grDrawCar(tCarElt *car, tCarElt *curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera *curCam)
Definition: grcar.cpp:761
void grDrawSkidmarks(tCarElt *car)
#define PRM_WHEEL_3D
Definition: car.h:670
Definition: Endpoint.h:36
ssgSelector * LODSelector
Definition: grcar.h:45
void grLinkCarlights(tCarElt *car)
Definition: grcarlight.cpp:403
#define SECT_LIGHT
Definition: car.h:508
tdble ax
angle along x axis
Definition: tgf.h:134
#define VAL_LIGHT_BRAKE
Definition: car.h:676
#define BRK_BRANCH
Track Structure and Track Loader Module Definition.
This file contains the divergences from PLIB.
#define PRM_WHEEL_3D_DIR
Definition: car.h:671
tdble envAngle
Definition: grcar.h:64
tdble px
Definition: grcar.h:66
void grInitBoardCar(tCarElt *car)
Definition: grboard.cpp:917
float LODThreshold[32]
Definition: grcar.h:48
static ssgSimpleState * commonState
Definition: grcar.cpp:62
tdble grGetDistToStart(tCarElt *car)
Definition: grcar.cpp:739
int grMipMap
Definition: grutil.cpp:40
#define SECT_EXHAUST
Definition: car.h:507
#define VAL_LIGHT_HEAD1
Definition: car.h:674
tdble z
z coordinate
Definition: tgf.h:133