Polylines in screen pixels: the source
Open the live demo · Read the guide · View on GitHub
Regions the guide quotes: routes (line 26), geometry (line 61), material (line 76), resize (line 104), check (line 114).
1/// Joined lines whose width is measured in screen pixels.
2library;
4import 'package:flutter3d/flutter3d.dart';
5import 'package:flutter3d_showcase/src/demo/demo.dart';
6import 'package:vector_math/vector_math.dart';
8final class PolylinesDemo extends ShowcaseDemo {
9 static const double _viewportWidth = 1280;
10 static const double _viewportHeight = 720;
12 final List<MeshData> _meshes = <MeshData>[];
13 final List<Material> _materials = <Material>[];
14 final List<MeshNode> _lines = <MeshNode>[];
17 void configureView(DemoContext context) {
18 context.orbit
19 ..distance = 8.2
20 ..pitch = 0.08
21 ..yaw = 0.12;
22 }
25 Scene build(DemoContext context) {
26 final List<List<Vector3>> routes = <List<Vector3>>[
27 <Vector3>[
28 Vector3(-3.2, 1.35, 0.0),
29 Vector3(-2.0, 1.75, 0.2),
30 Vector3(-0.8, 1.05, -0.1),
31 Vector3(0.4, 1.62, 0.15),
32 Vector3(1.7, 1.12, -0.05),
33 Vector3(3.2, 1.52, 0.1),
34 ],
35 <Vector3>[
36 Vector3(-3.2, 0.25, 0.0),
37 Vector3(-2.2, -0.35, 0.15),
38 Vector3(-1.0, 0.42, -0.1),
39 Vector3(0.0, -0.28, 0.1),
40 Vector3(1.25, 0.38, -0.15),
41 Vector3(2.15, -0.3, 0.1),
42 Vector3(3.2, 0.2, 0.0),
43 ],
44 <Vector3>[
45 Vector3(-3.2, -1.45, 0.0),
46 Vector3(-1.9, -0.85, -0.1),
47 Vector3(-0.55, -1.62, 0.15),
48 Vector3(0.8, -0.92, -0.1),
49 Vector3(2.0, -1.55, 0.12),
50 Vector3(3.2, -1.05, 0.0),
51 ],
52 ];
53 final List<double> widths = <double>[6, 12, 22];
54 final List<Vector4> palette = <Vector4>[
55 Vector4(0.12, 0.78, 1.0, 1.0),
56 Vector4(0.48, 0.3, 0.96, 1.0),
57 Vector4(1.0, 0.34, 0.2, 1.0),
58 Vector4(1.0, 0.76, 0.15, 1.0),
59 ];
61 _meshes.clear();
62 for (var routeIndex = 0; routeIndex < routes.length; routeIndex++) {
63 final List<Vector3> route = routes[routeIndex];
64 _meshes.add(
65 buildPolyline(
66 route,
67 width: widths[routeIndex],
68 colours: <Vector4>[
69 for (var point = 0; point < route.length; point++)
70 palette[(point + routeIndex) % palette.length],
71 ],
72 ),
73 );
74 }
76 _materials
77 ..clear()
78 ..addAll(<Material>[
79 for (var i = 0; i < _meshes.length; i++)
80 Material.polyline(
81 name: 'route ${i + 1}',
82 viewportWidth: _viewportWidth,
83 viewportHeight: _viewportHeight,
84 ),
85 ]);
86 _lines
87 ..clear()
88 ..addAll(<MeshNode>[
89 for (var i = 0; i < _meshes.length; i++)
90 MeshNode(
91 DeviceMesh.upload(context.device, _meshes[i]),
92 _materials[i],
93 name: 'route ${i + 1}',
94 ),
95 ]);
97 final Scene scene = Scene();
98 for (final MeshNode line in _lines) {
99 scene.add(line);
100 }
101 return scene;
102 }
104 void setViewport(double width, double height) {
105 for (final Material material in _materials) {
106 final viewport = material.polylineViewport!;
107 viewport[0] = width;
108 viewport[1] = height;
109 }
110 }
113 void verify(Scene scene, FrameResult frame) {
114 final bool geometryMatches = _meshes.every(
115 (MeshData mesh) =>
116 mesh.vertexCount >= 12 &&
117 mesh.indexCount == (mesh.vertexCount - 2) * 3,
118 );
119 final bool viewportsMatch = _materials.every((Material material) {
120 final viewport = material.polylineViewport;
121 return material.lighting == LightingModel.polyline &&
122 viewport != null &&
123 viewport[0] == _viewportWidth &&
124 viewport[1] == _viewportHeight;
125 });
126 if (_lines.length != 3 ||
127 !geometryMatches ||
128 !viewportsMatch ||
129 frame.drawCalls < 3) {
130 throw StateError('the joined pixel-width routes were not drawn');
131 }
132 }
133}