w0rm / elm-physics / Physics.World


type alias World data =
Internal.World.Protected data

Physical world is our abstract playground for physical simulations.

empty : World data

Let be the new world!

withGravity : Acceleration -> Direction3d Physics.Coordinates.WorldCoordinates -> World data -> World data

Set the standard gravity and its direction, e.g.:

planetEarth =
    withGravity
        (Acceleration.metersPerSecondSquared 9.80665)
        Direction3d.negativeZ
        world

add : Physics.Body.Body data -> World data -> World data

Add a body to the world.

worldWithFloor =
    add planeBody world

Check the Physics.Body module for possible bodies.

simulate : Duration -> World data -> World data

Simulate the world, given the number of seconds since the last frame.

To animate, call this on a message from onAnimationFrameDelta:

simulatedWorld =
    World.simulate (Duration.seconds (1 / 60)) world

Make sure to pass a short duration, such that bodies do not travel through each other during the single frame. This depends on minimum body size and maximum velocity.

bodies : World data -> List (Physics.Body.Body data)

Get all bodies from the world in unspecified order.

Use this to convert bodies into visual representation, e.g. WebGL entities.

contacts : World data -> List (Physics.Contact.Contact data)

Get all contacts from the last simulation frame.

raycast : Axis3d Length.Meters Physics.Coordinates.WorldCoordinates -> World data -> Maybe (RaycastResult data)

Find the closest intersection of a ray against all the bodies in the world. Except for particles, because they have no size.


type alias RaycastResult data =
{ body : Physics.Body.Body data
, point : Point3d Length.Meters Physics.Coordinates.BodyCoordinates
, normal : Direction3d Physics.Coordinates.BodyCoordinates 
}

The Raycast result includes the intersected body, intersection point and normal vector on the face, expressed within the local body coordinate system.

Use the Frame3d from Body.frame to transform the result into world coordinates.

keepIf : (Physics.Body.Body data -> Basics.Bool) -> World data -> World data

Keep bodies that satisfy the test.

update : (Physics.Body.Body data -> Physics.Body.Body data) -> World data -> World data

Apply a function to every body in the world.

constrain : (Physics.Body.Body data -> Physics.Body.Body data -> List Physics.Constraint.Constraint) -> World data -> World data

Configure constraints between pairs of bodies. Constraints allow to limit the freedom of movement of two bodies with relation to each other.

Check the Physics.Constraint module for possible constraints.

worldWithACar : World { part : String }
worldWithACar =
    constrain
        (\b1 b2 ->
            case
                ( (Body.data b1).part
                , (Body.data b2).part
                )
            of
                ( "wheel1", "base" ) ->
                    [ hingeConstraint1 ]

                ( "wheel2", "base" ) ->
                    [ hingeConstraint2 ]

                ( "wheel3", "base" ) ->
                    [ hingeConstraint3 ]

                ( "wheel4", "base" ) ->
                    [ hingeConstraint4 ]

                _ ->
                    []
        )
        worldWithCarParts

Note that this example only works for a single car, otherwise it would connect wheels of one car with the base of another. You might want to use constrainIf to apply constraints on a subset of bodies.

constrain =
    constrainIf (always True)

constrainIf : (Physics.Body.Body data -> Basics.Bool) -> (Physics.Body.Body data -> Physics.Body.Body data -> List Physics.Constraint.Constraint) -> World data -> World data

Configure constraints for a subset of bodies that satisfy the test.

For the above example we can tag each part of a car with the carId, and preselect parts of a single car with:

constrainCar carId =
    constrainIf
        (\body ->
            (Body.data body).carId == carId
        )