├── .gitignore
├── LICENSE
├── README.md
├── dentro
├── data
│ ├── click.png
│ ├── data.go
│ ├── dosfont.png
│ ├── flower.png
│ ├── inject.go
│ ├── light.png
│ ├── scene.obj
│ └── wildtextures-african-grey.png
├── index.html
├── main.go
├── music
│ ├── music.mp3
│ └── music.ogg
├── screen
│ └── screen.go
└── wasm.cmd
├── ep01
├── data
│ ├── GOPHER_MIC_DROP-256.png
│ ├── click.png
│ ├── data.go
│ └── inject.go
├── index.html
├── main.go
└── wasm.cmd
├── ep02
├── data
│ ├── ballet-egon-256.png
│ ├── click.png
│ ├── data.go
│ └── inject.go
├── index.html
├── main.go
└── wasm.cmd
├── ep03
├── data
│ ├── ashleymcnamara-pride_256.png
│ ├── click.png
│ ├── data.go
│ └── inject.go
├── index.html
├── main.go
└── wasm.cmd
├── ep04
├── data
│ ├── click.png
│ ├── data.go
│ ├── inject.go
│ └── wildtextures-african-inspir.png
├── index.html
├── main.go
└── wasm.cmd
├── ep05
├── data
│ ├── click.png
│ ├── data.go
│ └── inject.go
├── index.html
├── main.go
└── wasm.cmd
├── ep06
├── data
│ ├── click.png
│ ├── data.go
│ ├── flower.png
│ ├── inject.go
│ ├── snowflake1.png
│ ├── snowflake2.png
│ ├── snowflake3.png
│ └── snowflake4.png
├── index.html
├── main.go
└── wasm.cmd
├── ep08
├── index.html
├── main.go
└── wasm.cmd
├── hoaxplus
├── 00-intro
│ └── intro.go
├── 01-title
│ └── title.go
├── cmd
│ └── hoax
│ │ └── main.go
├── data
│ ├── Basehead.obj
│ ├── data.go
│ ├── data
│ │ └── click.png
│ └── inject.go
└── primitive
│ ├── line.go
│ ├── objloader.go
│ ├── point2d.go
│ └── point3d.go
├── index.html
├── loader.js
├── server
└── main.go
├── style.css
└── wasm_exec.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 | *.wasm
8 |
9 | # Test binary, build with `go test -c`
10 | *.test
11 |
12 | # Output of the go coverage tool, specifically when used with LiteIDE
13 | *.out
14 | /.idea
15 | /saved
16 | /.htaccess
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Klaus Post
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Go After Dark
2 |
3 | This is a new web series where we take a look at Go from a different perspective. In this series we drop everything about Go routers, REST, containers, databases and all the boring stuff of everyday Go.
4 |
5 | Instead we will have fun by recreating demo effects from the 90’s. We will mainly focus on graphical effects, but over time we may dive into other topics.
6 |
7 | This is the associated code for each episode.
8 |
9 | To watch the episodes go to https://afterdark.klauspost.com/ for a list of episodes.
10 |
11 |
12 | # Installing
13 |
14 | Install the code in your GOPATH and fetch dependencies using:
15 |
16 | ```
17 | go get -u github.com/klauspost/gad/...
18 | ```
19 |
20 | # Running
21 |
22 | Go into the directory you want to run and `go run main.go`. For example
23 |
24 | ```
25 | cd ep01
26 | go run main.go
27 | ```
28 |
29 | Data, except music, is embedded into the binaries. To re-generate this run `go generate` in
30 | the folder with the `main.go` file.
31 |
32 | # Web Assembly
33 |
34 | WASM requires Go 1.11. Your `wasm_exec.js` must match the version you use for building.
35 |
36 | In your go installation, you find it in `misc/wasm`. Copy it to the repository root.
37 |
38 | In each folder you will find a `wasm.cmd` that contains the commands needed to build the webassembly.
39 |
40 | The output will be called `fx.wasm` and will be placed in the same folder as `main.go`.
41 |
42 | A local server is needed to execute it. In the repository root execute `go run server/main.go`.
43 | When the server is running, you can see your effect on localhost, for example `http://localhost:8080/ep01`. See the browser console if errors occur.
44 |
45 |
46 | # License
47 |
48 | This code is released under a standard MIT license. See LICENCE file for more information.
49 |
--------------------------------------------------------------------------------
/dentro/data/click.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/dentro/data/click.png
--------------------------------------------------------------------------------
/dentro/data/dosfont.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/dentro/data/dosfont.png
--------------------------------------------------------------------------------
/dentro/data/flower.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/dentro/data/flower.png
--------------------------------------------------------------------------------
/dentro/data/inject.go:
--------------------------------------------------------------------------------
1 | package data
2 |
3 | import "github.com/klauspost/gfx"
4 |
5 | func init() {
6 | gfx.AddData(Asset)
7 | }
8 |
--------------------------------------------------------------------------------
/dentro/data/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/dentro/data/light.png
--------------------------------------------------------------------------------
/dentro/data/wildtextures-african-grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/dentro/data/wildtextures-african-grey.png
--------------------------------------------------------------------------------
/dentro/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Go After Dark WASM Intro
6 |
7 |
8 |
9 |
10 |
11 |
12 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/ep05/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "image"
5 | "image/color"
6 | _ "image/png"
7 | "math"
8 | "math/rand"
9 | "time"
10 |
11 | _ "github.com/klauspost/gad/ep05/data" // Load data.
12 | "github.com/klauspost/gfx"
13 | )
14 |
15 | const (
16 | renderWidth = 640
17 | renderHeight = 360
18 | )
19 |
20 | // Generates binary data.
21 | // To install go-bindata, do: go get -u github.com/jteeuwen/go-bindata/...
22 | //
23 | //go:generate go-bindata -ignore=\.go\z -pkg=data -o ./data/data.go ./data/...
24 |
25 | func main() {
26 | gfx.InitShadedPalette(192, color.RGBA{R: 251, G: 246, B: 158})
27 | fx := newFx()
28 | //gfx.RunWriteToDisk(fx, 1, "./saved/dots-%05d.png")
29 | gfx.Run(func() { gfx.RunTimed(fx) })
30 | }
31 |
32 | type coord struct{ x, y, z float32 }
33 |
34 | type fx struct {
35 | draw *image.Gray
36 | logW, logH uint
37 | lines [][]byte
38 | dots []coord
39 | }
40 |
41 | func newFx() *fx {
42 | var fx fx
43 |
44 | // Create our draw buffer
45 | fx.draw = image.NewGray(image.Rect(0, 0, renderWidth, renderHeight))
46 |
47 | // Store each line as a slice in a slice.
48 | w, h := fx.draw.Rect.Dx(), fx.draw.Rect.Dy()
49 | fx.lines = make([][]byte, h)
50 | for y := range fx.lines {
51 | fx.lines[y] = fx.draw.Pix[y*fx.draw.Stride : y*fx.draw.Stride+w]
52 | }
53 |
54 | // Generate some dots in a cylinder along positive z axis.
55 | const dots = 50000
56 | fx.dots = make([]coord, dots)
57 | rng := rand.New(rand.NewSource(time.Now().UnixNano()))
58 | for i := range fx.dots {
59 | // Random angle
60 | angle := rng.Float64() * math.Pi * 2
61 | // Random radius.
62 | r := rng.Float64() * renderWidth * 3
63 | // Random depth
64 | z := rng.Float32() * 50
65 | x := math.Sin(angle)
66 | y := math.Cos(angle)
67 |
68 | fx.dots[i] = coord{x: float32(x * r), y: float32(y * r), z: z}
69 | }
70 | return &fx
71 | }
72 |
73 | // Render the effect at time t.
74 | func (fx *fx) Render(t float64) image.Image {
75 | // Clear the screen or keep trails
76 | for i := range fx.draw.Pix {
77 | //fx.draw.Pix[i] = 0
78 | fx.draw.Pix[i] = fx.draw.Pix[i] >> 1
79 | }
80 |
81 | angleSin, angleCos := float32(1), float32(0)
82 | if true {
83 | // Rotate 0 -> 180 degrees when t goes 0 -> 1
84 | angleSin = float32(math.Sin(t * math.Pi))
85 | angleCos = float32(math.Cos(t * math.Pi))
86 | }
87 |
88 | // t2 goes from 0 -> 2 -> 0
89 | t2 := float32(math.Sin(t*math.Pi)) * 2
90 | // Offset z on all points over time, effectively moving the "camera" forward.
91 | zoff := 3 - 5*t2
92 |
93 | const (
94 | // We calculate output contribution using the z depth.
95 | // We use zMaxValue and subtract (z * zFalloff) for each dot.
96 | zMaxValue = 200
97 | zFalloff = 20.0
98 | // maxZ is where the contribution becomes zero.
99 | // zMaxValue - zFalloff*z = 0
100 | maxZ = zMaxValue / zFalloff
101 | )
102 |
103 | // Draw all our dots
104 | for _, d := range fx.dots {
105 | z := d.z + zoff
106 | if z <= 0 || z >= maxZ {
107 | // behind the camera or no contribution, skip
108 | continue
109 | }
110 | // Scale x+y and perspective project
111 | x := (t2 * d.x) / z
112 | y := (t2 * d.y) / z
113 |
114 | // 2d rotate while still centered on 0,0
115 | x, y = x*angleCos-y*angleSin, x*angleSin+y*angleCos
116 |
117 | x += renderWidth / 2
118 | y += renderHeight / 2
119 |
120 | if y := int(y); y >= 0 && y < renderHeight {
121 | x := int(x)
122 | if x >= 0 && x < renderWidth {
123 | l := fx.lines[y]
124 | l[x] = clamp8(int(l[x]) + (zMaxValue - int(z*zFalloff)))
125 | }
126 | }
127 | }
128 | return fx.draw
129 | }
130 |
131 | func clamp8(v int) uint8 {
132 | if v >= 255 {
133 | return 255
134 | }
135 | if v <= 0 {
136 | return 0
137 | }
138 | return uint8(v)
139 | }
140 |
--------------------------------------------------------------------------------
/ep05/wasm.cmd:
--------------------------------------------------------------------------------
1 | SET GOOS=
2 | SET GOARCH=
3 |
4 | go generate
5 |
6 | SET GOOS=js
7 | SET GOARCH=wasm
8 | go build -o fx.wasm main.go
9 |
--------------------------------------------------------------------------------
/ep06/data/click.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/ep06/data/click.png
--------------------------------------------------------------------------------
/ep06/data/flower.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/ep06/data/flower.png
--------------------------------------------------------------------------------
/ep06/data/inject.go:
--------------------------------------------------------------------------------
1 | package data
2 |
3 | import "github.com/klauspost/gfx"
4 |
5 | func init() {
6 | gfx.AddData(Asset)
7 | }
8 |
--------------------------------------------------------------------------------
/ep06/data/snowflake1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/ep06/data/snowflake1.png
--------------------------------------------------------------------------------
/ep06/data/snowflake2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/ep06/data/snowflake2.png
--------------------------------------------------------------------------------
/ep06/data/snowflake3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/ep06/data/snowflake3.png
--------------------------------------------------------------------------------
/ep06/data/snowflake4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/ep06/data/snowflake4.png
--------------------------------------------------------------------------------
/ep06/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Episode 6
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
Full Screen
20 |
21 |
22 |
Starting
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/ep06/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "image"
6 | "image/color"
7 | _ "image/png"
8 | "math"
9 | "math/bits"
10 | "math/rand"
11 |
12 | _ "github.com/klauspost/gad/ep06/data" // Load data.
13 | "github.com/klauspost/gfx"
14 | "golang.org/x/image/draw"
15 | )
16 |
17 | const (
18 | renderWidth = 640
19 | renderHeight = 360
20 | )
21 |
22 | // Generates binary data.
23 | // To install go-bindata, do: go get -u github.com/jteeuwen/go-bindata/...
24 | //
25 | //go:generate go-bindata -ignore=\.go\z -pkg=data -o ./data/data.go ./data/...
26 |
27 | func main() {
28 | //rz := newFx("./data/pride_circle_grey.png")
29 | //rz := newFx("./data/light.png")
30 | gfx.InitShadedPalette(180, color.RGBA{R: 110, G: 110, B: 200})
31 |
32 | //fx := newFx("data/flower.png")
33 | fx := newFx("data/snowflake2.png")
34 | gfx.Run(func() { gfx.RunTimed(fx) })
35 | //gfx.RunWriteToDisk(fx, 1, "./saved/snow-%05d.png")
36 | }
37 |
38 | type vec2 struct{ u, v float32 }
39 | type vec3 struct{ x, y, z float32 }
40 |
41 | // clipWrap will clip by wrapping, asteroid style.
42 | func (v vec2) clipWrap(n float32) float32 {
43 | if n >= v.u && n <= v.v {
44 | return n
45 | }
46 | return v.u + float32(math.Mod(float64(n-v.u), float64(v.v-v.u)))
47 | }
48 |
49 | type particle struct {
50 | basePos vec3
51 | speed vec3
52 | }
53 |
54 | type scene struct {
55 | parts []particle
56 | projected []vec3
57 | bounds struct {
58 | y vec2
59 | }
60 | }
61 |
62 | func (s *scene) generate() {
63 | const parts = 2500
64 | s.parts = make([]particle, parts)
65 | rng := rand.New(rand.NewSource(0xc0cac01a))
66 | const depth = 5
67 | for i := range s.parts {
68 | part := &s.parts[i]
69 | part.basePos = vec3{
70 | x: -(renderWidth * depth) + rng.Float32()*renderWidth*depth*2,
71 | y: -(renderHeight * depth) + rng.Float32()*renderHeight*depth*2,
72 | z: 0.1 + rng.Float32()*4*depth,
73 | }
74 | part.speed = vec3{
75 | x: 10 + rng.Float32()*50,
76 | y: 100 + rng.Float32()*500,
77 | z: rng.Float32(),
78 | }
79 | }
80 | s.projected = make([]vec3, parts)
81 | s.bounds.y = vec2{-renderHeight * depth * 1.5, renderHeight * depth * 1.5}
82 | }
83 |
84 | func (s scene) At(t float32) {
85 | dst := s.projected
86 | if len(s.parts) != len(dst) {
87 | panic(fmt.Sprintf("len(s.parts) != len(dst), %d != %d", len(s.parts), len(dst)))
88 | }
89 | for i, p := range s.parts {
90 | var pos vec3
91 | pos.x = p.basePos.x + p.speed.x*float32(math.Sin(float64(p.speed.x+p.speed.z*t*math.Pi*4)))
92 | pos.y = s.bounds.y.clipWrap(p.basePos.y + (p.speed.y * t))
93 | pos.z = max32(0.1, p.basePos.z+p.speed.z*0.5*float32(math.Sin(float64(p.speed.z*50+p.speed.z*t*math.Pi))))
94 |
95 | d := &dst[i]
96 | invZ := 1.0 / pos.z
97 | d.x = pos.x*invZ + renderWidth/2
98 | d.y = pos.y*invZ + renderHeight/2
99 | d.z = invZ
100 | }
101 | }
102 |
103 | type fx struct {
104 | // main and mipmaps
105 | img *image.Gray
106 | mipmaps []*image.Gray
107 | draw *image.Gray
108 | logW, logH uint
109 | lines [][]byte
110 | scene scene
111 | }
112 |
113 | func newFx(file string) *fx {
114 | var fx fx
115 |
116 | // Load picture
117 | img, err := gfx.LoadPalPicture(file)
118 | if err != nil {
119 | panic(err)
120 | }
121 | // Ensure we are grayscale.
122 | grey := image.NewGray(img.Rect)
123 | draw.Draw(grey, grey.Rect, img, image.Pt(0, 0), draw.Src)
124 | fx.img = grey
125 |
126 | // Calculate the with in log(2)
127 | fx.logW = uint(bits.Len32(uint32(img.Rect.Dx()))) - 1
128 | fx.logH = uint(bits.Len32(uint32(img.Rect.Dy()))) - 1
129 |
130 | // Ensure that the width and height are actually powers of two
131 | if img.Rect.Dx() != 1<= 0; i-- {
156 | img := image.NewGray(image.Rect(0, 0, prev.Rect.Dx()/2, prev.Rect.Dy()/2))
157 | fmt.Println(i, img.Rect)
158 | fx.mipmaps[i] = img
159 | for y := 0; y < img.Rect.Dy(); y++ {
160 | src0, src1 := prev.Pix[y*2*prev.Stride:], prev.Pix[(y*2+1)*prev.Stride:]
161 | dst := img.Pix[y*img.Stride : (y+1)*img.Stride]
162 | for x := range dst {
163 | // Average 4 pixels.
164 | dst[x] = uint8((uint(src0[x*2]) + uint(src0[x*2+1]) + uint(src1[x*2]) + uint(src0[x*2+1]) + 2) >> 2)
165 | }
166 | }
167 | prev = img
168 | }
169 | fx.scene.generate()
170 | return &fx
171 | }
172 |
173 | // Render the effect at time t.
174 | func (fx *fx) Render(t float64) image.Image {
175 | //drawFn := fx.drawSpriteFast
176 | //drawFn := fx.drawSpriteMip
177 | drawFn := fx.drawSpriteNice
178 | //drawFn := fx.drawSpriteGo
179 |
180 | return fx.RenderParticles(t, drawFn)
181 |
182 | for i := range fx.draw.Pix {
183 | fx.draw.Pix[i] = 0
184 | }
185 | // return fx.Render2D(t, drawFn)
186 | return fx.RenderTest(t, drawFn)
187 | }
188 |
189 | // Render the effect at time t.
190 | func (fx *fx) RenderParticles(t float64, drawFn func(x, y, r int32)) image.Image {
191 | // Render fake sky/ground.
192 | for y, line := range fx.lines {
193 | f := 255.0 - 192
194 | if y < 64 {
195 | f = math.Abs(256 - float64(y*2) - 64)
196 | }
197 | if y > renderHeight-96 {
198 | f = math.Abs(128 - renderHeight + float64(y+20)*1.15)
199 | }
200 | v := uint8(math.Min(255, math.Max(0, f)))
201 | for x := range line {
202 | line[x] = v
203 | }
204 | }
205 |
206 | fx.scene.At(float32(t))
207 | for _, p := range fx.scene.projected {
208 | drawFn(int32(p.x*256), int32(p.y*256), int32(30*256*p.z)-300)
209 | }
210 |
211 | return fx.draw
212 | }
213 |
214 | func (fx *fx) Render2D(t float64, drawFn func(x, y, r int32)) image.Image {
215 | const (
216 | halfWidth = renderWidth * 0.5
217 | halfHeight = renderHeight * 0.5
218 | )
219 |
220 | for i := int32(0); i < 1024; i++ {
221 | x := 10 + 20*(i%32-16)
222 | y := 20 * (i/32 - 16)
223 | r := 7 * math.Abs(math.Sin(t+t*float64(x)/5)+math.Cos(t+t*float64(y)/3))
224 | drawFn(x*256+halfWidth*256, y*256+halfHeight*256, int32(256*r))
225 | }
226 | return fx.draw
227 | }
228 |
229 | func (fx *fx) RenderTest(t float64, drawFn func(x, y, r int32)) image.Image {
230 | const (
231 | halfWidth = renderWidth * 0.5
232 | halfHeight = renderHeight * 0.5
233 | )
234 | drawFn(
235 | int32(halfWidth*256+256*50*math.Sin(t*math.Pi*2*4)),
236 | int32(halfHeight*256+256*50*math.Cos(t*math.Pi*2*4)),
237 | //int32(256*50),
238 | int32(256*130*math.Abs(math.Sin(t*math.Pi))),
239 | )
240 | drawFn(
241 | int32(150*256+256*t*100),
242 | int32(55*256),
243 | int32(256*50),
244 | )
245 | drawFn(
246 | int32(55*256),
247 | int32(256*50+256*t*100),
248 | int32(256*50),
249 | )
250 |
251 | drawFn(
252 | int32(halfWidth*1.5*256+255),
253 | int32(halfHeight*256+255),
254 | int32(256*150*(1-t)),
255 | )
256 | drawFn(
257 | int32(55*256),
258 | int32(255*256),
259 | int32(256*15*math.Abs(math.Cos(t*math.Pi*10))),
260 | )
261 | drawFn(
262 | int32(100*256+int32(t*200*256)),
263 | int32(255*256),
264 | int32(256*2*math.Abs(math.Cos(t*math.Pi*2))),
265 | )
266 | return fx.draw
267 | }
268 |
269 | // drawSpriteFast will draw a particle centered at x,y with radius r.
270 | // The image is drawn with nearest neighbor scaling, but subpixel position and radius.
271 | // Input is assumed to be 24.8
272 | func (fx *fx) drawSpriteFast(x, y, r int32) {
273 | m := fx.calcMapping(x, y, r, int32(len(fx.mipmaps)-1))
274 | if m.mip == nil {
275 | return
276 | }
277 |
278 | v := m.v0
279 | for y := m.startY; y < m.endY; y++ {
280 | // First destination pixel
281 | dst := fx.draw.Pix[int(y)*fx.draw.Stride:]
282 | // Line in mipmap to read from.
283 | mipLine := m.mip.Pix[(v>>16)*uint32(m.mip.Stride):]
284 | // Reset u
285 | u := m.u0
286 | for x := m.startX; x < m.endX; x++ {
287 | // Read from u
288 | xPos := u >> 16
289 | // Add input to output.
290 | dst[x] = clamp8uint32(uint32(mipLine[xPos]) + uint32(dst[x]))
291 | // Offset u for every pixel
292 | u += m.uStep
293 | }
294 | // Offset v for every line
295 | v += m.vStep
296 | }
297 | }
298 |
299 | // drawSpriteMip will draw a particle centered at x,y with radius r.
300 | // The image is drawn with nearest neighbor scaling, but choosing from a mipmap
301 | // and with subpixel position and radius.
302 | // Input is assumed to be 24.8
303 | func (fx *fx) drawSpriteMip(x, y, r int32) {
304 | m := fx.calcMapping(x, y, r, -1)
305 | if m.mip == nil {
306 | return
307 | }
308 |
309 | // This is similar to drawSpriteFast
310 | v := m.v0
311 | for y := m.startY; y < m.endY; y++ {
312 | dst := fx.draw.Pix[int(y)*fx.draw.Stride:]
313 | mipLine := m.mip.Pix[(v>>16)*uint32(m.mip.Stride):]
314 | u := m.u0
315 | for x := m.startX; x < m.endX; x++ {
316 | xPos := u >> 16
317 | dst[x] = clamp8uint32(uint32(mipLine[xPos]) + uint32(dst[x]))
318 | u += m.uStep
319 | }
320 | v += m.vStep
321 | }
322 | }
323 |
324 | // drawSpriteNice will draw a particle centered at x,y with radius r.
325 | // The input is selected from the appropriate mipmap and bilinear interpolation is used.
326 | // The image position and size have subpixel precision.
327 | // Input is assumed to be 24.8
328 | func (fx *fx) drawSpriteNice(x, y, r int32) {
329 | m := fx.calcMapping(x, y, r, -1)
330 | if m.mip == nil {
331 | return
332 | }
333 | // Mipmap must be at least 2x2.
334 | v := m.v0
335 | for y := m.startY; y < m.endY; y++ {
336 | dst := fx.draw.Pix[int(y)*fx.draw.Stride:]
337 |
338 | // Input line above and below the current desired input.
339 | mipLine0 := m.mip.Pix[(v>>16)*uint32(m.mip.Stride):]
340 | mipLine1 := mipLine0
341 |
342 | // Calculate weight for lines above/below desired input.
343 | vf1 := (v & 0xffff) >> 8
344 | vf0 := 256 - vf1
345 | if (v + 65536) < m.mipSize {
346 | // Set mipline 1 to next line unless last line.
347 | mipLine1 = mipLine0[m.mip.Stride:]
348 | }
349 | u := m.u0
350 | for x := m.startX; x < m.endX; x++ {
351 | // Calculate pixel offset before and after desired pixel.
352 | xPos0 := u >> 16
353 | xPos1 := xPos0
354 | if u+65536 < m.mipSize {
355 | xPos1++
356 | }
357 | // Calculate weights as fp24.8.
358 | uf1 := (u & 0xffff) >> 8
359 | uf0 := 256 - uf1
360 | // Using the calculated weights, calculate output pixel, scaled up 16 bits.
361 | pix := uint32(mipLine0[xPos0]) * uf0 * vf0
362 | pix += uint32(mipLine0[xPos1]) * uf1 * vf0
363 | pix += uint32(mipLine1[xPos0]) * uf0 * vf1
364 | pix += uint32(mipLine1[xPos1]) * uf1 * vf1
365 |
366 | // Add output to current pixel value.
367 | dst[x] = clamp8uint32((pix >> 16) + uint32(dst[x]))
368 | u += m.uStep
369 | }
370 | v += m.vStep
371 | }
372 | }
373 |
374 | // drawSpriteGo will draw a particle centered at x,y with radius r.
375 | // Input is assumed to be 24.8
376 | func (fx *fx) drawSpriteGo(x, y, r int32) {
377 | m := fx.calcMapping(x, y, r, -1)
378 | if m.startX == m.endX || m.startY == m.endY || m.mip == nil {
379 | return
380 | }
381 | draw.ApproxBiLinear.Scale(fx.draw, image.Rect(int(m.startX), int(m.startY), int(m.endX), int(m.endY)),
382 | image.NewUniform(color.White), image.Rect(int(m.u0>>16), int(m.v0>>16), int(m.u1>>16), int(m.v1>>16)),
383 | draw.Over, &draw.Options{
384 | SrcMask: grayToShallowAlpha(m.mip),
385 | })
386 | }
387 |
388 | // mapping contains the information about the sprite needed
389 | // to draw it to the screen without bounds checks.
390 | type mapping struct {
391 | // Start and end coordinates in screen space.
392 | // This is where we will be drawing the pixels.
393 | // This is directly translatable to a screen coordinate.
394 | startX, endX, startY, endY int32
395 |
396 | // Start and end coordinates in 16.16 fixed point coordinates on the source texture.
397 | // One pixel on source is equal to 65536.
398 | u0, u1, v0, v1 uint32
399 |
400 | // Every pixel increment u and v by this when moving one pixel in screen space.
401 | vStep, uStep uint32
402 |
403 | // The size (width/height) of the chosen mip in uv scale.
404 | mipSize uint32
405 |
406 | // The image to draw from.
407 | // If nil, do not draw anything.
408 | mip *image.Gray
409 | }
410 |
411 | // calcMapping will return a mapping for a sprite with radius r placed at (x,y)
412 | // at the specified mip level.
413 | func (fx *fx) calcMapping(x, y, r, mip int32) mapping {
414 | var m mapping
415 |
416 | // Quick discard
417 | if x+r < 0 || x-r > (renderWidth*256) || y+r < 0 || y-r > (renderHeight*256) {
418 | return m
419 | }
420 |
421 | // For very small radius we simply draw a point in a 2x2 square.
422 | if r <= 128 {
423 | m.startX, m.endX = (x-r)>>8, (x-r)>>8+1
424 | m.startY, m.endY = (y-r)>>8, (y-r)>>8+1
425 | if m.startX >= renderWidth || m.startX < 0 || m.startY >= renderHeight || m.startY < 0 {
426 | return m
427 | }
428 | m.u1 = uint32(x-r) & 0xff
429 | m.u0 = 256 - m.u1
430 | m.v1 = uint32(y-r) & 0xff
431 | m.v0 = 256 - m.v1
432 |
433 | // Radius times 1x1 pixel value.
434 | rmip := (r * int32(fx.mipmaps[0].Pix[0])) >> 5
435 | m.u0 = (m.u0 * uint32(rmip)) >> 8
436 | m.u1 = (m.u1 * uint32(rmip)) >> 8
437 | m.v0 = (m.v0 * uint32(rmip)) >> 8
438 | m.v1 = (m.v1 * uint32(rmip)) >> 8
439 | m.mipSize = 1
440 | // leave mip nil
441 | fx.drawPoint(&m)
442 | return m
443 | }
444 |
445 | mipLevel := mip
446 | if mip < 0 {
447 | mipLevel = int32(bits.Len32(uint32(r>>6))) - 1
448 | if int(mipLevel) >= len(fx.mipmaps) {
449 | mipLevel = int32(len(fx.mipmaps)) - 1
450 | } else if mipLevel < 1 {
451 | mipLevel = 1
452 | }
453 | }
454 | m.mip = fx.mipmaps[mipLevel]
455 | m.mipSize = uint32(1<<16) << uint(mipLevel)
456 |
457 | // output pixels per texture pixels * 256
458 | textureScale := float64(m.mip.Rect.Dx()) / (float64(r) / (128 * 256))
459 |
460 | // Screen space start, rounded down
461 | m.startX, m.startY = (x-r)>>8, (y-r)>>8
462 | // Screen space, rounded up.
463 | m.endX, m.endY = (x+r+255)>>8, (y+r+255)>>8
464 |
465 | // Calculate rounded difference and convert to texture space.
466 | m.u0, m.v0 = 255-uint32((x-r)-(m.startX<<8)), 255-uint32((y-r)-(m.startY<<8))
467 | m.u0, m.v0 = uint32(float64(m.u0)*textureScale), uint32(float64(m.v0)*textureScale)
468 |
469 | // Calculate rounded difference and convert to texture space.
470 | m.u1, m.v1 = 255-uint32((m.endX<<8)-(x+r)), 255-uint32((m.endY<<8)-(y+r))
471 | m.u1, m.v1 = m.mipSize-uint32(float64(m.u1)*textureScale), m.mipSize-uint32(float64(m.v1)*textureScale)
472 |
473 | // Calculate step size per screen space pixel.
474 | m.uStep = uint32(float64(m.u1-m.u0) / float64(m.endX-m.startX))
475 | m.vStep = uint32(float64(m.v1-m.v0) / float64(m.endY-m.startY))
476 |
477 | if false && (m.uStep == 0 || m.vStep == 0 || m.u0 >= m.u1 || m.v0 >= m.v1) {
478 | fmt.Printf("r:%d, m:%+v v0:%v, v1: %v scale:%v (%d, %d), x,y (%v, %v)\n",
479 | r, m, 256-uint32((y-r)-(m.startY<<8)), 256-uint32((m.endY<<8)-(y+r)),
480 | textureScale/256, m.endX-m.startX, m.mip.Rect.Dx(),
481 | float64(x)/256, float64(y)/256)
482 | // Sanity check
483 | m.mip = nil
484 | return m
485 | }
486 |
487 | // Clip left, top, right, bottom.
488 | if m.startX < 0 {
489 | m.u0 += m.uStep * uint32(-m.startX)
490 | m.startX = 0
491 | }
492 | if m.startY < 0 {
493 | m.v0 += m.vStep * uint32(-m.startY)
494 | m.startY = 0
495 | }
496 | if m.endX > renderWidth {
497 | // Not needed for most
498 | m.v1 -= uint32(m.endX-renderWidth) * m.uStep
499 | m.endX = renderWidth
500 | }
501 | if m.endY > renderHeight {
502 | // Not needed for most
503 | m.v1 -= uint32(m.endY-renderHeight) * m.vStep
504 | m.endY = renderHeight
505 | }
506 |
507 | if false {
508 | // Final sanity to make sure we don't go over due to rounding.
509 | for ; m.u0+m.uStep*uint32(m.endX-m.startX) >= m.mipSize; m.endX-- {
510 | }
511 | for ; m.v0+m.vStep*uint32(m.endY-m.startY) >= m.mipSize; m.endY-- {
512 | }
513 | }
514 | return m
515 | }
516 |
517 | // drawPoint will draw a single point between the pixel.
518 | func (fx *fx) drawPoint(m *mapping) {
519 | dst := fx.draw.Pix[m.startX+m.startY*int32(fx.draw.Stride):]
520 | dst[0] = clamp8uint32((m.u0*m.v0)>>8 + uint32(dst[0]))
521 | if m.endX < renderWidth {
522 | dst[1] = clamp8uint32((m.u1*m.v0)>>8 + uint32(dst[1]))
523 | }
524 | if m.endY >= renderHeight {
525 | return
526 | }
527 | dst = dst[fx.draw.Stride:]
528 | dst[0] = clamp8uint32((m.u0*m.v1)>>8 + uint32(dst[0]))
529 | if m.endX < renderWidth {
530 | dst[1] = clamp8uint32((m.u1*m.v1)>>8 + uint32(dst[1]))
531 | }
532 | }
533 |
534 | func clamp8uint32(v uint32) uint8 {
535 | if v >= 255 {
536 | return 255
537 | }
538 | return uint8(v)
539 | }
540 |
541 | // grayToShallowAlpha converts the grey image data to an alpha image.
542 | // The image data is a shallow (non-copy) representation of the input pixels.
543 | func grayToShallowAlpha(src *image.Gray) *image.Alpha {
544 | return &image.Alpha{
545 | Pix: src.Pix,
546 | Stride: src.Stride,
547 | Rect: src.Rect,
548 | }
549 | }
550 |
551 | func max32(a, b float32) float32 {
552 | if a >= b {
553 | return a
554 | }
555 | return b
556 | }
557 |
558 | type fp8x24 uint32
559 | type fp16x16 uint32
560 |
561 | func (f fp8x24) String() string {
562 | return fmt.Sprintf("(%d,0x%x)", uint32(f)>>8, uint8(f))
563 | }
564 | func (f fp16x16) String() string {
565 | return fmt.Sprintf("(%d,0x%x)", uint32(f)>>16, uint16(f))
566 | }
567 |
--------------------------------------------------------------------------------
/ep06/wasm.cmd:
--------------------------------------------------------------------------------
1 | SET GOOS=
2 | SET GOARCH=
3 |
4 | go generate
5 |
6 | SET GOOS=js
7 | SET GOARCH=wasm
8 | go build -o fx.wasm main.go
9 |
--------------------------------------------------------------------------------
/ep08/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Episode 8
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
Full Screen
22 |
23 |
24 |
Starting
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/ep08/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "image"
5 | "time"
6 |
7 | "github.com/klauspost/gad/hoaxplus/00-intro"
8 | "github.com/klauspost/gad/hoaxplus/01-title"
9 | _ "github.com/klauspost/gad/hoaxplus/data"
10 | "github.com/klauspost/gfx"
11 | )
12 |
13 | var (
14 | renderWidth = 624
15 | renderHeight = 240
16 | )
17 |
18 | // Generates binary data.
19 | // To install go-bindata, do: go get -u github.com/jteeuwen/go-bindata/...
20 | //
21 | //go:generate go-bindata -ignore=\.go\z -pkg=data -o ../../data/data.go --prefix=../../data ../../data/...
22 |
23 | func main() {
24 | // Create our draw buffer
25 | screen := image.NewGray(image.Rect(0, 0, renderWidth, renderHeight))
26 | fullColor := image.NewRGBA(image.Rect(0, 0, renderWidth, renderHeight))
27 | gfx.SetRenderSize(renderWidth, renderHeight)
28 | gfx.Fullscreen(false)
29 |
30 | fx := intro.NewIntro(screen)
31 | if true {
32 | fx = title.NewTitle(screen, fullColor)
33 | }
34 | gfx.Run(func() { gfx.RunTimedDur(fx, 5*time.Second) })
35 | }
36 |
--------------------------------------------------------------------------------
/ep08/wasm.cmd:
--------------------------------------------------------------------------------
1 | SET GOOS=
2 | SET GOARCH=
3 |
4 | REM go generate
5 |
6 | SET GOOS=js
7 | SET GOARCH=wasm
8 | go build -o fx.wasm main.go
9 |
--------------------------------------------------------------------------------
/hoaxplus/00-intro/intro.go:
--------------------------------------------------------------------------------
1 | package intro
2 |
3 | import (
4 | "github.com/klauspost/gfx"
5 | "image"
6 | )
7 |
8 | func NewIntro(screen *image.Gray) gfx.TimedEffect {
9 | return &intro{draw: screen}
10 | }
11 |
12 | type intro struct {
13 | draw *image.Gray
14 | cleared bool
15 | }
16 |
17 | func (fx *intro) Render(t float64) image.Image {
18 | if !fx.cleared {
19 | for i := range fx.draw.Pix {
20 | fx.draw.Pix[i] = 0
21 | }
22 | fx.cleared = true
23 | }
24 | img := fx.draw
25 | w, h := img.Rect.Dx(), img.Rect.Dy()
26 | top := img.Pix[:img.Stride]
27 | bottom := img.Pix[(h-1)*img.Stride:]
28 |
29 | xwhere := (int)(float64(w+1) * t)
30 | const white = 255
31 | const grey = 40
32 |
33 | drawLine := func(pix []byte, col byte, start, stop int) {
34 | if start < 0 {
35 | start = 0
36 | }
37 | if stop > len(pix) {
38 | stop = len(pix)
39 | }
40 | for i := start; i < stop; i++ {
41 | pix[i] = col
42 | }
43 | }
44 | drawLine(top, white, 0, xwhere+4)
45 | drawLine(top, grey, 0, xwhere)
46 | drawLine(bottom, white, w-xwhere-4, w)
47 | drawLine(bottom, grey, w-xwhere, w)
48 | return img
49 | }
50 |
--------------------------------------------------------------------------------
/hoaxplus/01-title/title.go:
--------------------------------------------------------------------------------
1 | package title
2 |
3 | import (
4 | "image"
5 | "image/color"
6 | "math"
7 |
8 | "github.com/klauspost/gad/hoaxplus/primitive"
9 | "github.com/klauspost/gfx"
10 | )
11 |
12 | func NewTitle(draw *image.Gray, screen *image.RGBA) gfx.TimedEffect {
13 | t := title{draw: draw, screen: screen}
14 | for i := range t.color[0][:] {
15 | if i <= 192 {
16 | t.color[0][i] =
17 | color.RGBA{
18 | R: uint8((248 * i) >> 8),
19 | G: uint8((289 * i) >> 8),
20 | B: uint8((294 * i) >> 8),
21 | A: 0xff,
22 | }
23 | t.color[1][i] =
24 | color.RGBA{
25 | R: uint8((300 * i) >> 8),
26 | G: uint8((278 * i) >> 8),
27 | B: uint8((252 * i) >> 8),
28 | A: 0xff,
29 | }
30 | } else {
31 | pixrem := i - 192
32 | t.color[0][i] =
33 | color.RGBA{
34 | R: 198 + uint8((57*pixrem)>>6),
35 | G: 218 + uint8((37*pixrem)>>6),
36 | B: 222 + uint8((33*pixrem)>>6),
37 | A: 0xff,
38 | }
39 | t.color[1][i] =
40 | color.RGBA{
41 | R: 226 + uint8((29*pixrem)>>6),
42 | G: 210 + uint8((45*pixrem)>>6),
43 | B: 190 + uint8((65*pixrem)>>6),
44 | A: 0xff,
45 | }
46 | }
47 | }
48 | b, err := gfx.Load("Basehead.obj")
49 | if err != nil {
50 | panic(err)
51 | }
52 | t.verts, t.edges = primitive.LoadOBJ(b)
53 | t.vTransformed = make(primitive.P3Ds, len(t.verts))
54 | t.vProjected = make(primitive.P2Ds, len(t.verts))
55 | return &t
56 | }
57 |
58 | type title struct {
59 | draw *image.Gray
60 | screen *image.RGBA
61 | cleared bool
62 | verts primitive.P3Ds
63 | edges [][2]int
64 | vTransformed primitive.P3Ds
65 | vProjected primitive.P2Ds
66 | color [2][256]color.RGBA
67 | }
68 |
69 | func (fx *title) Render(t float64) image.Image {
70 | img := fx.draw
71 | for i := range img.Pix {
72 | img.Pix[i] = 192
73 | }
74 | // Convert to float
75 | fw, fh := float32(img.Rect.Dx()), float32(img.Rect.Dy())
76 |
77 | // Draw line across screen
78 | primitive.Line{P2: primitive.Point2D{X: fw, Y: fh}}.DrawAA(img, 255)
79 |
80 | // Draw model
81 | fx.verts.RotateTo(fx.vTransformed, math.Pi/2, -t*math.Pi*2, 0)
82 | fx.vTransformed.ProjectTo(fx.vProjected, fw, fh, float32(math.Sin(t*math.Pi))*10)
83 | for _, edge := range fx.edges {
84 | p0, p1 := fx.vProjected[edge[0]], fx.vProjected[edge[1]]
85 | if p0.X == primitive.BehindCamera || p1.X == primitive.BehindCamera {
86 | continue
87 | }
88 | primitive.Line{
89 | P1: p0,
90 | P2: p1,
91 | }.DrawAA(img, 0)
92 | }
93 |
94 | fx.transfer()
95 | return fx.screen
96 | }
97 |
98 | func (fx *title) transfer() {
99 | w, h := fx.screen.Bounds().Dx(), fx.screen.Bounds().Dy()
100 | src := fx.draw
101 | dst := fx.screen
102 | for y := 0; y < h; y++ {
103 | xch := (int)((float64)(y*w) / (float64)(h))
104 | line := src.Pix[y*src.Stride : y*src.Stride+src.Rect.Dx()]
105 | dLine := dst.Pix[y*dst.Stride : y*dst.Stride+len(line)*4]
106 |
107 | // Left of change
108 | pal := fx.color[0][:]
109 | for x, v := range line[:xch] {
110 | col := pal[v]
111 | dLine[x*4] = col.R
112 | dLine[x*4+1] = col.G
113 | dLine[x*4+2] = col.B
114 | dLine[x*4+3] = 255
115 | }
116 |
117 | // Right side.
118 | line = line[xch:]
119 | dLine = dLine[xch*4:]
120 | pal = fx.color[1][:]
121 | for x, v := range line {
122 | col := pal[v]
123 | dLine[x*4] = col.R
124 | dLine[x*4+1] = col.G
125 | dLine[x*4+2] = col.B
126 | dLine[x*4+3] = 255
127 | }
128 | }
129 | }
130 |
131 | func (fx *title) transferGrey() {
132 | _, h := fx.screen.Bounds().Dx(), fx.screen.Bounds().Dy()
133 | src := fx.draw
134 | dst := fx.screen
135 | for y := 0; y < h; y++ {
136 | line := src.Pix[y*src.Stride : y*src.Stride+src.Rect.Dx()]
137 | dLine := dst.Pix[y*dst.Stride : y*dst.Stride+len(line)*4]
138 |
139 | for x, v := range line {
140 | dLine[x*4] = v
141 | dLine[x*4+1] = v
142 | dLine[x*4+2] = v
143 | dLine[x*4+3] = 255
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/hoaxplus/cmd/hoax/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "image"
5 | "time"
6 |
7 | "github.com/klauspost/gad/hoaxplus/00-intro"
8 | "github.com/klauspost/gad/hoaxplus/01-title"
9 | _ "github.com/klauspost/gad/hoaxplus/data"
10 | "github.com/klauspost/gfx"
11 | )
12 |
13 | var (
14 | renderWidth = 624
15 | renderHeight = 240
16 | )
17 |
18 | // Generates binary data.
19 | // To install go-bindata, do: go get -u github.com/jteeuwen/go-bindata/...
20 | //
21 | //go:generate go-bindata -ignore=\.go\z -pkg=data -o ../../data/data.go --prefix=../../data ../../data/...
22 |
23 | func main() {
24 | // Create our draw buffer
25 | screen := image.NewGray(image.Rect(0, 0, renderWidth, renderHeight))
26 | fullColor := image.NewRGBA(image.Rect(0, 0, renderWidth, renderHeight))
27 | gfx.SetRenderSize(renderWidth, renderHeight)
28 | gfx.Fullscreen(false)
29 |
30 | fx := intro.NewIntro(screen)
31 | if true {
32 | fx = title.NewTitle(screen, fullColor)
33 | }
34 | gfx.Run(func() { gfx.RunTimedDur(fx, 5*time.Second) })
35 | }
36 |
--------------------------------------------------------------------------------
/hoaxplus/data/Basehead.obj:
--------------------------------------------------------------------------------
1 | # Blender v2.69 (sub 0) OBJ File: 'Basehead.blend'
2 | # www.blender.org
3 | # Made by BlenderGuyz https://www.turbosquid.com/FullPreview/Index.cfm/ID/805661
4 | mtllib Basehead.mtl
5 | o Head_Cube
6 | v 0.794880 -0.456218 -1.453191
7 | v 0.631179 -0.544477 1.149647
8 | v 1.138971 -0.447948 -0.797869
9 | v 1.094424 -0.450260 0.416698
10 | v 0.439387 -0.454233 -1.604853
11 | v 0.277122 -0.541346 1.593228
12 | v 0.962543 -0.496748 0.802866
13 | v 1.031688 -0.430602 -1.168014
14 | v 0.707379 -2.084441 -1.645555
15 | v 0.839524 -2.829275 -0.206489
16 | v 1.397615 -2.236477 -0.621362
17 | v 0.434208 -2.923688 -0.123380
18 | v 1.050709 -1.962676 -1.461045
19 | v 1.293451 -2.041516 -1.087568
20 | v 1.235680 -2.613284 -0.304228
21 | v 0.340290 -2.143095 -1.758874
22 | v 1.115928 -2.194080 -1.851622
23 | v 1.845940 -2.157743 -1.262549
24 | v 0.617709 -2.264206 -1.954206
25 | v 2.010724 -2.349208 -0.716563
26 | v 1.200113 -3.008740 -0.212898
27 | v 1.574329 -2.080434 -1.682444
28 | v 0.570588 -3.111907 -0.052411
29 | v 1.740340 -2.762577 -0.342175
30 | v 0.544184 -1.218010 -1.316640
31 | v 0.785863 0.123222 -1.493973
32 | v 0.631784 0.065619 1.101769
33 | v 0.544759 -1.373754 1.087082
34 | v 1.175014 0.129346 -0.859118
35 | v 0.891132 -1.348171 0.039141
36 | v 0.868947 -1.290124 -0.704046
37 | v 1.139899 0.081269 0.384301
38 | v 0.837687 -1.364774 0.456978
39 | v 0.793231 1.461336 -0.051452
40 | v 0.713654 1.338543 -0.865439
41 | v 0.726249 1.374125 0.384978
42 | v 0.409165 -1.889288 0.476818
43 | v 0.413912 -1.767348 0.077705
44 | v 0.259894 -1.211585 -1.410389
45 | v 0.447793 0.127746 -1.647718
46 | v 0.713996 -0.856596 -1.347879
47 | v 0.752636 0.673336 -1.427497
48 | v 0.212867 0.086756 1.329009
49 | v 0.357345 -1.381319 1.188635
50 | v 0.732227 0.650184 1.043815
51 | v 0.654066 -0.939296 1.125531
52 | v 0.889012 -1.449899 -0.343519
53 | v 1.160249 0.646703 -0.086923
54 | v 1.130602 0.601183 -0.831471
55 | v 1.090904 0.593201 0.273403
56 | v 1.075487 -0.935149 -0.039751
57 | v 1.082869 -0.843542 -0.740058
58 | v 1.020563 -0.873545 0.347217
59 | v 0.772650 1.426925 -0.451773
60 | v 0.482622 1.605282 -0.040162
61 | v 0.426543 1.448078 -0.917558
62 | v 0.443451 1.503576 0.417306
63 | v 0.184642 -1.945136 0.517415
64 | v 0.176943 -1.828176 0.063050
65 | v 0.751049 -1.803618 -1.319485
66 | v 0.268966 -2.611370 -0.157706
67 | v 0.392801 -1.919171 -0.138765
68 | v 0.684180 1.119959 0.843505
69 | v 0.639849 1.116517 -1.197492
70 | v 1.045719 1.150136 -0.052040
71 | v 0.960438 1.120901 -0.785369
72 | v 0.975766 0.100961 0.771586
73 | v 0.742840 -1.359286 0.823574
74 | v 0.379030 -1.751386 0.972500
75 | v 1.068913 0.117326 -1.234360
76 | v 0.748300 -1.229600 -1.130803
77 | v 0.958901 -2.034204 -0.563438
78 | v 0.910357 -1.874164 -0.970900
79 | v 0.685983 -1.642155 0.064883
80 | v 0.545493 -2.517920 -0.209344
81 | v 0.988320 1.116698 0.346230
82 | v 0.810883 -2.329444 -0.291012
83 | v 0.540159 -1.931201 -1.516239
84 | v 0.648070 -1.672735 0.417637
85 | v 0.394747 -0.858695 -1.479472
86 | v 0.428887 0.688365 -1.571638
87 | v 0.281567 0.656137 1.176196
88 | v 0.313651 -0.949308 1.240532
89 | v 1.172400 0.599202 -0.417715
90 | v 1.093921 -0.881204 -0.391642
91 | v 0.470959 1.561494 -0.484958
92 | v 0.183718 -1.955385 -0.116337
93 | v 0.364051 1.225281 0.905220
94 | v 0.365010 1.202835 -1.287747
95 | v 1.028806 1.145044 -0.410251
96 | v 0.970931 0.601422 0.706430
97 | v 0.895122 -0.912495 0.819637
98 | v 0.219718 -1.781411 1.040744
99 | v 1.020569 0.612032 -1.172499
100 | v 0.978438 -0.840622 -1.122864
101 | v 0.275865 -1.996229 -1.638517
102 | v 0.621035 -1.760691 -0.169148
103 | v 0.913952 0.981099 0.682378
104 | v 0.898184 0.993185 -1.079507
105 | v 0.576067 -1.655662 0.765837
106 | v 0.475751 -1.690193 -1.344981
107 | v 0.417265 -2.268152 -0.174915
108 | v 0.816613 -1.826042 -0.435965
109 | v 0.198171 -2.327462 -0.147365
110 | v 0.667988 -1.636359 -1.149996
111 | v 0.795842 -1.716311 -0.802179
112 | v 0.636113 -2.103915 -0.226097
113 | v 0.232324 -1.701587 -1.455695
114 | v 1.208377 -0.413856 -0.464327
115 | v 1.241327 0.111121 -0.479527
116 | v 1.113224 -0.375647 0.201736
117 | v 1.155852 -0.009892 0.181728
118 | v 1.198228 0.309252 -0.085963
119 | v 1.155757 0.161210 0.105486
120 | v 1.116919 -0.704591 -0.038965
121 | v 1.073119 -0.617570 0.160612
122 | v 1.216728 0.282039 -0.250336
123 | v 1.157836 -0.635730 -0.232826
124 | v 1.234213 -0.351310 -0.286095
125 | v 1.256683 0.013661 -0.292317
126 | v 1.323840 0.269692 -0.011425
127 | v 1.191158 -0.763654 0.005345
128 | v 1.424983 0.225411 -0.165862
129 | v 1.309679 -0.681250 -0.175907
130 | v 1.440080 -0.390069 -0.239910
131 | v 1.487426 0.005347 -0.222527
132 | v 1.176485 -0.622691 -0.133370
133 | v 1.279293 -0.346559 -0.195914
134 | v 1.251290 0.200534 -0.165374
135 | v 1.302813 -0.014104 -0.199447
136 | v 1.297737 0.010328 -0.021320
137 | v 1.255109 -0.355427 -0.001312
138 | v 0.000000 -0.453655 -1.659522
139 | v 0.000000 -0.541361 1.644740
140 | v 0.000000 -2.166581 -1.797678
141 | v 0.000000 -2.931921 -0.092391
142 | v 0.000000 -2.022603 -1.682083
143 | v 0.000000 -2.309822 -1.987709
144 | v 0.000000 -3.150186 -0.031994
145 | v 0.000000 -1.194687 -1.471510
146 | v 0.000000 0.128182 -1.702579
147 | v 0.000000 0.083227 1.367990
148 | v 0.000000 -1.385609 1.215298
149 | v 0.000000 1.661600 -0.035653
150 | v 0.000000 1.484891 -0.938427
151 | v 0.000000 1.547083 0.431373
152 | v 0.000000 -1.962361 0.519891
153 | v 0.000000 -1.849640 0.069715
154 | v 0.000000 -2.629138 -0.126451
155 | v 0.000000 -0.855055 -1.534732
156 | v 0.000000 0.693109 -1.621896
157 | v 0.000000 0.666400 1.203721
158 | v 0.000000 -0.951767 1.277723
159 | v 0.000000 1.612926 -0.500365
160 | v 0.000000 -1.962373 -0.104327
161 | v 0.000000 1.246569 0.927286
162 | v 0.000000 1.223347 -1.312165
163 | v 0.000000 -1.812575 1.064772
164 | v -0.794880 -0.456218 -1.453191
165 | v -0.631179 -0.544477 1.149647
166 | v -1.138971 -0.447948 -0.797869
167 | v -1.094424 -0.450260 0.416698
168 | v -0.439387 -0.454233 -1.604853
169 | v -0.277122 -0.541346 1.593228
170 | v -0.962543 -0.496748 0.802866
171 | v -1.031688 -0.430602 -1.168014
172 | v -0.707379 -2.084441 -1.645555
173 | v -0.839524 -2.829275 -0.206489
174 | v -1.397615 -2.236477 -0.621362
175 | v -0.434208 -2.923688 -0.123380
176 | v -1.050709 -1.962676 -1.461045
177 | v -1.293451 -2.041516 -1.087568
178 | v -1.235680 -2.613284 -0.304228
179 | v -0.340290 -2.143095 -1.758874
180 | v -1.115928 -2.194080 -1.851622
181 | v -1.845940 -2.157743 -1.262549
182 | v -0.617709 -2.264206 -1.954206
183 | v -2.010724 -2.349208 -0.716563
184 | v -1.200113 -3.008740 -0.212898
185 | v -1.574329 -2.080434 -1.682444
186 | v -0.570588 -3.111907 -0.052411
187 | v -1.740340 -2.762577 -0.342175
188 | v -0.544184 -1.218010 -1.316640
189 | v -0.785863 0.123222 -1.493973
190 | v -0.631784 0.065619 1.101769
191 | v -0.544759 -1.373754 1.087082
192 | v -1.175014 0.129346 -0.859118
193 | v -0.891132 -1.348171 0.039141
194 | v -0.868947 -1.290124 -0.704046
195 | v -1.139899 0.081269 0.384301
196 | v -0.837687 -1.364774 0.456978
197 | v -0.793231 1.461336 -0.051452
198 | v -0.713654 1.338543 -0.865439
199 | v -0.726249 1.374125 0.384978
200 | v -0.409165 -1.889288 0.476818
201 | v -0.413912 -1.767348 0.077705
202 | v -0.259894 -1.211585 -1.410389
203 | v -0.447793 0.127746 -1.647718
204 | v -0.713996 -0.856596 -1.347879
205 | v -0.752636 0.673336 -1.427497
206 | v -0.212867 0.086756 1.329009
207 | v -0.357345 -1.381319 1.188635
208 | v -0.732227 0.650184 1.043815
209 | v -0.654066 -0.939296 1.125531
210 | v -0.889012 -1.449899 -0.343519
211 | v -1.160249 0.646703 -0.086923
212 | v -1.130602 0.601183 -0.831471
213 | v -1.090904 0.593201 0.273403
214 | v -1.075487 -0.935149 -0.039751
215 | v -1.082869 -0.843542 -0.740058
216 | v -1.020563 -0.873545 0.347217
217 | v -0.772650 1.426925 -0.451773
218 | v -0.482622 1.605282 -0.040162
219 | v -0.426543 1.448078 -0.917558
220 | v -0.443451 1.503576 0.417306
221 | v -0.184642 -1.945136 0.517415
222 | v -0.176943 -1.828176 0.063050
223 | v -0.751049 -1.803618 -1.319485
224 | v -0.268966 -2.611370 -0.157706
225 | v -0.392801 -1.919171 -0.138765
226 | v -0.684180 1.119959 0.843505
227 | v -0.639849 1.116517 -1.197492
228 | v -1.045719 1.150136 -0.052040
229 | v -0.960438 1.120901 -0.785369
230 | v -0.975766 0.100961 0.771586
231 | v -0.742840 -1.359286 0.823574
232 | v -0.379030 -1.751386 0.972500
233 | v -1.068913 0.117326 -1.234360
234 | v -0.748300 -1.229600 -1.130803
235 | v -0.958901 -2.034204 -0.563438
236 | v -0.910357 -1.874164 -0.970900
237 | v -0.685983 -1.642155 0.064883
238 | v -0.545493 -2.517920 -0.209344
239 | v -0.988320 1.116698 0.346230
240 | v -0.810883 -2.329444 -0.291012
241 | v -0.540159 -1.931201 -1.516239
242 | v -0.648070 -1.672735 0.417637
243 | v -0.394747 -0.858695 -1.479472
244 | v -0.428887 0.688365 -1.571638
245 | v -0.281567 0.656137 1.176196
246 | v -0.313651 -0.949308 1.240532
247 | v -1.172400 0.599202 -0.417715
248 | v -1.093921 -0.881204 -0.391642
249 | v -0.470959 1.561494 -0.484958
250 | v -0.183718 -1.955385 -0.116337
251 | v -0.364051 1.225281 0.905220
252 | v -0.365010 1.202835 -1.287747
253 | v -1.028806 1.145044 -0.410251
254 | v -0.970931 0.601422 0.706430
255 | v -0.895122 -0.912495 0.819637
256 | v -0.219718 -1.781411 1.040744
257 | v -1.020569 0.612032 -1.172499
258 | v -0.978438 -0.840622 -1.122864
259 | v -0.275865 -1.996229 -1.638517
260 | v -0.621035 -1.760691 -0.169148
261 | v -0.913952 0.981099 0.682378
262 | v -0.898184 0.993185 -1.079507
263 | v -0.576067 -1.655662 0.765837
264 | v 0.000000 -1.706536 -1.509472
265 | v -0.475751 -1.690193 -1.344981
266 | v -0.417265 -2.268152 -0.174915
267 | v -0.816613 -1.826042 -0.435965
268 | v -0.198171 -2.327462 -0.147365
269 | v -0.667988 -1.636359 -1.149996
270 | v 0.000000 -2.333460 -0.125651
271 | v -0.795842 -1.716311 -0.802179
272 | v -0.636113 -2.103915 -0.226097
273 | v -0.232324 -1.701587 -1.455695
274 | v -1.208377 -0.413856 -0.464327
275 | v -1.241327 0.111121 -0.479527
276 | v -1.113224 -0.375647 0.201736
277 | v -1.155852 -0.009892 0.181728
278 | v -1.198228 0.309252 -0.085963
279 | v -1.155757 0.161210 0.105486
280 | v -1.116919 -0.704591 -0.038965
281 | v -1.073119 -0.617570 0.160612
282 | v -1.216728 0.282039 -0.250336
283 | v -1.157836 -0.635730 -0.232826
284 | v -1.234213 -0.351310 -0.286095
285 | v -1.256683 0.013661 -0.292317
286 | v -1.323840 0.269692 -0.011425
287 | v -1.191158 -0.763654 0.005345
288 | v -1.424983 0.225411 -0.165862
289 | v -1.309679 -0.681250 -0.175907
290 | v -1.440080 -0.390069 -0.239910
291 | v -1.487426 0.005347 -0.222527
292 | v -1.176485 -0.622691 -0.133370
293 | v -1.279293 -0.346559 -0.195914
294 | v -1.251290 0.200534 -0.165374
295 | v -1.302813 -0.014104 -0.199447
296 | v -1.297737 0.010328 -0.021320
297 | v -1.255109 -0.355427 -0.001312
298 | usemtl Material
299 | s off
300 | f 40 5 133 141
301 | f 70 8 1 26
302 | f 83 6 134 153
303 | f 32 50 91 67
304 | f 92 7 2 46
305 | f 95 8 3 52
306 | f 53 4 7 92
307 | f 26 1 5 40
308 | f 79 37 38 74
309 | f 96 78 9 16
310 | f 77 75 10 15
311 | f 73 72 11 14
312 | f 75 61 12 10
313 | f 137 96 16 135
314 | f 72 77 15 11
315 | f 78 60 13 9
316 | f 61 149 136 12
317 | f 60 73 14 13
318 | f 108 101 78 96
319 | f 107 102 75 77
320 | f 106 103 72 73
321 | f 102 104 61 75
322 | f 259 108 96 137
323 | f 103 107 77 72
324 | f 101 105 60 78
325 | f 104 265 149 61
326 | f 105 106 73 60
327 | f 80 39 140 150
328 | f 95 71 25 41
329 | f 41 25 39 80
330 | f 5 80 150 133
331 | f 81 40 141 151
332 | f 8 95 41 1
333 | f 94 70 26 42
334 | f 42 26 40 81
335 | f 89 81 151 157
336 | f 64 42 81 89
337 | f 82 88 156 152
338 | f 43 82 152 142
339 | f 6 43 142 134
340 | f 67 91 45 27
341 | f 7 67 27 2
342 | f 2 27 43 6
343 | f 44 83 153 143
344 | f 93 44 143 158
345 | f 68 92 46 28
346 | f 100 68 28 69
347 | f 69 28 44 93
348 | f 45 63 88 82
349 | f 76 50 48 65
350 | f 70 94 49 29
351 | f 8 70 29 3
352 | f 47 85 51 30
353 | f 97 47 30 74
354 | f 71 95 52 31
355 | f 16 9 17 19
356 | f 15 10 21 24
357 | f 84 90 65 48
358 | f 4 32 67 7
359 | f 79 33 68 100
360 | f 86 154 144 55
361 | f 89 157 145 56
362 | f 56 145 154 86
363 | f 54 86 55 34
364 | f 90 54 34 65
365 | f 64 89 56 35
366 | f 99 64 35 66
367 | f 66 35 54 90
368 | f 74 30 33 79
369 | f 57 146 156 88
370 | f 55 144 146 57
371 | f 76 36 63 98
372 | f 58 93 158 147
373 | f 79 100 69 37
374 | f 65 34 36 76
375 | f 87 59 148 155
376 | f 58 147 148 59
377 | f 97 74 38 62
378 | f 62 38 59 87
379 | f 14 11 20 18
380 | f 10 12 23 21
381 | f 135 16 19 138
382 | f 11 15 24 20
383 | f 9 13 22 17
384 | f 12 136 139 23
385 | f 13 14 18 22
386 | f 38 37 58 59
387 | f 1 41 80 5
388 | f 99 94 42 64
389 | f 98 63 45 91
390 | f 28 46 83 44
391 | f 50 76 98 91
392 | f 99 66 49 94
393 | f 27 45 82 43
394 | f 31 52 85 47
395 | f 33 53 92 68
396 | f 53 33 30 51
397 | f 35 56 86 54
398 | f 36 57 88 63
399 | f 37 69 93 58
400 | f 57 36 34 55
401 | f 46 2 6 83
402 | f 49 66 90 84
403 | f 39 25 101 108
404 | f 97 62 102 107
405 | f 31 47 103 106
406 | f 62 87 104 102
407 | f 140 39 108 259
408 | f 47 97 107 103
409 | f 25 71 105 101
410 | f 87 155 265 104
411 | f 71 31 106 105
412 | f 52 3 109 85
413 | f 3 29 110 109
414 | f 29 49 84 110
415 | f 4 53 116 111
416 | f 50 32 112 114
417 | f 32 4 111 112
418 | f 85 109 119 118
419 | f 109 110 120 119
420 | f 110 84 117 120
421 | f 48 50 114 113
422 | f 53 51 115 116
423 | f 84 48 113 117
424 | f 51 85 118 115
425 | f 127 128 125 124
426 | f 128 130 126 125
427 | f 130 129 123 126
428 | f 118 119 128 127
429 | f 119 120 130 128
430 | f 120 117 129 130
431 | f 131 126 123 121
432 | f 132 131 112 111
433 | f 126 131 132 125
434 | f 125 132 122 124
435 | f 127 124 122 116
436 | f 122 132 111 116
437 | f 129 117 113 114
438 | f 121 114 112 131
439 | f 123 129 114 121
440 | f 118 127 116 115
441 | f 198 141 133 163
442 | f 228 184 159 166
443 | f 241 153 134 164
444 | f 190 225 249 208
445 | f 250 204 160 165
446 | f 253 210 161 166
447 | f 211 250 165 162
448 | f 184 198 163 159
449 | f 237 232 196 195
450 | f 254 174 167 236
451 | f 235 173 168 233
452 | f 231 172 169 230
453 | f 233 168 170 219
454 | f 137 135 174 254
455 | f 230 169 173 235
456 | f 236 167 171 218
457 | f 219 170 136 149
458 | f 218 171 172 231
459 | f 268 254 236 260
460 | f 267 235 233 261
461 | f 266 231 230 262
462 | f 261 233 219 263
463 | f 259 137 254 268
464 | f 262 230 235 267
465 | f 260 236 218 264
466 | f 263 219 149 265
467 | f 264 218 231 266
468 | f 238 150 140 197
469 | f 253 199 183 229
470 | f 199 238 197 183
471 | f 163 133 150 238
472 | f 239 151 141 198
473 | f 166 159 199 253
474 | f 252 200 184 228
475 | f 200 239 198 184
476 | f 247 157 151 239
477 | f 222 247 239 200
478 | f 240 152 156 246
479 | f 201 142 152 240
480 | f 164 134 142 201
481 | f 225 185 203 249
482 | f 165 160 185 225
483 | f 160 164 201 185
484 | f 202 143 153 241
485 | f 251 158 143 202
486 | f 226 186 204 250
487 | f 258 227 186 226
488 | f 227 251 202 186
489 | f 203 240 246 221
490 | f 234 223 206 208
491 | f 228 187 207 252
492 | f 166 161 187 228
493 | f 205 188 209 243
494 | f 255 232 188 205
495 | f 229 189 210 253
496 | f 174 177 175 167
497 | f 173 182 179 168
498 | f 242 206 223 248
499 | f 162 165 225 190
500 | f 237 258 226 191
501 | f 244 213 144 154
502 | f 247 214 145 157
503 | f 214 244 154 145
504 | f 212 192 213 244
505 | f 248 223 192 212
506 | f 222 193 214 247
507 | f 257 224 193 222
508 | f 224 248 212 193
509 | f 232 237 191 188
510 | f 215 246 156 146
511 | f 213 215 146 144
512 | f 234 256 221 194
513 | f 216 147 158 251
514 | f 237 195 227 258
515 | f 223 234 194 192
516 | f 245 155 148 217
517 | f 216 217 148 147
518 | f 255 220 196 232
519 | f 220 245 217 196
520 | f 172 176 178 169
521 | f 168 179 181 170
522 | f 135 138 177 174
523 | f 169 178 182 173
524 | f 167 175 180 171
525 | f 170 181 139 136
526 | f 171 180 176 172
527 | f 196 217 216 195
528 | f 159 163 238 199
529 | f 257 222 200 252
530 | f 256 249 203 221
531 | f 186 202 241 204
532 | f 208 249 256 234
533 | f 257 252 207 224
534 | f 185 201 240 203
535 | f 189 205 243 210
536 | f 191 226 250 211
537 | f 211 209 188 191
538 | f 193 212 244 214
539 | f 194 221 246 215
540 | f 195 216 251 227
541 | f 215 213 192 194
542 | f 204 241 164 160
543 | f 207 242 248 224
544 | f 197 268 260 183
545 | f 255 267 261 220
546 | f 189 266 262 205
547 | f 220 261 263 245
548 | f 140 259 268 197
549 | f 205 262 267 255
550 | f 183 260 264 229
551 | f 245 263 265 155
552 | f 229 264 266 189
553 | f 210 243 269 161
554 | f 161 269 270 187
555 | f 187 270 242 207
556 | f 162 271 276 211
557 | f 208 274 272 190
558 | f 190 272 271 162
559 | f 243 278 279 269
560 | f 269 279 280 270
561 | f 270 280 277 242
562 | f 206 273 274 208
563 | f 211 276 275 209
564 | f 242 277 273 206
565 | f 209 275 278 243
566 | f 287 284 285 288
567 | f 288 285 286 290
568 | f 290 286 283 289
569 | f 278 287 288 279
570 | f 279 288 290 280
571 | f 280 290 289 277
572 | f 291 281 283 286
573 | f 292 271 272 291
574 | f 286 285 292 291
575 | f 285 284 282 292
576 | f 287 276 282 284
577 | f 282 276 271 292
578 | f 289 274 273 277
579 | f 281 291 272 274
580 | f 283 281 274 289
581 | f 278 275 276 287
582 |
--------------------------------------------------------------------------------
/hoaxplus/data/data.go:
--------------------------------------------------------------------------------
1 | // Code generated by go-bindata.
2 | // sources:
3 | // ..\..\data\Basehead.obj
4 | // ..\..\data\data\click.png
5 | // DO NOT EDIT!
6 |
7 | package data
8 |
9 | import (
10 | "bytes"
11 | "compress/gzip"
12 | "fmt"
13 | "io"
14 | "strings"
15 | "os"
16 | "time"
17 | "io/ioutil"
18 | "path"
19 | "path/filepath"
20 | )
21 |
22 | func bindataRead(data []byte, name string) ([]byte, error) {
23 | gz, err := gzip.NewReader(bytes.NewBuffer(data))
24 | if err != nil {
25 | return nil, fmt.Errorf("Read %q: %v", name, err)
26 | }
27 |
28 | var buf bytes.Buffer
29 | _, err = io.Copy(&buf, gz)
30 | clErr := gz.Close()
31 |
32 | if err != nil {
33 | return nil, fmt.Errorf("Read %q: %v", name, err)
34 | }
35 | if clErr != nil {
36 | return nil, err
37 | }
38 |
39 | return buf.Bytes(), nil
40 | }
41 |
42 | type asset struct {
43 | bytes []byte
44 | info os.FileInfo
45 | }
46 |
47 | type bindataFileInfo struct {
48 | name string
49 | size int64
50 | mode os.FileMode
51 | modTime time.Time
52 | }
53 |
54 | func (fi bindataFileInfo) Name() string {
55 | return fi.name
56 | }
57 | func (fi bindataFileInfo) Size() int64 {
58 | return fi.size
59 | }
60 | func (fi bindataFileInfo) Mode() os.FileMode {
61 | return fi.mode
62 | }
63 | func (fi bindataFileInfo) ModTime() time.Time {
64 | return fi.modTime
65 | }
66 | func (fi bindataFileInfo) IsDir() bool {
67 | return false
68 | }
69 | func (fi bindataFileInfo) Sys() interface{} {
70 | return nil
71 | }
72 |
73 | var _baseheadObj = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x59\xdb\xae\x5d\xc9\x6d\x7c\xd7\x57\x2c\xc0\x0f\x4e\x1e\xfa\xa8\xc9\xbe\xfb\xd1\x09\x9c\x38\x80\x91\xfc\x41\x20\x79\x8e\x62\x01\x9a\x28\xd1\x65\x26\xce\xd7\xa7\xaa\xd8\x5b\xb2\x4e\x80\x5e\x63\x18\xda\xab\x2f\x6c\x36\x59\x2c\xb2\x79\x7e\x73\xfd\xfe\xc3\xf3\x7f\xfe\xf4\xfc\xe9\xfa\xc5\x9f\xfa\xba\xfe\xee\xf3\xd7\xb7\x57\xfe\xfb\xeb\x5f\x7f\xff\x2f\xd7\x1f\xde\x7f\x78\xfe\xdd\xf5\xdb\xdf\xbf\xf9\xfc\xfc\x97\xe7\x37\x3f\x3d\xbd\xe5\xca\xdf\xbe\xfa\xcd\xf5\xeb\xaf\xbf\xc6\xc7\xf3\xa7\xa7\x8f\x9f\xfe\x03\x23\x7f\x7a\xf3\xd3\xf3\xf5\xf6\xaf\x0f\x61\xff\xf4\xf5\xaf\xff\x7b\xfd\xe5\xcb\x97\xff\xfa\xfc\xbb\xd7\xaf\xb9\xfa\xcb\xd7\x4f\x6f\x3f\x7e\xfe\xef\xaf\xef\x7f\x7a\xfa\xf3\xc7\x9f\x5f\xff\xe1\xeb\x87\x0f\xff\xf6\xe9\xf9\x97\xf7\xcf\xbf\xbe\xfe\x23\x36\xfc\xcf\xd3\x9f\xdf\xfd\xfc\xfa\x8f\xff\xf8\x7a\xe6\xd6\xbb\xbd\xfa\xf9\xcb\x87\x0f\xef\xdf\x5e\xdf\x4e\xc6\xf7\xab\x8f\xd7\x3f\xe3\xe7\xbf\xff\xc3\xd7\xb7\xcf\xaf\x7e\xb9\xf2\xd3\x58\x75\xce\x7c\xa5\xfc\x54\x5b\x77\x9b\x57\x32\xfc\x2a\xb6\x4c\xd3\xbd\x98\x8d\xc5\xe9\x56\x6b\x1d\xe3\xb2\x27\xab\xab\xd7\x81\x59\xfc\x2c\x73\x0d\xd3\xe6\x4a\x41\xfc\x35\xd6\x98\x7d\x69\x3a\xaf\x5a\xbd\x86\xec\xec\x3d\x43\x5e\xb5\xde\xd7\x94\xe8\x5a\x56\x99\x23\x66\xab\x97\xc2\x93\x7b\xae\xb3\x15\x4d\xfb\x18\xe6\x1e\x27\x5b\xa9\x1d\xf2\xda\x2a\xee\xb1\x79\x75\x6f\xb5\x68\xf3\xea\x03\x27\xe7\xa7\x99\x7d\xf6\x1e\x07\x17\xeb\x53\xda\xd4\x92\x7b\x76\x8a\xc6\x48\xb6\x1a\x77\xce\xa3\xf0\x52\xfe\x94\x27\x6e\x65\x3a\xb9\x36\xfc\xa7\xe9\x59\x56\xa3\xda\xfe\x34\x7d\xf9\x68\x94\xe3\xb9\xd7\x19\xb7\x2a\x6b\x74\x6b\x9c\xf6\xd2\x69\x12\x4c\xc3\x72\xa5\xfb\xbe\x56\xf5\x3c\x39\xbd\x30\x1f\x5a\x18\xae\x37\x73\xa8\xd6\xf2\xc8\x8b\x27\xe2\x0a\x7d\x74\xd9\xbb\x5b\xae\x4d\xd3\xbe\x4a\x6d\x26\xd5\xaa\x35\xd3\x74\x9e\xa3\xf5\x19\xd3\x05\xbf\x32\xa7\xbb\x15\x9f\xb2\x6d\xc9\xf5\x61\x95\x52\xb3\x2f\x4d\x1b\x2e\xbe\x1a\x77\x8f\x36\xe7\xa8\xe1\x2e\x6b\xcb\xa5\x9a\xad\x9a\x29\xc7\x9e\x26\x0e\x71\xd7\xf4\xac\x0d\xc3\x9a\x6e\x63\x54\x39\xc4\x69\xe7\x15\x50\xb0\x21\xcd\x71\xef\x8e\x2b\x4a\xb5\xd5\xf8\x0b\xd3\xd0\xd7\xf2\x08\xab\x95\xba\x64\x01\x18\xda\x7a\xeb\x25\x34\xcf\xd9\x0c\x22\xcb\x53\xc6\x7d\xaa\x10\xe7\xe6\x73\xc5\xc5\x1a\xce\xf3\xed\x92\x0c\x13\xca\x25\xd3\xe1\x1d\x9d\xdd\x46\x6e\x34\x65\xc1\x1d\x6c\x65\xd9\x3c\xc3\x49\x66\xda\x0d\x79\x25\x34\x1f\xd0\x37\x5c\x02\x37\xd8\x08\x87\x02\xba\x36\x25\x12\x00\x87\x9e\xfc\x05\x84\xf4\x9a\x03\x0e\xb3\xcd\x5e\x2e\xb9\xc9\x5d\x60\xa9\x0b\x5e\x2e\x8f\x08\x18\xd8\x8c\xf3\x70\x17\x5b\x34\x63\xb6\xd1\xd7\x43\xf2\x68\xf2\x66\x01\xa4\x5a\xbd\xe4\xad\x3c\xc3\xa0\x38\x1f\x90\x93\xe0\x45\x04\x43\xab\xd9\x96\x59\x38\x6b\xe2\x57\xd1\x69\xa5\x4e\x43\x18\xe1\x88\xb2\xac\x46\xe0\xcd\x3e\x57\x1d\xd2\x79\x65\x8b\x28\x1a\xb9\xe6\xda\x77\xe4\xad\xb9\x16\xb7\x4c\xf3\xce\x1f\x65\xc2\xe5\x7b\x6f\x19\x7d\x6a\xaf\x00\x4a\x0d\x10\xdc\x88\xcb\x1d\xf1\xc5\x8b\x5d\x82\x5d\x29\x3d\x4c\x69\xb5\x05\x7c\x07\x80\xac\x7b\x00\xb1\x3b\xc2\x26\x06\x4a\xdc\x77\x00\x0f\x95\x36\x28\xa3\x9a\xb7\x38\xf6\x21\xb8\xe6\x05\x7f\x0b\x54\x13\x38\x63\x4c\x56\x28\xb2\xaf\x8b\x20\x5e\xa6\xeb\x8e\x3e\x8a\x22\x36\x0f\x20\x2a\x5c\xe4\x0d\xf7\xd9\x2e\xb2\x36\x25\xa5\x5a\x2e\x33\xce\x25\xf5\xac\x70\x11\xee\xd3\x23\x60\x41\x10\xf3\xa1\xf3\x5a\xdb\xbc\xbd\xad\x1e\x36\x1d\x73\x6c\xa5\x9b\x77\xdc\x13\xae\x1c\x45\x17\x86\x68\x1f\x50\x3b\x4e\x06\x08\xfb\x90\x25\x3b\xe2\x8c\x77\x83\xc5\x73\x6c\x2d\x0d\xaa\x4a\x99\x32\xad\x84\xf7\x27\xc0\x12\x4a\x0f\xc2\x85\x5b\x3b\xfc\x3c\xe5\xfc\x8a\x75\x31\x09\xa3\xe5\x2e\xa5\x80\x25\x5f\x14\x0c\x8b\x81\x59\xc3\x45\x93\x5e\x95\x2a\x55\x9e\x14\x62\x4b\xb3\xe0\x18\x03\x69\x55\x7a\xb5\xd7\x3e\xb2\xbc\x00\xf5\x40\x28\xdb\xf9\x22\x35\xcc\x22\xa6\x66\xf8\xa8\x58\x1d\xb6\x59\x17\xff\xa3\xcf\x49\x97\xd9\x44\xa5\x88\x8e\xd8\x9a\x01\xd2\x20\xdd\x85\xc3\xaa\xce\x05\xea\x46\xdb\x7b\x27\x8c\xa1\x41\xa0\x09\xb1\x2d\xd4\xd5\x8c\xe0\x8b\x69\x47\x62\x89\xf3\x06\xa6\xe5\xff\x3a\x10\x67\x61\x0e\xa0\xa3\x65\x02\x0b\x88\xf4\x16\xcc\x0e\xd2\x88\x38\xaa\x13\xd8\xf1\x8b\x1c\xdf\x7c\x4a\x32\xe0\x6c\x0f\xd6\x74\x82\x8c\x7b\xeb\xcc\x43\xe4\xb1\x10\x3e\x6d\x63\xa7\x8a\x15\x41\x13\x19\x1e\xe9\x42\xd3\x28\x22\x1e\x40\x62\xd6\x5e\x65\xca\x85\x45\x72\x34\x4e\xad\xdb\x0d\x0c\xd5\xa0\x32\x5c\xcd\xb4\x37\xf7\x02\x16\xde\xd0\x00\xf3\x2a\x7e\x67\x2e\x3d\xb2\x1f\xdc\x8c\x24\x14\xd8\x40\x10\xd2\x87\xa4\x5b\x2b\x43\xa4\x45\x6e\xdc\x27\xc3\xaf\xa0\x13\x9d\x8c\x7c\x19\x89\x10\x29\x71\xf4\x8d\x80\x09\xda\xc9\xe2\xdd\xb5\x1a\xbd\x49\xa3\x6e\xc0\x77\x04\xb0\x22\xc9\x10\x33\xa6\x60\xb5\x05\x50\x06\x73\x20\x1d\x8c\x40\x1b\x90\xf5\x88\x51\xcf\x9b\xb0\x56\x27\xce\x04\x28\xb8\x5a\xc7\x82\xc3\xca\xe6\x24\x38\x73\x74\xde\xd3\x80\xe2\x6e\x72\x0c\x42\x2a\x54\x1e\x15\x59\x23\x08\x90\xb9\x80\xcb\x26\x92\xca\x08\x9a\x45\x56\xcc\x25\x47\xd6\xc0\x45\xba\xa4\x79\xcb\x3b\x75\xc1\x1a\xa6\x20\x84\xf1\x5d\x71\xe4\xc0\x6c\xdf\xa6\xac\xb3\x64\xed\x75\xa0\x3d\x7e\x01\xa8\x33\x87\xfb\x57\x9b\x52\x15\x04\xcf\x04\x29\x3e\x03\x96\x70\x8f\x98\x36\x7a\x56\x8e\x80\xeb\xba\xa6\x17\xd2\x4d\xce\xdb\x94\xe0\x87\xa8\x10\x40\xeb\xad\xc9\x8b\x28\x5c\xca\x66\x61\xe4\xa8\x42\xd9\xb0\x24\x72\x4f\x24\x6c\x50\x6e\xdc\x6a\x61\x9d\x87\x1f\x58\x7c\x08\xb4\xdd\x4b\x48\x9e\x96\xe7\xd4\x5e\x84\x3d\xd2\x8d\xf6\x42\x1b\xf3\x2d\x3a\x5b\x10\xfc\x2a\xe6\xe1\x6c\x66\xcc\xcd\x87\x9d\x68\xd5\x55\xfb\x40\x94\xb5\x40\x66\x2f\x63\xe3\xa3\x8e\x3a\x82\x97\x10\x56\x41\x6a\xa8\x93\xc6\x03\xf3\x13\xa9\x59\xb7\x9b\x25\x88\x13\x5e\xef\xdb\x22\x40\x6b\xeb\x41\x2e\xe0\x69\x15\x5e\xa8\x3b\xd6\x46\x1e\x59\x5a\x8e\x5f\xb8\x79\x26\x16\xbc\xe6\x56\x1e\x79\x07\x1f\x59\x0c\x00\x6b\x28\xd4\xa0\xd5\xb0\xb6\xf9\x01\xb8\xd5\xde\x89\xdc\x11\x9e\x00\x35\xc3\xb0\xa1\x15\xac\xde\x08\x3d\x1c\x5b\x57\x54\x6f\x40\xea\x8e\x44\xd0\xcd\x88\x30\x59\xe0\xb2\xa9\x20\x87\x59\xcb\xe3\xc6\xc8\xa9\x0a\x54\x77\x04\x39\xb1\xb7\x80\x5b\xcf\x7b\xb2\x31\xf9\xb2\x16\xf0\x59\x74\x5f\x9f\xa0\xf3\xb1\xb9\x05\x75\xa8\x58\x12\xc5\x62\xf8\x01\x09\xc0\x9b\x6d\x50\x43\x6d\x0b\xca\x43\xb9\xa3\x22\xae\xd7\x87\x0f\x57\xdb\xa5\x22\x32\x0c\x54\x95\x5b\xd7\xc3\x0b\x8e\xb8\x0a\x95\xc7\x44\x76\x35\x85\x57\x1e\xb5\x7e\xa7\x34\x31\x2d\x6c\x11\xe9\x98\xe6\x5b\x8f\x58\x9a\x8c\x34\xf1\x61\xee\x51\x1b\xe0\xa8\xd9\xeb\xae\x51\xe1\x57\x5d\x04\xf9\xc7\x5d\x38\x81\xff\xda\x26\x44\x54\x85\x39\xee\x39\x7a\xee\x2b\xf8\x01\xff\xd6\x07\xe6\x59\x68\x0a\xa0\x96\x95\xcc\x51\xf1\x94\xf1\xa8\x0e\xa6\xa9\xec\x58\xb8\x77\xe4\xc3\x3c\x16\x8a\xc7\x5d\x0f\x41\xa0\xc2\xa5\x37\x94\xfa\xb2\x47\x6f\x73\xdf\x18\x35\xc9\x68\x51\xd5\x22\xe6\x56\x89\x7c\x88\x3c\x63\x3b\x13\x93\xa8\xa3\x90\x03\xc8\x64\x38\x10\xe6\xda\x8c\x39\x11\x25\xb6\x19\x13\x44\x13\xf0\x01\x5b\x6c\x56\xb3\xa5\x62\x45\x01\x83\x54\x1c\xbb\xeb\x28\x0f\xd2\xeb\x63\xcd\x19\x86\x40\x9e\x94\x49\x80\xa3\xb5\x81\x8b\x2b\xcc\x20\x6b\x22\xdd\x02\x86\x19\x19\x64\xc7\x53\xe9\xaa\x12\x51\x82\xb2\x16\x8a\xd2\x1b\x5a\x3c\x72\x35\x2a\x17\x57\x95\x30\x10\x96\x51\xe2\xa0\x6e\x47\x68\xed\x1a\x13\x16\x88\x17\x05\xd8\xab\x89\x36\x91\x1b\xa0\x67\x4c\x63\x54\xe9\x1a\x35\xa4\x45\x04\x20\x1a\xdb\x9e\x65\x31\x16\x65\x16\x0a\x39\x14\x17\x3c\x0e\x85\x5e\xd9\xf5\x16\x52\x51\x58\x0a\xa4\x8a\xea\x46\xa1\x00\x3b\x46\x5e\x84\x4d\x00\x0a\x42\x3c\x23\xf1\xc5\x32\x30\xd6\x2e\x7d\xb1\x17\x0e\xe1\x0e\x60\xcc\xb2\x98\x19\x59\x78\x0b\x26\x20\xd6\xae\xee\x5a\x60\x84\x65\x4f\xdf\xc1\x3a\x60\x24\x4d\xa3\xfc\x46\x15\x2c\x29\xb9\x5b\x04\xba\x1b\x68\x67\x8a\x2c\x00\x5e\x2d\x03\x5b\x97\x6f\x3a\x8f\x19\xb9\xa3\xb3\x8e\x09\x5a\xc4\xab\xc1\xfb\x7e\x4b\x80\x4a\x95\xcc\x51\x09\x14\x8b\xe9\x09\x5b\x6f\x63\x02\x57\x93\x6c\xcf\x04\xd4\x2d\x78\x11\x85\x63\x58\x0b\x8e\x60\x1e\x61\x8a\x5c\x48\xf6\xd2\xda\x10\x99\x6d\xdb\x83\x45\x9c\x2e\xd5\x55\x4e\xd2\x6c\xad\xec\x37\x0e\xde\x84\x4b\x92\x41\x12\xd5\x76\x54\x20\x90\xe2\x4e\x30\x61\x8f\x17\x27\xc0\x89\xdb\x04\x3a\xdb\xca\x71\x70\x05\xb3\xc5\x7b\xb5\x20\x39\x44\xad\x02\x36\x06\x63\xc7\x34\xd2\x87\xf7\xc7\x79\x23\xf0\xe3\xdf\x7c\x3c\x40\xd8\x2d\x1e\x6c\xfe\x08\x48\xd4\x84\x23\x36\x3b\x92\xc7\x0a\x8b\x54\xc4\x95\x64\x1b\xc8\xd0\xea\xb6\x88\xf1\x75\x45\x5c\x50\xf8\xd6\xbb\xec\xc7\x55\x01\x81\x85\x39\xc1\x50\x16\xb4\x8a\xbc\x5f\x37\xbd\xf9\x42\x21\xa4\x32\x13\xc8\x76\xd9\x06\xb0\x2f\xbe\x4f\x6e\x28\x44\xa2\x08\x6c\x28\xbb\xe2\x7d\x03\xc3\xef\x2c\x94\xf5\x5f\x14\x54\xb0\x67\x8b\xc0\x07\x74\x5f\x4e\xf3\xa9\xdc\xc9\x70\x1d\xe7\xee\x6a\xe1\x31\x8b\x98\xea\x30\xb3\x78\x01\x8f\xf4\xbe\x89\xe6\xfb\x34\x88\x66\x27\x06\xa0\xb8\xec\x06\xc0\xf7\xe9\xcc\x40\x2c\xfb\x61\x96\x77\xea\xfd\x3e\x0d\xbf\xcd\x20\xc8\x35\xf9\x50\xfc\x61\xba\xa8\x90\x99\x51\xc8\x14\x9a\xe5\x87\x69\x22\xa6\xee\x27\x0b\xca\xd8\x66\x3f\x68\xce\xaa\x1f\x64\x18\xac\x81\x8c\x30\xd6\x8f\xb3\xd0\x85\x65\x38\x5f\x3b\x63\xad\xfc\x42\x32\x89\x20\x2f\x05\x4b\xf3\xf5\xc3\x9d\x71\x93\x6e\x3d\x2c\x07\xa2\xee\xad\xfc\x38\x8b\xbc\x37\x03\x24\x0b\x68\xf7\xf1\xe3\x6c\x43\xa6\x14\x8c\x2b\xb2\xf1\x28\x2f\x8e\x45\x3e\x28\x2a\xbe\x50\xd2\xcf\x17\xb6\xe4\x53\x7b\x75\x85\x0f\x10\x3c\x36\xef\x7e\x37\x65\x47\x01\x52\x76\xe3\xa0\xd7\x66\x2f\x9c\x3c\x1b\x8a\xc8\x28\x17\x00\xf1\xe2\x3f\x5a\xa3\xc3\x8d\xd1\x60\x60\x3b\x67\xd3\xee\xf7\x59\xbe\x7a\x23\x07\x17\x14\xee\x2f\x24\x23\x8f\x02\x17\x8a\x04\x14\xf3\x2f\xac\x01\xd2\x59\x2e\x0f\xa2\x20\x7c\xd0\xfd\x8f\x17\x1e\xc2\x3f\xc0\x5f\x5e\x1a\xcb\x11\x50\x4a\xb3\xcb\xc1\x58\xfd\xc5\xa4\x97\x12\x6f\x5d\x00\xde\xfe\x9f\x64\xd2\xc0\x68\x2a\x40\xf1\xe6\xe3\x75\xd3\x4d\xdf\x2a\x9d\x1b\x57\xe9\xa6\x73\x95\xce\xad\xab\x74\xd3\xbb\x4a\xe7\xe6\x55\x3a\x77\xaf\xd2\x4d\xfb\x2a\xdd\xf4\xaf\xd2\x4d\x03\x2b\xdd\x74\xb0\xd2\x4d\x0b\x2b\xdd\xf4\xb0\xd2\x4d\x13\x2b\xdd\x74\xb1\xd2\x4d\x1b\x2b\xdd\xf4\xb1\xd2\x4d\x23\x2b\xdd\x74\xb2\xd2\x4d\x2b\x2b\xdd\xf4\xb2\xd2\x4d\x33\x2b\xdd\x74\xb3\xd2\x4d\x3b\x2b\xdd\xf4\xb3\xd2\xb9\xa1\x95\x8e\x1d\xad\x74\x6e\x69\xa5\x73\x4f\x2b\x9d\x9b\x5a\xe9\xa6\xab\x95\x8e\x6d\xad\x74\xee\x6b\xa5\x73\x63\x2b\x9d\x3b\x5b\xe9\xd8\xda\x4a\xe7\xde\x56\x3a\x37\xb7\xd2\x4d\x77\x2b\x9d\xdb\x5b\xe9\xa6\xbf\x95\xce\x0d\xae\x74\xec\x70\xa5\x73\x8b\x2b\x1d\x7b\x5c\xe9\xdc\xe4\x4a\x37\x5d\xae\x74\x6e\x73\xa5\x73\x9f\x2b\x1d\x1b\x5d\xe9\xa6\xd3\x95\x6e\x5a\x5d\xe9\xdc\xeb\x4a\xe7\x66\x57\x3a\x77\xbb\xd2\xb9\xdd\x95\x8e\xfd\xae\x74\x6e\x78\xa5\x73\xc7\x2b\xdd\xb4\xbc\xd2\x4d\xcf\x2b\xdd\x34\xbd\xd2\xb1\xeb\x95\xce\x6d\xaf\x74\xee\x7b\xa5\x73\xe3\x2b\x1d\x3b\x5f\xe9\xdc\xfa\x4a\xe7\xde\x57\x3a\x37\xbf\xd2\x4d\xf7\x2b\xdd\xb4\xbf\xd2\x4d\xff\x2b\x9d\x1b\x60\xe9\xa6\x03\x96\x8e\x2d\xb0\x74\xd3\x03\x4b\x37\x4d\xb0\x74\xee\x82\xa5\x9b\x36\x58\x3a\xf7\xc1\xd2\xb1\x11\x96\xce\x9d\xb0\x74\x6e\x85\xa5\x9b\x5e\x58\x3a\x37\xc3\xd2\x4d\x37\x2c\x1d\xdb\x61\xe9\xdc\x0f\x4b\xe7\x86\x58\x3a\x76\xc4\xd2\xb9\x25\x96\xce\x3d\xb1\x74\x6e\x8a\xa5\x9b\xae\x58\xba\x69\x8b\xa5\x9b\xbe\x58\x3a\x36\xc6\xd2\xb9\x33\x96\xee\x5a\x63\xdf\x5f\x15\xb0\x56\x8b\x5c\xd9\xf2\xdf\x60\xf1\xd4\x3a\x4b\x37\xbd\xb3\x74\xd3\x3c\x4b\x37\xdd\xb3\x74\xdb\x3e\xfb\x9b\xe7\x36\x9e\x4c\x3d\xc8\xd9\x51\x14\xd8\xa3\x04\x3a\xb4\xd7\xd2\x4d\x7f\x2d\xdd\x34\xd8\xd2\x4d\x87\x2d\x9d\x5b\x6c\xe9\xdc\x63\x4b\xe7\x26\x5b\x3a\x77\xd9\xd2\xb1\xcd\x96\x6e\xfa\x6c\xe9\xdc\x68\x4b\xe7\x4e\x5b\xba\x69\xb5\xa5\x9b\x5e\x5b\x3a\x37\xdb\xd2\xb9\xdb\x96\xce\xed\xb6\x74\xee\xb7\xa5\x9b\x86\x5b\xba\xe9\xb8\xa5\x73\xcb\x2d\xdd\xf4\xdc\xd2\x4d\xd3\x2d\x9d\xbb\x6e\xe9\xa6\xed\x96\xce\x7d\xb7\x74\x6c\xbc\x7d\xfd\xfc\xfc\xf3\x97\x0f\xd7\x9f\xde\x7c\x79\xfe\xf4\xfe\xcd\x87\x57\x9f\xaf\x8f\xef\xde\xbd\x7a\x77\xc1\x11\xed\xc2\x0d\x2e\xbe\x6a\xde\x5d\x80\x0a\x92\xce\x05\x4f\xbf\xbb\x60\x65\x10\x36\x94\xb4\x56\xf0\x09\xe6\x84\x39\x71\xe5\x3e\xf0\x05\xbf\x8d\xcb\xaf\xca\x85\x20\xe4\x79\x95\x0b\x4f\x93\x77\x57\x2b\x57\xc5\xcc\xe2\x6f\xd8\xd1\x20\x1d\xf5\x0e\x04\xaf\x0b\x8a\x83\x67\x71\x55\xec\xe8\x17\xea\x44\xa4\x22\x6e\x47\x08\xb2\x21\x82\xdc\xd1\xf8\x55\xae\x81\x52\x13\x24\xce\x85\x98\x60\x07\x10\x03\x14\xc2\x84\xc9\xb2\x9c\x6a\x69\xad\x73\x33\x02\xdf\xa4\xfb\xbc\xc0\x21\x30\xdf\xc2\x07\x77\xb1\x34\x03\x8e\x8d\xba\x60\x66\xf0\x92\x18\xa1\x20\xa6\x56\xa4\x7e\x2a\xd1\xf5\x0d\x31\x48\xa8\x38\x6e\x0c\x7d\x63\x5b\x96\x26\x23\xd6\x53\x83\x4a\xa9\x83\x07\x3b\xd3\x68\x9e\x52\xa6\xc4\x86\x22\x21\xbc\x8b\xeb\x1b\xe7\xe7\xa6\x63\xa7\xbe\xeb\x45\xaa\xa5\x4e\xdd\x34\xd0\x74\x0a\x94\xea\xbc\x1a\x30\x89\x40\xb4\x4a\x2b\xe4\xb0\x29\x98\x15\xa5\xb8\xdc\x52\xf5\x13\x0b\x26\xe7\x1a\x57\x1b\xeb\xf5\x42\xe5\x90\x8a\xb9\x0d\x6b\xac\x71\xf1\xe4\x66\x7e\x51\x4c\xa5\x4b\xe1\x88\x4a\xad\x40\xa6\xfc\x09\x1f\x6b\xdd\xe2\x56\x63\x4a\x6f\xbc\x03\xea\x34\x2c\xc0\xd0\xa4\x01\x51\xe6\x83\xba\x8d\x2f\x2c\x39\x16\x45\x38\x86\x98\x24\x4c\xb2\x3a\x47\xf0\x93\x08\xe1\xe7\x20\x34\xf0\xb0\x70\x8a\x1a\xfc\x06\xfe\x84\x02\xfe\xc0\x5a\xda\x19\x89\x1f\xa8\x02\x9e\xb0\x93\xaa\x23\x54\x30\x64\x94\xd4\x68\xa6\x3e\x09\x2c\xbc\x19\x3d\x8c\x96\x39\x02\x9c\x77\xb9\x74\xf1\x27\xd6\x2f\x6e\xc5\x51\x78\xd0\x40\xc5\xc9\x43\xf0\x30\x80\x3d\xf0\x54\xed\x2d\x50\x8c\x8b\xc3\xd4\xae\x9b\xc8\x04\xc0\x1f\x77\x8d\x0b\xe1\x8b\x2b\x17\x19\x79\x70\x00\x04\x27\x50\xc2\xde\x30\x1c\x2e\x58\xe4\xa0\x4e\x7c\x02\x16\x14\x61\xc2\x27\x52\x80\x73\x21\xf2\x35\x62\x18\xde\xac\xd4\xb2\x32\x32\x70\xdd\xb1\x51\x5e\xa8\x33\x54\xe7\x42\x1a\x8f\xf7\xab\x57\x6b\x61\x71\x98\x1a\xdf\x38\x86\xe6\xa0\x71\xf1\x9b\x6b\xa6\xbe\xf9\x2f\x96\x5e\x32\x29\xce\xc0\x00\xe2\x4f\x77\x82\x77\xb0\x1d\x3b\x84\x7c\xd4\x11\x18\x40\xd9\xd1\xb9\xaf\x73\x94\x8b\x97\x42\xad\xf2\x4a\xd0\x63\x50\x75\x9d\xd7\xe5\xc8\x49\x75\x5b\x93\x3e\x1c\x93\xd7\x61\x39\xc4\x08\x4c\xb9\x34\x3b\xe9\x13\xf2\x2f\xf2\x78\x5c\x48\x5e\x60\xf4\xf2\x20\xaa\xc6\xf5\x43\x04\x31\x2e\xc6\x41\x25\x4c\x5a\x6c\xc6\x2e\x0d\xb4\x15\xe6\xa5\x2e\x70\x8a\x00\xe3\xfc\x89\x0d\x53\x01\x53\x19\xe3\xac\xe2\xc3\xd3\x8c\x71\x2f\x30\xb1\xc2\xbc\x29\xc6\x19\xbe\x9a\x25\x42\x61\x7a\x2c\xa7\x54\x86\x38\x5f\xa3\x12\xe3\x11\xe2\x08\x0d\x57\xa0\x46\x8c\x03\x34\x3c\x12\xe7\x81\x31\xda\x56\xc7\x18\x14\x88\x9c\x6d\xbf\x25\xb8\x77\x59\x7a\xd2\x00\xf0\xc4\xe2\xf1\x04\x59\x27\x4e\x2b\xe7\x00\x2b\x98\x08\x2b\x34\x47\xbb\x77\x22\x6b\x71\x8e\xc0\x6e\x0c\x0b\x81\x19\xf5\x2b\xc0\x03\x78\xc9\x72\xb0\x3f\x60\x0e\x34\xf7\x19\xb4\x88\x01\xb8\x45\x11\x4a\x67\x75\xb9\x9a\x52\x0a\x3d\x41\x24\x77\x49\x19\xb4\x36\x9c\xa0\x80\xc0\x04\xa6\xcb\xc6\x0f\x03\xe3\xa2\x6a\xfc\x2d\x4d\x80\x91\x29\x19\x8b\x04\x11\xac\x33\xc3\xf4\xdd\x37\x6d\x8d\xd0\x8d\x9e\x11\x4b\xf5\x70\xc6\x1c\x62\x25\xac\x91\x3b\x82\x7f\xc0\x69\x2e\x63\x61\xf5\x1a\x9b\x17\x8b\x18\x8f\xf1\x11\xac\x65\xe1\x7b\x3e\xdc\xc4\x69\x79\x47\x0f\xdb\x55\x22\x4e\x81\x01\xee\xbe\x98\x8d\x26\xbf\x0a\x03\xd0\xe8\xe6\x4c\xe9\xf8\x80\xfe\x6c\xc0\x88\xd7\x2b\xed\x63\x74\xb9\x88\x1c\x26\x2f\x4c\x01\xfc\x7f\x8d\xcc\xc3\x95\xc6\x21\x1e\xdd\x24\x97\x05\x8e\x6d\xf4\x6c\xd9\x84\x53\xc4\xab\xe5\x90\x3e\x38\xc8\x13\x26\xa5\x9a\x50\x57\xc2\x1f\xe4\x3d\xa5\x8e\x1e\x21\x4d\x18\x13\x3e\xc2\x15\x26\x79\x8c\x71\xac\x09\x67\x94\x84\x2f\x5a\x59\x24\xa0\xaf\xc2\x43\x99\x61\xb4\x46\x5f\x50\x05\x38\x36\x65\xd0\xd8\xbf\xf6\x4e\xe1\x55\x5f\x79\xaf\x95\xf2\x52\x7a\xc4\xce\x12\x59\xce\xb6\x54\xca\x89\x80\xf0\x18\x95\x49\x34\xc2\x79\x8e\x70\x26\x4e\xa7\x66\xfa\xf2\x6f\x1a\x52\x6a\x8d\x11\xdd\x52\xbf\x64\x5a\xfb\x36\xb2\xe2\x74\xdd\x3c\x76\xd9\xb6\x93\xce\xd4\x48\xd9\xeb\xea\x43\x1f\x9b\x21\x5d\x2e\xd3\xe9\x6b\x46\x06\x62\x25\x21\x1c\xb3\xb8\x55\x8b\x8d\x14\x21\x96\x72\x65\xa8\x12\x25\x85\xe2\xce\x00\x5f\x14\x57\x17\xdb\x66\x2e\xdc\xb2\x62\xe3\xcb\xd5\x98\xc9\x7b\xa4\x5a\xb2\x02\xbf\xec\x21\x87\xc4\xd1\x34\x7f\x99\xa8\x45\xe7\x50\x83\x4e\xee\x12\xc0\x10\x46\xce\x9b\x32\x43\xaf\x90\x83\x35\x83\x92\x39\x23\x39\xa4\x19\x16\x05\xcc\x31\xca\xa4\x6a\xb8\xb2\xfa\x60\xaa\x91\x2f\xbc\xc4\xbc\x31\x85\x04\xb4\xf8\x68\xd7\xce\x4a\x99\x5a\x93\xb5\x83\xb2\x5c\xec\xec\xa4\x24\xfe\xe9\x89\x29\x5c\x10\x75\xfa\x7d\xe4\x20\xab\x2a\x0d\x69\xc3\x11\xe7\xb9\xec\xec\xd4\x03\x5a\x72\xb7\xab\x28\x70\xe9\xda\xa4\x85\xf7\x58\xd3\xa5\x25\xcf\xf4\x1e\x45\x96\xc5\x3c\x4e\xf0\xb0\x3c\x2d\xce\xfb\x53\x96\xd8\x07\x2b\x63\x07\x65\xa9\x7c\xe3\x1f\x81\x74\x0e\xa9\x52\xbe\xc0\xde\xd0\x92\xbe\x08\xcb\x23\xc3\x68\x9e\xe7\x85\xe5\xd9\xae\xa2\xe5\x59\x6f\xac\xb1\xbd\x83\x02\xf5\x62\x43\xd3\x95\x6d\xf9\xa5\x75\xa4\x0f\x31\x95\xbc\x42\x3b\xd2\xb7\x22\x74\x27\xd5\x30\xfe\x88\x08\xe5\x1d\x78\x36\x90\xc2\xdd\x2d\x6e\x01\x9d\xf9\x07\x35\xf8\xd6\x15\x29\xfc\xd2\xce\x25\x64\x09\x51\x23\x12\x6a\xa3\x0d\x64\x55\x20\x9c\xa3\x5c\xe7\xca\xc1\xae\x92\xca\x95\x00\x5d\xe5\x2a\x7b\x3e\x2a\x5c\x78\x82\x8a\x53\xb6\xa8\x84\x4a\x16\x48\xa2\x37\xa2\x92\xcf\x71\x3c\x8f\x88\x4e\xad\x69\x81\x4a\x8e\x46\xc4\x09\xa3\x35\xe4\x89\xe5\xd8\x93\x89\x62\x86\xbb\x24\x47\xd5\xd5\xd4\xa8\x8b\x69\x9d\x91\x0b\xea\x27\xca\x5d\xa5\x9e\x37\xa6\xab\x11\xa3\xe2\x0d\x7e\x71\xa7\xe4\xcd\xd0\xb9\xe8\x26\xce\x14\xa0\x18\xc4\x23\x0c\xbf\x28\xb5\x3f\x62\x47\x11\x87\x9d\x99\xbb\xfd\x61\x55\xc6\x0d\x47\xb7\x0d\x79\x2f\x9c\x07\xca\xf4\x1a\x76\x6e\x11\x29\x1a\xd5\x2d\x18\xeb\xa8\x35\x18\x75\xe1\x0b\xc5\x0d\x2b\x6d\xd6\xe9\xc2\x8f\xe2\x86\xf5\x20\x0b\x84\xc0\x98\x6c\xd7\x43\xa7\x1a\x3e\x75\x59\x4d\xb6\x5c\xf9\x11\x95\xba\x2d\xa3\x52\xb7\xa8\xc4\x58\x89\x92\xa4\x3d\x7c\xea\x64\x1a\x15\x46\xc2\x18\xbe\x3c\xe6\x39\xaa\x11\x46\xb6\x6b\xa7\xd7\xd8\x35\x75\x72\x8c\xfa\x46\x02\x5b\x1e\xb1\x3b\xb0\x4a\x2b\xd4\x18\xf5\x58\x53\x63\xa7\xe4\x05\x03\xb8\xb4\x84\x76\xb4\x88\xce\x6a\xb2\xba\x2a\xe1\xc0\x0f\x4f\x65\xe6\xe0\x68\x9c\x4e\x5f\x34\x79\x06\x3b\x35\x42\x66\x14\x3a\x19\xd3\xb6\xef\x0e\x26\xda\xbe\x0d\x7f\x15\xed\xc4\x0e\xea\xad\x5b\x34\x65\x55\x93\x4e\x63\xcb\x71\x8b\x9a\xca\xf6\x2d\x28\x23\x8b\xd9\xa0\xad\xe4\x64\xed\xd4\xba\x78\xce\x90\xc3\x50\xb5\xd8\x20\x27\x06\x7a\x67\xf8\x8a\x15\xff\x88\x2c\xc3\x7c\x31\xb7\x5f\xc5\xc6\xe2\xb0\xb9\xfd\x1a\x91\xbb\x7d\xce\xf7\xc6\x10\xf3\x93\xc3\x28\xa3\xe8\x6d\xa5\x11\xdb\xf3\x3c\x4f\xa8\x5b\xa1\xb3\x6c\x20\xee\x8d\x1c\x50\x36\x2f\xac\x6f\xbe\x88\x08\x0f\xac\xca\x7e\xca\x03\x65\x23\x3c\xa2\xc4\x95\x37\x5c\x35\x06\xff\x7a\xa9\x35\x5c\xab\x1a\x59\x72\xc4\x14\xf2\xad\x76\x35\x45\xa4\xa2\x45\xa5\x8b\xb0\x9c\xe9\x45\x65\x12\x69\x68\xc2\xa0\xb2\x8d\xf2\xa9\x72\x0a\xcb\x08\xbe\x79\x84\xcc\xc0\x8e\x6f\x84\x46\xb6\xaa\xf2\xb0\x62\x70\x67\xbd\x16\x1e\x62\xac\xfa\x78\xa0\xc5\x02\x87\x1b\x09\x8c\x73\xf2\x5c\x57\x56\xd3\xc8\x88\x68\x11\x66\x43\xf2\x08\xf6\x17\xbf\x7c\x8b\x4a\xb2\x3f\xd9\x5d\x15\x8c\x6e\x41\xf6\x27\x97\xef\x38\xcd\x31\x4f\xcb\x2a\x2e\xc8\xcb\x64\x7f\xca\xda\xfc\xcc\x7b\x73\x07\x65\xa9\x86\x14\x53\x93\xfd\xc9\x5c\x62\x6c\x61\x87\x32\x7a\xdb\x85\x3c\x19\x40\xf3\xe4\x8f\x19\xd9\x2a\x87\xfd\x88\x91\x78\xc0\xea\x64\xac\x13\x22\xc4\x09\x64\x19\xe6\x49\x31\xc1\xd8\x0c\xe0\xcc\x81\xa3\x3f\xec\x4c\x0f\x32\x73\x12\xa1\x2b\x3f\x6a\x80\x11\xeb\x22\x9b\xeb\x9c\xc1\x75\xd4\x42\xa7\xeb\x1c\x3e\xff\xb8\x56\x36\xe4\x39\xfa\x92\x2d\x25\x19\x67\x30\x03\x53\x7a\xf0\xa1\xed\x93\x07\x11\xb1\x1e\x1c\xc5\x1d\x43\xbc\xa9\x5d\x2b\xe6\x79\x5e\xf0\x21\x6f\xc1\x9c\x43\x1c\x05\x03\x90\x19\xf5\x05\x59\xc1\x63\xd4\x99\x5f\xb4\x65\xd8\x87\xfb\xb5\x53\x7a\x6b\x64\xc5\x97\xd6\x6a\x17\xf5\xd5\x17\xcf\x94\x77\x88\xc3\x69\x5b\x8e\xf4\x59\x0f\x8b\x39\x67\xb5\xab\xc7\xe9\xeb\xfb\x48\xdb\x1a\x72\xc4\x1f\x3a\xf3\xa6\x1c\x89\xcc\xc8\x5f\xba\xbb\x7d\x5b\xb3\xb6\xe5\xcb\xe3\x74\x9e\xbc\xf6\x59\x23\x76\x95\x18\xe5\xba\xef\xf7\x92\x7d\x28\x7d\xbc\xfa\xbf\x00\x00\x00\xff\xff\x59\x87\xfb\x46\x1b\x36\x00\x00")
74 |
75 | func baseheadObjBytes() ([]byte, error) {
76 | return bindataRead(
77 | _baseheadObj,
78 | "Basehead.obj",
79 | )
80 | }
81 |
82 | func baseheadObj() (*asset, error) {
83 | bytes, err := baseheadObjBytes()
84 | if err != nil {
85 | return nil, err
86 | }
87 |
88 | info := bindataFileInfo{name: "Basehead.obj", size: 13851, mode: os.FileMode(438), modTime: time.Unix(1552225649, 0)}
89 | a := &asset{bytes: bytes, info: info}
90 | return a, nil
91 | }
92 |
93 | var _dataClickPng = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xea\x0c\xf0\x73\xe7\xe5\x92\xe2\x62\x60\x60\xe0\xf5\xf4\x70\x09\x62\x60\x60\x2a\x00\xb2\x3f\xb0\x00\x09\x86\x84\xe5\xaf\xfb\x81\x02\x7c\x9e\x2e\x8e\x21\x15\x8c\x6f\xef\x3a\x7a\x1d\x0e\x10\x68\x78\xd8\xf0\x8e\xeb\x86\xf2\x52\x03\xf7\x8f\x66\x72\xee\xe5\xfc\x2f\xa6\x72\x95\x68\xba\x04\x4a\x58\x07\xc9\xf1\x07\xa9\x5c\x7a\x1f\xdd\x96\x29\x5b\xc7\x22\x14\x7c\xf9\xa5\x18\x03\x04\x74\x24\xd5\x57\xd6\xcc\xdb\xc5\xe6\xfe\x78\xfb\xe1\xae\xb7\x66\x29\x9a\xcf\x4e\x3f\x5e\xbe\x32\xbb\xa0\xe4\xe7\xdb\x3d\x45\xd6\x0f\x5b\x84\xfd\x2c\x20\x84\x9c\xf2\x22\xd1\xf3\x82\xed\xf3\xa5\x2c\xb7\xa8\xc5\xfc\xfe\x66\xf9\xe5\xde\xbe\x3d\xeb\x6e\xe7\x71\xcf\x9b\x96\x3a\xb3\x2b\xf9\x9f\x53\x4a\xaf\x8c\x14\xf7\x75\x49\xab\xfb\x79\xbb\xbd\x2c\xe0\xfa\x76\x4c\xb7\xb1\x3f\x2b\xb5\xfb\xda\x2d\xb7\x43\x4f\xcb\xbe\x2e\xa9\xf9\x3b\x7f\xe5\xf5\xd6\xd7\x57\x6e\x38\xec\x78\x78\xf4\xb7\x37\x97\xfa\x9c\x82\x43\x9c\x20\xe2\xae\xff\x8e\xaa\x4d\x92\x2f\x0b\x52\x97\xb7\x77\xdc\xe8\x6f\xaf\xee\x09\x89\x9f\x9a\x7e\x2f\xf0\x8d\xbe\x78\x7f\xc7\xce\xcf\x7e\x95\x39\xff\x7e\xfe\x14\xfc\xd8\xfe\xf0\xd5\x85\x49\xe7\xc2\x0f\xbd\xfd\x74\xec\x40\xc0\x8e\xe5\xaa\x67\x9b\xbf\xcb\x9c\xe2\xf6\xdf\x5b\x7e\x6a\xe1\x27\x3f\x88\x41\x5f\x39\xa7\x83\xed\x7e\x55\xe1\x76\xea\xa2\x8f\xb1\xc0\xba\x67\x72\xfb\xe6\x4e\x70\xde\x79\xf2\xc6\x85\x5f\xde\x7a\x48\xfe\x69\xf1\xfe\xba\xe4\xcf\xf9\xc3\x4f\x1b\x55\xc0\x6e\xb8\xc3\x00\x11\x2e\xda\xca\x1b\x63\xf9\x65\xfb\x6b\x73\x4b\x84\xe3\x80\xb2\x3f\x26\xdb\x6e\xfb\x77\x73\x62\x54\xd2\x9f\x53\x8a\xfc\x1c\x08\x99\xf2\xe7\x0f\x19\x50\x40\xc2\xe7\x4f\xde\xea\x91\xff\x9f\x2e\x03\x2b\xca\x9d\x0f\x54\xe3\x9e\xfd\x36\xf7\xcf\xee\x6b\x1f\x6b\xe4\xc0\x56\x80\x42\xe5\x7f\xfe\xf5\xa8\xee\x8e\xc3\x47\x36\xfc\x9a\x73\xa6\x5a\x11\x64\x50\x3b\xc8\x44\x99\x9f\x12\x95\x60\x57\x08\x80\x1c\x58\xfc\xb4\x01\x62\x0d\xc8\x28\xbb\x92\x66\x04\xe7\xdf\xdb\x20\x0b\x88\x27\x9c\x2d\x10\xf6\xff\x48\xb7\x63\x98\x2a\xe7\x94\xb5\x26\x7b\x52\x32\x88\xef\xe9\xea\xe7\xb2\xce\x29\xa1\x09\x10\x00\x00\xff\xff\x3a\xf3\x77\xa7\x47\x02\x00\x00")
94 |
95 | func dataClickPngBytes() ([]byte, error) {
96 | return bindataRead(
97 | _dataClickPng,
98 | "data/click.png",
99 | )
100 | }
101 |
102 | func dataClickPng() (*asset, error) {
103 | bytes, err := dataClickPngBytes()
104 | if err != nil {
105 | return nil, err
106 | }
107 |
108 | info := bindataFileInfo{name: "data/click.png", size: 583, mode: os.FileMode(438), modTime: time.Unix(1552243820, 0)}
109 | a := &asset{bytes: bytes, info: info}
110 | return a, nil
111 | }
112 |
113 | // Asset loads and returns the asset for the given name.
114 | // It returns an error if the asset could not be found or
115 | // could not be loaded.
116 | func Asset(name string) ([]byte, error) {
117 | cannonicalName := strings.Replace(name, "\\", "/", -1)
118 | if f, ok := _bindata[cannonicalName]; ok {
119 | a, err := f()
120 | if err != nil {
121 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
122 | }
123 | return a.bytes, nil
124 | }
125 | return nil, fmt.Errorf("Asset %s not found", name)
126 | }
127 |
128 | // MustAsset is like Asset but panics when Asset would return an error.
129 | // It simplifies safe initialization of global variables.
130 | func MustAsset(name string) []byte {
131 | a, err := Asset(name)
132 | if (err != nil) {
133 | panic("asset: Asset(" + name + "): " + err.Error())
134 | }
135 |
136 | return a
137 | }
138 |
139 | // AssetInfo loads and returns the asset info for the given name.
140 | // It returns an error if the asset could not be found or
141 | // could not be loaded.
142 | func AssetInfo(name string) (os.FileInfo, error) {
143 | cannonicalName := strings.Replace(name, "\\", "/", -1)
144 | if f, ok := _bindata[cannonicalName]; ok {
145 | a, err := f()
146 | if err != nil {
147 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
148 | }
149 | return a.info, nil
150 | }
151 | return nil, fmt.Errorf("AssetInfo %s not found", name)
152 | }
153 |
154 | // AssetNames returns the names of the assets.
155 | func AssetNames() []string {
156 | names := make([]string, 0, len(_bindata))
157 | for name := range _bindata {
158 | names = append(names, name)
159 | }
160 | return names
161 | }
162 |
163 | // _bindata is a table, holding each asset generator, mapped to its name.
164 | var _bindata = map[string]func() (*asset, error){
165 | "Basehead.obj": baseheadObj,
166 | "data/click.png": dataClickPng,
167 | }
168 |
169 | // AssetDir returns the file names below a certain
170 | // directory embedded in the file by go-bindata.
171 | // For example if you run go-bindata on data/... and data contains the
172 | // following hierarchy:
173 | // data/
174 | // foo.txt
175 | // img/
176 | // a.png
177 | // b.png
178 | // then AssetDir("data") would return []string{"foo.txt", "img"}
179 | // AssetDir("data/img") would return []string{"a.png", "b.png"}
180 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error
181 | // AssetDir("") will return []string{"data"}.
182 | func AssetDir(name string) ([]string, error) {
183 | node := _bintree
184 | if len(name) != 0 {
185 | cannonicalName := strings.Replace(name, "\\", "/", -1)
186 | pathList := strings.Split(cannonicalName, "/")
187 | for _, p := range pathList {
188 | node = node.Children[p]
189 | if node == nil {
190 | return nil, fmt.Errorf("Asset %s not found", name)
191 | }
192 | }
193 | }
194 | if node.Func != nil {
195 | return nil, fmt.Errorf("Asset %s not found", name)
196 | }
197 | rv := make([]string, 0, len(node.Children))
198 | for childName := range node.Children {
199 | rv = append(rv, childName)
200 | }
201 | return rv, nil
202 | }
203 |
204 | type bintree struct {
205 | Func func() (*asset, error)
206 | Children map[string]*bintree
207 | }
208 | var _bintree = &bintree{nil, map[string]*bintree{
209 | "Basehead.obj": &bintree{baseheadObj, map[string]*bintree{
210 | }},
211 | "data": &bintree{nil, map[string]*bintree{
212 | "click.png": &bintree{dataClickPng, map[string]*bintree{
213 | }},
214 | }},
215 | }}
216 |
217 | // RestoreAsset restores an asset under the given directory
218 | func RestoreAsset(dir, name string) error {
219 | data, err := Asset(name)
220 | if err != nil {
221 | return err
222 | }
223 | info, err := AssetInfo(name)
224 | if err != nil {
225 | return err
226 | }
227 | err = os.MkdirAll(_filePath(dir, path.Dir(name)), os.FileMode(0755))
228 | if err != nil {
229 | return err
230 | }
231 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
232 | if err != nil {
233 | return err
234 | }
235 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
236 | if err != nil {
237 | return err
238 | }
239 | return nil
240 | }
241 |
242 | // RestoreAssets restores an asset under the given directory recursively
243 | func RestoreAssets(dir, name string) error {
244 | children, err := AssetDir(name)
245 | // File
246 | if err != nil {
247 | return RestoreAsset(dir, name)
248 | }
249 | // Dir
250 | for _, child := range children {
251 | err = RestoreAssets(dir, path.Join(name, child))
252 | if err != nil {
253 | return err
254 | }
255 | }
256 | return nil
257 | }
258 |
259 | func _filePath(dir, name string) string {
260 | cannonicalName := strings.Replace(name, "\\", "/", -1)
261 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
262 | }
263 |
264 |
--------------------------------------------------------------------------------
/hoaxplus/data/data/click.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/klauspost/gad/8074eba3799ada5ddcd8a71f794efa03de654fb9/hoaxplus/data/data/click.png
--------------------------------------------------------------------------------
/hoaxplus/data/inject.go:
--------------------------------------------------------------------------------
1 | package data
2 |
3 | import "github.com/klauspost/gfx"
4 |
5 | func init() {
6 | gfx.AddData(Asset)
7 | }
8 |
--------------------------------------------------------------------------------
/hoaxplus/primitive/line.go:
--------------------------------------------------------------------------------
1 | package primitive
2 |
3 | import (
4 | "fmt"
5 | "image"
6 | )
7 |
8 | type Line struct {
9 | P1, P2 Point2D
10 | }
11 |
12 | func (l Line) Draw(dst *image.Gray, col byte) {
13 | w, h := dst.Rect.Dx(), dst.Rect.Dy()
14 | if !l.clip(w, h) {
15 | return
16 | }
17 |
18 | // Find which direction is longer
19 | yLonger := false
20 | shortLen := l.P2.Y - l.P1.Y
21 | longLen := l.P2.X - l.P1.X
22 |
23 | // Swap if we have to
24 | if absf(shortLen) > absf(longLen) {
25 | shortLen, longLen = longLen, shortLen
26 | yLonger = true
27 | }
28 |
29 | // Find how much we should increment on every pixel.
30 | var decInc float32
31 | if longLen != 0 {
32 | decInc = shortLen / longLen
33 | }
34 |
35 | // Small rounding adjustment to avoid accumulated errors.
36 | const sigma = 0.001
37 |
38 | if yLonger {
39 | if longLen > 0 {
40 | // Top to bottom, one y per loop
41 | l.P2.Y += sigma
42 | for j := l.P1.X; l.P1.Y <= l.P2.Y; l.P1.Y++ {
43 | setGray(dst, j, l.P1.Y, col)
44 | j += decInc
45 | }
46 | return
47 | }
48 | // Bottom to top, one y per loop
49 | l.P2.Y -= sigma
50 | for j := l.P1.X; l.P1.Y >= l.P2.Y; l.P1.Y-- {
51 | setGray(dst, j, l.P1.Y, col)
52 | j -= decInc
53 | }
54 | return
55 | }
56 | if longLen > 0 {
57 | // Left to right, one X per loop
58 | l.P2.X += sigma
59 | for j := l.P1.Y; l.P1.X <= l.P2.X; l.P1.X++ {
60 | setGray(dst, l.P1.X, j, col)
61 | j += decInc
62 | }
63 | return
64 | } else {
65 | l.P2.X -= sigma
66 | // Right to left, one X per loop
67 | for j := l.P1.Y; l.P1.X >= l.P2.X; l.P1.X-- {
68 | setGray(dst, l.P1.X, j, col)
69 | j -= decInc
70 | }
71 | }
72 | }
73 |
74 | func (l Line) DrawAA(dst *image.Gray, col byte) {
75 | w, h := dst.Rect.Dx(), dst.Rect.Dy()
76 | if !l.clip(w, h) {
77 | return
78 | }
79 |
80 | yLonger := false
81 | shortLen := l.P2.Y - l.P1.Y
82 | longLen := l.P2.X - l.P1.X
83 | if absf(shortLen) > absf(longLen) {
84 | shortLen, longLen = longLen, shortLen
85 | yLonger = true
86 | }
87 | var decInc float32
88 | if longLen != 0 {
89 | decInc = shortLen / longLen
90 | }
91 | const sigma = 0.001
92 |
93 | if yLonger {
94 | if longLen > 0 {
95 | // Top to bottom, one y per loop
96 | l.P2.Y += sigma
97 | for j := l.P1.X; l.P1.Y <= l.P2.Y; l.P1.Y++ {
98 | setGrayHorizontalAA(dst, j, l.P1.Y, col)
99 | j += decInc
100 | }
101 | return
102 | }
103 | // Bottom to top, one y per loop
104 | l.P2.Y -= sigma
105 | for j := l.P1.X; l.P1.Y >= l.P2.Y; l.P1.Y-- {
106 | setGrayHorizontalAA(dst, j, l.P1.Y, col)
107 | j -= decInc
108 | }
109 | return
110 | }
111 | if longLen > 0 {
112 | // Left to right, one X per loop
113 | l.P2.X += sigma
114 | for j := l.P1.Y; l.P1.X <= l.P2.X; l.P1.X++ {
115 | setGrayVerticalAA(dst, l.P1.X, j, col)
116 | j += decInc
117 | }
118 | return
119 | }
120 | // Right to left, one X per loop
121 | l.P2.X -= sigma
122 | for j := l.P1.Y; l.P1.X >= l.P2.X; l.P1.X-- {
123 | setGrayVerticalAA(dst, l.P1.X, j, col)
124 | j -= decInc
125 | }
126 | }
127 |
128 | // setGray will set a pixel.
129 | // It is assumed that X and y are clipped.
130 | func setGray(img *image.Gray, x, y float32, col byte) {
131 | img.Pix[roundP(x)+roundP(y)*img.Stride] = col
132 | }
133 |
134 | // setGray will set a pixel.
135 | // It is assumed that X and y are clipped.
136 | func setGrayAA(img *image.Gray, x, y float32, col byte) {
137 | // Convert to fixed point
138 | xx, yy := int(256*x), int(256*y)
139 |
140 | // Calculate weights
141 | x1, y1 := xx&255, yy&255
142 | x0, y0 := 256-x1, 256-y1
143 |
144 | // Apply weighted color to pixel
145 | weight := func(pix *byte, w int) {
146 | wOrg := 256 - w
147 | p := int(*pix)*wOrg + int(col)*w
148 | *pix = byte(p >> 8)
149 | }
150 |
151 | // Remove fraction from pixels coordinates.
152 | xx >>= 8
153 | yy >>= 8
154 |
155 | // Check if we can write to the next pixel
156 | xOK, yOK := xx < img.Rect.Dx()-1, yy < img.Rect.Dy()-1
157 |
158 | // Pre-multiply with image stride
159 | yy *= img.Stride
160 |
161 | // draw topleft pixel.
162 | p := &img.Pix[xx+yy]
163 | weight(p, (x0*y0)>>8)
164 | if xOK {
165 | p = &img.Pix[1+xx+yy]
166 | weight(p, (x1*y0)>>8)
167 | }
168 | if yOK {
169 | yy += img.Stride
170 | p = &img.Pix[xx+yy]
171 | weight(p, (x0*y1)>>8)
172 | if xOK {
173 | p = &img.Pix[1+xx+yy]
174 | weight(p, (x1*y1)>>8)
175 | }
176 | }
177 | }
178 |
179 | // setGrayHorizontalAA will set a pixel, but only do AA vertically.
180 | // This can be used when each pixel is drawn horizontally.
181 | // It is assumed that X and y are clipped.
182 | func setGrayHorizontalAA(img *image.Gray, x, y float32, col byte) {
183 | // Convert to fixed point
184 | xx, yy := int(256*x), int(256*y)
185 |
186 | // Calculate weights
187 | x1 := xx & 255
188 | x0 := 256 - x1
189 |
190 | // Apply weighted color to pixel.
191 | // w0 is color weight, w1 is existing weight.
192 | // Sum of w0 and w1 must be <= 256
193 | weight := func(pix *byte, w0, w1 int) {
194 | p := int(*pix)*w1 + int(col)*w0
195 | *pix = byte(p >> 8)
196 | }
197 |
198 | // Remove fraction from pixels coordinates.
199 | xx >>= 8
200 | yy >>= 8
201 |
202 | // Check if we can write to the next pixel
203 | xOK := xx < img.Rect.Dx()-1
204 |
205 | // Pre-multiply with image stride
206 | yy *= img.Stride
207 |
208 | // draw topleft pixel.
209 | p := &img.Pix[xx+yy]
210 | weight(p, x0, x1)
211 | if xOK {
212 | p = &img.Pix[1+xx+yy]
213 | weight(p, x1, x0)
214 | }
215 | }
216 |
217 | // setGrayVerticalAA will set a pixel, but only do AA horizontally.
218 | // This can be used when each pixel is drawn vertically.
219 | // It is assumed that X and y are clipped.
220 | func setGrayVerticalAA(img *image.Gray, x, y float32, col byte) {
221 | // Convert to fixed point
222 | xx, yy := int(256*x), int(256*y)
223 |
224 | // Calculate weights
225 | y1 := yy & 255
226 | y0 := 256 - y1
227 |
228 | // Apply weighted color to pixel.
229 | // w0 is color weight, w1 is existing weight.
230 | // Sum of w0 and w1 must be <= 256
231 | weight := func(pix *byte, w0, w1 int) {
232 | p := int(*pix)*w1 + int(col)*w0
233 | *pix = byte(p >> 8)
234 | }
235 |
236 | // Remove fraction from pixels coordinates.
237 | xx >>= 8
238 | yy >>= 8
239 |
240 | // Check if we can write to the next pixel
241 | yOK := yy < img.Rect.Dy()-1
242 |
243 | // Pre-multiply with image stride
244 | yy *= img.Stride
245 |
246 | // draw topleft pixel.
247 | p := &img.Pix[xx+yy]
248 | weight(p, y0, y1)
249 | if yOK {
250 | yy += img.Stride
251 | p = &img.Pix[xx+yy]
252 | weight(p, y1, y0)
253 | }
254 | }
255 |
256 | // roundP will round positive numbers towards nearest integer.
257 | func roundP(x float32) int {
258 | return int(x + 0.5)
259 | }
260 |
261 | func absf(x float32) float32 {
262 | switch {
263 | case x < 0:
264 | return -x
265 | case x == 0:
266 | return 0 // return correctly abs(-0)
267 | }
268 | return x
269 | }
270 |
271 | // line clipping converted from C++ on
272 | // https://www.geeksforgeeks.org/line-clipping-set-1-cohen-sutherland-algorithm/
273 | // Will also ensure that Y1 is smaller or equal to Y2.
274 | func (l *Line) clip(w, h int) bool {
275 | // Defining region codes
276 | const (
277 | INSIDE = 0
278 | LEFT = 1 << iota
279 | RIGHT
280 | BOTTOM
281 | TOP
282 | )
283 | if l.P1.Y > l.P2.Y {
284 | // Swap
285 | l.P1.X, l.P2.X = l.P2.X, l.P1.X
286 | l.P1.Y, l.P2.Y = l.P2.Y, l.P1.Y
287 | }
288 | fw, fh := float32(w)-0.51, float32(h)-0.51
289 |
290 | // Function to compute region code for a point(X, y)
291 | var computeCode = func(p Point2D) int {
292 | // initialized as being inside
293 | code := INSIDE
294 |
295 | if p.X < 0 {
296 | // to the left of rectangle
297 | code |= LEFT
298 | } else if p.X > fw {
299 | // to the right of rectangle
300 | code |= RIGHT
301 | }
302 | if p.Y < 0 {
303 | // below the rectangle
304 | code |= BOTTOM
305 | } else if p.Y > fh {
306 | // above the rectangle
307 | code |= TOP
308 | }
309 | return code
310 | }
311 |
312 | code1 := computeCode(l.P1)
313 | code2 := computeCode(l.P2)
314 | const minLen = (0.1 * 0.1) * 2
315 |
316 | for n := 0; ; n++ {
317 | if false && n > 5 {
318 | code1 = computeCode(l.P1)
319 | code2 = computeCode(l.P2)
320 | fmt.Println("Could not clip", l.P1, code1, "->", l.P2, code2)
321 | return false
322 | }
323 | if l.P1.DistSq(l.P2) < minLen {
324 | // Line too small to draw.
325 | return false
326 | }
327 | if (code1 == 0) && (code2 == 0) {
328 | // If both endpoints lie within rectangle
329 | return true
330 | }
331 | if (code1 & code2) != 0 {
332 | // If both endpoints are outside rectangle,
333 | // in same region
334 | return false
335 | }
336 |
337 | // Some segment of line lies within the
338 | // rectangle
339 | var codeOut int
340 | var x, y float32
341 |
342 | // At least one endpoint is outside the
343 | // rectangle, pick it.
344 | if code1 != 0 {
345 | codeOut = code1
346 | } else {
347 | codeOut = code2
348 | }
349 |
350 | // Find intersection point;
351 | // using formulas y = Y1 + slope * (X - X1),
352 | // X = X1 + (1 / slope) * (y - Y1)
353 | switch {
354 | case (codeOut & TOP) != 0:
355 | // point is above the clip rectangle
356 | x = l.P1.X + (l.P2.X-l.P1.X)*(fh-l.P1.Y)/(l.P2.Y-l.P1.Y)
357 | y = fh
358 |
359 | case (codeOut & BOTTOM) != 0:
360 | // point is below the rectangle
361 | x = l.P1.X + (l.P2.X-l.P1.X)*(-l.P1.Y)/(l.P2.Y-l.P1.Y)
362 | y = 0
363 | case (codeOut & RIGHT) != 0:
364 | // point is to the right of rectangle
365 | y = l.P1.Y + (l.P2.Y-l.P1.Y)*(fw-l.P1.X)/(l.P2.X-l.P1.X)
366 | x = fw
367 | case (codeOut & LEFT) != 0:
368 | // point is to the left of rectangle
369 | y = l.P1.Y + (l.P2.Y-l.P1.Y)*(-l.P1.X)/(l.P2.X-l.P1.X)
370 | x = 0
371 | }
372 |
373 | // Now intersection point X,y is found
374 | // We replace point outside rectangle
375 | // by intersection point
376 | if codeOut == code1 {
377 | l.P1.X = x
378 | l.P1.Y = y
379 | code1 = computeCode(l.P1)
380 | } else {
381 | l.P2.X = x
382 | l.P2.Y = y
383 | code2 = computeCode(l.P2)
384 | }
385 | }
386 | }
387 |
--------------------------------------------------------------------------------
/hoaxplus/primitive/objloader.go:
--------------------------------------------------------------------------------
1 | package primitive
2 |
3 | import (
4 | "bufio"
5 | "bytes"
6 | "fmt"
7 | "strconv"
8 | "strings"
9 | )
10 |
11 | // LoadOBJ will load and OBJ and return vertices and deduplicated edges.
12 | func LoadOBJ(b []byte) (verts P3Ds, edges [][2]int) {
13 | scanner := bufio.NewScanner(bytes.NewBuffer(b))
14 | known := make(map[uint64]struct{})
15 |
16 | addLine := func(a, b uint64) {
17 | if a == b {
18 | return
19 | }
20 | if b < a {
21 | a, b = b, a
22 | }
23 | v := a | (b << 32)
24 | if _, ok := known[v]; ok {
25 | return
26 | }
27 | known[v] = struct{}{}
28 | edges = append(edges, [2]int{int(a), int(b)})
29 | }
30 |
31 | for scanner.Scan() {
32 | t := scanner.Text()
33 | if strings.HasPrefix(t, "v ") {
34 | var c Point3D
35 | n, err := fmt.Sscanf(t, "v %f %f %f", &c.X, &c.Y, &c.Z)
36 | if err != nil {
37 | panic(err)
38 | }
39 | if n != 3 {
40 | panic("not 3")
41 | }
42 | verts = append(verts, c)
43 | continue
44 | }
45 | if strings.HasPrefix(t, "f ") {
46 | t := strings.TrimPrefix(t, "f ")
47 | faces := strings.Fields(t)
48 | indices := make([]uint64, len(faces))
49 | for i, v := range faces {
50 | s, err := strconv.ParseUint(v, 10, 32)
51 | if err != nil {
52 | panic(err)
53 | }
54 | if s == 0 {
55 | panic("index 0 face found, should start with 1")
56 | }
57 | indices[i] = s - 1
58 | }
59 | for i, v := range indices {
60 | if i == 0 {
61 | // add first to last
62 | addLine(v, indices[len(indices)-1])
63 | continue
64 | }
65 | addLine(v, indices[i-1])
66 | }
67 | }
68 | }
69 | return
70 | }
71 |
--------------------------------------------------------------------------------
/hoaxplus/primitive/point2d.go:
--------------------------------------------------------------------------------
1 | package primitive
2 |
3 | type Point2D struct {
4 | X, Y float32
5 | }
6 |
7 | type P2Ds []Point2D
8 |
9 | func (p Point2D) DistSq(p2 Point2D) float32 {
10 | a, b := p.X-p2.X, p.Y-p2.Y
11 | return a*a + b*b
12 | }
13 |
--------------------------------------------------------------------------------
/hoaxplus/primitive/point3d.go:
--------------------------------------------------------------------------------
1 | package primitive
2 |
3 | import "math"
4 |
5 | type Point3D struct{ X, Y, Z float32 }
6 | type P3Ds []Point3D
7 |
8 | func (c *Point3D) Scale(f float32) {
9 | c.X *= f
10 | c.Y *= f
11 | c.Z *= f
12 | }
13 |
14 | func (p P3Ds) Scale(f float32) {
15 | for i := range p {
16 | p[i].Scale(f)
17 | }
18 | }
19 |
20 | // rotateFn returns a function that rotates around (0,0,0).
21 | // Supply angles in radians.
22 | // dst must be same size or bigger than p.
23 | func (p P3Ds) RotateTo(dst P3Ds, xAn, yAn, zAn float64) {
24 | fn := rotateFn(xAn, yAn, zAn)
25 | for i, v := range p {
26 | dst[i] = fn(v)
27 | }
28 | }
29 |
30 | // BehindCamera is magic
31 | const BehindCamera = 10e21
32 |
33 | // rotateFn returns a function that rotates around (0,0,0).
34 | // dst must be same size or bigger than p.
35 | func (p P3Ds) ProjectTo(dst []Point2D, w, h, zoff float32) {
36 | halfWidth := w * 0.5
37 | halfHeight := h * 0.5
38 | for i, v := range p {
39 | z := v.Z + zoff
40 | if z <= 0 {
41 | dst[i] = Point2D{X: BehindCamera, Y: BehindCamera}
42 | continue
43 | }
44 | invZ := 1 / z
45 | x := halfWidth * v.X * invZ
46 | y := halfWidth * v.Y * invZ
47 | x += halfWidth
48 | y += halfHeight
49 | dst[i] = Point2D{X: x, Y: y}
50 | }
51 | }
52 |
53 | // rotateFn returns a function that rotates around (0,0,0).
54 | // Supply angles in radians.
55 | func rotateFn(xAn, yAn, zAn float64) func(c Point3D) Point3D {
56 | var (
57 | s1 = float32(math.Sin(zAn))
58 | s2 = float32(math.Sin(xAn))
59 | s3 = float32(math.Sin(yAn))
60 | c1 = float32(math.Cos(zAn))
61 | c2 = float32(math.Cos(xAn))
62 | c3 = float32(math.Cos(yAn))
63 |
64 | zero = c1*c3 + s1*s2*s3
65 | one = c2 * s3
66 | two = -c3*s1 + c1*s2*s3
67 | three = c2 * s1
68 | four = -s2
69 | five = c2 * c1
70 | six = -c1*s3 + c3*s1*s2
71 | seven = c2 * c3
72 | eight = s1*s3 + c1*c3*s2
73 | )
74 | return func(c Point3D) Point3D {
75 | c.X, c.Y, c.Z = c.X*zero+c.Y*one+c.Z*two, c.X*three+c.Y*four+c.Z*five, c.X*six+c.Y*seven+c.Z*eight
76 | return c
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Go After Dark
7 |
8 |
9 |
10 |
11 |
GO AFTER DARK
12 |
13 | Go After Dark is a video series where we create realtime graphical effects in Go.
14 | We don't care about boring everyday problems but try to make something cool looking and fun.
15 | This series allows you to pick up graphical programming from the start - only assuming you have basic knowledge of the language.
16 |