ArnoudBuzing/PhysicsModelLink

Rigid body physics simulation and visualization for standard Wolfram Language 3D primitives

Paclet Manifest

Web ContentResourceCreateNotebook

Headline ImageResourceCreateNotebook

Basic DescriptionResourceCreateNotebook

PhysicsModelLink provides a high-level interface for creating and simulating rigid body physics in the Wolfram Language. It lets you wrap standard 3D graphics primitives—such as spheres, cuboids, cylinders, cones, and capsules—as dynamic or fixed bodies, run time-stepped physics simulations with gravity and collisions, and visualize or animate the results as Graphics3D scenes.

DetailsResourceCreateNotebook

PhysicsModelLink provides rigid body physics simulation for standard Wolfram Language 3D graphics primitives including Sphere, Cuboid, Cylinder, Cone, and CapsuleShape.

The underlying physics engine is the Rapier 3D physics library (Rust crate rapier3d), accessed via LibraryLink.

Simulations are stateful: CreatePhysicsModel allocates a persistent physics world in memory, and DestroyPhysicsModel frees it. Each world is identified by a unique integer handle.

Bodies are classified as either DynamicBody (affected by gravity and collisions) or FixedBody (immovable obstacles/floors).

Each body has physical material properties that can be set via options: "Density" (default 1.0), "Restitution" (bounciness, default 0.5), and "Friction" (default 0.5).

Initial velocities can be assigned to dynamic bodies using the "Velocity" option.

Body orientations are tracked internally as quaternions and converted to/from 3×3 rotation matrices for compatibility with GeometricTransformation.

Time evolution is performed with PhysicsModelIterate, which steps the simulation by a given number of substeps at a fixed time increment dt. Smaller dt values yield more accurate results.

PhysicsModelEvolve is a convenience function that collects a sequence of PhysicsModelObject frames for animation.

PhysicsModelPlot renders the current state as a Graphics3D scene, automatically applying positions and rotations returned by the engine.

PhysicsBoundaryBox generates six invisible FixedBody walls to confine objects within a bounding region.

PhysicsModelVideo produces an AnimationVideo from a list of simulation frames.

The Rapier library is compiled as a platform-specific shared library (.dylib on macOS,.so on Linux,.dll on Windows) and loaded from the paclet's LibraryResources/$SystemID/ directory at package initialization.

Primary ContextResourceCreateNotebook

ArnoudBuzing`PhysicsModelLink`

Main Guide PageResourceCreateNotebook

ExamplesResourceCreateNotebook

Initialization for ExamplesResourceCreateNotebook

PacletDirectoryLoad["/Users/arnoudb/github/PhysicsModelLink/PhysicsModelLink"];

Needs["ArnoudBuzing`PhysicsModelLink`"];

Basic Examples

Create a simple model with a falling ball and a fixed floor:

model=CreatePhysicsModel[{
PhysicsBoundaryBox[{{-4,-4,0},{4,4,6}},"Thickness"->1],
FixedBody[{HatchShading[.6,Blue],Cuboid[{-4,-4,-1},{4,4,0}]}],
DynamicBody[{MaterialShading["Gold"],Sphere[{0,0,5},0.6]}]},
]

Plot the model in its initial state:

PhysicsModelPlot[model]

Evolve the model for 300 steps with time step 1/60:

frames=PhysicsModelEvolve[model,300,1/60];

Generate a video from the frames:

