TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
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-2026 by Christophe Guionneau
6 Christos Dimitrakakis
7 Bernhard Wymann
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 <math.h>
21#include <stdlib.h>
22#include <sys/types.h>
23#include <stdio.h>
24#include <ctype.h>
25#ifdef WIN32
26#include <windows.h>
27#endif
28#include <GL/glut.h>
29#include <plib/ssg.h>
30
31#include <tgfclient.h>
32#include <track.h>
33#include <car.h>
34#include <graphic.h>
35#include <robottools.h>
36
37#include "grmain.h"
38#include "grshadow.h"
39#include "grskidmarks.h"
40#include "grcar.h"
41#include "grcam.h"
42#include "grscene.h"
43#include "grboard.h"
44#include "grssgext.h"
45#include "grutil.h"
46
47#ifdef DMALLOC
48#include "dmalloc.h"
49#endif
50
51static ssgSimpleState *skidState = NULL;
52
56
59{
60 int i;
61 int k;
62 ssgNormalArray *shd_nrm;
63 sgVec3 nrm;
64
66 (char*)NULL, MAXSTRIP_BYWHEEL);
68 (char*)NULL, MAXPOINT_BY_STRIP);
70 (char*)NULL, DELTATSTRIP);
71
73 return;
74 }
75
76 shd_nrm = new ssgNormalArray(1);
77 nrm[0] = nrm[1] = 0.0;
78 nrm[2] = 1.0;
79 shd_nrm->add(nrm);
80
81 if (skidState == NULL) {
82 skidState = new ssgSimpleState();
83 if (skidState) {
84 skidState->disable(GL_LIGHTING);
85 skidState->enable(GL_BLEND);
86 skidState->enable(GL_CULL_FACE);
87 // add texture
88 skidState->enable(GL_TEXTURE_2D);
89 skidState->setColourMaterial(GL_AMBIENT_AND_DIFFUSE);
90 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
100 grCarInfo[car->index].skidmarks->strips[i].vta = (ssgVtxTableShadow **)malloc(grSkidMaxStripByWheel
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++) {
114 grCarInfo[car->index].skidmarks->strips[i].state[k] = SKID_UNUSED;
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
133 grCarInfo[car->index].skidmarks->strips[i].running_skid = 0;
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
137 grCarInfo[car->index].skidmarks->strips[i].last_state_of_skid = 0;
138 grCarInfo[car->index].skidmarks->strips[i].tex_state = 0.0;
139 }
140}
141
142
144void 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
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 */
284 grCarInfo[car->index].skidmarks->strips[i].last_state_of_skid = 1;
285 /* start a new one */
286 grCarInfo[car->index].skidmarks->strips[i].running_skid = grCarInfo[car->index].skidmarks->strips[i].next_skid;
287 if (grCarInfo[car->index].skidmarks->strips[i].state[grCarInfo[car->index].skidmarks->strips[i].running_skid] != SKID_UNUSED) {
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;
296 grCarInfo[car->index].skidmarks->strips[i].state[grCarInfo[car->index].skidmarks->strips[i].running_skid] = SKID_BEGIN;
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();
307 grCarInfo[car->index].skidmarks->strips[i].size[grCarInfo[car->index].skidmarks->strips[i].running_skid] = 2;
308 grCarInfo[car->index].skidmarks->strips[i].timeStrip=t;
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]);
320 grCarInfo[car->index].skidmarks->strips[i].size[grCarInfo[car->index].skidmarks->strips[i].running_skid] += 2;
321 if ( grCarInfo[car->index].skidmarks->strips[i].state[grCarInfo[car->index].skidmarks->strips[i].running_skid] == SKID_BEGIN)
322 {
323 grCarInfo[car->index].skidmarks->strips[i].state[grCarInfo[car->index].skidmarks->strips[i].running_skid] = SKID_RUNNING;
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();
327 grCarInfo[car->index].skidmarks->strips[i].timeStrip=t;
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 */
335 grCarInfo[car->index].skidmarks->strips[i].state[grCarInfo[car->index].skidmarks->strips[i].running_skid] = SKID_STOPPED;
336 grCarInfo[car->index].skidmarks->strips[i].vta[grCarInfo[car->index].skidmarks->strips[i].running_skid]->recalcBSphere();
337 grCarInfo[car->index].skidmarks->strips[i].last_state_of_skid = 0;
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;
341 if (grCarInfo[car->index].skidmarks->strips[i].next_skid >= grSkidMaxStripByWheel) {
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
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}
struct CarElt tCarElt
Car structure (tCarElt).
#define GR_ATT_MAXPOINTBYSTRIP
Definition graphic.h:88
#define GR_SCT_GRAPHIC
Definition graphic.h:82
#define GR_ATT_SKIDDELTAT
Definition graphic.h:89
#define GR_ATT_MAXSTRIPBYWHEEL
Definition graphic.h:87
tgrCarInfo * grCarInfo
Definition grmain.cpp:65
void * grHandle
Definition grmain.cpp:58
int grNbCars
Definition grmain.cpp:56
float tdble
Floating point type used in TORCS.
Definition tgf.h:47
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
ssgBranch * SkidAnchor
Definition grscene.cpp:78
int grSkidMaxPointByStrip
void grShutdownSkidmarks(void)
remove the skidmarks information for a car
void grUpdateSkidmarks(tCarElt *car, double t)
update if necessary the skidmarks for a car
void grDrawSkidmarks(tCarElt *car)
static ssgSimpleState * skidState
void grInitSkidmarks(tCarElt *car)
initialize the skidmak structure for a car
double grSkidDeltaT
int grSkidMaxStripByWheel
#define SKID_UNUSED
Definition grskidmarks.h:8
#define MAXSTRIP_BYWHEEL
Definition grskidmarks.h:5
#define DELTATSTRIP
Definition grskidmarks.h:3
#define SKID_STOPPED
Definition grskidmarks.h:11
#define SKID_RUNNING
Definition grskidmarks.h:10
#define SKID_BEGIN
Definition grskidmarks.h:9
#define MAXPOINT_BY_STRIP
Definition grskidmarks.h:4
This file contains the divergences from PLIB.
void grApplyTextureAnisotropy(ssgTexture *tex)
Definition grtexture.cpp:67
tPrivCar priv
private
Definition car.h:463
tPublicCar pub
public
Definition car.h:461
int index
car index
Definition car.h:459
tdble y
y coordinate
Definition tgf.h:131
tdble x
x coordinate
Definition tgf.h:130
tdble z
z coordinate
Definition tgf.h:132
tWheelState wheel[4]
Definition car.h:292
tdble speed
Definition car.h:194
tTrackSeg * seg
Track segment where the wheel is.
Definition car.h:256
tPosd relPos
position relative to GC
Definition car.h:252
tTrackSurface * surface
Segment surface.
Definition track.h:409
const char * material
Type of material used.
Definition track.h:262
#define GfOut
Definition tgf.h:372