flutter3d
Showcase Changelog 38 packages API reference

The held item's own pass: the source

since 0.4.0 Scene and geometry

Regions the guide quotes: world (line 27), hands (line 60), pass (line 88), motion (line 96), check (line 117).

1/// A held item drawn in its own pass, over the finished world.
2library;
3
4import 'dart:math' as math;
5
6import 'package:flutter3d/flutter3d.dart';
7import 'package:flutter3d_showcase/src/demo/demo.dart';
8import 'package:vector_math/vector_math.dart';
9
10final class ViewModelDemo extends ShowcaseDemo {
11 double fovDegrees = 48.0;
12 double _bob = 0.0;
14 late final CameraNode _handCamera;
15 late final MeshNode _tool;
17 @override
18 void configureView(DemoContext context) {
19 context.orbit
20 ..distance = 6.0
21 ..pitch = 0.2
22 ..yaw = 0.4;
23 }
25 @override
26 Scene build(DemoContext context) {
27 final Material stone = Material(
28 name: 'stone',
29 baseColor: Vector4(0.58, 0.56, 0.52, 1.0),
30 roughness: 0.82,
31 );
32 final Scene world = Scene()
33 ..ambientColor = Vector3(0.4, 0.46, 0.6)
34 ..ambientIntensity = 0.16
35 ..add(
36 MeshNode(
37 DeviceMesh.upload(
38 context.device,
39 const PlaneShape(width: 20, depth: 20).build(),
40 ),
41 stone.copy()..doubleSided = true,
42 name: 'floor',
43 ),
44 )
45 ..add(
46 MeshNode(
47 DeviceMesh.upload(
48 context.device,
49 CuboidShape(size: Vector3(1.4, 2.4, 1.4)).build(),
50 ),
51 stone,
52 name: 'pillar',
53 )..setPosition(0.0, 1.2, -3.0),
54 )
55 ..add(
56 LightNode(name: 'sun', intensity: 3.0)
57 ..setLocalForward(Vector3(-0.4, -0.8, -0.3)),
58 );
60 final Scene handsScene = Scene()
61 ..add(
62 _tool = MeshNode(
63 DeviceMesh.upload(
64 context.device,
65 CuboidShape(size: Vector3(0.12, 0.12, 0.6)).build(),
66 ),
67 Material(
68 name: 'tool',
69 baseColor: Vector4(0.66, 0.68, 0.72, 1.0),
70 metallic: 0.85,
71 roughness: 0.28,
72 ),
73 name: 'held tool',
74 )..setPosition(0.22, -0.2, -0.5),
75 )
76 ..add(
77 LightNode(name: 'hand key', intensity: 2.6)
78 ..setLocalForward(Vector3(-0.3, -0.5, -0.8)),
79 );
80 _handCamera = CameraNode(
81 name: 'hand camera',
82 projection: PerspectiveProjection(
83 fovYRadians: fovDegrees * math.pi / 180.0,
84 ),
85 );
86 handsScene.add(_handCamera);
88 context.renderer.addNode(
89 ViewModelNode(scene: handsScene, camera: _handCamera),
90 );
91 return world;
92 }
94 @override
95 void update(DemoContext context, double dt) {
96 _bob += dt;
97 _tool.setPosition(0.22, -0.2 + math.sin(_bob * 2.4) * 0.02, -0.5);
98 _handCamera.projection = PerspectiveProjection(
99 fovYRadians: fovDegrees * math.pi / 180.0,
100 );
101 }
103 @override
104 List<DemoControl> controls(DemoContext context) => <DemoControl>[
105 SliderControl(
106 'Hand field of view',
107 min: 25,
108 max: 90,
109 value: () => fovDegrees,
110 onChanged: (double value) => fovDegrees = value,
111 format: (double value) => '${value.round()} deg',
112 ),
113 ];
115 @override
116 void verify(Scene scene, FrameResult frame) {
117 final bool viewModelRan = frame.passes.any(
118 (FramePass pass) => pass.name == 'view model',
119 );
120 if (!viewModelRan || frame.drawCalls < 2) {
121 throw StateError('the view model pass did not draw over the world');
122 }
123 }