Drift an object flying in air

gleemer
Posts: 15
Joined: Sat Nov 29, 2008 6:34 am

Drift an object flying in air

Post by gleemer »

How would you go about nudging or adding a drifting force (left or right) to an rigid body lifted into the air and gradually falling down (due to gravity).

Would you apply a small central impulse to the object ?

thnx
pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Re: Drift an object flying in air

Post by pico »

Hi,

i use ApplyTorqueImpulse.
To stay upward i create a btQuaternion that points up.
Then i use btTransformUtil::calculateVelocity (with 1 second time) to calculate the angular velocity which i then apply each step.
This allows to give good shakes to the objet and it aligns after some time again to the xz axis. Feels very natural.
gleemer
Posts: 15
Joined: Sat Nov 29, 2008 6:34 am

Re: Drift an object flying in air

Post by gleemer »

Hey thanks a bundle. :D

I sorted it out and wanted to share the result. It works well.
I know a lot of people are looking for a way to keep things upright, like a vehicle. Rather than using an upward constraint, this solution allows for free rotation that interpolates gradually back to the upward position.

Code: Select all

// ====================================================================================== //
//
// ====================================================================================== //
- (void) InterpolateUpward {
		btVector3 linVelA, angVelA;
		btTransform  fromA, toA;
		 
		gBV_carChassis->getMotionState()->getWorldTransform( fromA );
		btQuaternion point_up( btVector3(0.f, 1.f, 0.f), 0.0f );
		btMatrix3x3 fromMat = fromA.getBasis();
 		btQuaternion orn;
		
		fromA.getBasis().getRotation(orn);
		point_up *= orn;
		 		 
		btMatrix3x3 upMat( point_up );
		 
		toA.setBasis( upMat ); 
	 
		// timestep 1.0 sec
		btTransformUtil::calculateVelocity(fromA, toA, btScalar(1.0f), linVelA, angVelA );
 
		gBV_carChassis->setAngularVelocity( angVelA );

} // InterpolateUpward 
 

Called every second or so when you update your scene.

Code: Select all

if ( (fps_ttotal - gSaveTotalTm) > 1 ) {
				[self InterpolateUpward];
				gSaveTotalTm = fps_ttotal;
			}
gleemer
Posts: 15
Joined: Sat Nov 29, 2008 6:34 am

Re: Drift an object flying in air

Post by gleemer »

Here is a slimmed down version, since I am not using the Linear velocity. Essentially parsing down the function btTransformUtil::calculateVelocity to get the necessary info.

Code: Select all

// ====================================================================================== //,,,,,,,,, 
//
// ====================================================================================== //
- (void) InterpolateUpward {
		btVector3 linVelA, angVelA;
		btTransform  fromA, toA;
		float yaw, pitch , roll;
		 
		gBV_carChassis->getMotionState()->getWorldTransform( fromA );
		btQuaternion point_up( btVector3(0.f, 1.f, 0.f), 0.0f );
		btMatrix3x3 fromMat = fromA.getBasis();
 		btQuaternion orn;
		
		fromA.getBasis().getRotation(orn);
		point_up *= orn;
		 		 
		btMatrix3x3 upMat( point_up );
		 
		toA.setBasis( upMat );
		
		btMatrix3x3 dmat = toA.getBasis() * fromA.getBasis().inverse();
		btQuaternion dorn;
		dmat.getRotation(dorn);
		// floating point inaccuracy can lead to w component > 1..., which breaks 
		dorn.normalize();
		btScalar  angle = dorn.getAngle();
		btVector3 axis = btVector3(dorn.x(), dorn.y(), dorn.z());
		// axis[3] = btScalar(0.0f);
		btScalar len = axis.length2();
		if (len < SIMD_EPSILON * SIMD_EPSILON ) {
			axis = btVector3(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
		} else {
			axis /= sqrtf( len );
		}
		// when timestep == 1.0
		angVelA = axis * angle;   // otherwise divide by timeStep:    angVel = axis * angle / timeStep;
                gBV_carChassis->setAngularVelocity( angVelA );

} // InterpolateUpward 
gleemer
Posts: 15
Joined: Sat Nov 29, 2008 6:34 am

Re: Drift an object flying in air

Post by gleemer »

Scratch what I have above. It is only setting the angular velocity to 0,0,0.

So for now ONLY when the vehicle is in the air, I check for rotation on x and z axis to see if it is greater than a constant threshold. then gradually creep toward the threshold until both x & z angles are below it. This straightens out the vehicle while in flight.

Code: Select all

- (void) InterpolateUpward {
		float xv, yv, zv, wv;
		btTransform	 currTrans;
		btQuaternion qt1;
		bool didChange = false;
		
		gBV_carChassis->getMotionState()->getWorldTransform( currTrans );
		currTrans.getBasis().getRotation( qt1 );
		xv = qt1.x();
		yv = qt1.y();
		zv = qt1.z();
		wv = qt1.w();
		
		if ( xv > ANGLE_THRESHOLD ) {
			xv += -0.01f; 
			qt1.setX( xv );
			didChange = true; 
		}
		if ( xv < -ANGLE_THRESHOLD ) {
			xv += 0.01f; 
			qt1.setX( xv );
			didChange = true; 
		}
		if ( zv > ANGLE_THRESHOLD ) {
			zv += -0.01f;
			qt1.setZ( zv ); 
			didChange = true;
		}
		if ( zv < -ANGLE_THRESHOLD ) {
			zv += 0.01f;
			qt1.setZ( zv ); 
			didChange = true;
		}
		if ( didChange ) {
			gBV_carChassis->setAngularVelocity( btVector3( 0.0f, 0.0f, 0.0f ) );
			currTrans.setRotation( qt1 );
			gBV_carChassis->getWorldTransform().setBasis( currTrans.getBasis() );
		}
		
} // InterpolateUpward