Esempio n. 1
0
void SimCarCollideZ(tCar *car)
{
	int i;
	t3Dd normal;
	tdble dotProd;
	tWheel *wheel;
	const float CRASH_THRESHOLD = -5.0f;

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

	for (i = 0; i < 4; i++) {
		wheel = &(car->wheel[i]);
		if (wheel->state & SIM_SUSP_COMP) {
			car->DynGCg.pos.z += wheel->susp.spring.packers - wheel->rideHeight;
			RtTrackSurfaceNormalL(&(wheel->trkPos), &normal);
			dotProd = (car->DynGCg.vel.x * normal.x + car->DynGCg.vel.y * normal.y + car->DynGCg.vel.z * normal.z) * wheel->trkPos.seg->surface->kRebound;
			if (dotProd < 0.0f) {
				if (dotProd < CRASH_THRESHOLD) {
					car->collision |= SEM_COLLISION_Z_CRASH;
				}
				car->collision |= SEM_COLLISION | SEM_COLLISION_Z;
				car->DynGCg.vel.x -= normal.x * dotProd;
				car->DynGCg.vel.y -= normal.y * dotProd;
				car->DynGCg.vel.z -= normal.z * dotProd;
				if ((car->carElt->_state & RM_CAR_STATE_FINISH) == 0) {
					car->dammage += (int)(wheel->trkPos.seg->surface->kDammage * fabs(dotProd) * simDammageFactor[car->carElt->_skillLevel]);
				}
			}
		}
	}
}
void
SimWheelUpdateRide(tCar *car, int index)
{
    tWheel *wheel = &(car->wheel[index]);
    tdble Zroad;


    /* compute suspension travel */
    RtTrackGlobal2Local(car->trkPos.seg, wheel->pos.x, wheel->pos.y, &(wheel->trkPos), TR_LPOS_SEGMENT);
    wheel->zRoad = Zroad = RtTrackHeightL(&(wheel->trkPos));

	tdble prexwheel = wheel->susp.x / wheel->susp.spring.bellcrank;

	tdble new_susp_x= prexwheel - wheel->rel_vel * SimDeltaTime;
    tdble max_extend;

    
    t3Dd normal;
    t3Dd rel_normal;
    // Find normal of track.
    RtTrackSurfaceNormalL(&(wheel->trkPos), &normal);
    wheel->normal = normal; 
    {
		sgQuat Q;
		sgCopyQuat (Q, car->posQuat);
		sgPreRotQuat (Q, FLOAT_RAD2DEG(wheel->relPos.ax), 1.0f, 0.0f, 0.0f);
		sgVec3 P = {normal.x, normal.y, normal.z};
		sgRotateVecQuat (P, Q);
		sg2t3 (P, rel_normal);
	}
    tdble dZ = wheel->pos.z - Zroad;

    //NaiveRotate (d, angles, &d);
#ifdef USE_THICKNESS
	int seg_id = ((int) ((tdble) N_THICKNESS_SEGMENTS *  (wheel->relPos.ay/(2*M_PI)))) % N_THICKNESS_SEGMENTS;
	if (seg_id<0) seg_id += N_THICKNESS_SEGMENTS;
	tdble adjRadius = wheel->radius + wheel->thickness[seg_id];
#else
	tdble adjRadius = wheel->radius;
#endif
    if (rel_normal.z > MIN_NORMAL_Z) {		
		wheel->susp.fx = adjRadius - adjRadius/rel_normal.z;
		wheel->susp.fy = 0.0;
		//wheel->susp.x = wheel->rideHeight =
		max_extend = adjRadius + ((dZ)*normal.z - adjRadius)/rel_normal.z;
    } else {
		//wheel->susp.x = wheel->rideHeight = (wheel->pos.z - Zroad);
		//	wheel->susp.x = wheel->rideHeight = wheel->susp.spring.packers; 
		wheel->susp.fx = 0.0;
		wheel->state = wheel->state | SIM_SUSP_COMP;
		max_extend = 0.0;
    }

	/* Note from Christos about the 'max_extend' variable set right above :
	   This variable's name a left-over from simuv2. It has a slightly extended use.
	   Perhaps the name should be changed.

	   In simuv2, when the suspension was fully compressed then the suspension reaction
	   was ignored, the car speed was set to be tangential to the track,
	   and the car height was set to be just above the track.

	   Now it basically signifies that the car is not a 'normal' regime, meaning either:
	   a) The suspension is maxed out, and perhaps the car is touching the ground.
	   b) The car has rolled over more than a certain amount.

	   In either case, the collision code is used to see how to react.
	   In the collision code, we check if the car is upright :
	   
	   If the car is upright:
	   * If the car is not very low, then the simuv2 approach is used.
	   * If the car is under the track (beyond a margin) then damages are taken
	     and there is some friction.
	   If the car is not upright, then we use the collision code with the ground.

	   Now, this collision code with the ground (collidez) seems to be somewhat problematic,
	   but I do not know why. Virtually the same code is used for collisions with the walls,
	   and there the car behaves nicely.
	   
	   Possibly there is a mixup with the frames of reference.
	*/
	
	wheel->rideHeight = max_extend;

    wheel->bump_force = 0.0; // force of the wheel bumping up into the frame
	if (max_extend < new_susp_x) {
		new_susp_x = max_extend;
		wheel->rel_vel = 0.0f;
	} else if (new_susp_x <= wheel->susp.spring.packers) {
        wheel->bump_force = wheel->mass * wheel->rel_vel / SimDeltaTime;
        wheel->susp.x = wheel->susp.spring.packers;
		wheel->rel_vel = 0.0f; 
	}
 
	tdble prex = wheel->susp.x;
	wheel->susp.x = new_susp_x;

	wheel->relPos.az = wheel->steer + wheel->staticPos.az;
    // Transform from world to suspension FOR
    if (index % 2) {
		wheel->relPos.ax = -wheel->staticPos.ax;
    } else {
		wheel->relPos.ax =  wheel->staticPos.ax;
    }

    wheel->relPos.ax += wheel->dynamic_camber*wheel->steer;
	if (car->options->alignment_damage && wheel->rotational_damage_x>0.0) {
		wheel->relPos.ax += wheel->rotational_damage_x*sin(wheel->relPos.ay + wheel->bent_damage_x);
		wheel->relPos.az += wheel->rotational_damage_z*cos(wheel->relPos.ay + wheel->bent_damage_z);
	}




    //wheel->relPos.z = - wheel->susp.x / wheel->susp.spring.bellcrank + wheel->radius; /* center relative to GC */
    /* verify the suspension travel */
    SimSuspCheckIn(&(wheel->susp));
    //wheel->rideHeight = wheel->susp.x / wheel->susp.spring.bellcrank;
    if (index % 2) {
		wheel->relPos.ax -= wheel->susp.dynamic_angles.x;
    } else {
		wheel->relPos.ax += wheel->susp.dynamic_angles.x;
    }

    wheel->susp.v = (prex - wheel->susp.x) / SimDeltaTime;
    /* update wheel brake */
    SimBrakeUpdate(car, wheel, &(wheel->brake));
    
}