-
Notifications
You must be signed in to change notification settings - Fork 13
/
meshface.go
138 lines (112 loc) · 2.87 KB
/
meshface.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package main
import (
. "github.com/buchanae/ink/color"
. "github.com/buchanae/ink/dd"
"github.com/buchanae/ink/gfx"
"github.com/buchanae/ink/rand"
"github.com/buchanae/ink/voronoi"
)
const (
N = 10
Padding = 0.01
Margin = Padding * 2
)
// TODO idea
// use MeshShade to shade an image of a face
// using image brightness to determine point
// density. kinda like pointilism, but connecting
// points into mesh
/*
TODO ideas:
- voronoi mesh of blue noise. draw lines of mesh edges.
should create a mesh/web texture
- rand.BlueNoise needs to be cleaned up.
- easily generate points in rect/shape
- don't require N, just generate until full
- want easier interpolation, padding, etc.
- want easier variable curves (e.g. x^2)
always find it unintuitive to define a model
where a variable grows how I want
*/
func Ink(doc gfx.Doc) {
rand.SeedNow()
for i := float32(0); i < N; i++ {
p := i / N
split := rand.Range(.3, .7)
bot := i/N + (Padding / 2)
top := (i+1)/N - (Padding / 2)
ra := Rect{
A: XY{Margin, bot},
B: XY{split - (Padding / 2), top},
}
rb := Rect{
A: XY{split + (Padding / 2), bot},
B: XY{1 - Margin, top},
}
c := RGBA{p, p, p, 1}
MeshShade(doc, ra, c, i)
//gfx.Fill{ra, c}.Draw(doc)
gfx.Fill{rb, c}.Draw(doc)
}
}
// TODO be able to turn on tracing from within the doc/sketch
// TODO voronoi should definitely have a Mesh() method
// TODO this is a good example of a sketch where memoization
// (smarter caching) would help. this takes time to generate
// millions of blue noise points. would be nice to skip that
// if all we need is to change the color
func MeshShade(doc gfx.Layer, r Rect, c RGBA, i float32) {
space := Interp(0.002, 0.02, i/N)
na := BlueNoiseInBox(100000, space, r)
// TODO want voronoi without edges
v := voronoi.New(na, r)
seen := map[Line]struct{}{}
for _, t := range v.Triangulate() {
for _, e := range t.Edges() {
if e.A.X < e.B.X || e.A.Y < e.B.Y {
e.A, e.B = e.B, e.A
// TODO cool mistake
//e.A = e.B
}
if _, ok := seen[e]; ok {
continue
}
seen[e] = struct{}{}
gfx.Stroke{
Shape: e,
Width: 0.0005,
Color: c,
}.Draw(doc)
}
}
}
func CellShade(doc gfx.Layer, r Rect, c RGBA, i float32) {
space := Interp(0.002, 0.01, i/N)
na := BlueNoiseInBox(50000, space, r)
// TODO want voronoi without edges
v := voronoi.New(na, r)
for _, e := range v.Edges() {
gfx.Stroke{
Shape: e,
Color: c,
}.Draw(doc)
}
}
func DotShade(doc gfx.Layer, r Rect, c RGBA, i float32) {
space := Interp(0.002, 0.009, i/N)
na := BlueNoiseInBox(100000, space, r)
for _, xy := range na {
gfx.Dot{xy, c, 0.001}.Draw(doc)
}
}
func Interp(from, to, p float32) float32 {
return (to-from)*p + from
}
func BlueNoiseInBox(n int, space float32, box Rect) []XY {
bn := rand.BlueNoise{
Limit: n,
Rect: box,
Spacing: space,
}
return bn.Generate()
}