static fhRenderMatrix RB_CreatePointLightViewMatrix( const idRenderLightLocal* lightDef, int side )
{
	static const idMat3 sides[6] = {
		idMat3( //+x
			1, 0, 0,
		    0, 1, 0,
			0, 0, 1),
		idMat3( //-x
			-1, 0, 0,
			0, 1, 0,
			0, 0, -1),
		idMat3( //+y
			0, 1, 0,
			-1, 0, 0,
			0, 0, 1),
		idMat3( //-y
			0, -1, 0,
			1, 0, 0,
			0, 0, 1 ),
		idMat3( //z
			0, 0, 1,
			0, 1, 0,
			-1, 0, 0 ),
		idMat3( //-z
			0, 0, -1,
			0, 1, 0,
			1, 0, 0 )
	};

	const idVec3 origin = lightDef->globalLightOrigin;
	const idMat3 axis = sides[side] * lightDef->parms.axis;

	fhRenderMatrix	viewerMatrix;
	viewerMatrix[0] = axis[0][0];
	viewerMatrix[4] = axis[0][1];
	viewerMatrix[8] = axis[0][2];
	viewerMatrix[12] = -origin[0] * viewerMatrix[0] + -origin[1] * viewerMatrix[4] + -origin[2] * viewerMatrix[8];

	viewerMatrix[1] = axis[1][0];
	viewerMatrix[5] = axis[1][1];
	viewerMatrix[9] = axis[1][2];
	viewerMatrix[13] = -origin[0] * viewerMatrix[1] + -origin[1] * viewerMatrix[5] + -origin[2] * viewerMatrix[9];

	viewerMatrix[2] = axis[2][0];
	viewerMatrix[6] = axis[2][1];
	viewerMatrix[10] = axis[2][2];
	viewerMatrix[14] = -origin[0] * viewerMatrix[2] + -origin[1] * viewerMatrix[6] + -origin[2] * viewerMatrix[10];

	viewerMatrix[3] = 0;
	viewerMatrix[7] = 0;
	viewerMatrix[11] = 0;
	viewerMatrix[15] = 1;

	return fhRenderMatrix::FlipMatrix() * viewerMatrix;
}
Exemple #2
0
/*
================
sdDeliveryVehicle::Magog_DoMove
================
*/
void sdDeliveryVehicle::Magog_DoMove( const idVec3& aheadPointIdeal, const idVec3& aheadPointDir, const idVec3& endPoint, float itemRotation, float maxYawScale, bool orientToEnd, bool clampRoll, bool slowNearEnd, float pathSpeed ) {
	float frameTime = MS2SEC( gameLocal.msec );

	idVec3 aheadPoint = aheadPointIdeal;
	const idVec3& origin = GetPhysics()->GetOrigin();
	const idVec3& velocity = GetPhysics()->GetLinearVelocity();
	const idMat3& axis = GetPhysics()->GetAxis();
	const idAngles angles = axis.ToAngles();
	const idVec3& angVel = GetPhysics()->GetAngularVelocity();
	
	const idVec3& currentFwd = axis[ 0 ];
	const idVec3& currentRight = axis[ 1 ];
	const idVec3& currentUp = axis[ 2 ];
	
	float rollVel = angVel * currentFwd;
	float pitchVel = angVel * currentRight;
	float yawVel = angVel * currentUp;

	// find the current height of the vehicle
	idVec3 futureContribution = velocity * 1.0f;
	futureContribution.z = 0.0f;
	float futureContributionLength = futureContribution.Length();
	if ( futureContributionLength > 2000.0f ) {
		futureContribution = futureContribution * ( 2000.0f / futureContributionLength );
	}

	idVec3 futureSpot = origin + futureContribution;
	futureSpot.z -= HOVER_DOWNCAST_LENGTH;

	trace_t trace;
	gameLocal.clip.TraceBounds( CLIP_DEBUG_PARMS trace, origin, futureSpot, GetPhysics()->GetBounds(), axis, MASK_SOLID | MASK_OPAQUE, this );
	futureSpot = trace.endpos;

	// shift the ahead point based on the trace
	float currentHeight = origin.z - futureSpot.z;
	if ( currentHeight < HOVER_DOWNCAST_LENGTH ) { 
		aheadPoint.z = origin.z - currentHeight + HOVER_HEIGHT_AIM;
	} else {
		aheadPoint.z = origin.z - HOVER_DOWNCAST_LENGTH + HOVER_HEIGHT_AIM;
	}

//	sys.debugCircle( g_colorRed, origin, '0 0 1', 16, 8, 0 );
//	sys.debugArrow( g_colorRed, origin, futureSpot, 256, 0 );
//	sys.debugCircle( g_colorRed, futureSpot, '0 0 1', 16, 8, 0 );
//	sys.debugCircle( '0 1 0', aheadPoint, '0 0 1', 256.0f, 16, 0 );


	idVec3 point;
	float lookaheadFactor;

	{
		// generate a cubic spline between the two points
		idVec3 x0 = origin;
		idVec3 x1 = aheadPoint;
		idVec3 dx0 = velocity * 3.0f;					// maintaining our current velocity is more important
		idVec3 dx1 = aheadPointDir * pathSpeed * 1.0f;	// than matching the destination vector
		
		// calculate coefficients
		idVec3 D = x0;
		idVec3 C = dx0;
		idVec3 B = 3*x1 - dx1 - 2*C - 3*D;
		idVec3 A = x1 - B - C - D;
		
		float distanceLeft = ( endPoint - origin ).Length();
		lookaheadFactor = ( distanceLeft / 6096.0f ) * 0.5f;
		lookaheadFactor = idMath::ClampFloat( 0.2f, 0.5f, lookaheadFactor );
		if ( !slowNearEnd ) {
			lookaheadFactor = 0.5f;
		}
		
		point = ( A * lookaheadFactor + B )*lookaheadFactor*lookaheadFactor + C*lookaheadFactor + D;
	}


	//
	// Follower logic
	//
	idVec3 delta = point - origin;
	idVec3 aheadDelta = aheadPoint - origin;

	idVec3 newVelocity = vec3_origin;

	//
	// Z axis
	//

	// figure out what Z velocity is needed to get where we want to go within a frame
	float Zvel = aheadDelta.z / frameTime;
	Zvel = idMath::ClampFloat( -maxZVel, maxZVel, Zvel );
	
	// figure out what Z acceleration is neccessary
	float ZAccel = ( Zvel - velocity.z ) / frameTime;
	ZAccel = idMath::ClampFloat( -maxZAccel, maxZAccel, ZAccel );
	
	// chop the Z acceleration when its nearing the end - helps to avoid settling issues
	if ( lookaheadFactor < 0.5f ) {
		ZAccel *= idMath::Sqrt( lookaheadFactor * 2.0f );
	}
	
	Zvel = velocity.z + ZAccel * frameTime;
	
	// rapidly prevent acceleration downwards when its below the target
	if ( aheadDelta.z > 0.0f && Zvel < 0.0f ) {
		Zvel *= 0.9f;
	}
			
	//
	// X & Y
	//
	
	// ignore Z
	delta.z = 0.0f;
	aheadDelta.z = 0.0f;
	idVec3 flatVelocity = velocity;
	flatVelocity.z = 0.0f;

	float distance = delta.Length();
	idVec3 direction;
	if ( distance > idMath::FLT_EPSILON ) {
		direction = delta / distance;
	} else {
		direction = vec3_origin;
	}
	
	// figure out how fast it needs to go to get there in time
	float vel = distance / 0.5f;
	vel = idMath::ClampFloat( -pathSpeed, pathSpeed, vel );
	
	idVec3 vecVel = vel * direction;
	
	// figure out what acceleration is neccessary
	idVec3 velDelta = vecVel - flatVelocity;
	idVec3 velDeltaDir = velDelta;
	float velDeltaLength = velDeltaDir.Normalize();

	float accel = velDeltaLength / frameTime;
	accel = idMath::ClampFloat( -600.0f, 600.0f, accel );
	
	idVec3 vecAccel = accel * frameTime * velDeltaDir;
	newVelocity = flatVelocity + vecAccel;
	
	
	newVelocity.z = Zvel;
	
	//
	// Angles
	//
	idVec3 velDir = velocity;
	float velLength = velDir.Normalize();
	
	// calculate what acceleration we are undergoing
	idVec3 velAccel = ( newVelocity - velocity ) / frameTime;
	
	// calculate a component due to air resistance
	float speed = InchesToMetres( velLength );
	float rho = 1.2f;
	float sideArea = InchesToMetres( 650.0f ) * InchesToMetres( 650.0f );
	float Cd = 0.6f;
	float dragForceMagnitude = MetresToInches( 0.5 *  Cd * sideArea * rho * speed * speed );
	// assume mass is 10,000 -> I know this works nicely
	idVec3 dragAccel = ( dragForceMagnitude / 10000.f ) * velDir;
	
	idVec3 desiredAccel = velAccel + dragAccel;
	desiredAccel *= 0.4f;
	desiredAccel.z += MetresToInches( 9.8f );
	
	// ok, so we desire to be looking at the target
	idVec3 forwards = endPoint - origin;
	forwards.z = 0.0f;
	forwards.Normalize();
			
	if ( orientToEnd ) {
		idAngles targetAngles = ang_zero;
		targetAngles.yaw = idMath::AngleNormalize180( itemRotation );
		forwards = targetAngles.ToForward();
	}
	
	// figure out the axes corresponding to this orientation
	idVec3 up = desiredAccel;
	up.Normalize();
	idVec3 right = up.Cross( forwards );
	right.Normalize();
	forwards = right.Cross( up );
	forwards.Normalize();
	
	// convert that to an angles
	idAngles desiredAngles = ( idMat3( forwards, right, up ) ).ToAngles();
	if ( clampRoll ) {
		desiredAngles.roll = idMath::ClampFloat( -9.0f, 9.0f, desiredAngles.roll );
	} else {
		desiredAngles.roll = idMath::ClampFloat( -30.0f, 30.0f, desiredAngles.roll );
	}
	desiredAngles.pitch = idMath::ClampFloat( -30.0f, 30.0f, desiredAngles.pitch );

	// find the diff between that and what we currently have
	idAngles diffAngles = ( desiredAngles - angles ).Normalize180();
	diffAngles = diffAngles * 0.1f;
	diffAngles = diffAngles / frameTime;
	diffAngles *= 0.1f;

	
	// translate the old angular velocity back to an angle diff style value
	idAngles oldDiffAngles;
	oldDiffAngles.pitch = angVel * currentRight;
	oldDiffAngles.yaw = angVel * currentUp;
	oldDiffAngles.roll = angVel * currentFwd;
	
	// blend the old and the new to soften the quick changes
	diffAngles = oldDiffAngles * 0.9f + diffAngles * 0.1f;
	
	// figure out how much we're trying to change by in a single frame
	idAngles angleAccel = diffAngles - oldDiffAngles;
	float maxAngleAccel = 45.0f * frameTime;
	float maxYawAccel = maxAngleAccel * maxYawScale;
	
	angleAccel.pitch = idMath::ClampFloat( -maxAngleAccel, maxAngleAccel, angleAccel.pitch );
	angleAccel.yaw = idMath::ClampFloat( -maxYawAccel, maxYawAccel, angleAccel.yaw );
	angleAccel.roll = idMath::ClampFloat( -maxAngleAccel, maxAngleAccel, angleAccel.roll );

	diffAngles = oldDiffAngles + angleAccel;	
	idVec3 newAngVel = diffAngles.pitch * currentRight + 
						diffAngles.yaw * currentUp + 
						diffAngles.roll * currentFwd;

	// HACK: ensure it never gets below the minimum height
	if ( currentHeight < HOVER_HEIGHT_MIN ) {
		idVec3 newOrigin = origin;
		newOrigin.z = origin.z - currentHeight + HOVER_HEIGHT_MIN;
		GetPhysics()->SetOrigin( newOrigin );			
	} else if ( currentHeight < HOVER_HEIGHT_RESCUE ) {
		float oldNewVelLength = newVelocity.Length();
	
		float scale = ( HOVER_HEIGHT_RESCUE - currentHeight ) / ( HOVER_HEIGHT_RESCUE - HOVER_HEIGHT_MIN );
		scale = idMath::Sqrt( scale );
		float rescueVelocity = scale * ( HOVER_HEIGHT_RESCUE - HOVER_HEIGHT_MIN ) / 0.5f;
		float rescueAcceleration = ( rescueVelocity - velocity.z ) / frameTime;
		rescueAcceleration = idMath::ClampFloat( 0.0f, 1800.0f, rescueAcceleration );
		rescueVelocity = velocity.z + rescueAcceleration * frameTime;
		if ( rescueVelocity > newVelocity.z ) {
			newVelocity.z = rescueVelocity;
		}
		
		newVelocity.Normalize();
		newVelocity *= oldNewVelLength;
	}
			
	GetPhysics()->SetLinearVelocity( newVelocity );
	GetPhysics()->SetAxis( angles.ToMat3() );
	GetPhysics()->SetAngularVelocity( newAngVel );
}