Basically, You create shapes (btBvhTriangleMeshShape, btTriangleMesh). That’s used to test and report contact points. Then, for dynamic objects(chassis, wheels,…) you create one rigidbody (btRigidBody). The rigid body is responsible for transforming contacts into velocity and torque to objects.
BulletPhysics/Ammojs provide an helper objects for vehicles. instead of doing everything manually (shapes, bodies, joints), it create everything you need with a few calls:
var tuning = new Ammo.btVehicleTuning();
var rayCaster = new Ammo.btDefaultVehicleRaycaster(physicsWorld);
vehicle = new Ammo.btRaycastVehicle(tuning, body, rayCaster);
One the physics objects are in place, rendered meshes position and orientation are updated each frame from the rigid bodies Line 128-200 and more specifically lines 182-198.
The interaction between the keyboard and the physic objects are line 169-178. Depending on key pressed, forces are applied to the vehicle.
Theworkflow for physics is always the same (using ammojs directly or thru impostors): you apply forces/torque to physic objects. Physics objects respond to forces and contacts. Physics objects matrices are then applied to rendered mesh (manually in this case or handled by the engine like with the impostors in Babylonjs)
Let me know if you have more questions