Exemplo n.º 1
0
/* Initial configuration */
void
SimConfig(tCarElt *carElt, tRmInfo* ReInfo)
{
    tCar *car = &(SimCarTable[carElt->index]);

    memset(car, 0, sizeof(tCar));

    car->carElt = carElt;
    car->DynGCg = car->DynGC = carElt->_DynGC;

    car->trkPos = carElt->_trkPos;
    car->ctrl   = &carElt->ctrl;
    car->params = carElt->_carHandle;
    car->ReInfo = ReInfo;
    SimCarConfig(car);

    SimCarCollideConfig(car);
    sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
					RAD2DEG(carElt->_yaw), RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));

	sgEulerToQuat (car->posQuat, -RAD2DEG(carElt->_yaw), RAD2DEG(carElt->_pitch), RAD2DEG(carElt->_roll));
	sgQuatToMatrix (car->posMat, car->posQuat);

	simu_total_time = 0.0f;
	simu_init_time = GfTimeClock();
	//sgMakeRotMat4 (car->posMat, RAD2DEG(carElt->_yaw), RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));

}
Exemplo n.º 2
0
/* Initial configuration */
void
SimConfig(tCarElt *carElt)
{
    tCar *car = &(SimCarTable[carElt->index]);

    memset(car, 0, sizeof(tCar));

    car->carElt = carElt;
    car->DynGCg = car->DynGC = carElt->_DynGC;
    car->trkPos = carElt->_trkPos;
    car->ctrl   = &carElt->ctrl;
    car->params = carElt->_carHandle;

    SimCarConfig(car);

    SimCarCollideConfig(car, PTrack);
    sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
		    (float) RAD2DEG(carElt->_yaw), (float) RAD2DEG(carElt->_roll), (float) RAD2DEG(carElt->_pitch));
}
Exemplo n.º 3
0
// Collision response for walls.
// TODO: Separate common code with car-car collision response.
static void SimCarWallCollideResponse(void *clientdata, DtObjectRef obj1, DtObjectRef obj2, const DtCollData *collData)
{
	tCar* car;		// The car colliding with the wall.
	float nsign;	// Normal direction correction for collision plane.
	sgVec2 p;		// Cars collision point delivered by solid.

	// TODO: If other movable objects are added which could collide with the wall, it will be
	// necessary to validate if the object is actually a car.

	if (obj1 == clientdata) {
		car = (tCar*) obj2;
		nsign = -1.0f;
		p[0] = (float) collData->point2[0];
		p[1] = (float) collData->point2[1];
	} else {
		car = (tCar*) obj1;
		nsign = 1.0f;
		p[0] = (float) collData->point1[0];
		p[1] = (float) collData->point1[1];
	}

	sgVec2 n;		// Collision normal delivered by solid, corrected such that it points away from the wall.
	n[0] = nsign * (float) collData->normal[0];
	n[1] = nsign * (float) collData->normal[1];
	float pdist = sgLengthVec2(n);	// Distance of collision points.
	sgNormaliseVec2(n);

	sgVec2 r;
	sgSubVec2(r, p, (const float*)&(car->statGC));

	tCarElt *carElt = car->carElt;

	sgVec2 vp;		// Speed of car collision point in global frame of reference.
	sgVec2 rg;		// raduis oriented in global coordinates, still relative to CG (rotated aroung CG).

	float sina = sin(carElt->_yaw);
	float cosa = cos(carElt->_yaw);
	rg[0] = r[0]*cosa - r[1]*sina;
	rg[1] = r[0]*sina + r[1]*cosa;

	vp[0] = car->DynGCg.vel.x - car->DynGCg.vel.az * rg[1];
	vp[1] = car->DynGCg.vel.y + car->DynGCg.vel.az * rg[0];

	sgVec2 tmpv;
	static const float CAR_MIN_MOVEMENT = 0.02f;
	static const float CAR_MAX_MOVEMENT = 0.05f;
	sgScaleVec2(tmpv, n, MIN(MAX(pdist, CAR_MIN_MOVEMENT), CAR_MAX_MOVEMENT));
	if (car->blocked == 0) {
		sgAddVec2((float*)&(car->DynGCg.pos), tmpv);
		car->blocked = 1;
    }

	// Doing no dammage and correction if the cars are moving out of each other.
	if (sgScalarProductVec2(vp, n) > 0) {
		return;
	}

	float rp = sgScalarProductVec2(rg, n);

	// Pesudo cross product to find out if we are left or right.
	// TODO: SIGN, scrap value?
	float rpsign = n[0]*rg[1] - n[1]*rg[0];

	const float e = 1.0f;	// energy restitution
	float j = -(1.0f + e) * sgScalarProductVec2(vp, n) / (car->Minv + rp * rp * car->Iinv.z);
	const float ROT_K = 0.5f;

	// Damage.
	tdble damFactor, atmp;
	atmp = atan2(r[1], r[0]);
	if (fabs(atmp) < (PI / 3.0)) {
		// Front collision gives more damage.
		damFactor = 1.5f;
	} else {
		// Rear collision gives less damage.
		damFactor = 1.0f;
	}

	static const float DMGFACTOR = 0.00002f;
	if ((car->carElt->_state & RM_CAR_STATE_FINISH) == 0) {
		car->dammage += (int)(CAR_DAMMAGE * (DMGFACTOR*j*j) * damFactor * simDammageFactor[car->carElt->_skillLevel]);
	}

	sgScaleVec2(tmpv, n, j * car->Minv);
	sgVec2 v2a;

	if (car->collision & SEM_COLLISION_CAR) {
		sgAddVec2(v2a, (const float*)&(car->VelColl.x), tmpv);
		car->VelColl.az = car->VelColl.az + j * rp * rpsign * car->Iinv.z * ROT_K;
	} else {
		sgAddVec2(v2a, (const float*)&(car->DynGCg.vel), tmpv);
		car->VelColl.az = car->DynGCg.vel.az + j * rp * rpsign * car->Iinv.z * ROT_K;
	}

	static float VELMAX = 3.0f;
	if (fabs(car->VelColl.az) > VELMAX) {
		car->VelColl.az = SIGN(car->VelColl.az) * VELMAX;
	}

	sgCopyVec2((float*)&(car->VelColl.x), v2a);

	// Move the car for the collision lib.
	sgMakeCoordMat4(carElt->pub.posMat, car->DynGCg.pos.x, car->DynGCg.pos.y,
					car->DynGCg.pos.z - carElt->_statGC_z, RAD2DEG(carElt->_yaw),
					RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));
	dtSelectObject(car);
	dtLoadIdentity();
	dtTranslate(-carElt->_statGC_x, -carElt->_statGC_y, 0.0f);
	dtMultMatrixf((const float *)(carElt->_posMat));

	car->collision |= SEM_COLLISION_CAR;
}
Exemplo n.º 4
0
static void SimCarCollideResponse(void * /*dummy*/, DtObjectRef obj1, DtObjectRef obj2, const DtCollData *collData)
{
	sgVec2 n;		// Collision normal delivered by solid: Global(point1) - Global(point2)
	tCar *car[2];	// The cars.
	sgVec2 p[2];	// Collision points delivered by solid, in body local coordinates.
	sgVec2 r[2];	// Collision point relative to center of gravity.
	sgVec2 vp[2];	// Speed of collision point in world coordinate system.
	sgVec3 pt[2];	// Collision points in global coordinates.

	int i;

	car[0] = (tCar*)obj1;
	car[1] = (tCar*)obj2;

	// Handle cars collisions during pit stops as well.
	static const int NO_SIMU_WITHOUT_PIT = RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT;

	if ((car[0]->carElt->_state & NO_SIMU_WITHOUT_PIT) ||
		(car[1]->carElt->_state & NO_SIMU_WITHOUT_PIT))
	{
		return;
	}

    if (car[0]->carElt->index < car[1]->carElt->index) {
		// vector conversion from double to float.
		p[0][0] = (float)collData->point1[0];
		p[0][1] = (float)collData->point1[1];
		p[1][0] = (float)collData->point2[0];
		p[1][1] = (float)collData->point2[1];
		n[0]  = (float)collData->normal[0];
		n[1]  = (float)collData->normal[1];
    } else {
		// swap the cars (not the same for the simu).
		car[0] = (tCar*)obj2;
		car[1] = (tCar*)obj1;
		p[0][0] = (float)collData->point2[0];
		p[0][1] = (float)collData->point2[1];
		p[1][0] = (float)collData->point1[0];
		p[1][1] = (float)collData->point1[1];
		n[0]  = -(float)collData->normal[0];
		n[1]  = -(float)collData->normal[1];
	}

	sgNormaliseVec2(n);

	sgVec2 rg[2];	// radius oriented in global coordinates, still relative to CG (rotated aroung CG).
	tCarElt *carElt;

	for (i = 0; i < 2; i++) {
		// vector GP (Center of gravity to collision point). p1 and p2 are delivered from solid as
		// points in the car coordinate system.
		sgSubVec2(r[i], p[i], (const float*)&(car[i]->statGC));

		// Speed of collision points, linear motion of center of gravity (CG) plus rotational
		// motion around the CG.
		carElt = car[i]->carElt;
		float sina = sin(carElt->_yaw);
		float cosa = cos(carElt->_yaw);
		rg[i][0] = r[i][0]*cosa - r[i][1]*sina;
		rg[i][1] = r[i][0]*sina + r[i][1]*cosa;

		vp[i][0] = car[i]->DynGCg.vel.x - car[i]->DynGCg.vel.az * rg[i][1];
		vp[i][1] = car[i]->DynGCg.vel.y + car[i]->DynGCg.vel.az * rg[i][0];
	}

	// Relative speed of collision points.
	sgVec2 v1ab;
	sgSubVec2(v1ab, vp[0], vp[1]);

	// try to separate the cars. The computation is necessary because dtProceed is not called till
	// the collision is resolved. 
	for (i = 0; i < 2; i++) {
		sgCopyVec2(pt[i], r[i]);
		pt[i][2] = 0.0f;
		// Transform points relative to cars local coordinate system into global coordinates.
		sgFullXformPnt3(pt[i], car[i]->carElt->_posMat);
	}

	// Compute distance of collision points.
	sgVec3 pab;
	sgSubVec2(pab, pt[1], pt[0]);
	float distpab = sgLengthVec2(pab);

	sgVec2 tmpv;
	
	sgScaleVec2(tmpv, n, MIN(distpab, 0.05));
	// No "for" loop here because of subtle difference AddVec/SubVec. 
	if (car[0]->blocked == 0 && !(car[0]->carElt->_state & RM_CAR_STATE_NO_SIMU)) {
		sgAddVec2((float*)&(car[0]->DynGCg.pos), tmpv);
		car[0]->blocked = 1;
    }
	if (car[1]->blocked == 0 && !(car[1]->carElt->_state & RM_CAR_STATE_NO_SIMU)) {
		sgSubVec2((float*)&(car[1]->DynGCg.pos), tmpv);
		car[1]->blocked = 1;
    }

	// Doing no dammage and correction if the cars are moving out of each other.
	if (sgScalarProductVec2(v1ab, n) > 0) {
		return;
	}

	// impulse.
	float rpn[2];
	rpn[0] = sgScalarProductVec2(rg[0], n);
	rpn[1] = sgScalarProductVec2(rg[1], n);

	// Pseudo cross product to find out if we are left or right.
	// TODO: SIGN, scrap value?
	float rpsign[2];
	rpsign[0] =  n[0]*rg[0][1] - n[1]*rg[0][0];
	rpsign[1] = -n[0]*rg[1][1] + n[1]*rg[1][0];

	const float e = 1.0f;	// energy restitution

	float j = -(1.0f + e) * sgScalarProductVec2(v1ab, n) /
		((car[0]->Minv + car[1]->Minv) +
		rpn[0] * rpn[0] * car[0]->Iinv.z + rpn[1] * rpn[1] * car[1]->Iinv.z);

	for (i = 0; i < 2; i++) {
		if (car[i]->carElt->_state & RM_CAR_STATE_NO_SIMU) {
			continue;
		}

		// Damage.
		tdble damFactor, atmp;
		atmp = atan2(r[i][1], r[i][0]);
		if (fabs(atmp) < (PI / 3.0)) {
			// Front collision gives more damage.
			damFactor = 1.5f;
		} else {
			// Rear collision gives less damage.
			damFactor = 1.0f;
		}

		if ((car[i]->carElt->_state & RM_CAR_STATE_FINISH) == 0) {
			car[i]->dammage += (int)(CAR_DAMMAGE * fabs(j) * damFactor * simDammageFactor[car[i]->carElt->_skillLevel]);
		}

		// Compute collision velocity.
		const float ROT_K = 1.0f;

		float js = (i == 0) ? j : -j;
		sgScaleVec2(tmpv, n, js * car[i]->Minv);
		sgVec2 v2a;

		if (car[i]->collision & SEM_COLLISION_CAR) {
			sgAddVec2(v2a, (const float*)&(car[i]->VelColl.x), tmpv);
			car[i]->VelColl.az = car[i]->VelColl.az + js * rpsign[i] * rpn[i] * car[i]->Iinv.z * ROT_K;
		} else {
			sgAddVec2(v2a, (const float*)&(car[i]->DynGCg.vel), tmpv);
			car[i]->VelColl.az = car[i]->DynGCg.vel.az + js * rpsign[i] * rpn[i] * car[i]->Iinv.z * ROT_K;
		}

		static float VELMAX = 3.0f;
		if (fabs(car[i]->VelColl.az) > VELMAX) {
			car[i]->VelColl.az = SIGN(car[i]->VelColl.az) * VELMAX;
		}

		sgCopyVec2((float*)&(car[i]->VelColl.x), v2a);

		// Move the car for the collision lib.
		tCarElt *carElt = car[i]->carElt;
		sgMakeCoordMat4(carElt->pub.posMat, car[i]->DynGCg.pos.x, car[i]->DynGCg.pos.y,
						car[i]->DynGCg.pos.z - carElt->_statGC_z, RAD2DEG(carElt->_yaw),
						RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));
		dtSelectObject(car[i]);
		dtLoadIdentity();
		dtTranslate(-carElt->_statGC_x, -carElt->_statGC_y, 0.0f);
		dtMultMatrixf((const float *)(carElt->_posMat));

		car[i]->collision |= SEM_COLLISION_CAR;
	}
}
Exemplo n.º 5
0
void
SimUpdate(tSituation *s, double deltaTime, int telemetry)
{
    int		i;
    int		ncar;
    tCarElt 	*carElt;
    tCar 	*car;
    sgVec3	P;
	static const float UPSIDE_DOWN_TIMEOUT = 5.0f;

	double timestamp_start = GfTimeClock();
    SimDeltaTime = deltaTime;
    SimTelemetry = 0;//telemetry;
    for (ncar = 0; ncar < s->_ncars; ncar++) {
		SimCarTable[ncar].collision = 0;
		SimCarTable[ncar].blocked = 0;
    }
    
    for (ncar = 0; ncar < s->_ncars; ncar++) {
		car = &(SimCarTable[ncar]);
		carElt = car->carElt;

		if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
			RemoveCar(car, s);
			continue;
		} else if (((s->_maxDammage) && (car->dammage > s->_maxDammage)) ||
				   (car->fuel == 0) ||
				   (car->upside_down_timer > UPSIDE_DOWN_TIMEOUT) ||
				   (car->carElt->_state & RM_CAR_STATE_ELIMINATED))  {
			RemoveCar(car, s);
			if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
				continue;
			}
		}
	
		if (s->_raceState & RM_RACE_PRESTART) {
			car->ctrl->gear = 0;
		}
	



		CHECK(car);
		ctrlCheck(car);
		CHECK(car);
		SimSteerUpdate(car);
		CHECK(car);
		SimGearboxUpdate(car);
		CHECK(car);
		SimEngineUpdateTq(car);
		CHECK(car);


		if (!(s->_raceState & RM_RACE_PRESTART)) {

				SimCarUpdateWheelPos(car);
			CHECK(car);
				SimBrakeSystemUpdate(car);
			CHECK(car);
				SimAeroUpdate(car, s);
			CHECK(car);
				for (i = 0; i < 2; i++){
				SimWingUpdate(car, i, s);
			}
			CHECK(car);
				for (i = 0; i < 4; i++){
				SimWheelUpdateRide(car, i);
			}
			CHECK(car);
				for (i = 0; i < 2; i++){
				SimAxleUpdate(car, i);
			}
			CHECK(car);
				for (i = 0; i < 4; i++){
				SimWheelUpdateForce(car, i);
			}
			CHECK(car);
		}
		SimTransmissionUpdate(car);
		CHECK(car);

		if (!(s->_raceState & RM_RACE_PRESTART)) {
				SimWheelUpdateRotation(car);
			CHECK(car);
				SimCarUpdate(car, s);
			CHECK(car);
		}
    }

    SimCarCollideCars(s);

    /* printf ("%f - ", s->currentTime); */
    
    for (ncar = 0; ncar < s->_ncars; ncar++) {
		car = &(SimCarTable[ncar]);
		CHECK(car);
		carElt = car->carElt;

		if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
			continue;
		}

		CHECK(car);
		SimCarUpdate2(car, s);

		/* copy back the data to carElt */

		carElt->pub.DynGC = car->DynGC;
		carElt->pub.DynGCg = car->DynGCg;
#if 0
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
						RAD2DEG(carElt->_yaw), RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));
#else
		sgQuatToMatrix (carElt->pub.posMat, car->posQuat);
		carElt->pub.posMat[3][0] = car->DynGCg.pos.x;
		carElt->pub.posMat[3][1] = car->DynGCg.pos.y;
		carElt->pub.posMat[3][2] = car->DynGCg.pos.z - carElt->_statGC_z;
		carElt->pub.posMat[0][3] =  SG_ZERO ;
		carElt->pub.posMat[1][3] =  SG_ZERO ;
		carElt->pub.posMat[2][3] =  SG_ZERO ;
		carElt->pub.posMat[3][3] =  SG_ONE ;
#endif
		carElt->_trkPos = car->trkPos;
		for (i = 0; i < 4; i++) {
			carElt->priv.wheel[i].relPos = car->wheel[i].relPos;
			carElt->_wheelSeg(i) = car->wheel[i].trkPos.seg;
			carElt->_brakeTemp(i) = car->wheel[i].brake.temp;
			carElt->pub.corner[i] = car->corner[i].pos;
		}
		carElt->_gear = car->transmission.gearbox.gear;
		carElt->_enginerpm = car->engine.rads;
		carElt->_fuel = car->fuel;
		carElt->priv.collision |= car->collision;
		carElt->_dammage = car->dammage;

		P[0] = -carElt->_statGC_x;
		P[1] = -carElt->_statGC_y;
		P[2] = -carElt->_statGC_z;
		sgXformPnt3(P, carElt->_posMat);
		carElt->_pos_X = P[0];
		carElt->_pos_Y = P[1];
		carElt->_pos_Z = P[2];
	}
	simu_total_time +=  GfTimeClock() - timestamp_start;
}
Exemplo n.º 6
0
static void
RemoveCar(tCar *car, tSituation *s)
{
    int		i;
    tCarElt 	*carElt;
    tTrkLocPos	trkPos;
    int		trkFlag;
    tdble	travelTime;
    tdble	dang;

#define PULL_Z_OFFSET 3.0
#define PULL_SPD      0.5

    carElt = car->carElt;

    if (carElt->_state & RM_CAR_STATE_PULLUP) {
		carElt->_pos_Z += car->restPos.vel.z * SimDeltaTime;
		carElt->_yaw += car->restPos.vel.az * SimDeltaTime;
		carElt->_roll += car->restPos.vel.ax * SimDeltaTime;
		carElt->_pitch += car->restPos.vel.ay * SimDeltaTime;
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
						RAD2DEG(carElt->_yaw), RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));

		if (carElt->_pos_Z > (car->restPos.pos.z + PULL_Z_OFFSET)) {
			carElt->_state &= ~RM_CAR_STATE_PULLUP;
			carElt->_state |= RM_CAR_STATE_PULLSIDE;

			travelTime = DIST(car->restPos.pos.x, car->restPos.pos.y, carElt->_pos_X, carElt->_pos_Y) / PULL_SPD;
			car->restPos.vel.x = (car->restPos.pos.x - carElt->_pos_X) / travelTime;
			car->restPos.vel.y = (car->restPos.pos.y - carElt->_pos_Y) / travelTime;
		}
		return;
    }
    

    if (carElt->_state & RM_CAR_STATE_PULLSIDE) {
		carElt->_pos_X += car->restPos.vel.x * SimDeltaTime;
		carElt->_pos_Y += car->restPos.vel.y * SimDeltaTime;
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
						RAD2DEG(carElt->_yaw), RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));

		if ((fabs(car->restPos.pos.x - carElt->_pos_X) < 0.5) && (fabs(car->restPos.pos.y - carElt->_pos_Y) < 0.5)) {
			carElt->_state &= ~RM_CAR_STATE_PULLSIDE;
			carElt->_state |= RM_CAR_STATE_PULLDN;
		}
		return;
    }

    if (carElt->_state & RM_CAR_STATE_PULLDN) {
		carElt->_pos_Z -= car->restPos.vel.z * SimDeltaTime;
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
						RAD2DEG(carElt->_yaw), RAD2DEG(carElt->_roll), RAD2DEG(carElt->_pitch));

		if (carElt->_pos_Z < car->restPos.pos.z) {
			carElt->_state &= ~RM_CAR_STATE_PULLDN;
			carElt->_state |= RM_CAR_STATE_OUT;
		}
		return;
    }

    if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
		return;
    }

    if ((s->_maxDammage) && (car->dammage > s->_maxDammage)) {
		carElt->_state |= RM_CAR_STATE_BROKEN;
    } else {
		carElt->_state |= RM_CAR_STATE_OUTOFGAS;
    }
    carElt->_gear = car->transmission.gearbox.gear = 0;
    carElt->_enginerpm = car->engine.rads = 0;
  
    if (!(carElt->_state & RM_CAR_STATE_DNF)) {
		if (fabs(carElt->_speed_x) > 1.0) {
			return;
		}
    }
    carElt->_state |= RM_CAR_STATE_PULLUP;

    carElt->priv.collision = car->collision = 0;
    for(i = 0; i < 4; i++) {
		carElt->_skid[i] = 0;
		carElt->_wheelSpinVel(i) = 0;
		carElt->_brakeTemp(i) = 0;
    }
    carElt->pub.DynGC = car->DynGC;
    carElt->_speed_x = 0;

    /* compute the target zone for the wrecked car */
    trkPos = car->trkPos;
    if (trkPos.toRight >  trkPos.seg->width / 2.0) {
		while (trkPos.seg->lside != 0) {
			trkPos.seg = trkPos.seg->lside;
		}
		trkPos.toLeft = -3.0;
		trkFlag = TR_TOLEFT;
    } else {
		while (trkPos.seg->rside != 0) {
			trkPos.seg = trkPos.seg->rside;
		}
		trkPos.toRight = -3.0;
		trkFlag = TR_TORIGHT;
    }

    trkPos.type = TR_LPOS_SEGMENT;
    RtTrackLocal2Global(&trkPos, &(car->restPos.pos.x), &(car->restPos.pos.y), trkFlag);
    car->restPos.pos.z = RtTrackHeightL(&trkPos) + carElt->_statGC_z;
    car->restPos.pos.az = RtTrackSideTgAngleL(&trkPos);
    car->restPos.pos.ax = 0;
    car->restPos.pos.ay = 0;

    car->restPos.vel.z = PULL_SPD;
    travelTime = (car->restPos.pos.z + PULL_Z_OFFSET - carElt->_pos_Z) / car->restPos.vel.z;
    dang = car->restPos.pos.az - carElt->_yaw;
    NORM_PI_PI(dang);
    car->restPos.vel.az = dang / travelTime;
    dang = car->restPos.pos.ax - carElt->_roll;
    NORM_PI_PI(dang);
    car->restPos.vel.ax = dang / travelTime;
    dang = car->restPos.pos.ay - carElt->_pitch;
    NORM_PI_PI(dang);
    car->restPos.vel.ay = dang / travelTime;

}
Exemplo n.º 7
0
void
SimUpdateSingleCar(int index, double deltaTime,tSituation *s)
{
	int i;
	//int ncar;
	tCarElt *carElt;
	tCar *car;
	
	SimDeltaTime = (tdble) deltaTime;
	SimCarTable[index].collision = 0;
	SimCarTable[index].blocked = 0;
	
	car = &(SimCarTable[index]);
	carElt = car->carElt;

	CHECK(car);
	ctrlCheck(car);
	CHECK(car);
	SimSteerUpdate(car);
	CHECK(car);
	SimGearboxUpdate(car);
	CHECK(car);
	SimEngineUpdateTq(car);
	CHECK(car);
	
	SimCarUpdateWheelPos(car);
	CHECK(car);
	SimBrakeSystemUpdate(car);
	CHECK(car);
	SimAeroUpdate(car, s);
	CHECK(car);
	for (i = 0; i < 2; i++){
		SimWingUpdate(car, i, s);
	}
	CHECK(car);
	for (i = 0; i < 4; i++){
		SimWheelUpdateRide(car, i);
	}
	CHECK(car);
	for (i = 0; i < 2; i++){
		SimAxleUpdate(car, i);
	}
	CHECK(car);
	for (i = 0; i < 4; i++){
		SimWheelUpdateForce(car, i);
	}
	CHECK(car);
	SimTransmissionUpdate(car);
	CHECK(car);
	SimWheelUpdateRotation(car);
	CHECK(car);
	SimCarUpdate(car, s);
	CHECK(car);
	
	/* copy back the data to carElt */

	carElt->pub.DynGC = car->DynGC;
	carElt->pub.DynGCg = car->DynGCg;
	sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
					(float) RAD2DEG(carElt->_yaw), (float) RAD2DEG(carElt->_roll), (float) RAD2DEG(carElt->_pitch));
	carElt->_trkPos = car->trkPos;
	for (i = 0; i < 4; i++) {
		carElt->priv.wheel[i].relPos = car->wheel[i].relPos;
		carElt->_wheelSeg(i) = car->wheel[i].trkPos.seg;
		carElt->_brakeTemp(i) = car->wheel[i].brake.temp;
		carElt->pub.corner[i] = car->corner[i].pos;
	}
	carElt->_gear = car->transmission.gearbox.gear;
	carElt->_enginerpm = car->engine.rads;
	carElt->_fuel = car->fuel;
	carElt->priv.collision |= car->collision;
	carElt->_dammage = car->dammage;
}
Exemplo n.º 8
0
void
SimUpdate(tSituation *s, double deltaTime)
{
	int i;
	int ncar;
	tCarElt *carElt;
	tCar *car;
	
	SimDeltaTime = (tdble) deltaTime;
	for (ncar = 0; ncar < s->_ncars; ncar++) {
		SimCarTable[ncar].collision = 0;
		SimCarTable[ncar].blocked = 0;
	}
	
	for (ncar = 0; ncar < s->_ncars; ncar++) {
		car = &(SimCarTable[ncar]);
		carElt = car->carElt;
	
		if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
			RemoveCar(car, s);
			continue;
		} else if (((s->_maxDammage) && (car->dammage > s->_maxDammage)) ||
			(car->fuel == 0) ||
			(car->carElt->_state & RM_CAR_STATE_ELIMINATED))  {
			RemoveCar(car, s);
			if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
				continue;
			}
		}
	
		if (s->_raceState & RM_RACE_PRESTART && 
				(car->carElt->_skillLevel < 3 || !(s->_features & RM_FEATURE_PENALTIES))) {
			car->ctrl->brakeCmd = 1.0;
			car->ctrl->clutchCmd = 1.0;
		}
	
		CHECK(car);
		ctrlCheck(car);
		CHECK(car);
		SimSteerUpdate(car);
		CHECK(car);
		SimGearboxUpdate(car);
		CHECK(car);
		SimEngineUpdateTq(car);
		CHECK(car);
	
		if (!(s->_raceState & RM_RACE_PRESTART) || car->carElt->_skillLevel == 3) {
	
			SimCarUpdateWheelPos(car);
			CHECK(car);
			SimBrakeSystemUpdate(car);
			CHECK(car);
			SimAeroUpdate(car, s);
			CHECK(car);
			for (i = 0; i < 2; i++){
				SimWingUpdate(car, i, s);
			}
			CHECK(car);
			for (i = 0; i < 4; i++){
				SimWheelUpdateRide(car, i);
			}
			CHECK(car);
			for (i = 0; i < 2; i++){
				SimAxleUpdate(car, i);
			}
			CHECK(car);
			for (i = 0; i < 4; i++){
				SimWheelUpdateForce(car, i);
			}
			CHECK(car);
			SimTransmissionUpdate(car);
			CHECK(car);
			SimWheelUpdateRotation(car);
			CHECK(car);
			SimCarUpdate(car, s);
			CHECK(car);
		} else {
			SimTransmissionUpdate(car);
			SimEngineUpdateRpm(car, 0.0);
		}
	}
	
	SimCarCollideCars(s);
	
	/* printf ("%f - ", s->currentTime); */
	
	for (ncar = 0; ncar < s->_ncars; ncar++) {
		car = &(SimCarTable[ncar]);
		CHECK(car);
		carElt = car->carElt;
	
		if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
			continue;
		}
	
		CHECK(car);
		SimCarUpdate2(car, s); /* telemetry */
	
		/* copy back the data to carElt */
	
		carElt->pub.DynGC = car->DynGC;
		carElt->pub.DynGCg = car->DynGCg;
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
				(float) RAD2DEG(carElt->_yaw), (float) RAD2DEG(carElt->_roll), (float) RAD2DEG(carElt->_pitch));
		carElt->_trkPos = car->trkPos;
		for (i = 0; i < 4; i++) {
			carElt->priv.wheel[i].relPos = car->wheel[i].relPos;
			carElt->_wheelSeg(i) = car->wheel[i].trkPos.seg;
			carElt->_brakeTemp(i) = car->wheel[i].brake.temp;
			carElt->pub.corner[i] = car->corner[i].pos;
		}
		carElt->_gear = car->transmission.gearbox.gear;
		carElt->_enginerpm = car->engine.rads;
		carElt->_fuel = car->fuel;
		carElt->priv.collision |= car->collision;
		carElt->_dammage = car->dammage;
	}
}
Exemplo n.º 9
0
static void
RemoveCar(tCar *car, tSituation *s)
{
	int i;
	tCarElt *carElt;
	tTrkLocPos trkPos;
	int trkFlag;
	tdble travelTime;
	tdble dang;

	static tdble PULL_Z_OFFSET = 3.0;
	static tdble PULL_SPD = 0.5;

	carElt = car->carElt;

	if (carElt->_state & RM_CAR_STATE_PULLUP) {
		carElt->_pos_Z += car->restPos.vel.z * SimDeltaTime;
		carElt->_yaw += car->restPos.vel.az * SimDeltaTime;
		carElt->_roll += car->restPos.vel.ax * SimDeltaTime;
		carElt->_pitch += car->restPos.vel.ay * SimDeltaTime;
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
			(float) RAD2DEG(carElt->_yaw), (float) RAD2DEG(carElt->_roll), (float) RAD2DEG(carElt->_pitch));

		if (carElt->_pos_Z > (car->restPos.pos.z + PULL_Z_OFFSET)) {
			carElt->_state &= ~RM_CAR_STATE_PULLUP;
			carElt->_state |= RM_CAR_STATE_PULLSIDE;

			// Moved pullside velocity computation down due to floating point error accumulation.
		}
		return;
	}


	if (carElt->_state & RM_CAR_STATE_PULLSIDE) {
		// Recompute speed to avoid missing the parking point due to error accumulation (the pos might be
		// in the 0-10000 range, depending on the track and vel*dt is around 0-0.001, so basically all
		// but the most significant digits are lost under bad conditions, happens e.g on e-track-4).
		// Should not lead to a division by zero because the pullside process stops if the car is within
		// [0.5, 0.5]. Do not move it back.
		travelTime = DIST(car->restPos.pos.x, car->restPos.pos.y, carElt->_pos_X, carElt->_pos_Y) / PULL_SPD;
		car->restPos.vel.x = (car->restPos.pos.x - carElt->_pos_X) / travelTime;
		car->restPos.vel.y = (car->restPos.pos.y - carElt->_pos_Y) / travelTime;

		carElt->_pos_X += car->restPos.vel.x * SimDeltaTime;
		carElt->_pos_Y += car->restPos.vel.y * SimDeltaTime;
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
			(float) RAD2DEG(carElt->_yaw), (float) RAD2DEG(carElt->_roll), (float) RAD2DEG(carElt->_pitch));

		if ((fabs(car->restPos.pos.x - carElt->_pos_X) < 0.5) && (fabs(car->restPos.pos.y - carElt->_pos_Y) < 0.5)) {
			carElt->_state &= ~RM_CAR_STATE_PULLSIDE;
			carElt->_state |= RM_CAR_STATE_PULLDN;
		}
		return;
	}


	if (carElt->_state & RM_CAR_STATE_PULLDN) {
		carElt->_pos_Z -= car->restPos.vel.z * SimDeltaTime;
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
			(float) RAD2DEG(carElt->_yaw), (float) RAD2DEG(carElt->_roll), (float) RAD2DEG(carElt->_pitch));

		if (carElt->_pos_Z < car->restPos.pos.z) {
			carElt->_state &= ~RM_CAR_STATE_PULLDN;
			carElt->_state |= RM_CAR_STATE_OUT;
		}
		return;
	}


	if (carElt->_state & (RM_CAR_STATE_NO_SIMU & ~RM_CAR_STATE_PIT)) {
		return;
	}

	if (carElt->_state & RM_CAR_STATE_PIT) {
		if ((s->_maxDammage) && (car->dammage > s->_maxDammage)) {
			// Broken during pit stop.
			carElt->_state &= ~RM_CAR_STATE_PIT;
			carElt->_pit->pitCarIndex = TR_PIT_STATE_FREE;
		} else {
			return;
		}
	}

	if ((s->_maxDammage) && (car->dammage > s->_maxDammage)) {
		carElt->_state |= RM_CAR_STATE_BROKEN;
	} else {
		carElt->_state |= RM_CAR_STATE_OUTOFGAS;
	}

	carElt->_gear = car->transmission.gearbox.gear = 0;
	carElt->_enginerpm = car->engine.rads = 0;

	if (!(carElt->_state & RM_CAR_STATE_DNF)) {
		if (fabs(carElt->_speed_x) > 1.0) {
			return;
		}
	}

	carElt->_state |= RM_CAR_STATE_PULLUP;
	// RM_CAR_STATE_NO_SIMU evaluates to > 0 from here, so we remove the car from the
	// collision detection.
	SimCollideRemoveCar(car, s->_ncars);

	carElt->priv.collision = car->collision = 0;
	for(i = 0; i < 4; i++) {
		carElt->_skid[i] = 0;
		carElt->_wheelSpinVel(i) = 0;
		carElt->_brakeTemp(i) = 0;
	}

	carElt->pub.DynGC = car->DynGC;
	carElt->_speed_x = 0;

	// Compute the target zone for the wrecked car.
	trkPos = car->trkPos;
	if (trkPos.toRight >  trkPos.seg->width / 2.0) {
		while (trkPos.seg->lside != 0) {
			trkPos.seg = trkPos.seg->lside;
		}
		trkPos.toLeft = -3.0;
		trkFlag = TR_TOLEFT;
	} else {
		while (trkPos.seg->rside != 0) {
			trkPos.seg = trkPos.seg->rside;
		}
		trkPos.toRight = -3.0;
		trkFlag = TR_TORIGHT;
	}

	trkPos.type = TR_LPOS_SEGMENT;
	RtTrackLocal2Global(&trkPos, &(car->restPos.pos.x), &(car->restPos.pos.y), trkFlag);
	car->restPos.pos.z = RtTrackHeightL(&trkPos) + carElt->_statGC_z;
	car->restPos.pos.az = RtTrackSideTgAngleL(&trkPos);
	car->restPos.pos.ax = 0;
	car->restPos.pos.ay = 0;

	car->restPos.vel.z = PULL_SPD;
	travelTime = (car->restPos.pos.z + PULL_Z_OFFSET - carElt->_pos_Z) / car->restPos.vel.z;
	dang = car->restPos.pos.az - carElt->_yaw;
	FLOAT_NORM_PI_PI(dang);
	car->restPos.vel.az = dang / travelTime;
	dang = car->restPos.pos.ax - carElt->_roll;
	FLOAT_NORM_PI_PI(dang);
	car->restPos.vel.ax = dang / travelTime;
	dang = car->restPos.pos.ay - carElt->_pitch;
	FLOAT_NORM_PI_PI(dang);
	car->restPos.vel.ay = dang / travelTime;
}