TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
collide.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : collide.cpp
4 created : Sun Mar 19 00:06:19 CET 2000
5 copyright : (C) 2000-2017 by Eric Espie, Bernhard Wymann
6 email : torcs@free.fr
7 version : $Id$
8
9 ***************************************************************************/
10
11/***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20#include "sim.h"
21
22#define CAR_DAMMAGE 0.1
23
24
26{
27 int i;
28 const float CRASH_THRESHOLD = -5.0f;
29
30 if (car->carElt->_state & RM_CAR_STATE_NO_SIMU) {
31 return;
32 }
33
34 // Calculate transformation matrix to transform the surface normal into the car body local coordinate system.
35 // Because this is just a rotation matrix the inverse is the transposed matrix.
36 sgMat4 dst;
37 sgMakeRotMat4(dst, RAD2DEG(car->DynGC.pos.az), RAD2DEG(car->DynGC.pos.ax), RAD2DEG(car->DynGC.pos.ay));
38 sgTransposeNegateMat4(dst);
39
40 // Get the normal of the surface under the center of gravity of the car. Beware, TR_LPOS_SEGMENT must
41 // be set to get this result.
42 t3Dd normal;
43 tTrkLocPos normalPos;
44 RtTrackGlobal2Local(car->trkPos.seg, car->DynGCg.pos.x, car->DynGCg.pos.y, &normalPos, TR_LPOS_SEGMENT);
45 RtTrackSurfaceNormalL(&normalPos, &normal);
46
47 // Now transform the normal to the car body coordinate system.
48 sgVec3 dstVec;
49 sgXformVec3(dstVec, (float *) &normal.x, dst);
50 tdble sumdz = 0.0f;
51
52 // Check if any car corners are below the surface. If so, try to rotate the corner out of the ground.
53 for (i = 0; i < 4; i++) {
54 tTrkLocPos cornerPos;
55 RtTrackGlobal2Local(car->trkPos.seg, car->corner[i].pos.ax, car->corner[i].pos.ay, &cornerPos, TR_LPOS_SEGMENT);
56 tdble z = RtTrackHeightL(&cornerPos);
57 tdble dz = car->corner[i].pos.az - z;
58 sumdz += dz;
59
60 // Car corner below surface
61 if (dz < 0.0f) {
62 tdble dPosAy = dz/car->corner[i].pos.x*fabs(dstVec[0]);
63 car->DynGCg.pos.ay += dPosAy;
64 tdble dPosAx = dz/car->corner[i].pos.y*fabs(dstVec[1]);
65 car->DynGCg.pos.ax -= dPosAx;
67 }
68 }
69
70 if (sumdz > 0.0f) sumdz = 0.0f;
71
72 // The above part cannot resolve the collision in all cases, e.g. when all corners are below the surface.
73 // For this case we check if the car floor below the center of gravity is eventually below the ground too.
74 tdble z = RtTrackHeightG(car->trkPos.seg, car->DynGCg.pos.x, car->DynGCg.pos.y);
75 tdble dz = car->DynGCg.pos.z - (car->statGC.z - sumdz)/normal.z - z;
76
77 if (dz < 0.0f) {
78 tdble dotProd = (car->DynGCg.vel.x * normal.x + car->DynGCg.vel.y * normal.y + car->DynGCg.vel.z * normal.z);
79 if (dotProd < 0.0f) {
80 if (dotProd < CRASH_THRESHOLD) {
82 }
84 car->DynGCg.vel.x -= normal.x * dotProd;
85 car->DynGCg.vel.y -= normal.y * dotProd;
86 car->DynGCg.vel.z -= normal.z * dotProd;
87
88 if ((car->carElt->_state & RM_CAR_STATE_FINISH) == 0) {
89 car->dammage += (int)(normalPos.seg->surface->kDammage * fabs(dotProd) * rulesDamageFactor * simDammageFactor[car->carElt->_skillLevel]);
90 }
91 }
92 }
93}
94
95const tdble BorderFriction = 0.0f;
96
97// Collision of car/track borders.
98// Be aware that it does not work for convex edges (e.g. e-track-2, end of the straight, left),
99// because under these conditions it is possible that all car corners are on the track and
100// the car body is partially outside the track.
102{
103 tTrackSeg *seg = car->trkPos.seg;
104 tTrkLocPos trkpos;
105 int i;
106 tDynPt *corner;
107 tdble initDotProd;
108 tdble dotProd, cx, cy, dotprod2;
109 tTrackBarrier *curBarrier;
110 tdble dmg;
111
112 if (car->carElt->_state & RM_CAR_STATE_NO_SIMU) {
113 return;
114 }
115
116 corner = &(car->corner[0]);
117 for (i = 0; i < 4; i++, corner++) {
118 seg = car->trkPos.seg;
119 RtTrackGlobal2Local(seg, corner->pos.ax, corner->pos.ay, &trkpos, TR_LPOS_TRACK);
120 seg = trkpos.seg;
121 tdble toSide;
122
123 if (trkpos.toRight < 0.0) {
124 // collision with right border.
125 curBarrier = seg->barrier[TR_SIDE_RGT];
126 toSide = trkpos.toRight;
127 } else if (trkpos.toLeft < 0.0) {
128 // collision with left border.
129 curBarrier = seg->barrier[TR_SIDE_LFT];
130 toSide = trkpos.toLeft;
131 } else {
132 continue;
133 }
134
135 const tdble& nx = curBarrier->normal.x;
136 const tdble& ny = curBarrier->normal.y;
137
138 car->DynGCg.pos.x -= nx * toSide;
139 car->DynGCg.pos.y -= ny * toSide;
140
141 // Corner position relative to center of gravity.
142 cx = corner->pos.ax - car->DynGCg.pos.x;
143 cy = corner->pos.ay - car->DynGCg.pos.y;
144
145 car->blocked = 1;
146 car->collision |= SEM_COLLISION;
147
148 // Impact speed perpendicular to barrier (of corner).
149 initDotProd = nx * corner->vel.x + ny * corner->vel.y;
150
151 // Compute dmgDotProd (base value for later damage) with a heuristic.
152 tdble absvel = MAX(1.0, sqrt(car->DynGCg.vel.x*car->DynGCg.vel.x + car->DynGCg.vel.y*car->DynGCg.vel.y));
153 tdble GCgnormvel = car->DynGCg.vel.x*nx + car->DynGCg.vel.y*ny;
154 tdble cosa = GCgnormvel/absvel;
155 tdble dmgDotProd = GCgnormvel*cosa;
156
157 dotProd = initDotProd * curBarrier->surface->kFriction;
158 car->DynGCg.vel.x -= nx * dotProd;
159 car->DynGCg.vel.y -= ny * dotProd;
160 dotprod2 = (nx * cx + ny * cy);
161
162 // Angular velocity change caused by friction of colliding car part with wall.
163 static tdble VELSCALE = 10.0f;
164 static tdble VELMAX = 6.0f;
165 car->DynGCg.vel.az -= dotprod2 * dotProd / VELSCALE;
166 if (fabs(car->DynGCg.vel.az) > VELMAX) {
167 car->DynGCg.vel.az = SIGN(car->DynGCg.vel.az) * VELMAX;
168 }
169
170 // Damage.
171 dotProd = initDotProd;
172 if (dotProd < 0.0f && (car->carElt->_state & RM_CAR_STATE_FINISH) == 0) {
173 dmg = curBarrier->surface->kDammage * (0.5f*dmgDotProd*dmgDotProd + 0.005f*fabs(1.0f-cosa)*absvel) * rulesDamageFactor * simDammageFactor[car->carElt->_skillLevel];
174 car->dammage += (int) dmg;
175 } else {
176 dmg = 0.0f;
177 }
178
179 dotProd *= curBarrier->surface->kRebound;
180
181 // If the car moves toward the barrier, rebound.
182 if (dotProd < 0.0f) {
184 car->normal.x = nx * dmg;
185 car->normal.y = ny * dmg;
186 car->collpos.x = corner->pos.ax;
187 car->collpos.y = corner->pos.ay;
188 car->DynGCg.vel.x -= nx * dotProd;
189 car->DynGCg.vel.y -= ny * dotProd;
190 }
191 }
192}
193
194
195static void SimCarCollideResponse(void * /*dummy*/, DtObjectRef obj1, DtObjectRef obj2, const DtCollData *collData)
196{
197 sgVec2 n; // Collision normal delivered by solid: Global(point1) - Global(point2)
198 tCar *car[2]; // The cars.
199 sgVec2 p[2]; // Collision points delivered by solid, in body local coordinates.
200 sgVec2 r[2]; // Collision point relative to center of gravity.
201 sgVec2 vp[2]; // Speed of collision point in world coordinate system.
202 sgVec3 pt[2]; // Collision points in global coordinates.
203
204 int i;
205
206 car[0] = (tCar*)obj1;
207 car[1] = (tCar*)obj2;
208
209 // Handle cars collisions during pit stops as well.
210 static const int NO_SIMU_WITHOUT_PIT = RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT;
211
212 if ((car[0]->carElt->_state & NO_SIMU_WITHOUT_PIT) ||
213 (car[1]->carElt->_state & NO_SIMU_WITHOUT_PIT))
214 {
215 return;
216 }
217
218 if (car[0]->carElt->index < car[1]->carElt->index) {
219 // vector conversion from double to float.
220 p[0][0] = (float)collData->point1[0];
221 p[0][1] = (float)collData->point1[1];
222 p[1][0] = (float)collData->point2[0];
223 p[1][1] = (float)collData->point2[1];
224 n[0] = (float)collData->normal[0];
225 n[1] = (float)collData->normal[1];
226 } else {
227 // swap the cars (not the same for the simu).
228 car[0] = (tCar*)obj2;
229 car[1] = (tCar*)obj1;
230 p[0][0] = (float)collData->point2[0];
231 p[0][1] = (float)collData->point2[1];
232 p[1][0] = (float)collData->point1[0];
233 p[1][1] = (float)collData->point1[1];
234 n[0] = -(float)collData->normal[0];
235 n[1] = -(float)collData->normal[1];
236 }
237
238 sgNormaliseVec2(n);
239
240 // Because of the type conversion and the transformation to 2D the length of the normal might be 0 now, which could cause NaN
241 if (isnan(n[0]) || isnan(n[1])) {
242 return;
243 }
244
245 sgVec2 rg[2]; // radius oriented in global coordinates, still relative to CG (rotated aroung CG).
246 tCarElt *carElt;
247
248 for (i = 0; i < 2; i++) {
249 // vector GP (Center of gravity to collision point). p1 and p2 are delivered from solid as
250 // points in the car coordinate system.
251 sgSubVec2(r[i], p[i], (const float*)&(car[i]->statGC));
252
253 // Speed of collision points, linear motion of center of gravity (CG) plus rotational
254 // motion around the CG.
255 carElt = car[i]->carElt;
256 float sina = sin(carElt->_yaw);
257 float cosa = cos(carElt->_yaw);
258 rg[i][0] = r[i][0]*cosa - r[i][1]*sina;
259 rg[i][1] = r[i][0]*sina + r[i][1]*cosa;
260
261 vp[i][0] = car[i]->DynGCg.vel.x - car[i]->DynGCg.vel.az * rg[i][1];
262 vp[i][1] = car[i]->DynGCg.vel.y + car[i]->DynGCg.vel.az * rg[i][0];
263 }
264
265 // Relative speed of collision points.
266 sgVec2 v1ab;
267 sgSubVec2(v1ab, vp[0], vp[1]);
268
269 // try to separate the cars. The computation is necessary because dtProceed is not called till
270 // the collision is resolved.
271 for (i = 0; i < 2; i++) {
272 sgCopyVec2(pt[i], r[i]);
273 pt[i][2] = 0.0f;
274 // Transform points relative to cars local coordinate system into global coordinates.
275 sgFullXformPnt3(pt[i], car[i]->carElt->_posMat);
276 }
277
278 // Compute distance of collision points.
279 sgVec3 pab;
280 sgSubVec2(pab, pt[1], pt[0]);
281 float distpab = sgLengthVec2(pab);
282
283 sgVec2 tmpv;
284
285 sgScaleVec2(tmpv, n, MIN(distpab, 0.05));
286 // No "for" loop here because of subtle difference AddVec/SubVec.
287 if (car[0]->blocked == 0 && !(car[0]->carElt->_state & RM_CAR_STATE_NO_SIMU)) {
288 sgAddVec2((float*)&(car[0]->DynGCg.pos), tmpv);
289 car[0]->blocked = 1;
290 }
291 if (car[1]->blocked == 0 && !(car[1]->carElt->_state & RM_CAR_STATE_NO_SIMU)) {
292 sgSubVec2((float*)&(car[1]->DynGCg.pos), tmpv);
293 car[1]->blocked = 1;
294 }
295
296 // Doing no dammage and correction if the cars are moving out of each other.
297 if (sgScalarProductVec2(v1ab, n) > 0) {
298 return;
299 }
300
301 // impulse.
302 float rpn[2];
303 rpn[0] = sgScalarProductVec2(rg[0], n);
304 rpn[1] = sgScalarProductVec2(rg[1], n);
305
306 // Pseudo cross product to find out if we are left or right.
307 // TODO: SIGN, scrap value?
308 float rpsign[2];
309 rpsign[0] = n[0]*rg[0][1] - n[1]*rg[0][0];
310 rpsign[1] = -n[0]*rg[1][1] + n[1]*rg[1][0];
311
312 const float e = 1.0f; // energy restitution
313
314 float j = -(1.0f + e) * sgScalarProductVec2(v1ab, n) /
315 ((car[0]->Minv + car[1]->Minv) +
316 rpn[0] * rpn[0] * car[0]->Iinv.z + rpn[1] * rpn[1] * car[1]->Iinv.z);
317
318 for (i = 0; i < 2; i++) {
319 if (car[i]->carElt->_state & RM_CAR_STATE_NO_SIMU) {
320 continue;
321 }
322
323 // Damage.
324 tdble damFactor, atmp;
325 atmp = atan2(r[i][1], r[i][0]);
326 if (fabs(atmp) < (PI / 3.0)) {
327 // Front collision gives more damage.
328 damFactor = 1.5f;
329 } else {
330 // Rear collision gives less damage.
331 damFactor = 1.0f;
332 }
333
334 if ((car[i]->carElt->_state & RM_CAR_STATE_FINISH) == 0) {
335 car[i]->dammage += (int)(CAR_DAMMAGE * fabs(j) * damFactor * rulesDamageFactor * simDammageFactor[car[i]->carElt->_skillLevel]);
336 }
337
338 // Compute collision velocity.
339 const float ROT_K = 1.0f;
340
341 float js = (i == 0) ? j : -j;
342 sgScaleVec2(tmpv, n, js * car[i]->Minv);
343 sgVec2 v2a;
344
345 if (car[i]->collision & SEM_COLLISION_CAR) {
346 sgAddVec2(v2a, (const float*)&(car[i]->VelColl.x), tmpv);
347 car[i]->VelColl.az = car[i]->VelColl.az + js * rpsign[i] * rpn[i] * car[i]->Iinv.z * ROT_K;
348 } else {
349 sgAddVec2(v2a, (const float*)&(car[i]->DynGCg.vel), tmpv);
350 car[i]->VelColl.az = car[i]->DynGCg.vel.az + js * rpsign[i] * rpn[i] * car[i]->Iinv.z * ROT_K;
351 }
352
353 static float VELMAX = 3.0f;
354 if (fabs(car[i]->VelColl.az) > VELMAX) {
355 car[i]->VelColl.az = SIGN(car[i]->VelColl.az) * VELMAX;
356 }
357
358 sgCopyVec2((float*)&(car[i]->VelColl.x), v2a);
359
360 // Move the car for the collision lib.
361 tCarElt *carElt = car[i]->carElt;
362 sgMakeCoordMat4(carElt->pub.posMat, car[i]->DynGCg.pos.x, car[i]->DynGCg.pos.y,
363 car[i]->DynGCg.pos.z - carElt->_statGC_z, RAD2DEG(carElt->_yaw),
364 RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));
365 dtSelectObject(car[i]);
367 dtMultMatrixf((const float *)(carElt->_posMat));
368
369 car[i]->collision |= SEM_COLLISION_CAR;
370 }
371}
372
373
374// Collision response for walls.
375// TODO: Separate common code with car-car collision response.
376static void SimCarWallCollideResponse(void *clientdata, DtObjectRef obj1, DtObjectRef obj2, const DtCollData *collData)
377{
378 tCar* car; // The car colliding with the wall.
379 float nsign; // Normal direction correction for collision plane.
380 sgVec2 p; // Cars collision point delivered by solid.
381
382 // TODO: If other movable objects are added which could collide with the wall, it will be
383 // necessary to validate if the object is actually a car.
384
385 if (obj1 == clientdata) {
386 car = (tCar*) obj2;
387 nsign = -1.0f;
388 p[0] = (float) collData->point2[0];
389 p[1] = (float) collData->point2[1];
390 } else {
391 car = (tCar*) obj1;
392 nsign = 1.0f;
393 p[0] = (float) collData->point1[0];
394 p[1] = (float) collData->point1[1];
395 }
396
397 sgVec2 n; // Collision normal delivered by solid, corrected such that it points away from the wall.
398 n[0] = nsign * (float) collData->normal[0];
399 n[1] = nsign * (float) collData->normal[1];
400 float pdist = sgLengthVec2(n); // Distance of collision points.
401 sgNormaliseVec2(n);
402
403 // Because of the type conversion and the transformation to 2D the length of the normal might be 0 now, which could cause NaN
404 if (isnan(n[0]) || isnan(n[1])) {
405 return;
406 }
407
408 sgVec2 r;
409 sgSubVec2(r, p, (const float*)&(car->statGC));
410
411 tCarElt *carElt = car->carElt;
412
413 sgVec2 vp; // Speed of car collision point in global frame of reference.
414 sgVec2 rg; // raduis oriented in global coordinates, still relative to CG (rotated aroung CG).
415
416 float sina = sin(carElt->_yaw);
417 float cosa = cos(carElt->_yaw);
418 rg[0] = r[0]*cosa - r[1]*sina;
419 rg[1] = r[0]*sina + r[1]*cosa;
420
421 vp[0] = car->DynGCg.vel.x - car->DynGCg.vel.az * rg[1];
422 vp[1] = car->DynGCg.vel.y + car->DynGCg.vel.az * rg[0];
423
424 sgVec2 tmpv;
425 static const float CAR_MIN_MOVEMENT = 0.02f;
426 static const float CAR_MAX_MOVEMENT = 0.05f;
427 sgScaleVec2(tmpv, n, MIN(MAX(pdist, CAR_MIN_MOVEMENT), CAR_MAX_MOVEMENT));
428 if (car->blocked == 0) {
429 sgAddVec2((float*)&(car->DynGCg.pos), tmpv);
430 car->blocked = 1;
431 }
432
433 // Doing no dammage and correction if the cars are moving out of each other.
434 if (sgScalarProductVec2(vp, n) > 0) {
435 return;
436 }
437
438 float rp = sgScalarProductVec2(rg, n);
439
440 // Pesudo cross product to find out if we are left or right.
441 // TODO: SIGN, scrap value?
442 float rpsign = n[0]*rg[1] - n[1]*rg[0];
443
444 const float e = 1.0f; // energy restitution
445 float j = -(1.0f + e) * sgScalarProductVec2(vp, n) / (car->Minv + rp * rp * car->Iinv.z);
446 const float ROT_K = 0.5f;
447
448 // Damage.
449 tdble damFactor, atmp;
450 atmp = atan2(r[1], r[0]);
451 if (fabs(atmp) < (PI / 3.0)) {
452 // Front collision gives more damage.
453 damFactor = 1.5f;
454 } else {
455 // Rear collision gives less damage.
456 damFactor = 1.0f;
457 }
458
459 static const float DMGFACTOR = 0.00002f;
460 if ((car->carElt->_state & RM_CAR_STATE_FINISH) == 0) {
461 car->dammage += (int)(CAR_DAMMAGE * (DMGFACTOR*j*j) * damFactor * rulesDamageFactor * simDammageFactor[car->carElt->_skillLevel]);
462 }
463
464 sgScaleVec2(tmpv, n, j * car->Minv);
465 sgVec2 v2a;
466
467 if (car->collision & SEM_COLLISION_CAR) {
468 sgAddVec2(v2a, (const float*)&(car->VelColl.x), tmpv);
469 car->VelColl.az = car->VelColl.az + j * rp * rpsign * car->Iinv.z * ROT_K;
470 } else {
471 sgAddVec2(v2a, (const float*)&(car->DynGCg.vel), tmpv);
472 car->VelColl.az = car->DynGCg.vel.az + j * rp * rpsign * car->Iinv.z * ROT_K;
473 }
474
475 static float VELMAX = 3.0f;
476 if (fabs(car->VelColl.az) > VELMAX) {
477 car->VelColl.az = SIGN(car->VelColl.az) * VELMAX;
478 }
479
480 sgCopyVec2((float*)&(car->VelColl.x), v2a);
481
482 // Move the car for the collision lib.
483 sgMakeCoordMat4(carElt->pub.posMat, car->DynGCg.pos.x, car->DynGCg.pos.y,
484 car->DynGCg.pos.z - carElt->_statGC_z, RAD2DEG(carElt->_yaw),
485 RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));
486 dtSelectObject(car);
488 dtMultMatrixf((const float *)(carElt->_posMat));
489
491}
492
493
494// Remove wrecked cars to avoid glitches in collision detection and to improve performance.
495// Called by RemoveCar.
496void SimCollideRemoveCar(tCar *car, int nbcars)
497{
498 // Find the car to remove.
499 int i;
500 for (i = 0; i < nbcars; i++) {
501 if (&SimCarTable[i] == car) {
502 break;
503 }
504 }
505
506 // Remove it.
507 if (SimCarTable[i].shape != NULL) {
509 dtDeleteShape(SimCarTable[i].shape);
510 SimCarTable[i].shape = NULL;
511 }
512}
513
514
515// Static object and shape list.
516// TODO: Dynamic implementation.
518// Id to the next free slot in fixedobjects.
519static unsigned int fixedid;
520
521
522void SimCarCollideShutdown(int nbcars)
523{
524 int i;
525
526 for (i = 0; i < nbcars; i++) {
527 // Check if car has not been removed already (wrecked).
528 if (SimCarTable[i].shape != NULL) {
530 dtDeleteShape(SimCarTable[i].shape);
531 }
532 }
533
534 unsigned int j;
535 for (j = 0; j < fixedid; j++) {
539 }
540 fixedid = 0;
541
543}
544
545
546// Searching backwards for the first non wall segments to start.
547// Used for the creation of collision detection model of the wall.
548static tTrackSeg *getFirstWallStart(tTrackSeg *start, int side)
549{
550 tTrackSeg *first = start;
551
552 // Moving backward out of wall.
553 do {
554 // A wall is a wall on the track if it is not the barrier at the same time.
555 if (first->side[side] != NULL && first->side[side]->style == TR_WALL &&
556 first->side[side]->side[side] != NULL)
557 {
558 first = first->prev;
559 } else {
560 break;
561 }
562 } while (first != start);
563
564 // Searching forward for the first wall segment.
565 start = first;
566 do {
567 if (first->side[side] != NULL && first->side[side]->style == TR_WALL &&
568 first->side[side]->side[side] != NULL)
569 {
570 return first;
571 } else {
572 first = first->next;
573 }
574 } while (first != start);
575
576 return NULL;
577}
578
579
580// Create the left walls, start must point to a segment with a wall on the left and a leading
581// non wall segment.
582// FIXME: Does not work for a closed ring "by design".
583void buildWalls(tTrackSeg *start, int side) {
584
585 if (start == NULL) {
586 return;
587 }
588
589 tTrackSeg *current = start;
590 bool close = false;
591
592 // Going down the wall.
593 do {
594 tTrackSeg* s = current->side[side];
595 tTrackSeg* p = current->prev->side[side];
596 tTrackSeg* n = current->next->side[side];
597
598 // Current segment is a wall?
599 if (s != NULL && s->style == TR_WALL && s->side[side] != NULL) {
600
601 float h = s->height;
602 t3Dd svl = s->vertex[TR_SL];
603 t3Dd svr = s->vertex[TR_SR];
604 t3Dd evl = s->vertex[TR_EL];
605 t3Dd evr = s->vertex[TR_ER];
606 static float weps = 0.01f;
607
608 // Close the start with a ploygon?
609 if (p == NULL || p->style != TR_WALL ||
610 (fabs(p->vertex[TR_EL].x - svl.x) > weps) ||
611 (fabs(p->vertex[TR_ER].x - svr.x) > weps) ||
612 (fabs(h - p->height) > weps) ||
613 fixedid == 0)
614 {
615 // Enough space in array?
616 if (fixedid >= sizeof(fixedobjects)/sizeof(fixedobjects[0])) {
617 GfError("fixedobjects full in %s, line %d\n", __FILE__, __LINE__);
618 return;
619 }
620
621 if (close == true) {
623 GfError("Shape not closed %s, line %d\n", __FILE__, __LINE__);
624 }
625
626 // Start new shape.
628 fixedid++;
629 close = true;
630
632 dtVertex(svl.x, svl.y, svl.z);
633 dtVertex(svr.x, svr.y, svr.z);
634 dtVertex(svr.x, svr.y, svr.z + h);
635 dtVertex(svl.x, svl.y, svl.z + h);
636 dtEnd();
637 }
638
639 // Build sides, left, top, right. Depending on how we want to use it we
640 // can remove top perhaps.
641 // TODO: do we want the top poly?
642 if (close == true) {
643 // Left.
645 dtVertex(svl.x, svl.y, svl.z);
646 dtVertex(svl.x, svl.y, svl.z + h);
647 dtVertex(evl.x, evl.y, evl.z + h);
648 dtVertex(evl.x, evl.y, evl.z);
649 dtEnd();
650 /*
651 // Top.
652 dtBegin(DT_POLYGON);
653 dtVertex(svl.x, svl.y, svl.z + h);
654 dtVertex(svr.x, svr.y, svr.z + h);
655 dtVertex(evr.x, evr.y, evr.z + h);
656 dtVertex(evl.x, evl.y, evl.z + h);
657 dtEnd();*/
658 // Right.
660 dtVertex(svr.x, svr.y, svr.z + h);
661 dtVertex(svr.x, svr.y, svr.z);
662 dtVertex(evr.x, evr.y, evr.z);
663 dtVertex(evr.x, evr.y, evr.z + h);
664 dtEnd();
665 } else {
666 GfError("Shape not open %s, line %d\n", __FILE__, __LINE__);
667 }
668
669 // Close the end with a ploygon?
670 if (n == NULL || n->style != TR_WALL ||
671 (fabs(n->vertex[TR_SL].x - evl.x) > weps) ||
672 (fabs(n->vertex[TR_SR].x - evr.x) > weps) ||
673 (fabs(h - n->height) > weps))
674 {
675 if (close == true) {
677 dtVertex(svl.x, svl.y, svl.z);
678 dtVertex(svr.x, svr.y, svr.z);
679 dtVertex(svr.x, svr.y, svr.z + h);
680 dtVertex(svl.x, svl.y, svl.z + h);
681 dtEnd();
682
684 close = false;
685 } else {
686 GfError("Shape not open %s, line %d\n", __FILE__, __LINE__);
687 }
688 }
689
690 }
691
692 current = current->next;
693
694 } while (current != start);
695
696}
697
698
699void
701{
702 tCarElt *carElt;
703
704 // Create car collision objects.
705 carElt = car->carElt;
706 // The current car shape is a box...
707 car->shape = dtBox(carElt->_dimension_x, carElt->_dimension_y, carElt->_dimension_z);
708 dtCreateObject(car, car->shape);
709
710 car->collisionAware = 1;
711
712 // Create fixed track collision objects (just pit wall for now).
713 // TODO: car body/curbs collision.
714 // TODO: car body/flat wall collision (e.g. for pavement, sidewalk).
715 // TODO: define static objects in XML file/tTrack, collide with them as well.
716}
717
718
719void
721{
723 // Hmm, why is caching disabled, are our objects too fast, so it does not work?
724 // TODO: understand this and reconsider caching.
726 dtSetTolerance(0.001);
727
728 fixedid = 0;
729
730 if (track != NULL) {
731 tTrackSeg *firstleft = getFirstWallStart(track->seg, TR_SIDE_LFT);
732 tTrackSeg *firstright = getFirstWallStart(track->seg, TR_SIDE_RGT);
733
734 buildWalls(firstleft, TR_SIDE_LFT);
735 buildWalls(firstright, TR_SIDE_RGT);
736
737 unsigned int i;
738 for (i = 0; i < fixedid; i++) {
741 }
742 }
743}
744
745
746// TODO: Rename, because actually the dtProceed handles all solid managed objects, e.g. walls.
747void
749{
750 tCar *car;
751 tCarElt *carElt;
752 int i;
753
754 for (i = 0; i < s->_ncars; i++) {
755 carElt = s->cars[i];
756 if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
757 continue;
758 }
759
760 car = &(SimCarTable[carElt->index]);
761 dtSelectObject(car);
762 // Fit the bounding box around the car, statGC's are the static offsets.
764 // Place the bounding box such that it fits the car in the world.
765 dtMultMatrixf((const float *)(carElt->_posMat));
766 memset(&(car->VelColl), 0, sizeof(tPosd));
767 }
768
769 // Running the collision detection. If no collision is detected, call dtProceed.
770 // dtProceed just works if all objects are disjoint.
771 if (dtTest() == 0) {
772 dtProceed();
773 }
774
775 for (i = 0; i < s->_ncars; i++) {
776 carElt = s->cars[i];
777 if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
778 continue;
779 }
780 car = &(SimCarTable[carElt->index]);
781 if (car->collision & SEM_COLLISION_CAR) {
782 car->DynGCg.vel.x = car->VelColl.x;
783 car->DynGCg.vel.y = car->VelColl.y;
784 car->DynGCg.vel.az = car->VelColl.az;
785 }
786 }
787}
788
static Point p[4]
Definition Convex.cpp:54
static const double PI
#define SEM_COLLISION_Z
Definition car.h:697
#define RM_CAR_STATE_PIT
Car currently stopped in pits.
Definition car.h:211
#define SEM_COLLISION
Definition car.h:694
#define RM_CAR_STATE_NO_SIMU
Do not simulate the car.
Definition car.h:217
#define SEM_COLLISION_XYSCENE
Definition car.h:695
#define SEM_COLLISION_Z_CRASH
Definition car.h:698
struct CarElt tCarElt
Car structure (tCarElt).
#define RM_CAR_STATE_FINISH
Car having passed the finish line.
Definition car.h:210
#define SEM_COLLISION_CAR
Definition car.h:696
tdble simDammageFactor[]
T y
Definition v2_t.h:83
T x
Definition v2_t.h:83
const tdble BorderFriction
Definition collide.cpp:95
void SimCarCollideXYScene(tCar *car)
Definition collide.cpp:101
void SimCarCollideZ(tCar *car)
Definition collide.cpp:25
void SimCarCollideConfig(tCar *car, tTrack *track)
Definition collide.cpp:700
static void SimCarCollideResponse(void *, DtObjectRef obj1, DtObjectRef obj2, const DtCollData *collData)
Definition collide.cpp:195
void SimCarCollideInit(tTrack *track)
Definition collide.cpp:720
static unsigned int fixedid
Definition collide.cpp:519
static void SimCarWallCollideResponse(void *clientdata, DtObjectRef obj1, DtObjectRef obj2, const DtCollData *collData)
Definition collide.cpp:376
static tTrackSeg * getFirstWallStart(tTrackSeg *start, int side)
Definition collide.cpp:548
#define CAR_DAMMAGE
Definition collide.cpp:22
void SimCarCollideShutdown(int nbcars)
Definition collide.cpp:522
void buildWalls(tTrackSeg *start, int side)
Definition collide.cpp:583
static DtShapeRef fixedobjects[100]
Definition collide.cpp:517
void SimCarCollideCars(tSituation *s)
Definition collide.cpp:748
void SimCollideRemoveCar(tCar *car, int nbcars)
Definition collide.cpp:496
static jsJoystick * js[NUM_JOY]
float tdble
Floating point type used in TORCS.
Definition tgf.h:47
struct trackSeg tTrackSeg
Track segment (tTrackSeg) The segments can be straights (type TR_STR): (the track goes from the right...
void RtTrackGlobal2Local(tTrackSeg *segment, tdble X, tdble Y, tTrkLocPos *p, int type)
Convert global coordinates to a local track position.
Definition rttrack.cpp:298
tdble RtTrackHeightL(tTrkLocPos *p)
Returns the absolute height in meters of the road at the Local position p.
Definition rttrack.cpp:365
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
void RtTrackSurfaceNormalL(tTrkLocPos *p, t3Dd *norm)
Used to get the normal vector of the road (pointing upward).
Definition rttrack.cpp:567
struct Situation tSituation
cars situation used to inform the GUI and the drivers
static tRmRaceParam rp
tCar * SimCarTable
Definition simu.cpp:34
tdble rulesDamageFactor
Definition simu.cpp:40
void dtVertex(DtScalar x, DtScalar y, DtScalar z)
Definition C-api.cpp:124
void dtSetObjectResponse(DtObjectRef object, DtResponse response, DtResponseType type, void *client_data)
Definition C-api.cpp:261
DtShapeRef dtBox(DtScalar x, DtScalar y, DtScalar z)
Definition C-api.cpp:84
void dtCreateObject(DtObjectRef object, DtShapeRef shape)
Definition C-api.cpp:195
@ DT_SMART_RESPONSE
Definition solid.h:51
void * DtObjectRef
Definition solid.h:39
void dtBegin(DtPolyType type)
Definition C-api.cpp:118
void dtClearDefaultResponse()
Definition C-api.cpp:257
void dtEnd()
Definition C-api.cpp:119
void dtLoadIdentity()
Definition C-api.cpp:230
void dtDeleteShape(DtShapeRef shape)
Definition C-api.cpp:172
void dtSetTolerance(DtScalar tol)
Definition C-api.cpp:308
void dtSelectObject(DtObjectRef object)
Definition C-api.cpp:200
void dtSetDefaultResponse(DtResponse response, DtResponseType type, void *client_data)
Definition C-api.cpp:252
@ DT_POLYGON
Definition solid.h:44
void dtEndComplexShape()
Definition C-api.cpp:105
void dtMultMatrixf(const float *m)
Definition C-api.cpp:242
DtShapeRef dtNewComplexShape()
Definition C-api.cpp:100
void * DtShapeRef
Definition solid.h:40
void dtProceed()
Definition C-api.cpp:290
DtCount dtTest()
Definition C-api.cpp:348
void dtDeleteObject(DtObjectRef object)
Definition C-api.cpp:208
void dtClearObjectResponse(DtObjectRef object)
Definition C-api.cpp:266
void dtDisableCaching()
Definition C-api.cpp:306
tPublicCar pub
public
Definition car.h:461
int index
car index
Definition car.h:459
DtVector point1
Definition solid.h:56
DtVector point2
Definition solid.h:57
DtVector normal
Definition solid.h:58
tCarElt ** cars
list of cars
Definition raceman.h:89
3D point.
Definition tgf.h:114
tdble y
y coordinate
Definition tgf.h:116
tdble z
z coordinate
Definition tgf.h:117
tdble x
x coordinate
Definition tgf.h:115
int blocked
Definition carstruct.h:86
tPosd VelColl
Definition carstruct.h:70
tDynPt DynGCg
Definition carstruct.h:65
t3Dd Iinv
Definition carstruct.h:60
t3Dd collpos
Definition carstruct.h:81
t3Dd statGC
Definition carstruct.h:59
DtShapeRef shape
Definition carstruct.h:85
tCarElt * carElt
Definition carstruct.h:40
tDynPt DynGC
Definition carstruct.h:64
t3Dd normal
Definition carstruct.h:80
int collision
Definition carstruct.h:79
tTrkLocPos trkPos
Definition carstruct.h:72
tDynPt corner[4]
Definition carstruct.h:78
tdble Minv
Definition carstruct.h:57
int dammage
Definition carstruct.h:87
int collisionAware
Definition carstruct.h:91
Dynamic point structure.
Definition tgf.h:142
tPosd vel
velocity
Definition tgf.h:144
tPosd pos
position
Definition tgf.h:143
6 DOF position.
Definition tgf.h:129
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
sgMat4 posMat
position matrix
Definition car.h:195
Track structure.
Definition track.h:533
Location on the track in local coordinates.
Definition track.h:434
tdble toLeft
Distance (- to left, + to right) relative to left side of segment.
Definition track.h:449
tdble toRight
Distance (+ to left, - to right) relative to the right side of segment.
Definition track.h:447
tTrackSeg * seg
Track segment.
Definition track.h:435
tTrackSurface * surface
Barrier surface.
Definition track.h:280
vec2f normal
Definition track.h:281
tTrackSurface * surface
Segment surface.
Definition track.h:409
tdble height
Max height for curbs.
Definition track.h:380
t3Dd vertex[4]
Coordinates of the 4 corners of the segment.
Definition track.h:342
tTrackBarrier * barrier[2]
Segment barriers.
Definition track.h:410
struct trackSeg * next
Next segment.
Definition track.h:412
struct trackSeg * prev
Previous segment.
Definition track.h:413
int style
Border and barrier segments style:
Definition track.h:319
struct trackSeg * side[2]
Definition track.h:422
tdble kRebound
Coefficient of energy restitution.
Definition track.h:265
tdble kDammage
Dammages in case of collision.
Definition track.h:269
tdble kFriction
Coefficient of friction.
Definition track.h:264
#define MIN(x, y)
Definition tgf.h:56
#define SIGN(x)
Sign of the expression.
Definition tgf.h:77
#define MAX(x, y)
Definition tgf.h:52
#define GfError
Definition tgf.h:350
#define RAD2DEG(x)
Radian to degree conversion.
Definition tgf.h:74
#define TR_SIDE_RGT
Definition track.h:419
#define TR_EL
End-Left corner.
Definition track.h:351
#define TR_LPOS_SEGMENT
Relative to the segment which the point is located, including border and sides, mostly used for conta...
Definition track.h:443
struct trackBarrier tTrackBarrier
Barrier.
#define TR_SIDE_LFT
Definition track.h:418
#define TR_LPOS_TRACK
Local position relative to the outermost barriers, mostly used for collision detection with barrier.
Definition track.h:444
#define TR_ER
End_Right corner.
Definition track.h:352
#define TR_SL
Start-Left corner.
Definition track.h:349
#define TR_WALL
Wall (barrier only)
Definition track.h:328
#define TR_SR
Start-Right corner.
Definition track.h:350
int track(tModInfo *modInfo)
Definition trackitf.cpp:85