stage_3d 0.1.0-alpha.6
stage_3d: ^0.1.0-alpha.6 copied to clipboard
Flutter 3D plugin with Google Filament rendering and Jolt Physics for GLB models, scene nodes, lighting, animation, and spatial queries.
Stage 3D #
Stage 3D is a Flutter 3D plugin and Gateway API powered by Google Filament rendering and Jolt Physics for building interactive 3D experiences with GLB models, physics, animation, lighting, scene components, and spatial queries.
Stage 3D connects Flutter apps to native 3D capabilities through a reusable
gateway API. Use the component-friendly StageScene runtime, build your own
scene layer, or use the rendering, physics, input, material, lighting,
animation, and spatial query APIs independently inside any Flutter UI.
Stage 3D currently combines
Jolt Physics v5.5.0 with
Filament rendering on Android and a
native Windows Filament demo backend. The Android backend is packaged as a
Flutter plugin through Filament's Android bindings. The Windows backend uses
native Filament C++ and currently lives in this repository's Windows demo
runner; extracting it into a reusable Windows plugin backend is the next
packaging step.
Support & Contact: efimovi420@gmail.com
If Stage 3D helps your project, please consider starring the repository.
Preview #
[Stage 3D Android scene preview]
Native Backends #
Stage 3D ships with native integrations for two separate systems:
- Jolt Physics through a C++
dart:ffiadapter for simulation, rigid bodies, collider shapes, compound shapes, impulses, kinematic motion, and ray casts. - Filament through an Android Platform View, plus a Windows C++ demo
backend for
.glbrendering, model instances, animations, lights, environment settings, render options, procedural meshes, and shader materials.
The APIs are intentionally separate. You can use only Jolt, only Filament, the
included StageScene component runtime, or your own scene layer.
Features #
| Capability | Current API |
|---|---|
| Physics worlds | Create, step, and dispose reusable PhysicsWorld instances |
| Rigid bodies | Static, kinematic, and dynamic bodies |
| Collider shapes | Box, capsule, sphere, cylinder, and compound colliders |
| Spatial queries | Finite Jolt ray casts with closest-hit results |
| Native rendering | Filament Android viewport and Windows C++ demo backend |
| 3D assets | Reusable .glb assets and independent visual instances |
| Animations | Inspect clips and control per-instance playback |
| Lighting | Directional and movable point lights |
| Procedural meshes | Terrain, atlas textures, normals, and optional collider metadata |
| Shader materials | .mat / .shader metadata with compiled .filamat assets |
| Debug tools | Compact collider inspector in Flutter debug builds |
Suitable For #
- interactive product and property visualization;
- lightweight Flutter games and gameplay prototypes;
- educational physics demos;
- animated 3D model viewers;
- object picking with ray casting;
- reusable scene and interaction experiments.
Project Status #
Stage 3D is an experimental alpha. Packaged native Filament rendering currently
targets Android. This repository also includes a working Windows C++ Filament
demo backend, but it is not yet extracted as a reusable Windows Flutter plugin
for downstream applications. Native Jolt physics currently targets Android;
other Flutter targets use a lightweight preview physics backend for tests and UI
iteration. Public APIs may change before a stable 1.0.0 release.
Quick Start #
Import the public API:
import 'package:stage_3d/stage_3d.dart';
Create a world, floor, and dynamic ball:
final world = createPhysicsWorld();
final floor = world.createBody(
const RigidBodySettings(
shape: BoxShape(halfWidth: 8, halfHeight: 0.25, halfDepth: 8),
motionType: MotionType.static,
transform: PhysicsTransform(position: Vector3(0, -0.25, 0)),
),
);
final ball = world.createBody(
const RigidBodySettings(
shape: SphereShape(radius: 0.5),
motionType: MotionType.dynamic,
transform: PhysicsTransform(position: Vector3(0, 4, 0)),
),
);
world.addImpulse(ball, const Vector3(2, 4, 0));
world.step(1 / 60);
final transform = world.getTransform(ball);
world.destroyBody(ball);
world.destroyBody(floor);
world.dispose();
Scene Node Example #
Use StageObject.node when one object needs a shared transform for rendering,
physics, input, scripts, or other behavior. This is similar to a Godot node with
components attached to it.
The components are regular Dart objects. Applications can attach
PhysicsBodyComponent, RenderModelComponent, PositionedModel, or custom
StageComponent subclasses to their own scene objects instead of using the
included demo scene.
import 'package:stage_3d/stage_3d.dart';
final world = createPhysicsWorld();
final scene = StageScene();
final models = RenderModelController();
final foxAsset = models.loadAsset(
const ModelAsset(assetPath: 'models/Fox.glb', animationIndex: 0),
);
final foxTransform = const PhysicsTransform(
position: Vector3(0, 5, 0),
);
final fox = scene.add(
StageObject.node(
'fox',
transform: foxTransform,
components: [
PhysicsBodyComponent(
world,
settings: const RigidBodySettings(
shape: CompoundShape([
PositionedShape(
shape: CapsuleShape(halfHeight: 0.65, radius: 0.45),
),
PositionedShape(
shape: BoxShape(
halfWidth: 0.32,
halfHeight: 0.14,
halfDepth: 0.28,
),
position: Vector3(0, -1.05, 0),
),
]),
motionType: MotionType.dynamic,
transform: foxTransform,
),
),
PositionedModel(
asset: foxAsset,
position: Vector3(0, 0.2, 0),
).toComponent(models),
],
),
);
void tick(double deltaSeconds) {
world.step(deltaSeconds);
scene.update(deltaSeconds);
}
CompoundShape groups multiple local PositionedShape colliders into one Jolt
body. PositionedModel adds a local visual offset to the same node, so the
model and collider move together while still being tuned independently.
Camera Presets #
Use StageCamera with FilamentViewportController when a scene needs multiple
views, such as a wide scene camera and a close model camera.
final viewport = FilamentViewportController();
const wideCamera = StageCamera.orbit(
target: Vector3.zero,
yaw: -0.6,
pitch: 0.35,
distance: 8,
);
const closeCamera = StageCamera.orbit(
target: Vector3(0, 1, 0),
yaw: 0.25,
pitch: 0.2,
distance: 3,
);
viewport.setCamera(wideCamera);
viewport.setCamera(closeCamera);
The same controller API updates the Android Filament camera and the Flutter fallback preview camera.
Resource Lifetime #
Stage 3D uses native C++ resources through Jolt and Filament. Dart garbage collection does not automatically free every native renderer or physics object, so applications should keep ownership explicit.
Recommended lifecycle:
final world = createPhysicsWorld();
final scene = StageScene();
final models = RenderModelController();
final lights = RenderLightController();
final asset = models.loadAsset(
const ModelAsset(assetPath: 'models/Fox.glb'),
);
final instance = models.createInstance(
asset,
transform: const PhysicsTransform(position: Vector3(0, 0, 0)),
);
final light = lights.createLight(
const DirectionalLight(direction: Vector3(0, -1, -0.25)),
);
// When removing individual objects created manually:
models.destroyInstance(instance);
lights.destroyLight(light);
// When closing the scene/screen:
scene.dispose();
world.dispose();
If a model is attached through RenderModelComponent, disposing its
StageObject or the whole StageScene destroys that visible instance for you.
The bundled FilamentViewport also releases native Filament assets, procedural
meshes, lights, materials, textures, skybox, and renderer objects when the
Flutter platform view is disposed.
For long-running apps, avoid repeatedly creating new model instances, lights, or
procedural meshes without destroying the old ones. Reuse loaded assets and
instances when possible, and unload whole screens/scenes by calling
StageScene.dispose() and PhysicsWorld.dispose().
Documentation #
- Physics API guide
- Rendering bridge
- Rendering lights
- Rendering meshes and shaders
- Stage scene runtime
- Virtual joystick
- Windows Filament backend
- Public Dart entrypoint:
lib/jolt_physics.dart - Rendering entrypoint:
lib/jolt_rendering.dart - Collider prototypes:
lib/physics/collider_shape.dart - Rigid body prototypes:
lib/physics/rigid_body.dart - Light prototypes:
lib/rendering/light.dart - Model asset prototypes:
lib/rendering/model_asset.dart - Mesh prototypes:
lib/rendering/textured_mesh_prototype.dart
Architecture #
Flutter application
|
| Dart API
v
PhysicsWorld and RigidBody
|
| dart:ffi
v
Jolt Physics C++ adapter
The included Android demo adds an independent rendering path:
Jolt body transform -> Flutter scene -> MethodChannel -> Filament -> Fox.glb
Jolt calculates physics. Filament renders the visual model. The two systems are kept separate so a visual model can use the collider that best fits gameplay.
Procedural mesh prototypes serialize from Dart into each Filament backend. The
Android bridge currently converts them into temporary in-memory GLB assets,
while the Windows backend creates native Filament vertex and index buffers.
They support generated planes, heightmapped terrain, atlas texture crops,
recalculated normals, basic PBR settings, optional collider metadata, and custom
Filament shader materials.
Dart can describe .mat / .shader sources, compiled .filamat assets,
scalar uniforms, color uniforms, and named texture uniforms such as normal or
roughness maps.
Run The Demo #
flutter run
The default demo opens a Filament fox scene with a textured floor, environment
settings, render options, animation, camera controls, and Dart-created lights.
The older Jolt physics scene is still available from the /jolt route.
Current Platform Support #
| Platform | Backend |
|---|---|
| Android | Jolt Physics through dart:ffi; Filament through Android Gradle/Maven dependencies |
| Windows | Working repository demo backend; reusable plugin packaging is pending |
| Other Flutter targets | Lightweight preview backend |
Android downloads Filament through Gradle dependencies. To run the Windows demo from this repository, install the official Google Filament Windows release and expose it before building:
$env:STAGE_FILAMENT_ROOT = 'C:\SDKs\filament'
flutter build windows --debug
For a persistent setup, add STAGE_FILAMENT_ROOT to your user environment
variables. See Windows Filament backend for
setup notes and current limitations.
Downstream Flutter apps that depend on stage_3d from git currently get the
Android plugin backend automatically. Windows support in a downstream app
requires the Windows runner integration from this repository until the Windows
backend is moved into a real Flutter Windows plugin target.
The current public shape API supports BoxShape, CapsuleShape,
SphereShape, CylinderShape, and CompoundShape.
Native Files #
- Jolt C++ adapter:
android/src/main/cpp/jolt_ffi.cpp - Filament Platform View:
android/src/main/kotlin/com/stage3d/stage_3d/FilamentPlatformView.kt
Test Model #
The animated Fox.glb asset comes from the
Khronos glTF Sample Models repository.
The mesh is CC0. Rigging and animation are licensed under CC-BY 4.0 by
@tomkranis.