The scene graph: the source
Open the live demo · Read the guide · View on GitHub
Regions the guide quotes: hierarchy (line 35), root (line 64), motion (line 96), check (line 115).
1/// A small hierarchy whose child transforms follow two rotating pivots.
2library;
4import 'package:flutter3d/flutter3d.dart';
5import 'package:flutter3d_showcase/src/demo/demo.dart';
6import 'package:vector_math/vector_math.dart';
8final class SceneGraphDemo extends ShowcaseDemo {
9 double speed = 0.7;
11 late final SceneNode _systemPivot;
12 late final SceneNode _planetPivot;
13 late final SceneNode _moonPivot;
14 late final MeshNode _moon;
15 late final Vector3 _initialMoonPosition;
16 late final int _initialMoonVersion;
18 double _angle = 0.0;
21 void configureView(DemoContext context) {
22 context.orbit
23 ..distance = 10.0
24 ..pitch = 0.4
25 ..yaw = 0.35;
26 }
29 Scene build(DemoContext context) {
30 final DeviceMesh sphere = DeviceMesh.upload(
31 context.device,
32 const SphereShape(segments: 32, rings: 16).build(),
33 );
35 _systemPivot = SceneNode(name: 'system pivot');
36 _planetPivot = SceneNode(name: 'planet orbit')..setPosition(3.1, 0.0, 0.0);
37 _moonPivot = SceneNode(name: 'moon orbit')..setPosition(1.15, 0.0, 0.0);
39 final MeshNode planet = MeshNode(
40 sphere,
41 Material(
42 name: 'blue planet',
43 baseColor: Vector4(0.18, 0.48, 0.88, 1.0),
44 roughness: 0.62,
45 ),
46 name: 'planet',
47 )..setUniformScale(0.72);
48 _moon = MeshNode(
49 sphere,
50 Material(
51 name: 'moon rock',
52 baseColor: Vector4(0.72, 0.7, 0.66, 1.0),
53 roughness: 0.92,
54 ),
55 name: 'moon',
56 )..setUniformScale(0.25);
58 _systemPivot.add(_planetPivot);
59 _planetPivot
60 ..add(planet)
61 ..add(_moonPivot);
62 _moonPivot.add(_moon);
64 final MeshNode star = MeshNode(
65 sphere,
66 Material(
67 name: 'star',
68 baseColor: Vector4(1.0, 0.56, 0.12, 1.0),
69 emissive: Vector3(1.0, 0.28, 0.04),
70 emissiveStrength: 1.8,
71 roughness: 0.5,
72 ),
73 name: 'star',
74 )..setUniformScale(1.15);
75 final Scene scene = Scene()
76 ..ambientColor = Vector3(0.2, 0.26, 0.42)
77 ..ambientIntensity = 0.12
78 ..add(star)
79 ..add(_systemPivot)
80 ..add(
81 LightNode(
82 type: LightType.point,
83 intensity: 24.0,
84 range: 12.0,
85 name: 'starlight',
86 ),
87 );
89 _initialMoonPosition = _moon.readWorldPosition();
90 _initialMoonVersion = _moon.worldVersion;
91 return scene;
92 }
95 void update(DemoContext context, double dt) {
96 _angle += dt * speed;
97 _systemPivot.setRotationYawPitchRoll(_angle, 0.0, 0.0);
98 _planetPivot.setRotationYawPitchRoll(_angle * 2.7, 0.0, 0.0);
99 }
102 List<DemoControl> controls(DemoContext context) => <DemoControl>[
103 SliderControl(
104 'Orbit speed',
105 min: 0.0,
106 max: 2.0,
107 value: () => speed,
108 onChanged: (double value) => speed = value,
109 format: (double value) => value.toStringAsFixed(2),
110 ),
111 ];
114 void verify(Scene scene, FrameResult frame) {
115 final Vector3 current = _moon.readWorldPosition();
116 final bool hierarchyIsIntact =
117 _moon.parent == _moonPivot &&
118 _moonPivot.parent == _planetPivot &&
119 _planetPivot.parent == _systemPivot;
120 if (!hierarchyIsIntact ||
121 (current - _initialMoonPosition).length < 0.001 ||
122 _moon.worldVersion == _initialMoonVersion ||
123 frame.drawCalls < 3) {
124 throw StateError('the child transforms did not follow their parents');
125 }
126 }
127}