Particles that light: the source
Open the live demo · Read the guide · View on GitHub
Regions the guide quotes: emit (line 37), light (line 55), advance (line 62), follow (line 64), check (line 73).
1/// A torch whose flame lights the room it burns in, measured from the
2/// particles themselves rather than from a light somebody hand-tuned to
3/// match.
4///
5/// Quoted by `particle_lights.md` and shown whole in the Source tab.
6library;
8import 'package:flutter3d/flutter3d.dart';
9import 'package:flutter3d_particles/flutter3d_particles.dart';
10import 'package:flutter3d_showcase/src/demo/demo.dart';
11import 'package:vector_math/vector_math.dart';
13/// Mixing in [LightEmitter] is the whole of what it takes to become a source
14/// the particle system will measure. It carries no fields of its own.
15final class _Torch with LightEmitter {}
17final class ParticleLightsDemo extends ShowcaseDemo {
18 late final ParticleSystem _particles;
19 late final LightNode _glow;
21 final _Torch _torch = _Torch();
23 static const double _rate = 240.0;
26 void configureView(DemoContext context) {
27 context.orbit
28 ..distance = 4.0
29 ..pitch = 0.2
30 ..yaw = 0.4;
31 }
34 Scene build(DemoContext context) {
35 _particles = ParticleSystem(capacity: 256, seed: 77);
37 final ParticleEffect flame = ParticleEffect(
38 count: 1,
39 emitter: const ConeEmitter(speed: Range(0.8, 1.6), halfAngleDegrees: 12),
40 lifetime: const Range(0.4, 0.7),
41 size: const Range(0.08, 0.14),
42 color: Vector4(1.0, 0.6, 0.2, 1.0),
43 affectors: <ParticleAffector>[const ParticleFade(startsAt: 0.3)],
44 );
45 _particles.emit(
46 _torch,
47 flame,
48 Vector3.zero(),
49 perSecond: _rate,
50 direction: Vector3(0.0, 1.0, 0.0),
51 );
53 context.renderer.addContributor(ParticleContributor(_particles));
55 _glow = LightNode(name: 'glow', type: LightType.point, intensity: 0.0);
57 return Scene()..add(_glow);
58 }
61 void update(DemoContext context, double dt) {
62 _particles.advance(dt);
64 final ParticleGlow glow = _torch.glow;
65 if (glow.located) {
66 _glow.setPositionFrom(glow.centre);
67 _glow.intensity = glow.power * 0.6;
68 }
69 }
72 void verify(Scene scene, FrameResult frame) {
73 if (_torch.glow.count == 0 || _torch.glow.power <= 0.0) {
74 throw StateError('the torch should be lit by its own flame');
75 }
76 if (frame.drawCalls < 1) {
77 throw StateError('the flame did not reach the frame');
78 }
79 }
80}