PhysicsModelVideo[frames,PlotRange->1.01` {{-5,5},{-5,5},{-1,6}}]

Create a model with four balls with various levels of bounciness:

model=CreatePhysicsModel[{PhysicsBoundaryBox[{{-4,-4,0},{4,4,6}},"Thickness"->1],FixedBody[{HatchShading[.6,Gray],Cuboid[{-4,-4,-1},{4,4,0}]},"Restitution"->1.0],DynamicBody[{MaterialShading["Gold"],Sphere[{-2.5,0,5.0},0.5]},"Restitution"->0.95],DynamicBody[{MaterialShading["Copper"],Sphere[{-0.8,0,5.0},0.5]},"Restitution"->0.6],DynamicBody[{MaterialShading["Silver"],Sphere[{0.8,0,5.0},0.5]},"Restitution"->0.2],DynamicBody[{MaterialShading["Brass"],Sphere[{2.5,0,5.0},0.5]},"Restitution"->0.0]},
];

Evolve the model for 300 steps with time step 1/60:

frames=PhysicsModelEvolve[model,300,1.0/60.0];

Generate a video from the frames:

PhysicsModelVideo[frames,PlotRange->1.03 {{-4,4},{-4,4},{-0.5,6}}]

Create a model with an avalanche of spheres:

model=CreatePhysicsModel[{PhysicsBoundaryBox[{{-5,-5,-10},{5,5,16}}],FixedBody[{Sphere[{0,0,-6},4]}],Flatten@Table[DynamicBody[{Sphere[{i,j,k}+RandomReal[{-0.01,0.01},3],0.25]}],{i,-3,3},{j,-3,3},{k,0,14}]},]

Evolve the model for 300 steps with time step 1/60:

frames=PhysicsModelEvolve[model,300,1/60];

Generate a video from the frames:

PhysicsModelVideo[frames,PlotRange->1.05 {{-7,7},{-7,7},{-10,2}}]

Create a model with a dodecahedron rolling on an inclined plane:

dodecahedron=Translate[ConvexHullMesh[N[PolyhedronData["Dodecahedron","Points"]]],{3,0,5}];
model=CreatePhysicsModel[{
DynamicBody[{StandardOrange,HatchShading[],dodecahedron}],PhysicsBoundaryBox[{{-5,-5,0},{5,5,7}}],FixedBody[{Gray,HatchShading[],ConvexHullMesh[{{-5,-5,0},{-5,5,0},{5,5,0},{5,-5,0},{-5,-5,1},{-5,5,1},{5,5,3},{5,-5,3}}]}]},]

Evolve the model for 300 steps with time step 1/60:

frames=PhysicsModelEvolve[model,500,1/60.0];

Generate a video from the frames:

PhysicsModelVideo[frames,PlotRange->1.01 {{-5,5},{-5,5},{0,7}}]

Create a collection of "dominoes":

dominoes=Table[DynamicBody[{MaterialShading["Copper"],Cuboid[{x-0.08,-0.3,0},{x+0.08,0.3,0.8}]}],{x,-3,3,0.6}];

Create a ball that will push over the dominoes:

ball=DynamicBody[{MaterialShading["Gold"],Sphere[{-3.8,0,0.4},0.35]},"Density"->5.0,"Velocity"->{3,0,0}];

Create the model from the ball and dominoes:

model=CreatePhysicsModel[{PhysicsBoundaryBox[{{-4,-4,0},{4,4,6}},"Thickness"->1],FixedBody[{HatchShading[.6,Gray],Cuboid[{-4,-4,-1},{4,4,0}]}],dominoes,ball},"Gravity"->{0,0,-9.81},"Graphics3DOptions"->{Background->Black,Axes->False,Boxed->False,ViewPoint->Front,ImageSize->Large}];

Evolve the model for 300 steps with time step 1/60:

frames=PhysicsModelEvolve[model,300,1.0/60.0];

Generate a video from the frames:

PhysicsModelVideo[frames,PlotRange->1.03 {{-4,4},{-4,4},{-0.5,6}}]

Create a model with a large number of cones:

model=CreatePhysicsModel[{PhysicsBoundaryBox[{{-4,-4,0},{4,4,6}},"Thickness"->1],FixedBody[{HatchShading[.6,Blue],Cuboid[{-4,-4,-1},{4,4,0}]}],FixedBody[{HatchShading[.6,Orange],Cylinder[{{-2,-2,0.5},{2,2,0.5}},1.0]}],Table[DynamicBody[{MaterialShading["Copper"],Cone[{{i,j,4},{i+RandomReal[{0,0.1}],j+RandomReal[{0,0.1}],5}},0.25]}],{i,-3,3,1},{j,-3,3,1}]},];

Evolve the model for 300 steps with time step 1/60:

frames=PhysicsModelEvolve[model,300,1.0/60.0];

Generate a video from the frames:

PhysicsModelVideo[frames,PlotRange->1.03 {{-4,4},{-4,4},{-0.5,6}}]

Scope

Source & Additional Information

CreatorResourceCreateNotebook

Arnoud Buzing

Source Control RepositoryResourceCreateNotebook

https://github.com/arnoudbuzing/PhysicsModelLink

LicenseResourceCreateNotebook

KeywordsResourceCreateNotebook

keyword 1

CategoriesResourceCreateNotebook

Related Resource ObjectsResourceCreateNotebook

Resource Name (resources from any Wolfram repository)

Original Source References and AttributionsResourceCreateNotebook

Source, reference or citation

LinksResourceCreateNotebook

Link to other related material

CompatibilityResourceCreateNotebook

Wolfram Language VersionResourceCreateNotebook

14.1+

Operating SystemResourceCreateNotebook

EnvironmentsResourceCreateNotebook

Cloud SupportResourceCreateNotebook

Required FeaturesResourceCreateNotebook

DisclosuresResourceCreateNotebook

Portions of the paclet code were interactively generated with the help of LLMs.

Author NotesResourceCreateNotebook

Additional information about limitations, issues, etc.