/
sim_snow.go
122 lines (97 loc) · 2.74 KB
/
sim_snow.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package effect
import (
"korok.io/korok/math/f32"
"korok.io/korok/gfx"
"korok.io/korok/math"
)
// SnowSimulator can simulate snow effect.
type SnowSimulator struct {
Pool
RateController
LifeController
VisualController
velocity Channel_v2
deltaRot Channel_f32
// Configuration.
Config struct{
Duration, Rate float32
Life Var
Size Var
Color f32.Vec4
Position [2]Var
Velocity [2]Var
Rotation Var
}
}
func NewSnowSimulator(cap int, w, h float32) *SnowSimulator {
sim := SnowSimulator{Pool: Pool{Cap: cap}}
sim.AddChan(Life, Size)
sim.AddChan(Position, Velocity)
sim.AddChan(Color)
sim.AddChan(Rotation)
sim.AddChan(RotationDelta)
// config
sim.Config.Duration = math.MaxFloat32
sim.Config.Rate = float32(cap)/10
sim.Config.Life = Var{10, 4}
sim.Config.Color = f32.Vec4{1, 1, 1, 1}
sim.Config.Size = Var{6, 6}
sim.Config.Position[0] = Var{0, w}
sim.Config.Position[1] = Var{h/2, 0}
sim.Config.Velocity[0] = Var{-10, 20}
sim.Config.Velocity[1] = Var{-50, 20}
sim.Config.Rotation = Var{0, 3.14/180}
return &sim
}
func (sim *SnowSimulator) Initialize() {
sim.Pool.Initialize()
sim.Life = sim.Field(Life).(Channel_f32)
sim.ParticleSize = sim.Field(Size).(Channel_f32)
sim.Position = sim.Field(Position).(Channel_v2)
sim.velocity = sim.Field(Velocity).(Channel_v2)
sim.Color = sim.Field(Color).(Channel_v4)
sim.Rotation = sim.Field(Rotation).(Channel_f32)
sim.deltaRot = sim.Field(RotationDelta).(Channel_f32)
sim.RateController.Initialize(sim.Config.Duration, sim.Config.Rate)
}
func (sim *SnowSimulator) Simulate(dt float32) {
if new := sim.Rate(dt); new > 0 {
sim.NewParticle(new)
}
n := int32(sim.Live)
// update old particle
sim.Life.Sub(n, dt)
// position integrate: p' = p + v * t
sim.Position.Integrate(n, sim.velocity, dt)
// rotation
sim.Rotation.Integrate(n, sim.deltaRot, dt)
// GC
sim.GC(&sim.Pool)
}
func (sim *SnowSimulator) Size() (live, cap int) {
return int(sim.Live), sim.Cap
}
func (sim *SnowSimulator) NewParticle(new int) {
if (sim.Live + new) > sim.Cap {
return
}
start := sim.Live
sim.Live += new
for i := start; i < sim.Live; i++ {
sim.Life[i] = sim.Config.Life.Random()
sim.Color[i] = sim.Config.Color
sim.ParticleSize[i] = sim.Config.Size.Random()
f := sim.ParticleSize[i]/(sim.Config.Size.Base+sim.Config.Size.Var)
sim.Color[i][3] = f
sim.Rotation[i] = sim.Config.Rotation.Random()
px := sim.Config.Position[0].Random()
py := sim.Config.Position[1].Random()
sim.Position[i] = f32.Vec2{px, py}
dx := sim.Config.Velocity[0].Random()
dy := sim.Config.Velocity[1].Random()
sim.velocity[i] = f32.Vec2{dx, dy}
}
}
func (sim *SnowSimulator) Visualize(buf []gfx.PosTexColorVertex, tex gfx.Tex2D) {
sim.VisualController.Visualize(buf, tex, int(sim.Live), false)
}