-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpoints.go
85 lines (77 loc) · 2.23 KB
/
points.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
package texture
import (
"github.com/jphsd/datastruct"
)
// BlinnField implements the ideas from Blinn's 1982 paper, A Generalization of Algebraic Surface Drawing.
// In Blinn's paper, D() is the distance squared, F() is the exponential function and the values of A and B
// are determined from the desired metaball radius and blobiness.
type BlinnField struct {
Name string
Points [][]float64
A []float64
B []float64
D func([]float64, []float64) float64
F func(float64) float64
Scale float64
Offset float64
}
func NewBlinnField(points [][]float64, a, b []float64,
d func([]float64, []float64) float64, f func(float64) float64,
scale, offset float64) *BlinnField {
return &BlinnField{"BlinnField", points, a, b, d, f, scale, offset}
}
// Eval2 implements the Field interface.
func (pf *BlinnField) Eval2(x, y float64) float64 {
loc := []float64{x, y}
var sum float64
for i, pi := range pf.Points {
d := pf.D(loc, pi)
if i < len(pf.A) {
d *= pf.A[i]
}
v := pf.F(d)
if i < len(pf.B) {
v *= pf.B[i]
}
sum += v
}
return clamp(sum*pf.Scale + pf.Offset)
}
// WorleyField implements the ideas from Worley's 1996 paper, A Cellular Texture Basis Function.
// In Worley's paper, the D() is the Euclidean distance function, F() is the identity function, all A
// are 1 and B determines the weights based on the distance from the point being queried.
type WorleyField struct {
Name string
Points [][]float64
A []float64
B []float64
F func(float64) float64
Scale float64
Offset float64
kdtree *datastruct.KDTree
np int
}
func NewWorleyField(points [][]float64, a, b []float64,
d func([]float64, []float64) float64, f func(float64) float64,
scale, offset float64) *WorleyField {
kdtree := datastruct.NewKDTree(2, points...)
kdtree.Dist = d
np := len(b)
if np > len(points) {
np = len(points)
}
return &WorleyField{"WorleyField", points, a, b, f, scale, offset, kdtree, np}
}
// Eval2 implements the Field interface.
func (pf *WorleyField) Eval2(x, y float64) float64 {
loc := []float64{x, y}
_, ds, _ := pf.kdtree.KNN(loc, pf.np)
var sum float64
for i, d := range ds {
if i < len(pf.A) {
d *= pf.A[i]
}
sum += pf.F(d) * pf.B[i]
}
return clamp(sum*pf.Scale + pf.Offset)
}