LuisaComputeSimulator is a high-performance cross-platform physics simulator built on LuisaCompute. It provides real-time simulation of soft bodies, cloth, and rigid bodies with penetration-free contact handling, accelerated by GPU/CPU backends.
Performance Demo: 88K vertices, 174K triangles, 3M+ collision pairs → ~3 FPS on RTX 3090 (CUDA), ~2 FPS on M2 Max (Metal)
| Feature | Description |
|---|---|
| Soft Body / Cloth Simulation | High-resolution soft-body and cloth simulation with FEM-based constitutive models |
| Rigid Body Dynamics | Rigid body simulation with collision and friction |
| Soft-Cloth-Rigid Coupling | Seamless interaction among soft bodies, cloth, and rigid bodies in one solver |
| Penetration-Free Contact (IPC) | Robust collision handling using barrier functions |
| Affine Body Dynamics (ABD) | Efficient reduced-space simulation for rigid bodies |
| Multi-Backend Support | CUDA, DirectX 12, Vulkan, Metal, CPU (Fallback) |
| Python & C++ APIs | Flexible programming interfaces for different use cases |
| Interactive GUI | Real-time visualization with Polyscope |
- ✅ Soft Body / Cloth Simulation (Spring + ARAP FEM)
- ✅ Rigid Body Simulation
- ✅ Soft-Rigid Body Coupling
- ✅ Cloth-Soft-Rigid Coupling
- ✅ Ground Collision
- ✅ Frictional Contact
- ✅ Continuous Collision Detection (CCD)
- ✅ Fixed Point / Pinned Constraints
- ✅ Tetrahedral Mesh (In Development)
- 🔄 Joint Constraints (Planned)
- 🔄 OpenUSD Scene Support
Sample Python-frontend code can be found at:
- test_cloth_animation (cloth twisting animation)
- test_soft_folding.py (soft-body tetrahedral simulation)
- test_cloth_soft_rigid_coupling.py (cloth-soft-rigid coupling)
import os
import sys
import trimesh
import numpy as np
root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
sys.path.insert(0, os.path.join(root, "build", "bin"))
import lcs_py as lcs
# Initialize solver with backend
solver = lcs.NewtonSolver()
solver.init_device(backend_name="metal") # or cuda, dx, vk
# Create rigid body from mesh file
cube_mesh = trimesh.load("cube.obj", process=False)
cube = solver.create_world_data_from_array("cube", cube_mesh.vertices, cube_mesh.faces)
cube.set_simulation_type(lcs.MaterialType.Rigid)
cube.set_translation(0.0, 0.34, 0.0)
cube.set_rotation(0.5235988, 0.0, 0.5235988)
cube.set_scale(0.1)
cube_id = solver.register_world_data(cube)
# Create cloth from file with different stretch models
cloth = solver.create_world_data_from_file_path("cloth", "square2K.obj")
cloth.set_simulation_type(lcs.MaterialType.Cloth)
# Configure cloth material with different constitutive models:
# - Spring: Basic linear spring energy
# - FEM_BW98: Finite element method (stable for large deformations)
cloth.set_physics_material_cloth(
thickness=0.001,
youngs_modulus=1e6,
poisson_ratio=0.3,
stretch_model="FEM_BW98", # or "Spring"
bending_model="QuadraticBending"
)
cloth.set_scale(0.75)
# Add fixed points
cloth.add_fixed_point_by_method("LeftBack")
cloth.add_fixed_point_by_method("RightBack")
cloth.add_fixed_point_by_method("LeftFront")
cloth.add_fixed_point_by_method("RightFront")
cloth_id = solver.register_world_data(cloth)
# Configure simulation
config = solver.get_config()
config.use_floor = False
config.use_self_collision = False
config.implicit_dt = 1/60
# Initialize solver (compiles shaders, allocates buffers)
solver.init_solver()
# Run simulation
for frame in range(100):
solver.physics_step_gpu()
solver.save_sim_result(f"output/frame_{frame}.obj")
solver.cleanup_device()Sample Cpp-frontend code can be found at app_integration.cpp.
#include <string>
#include <vector>
#include "SimulationSolver/newton_solver.h"
int main(int argc, char** argv)
{
// Set log level
luisa::log_level_info();
// Parse backend from command line
std::string backend = (argc >= 2) ? argv[1] : "";
// Create solver instance
lcs::NewtonSolver solver;
solver.create_device(argv[0], backend);
// ========================================================================
// Cloth with FEM_BW98 (Finite Element Method) - large deformations
// ========================================================================
auto upper_square = lcs::Initializer::WorldData()
.set_name("upper square")
.load_mesh_from_path(std::string(LCSV_RESOURCE_PATH) + "/InputMesh/square2.obj")
.set_material_type(lcs::Material::MaterialType::Cloth)
.set_physics_material(lcs::Material::ClothMaterial{
.stretch_model = lcs::Material::ConstitutiveStretchModelCloth::FEM_BW98,
.bending_model = lcs::Material::ConstitutiveBendingModelCloth::DihedralAngle,
.thickness = 0.001f,
.youngs_modulus = 1e6f,
.poisson_ratio = 0.3f,
})
.set_translation({ 0.0f, 0.4f, 0.0f });
uint upper_square_id = solver.register_world_data(upper_square);
// ========================================================================
// Cloth with Spring model - linear, fast
// ========================================================================
std::vector<std::array<float, 3>> square_mesh_vertices{ { -0.5, 0, -0.5 }, { 0.5, 0, -0.5 }, { -0.5, 0, 0.5 }, { 0.5, 0, 0.5 } };
std::vector<std::array<uint, 3>> square_mesh_faces{ { 0, 3, 1 }, { 0, 2, 3 } };
auto lower_square = lcs::Initializer::WorldData()
.set_name("lower square")
.load_mesh_from_array(square_mesh_vertices, square_mesh_faces)
.set_material_type(lcs::Material::MaterialType::Cloth)
.set_physics_material(lcs::Material::ClothMaterial{
.stretch_model = lcs::Material::ConstitutiveStretchModelCloth::Spring
})
.set_scale(0.8f)
.set_translation({ 0.1f, 0.2f, 0.0f })
.add_fixed_point_from_method({ .method = lcs::Initializer::FixedPointsType::Left })
.add_fixed_point_from_method({ .method = lcs::Initializer::FixedPointsType::Right });
uint lower_square_id = solver.register_world_data(lower_square);
// Configure solver
auto& config = solver.get_config();
config.use_floor = false;
config.use_self_collision = true;
config.implicit_dt = 1.0 / 60.0;
config.use_energy_linesearch = true;
config.nonlinear_iter_count = 10;
config.pcg_iter_count = 100;
// Initialize solver (compiles shaders, allocates buffers)
solver.init_solver();
// Get initial vertices
std::vector<std::vector<std::array<float, 3>>> rendering_vertices;
solver.get_curr_vertices_to_host(rendering_vertices);
// Main simulation loop
for (uint ii = 0; ii < 20; ii++)
{
solver.physics_step_GPU(); // or solver.physics_step_CPU()
solver.get_curr_vertices_to_host(rendering_vertices);
// Render or process vertices here
}
// Save result
solver.save_mesh_to_obj(luisa::format("{}/OutputMesh/sample.obj", LCSV_RESOURCE_PATH));
return 0;
}You can use Cmake:
# Clone the repository
git clone https://github.com/ChengzhuUwU/LuisaComputeSimulator.git
cd LuisaComputeSimulator
# Configure and build (CMake)
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -jYou can also use Xmake:
# Clone dependencies
xmake lua setup.lua
# Configure (platform-specific)
xmake f -m release
xmake build# Run with default scene
./build/bin/app_simulation
# Specify backend and scene
./build/bin/app_simulation cuda Resources/Scenes/cloth_rigid_coupling_high_res.json# With GUI (requires polyscope)
python PythonBindings/example_usage.py --backend cuda
# Headless mode (batch processing)
python PythonBindings/example_usage.py --backend cuda --headless --advance_frames 60Note: Most used backends in LuisaCompute :
cuda,dx(DirectX),vk(Vulkan),metal(macOS)
More compiling details can be found at BUILD.md
| Backend | Windows | Linux | MacOS | Description |
|---|---|---|---|---|
| CUDA | Supported | Supported | Requires CUDA Toolkit (CUDA > 12.0) | |
| Vulkan | Supported | Experimental | Developing | Requires vulkan SDK. Linux (currently for x86_64 only) and Macos is in development |
| DirectX12 | Supported | |||
| Metal | Supported | |||
| Fallback | Supported | Supported | Supported | CPU fallback via TBB/Embree. Requires llvm, TBB and Embree |
| 88K vertices, 174K triangles, 3M+ collision pairs |
|---|
![]() |
| ~3 FPS on RTX 3090 (CUDA), ~2 FPS on M2 Max (Metal) |
| Scene | Preview | Description |
|---|---|---|
| Cloth-Rigid Coupling | ![]() |
High-res cloth on rigid cube |
| Rotation Cylinder 7K | ![]() |
Cloth wrapping cylinder |
| Pinned Cloth | ![]() |
Different material properties |
| Moving Boundary | ![]() |
Dynamic Dirichlet boundary |
| Rigid Bucket | ![]() |
Multi-body collision |
| Folding Cubes | ![]() |
Self-collision folding |
| Friction Test | ![]() |
Frictional contact |
- Python Bindings
- Cloth Simulation
- Rigid Body Simulation
- Soft Body (Spring + ARAP FEM)
- Soft-Cloth-Rigid Coupling
- Penetration-Free Contact (IPC)
- Affine Body Dynamics
- Frictional Modeling
- C++ Integration API
- Tetrahedral Mesh Support
- Joint Constraints
- UV Mapping Package
- Strain Limiting
- Consistent Solve
- Thin Shell Rigid-Body
- Matrix Assembly Optimization
- Better Preconditioners
- Constitutions: libuipc, GAMES 103, PNCG-IPC, HOBAK, solid-sim-tutorial, Codim-IPC, ZOZO's Contact Solver
- DCD & CCD: ZOZO's Contact Solver, libuipc.
- PCG (Linear Equation Solver): MAS, AMGCL, libuipc.
- Framework: libshell, LuisaComputeGaussSplatting.
- GPU Intrinsic: LuisaComputeGaussSplatting.
- Collision Energy: MAS, PNCG-IPC
- Affine Body Dynamics: abd-warp, libuipc (documentation, theory derivation).
This project is licensed under the MIT License. See LICENSE for details.
Thanks to LuisaCompute and Libuipc community, their open-source spirit has propelled the advancement of the reality.
LuisaComputeSimulator — High-Performance Physics Simulation 📈








