/
animator.go
123 lines (91 loc) · 2.76 KB
/
animator.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
123
package sim
import (
"image"
"math"
"log"
"fmt"
"os"
"image/png"
"github.com/bbeni/sphugo/gfx"
//"sync"
)
type Animator struct {
//frames for rendering
Frames []image.Image
//FramesMu sync.Mutex
// as refernce to simulation variables
Simulation *Simulation
// reference to particles
// also used to order particles acoording to z-value before rendering
renderingParticleArray []*Particle
}
func MakeAnimator(simulation *Simulation) Animator {
if simulation.Root == nil || len(simulation.Root.Particles) == 0 {
panic("int Run(): Simulation not initialized!")
}
ani := Animator {
renderingParticleArray: make([]*Particle, len(simulation.Root.Particles)),
}
for i, _ := range simulation.Particles {
ani.renderingParticleArray[i] = &simulation.Particles[i]
}
ani.Simulation = simulation
ani.Frames = make([]image.Image, 0, simulation.Config.NSteps)
// render first frame
ani.Frame()
return ani
}
func (ani *Animator) CurrentFrame() gfx.Canvas {
//
// order according to z-value
//
extractZindex := func(p *Particle) int {
//return int(p.Rho*100000)
return -p.Z
}
QuickSort(ani.renderingParticleArray, extractZindex)
canvas := gfx.NewCanvas(1280, 720)
canvas.Clear(gfx.BLACK)
for _, particle := range ani.renderingParticleArray {
x := float32(particle.Pos.X) * float32(canvas.W)
y := float32(particle.Pos.Y) * float32(canvas.H)
//zNormalized := float32(particle.Z)/float32(math.MaxInt)
//color_index := 255 - uint8((particle.Rho - 1)*64)
//color_index := 255 - uint8(zNormalized * 256)
m := ani.Simulation.Config.ParticleMass
colorFormula := float64(particle.Rho/(m* float64(len(ani.Simulation.Particles)*10))*256)
//colorFormula := float64(particle.Vel.Norm()*256)
color_index := uint8(math.Min(colorFormula, 255))
color := gfx.ParaRamp(color_index)
//color := gfx.HeatRamp(color_index)
//color := gfx.ToxicRamp(color_index)
//color := gfx.RainbowRamp(color_index)
if color_index > 255 {
nnRadius := float32(particle.NNDists[0])*float32(canvas.W)
canvas.DrawCircle(x, y, nnRadius, 2, gfx.WHITE)
}
//canvas.DrawDisk(float32(x), float32(y), zNormalized*zNormalized*20+1, color)
canvas.DrawDisk(float32(x), float32(y), 4, color)
}
return canvas
}
// save the last frame of the simultion in the buffer
func (ani *Animator) Frame() {
canvas := ani.CurrentFrame()
ani.Frames = append(ani.Frames, canvas.Img)
}
func (ani *Animator) FrameToPNG(file_path string, i int) bool {
// TODO: check i for bounds
file, err := os.Create(file_path)
defer file.Close()
if err != nil {
fmt.Printf("Error: couldn't create file %q : %q", file_path, err)
return false
}
err = png.Encode(file, ani.Frames[i])
if err != nil {
log.Printf("Error: couldn't encode PNG %q : %q", file_path, err)
return false
}
return true
}