Property definitions

noise $ PerlinNoise :: defaultinit
# 2D Perlin noise generator using layered `InterpolatedNoise`
#
# Get values at any coordinates with `[]`.
# The behavior of this generator can be customized using its attributes `min`,
# `max`, `period` and `seed`.
#
# This noise is more realistic and less smooth than the `InterpolatedNoise`.
#
# Due to implementation logic, the full amplitude cannot be reached.
# In practice, only `amplitude * (1.0 - 1.0 / n_levels)` is covered.
#
# This implementation uses a custom deterministic pseudo random number
# generator to set `InterpolatedNoise::seed` of the `layers`.
# It is seeded with the local `seed` and can be further customized by
# redefining `pseudo_random`.
# 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 PerlinNoise
# 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
# 76666555444322234567789abbcbbaabbaa98777766665665566667888987655444444
# 776665554443322234567789abbbbbbbbba98777766666665556666788998654444444
# 777766544443322234566789abbbbbbbbaa99877777776665556666788888655444444
# 777776444443322244556679abbbccbbbaa99877777776655556666688888655444444
# 777766444444332244555678abbbccbbbaa99887787877655556666678888654444444
# 8887654344443333444456789abcccbbaa999877888886555555666688777654444455
# 8887654344443333444456789abbcdcbaa999887889887655555566677777654444456
# 7876654434444444444456778abbcccaaa999888899888655555566677777654444556
# 78765544344445544444567789bbccca99999888899988765555566666667654445566
# 77765444344455554445567889bbccba99999998999988765555566555666654445667
# 7765444334555665445556788abbbba988998999999988765555566545556554456677
# 87654444334556655455567899bbbba998888899999887766555566544556555456777
# 87655444334566665555567899bbbbba98888899988888776555566544556555556777
# 97655544334566665555567899abbbba98888899988888776555655544456555667777
# 97655544444566665556667899aaaaba98888999877777776555555444456666667777
# 866555444456666666566789999aaaaa98889998877777766556544443456667777777
# 976555445556776666666789aa99aaaa98889998876777666555544444456677887777
# 9765554556667777776667899999aaaa98889988876676666555443444446678888888
# 87655555666777788766678999899aaa99889988776666666554433344446789998888
# 876555566777788888766889998899a999889987776666666543333334456899a99899
# 766556677877889998877888888889a99998888777666666653222233345799aaa999a
# 6665556777777899998878988888899999999887777656666543222233446899aa999a
# 6655456777777899999888988888889999a988887776566666532222233457899a999a
# 665555677777789999998998888878899aa9888887765666655322222234578899aa9a
# 665555677777789999a98888888877899aa9888887766666655322222234467899aa9a
# 65666677667778999aaa988878877789aaa9888887776676654322222344467889aa9a
# 55566677767788899aaa987777777789aaa9888887776666654322222344567889aaa9
# 5566767777788889aaaa987777777789aaaa988887777666555432122344556899aaa9
# 5567777777788889aaaa977777777789aaaa99888777766555543212234555689aaaaa
# 5667877777889989aaa9876677777889aaaa99888777765554443212334555689aaaaa
# ~~~
class PerlinNoise
	super Noise

	# Desired number of `layers`
	#
	# This attribute must be assigned before any call to `layers` or `[]`.
	#
	# By default, it is the highest integer under the logarithm base 2
	# of `amplitude`, or 4, whichever is the highest.
	var n_layers: Int = 4.max(amplitude.abs.log_base(2.0).to_i) is lazy, writable

	# Layers of `InterpolatedNoise` composing `self`
	var layers: Array[InterpolatedNoise] is lazy do
		var layers = new Array[InterpolatedNoise]

		var max = max
		var min = min
		var period = period
		var seed = seed
		for l in n_layers.times do
			min = min / 2.0
			max = max / 2.0
			seed = pseudo_random(seed)

			var layer = new InterpolatedNoise
			layer.min = min
			layer.max = max
			layer.period = period
			layer.seed = seed
			layers.add layer

			period = period / 2.0
		end
		return layers
	end

	redef fun [](x, y)
	do
		var val = 0.0
		for layer in layers do
			val += layer[x, y]
		end
		return val
	end

	# Deterministic pseudo random number generator
	#
	# Used to get seeds for layers from the previous layers or `seed`.
	protected fun pseudo_random(value: Int): Int
	do
		return (value * 3537391).mask % 1291377
	end
end
lib/noise/noise.nit:72,1--202,3