flutter_scene_rapier 0.5.2
flutter_scene_rapier: ^0.5.2 copied to clipboard
Rapier 3D physics backend for flutter_scene. Implements the scene package's physics simulation contract against Rapier via FFI.
flutter_scene_rapier #
A Rapier 3D physics backend for
flutter_scene. It implements the
abstract physics contract from flutter_scene (rigid bodies, colliders,
joints, queries, and collision events) against the Rapier engine over
dart:ffi, with a WebAssembly backend for the web.
Status: experimental. The API may change between releases.
Requirements #
No Rust toolchain for the supported platforms below. The build hook downloads a precompiled library for your target and verifies its checksum. Other targets fall back to building from source, which needs Rust.
Platform support #
| Platform | Prebuilt binary | Notes |
|---|---|---|
| Android (arm64, armv7, x64) | yes | |
| iOS (arm64 device + arm64 sim) | yes | x86_64 simulator builds from source |
| macOS (Apple Silicon) | yes | Intel builds from source |
| Linux (x64, arm64) | yes | |
| Windows (x64, arm64) | yes | |
| Web | yes | loads a WebAssembly module at runtime |
Install #
dependencies:
flutter_scene: ^0.24.0
flutter_scene_rapier: ^0.5.2
Quick start #
Wrap a RapierWorld in flutter_scene's PhysicsWorld component on the
scene root, then attach RigidBody and Collider components to the nodes
you want simulated (the body goes on before the collider). The scene
advances physics on a fixed timestep and interpolates transforms for you.
import 'package:flutter_scene/physics.dart';
import 'package:flutter_scene/scene.dart';
import 'package:flutter_scene_rapier/flutter_scene_rapier.dart';
import 'package:vector_math/vector_math.dart';
await RapierWorld.ensureInitialized();
final scene = Scene();
final world = PhysicsWorld(RapierWorld(gravity: Vector3(0, -9.81, 0)));
scene.root.addComponent(world);
// A static floor.
final floor = Node(localTransform: Matrix4.translation(Vector3(0, -0.5, 0)));
floor.addComponent(RigidBody(type: BodyType.fixed));
floor.addComponent(Collider(shape: BoxShape(halfExtents: Vector3(10, 0.5, 10))));
scene.add(floor);
// A falling dynamic box.
final box = Node(localTransform: Matrix4.translation(Vector3(0, 5, 0)));
box.addComponent(RigidBody(type: BodyType.dynamic_, mass: 1));
box.addComponent(Collider(shape: BoxShape(halfExtents: Vector3.all(0.5))));
scene.add(box);
world.collisions.listen((event) {
// CollisionBegan, CollisionEnded, TriggerEntered, or TriggerExited.
});
Each frame, advance and render the scene:
scene.update(deltaSeconds); // steps physics + interpolates
scene.render(camera, canvas, viewport: Offset.zero & size);
Beyond rigid bodies and colliders, the backend supports every flutter_scene
joint (FixedJoint, SphericalJoint, RevoluteJoint, PrismaticJoint,
and GenericJoint, with limits and motors), the kinematic character
controller (KinematicCharacterController.move), and scene queries
(world.raycast, world.raycastAll, world.overlapSphere,
world.overlapBox, world.shapeCast).
A triangle mesh collider collides from its front face only, the side its corners wind counter-clockwise around, which is also the side it renders from.
Name clash: the physics
BoxShapecollides with Flutter's paintingBoxShape. In a file that imports both, hide the one you do not need, e.g.import 'package:flutter/material.dart' hide BoxShape;.
Web #
On the web, the package loads a WebAssembly build of the physics shim at
runtime (Flutter GPU / dart:ffi do not exist there; flutter_scene runs
on a WebGL2 backend). The module for each release is fetched from a
CORS-enabled host. To run against a locally built module during
development, serve it and point the loader at it:
flutter run -d chrome \
--dart-define=FLUTTER_SCENE_RAPIER_WASM_URL=/flutter_scene_rapier_native.wasm
Contributing / building from source #
The native shim lives in native/ (Rust). To build it locally instead of
downloading a prebuilt binary (required when you edit native/src), set:
FLUTTER_SCENE_RAPIER_BUILD_FROM_SOURCE=1
This needs a Rust toolchain (rustup). For web, build the wasm with
cargo build --release --target wasm32-unknown-unknown and optimize it
with wasm-opt -Oz.
License #
MIT (see LICENSE). The distributed binaries statically link Rapier and
other Rust crates under their own permissive licenses; see
THIRD_PARTY_NOTICES.md.