Hi G! Welcome to the forum. Let’s ping @Cedric , as he is darned good at physics engines.
One way that might work… is to “watch” wheel.rotationQuaternion (or possibly wheel.rotationQuaternion.toEulerAngles().y). As you steer the wheels, wheel.rotationQuaternion should be changing, and you may be able to do some IF/THEN testing there.
For example, if (wheel.rotationQuaternion.toEulerAngles().y < something) {allow further steering) else { don’t }.
You may also be able to “sync” the steer-amount of the two wheels… with this same method. Every time the steer-amount changes on wheel1, wheel2.rotationQuaternion = new BABYLON.Quaternion( wheel2.rotationQuaternion.x, wheel1.rotationQuaternion.y, wheel2.rotationQuaternion.z, wheel2.rotationQuaternion.w); (Notice that I made a new wheel2.rotationQuaternion, exactly the same as its PREVIOUS one, except I used a .Y value copied from wheel1.rotationQuaternion.y.)
I replaced old one with new one… because… Quaternions really don’t like to be “edited”. It’s best to replace them with a new one. Quats DO like being added, subtracted, multipled, divided, and scaled, though (mostly by/with/from/to OTHER quats).
We/you MIGHT need to do a “forceUpdate()?” on wheel2.physicsImpostor.physicsBody.quaternion… after we change wheel2.rotationQuaternion… so that the physicsBODY.quaternion (a AmmoJS native object) exactly matches the newly-installed wheel2.rotationQuaternion.
I’m not real familiar with the (multiple) ways to re-sync a mesh.physicsImpostor.physicsBody.quaternion… with a fresh mesh.rotationQuaternion… but essentially, the forceUpdate() is a removal of the old impostor, and replacing it.
We COULD have used wheel1.rotationQuaternion.copy() or .clone() or similar…(for installing on wheel2.rotationQuaternion) but… that could affect the wheel’s x-rotation, too. (“Goodyear” lettering on tires might be printed on the TOP of wheel1 but on the bottom of wheel2 - caused by differing tire spins - possibly after leaving a jumping ramp.) Maybe nobody will notice tiny details like that, though.
Anyway, SOME values on steerwheel1.rotationQuaternion and steerwheel2.rotationQuaternion SHOULD be changing as you steer the wheels. You might be able to use those values as both a steering limit, and a turn-amount sync method.
Also, keep in mind that distance joints and lock joints… are invisible, so a lockJoint “rod” might be able to be connected between “nose” of wheel1 and “nose” of wheel2. (nose == leading edge). Lock joints have no mainAxis and connectedAxis, as far as I know… but they DO have mainPivot and connectedPivot… and in this case… you will want them to be very accurate. It should be simple, though. Set mainPivot 0, 0, 3 and connectedPivot 0,0,3 also. That means… 3 units forward of mesh origin (center of mesh) on BOTH connected shapes. Essentailly you made a steering arm… connecting the two wheels.
BUT… I am worried about this idea. This connecting rod MIGHT spin-around X… as the wheels “roll”. Depending upon where the user stops the car, the rod that was once 3 units “forward” +z of wheel hubs… might be 3 units above or below hubs . If you were to turn steering wheel when connecting rod was above or below hubs… wheel2 will not steer same as wheel1. (connecting rod failed because rod connect pivot-points… rotated (rolled) around x… when wheels/tires rotated around x)
Hard to describe.
Anyway, watch your wheel.rotationQuaternion, and even watch wheel.physicsImpostor.physicsBody.quaternion (puke them to console as you steer one wheel)… see what the values are doing… and start playing with those). Oh, by the way, Quaternion values sort of suck… but heavy medication and deep meditation… can help.
Stay tuned for other ideas, and please report test results… to help teach others. Thanks!