Generates smoother noise than PerlinNoise
.
Each coordinates at a multiple of period
defines a random vector and
values in between are interpolated from these vectors.
This implementation uses a custom deterministic pseudo random number
generator seeded with seed
.
It can be further customized by redefining gradient_vector
.
This process do not require any state, so this class only holds the
attributes of the generator and does not keep any generated data.
var map = new InterpolatedNoise
map.min = 0.0
map.max = 16.0
map.period = 20.0
map.seed = 0
var max = 0.0
var min = 100.0
for y in 30.times do
for x in 70.times do
# Get a value at x, y
var val = map[x.to_f, y.to_f]
printn val.to_i.to_hex
max = max.max(val)
min = min.min(val)
end
print ""
end
assert max <= map.max
assert min >= map.min
89abcddeeeeeeeddcba9877666555555555666778766555544444555566789abcddeee
789abcddeeeeeeddccba887766655555555566677766555544444555566779abcddeee
689abcddeeeeeeeddcba988776655555555555667666555554455555566778abccdeee
678abccdeeeeeeeedccba988766655555555555666655555555555556666789abcddee
5789abcddeeeeeeeddcba998776655544444555666655555555555556666789abcddee
5689abcddeeeeeeeedccba98776655544444455566555555555555566666789abccdde
4679abccdeeeffeeeddcba98776655444444445565555555555555666666789abbcddd
4678abccdeeeffeeeedcba98876555444444444555555555566666666666689aabccdd
46789abcdeeeeffeeedccb988765544443344445555566666666666666666789abccdd
45789abcddeeeffeeeddcb987765544433334445555666666666666666666789abbccd
45789abcddeeeeeeeeddcb987665444333333445556666666777777777766789aabccc
45789abcddeeeeeeeeddca987655443333333445566666777777777777776789aabbcc
45789abcddeeeeeeeedcca9876544333333333455666777777788877777767899aabbc
46789abcddeeeeeeeddcba9876544333222333455667777888888888877767899aabbb
46789abcdddeeeeedddcba87655433222223334566777888889998888877778899aabb
5678aabcdddeeeedddccb987654332222222334566778889999999998887778899aaab
5689abbcddddeedddccba9865443222222223345677889999aaaa99998877788999aaa
6789abbcddddddddccbba8765432221111223345678899aaaaaaaaaa9988778889999a
6789abccdddddddccbba9865433221111122344577899aabbbbbbbaaa9987788889999
789abbccddddddccbba9876543211111111234567899aabbbccccbbbaa987788888899
889abbccdddddccbba9886543211000001123456889abbcccccccccbba988888888888
899abbcccddddcccbaa9875432211000011223457899abbcccccccccbba98888888888
899abbccccddccccbba9876533211000001123456789aabccccddcccbbaa9998888888
899abbccccccccccbbaa9765432111000011223456899abbcccdddcccbba9999988888
899abbbcccccccccbbaa9865432211000011123456789abbccdddddcccbba999988888
899aabbcccccccccbbaa9875433211100001122346789abbccddddddcccbaa99988888
899aabbbcccccccbbbbaa876543211100001122345689aabccdddddddccbaaa9988887
899aabbbbbbccbbbbbbaa876543221110001112335679aabccddddddddcbbaa9988877
899aaabbbbbbbbbbbbbaa9765433211111111123356789abccddddddddccbaa9988777
8999aaaabbbbbbbbbbaaa9765433221111111122356789abccdddeedddccbaa9988777
noise :: InterpolatedNoise :: gradient_vector
Get the componentw
of the gradient unit vector at x
, y
noise $ InterpolatedNoise :: SELF
Type of this instance, automatically specialized in every classnoise $ InterpolatedNoise :: core_serialize_to
Actual serialization ofself
to serializer
noise $ InterpolatedNoise :: from_deserializer
Create an instance of this class from thedeserializer
serialization :: Serializable :: accept_json_serializer
Refinable service to customize the serialization of this class to JSONserialization :: Serializable :: accept_msgpack_attribute_counter
Hook to customize the behavior of theAttributeCounter
serialization :: Serializable :: accept_msgpack_serializer
Hook to customize the serialization of this class to MessagePackserialization :: Serializable :: add_to_bundle
Called by[]=
to dynamically choose the appropriate method according
noise :: Noise :: amplitude=
Set the desired amplitude of the values returned by[]
core :: Object :: class_factory
Implementation used byget_class
to create the specific class.
serialization :: Serializable :: core_serialize_to
Actual serialization ofself
to serializer
core :: Object :: defaultinit
noise :: Noise :: defaultinit
serialization :: Serializable :: from_deserializer
Create an instance of this class from thedeserializer
noise :: InterpolatedNoise :: gradient_vector
Get the componentw
of the gradient unit vector at x
, y
core :: Object :: is_same_instance
Return true ifself
and other
are the same instance (i.e. same identity).
core :: Object :: is_same_serialized
Isself
the same as other
in a serialization context?
core :: Object :: is_same_type
Return true ifself
and other
have the same dynamic type.
serialization :: Serializable :: msgpack_extra_array_items
Hook to request a larger than usual metadata arraycore :: Object :: output_class_name
Display class name on stdout (debug only).serialization :: Serializable :: serialize_msgpack
Serializeself
to MessagePack bytes
serialization :: Serializable :: serialize_to
Serializeself
to serializer
serialization :: Serializable :: serialize_to_json
Serializeself
to JSON
serialization :: Serializable :: to_pretty_json
Serializeself
to plain pretty JSON
Serializer::serialize
# Simple interpolated noise
#
# Generates smoother noise than `PerlinNoise`.
#
# Each coordinates at a multiple of `period` defines a random vector and
# values in between are interpolated from these vectors.
#
# This implementation uses a custom deterministic pseudo random number
# generator seeded with `seed`.
# It can be further customized by redefining `gradient_vector`.
# This process do not require any state, so this class only holds the
# attributes of the generator and does not keep any generated data.
#
# ## Usage example
#
# ~~~
# var map = new InterpolatedNoise
# map.min = 0.0
# map.max = 16.0
# map.period = 20.0
# map.seed = 0
#
# var max = 0.0
# var min = 100.0
# for y in 30.times do
# for x in 70.times do
# # Get a value at x, y
# var val = map[x.to_f, y.to_f]
# printn val.to_i.to_hex
#
# max = max.max(val)
# min = min.min(val)
# end
# print ""
# end
# assert max <= map.max
# assert min >= map.min
# ~~~
#
# ## Result at seed == 0
#
# ~~~raw
# 89abcddeeeeeeeddcba9877666555555555666778766555544444555566789abcddeee
# 789abcddeeeeeeddccba887766655555555566677766555544444555566779abcddeee
# 689abcddeeeeeeeddcba988776655555555555667666555554455555566778abccdeee
# 678abccdeeeeeeeedccba988766655555555555666655555555555556666789abcddee
# 5789abcddeeeeeeeddcba998776655544444555666655555555555556666789abcddee
# 5689abcddeeeeeeeedccba98776655544444455566555555555555566666789abccdde
# 4679abccdeeeffeeeddcba98776655444444445565555555555555666666789abbcddd
# 4678abccdeeeffeeeedcba98876555444444444555555555566666666666689aabccdd
# 46789abcdeeeeffeeedccb988765544443344445555566666666666666666789abccdd
# 45789abcddeeeffeeeddcb987765544433334445555666666666666666666789abbccd
# 45789abcddeeeeeeeeddcb987665444333333445556666666777777777766789aabccc
# 45789abcddeeeeeeeeddca987655443333333445566666777777777777776789aabbcc
# 45789abcddeeeeeeeedcca9876544333333333455666777777788877777767899aabbc
# 46789abcddeeeeeeeddcba9876544333222333455667777888888888877767899aabbb
# 46789abcdddeeeeedddcba87655433222223334566777888889998888877778899aabb
# 5678aabcdddeeeedddccb987654332222222334566778889999999998887778899aaab
# 5689abbcddddeedddccba9865443222222223345677889999aaaa99998877788999aaa
# 6789abbcddddddddccbba8765432221111223345678899aaaaaaaaaa9988778889999a
# 6789abccdddddddccbba9865433221111122344577899aabbbbbbbaaa9987788889999
# 789abbccddddddccbba9876543211111111234567899aabbbccccbbbaa987788888899
# 889abbccdddddccbba9886543211000001123456889abbcccccccccbba988888888888
# 899abbcccddddcccbaa9875432211000011223457899abbcccccccccbba98888888888
# 899abbccccddccccbba9876533211000001123456789aabccccddcccbbaa9998888888
# 899abbccccccccccbbaa9765432111000011223456899abbcccdddcccbba9999988888
# 899abbbcccccccccbbaa9865432211000011123456789abbccdddddcccbba999988888
# 899aabbcccccccccbbaa9875433211100001122346789abbccddddddcccbaa99988888
# 899aabbbcccccccbbbbaa876543211100001122345689aabccdddddddccbaaa9988887
# 899aabbbbbbccbbbbbbaa876543221110001112335679aabccddddddddcbbaa9988877
# 899aaabbbbbbbbbbbbbaa9765433211111111123356789abccddddddddccbaa9988777
# 8999aaaabbbbbbbbbbaaa9765433221111111122356789abccdddeedddccbaa9988777
# ~~~
class InterpolatedNoise
super Noise
redef fun [](x, y)
do
x = x/period
y = y/period
# Get grid coordinates
var x0 = if x > 0.0 then x.to_i else x.to_i - 1
var x1 = x0 + 1
var y0 = if y > 0.0 then y.to_i else y.to_i - 1
var y1 = y0 + 1
# Position in grid
var sx = x - x0.to_f
var sy = y - y0.to_f
# Interpolate
var n0 = gradient_dot_product(x0, y0, x, y)
var n1 = gradient_dot_product(x1, y0, x, y)
var ix0 = sx.lerp(n0, n1)
n0 = gradient_dot_product(x0, y1, x, y)
n1 = gradient_dot_product(x1, y1, x, y)
var ix1 = sx.lerp(n0, n1)
var val = sy.lerp(ix0, ix1)
# Return value in [min...max] from val in [-1.0...1.0]
val /= 2.0
val += 0.5
return val.lerp(min, max)
end
# Get the component `w` of the gradient unit vector at `x`, `y`
#
# `w` at 0 targets the X axis, at 1 the Y axis.
#
# Returns a value between -1.0 and 1.0.
#
# Require: `w == 0 or w == 1`
protected fun gradient_vector(x, y, w: Int): Float
do
assert w == 0 or w == 1
# Use our own deterministic pseudo random number generator
#
# These magic prime numbers were determined good enough by
# non-emperical experimentation. They may need to be changed/improved.
var seed = 817721 + self.seed
var i = seed * (x+seed) * 25111217 * (y+seed) * 72233613
var mod = 137121
var angle = (i.mask.abs%mod).to_f*2.0*pi/mod.to_f
# Debug code to evaluate the efficiency of the random angle generator
# The average of the produced angles should be at pi
#
#var sum = once new Container[Float](0.0)
#var count = once new Container[Float](0.0)
#sum.item += angle
#count.item += 1.0
#if count.item.to_i % 1000 == 0 then print "avg:{sum.item/count.item}/{count.item} i:{i} a:{angle} ({x}, {y}: {seed})"
if w == 0 then return angle.cos
return angle.sin
end
private fun gradient_dot_product(ix, iy: Int, x, y: Float): Float
do
var dx = x - ix.to_f
var dy = y - iy.to_f
return dx*gradient_vector(ix, iy, 0) + dy*gradient_vector(ix, iy, 1)
end
end
lib/noise/noise.nit:204,1--350,3