Dynamics
The DynamicsExtensions class provides extension methods for particle dynamics โ forces, momentum, energy, work, power, and collisions.
๐๏ธ Newton's Lawsโ
Compute acceleration from force, force from mass and acceleration, net force, and weight:
// Newton's 2nd law: a = F/m
var force = new Vector(10, 0, 0);
Vector acceleration = force.Acceleration(mass: 5); // (2, 0, 0)
// F = ma
Vector F = 10.0.Force(new Vector(0, 0, -9.8)); // (0, 0, -98)
// Sum of forces
Vector net = f1.NetForce(f2, f3);
// Weight (default direction: -Z)
Vector W = 80.0.Weight(); // (0, 0, -784.5)
๐ฅ Momentum & Impulseโ
Compute linear momentum and impulse:
Vector p = 5.0.Momentum(new Vector(3, 4, 0)); // (15, 20, 0)
Vector J = force.Impulse(duration: 0.5); // Fยทฮt
Vector J2 = mass.ImpulseFromVelocityChange(vBefore, vAfter); // mยทฮv
Vector vNew = impulse.ApplyImpulse(mass: 5, v0); // v + J/m
โก Energyโ
Compute kinetic energy, potential energy, and mechanical energy:
double ke = 4.0.KineticEnergy(new Vector(3, 4, 0)); // ยฝmvยฒ = 50 J
double pe = 10.0.PotentialEnergy(height: 5); // mgh
double U = m1.GravitationalPotentialEnergy(m2, r); // -Gmโmโ/r
double E = mass.MechanicalEnergy(velocity, height); // KE + PE
double v = mass.SpeedFromKineticEnergy(ke); // โ(2ยทKE/m)
๐ง Work & Powerโ
Compute work done by a force and instantaneous or average power:
double W = force.Work(displacement); // Fยทd (dot product)
double W2 = 10.0.Work(5, angleRadians: Math.PI / 3); // Fยทdยทcos(ฮธ) = 25 J
double P = force.Power(velocity); // Fยทv (instantaneous)
double P2 = 100.0.AveragePower(duration: 5); // W/ฮt = 20 W
double ฮKE = mass.WorkEnergyTheorem(vBefore, vAfter); // ยฝm(vโยฒ - vโยฒ)
๐ซ Elastic & Inelastic Collisionsโ
Compute outcomes of 1D and 3D collisions:
// 1D elastic collision โ both momentum and energy conserved
var (v1f, v2f) = m1.ElasticCollision(v1, m2, v2);
// Perfectly inelastic (sticky) collision
double vf = m1.InelasticCollisionVelocity(v1, m2, v2);
Vector vf3d = m1.InelasticCollisionVelocity(v1Vec, m2, v2Vec); // 3D version
double loss = m1.InelasticCollisionEnergyLoss(v1, m2, v2);
// Coefficient of restitution: e = 1 (elastic), e = 0 (perfectly inelastic)
double e = v1Before.CoefficientOfRestitution(v2Before, v1After, v2After);
๐งฑ Rigid Bodyโ
Create rigid bodies from standard shapes with automatic inertia tensors:
var sphere = RigidBody.CreateSolidSphere(mass: 10, radius: 2);
var box = RigidBody.CreateSolidBox(mass: 12, width: 2, height: 3, depth: 4);
var cyl = RigidBody.CreateSolidCylinder(mass: 6, radius: 1, height: 4);
var hollow = RigidBody.CreateHollowSphere(mass: 5, radius: 3);
var tube = RigidBody.CreateHollowCylinder(mass: 8, innerRadius: 1, outerRadius: 2, height: 3);
var rod = RigidBody.CreateThinRod(mass: 4, length: 5);
var wall = RigidBody.CreateStatic(new Vector(0, 0, 0)); // immovable
Apply forces, torques, and query state:
var body = RigidBody.CreateSolidSphere(10, 1);
body.Position = new Vector(0, 5, 0);
body.Velocity = new Vector(3, 0, 0);
body.ApplyForce(new Vector(0, 0, -98)); // gravity
body.ApplyForceAtPoint( // generates torque too
new Vector(10, 0, 0), worldPoint: new Vector(0, 1, 0));
body.ApplyTorque(new Vector(0, 0, 5));
Vector a = body.LinearAcceleration; // F/m
Vector alpha = body.AngularAcceleration; // Iโปยนฯ
Vector p = body.LinearMomentum; // mv
Vector L = body.AngularMomentum; // Iฯ
double KE = body.KineticEnergy; // ยฝmvยฒ + ยฝฯแตIฯ
body.ClearForces(); // reset accumulators after integration step
โฑ๏ธ RigidBody Integrationโ
Three time-stepping methods advance a RigidBody by one dt. Each delegates to the corresponding ODE solver in DifferentialEquationExtensions, packing body state into VectorN internally.
// Semi-implicit (symplectic) Euler โ stable for games, first-order
// Apply forces before calling; accumulators are cleared afterwards
var body = RigidBody.CreateSolidSphere(10, 1);
body.Position = new Vector(0, 0, 100);
body.ApplyForce(new Vector(0, 0, -9.80665 * body.Mass));
body.IntegrateSemiImplicitEuler(dt: 0.001);
// Velocity Verlet โ O(dtยฒ) accuracy, excellent energy conservation
// Forces are evaluated by forceFunc (no need to pre-apply)
Func<RigidBody, (Vector force, Vector torque)> gravity = b =>
(new Vector(0, 0, -9.80665 * b.Mass), new Vector(0, 0, 0));
body.IntegrateVelocityVerlet(gravity, dt: 0.01);
// Explicit Euler โ simplest, least stable
body.ApplyForce(new Vector(0, 0, -9.80665 * body.Mass));
body.IntegrateEuler(dt: 0.001);
๐งฒ Common Force Modelsโ
Ready-made force functions for building simulations โ combine them in a forceFunc for the integrators.
// Spring (Hooke's law): F = -kยท(|ฮr| - Lโ)ยทrฬ
var spring = 50.0.SpringForce(restLength: 2.0, position, anchor);
// Viscous damping: F = -cยทv
var damping = 0.5.DampingForce(velocity);
// Aerodynamic drag: F = -ยฝยทCdยทฯยทAยท|v|ยทv
var drag = 0.47.DragForce(fluidDensity: 1.225, crossSectionArea: 0.01, velocity);
// Friction (kinetic โ moving object)
var kinetic = 0.3.FrictionForce(normalForceMagnitude: 98, velocity);
// Friction (static โ stationary object, opposes applied force up to ฮผN)
var friction = 0.5.FrictionForce(normalForceMagnitude: 100, velocity: new Vector(0, 0, 0),
appliedTangentialForce: new Vector(20, 0, 0)); // returns (-20, 0, 0)
// Compose forces in a Verlet simulation
Func<RigidBody, (Vector, Vector)> forces = b =>
{
var F = 50.0.SpringForce(2.0, b.Position, new Vector(0, 0, 0))
+ 0.5.DampingForce(b.Velocity);
return (F, new Vector(0, 0, 0));
};
body.IntegrateVelocityVerlet(forces, dt: 0.01);
๐ Moment of Inertia (Scalar)โ
double I = 10.0.MomentOfInertiaSolidSphere(radius: 2); // 2/5ยทmrยฒ
double I2 = 10.0.MomentOfInertiaHollowSphere(radius: 2); // 2/3ยทmrยฒ
double I3 = 8.0.MomentOfInertiaSolidCylinder(radius: 3); // ยฝmrยฒ
double I4 = 6.0.MomentOfInertiaThinRod(length: 4); // mLยฒ/12
double I5 = 6.0.MomentOfInertiaThinRodEnd(length: 4); // mLยฒ/3
double I6 = 12.0.MomentOfInertiaSolidBox(sideA: 3, sideB: 4); // m/12ยท(aยฒ+bยฒ)
// Parallel axis theorem: I_new = I_cm + mยทdยฒ
double Inew = I.ParallelAxis(mass: 10, distance: 3);
๐งฎ Inertia Tensor (3ร3 Matrix)โ
Matrix I = 10.0.InertiaTensorSolidSphere(radius: 2);
Matrix Ib = 12.0.InertiaTensorSolidBox(width: 2, height: 3, depth: 4);
Matrix Ic = 6.0.InertiaTensorSolidCylinder(radius: 1, height: 4);
// Parallel axis theorem for 3ร3 tensor: I_new = I_cm + mยท(dยฒE - dโd)
Matrix Inew = I.ParallelAxis(mass: 10, offset: new Vector(3, 0, 0));
๐ Torque & Rotational Dynamicsโ
// Vector: ฯ = r ร F
Vector tau = momentArm.Torque(force);
// Scalar: ฯ = Fยทrยทsin(ฮธ)
double tau2 = 20.0.Torque(momentArm: 3, angleRadians: Math.PI / 6);
// Angular momentum: L = Iฯ
Vector L = inertiaTensor.AngularMomentum(omega);
double Ls = momentOfInertia.AngularMomentum(omega);
// Angular acceleration: ฮฑ = Iโปยนฯ
Vector alpha = inverseInertiaTensor.AngularAcceleration(torque);
// Rotational kinetic energy: KE = ยฝฯแตIฯ
double KE = inertiaTensor.RotationalKineticEnergy(omega);
double KEs = momentOfInertia.RotationalKineticEnergy(omega);