spline
This commit is contained in:
@@ -50,6 +50,10 @@ func lerp(part, from, to float64) float64 {
|
||||
return from + part*(to-from)
|
||||
}
|
||||
|
||||
func lerp32(part, from, to float32) float32 {
|
||||
return from + part*(to-from)
|
||||
}
|
||||
|
||||
func (n PerlinNoise) Sample(x, y, z float64, yamp, ymin float64) (v float64) {
|
||||
var h1, h2, h3 uint8
|
||||
var t1, t2, t3 float64
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
package gen
|
||||
|
||||
type Spline interface {
|
||||
Sample(t []float32) float32
|
||||
}
|
||||
|
||||
type FixedSpline struct {
|
||||
Val float32
|
||||
}
|
||||
|
||||
func (s FixedSpline) Sample(t []float32) float32 {
|
||||
return s.Val
|
||||
}
|
||||
|
||||
type SubSpline struct {
|
||||
Loc, Der float32
|
||||
Val Spline
|
||||
}
|
||||
type SplineA struct {
|
||||
TargetIndex int
|
||||
Points []SubSpline
|
||||
}
|
||||
|
||||
func ternery[T any](a bool, b T, c T) T {
|
||||
if a {
|
||||
return b
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (s SplineA) Sample(in []float32) float32 {
|
||||
f := in[s.TargetIndex]
|
||||
|
||||
i := 0
|
||||
for _, p := range s.Points {
|
||||
if f <= p.Loc {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
if i == 0 || i == len(s.Points) {
|
||||
if i != 0 {
|
||||
i--
|
||||
}
|
||||
v := s.Points[i].Val.Sample(in)
|
||||
return v + s.Points[i].Der*(f-s.Points[i].Loc)
|
||||
}
|
||||
s1 := s.Points[i-1]
|
||||
s2 := s.Points[i]
|
||||
g := s.Points[i-1].Loc
|
||||
h := s.Points[i].Loc
|
||||
k := (f - g) / (h - g)
|
||||
l := s.Points[i-1].Der
|
||||
m := s.Points[i].Der
|
||||
n := s1.Val.Sample(in)
|
||||
o := s2.Val.Sample(in)
|
||||
p := l*(h-g) - (o - n)
|
||||
q := -m*(h-g) + (o - n)
|
||||
r := lerp32(k, n, o) + k*(1.0-k)*lerp32(k, p, q)
|
||||
return r
|
||||
}
|
||||
|
||||
const (
|
||||
splineIndexContinentalNess = iota
|
||||
splineIndexErosion
|
||||
splineIndexWeirdness
|
||||
)
|
||||
|
||||
func getOffsetValue(weirdness float32, continentalness float32) float32 {
|
||||
f0 := 1.0 - (1.0-continentalness)*0.5
|
||||
f1 := 0.5 * (1.0 - continentalness)
|
||||
f2 := (weirdness + 1.17) * 0.46082947
|
||||
off := f2*f0 - f1
|
||||
if weirdness < -0.7 {
|
||||
if off > -0.2222 {
|
||||
return off
|
||||
}
|
||||
return -0.2222
|
||||
}
|
||||
if off > 0 {
|
||||
return off
|
||||
}
|
||||
return 0
|
||||
|
||||
}
|
||||
|
||||
func createSpline38219(f float32, bl bool) Spline {
|
||||
s := SplineA{
|
||||
TargetIndex: splineIndexWeirdness,
|
||||
Points: nil,
|
||||
}
|
||||
i := getOffsetValue(-1.0, f)
|
||||
k := getOffsetValue(1.0, f)
|
||||
l := 1.0 - (1.0-f)*0.5
|
||||
u := 0.5 * (1.0 - f)
|
||||
l = u/(0.46082947*l) - 1.17
|
||||
|
||||
if -0.65 < l && l < 1.0 {
|
||||
u = getOffsetValue(-0.65, f)
|
||||
p := getOffsetValue(-0.75, f)
|
||||
q := (p - i) * 4.0
|
||||
r := getOffsetValue(l, f)
|
||||
z := (k - r) / (1.0 - l)
|
||||
|
||||
s.Points = append(s.Points, SubSpline{-1.0, q, FixedSpline{i}})
|
||||
s.Points = append(s.Points, SubSpline{-0.75, 0, FixedSpline{p}})
|
||||
s.Points = append(s.Points, SubSpline{-0.65, 0, FixedSpline{u}})
|
||||
s.Points = append(s.Points, SubSpline{l - 0.01, 0, FixedSpline{r}})
|
||||
s.Points = append(s.Points, SubSpline{l, z, FixedSpline{r}})
|
||||
s.Points = append(s.Points, SubSpline{1.0, z, FixedSpline{k}})
|
||||
} else {
|
||||
u = (k - i) * 0.5
|
||||
if bl {
|
||||
s.Points = append(s.Points, SubSpline{-1.0, 0, FixedSpline{ternery(i > 0.2, i, 0.2)}})
|
||||
s.Points = append(s.Points, SubSpline{0.0, u, FixedSpline{lerp32(0.5, i, k)}})
|
||||
} else {
|
||||
s.Points = append(s.Points, SubSpline{-1.0, u, FixedSpline{i}})
|
||||
}
|
||||
s.Points = append(s.Points, SubSpline{1.0, u, FixedSpline{k}})
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func createFlatOffsetSpline(f, g, h, i, j, k float32) Spline {
|
||||
l := 0.5 * (g - f)
|
||||
if l < k {
|
||||
l = k
|
||||
}
|
||||
m := 5.0 * (h - g)
|
||||
n := m
|
||||
if l < m {
|
||||
n = l
|
||||
}
|
||||
|
||||
return SplineA{
|
||||
TargetIndex: splineIndexWeirdness,
|
||||
Points: []SubSpline{
|
||||
{-1, l, FixedSpline{f}},
|
||||
{-0.4, n, FixedSpline{g}},
|
||||
{0, m, FixedSpline{h}},
|
||||
{0.4, 2.0 * (i - h), FixedSpline{i}},
|
||||
{1, 0.7 * (j - i), FixedSpline{j}},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func landSpline(f, g, h, i, j, k float32, bl bool) Spline {
|
||||
s1 := createSpline38219(lerp32(i, 0.6, 1.5), bl)
|
||||
s2 := createSpline38219(lerp32(i, 0.6, 1.0), bl)
|
||||
s3 := createSpline38219(i, bl)
|
||||
ih := 0.5 * i
|
||||
s4 := createFlatOffsetSpline(f-0.15, ih, ih, ih, i*0.6, 0.5)
|
||||
s5 := createFlatOffsetSpline(f, j*i, g*i, ih, i*0.6, 0.5)
|
||||
s6 := createFlatOffsetSpline(f, j, j, g, h, 0.5)
|
||||
s7 := createFlatOffsetSpline(f, j, j, g, h, 0.5)
|
||||
s8 := SplineA{
|
||||
TargetIndex: splineIndexWeirdness,
|
||||
Points: []SubSpline{
|
||||
{-1, 0, FixedSpline{f}},
|
||||
{-0.4, 0, s6},
|
||||
{0, 0, FixedSpline{h + 0.07}},
|
||||
},
|
||||
}
|
||||
s9 := createFlatOffsetSpline(-0.02, k, k, g, h, 0)
|
||||
s := SplineA{
|
||||
TargetIndex: splineIndexErosion,
|
||||
Points: []SubSpline{
|
||||
{-0.85, 0, s1},
|
||||
{-0.7, 0, s2},
|
||||
{-0.4, 0, s3},
|
||||
{-0.35, 0, s4},
|
||||
{-0.1, 0, s5},
|
||||
{0.2, 0, s6},
|
||||
},
|
||||
}
|
||||
if bl {
|
||||
s.Points = append(s.Points, SubSpline{0.4, 0, s7})
|
||||
s.Points = append(s.Points, SubSpline{0.45, 0, s8})
|
||||
s.Points = append(s.Points, SubSpline{0.55, 0, s8})
|
||||
s.Points = append(s.Points, SubSpline{0.58, 0, s7})
|
||||
}
|
||||
s.Points = append(s.Points, SubSpline{0.7, 0, s9})
|
||||
return s
|
||||
}
|
||||
|
||||
func CreateBiomeDepthSpline() Spline {
|
||||
sp1 := landSpline(-0.15, 0.00, 0.0, 0.1, 0.00, -0.03, false)
|
||||
sp2 := landSpline(-0.10, 0.03, 0.1, 0.1, 0.01, -0.03, false)
|
||||
sp3 := landSpline(-0.10, 0.03, 0.1, 0.7, 0.01, -0.03, true)
|
||||
sp4 := landSpline(-0.05, 0.03, 0.1, 1.0, 0.01, 0.01, true)
|
||||
|
||||
return SplineA{
|
||||
TargetIndex: splineIndexContinentalNess,
|
||||
Points: []SubSpline{
|
||||
{Loc: -1.10, Val: FixedSpline{Val: 0.044}, Der: 0.0},
|
||||
{Loc: -1.02, Val: FixedSpline{Val: -0.2222}, Der: 0.0},
|
||||
{Loc: -0.51, Val: FixedSpline{Val: -0.2222}, Der: 0.0},
|
||||
{Loc: -0.44, Val: FixedSpline{Val: -0.12}, Der: 0.0},
|
||||
{Loc: -0.18, Val: FixedSpline{Val: -0.12}, Der: 0.0},
|
||||
{Loc: -0.16, Val: sp1, Der: 0.0},
|
||||
{Loc: -0.15, Val: sp1, Der: 0.0},
|
||||
{Loc: -0.10, Val: sp2, Der: 0.0},
|
||||
{Loc: 0.25, Val: sp3, Der: 0.0},
|
||||
{Loc: 1.00, Val: sp4, Der: 0.0},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var BiomeDepthSpline = CreateBiomeDepthSpline()
|
||||
@@ -0,0 +1,10 @@
|
||||
package gen
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSpline(t *testing.T) {
|
||||
v := BiomeDepthSpline.Sample([]float32{0.236413047, 0.220234469, 0.139604524, -0.339296669})
|
||||
if v != 0.025035858154296875 {
|
||||
t.Errorf("bad value: %f", v)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user