TORCS  1.3.9
The Open Racing Car Simulator
grskidmarks.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  file : grskidmarks.cpp
4  created : Fri Mar 22 23:17:24 CET 2002
5  copyright : (C) 2001-2005 by Christophe Guionneau
6  Christos Dimitrakakis
7  Bernhard Wymann
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 
38 #include "grmain.h"
39 #include "grshadow.h"
40 #include "grskidmarks.h"
41 #include "grcar.h"
42 #include "grcam.h"
43 #include "grscene.h"
44 #include "grboard.h"
45 #include "grssgext.h"
46 #include "grutil.h"
47 
48 #ifdef DMALLOC
49 #include "dmalloc.h"
50 #endif
51 
52 static ssgSimpleState *skidState = NULL;
53 
56 double grSkidDeltaT;
57 
60 {
61  int i;
62  int k;
63  ssgNormalArray *shd_nrm;
64  sgVec3 nrm;
65 
67  (char*)NULL, MAXSTRIP_BYWHEEL);
69  (char*)NULL, MAXPOINT_BY_STRIP);
71  (char*)NULL, DELTATSTRIP);
72 
73  if (!grSkidMaxStripByWheel) {
74  return;
75  }
76 
77  shd_nrm = new ssgNormalArray(1);
78  nrm[0] = nrm[1] = 0.0;
79  nrm[2] = 1.0;
80  shd_nrm->add(nrm);
81 
82  if (skidState == NULL) {
83  skidState = new ssgSimpleState();
84  if (skidState) {
85  skidState->disable(GL_LIGHTING);
86  skidState->enable(GL_BLEND);
87  skidState->enable(GL_CULL_FACE);
88  // add texture
89  skidState->enable(GL_TEXTURE_2D);
90  skidState->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
91  skidState->setTexture ("data/textures/grey-tracks.rgb", TRUE, TRUE, TRUE);
92  }
93  }
94 
95  grCarInfo[car->index].skidmarks = (tgrSkidmarks *)malloc(sizeof(tgrSkidmarks));
96  for (i = 0; i<4; i++) {
97  grCarInfo[car->index].skidmarks->strips[i].vtx = (ssgVertexArray **)malloc(grSkidMaxStripByWheel * sizeof(ssgVertexArray *));
98  grCarInfo[car->index].skidmarks->strips[i].tex = (ssgTexCoordArray **)malloc(grSkidMaxStripByWheel * sizeof(ssgTexCoordArray *));
99 
101  * sizeof(ssgVtxTableShadow *));
102  grCarInfo[car->index].skidmarks->strips[i].clr = ( ssgColourArray **)malloc(grSkidMaxStripByWheel
103  * sizeof( ssgColourArray *));
104 
105  grCarInfo[car->index].skidmarks->strips[i].smooth_colour[0]=0.0;
106  grCarInfo[car->index].skidmarks->strips[i].smooth_colour[1]=0.0;
107  grCarInfo[car->index].skidmarks->strips[i].smooth_colour[2]=0.0;
108  grCarInfo[car->index].skidmarks->strips[i].smooth_colour[3]=0.0;
109 
110  grCarInfo[car->index].skidmarks->strips[i].state = (int *)malloc(grSkidMaxStripByWheel * sizeof(int));
111  grCarInfo[car->index].skidmarks->strips[i].size = (int *)malloc(grSkidMaxStripByWheel * sizeof(int));
112 
113  for (k = 0; k < grSkidMaxStripByWheel; k++) {
115  grCarInfo[car->index].skidmarks->strips[i].vtx[k] = new ssgVertexArray(grSkidMaxPointByStrip + 1);
116  grCarInfo[car->index].skidmarks->strips[i].tex[k] = new ssgTexCoordArray(grSkidMaxPointByStrip + 1);
117  grCarInfo[car->index].skidmarks->strips[i].clr[k] = new ssgColourArray(grSkidMaxPointByStrip + 1);
118 
119  grCarInfo[car->index].skidmarks->strips[i].vta[k] =
121  (GL_TRIANGLE_STRIP,
122  grCarInfo[car->index].skidmarks->strips[i].vtx[k],
123  shd_nrm,
124  grCarInfo[car->index].skidmarks->strips[i].tex[k],
125  grCarInfo[car->index].skidmarks->strips[i].clr[k]
126  );
127  grCarInfo[car->index].skidmarks->strips[i].vta[k]->setCullFace(0);
128  grCarInfo[car->index].skidmarks->strips[i].vta[k]->setState(skidState);
129  grCarInfo[car->index].skidmarks->strips[i].timeStrip = 0;
130  SkidAnchor->addKid(grCarInfo[car->index].skidmarks->strips[i].vta[k]);
131  }
132  // no skid is in use
134  // the next skid to used is the first one
135  grCarInfo[car->index].skidmarks->strips[i].next_skid = 0;
136  // there was no skid for this wheel during the next shot
138  grCarInfo[car->index].skidmarks->strips[i].tex_state = 0.0;
139  }
140 }
141 
142 
144 void grUpdateSkidmarks(tCarElt *car, double t)
145 {
146  int i = 0;
147  sgVec3 vtx;
148  sgVec3 *tvtx;
149  sgVec2 *tclist;
150  sgVec2 TxVtx;
151  ssgVertexArray *basevtx = NULL;
152  sgVec4 cur_clr;
153  ssgTexCoordArray* texcoords = NULL;
154  tdble skid_sensitivity = 0.75f;
155 
156  if (!grSkidMaxStripByWheel) {
157  return;
158  }
159 
160  cur_clr[0] = cur_clr[1] = cur_clr[2] = 1.0f;
161 
162  for (i = 0; i < 4; i++) {
163 
164  tdble sling_mud = 1.0f;
165 
166  if (car->priv.wheel[i].seg) { // sanity check
167  const char* s = car->priv.wheel[i].seg->surface->material;
168  if (strstr(s, "sand")) {
169  cur_clr[0] = 0.8f;
170  cur_clr[1] = 0.6f;
171  cur_clr[2] = 0.35f;
172  skid_sensitivity = 0.9f;
173  } else if (strstr(s, "dirt")) {
174  cur_clr[0] = 0.7f;
175  cur_clr[1] = 0.55f;
176  cur_clr[2] = 0.45f;
177  skid_sensitivity = 0.9f;
178  } else if (strstr(s,"mud")) {
179  cur_clr[0] = 0.5f;
180  cur_clr[1] = 0.35f;
181  cur_clr[2] = 0.15f;
182  skid_sensitivity = 1.0f;
183  } else if (strstr(s,"grass")) {
184  cur_clr[0] = 0.75f;
185  cur_clr[1] = 0.5f;
186  cur_clr[2] = 0.3f;
187  skid_sensitivity = 0.8f;
188  } else if (strstr(s,"gravel")) {
189  cur_clr[0] = 0.6f;
190  cur_clr[1] = 0.6f;
191  cur_clr[2] = 0.6f;
192  skid_sensitivity = 0.7f;
193  } else {
194  sling_mud=0.0;
195  cur_clr[0] = 0.0f;
196  cur_clr[1] = 0.0f;
197  cur_clr[2] = 0.0f;
198  skid_sensitivity = 0.5f;
199  }
200  }
201 
202  if (car->_skid[i] > 0.1f) {
203  cur_clr[3] = tanh(skid_sensitivity*car->_skid[i]);
204  } else {
205  cur_clr[3] = 0.0f;
206  }
207 
208  for (int c = 0; c < 3; c++) {
209  tdble tmp = grCarInfo[car->index].skidmarks->strips[i].smooth_colour[c];
210  grCarInfo[car->index].skidmarks->strips[i].smooth_colour[c] = 0.9f*tmp + 0.1f*cur_clr[c];
211  cur_clr[c] = tmp;
212  }
213 
214  if ((t - grCarInfo[car->index].skidmarks->strips[i].timeStrip) < grSkidDeltaT) {
215  continue;
216  }
217 
218  if (car->pub.speed > 1.0f) {
219  if (cur_clr[3] > 0.1f) {
220 
221  basevtx = new ssgVertexArray(4 * 2 + 1);
222  tdble sling_left = 0.0f;
223  tdble sling_right = 0.0f;
224  sling_right = sling_mud;
225  sling_left = -sling_mud;
226 
227  // TO-DO: Temporary fix, trying to make sure that
228  // skids are above the road surface. This is needed
229  // because the wheel position depends on the current
230  // physical model road height, which is not exactly
231  // the same as the gfx road height, even if it is so
232  // on average, because the physical model adds some
233  // sinewave to the road height to simulate uneveness
234  // of the track. A better fix would be to add a
235  // routine grTrackHeightL(tTrkLocPos *p), similar to
236  // TrTrackHeightL(), but which aim to give the height
237  // of the graphical track.
238  tdble z_adjust = 0.95;
239  tdble contact_z = car->priv.wheel[i].relPos.z - car->_wheelRadius(i)*z_adjust;
240 
241 
242  vtx[0] = car->priv.wheel[i].relPos.x - car->_tireHeight(i);
243  // Because of backface culling the winding of the triangles matters.
244  if (car->_speed_x > 0.0f) {
245  vtx[1] = car->priv.wheel[i].relPos.y + (sling_right + 1.0)*car->_tireWidth(i) / 2.0;
246  } else {
247  vtx[1] = car->priv.wheel[i].relPos.y + (sling_left - 1.0)* car->_tireWidth(i) / 2.0;
248  }
249  vtx[2] = contact_z;
250  basevtx->add(vtx);
251 
252  vtx[0] = car->priv.wheel[i].relPos.x - car->_tireHeight(i);
253  // Because of backface culling the winding of the triangles matters.
254  if (car->_speed_x > 0.0f) {
255  vtx[1] = car->priv.wheel[i].relPos.y + (sling_left - 1.0)* car->_tireWidth(i) / 2.0;
256  } else {
257  vtx[1] = car->priv.wheel[i].relPos.y + (sling_right + 1.0)*car->_tireWidth(i) / 2.0;
258  }
259  vtx[2] = contact_z;
260  basevtx->add(vtx);
261 
262  texcoords = new ssgTexCoordArray();
263 
264  TxVtx[0] = grCarInfo[car->index].skidmarks->strips[i].tex_state;
265 
266  TxVtx[1] = 0.75f + sling_right*0.25f;
267  texcoords->add(TxVtx);
268 
269  TxVtx[1] = 0.25f+sling_left*0.25f;
270  texcoords->add(TxVtx);
271 
272 
273  float dt = 0.01f; // should get it from somewhere else really. I could also account for radius, but that's a bit of an overkill.
274  grCarInfo[car->index].skidmarks->strips[i].tex_state += dt*car->_wheelSpinVel(i);
275 
276  grCarInfo[car->index].skidmarks->base = new ssgVtxTable(GL_TRIANGLE_STRIP, basevtx, NULL, texcoords, NULL);
277  grCarInfo[car->index].skidmarks->base->transform(grCarInfo[car->index].carPos);
278  grCarInfo[car->index].skidmarks->base->getVertexList((void**)&tvtx);
279  grCarInfo[car->index].skidmarks->base->getTexCoordList((void**)&tclist);
282  if (grCarInfo[car->index].skidmarks->strips[i].last_state_of_skid == 0) {
283  /* begin case */
285  /* start a new one */
288  grCarInfo[car->index].skidmarks->strips[i].vtx[grCarInfo[car->index].skidmarks->strips[i].running_skid]->removeAll();
289  grCarInfo[car->index].skidmarks->strips[i].tex[grCarInfo[car->index].skidmarks->strips[i].running_skid]->removeAll();
290  grCarInfo[car->index].skidmarks->strips[i].clr[grCarInfo[car->index].skidmarks->strips[i].running_skid]->removeAll();
291  grCarInfo[car->index].skidmarks->strips[i].tex_state = 0.0;
292  //printf("clearing [%d] %d\n",i,grCarInfo[car->index].skidmarks->strips[i].running_skid);
293  }
294 
295  grCarInfo[car->index].skidmarks->strips[i].tex_state = 0.0;
297 
298  grCarInfo[car->index].skidmarks->strips[i].vtx[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(tvtx[0]);
299  grCarInfo[car->index].skidmarks->strips[i].vtx[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(tvtx[1]);
300  grCarInfo[car->index].skidmarks->strips[i].tex[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(tclist[0]);
301  grCarInfo[car->index].skidmarks->strips[i].tex[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(tclist[1]);
302  grCarInfo[car->index].skidmarks->strips[i].clr[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(cur_clr);
303  grCarInfo[car->index].skidmarks->strips[i].clr[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(cur_clr);
304 
305  //printf("begin [%d] skid %d x = %.2f y = %.2f \n",i,grCarInfo[car->index].skidmarks->strips[i].running_skid,tvtx[0][0],tvtx[0][1]);
306  grCarInfo[car->index].skidmarks->strips[i].vta[grCarInfo[car->index].skidmarks->strips[i].running_skid]->recalcBSphere();
309  grCarInfo[car->index].skidmarks->strips[i].vta[grCarInfo[car->index].skidmarks->strips[i].running_skid]->setCullFace(TRUE);
310  } else {
311  /* continue case */
312  grCarInfo[car->index].skidmarks->strips[i].vtx[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(tvtx[0]);
313  grCarInfo[car->index].skidmarks->strips[i].vtx[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(tvtx[1]);
314  grCarInfo[car->index].skidmarks->strips[i].tex[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(tclist[0]);
315  grCarInfo[car->index].skidmarks->strips[i].tex[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(tclist[1]);
316  grCarInfo[car->index].skidmarks->strips[i].clr[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(cur_clr);
317  grCarInfo[car->index].skidmarks->strips[i].clr[grCarInfo[car->index].skidmarks->strips[i].running_skid]->add(cur_clr);
318 
319  //printf("continue [%d] x = %.2f y = %.2f \n",i,tvtx[0][0],tvtx[0][1]);
322  {
324  /*SkidAnchor->addKid(grCarInfo[car->index].skidmarks->strips[i].vta[grCarInfo[car->index].skidmarks->strips[i].running_skid]);*/
325  }
326  grCarInfo[car->index].skidmarks->strips[i].vta[grCarInfo[car->index].skidmarks->strips[i].running_skid]->recalcBSphere();
328  }
329  basevtx->removeAll();
330  delete grCarInfo[car->index].skidmarks->base;
331  } else {
333  if (grCarInfo[car->index].skidmarks->strips[i].last_state_of_skid != 0) {
334  /* end the running skid */
336  grCarInfo[car->index].skidmarks->strips[i].vta[grCarInfo[car->index].skidmarks->strips[i].running_skid]->recalcBSphere();
338  //printf("end skid [%d] %d\n",i,grCarInfo[car->index].skidmarks->strips[i].running_skid);
339 
340  grCarInfo[car->index].skidmarks->strips[i].next_skid += 1;
342  grCarInfo[car->index].skidmarks->strips[i].next_skid = 0;
343  /* reset the next skid vertexArray */
344  grCarInfo[car->index].skidmarks->strips[i].vtx[grCarInfo[car->index].skidmarks->strips[i].next_skid]->removeAll();
345  grCarInfo[car->index].skidmarks->strips[i].tex[grCarInfo[car->index].skidmarks->strips[i].running_skid]->removeAll();
346  grCarInfo[car->index].skidmarks->strips[i].clr[grCarInfo[car->index].skidmarks->strips[i].next_skid]->removeAll();
347  //printf("remove all in skid [%d] %d\n",i,grCarInfo[car->index].skidmarks->strips[i].next_skid);
348  }
349  }
350  }
351  }
352  }
353 }
354 
355 
358 {
359  int i;
360  int z;
361 
362  GfOut("-- grShutdownSkidmarks\n");
363 
364  if (!grSkidMaxStripByWheel) {
365  return;
366  }
367 
368  SkidAnchor->removeAllKids();
369  for (z = 0; z < grNbCars; z++) {
370  for (i = 0; i<4; i++) {
371  free(grCarInfo[z].skidmarks->strips[i].vtx);
372  free(grCarInfo[z].skidmarks->strips[i].vta);
373  free(grCarInfo[z].skidmarks->strips[i].tex);
374  free(grCarInfo[z].skidmarks->strips[i].state);
375  free(grCarInfo[z].skidmarks->strips[i].size);
376  free(grCarInfo[z].skidmarks->strips[i].clr);
377  }
378  free(grCarInfo[z].skidmarks);
379  grCarInfo[z].skidmarks = NULL;
380  }
381  skidState = NULL;
382 }
383 
384 
386 {
387  /* nothing to do */
388 
389 
390 }
#define GR_ATT_MAXSTRIPBYWHEEL
Definition: graphic.h:87
int grSkidMaxPointByStrip
Definition: grskidmarks.cpp:55
ssgVertexArray ** vtx
Definition: grskidmarks.h:19
float tex_state
Definition: grskidmarks.h:31
tdble y
y coordinate
Definition: tgf.h:132
int grNbCars
Definition: grmain.cpp:57
ssgTexCoordArray ** tex
Definition: grskidmarks.h:21
ssgVtxTable * base
Definition: grskidmarks.h:36
void grInitSkidmarks(tCarElt *car)
initialize the skidmak structure for a car
Definition: grskidmarks.cpp:59
tgrSkidStrip strips[4]
Definition: grskidmarks.h:37
Car structure (tCarElt).
Definition: car.h:455
double timeStrip
Definition: grskidmarks.h:26
Robots Tools.
ssgVtxTableShadow ** vta
Definition: grskidmarks.h:20
int grSkidMaxStripByWheel
Definition: grskidmarks.cpp:54
sgVec4 smooth_colour
Definition: grskidmarks.h:23
The Gaming Framework API (client part).
const char * material
Type of material used.
Definition: track.h:245
tPosd relPos
position relative to GC
Definition: car.h:250
#define MAXSTRIP_BYWHEEL
Definition: grskidmarks.h:5
double grSkidDeltaT
Definition: grskidmarks.cpp:56
int running_skid
Definition: grskidmarks.h:27
float tdble
Floating point type used in TORCS.
Definition: tgf.h:48
#define GfOut
Definition: tgf.h:373
tgrSkidmarks * skidmarks
Definition: grcar.h:60
tdble x
x coordinate
Definition: tgf.h:131
tWheelState wheel[4]
Definition: car.h:290
tPublicCar pub
public
Definition: car.h:459
void grUpdateSkidmarks(tCarElt *car, double t)
update if necessary the skidmarks for a car
Graphic Module Interface Definition.
#define GR_SCT_GRAPHIC
Definition: graphic.h:82
tPrivCar priv
private
Definition: car.h:461
This is the car structure.
int index
car index
Definition: car.h:457
sgMat4 carPos
Definition: grcar.h:61
ssgColourArray ** clr
Definition: grskidmarks.h:22
#define SKID_RUNNING
Definition: grskidmarks.h:10
#define GR_ATT_MAXPOINTBYSTRIP
Definition: graphic.h:88
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
tTrackSeg * seg
Track segment where the wheel is.
Definition: car.h:254
void grShutdownSkidmarks(void)
remove the skidmarks information for a car
tgrCarInfo * grCarInfo
Definition: grmain.cpp:66
static ssgSimpleState * skidState
Definition: grskidmarks.cpp:52
tdble speed
Definition: car.h:194
#define SKID_STOPPED
Definition: grskidmarks.h:11
#define SKID_BEGIN
Definition: grskidmarks.h:9
tTrackSurface * surface
Segment surface.
Definition: track.h:394
#define SKID_UNUSED
Definition: grskidmarks.h:8
void * grHandle
Definition: grmain.cpp:59
void grDrawSkidmarks(tCarElt *car)
#define MAXPOINT_BY_STRIP
Definition: grskidmarks.h:4
ssgBranch * SkidAnchor
Definition: grscene.cpp:76
int last_state_of_skid
Definition: grskidmarks.h:29
Track Structure and Track Loader Module Definition.
This file contains the divergences from PLIB.
#define DELTATSTRIP
Definition: grskidmarks.h:3
#define GR_ATT_SKIDDELTAT
Definition: graphic.h:89
tdble z
z coordinate
Definition: tgf.h:133