Getting the ball rolling

Started by
6 comments, last by chenium 14 years ago
Hello, I'm working on a pool game currently and having trouble figuring out how to get the ball rolling correctly. According to resources on the internet, when the ball is hit straight on without any english, the ball slides initially and begins to roll due to the friction from the table. The ball is in natural roll when v = wr, where v is the velocity at the center of mass, w is the angular velocity, and r is the radius of the ball. My issue is, when I apply friction to the ball F=uN to induce the roll, I apply a torque to initiate the roll and also apply the same force to the linear velocity. At low speeds, the friction acting on the linear velocity may eventually cause it to go in the opposite direction before it can detect the natural roll state! Am I incorrectly applying the forces of friction on the ball in the sliding state? here is my update method for the ball:

override public function update( et : Number ) : void
{
	var gravity : Number = World.GRAVITY;
	
	// -- add forces due to friction
	//var frictionForce : Vector3D = velocity.clone();
	//frictionForce.normalize();
	
	var mu : Number;
	var contactVec : Vector3D;
	var vp : Vector3D;
	var friction : Vector3D;
	
	if ( bodyState == STATE_SLIDING )
	{
		// -- find the velocity at a point on the surface of the ball
		contactVec = new Vector3D( 0.0, 0.0, radius );	
		//vp = contactVec.crossProduct( angularVelocity );
		vp = new Vector3D();
		vp.incrementBy( velocity );
		vp.normalize();
		
		// -- friction is a vector in the opposite direction of the velocity
		vp.scaleBy( -MU_SLIDE * gravity * mass );
		addForce( vp, contactVec );
	}
	else if ( bodyState == STATE_ROLLING )
	{
		// -- apply rolling resistence as torque
		contactVec = new Vector3D( 0.0, 0.0, radius );	
		vp = contactVec.crossProduct( angularVelocity );
		vp.normalize();
	
		vp.scaleBy( MU_ROLL * gravity * mass );
		addTorque( contactVec.crossProduct( vp ) );
	}
}



And here is my method for integrating forces on the object

public function integrateForces( et : Number ) : void
{
	torque.scaleBy( invInertia * et );
	angularVelocity.incrementBy( torque );
	
	var threshold : Number = 0.0001;
	
	if ( bodyState == STATE_ROLLING )
	{
		var cp : Vector3D = new Vector3D( 0, 0, radius );
		var av : Vector3D = cp.crossProduct( angularVelocity );
		
		velocity.x = av.x;
		velocity.y = av.y;
		velocity.z = av.z;
	}
	else if ( bodyState == STATE_SLIDING )
	{
		force.scaleBy( invMass * et );
		velocity.incrementBy( force );
		
		// -- check if i'm rolling
		var contact : Vector3D = new Vector3D( 0, 0, radius );
		var rw : Vector3D = contact.crossProduct( angularVelocity );
		var dotp : Number = rw.dotProduct( velocity );
		var diff : Number = rw.subtract( velocity ).length;
		
		if ( dotp && diff < 0.05 )
		{
			bodyState = STATE_ROLLING;
			trace( "rolling" );
			
			velocity.x = rw.x;
			velocity.y = rw.y;
			velocity.z = rw.z;
		}
	}
	
	// -- check if i'm coming to a stop
	var velSquared : Number = velocity.lengthSquared;
	var angSquared : Number = angularVelocity.lengthSquared;
	
	if ( velSquared < threshold && angSquared < threshold )
	{
		bodyState = STATE_REST;
		
		velocity.x = 0;
		velocity.y = 0;
		velocity.z = 0;
		
		angularVelocity.x = 0;
		angularVelocity.y = 0;
		angularVelocity.z = 0;
	}
	
	force.x = 0;
	force.y = 0;
	force.z = 0;
	
	torque.x = 0;
	torque.y = 0;
	torque.z = 0;
}



Advertisement
Another question I have is when the ball is actually in the rolling state, I change the linear velocity based on the relationship of v=wr. Is that the correct way of doing it or is there another way?
Well, unfortunately I can't help you directly with your problem but I can tell you that games are about the appearance of being correct, not about actually BEING correct.

So, unless you trying to do it as realistically as possible for a reason, I say fudge it so that it looks like you want, and call it good :P

If you are wanting to be a purist though, I would say that I don't think real physics is made up of state machines. Sliding and rolling balls don't magically have different forces applied to them, the issue is just whether or not the speed is greater than some maximum threshold needed for the felt of the table to cause the right kind of friction?

I'm not that much of a physics guy but hopefully you smell what I'm cooking
It is a complicated issue. As Atrix said, you have to cook the Results a bit.
The simplest Model is start rolling bellow a certain Speed.
If you want to know some Theory about Ball rolling I recommend that you look for a specialized Book, about the Physics of Billiards, or any Sport that uses a Ball. For example the way a Tennis Ball starts rolling will be similar to Billiards.
I'm not great with friction yet, so I'm probably no help but a few thoughts came to me. Should you be applying torque on the ball? I would assume not, only LV, or better yet a force, which would induce an acceleration. The friction model should create the torque for you as the cueball slows.
Found this while investigating:

http://robocup.mi.fu-berlin.de/buch/rolling.pdf
Burnt_Fyr that Document is very good indeed.
Most Articles about pool have an abrupt transition between sliping and rolling, with which I don't agree. A ball should not instantaneously go from Kinetic Friction to Rolling Friction, without going through some intermediate state of half Friction half rolling.
This document makes a much better Analysis.
Thanks for the replies, I figured out my problems. As for sliding vs rolling, once the angular velocity of the ball matches the linear velocity, the point where the ball is in contact with the ground, the relative velocity is zero. Therefore the ball is technically at rest so there is no friction.

To account for slipping from the ball sliding + the ball spinning during my "slide" state, I calculate the velocity at the point of contact which is the sum of the velocity at the center of mass and the radius x angular velocity. I find my friction from that velocity and apply it to the center of mass and also as a torque.

if ( bodyState == STATE_SLIDING ){	// -- find the velocity at a point on the surface of the ball	contactVec = new Vector3D( 0.0, 0.0, radius );		vp = angularVelocity.crossProduct( contactVec );	vp.incrementBy( velocity );	vp.normalize();					// -- friction is a vector in the opposite direction of the velocity	vp.scaleBy( -MU_SLIDE * gravity * mass );	addForce( vp, contactVec );}


as for my addForce method, it applies a force to the center of mass as well as a torque based off a point from the cm
public function addForce( af : Vector3D, point : Vector3D ) : void{	atRest = false;	force.incrementBy( af );	torque.incrementBy( point.crossProduct( af ) ); }


I tried my code with top spin and back spin and the results look good.

Here is a link to my project as a swf. Click anywhere in the swf to shoot the ball. Currently, it's hard coded to add backspin at the hit.

http://megaswf.com/view/215cfff8869689bdfaa557a1df99ab53.html

This topic is closed to new replies.

Advertisement