terry-bit-io / elm-physics / Physics.Body


type alias Body data =
Internal.Body.Protected data

Represents a physical body containing user defined data, like a WebGL mesh.

By default bodies don’t move. To change this, use withBehavior.

All bodies start out centered on the origin, use moveTo to set the position.

The supported bodies are:

For complex bodies check compound.

block : Block3d Length.Meters Physics.Coordinates.BodyCoordinates -> data -> Body data

A block is created from elm-geometry Block3d. To create a 1x1x1 cube, centered at the origin of the body, call this:

cubeBody =
    block
        (Block3d.centeredOn
            Frame3d.atOrigin
            ( meters 1, meters 1, meters 1 )
        )
        data

plane : data -> Body data

A plane with the normal that points in the direction of the z axis.

A plane is collidable in the direction of the normal. Planes don’t collide with other planes and are always static.

sphere : Sphere3d Length.Meters Physics.Coordinates.BodyCoordinates -> data -> Body data

A sphere is created from elm-geometry Sphere3d.

To create a 1 meter radius sphere, that is centered at the origin of the body, call this:

sphereBody =
    sphere
        (Sphere3d.atOrigin (meters 1))
        data

cylinder : Cylinder3d Length.Meters Physics.Coordinates.BodyCoordinates -> data -> Body data

A cylinder is created from elm-geometry Cylinder3d. To create a vertical cylinder, centered at the origin of the body, call this:

cylinderBody =
    cylinder
        (Cylinder3d.centeredOn
            Point3d.origin
            Direction3d.z
            { radius = Length.meter, length = Length.meter }
        )
        data

This cylinder is approximated with a convex polyhedron mesh that has 12 side faces.

For more subdivisions at the cost of worse performance, create a compound body with Shape.cylinder.

particle : data -> Body data

A particle is an abstract point that doesn’t have dimensions. Particles don’t collide with each other.

Behavior


type Behavior

Bodies may have static or dynamic behavior.

dynamic : Mass -> Behavior

Dynamic bodies move and react to forces and collide with other dynamic and static bodies.

static : Behavior

Static bodies don’t move and only collide with dynamic bodies.

withBehavior : Behavior -> Body data -> Body data

Change the behavior, e.g. to make a body dynamic:

dynamicBody =
    staticBody
        |> withBehavior (dynamic (Mass.kilograms 5))

Properties

frame : Body data -> Frame3d Length.Meters Physics.Coordinates.WorldCoordinates { defines : Physics.Coordinates.BodyCoordinates }

Get the position and orientation of the body in the world as Frame3d.

This is useful to transform points and directions between world and body coordinates.

originPoint : Body data -> Point3d Length.Meters Physics.Coordinates.WorldCoordinates

Get the origin point of a body in the world

velocity : Body data -> Vector3d Speed.MetersPerSecond Physics.Coordinates.WorldCoordinates

Get the linear velocity of a body

angularVelocity : Body data -> Vector3d AngularSpeed.RadiansPerSecond Physics.Coordinates.WorldCoordinates

Get the angular velocity of a body

velocityAt : Point3d Length.Meters Physics.Coordinates.WorldCoordinates -> Body data -> Vector3d Speed.MetersPerSecond Physics.Coordinates.WorldCoordinates

Get the linear velocity of a point on a body.

This takes into account both linear and angular velocities of the body.

centerOfMass : Body data -> Point3d Length.Meters Physics.Coordinates.BodyCoordinates

Get the center of mass of a body in the body coordinate system.

mass : Body data -> Maybe Mass

Get a mass of a body. Returns Nothing if a body is not dynamic.

Position and orientation

moveTo : Point3d Length.Meters Physics.Coordinates.WorldCoordinates -> Body data -> Body data

Set the position of the body in the world, e.g. to raise a body 5 meters above the origin:

movedBody =
    body
        |> moveTo (Point3d.meters 0 0 5)

translateBy : Vector3d Length.Meters Physics.Coordinates.WorldCoordinates -> Body data -> Body data

Move the body in the world relative to its current position, e.g. to translate a body down by 5 meters:

translatedBody =
    body
        |> translateBy (Vector3d.meters 0 0 -5)

rotateAround : Axis3d Length.Meters Physics.Coordinates.WorldCoordinates -> Angle -> Body data -> Body data

Rotate the body in the world around axis, e.g. to rotate a body 45 degrees around Z axis:

movedBody =
    body
        |> rotateAround Axis3d.z (Angle.degrees 45)

User-Defined Data

data : Body data -> data

Get user-defined data.

withData : data -> Body data -> Body data

Update user-defined data.

Interaction

applyForce : Quantity Basics.Float Force.Newtons -> Direction3d Physics.Coordinates.WorldCoordinates -> Point3d Length.Meters Physics.Coordinates.WorldCoordinates -> Body data -> Body data

Apply a force in a direction at a point on a body. The force will be applied during one simulation step.

Keep applying the force every simulation step to accelerate.

pushedBox =
    box
        |> applyForce
            (Force.newtons 50)
            Direction3d.positiveY
            pointOnBox

applyImpulse : Quantity Basics.Float (Quantity.Product Force.Newtons Duration.Seconds) -> Direction3d Physics.Coordinates.WorldCoordinates -> Point3d Length.Meters Physics.Coordinates.WorldCoordinates -> Body data -> Body data

Apply an impulse in a direction at a point on a body. Applying an impulse is the same as applying a force during the interval of time. The changes are applied to velocity and angular velocity of the body.

For example, to hit a billiard ball with a force of 50 newtons, with the duration of the hit 0.005 seconds:

impulse =
    Force.newtons 50
        |> Quantity.times (Duration.seconds 0.005)

hitCueBall =
    cueBall
        |> applyImpulse
            impulse
            Direction3d.positiveY
            hitPoint

Advanced

withMaterial : Physics.Material.Material -> Body data -> Body data

Set the material to control friction and bounciness.

compound : List Physics.Shape.Shape -> data -> Body data

Make a compound body from a list of shapes.

For example, the sphere from above can be defined like this:

sphere radius data =
    compound
        [ Shape.sphere
            (Sphere3d.atOrigin (meters 1))
        ]
        data

We only support rigid bodies.

Under the hood, we find the center of mass and the inertia tensor. It is assumed, that the shapes have the same density and do not overlap.

withDamping : { linear : Basics.Float, angular : Basics.Float } -> Body data -> Body data

Set linear and angular damping, in order to decrease velocity over time.

These parameters specify the proportion of velocity lost per second.

This may be useful to e.g. simulate the friction of a sphere rolling on the flat surface. The normal friction between these surfaces doesn’t work, because there is just 1 contact point.

Inputs are clamped between 0 and 1, the defaults are 0.01.

transformWithInverseInertia : Body data -> Vector3d units Physics.Coordinates.WorldCoordinates -> Vector3d (Quantity.Rate units (Quantity.Product Mass.Kilograms (Quantity.Squared Length.Meters))) Physics.Coordinates.WorldCoordinates

Transform a vector using the inverse moment of inertia of a body.

This lets you compute angular acceleration from torque, or angular velocity contribution from impulse.

You’ll most likely need to use Vector3d.unwrap on the result.