Real Physics Enabled Racing Game

It took me forever to convince the powers that be of Ammo.js to put in my fixes for Global Contact Support and how important Ammo.addFunction really is.

Im glad to see someone else using it:

var collisionCallbackPointer = Ammo.addFunction( collisionCallbackFunc);
world.setContactProcessedCallback(collisionCallbackPointer);

Works like a charm dont it :slight_smile:

BTW… I have WASM builds of Ammo.js with all these fixes as well… Let me know if you want the Matching WASM builds for the Ammo.js from them Babylon Dist Folder

Yeah. AmmoJS is awesome, but hard to extend in JS, so any serious project should really be using their own fork. Take the RaycastVehicle. The default raycaster is missing collision masking/filtering, so you’ll have to either add a couple of lines in that function, or extend the class yourself.
My own version has a ton of added features. Anything from dynamic destruction to, well, most of the physics improvements in SuperTuxKart: GitHub - supertuxkart/stk-code: The code base of supertuxkart

But I get why it should be kept as simple as possible. My features are most likely useless to most people, so it would only add to (down)loading of the library.

Yo @Raggar … How are you using the Superkart code base in your ammo.js…

Did you make another ammo.js project and replace the WHOLE bullet folder ???

Did you just piece the changes from the superkart version into the ammo.js bullet 2.82 version ???

I am very interested in the Raycast Collision Filter code you used… Can you share that little peice with me :slight_smile:

I’ve taken the bit and parts and ported them over one by one. If I remember correctly, very few, if any, changes are needed to make it work.

In the castRay function of your raycaster, you simply put:

 rayCallback.m_collisionFilterMask = collisionFilterMask;
 rayCallback.m_collisionFilterGroup = collisionFilterGroup;

Before you do the rayTest.
So between setting the result callback and calling the rayTest function. Then it’s automatically handled.

Then you just need a way of setting your mask and group. The best way of doing this is to create a function that takes two ints, one for the mask and one for the group, and do collisionFilterMask = BIT(int)
Then export this function in the idl.

A cool feature of the SuperTuxKart project as well is auto-stabilization of the vehicle when airborne.
You can give it a Vector3 telling it which direction is up (0,1,0), and an int or float as an impulse to automatically stabilize the vehicle, so it hits the ground correctly.

        btVector3 kart_up    = getChassisWorldTransform().getBasis().getColumn(1);
        //btVector3 terrain_up = btVector3(0, 1, 0);
        // Length of axis depends on the angle - i.e. the further awat
        // the kart is from being upright, the larger the applied impulse
        // will be, resulting in fast changes when the kart is on its
        // side, but not overcompensating (and therefore shaking) when
        // the kart is not much away from being upright.
        btVector3 axis = kart_up.cross(terrain_up);

        // To avoid the kart going backwards/forwards (or rolling sideways),
        // set the pitch/roll to 0 before applying the 'straightening' impulse.
        // TODO: make this works if gravity is changed.
        btVector3 av = m_chassisBody->getAngularVelocity();
        av.setX(0);
        av.setZ(0);
        m_chassisBody->setAngularVelocity(av);
        // Give a nicely balanced feeling for rebalancing the kart
        m_chassisBody->applyTorqueImpulse(axis * stabImpulse);

Yo @Raggar … So have you got ANYTHING in babylon using a raycast vehicle ???

And… How the HECK are you handling skidding… Locking the back wheels and skidding… ???

I just made up some Friction Slip Lerping that when you hit the handbrake i lock the back wheels and decrease each wheel friction slip by a small percent and then start LERPING that friction back to the default friction slip for each wheel… I can fine tune how much SKIDDING and HOW LONG to lerp that difference back… is working i guess… But how the heck is every one else using bullet and raycast vehicle doing the skidding.

I tried to look at supertukkart … but they have a whole skidding manager that does that… And i cant tell if that enhancements to bullet raycast vehicle or something that added on to fake the skidding… I dont see them directly messing witht he wheel friction when you hit a handbrake either…

Can you help explain some that to me… Please :slight_smile:

Yo @Raggar … Thanks for the Raycast Filter Group Info…

I endup making attributes in ammo.idl for the default raycaster class:

class btDefaultVehicleRaycaster : public btVehicleRaycaster
{
	btDynamicsWorld*	m_dynamicsWorld;
public:
	// Mackey Kinard
	short int	m_collisionFilterGroup;
	short int	m_collisionFilterMask;

	btDefaultVehicleRaycaster(btDynamicsWorld* world)
		:m_dynamicsWorld(world),
		m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),	// Mackey Kinard
		m_collisionFilterMask(btBroadphaseProxy::AllFilter)			// Mackey Kinard
	{
	}

	virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result);

};

And In castRay:

void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result)
{
//	RayResultCallback& resultCallback;

	btCollisionWorld::ClosestRayResultCallback rayCallback(from,to);

	// Mackey Kinard
	rayCallback.m_collisionFilterMask = m_collisionFilterMask;
	rayCallback.m_collisionFilterGroup = m_collisionFilterGroup;

	m_dynamicsWorld->rayTest(from, to, rayCallback);

	if (rayCallback.hasHit())
	{
		
		const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
        if (body && body->hasContactResponse())
		{
			result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
			result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
			result.m_hitNormalInWorld.normalize();
			result.m_distFraction = rayCallback.m_closestHitFraction;
			return (void*)body;
		}
	}
	return 0;
}

Ammo.idl

interface btDefaultVehicleRaycaster {
  void btDefaultVehicleRaycaster(btDynamicsWorld world);
  // Mackey Kinard
	attribute short	m_collisionFilterGroup;
	attribute short	m_collisionFilterMask;
};
btDefaultVehicleRaycaster implements btVehicleRaycaster;

Thanks Bro :slight_smile: