/spg

A C++ physics simulation library with automatic derivatives and multiple solvers such as XPBD, Vertex Block Descent or Newton Backward Euler

Primary LanguageC++MIT LicenseMIT

SPG

SPG (short for Spring) is a research-focused C++ physics simulation library for easy implementation and comparison of solvers and mechanical energy models. It provides a common interface for solvers and energies, making all solver implementations compatible with all energies without requiring additional effort. A set of solvers and energies are already implemented in SPG. I personally use it to implement and compare interesting ideas from state-of-the-art research.

SPG solver comparison example

General nonlinear energies $E(x) = f(x)$ are supported. Energies of the particular form $E(x) = \frac{1}{2}C(x)^T K C(x)$, with $C(x)$ a vector of nonlinear constraint functions and $K$ a stiffness matrix, can also be defined by providing just the implementation of $C(x)$ and become automatically compatible with constraint-based solvers (e.g. XPBD) as well as energy-based and force-based solvers.

Through the use of autodiff and templates (using TinyAD as autodiff backend), automatic first and second order derivatives are provided from a simple energy or constraint definition. This helps to keep the code to a minimum, very close to the actual formulas of the corresponding solvers and models. It is also possible to override these automatic versions with more efficient custom implementations if needed.

As an example, by providing the following constraint code for the Discrete Bending Energy, the corresponding constraint derivatives, energy, forces and force jacobians are automatically available, making it compatible with all the implemented solvers:

    [...]
    const Vector3T<RealT> e0 = x1 - x0;
    const Vector3T<RealT> e3 = x2 - x1;
    const Vector3T<RealT> e4 = x3 - x1;

    const Vector3T<RealT> n1 = e0.cross(e3).normalized();
    const Vector3T<RealT> n2 = -e0.cross(e4).normalized();

    const auto theta = atan2((n1.cross(n2)).dot(e0.normalized()), n1.dot(n2));
    const auto constraint = theta - restTheta;
    [...]

Current implemented solvers

Current implemented energies

The current implementations are focused on parallel CPU simulation of deformables, including cloth, spring systems and finite element models. Some of the solvers meant for GPU computation may underperform, but this common framework allows to analyse and compare other important aspects such as convergence and stability properties.

This is still a experimental project, which is the best excuse I can think of to justify the lack of proper documentation and unit testing.

I intend to explore several big features in the future, in no particular order (if you are interested in contributing, let me know):

  • Unified energy damping model
  • Proper boundary conditions
  • Collision detection
  • Rigid bodies
  • Differentiable simulation
  • GPU support

Compilation and dependencies

CMake is used to generate and compile the project. It has been tested in Windows 11 with VSCode and MSVC 19, and in Ubuntu 24.04. You can configure it in your preferred IDE. The apps/ folder contains demo examples, including a small elastic pendulum simulation with the basics of setting up and simulating a scene, and a solver comparison demo that allows to set up different scenes and simulate them with multiple configurable solvers.

SPG uses Eigen and TinyAD as dependencies. The solver comparison demo also uses Polyscope for GUI and rendering. All of these come as submodules.

For a quick Terminal compilation on both Windows and Ubuntu, run:

git clone https://github.com/alexrodag/spg.git
cd spg
git submodule update --init --recursive
mkdir build
cd build
cmake ..
cmake --build . --config Release -j

Note: In Ubuntu, if there is an error when configuring polyscope, you may need to run the following (check updated instructions in https://polyscope.run/building/) )

sudo apt install xorg-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev

Author: Alex Rodriguez