GoblinPhysics icon indicating copy to clipboard operation
GoblinPhysics copied to clipboard

Raycast vehicle system

Open chandlerprall opened this issue 10 years ago • 6 comments

Dependent on first adding more callbacks that such a system can tie into.

chandlerprall avatar Sep 23 '14 03:09 chandlerprall

:+1: Definitely behind this. Do you recall what callbacks you needed? Cannon's implementation appears to update the vehicle every step.

nmai avatar Oct 18 '15 21:10 nmai

World will emit a stepStart event which serves the same purpose. World would need to be modified to track its vehicle systems similar to how rigid bodies are tracked (this.systems, this.addSystem, this.removeSystem). All systems should be notified when they are added/removed to/from the world so they can manage any relevant constraints. Knowing what world it is added to also provides a way to cast the rays.

A RaycastVehicleSystem should take the vehicle's rigid body and a system description in the constructor, something listing the wheels/suspension information, build the internal state, add constraints to the world, and listen for stepStart.

Depending on implementation details, HingeConstraint may need motor capability added and SliderConstraint may need limits & a motor, or a SpringConstraint be created (ideal).

At a broad level I believe that's everything required.

chandlerprall avatar Oct 18 '15 21:10 chandlerprall

The idea of creating a separate systems array to track vehicles didn't make much sense to me until I looked at the RigidBody implementation- not only does it track values but it also contains a number of helper functions. Looks like the way to go.

Two questions though:

  • How can we handle constraints? In cannon's implementation, traditional constraints do not seem to be used. Instead, all the math is handled within the RaycastVehicle updateVehicle callback and various helper functions. Wheel positions and their custom options are tracked within an array of WheelInfo objects.

    As it stands, Cannon's RaycastVehicle is ~700 lines of code and I feel that the vast majority of it is because the developer re-implemented things like HingeConstraint and SpringConstraint. I can only assume this is because the wheels aren't actually bodies and cannot be used with the standard constraint definitions.

    Is there a clean solution for this?

  • Do you think it would be possible to use systems to track more than just raycast vehicles or do you see that causing problems later? I think as long as each system exposed certain functions like update there should be no issues.

nmai avatar Oct 18 '15 23:10 nmai

I'll answer the second question first, you are correct. This should be a reusable interface that other systems like a ragdoll body could take advantage of as well.

To your first question. It is completely valid for a system to handle its internal constraints itself, for example Bullet's ragdoll system implements a featherweight constraint solver for ragdolls which runs independent of the rest of the world's constraints. As you noted, Cannon takes the same approach for its vehicles. It's a trade off between performance and accuracy. I'd prefer the accuracy provided by intertwining the constraints into the world unless we can show that's terrible performance.

As an overall approach which likely has holes, each wheel will need a spring for suspension and a slider for applying the wheel's change in velocity. Since a raycast vehicle doesn't have actual, physical wheels there's no need for any hinge constraints for steering the wheel or applying power. I believe nothing needs to be added to the slider constraint for this, as the bias can be used to add velocity to the system in lieu of a motor. Should probably create an independent SpringConstraint.

At each step, a ray is cast from the mount point on the vehicle's rigid body "downward" to a maximum length of max_suspension_length + wheel_radius, if an object collides with the ray then the spring and slider constraints are activated and updated for that frame. For performance there would need to be direct modification of the constraints' values instead of destroying/recreating them every frame. Because it's probably not obvious, the slider constraint would act to propel the car and the object beneath it in equal but opposite directions.

It's possible the slider could be avoided and a FrictionConstraint is used instead. In this case a custom Contact object would need to be created and filled in with the results of the ray intersection.

Couple things that look like they could be useful that a quick search pulled up - http://www.asawicki.info/Mirror/Car%20Physics%20for%20Games/Car%20Physics%20for%20Games.html http://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc12/Srisuchat/Thesis.pdf

Both of these end up going into engine/clutch/gearing that can be ignored for Goblin, at least for the initial implementation.

chandlerprall avatar Oct 18 '15 23:10 chandlerprall

Thanks, that's some good info. Could you give me a rough example of how the SliderConstraint solution would be implemented? Specifically, how would force be applied to the object in contact?

nmai avatar Oct 19 '15 00:10 nmai

Thinking about this some more, the SliderConstraint isn't the best answer because it will constrain all motion, not just apply force along one axis. Perhaps the best start is to take the approach detailed in that PDF and keep it all local to the vehicle system, no external constraints.

chandlerprall avatar Oct 19 '15 15:10 chandlerprall