TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
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
51extern ssgEntity *grssgLoadAC3D ( const char *fname, const ssgLoaderOptions* options );
52extern ssgEntity *grssgCarLoadAC3D ( const char *fname, const ssgLoaderOptions* options,int index );
53extern double carTrackRatioX;
54extern double carTrackRatioY;
55
56ssgBranch *CarsAnchorTmp = 0;
57
58
59static int grCarIndex;
60
61static ssgSimpleState *brakeState = NULL;
62static 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
86static 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.
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
414static 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
477void 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
512void
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;
600 grCarInfo[index].wheelTexture = grSsgLoadTexState(param);
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");
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
703 options.endLoad();
704
705 TRACE_GL("loadcar: end");
706}
707
708static void
709grDrawShadow(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
761void grDrawCar(tCarElt *car, tCarElt *curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera *curCam)
762{
763 sgCoord wheelpos;
764 sgMat4 renderCarPos;
765 int index, i, j;
766 static float maxVel[3] = { 20.0, 40.0, 70.0 };
767 float lod;
768
769 TRACE_GL("cggrDrawCar: start");
770
771 index = car->index;
772 if (car->priv.collision_state.collision_count > 0) {
773 tCollisionState* collision_state = &car->priv.collision_state;
774 grPropagateDamage (grCarInfo[index].carEntity, collision_state->pos, collision_state->force, 0);
775 collision_state->collision_count = 0;
776 }
777
778 grCarInfo[index].distFromStart=grGetDistToStart(car);
779 grCarInfo[index].envAngle=RAD2DEG(car->_yaw);
780
781 if ((car == curCar) && (dispCarFlag != 1)) {
782 grCarInfo[index].LODSelector->select(0);
783 } else {
784 lod = curCam->getLODFactor(car->_pos_X, car->_pos_Y, car->_pos_Z);
785 i = 0;
786 while (lod < grCarInfo[index].LODThreshold[i] * grLodFactorValue) {
787 i++;
788 }
789 if ((car->_state & RM_CAR_STATE_DNF) && (grCarInfo[index].LODThreshold[i] > 0.0)) {
790 i++;
791 }
792 grCarInfo[index].LODSelector->select(grCarInfo[index].LODSelectMask[i]);
793 if (dispDrvFlag) {
794 grCarInfo[index].driverSelector->select(1);
795 } else {
796 grCarInfo[index].driverSelector->select(0);
797 }
798 }
799
800 sgCopyMat4(grCarInfo[index].carPos, car->_posMat);
801 sgCopyMat4(renderCarPos, grCarInfo[index].carPos);
802 renderCarPos[3][0] = (float)(car->_pos_X_D - grRenderOrigin[0]);
803 renderCarPos[3][1] = (float)(car->_pos_Y_D - grRenderOrigin[1]);
804 grCarInfo[index].px=car->_pos_X;
805 grCarInfo[index].py=car->_pos_Y;
806
807 grCarInfo[index].carTransform->setTransform(renderCarPos);
808
809 if ((car == curCar) && (dispCarFlag != 1)) {
810 grDrawShadow(car, 0);
811 } else {
812 grDrawShadow(car, 1);
813 }
814
815 grUpdateSkidmarks(car, curTime);
816 grDrawSkidmarks(car);
817 grAddSmoke(car, curTime);
818
819 if ((car == curCar) && (dispCarFlag != 1)) {
820 grUpdateCarlight(car, curCam, 0);
821 } else {
822 grUpdateCarlight(car, curCam, 1);
823 }
824
825 /* Env mapping selection by the position on the track */
826 grCarInfo[index].envSelector->selectStep(car->_trkPos.seg->envIndex);
827
828 /* wheels */
829 for (i = 0; i < 4; i++) {
830 float *clr;
831
832 sgSetCoord(&wheelpos, car->priv.wheel[i].relPos.x, car->priv.wheel[i].relPos.y, car->priv.wheel[i].relPos.z,
833 RAD2DEG(car->priv.wheel[i].relPos.az), RAD2DEG(car->priv.wheel[i].relPos.ax), 0);
834 grCarInfo[index].wheelPos[i]->setTransform(&wheelpos);
835 sgSetCoord(&wheelpos, 0, 0, 0, 0, 0, RAD2DEG(car->priv.wheel[i].relPos.ay));
836 grCarInfo[index].wheelRot[i]->setTransform(&wheelpos);
837 for (j = 0; j < 3; j++) {
838 if (fabs(car->_wheelSpinVel(i)) < maxVel[j])
839 break;
840 }
841 grCarInfo[index].wheelselector[i]->select(1<<j);
842 clr = grCarInfo[index].brkColor[i]->get(0);
843 clr[0] = 0.1 + car->_brakeTemp(i) * 1.5;
844 clr[1] = 0.1 + car->_brakeTemp(i) * 0.3;
845 clr[2] = 0.1 - car->_brakeTemp(i) * 0.3;
846 }
847
848 /* push the car at the end of the display order */
849 CarsAnchorTmp->addKid(grCarInfo[index].carTransform);
850 CarsAnchor->removeKid(grCarInfo[index].carTransform);
851 CarsAnchor->addKid(grCarInfo[index].carTransform);
852 CarsAnchorTmp->removeKid(grCarInfo[index].carTransform);
853
854 TRACE_GL("cggrDrawCar: end");
855}
856
#define SECT_EXHAUST
Definition car.h:511
#define VAL_LIGHT_HEAD2
Definition car.h:679
#define PRM_YPOS
Definition car.h:569
#define PRM_SHADOW_TEXTURE
Definition car.h:619
#define PRM_POWER
Definition car.h:598
#define VAL_LIGHT_BRAKE2
Definition car.h:681
#define FRNT_RGT
front right
Definition car.h:38
#define VAL_LIGHT_REAR
Definition car.h:683
#define VAL_LIGHT_HEAD1
Definition car.h:678
#define PRM_WHEEL_TEXTURE
Definition car.h:618
#define REAR_RGT
rear right
Definition car.h:40
#define SECT_LIGHT
Definition car.h:512
#define REAR_LFT
rear left
Definition car.h:41
#define SECT_GROBJECTS
Definition car.h:510
#define PRM_WHEEL_3D
Definition car.h:674
#define RM_CAR_STATE_DNF
Car did not finish.
Definition car.h:212
#define _dimension_x
short cut to tInitCar::dimension.x
Definition car.h:102
#define PRM_ZPOS
Definition car.h:570
struct CarElt tCarElt
Car structure (tCarElt).
#define PRM_TYPE
Definition car.h:531
#define PRM_SIZE
Definition car.h:532
#define FRNT_LFT
front left
Definition car.h:39
#define PRM_WHEEL_3D_DIR
Definition car.h:675
#define PRM_THRESHOLD
Definition car.h:613
#define PRM_CAR
Definition car.h:614
#define PRM_WHEELSON
Definition car.h:615
#define LST_RANGES
Definition car.h:612
#define PRM_XPOS
Definition car.h:568
#define VAL_LIGHT_BRAKE
Definition car.h:680
struct tCollisionState_ tCollisionState
float getLODFactor(float x, float y, float z)
Definition grcam.cpp:199
virtual void transform(const sgMat4 m)
Definition grshadow.h:23
void grInitBoardCar(tCarElt *car)
Definition grboard.cpp:914
static ssgSimpleState * commonState
Definition grcar.cpp:62
double carTrackRatioX
Definition grloadac.cpp:49
static void grDrawShadow(tCarElt *car, int visible)
Definition grcar.cpp:709
ssgEntity * grssgLoadAC3D(const char *fname, const ssgLoaderOptions *options)
#define BRK_OFFSET
double carTrackRatioY
Definition grloadac.cpp:50
static const int GR_SHADOW_POINTS
Definition grcar.cpp:414
ssgBranch * CarsAnchorTmp
Definition grcar.cpp:56
void grPropagateDamage(ssgEntity *l, sgVec3 poc, sgVec3 force, int cnt)
Definition grcar.cpp:477
#define BRK_ANGLE
static ssgTransform * initWheel(tCarElt *car, int wheel_index)
Definition grcar.cpp:86
void grInitShadow(tCarElt *car)
Definition grcar.cpp:416
void grInitCommonState(void)
Definition grcar.cpp:64
static ssgSimpleState * brakeState
Definition grcar.cpp:61
ssgEntity * grssgCarLoadAC3D(const char *fname, const ssgLoaderOptions *options, int index)
void grInitCar(tCarElt *car)
Definition grcar.cpp:513
#define BRK_BRANCH
tdble grGetDistToStart(tCarElt *car)
Definition grcar.cpp:739
#define MULT
void grDrawCar(tCarElt *car, tCarElt *curCar, int dispCarFlag, int dispDrvFlag, double curTime, class cGrPerspCamera *curCam)
Definition grcar.cpp:761
static int grCarIndex
Definition grcar.cpp:59
tgrCarInfo * grCarInfo
Definition grmain.cpp:65
void grUpdateCarlight(tCarElt *car, class cGrPerspCamera *curCam, int disp)
void grAddCarlight(tCarElt *car, int type, sgVec3 pos, double size)
void grLinkCarlights(tCarElt *car)
#define LIGHT_TYPE_BRAKE
Definition grcarlight.h:92
#define LIGHT_TYPE_FRONT2
Definition grcarlight.h:89
#define LIGHT_TYPE_FRONT
Definition grcarlight.h:88
#define LIGHT_TYPE_REAR
Definition grcarlight.h:90
#define LIGHT_NO_TYPE
Definition grcarlight.h:95
#define LIGHT_TYPE_BRAKE2
Definition grcarlight.h:93
tdble grLodFactorValue
Definition grmain.cpp:69
EWheelDetail grUseDetailedWheels
Definition grmain.cpp:70
@ DETAILED
Definition grmain.h:77
float tdble
Floating point type used in TORCS.
Definition tgf.h:47
const char * GfParmGetStr(void *parmHandle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle.
Definition params.cpp:2453
tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle.
Definition params.cpp:2534
int GfParmGetEltNb(void *handle, const char *path)
Count the number of subsections in a section in the parameter set handle.
Definition params.cpp:2243
struct trackSeg tTrackSeg
Track segment (tTrackSeg) The segments can be straights (type TR_STR): (the track goes from the right...
tdble RtTrackHeightG(tTrackSeg *seg, tdble X, tdble Y)
Returns the absolute height in meters of the road at the Global position (segment,...
Definition rttrack.cpp:465
ssgStateSelector * grEnvSelector
Definition grscene.cpp:60
sgVec3 grRenderOrigin
Definition grscene.cpp:57
ssgBranch * CarsAnchor
Definition grscene.cpp:74
ssgBranch * ShadowAnchor
Definition grscene.cpp:75
static ssgLoaderOptionsEx options
Definition grscene.cpp:167
void grUpdateSkidmarks(tCarElt *car, double t)
update if necessary the skidmarks for a car
void grDrawSkidmarks(tCarElt *car)
void grAddSmoke(tCarElt *car, double t)
Definition grsmoke.cpp:221
This file contains the divergences from PLIB.
float grGammaValue
Definition grutil.cpp:39
ssgState * grSsgLoadTexState(const char *img)
Definition grutil.cpp:219
char * grTexturePath
Definition grutil.cpp:43
char * grFilePath
Definition grutil.cpp:42
int grMipMap
Definition grutil.cpp:40
#define DBG_SET_NAME(base, name, index, subindex)
Definition grutil.h:34
#define TRACE_GL(msg)
Definition grutil.h:28
tPrivCar priv
private
Definition car.h:463
int index
car index
Definition car.h:459
Parameter header structure, a parameter can either carry a numeric or a string value,...
Definition params.cpp:63
int collision_count
Definition car.h:281
sgVec3 force
Definition car.h:283
sgVec3 pos
Definition car.h:282
tdble y
y coordinate
Definition tgf.h:131
tdble x
x coordinate
Definition tgf.h:130
tdble z
z coordinate
Definition tgf.h:132
tdble ay
angle along y axis
Definition tgf.h:134
tdble ax
angle along x axis
Definition tgf.h:133
tdble az
angle along z axis
Definition tgf.h:135
tCollisionState collision_state
collision state
Definition car.h:315
tWheelState wheel[4]
Definition car.h:292
tPosd relPos
position relative to GC
Definition car.h:252
int type
Geometrical type:
Definition track.h:297
tdble radius
Radius in meters of the middle of the track (>0)
Definition track.h:337
tdble lgfromstart
Length of beginning of segment from starting line.
Definition track.h:336
#define GfOut
Definition tgf.h:372
#define MIN(x, y)
Definition tgf.h:56
#define FREEZ(x)
Definition tgf.h:59
#define RAD2DEG(x)
Radian to degree conversion.
Definition tgf.h:74
#define TR_STR
Straight.
Definition track.h:304