indexing description: "2D Perlin Noise" author: "Urs Doenni" date: "$Date$" revision: "$Revision$" class EM_2D_PERLIN_NOISE inherit EM_2D_PROCEDURE EM_PERLIN_NOISE create make, make_with_interpolator feature make_with_interpolator (an_interpolator: EM_INTERPOLATOR) is -- create the object using some interpololator do make set_interpolator (an_interpolator) end evaluate_at(eval_at: EM_VECTOR2D): DOUBLE is -- Evaluate 2D perlin noise at 'x', 'y' local oct: INTEGER do Result := 0.0 from oct := 1 until oct > num_of_octaves loop Result := Result + perlin_noise (eval_at.x, eval_at.y, oct) oct := oct + 1 end end set_repeat_at(a_repeat: EM_VECTOR2I) is -- repeat perlin noise after -- x in x-direction and after -- y in y-direction -- If x or y are 0, then the procedure isn't repeated in this direction require valid_x: repeat.x >= 0 valid_y: repeat.y >= 0 do repeat := a_repeat ensure repeat_set: repeat = a_repeat end repeat: EM_VECTOR2I feature perlin_noise(x, y: DOUBLE; an_octave: INTEGER): DOUBLE is -- compute perlin noise octave 'an_octave' at (x,y) require octave_valid: an_octave >= 1 local fraq_x, fraq_y: DOUBLE int_x, int_y: INTEGER nx0y0, nx0y1, nx1y0, nx1y1: DOUBLE ix0, ix1: DOUBLE factor: DOUBLE amplitude: DOUBLE mod_x, mod_y: INTEGER do factor := 2 ^ (an_octave - 1).to_double amplitude := persistence ^ (an_octave - 1).to_double mod_x := (repeat.x * factor).floor mod_y := (repeat.y * factor).floor int_x := (x * factor).floor int_y := (y * factor).floor fraq_x := (x * factor) - int_x fraq_y := (y * factor) - int_y int_x := modulo(int_x, mod_x) int_y := modulo(int_y, mod_y) nx0y0 := get_noise (int_x, int_y) nx0y1 := get_noise (int_x, modulo((int_y + 1), mod_y)) nx1y0 := get_noise (modulo((int_x + 1), mod_x), int_y) nx1y1 := get_noise (modulo((int_x + 1), mod_x), modulo((int_y + 1), mod_y)) ix0 := interpolator.interpolate (nx0y0, nx1y0, fraq_x) ix1 := interpolator.interpolate (nx0y1, nx1y1, fraq_x) Result := (interpolator.interpolate (ix0, ix1, fraq_y) * amplitude) ensure Result_valid: Result >= 0 and Result <= 1.0 end get_noise(an_x, an_y: INTEGER): DOUBLE is -- returns an integer value between 0 and largest_noise local x, y: INTEGER tmp_x, tmp_y: INTEGER do x := an_x y := an_y tmp_y := perm_array.item(modulo(y, random_size).abs) tmp_x := perm_array.item(modulo(x + tmp_y, random_size).abs) Result := random_array.item (modulo(tmp_x, random_size).abs) * noise_factor ensure Result >= 0 and Result <= 1.0 end end