Noise Function

BlitzMax Forums/BlitzMax Programming/Noise Function

Scienthsine(Posted 2008) [#1]
I need to use some perlin noise for something I'm working on, and using the simple noise function on this site: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm I seem to have problems...

I converted the pseudocode to this in max:
	Function noise:Float(x:Int) 
		x = (x Shl 13) ^ x
		Return (1.0 - ((x * (x * x * 15731 + 789221) + 1376312589) & $7fffffff) / 1073741824.0) 
	End Function


The problem seems to be that the '^x' bit will hit a max value and start only returning that. I think the original algorithm requires that the appropriate rollover effects of an integer power function take place.

Any ideas anyone, or another noise function?


Yeshu777(Posted 2008) [#2]
Try...


x = (x Shl 13) ~ x




sswift(Posted 2008) [#3]
Click my name and look at my code archives entries, I'm pretty sure I posted some functions to do perlin noise in Blitz 3D. Should be easy to convert to Max. I forget if it works with floats or ints. I think I just used ints and kept doubling them and scaled the result to the range I needed.


Scienthsine(Posted 2008) [#4]
Ya, I found a few blitz/perlin examples. I guess it doesn't really matter, I should be able to use rnd just fine if I store the results in an array and then use that as my 'psuedo random function'.


Wiering(Posted 2008) [#5]
Here is a version I ported from C code (only 1D and 2D). I added the NoiseSize variables to set where the pattern repeats.

Strict

Import brl.random

' Perlin Noise

Type TPerlin
	Field NoiseSizeX: Int
	Field NoiseSizeY: Int
	Field NoiseSizeZ: Int

	Const BN = $100
	Const BM = $FF
	Const N = $1000
	Const NP = 12 ' 2^N
	Const NM = $FFF

	Field p: Int[BN + BN + 2]
	Field g1: Double[BN + BN + 2]
	Field g2: Double[BN + BN + 2, 2]

    Const DEFAULT_NOISE_SIZE = $10000

	Method Init (XS: Int = 0, YS: Int = 0, ZS: Int = 0)	
	  Local i: Int, j: Int, k: Int
	  Local s: Double

      If XS <= 0 Then XS = DEFAULT_NOISE_SIZE
      If YS <= 0 Then YS = DEFAULT_NOISE_SIZE
      If ZS <= 0 Then ZS = DEFAULT_NOISE_SIZE

	  NoiseSizeX = XS
	  NoiseSizeY = YS
	  NoiseSizeZ = ZS

	  For i = 0 To BN - 1 
	    p[i] = i
	    g1[i] = Double (Rand (0, BN + BN - 1) - BN) / BN
	    For j = 0 To 1
	      g2[i, j] = Double (Rand (0, BN + BN - 1) - BN) / BN
	    Next
	    s = Sqr (g2[i, 0] * g2[i, 0] + g2[i, 1] * g2[i, 1])
	    g2[i, 0] = g2[i, 0] / s
	    g2[i, 1] = g2[i, 1] / s
	  Next
	  For i = BN - 1 To 0 Step -1
	    k = p[i]
	    j = Rand (0, BN - 1)
	    p[i] = p[j]
	    p[j] = k
	  Next
	  For i = 0 To BN + 1
	    p[BN + i] = p[i]
	    g1[BN + i] = g1[i]
	    For j = 0 To 1 
	      g2[BN + i, j] = g2[i, j]
	    Next
	  Next
	End Method

	Method S_Curve: Double (t: Double)
	  Return t * t * (3.0 - 2.0 * t)
	End Method

	Method Lerp: Double (t: Double, a: Double, b: Double)
	  Return a + t * (b - a)
	End Method

	Method Noise1: Double (x: Double)
	  Local t: Double = x + N
	  Local bx0: Int = Int (Floor (t) Mod NoiseSizeX) & BM
	  Local bx1: Int = Int ((bx0 + 1) Mod NoiseSizeX) & BM
	  Local rx0: Double = t - (Floor (t))
	  Local rx1: Double = rx0 - 1.0
	  Local sx: Double = s_curve (rx0)
	  Local u: Double = rx0 * g1[p[bx0]]
	  Local v: Double = rx1 * g1[p[bx1]]
	  Local c: Double = 0.5 + Lerp (sx, u, v)
	  If c < 0.0 Then c = 0.0 Else If c > 0.99999999 Then c = 0.99999999
	  Return c
	End Method

	Method Noise2: Double (x: Double, y: Double)
	  Local t: Double = Double (x + N)
	  Local bx0: Int = Int (Floor (t) Mod NoiseSizeX) & BM
	  Local bx1: Int = Int ((bx0 + 1) Mod NoiseSizeX) & BM
	  Local rx0: Double = t - (Floor (t))
	  Local rx1: Double = rx0 - 1.0
	  t = y + N
	  Local by0: Int = Int (Floor (t) Mod NoiseSizeY) & BM
	  Local by1: Int = Int ((by0 + 1) Mod NoiseSizeY) & BM
	  Local ry0: Double = t - (Floor (t))
	  Local ry1: Double = ry0 - 1.0
	  Local i: Int = p[bx0]
	  Local j: Int = p[bx1]
	  Local b00: Int = p[i + by0]
	  Local b10: Int = p[j + by0]
	  Local b01: Int = p[i + by1]
	  Local b11: Int = p[j + by1]
	  Local sx: Double = s_curve (rx0)
	  Local sy: Double = s_curve (ry0)
	  Local u: Double = rx0 * g2[b00, 0] + ry0 * g2[b00, 1]
	  Local v: Double = rx1 * g2[b10, 0] + ry0 * g2[b10, 1]
	  Local a: Double = lerp (sx, u, v)
	  u = rx0 * g2[b01, 0] + ry1 * g2[b01, 1]
	  v = rx1 * g2[b11, 0] + ry1 * g2[b11, 1]
	  Local b: Double = Lerp (sx, u, v)
	  Local c: Double = 0.5 + Lerp (sy, a, b)
	  If c < 0.0 Then c = 0.0 Else If c > 0.99999999 Then c = 0.99999999
	  Return c
	End Method

End Type


And here is a small example:

Strict
Import brl.random
Import "Perlin.bmx"

Const SCREEN_WIDTH = 320
Const SCREEN_HEIGHT = 240

Local i: Int, j: Int
Local r: Int, g: Int, b: Int
Local f: Double
Local x: Double, y: Double
Local u: Double, v: Double
Local Perlin: TPerlin = New TPerlin
Perlin.Init (10, 10, 10)

x = 0.0
y = 0.0

Graphics SCREEN_WIDTH, SCREEN_HEIGHT
Repeat
  For j = 0 To SCREEN_HEIGHT - 1
    For i = 0 To SCREEN_WIDTH - 1
      u = Float (i) / 100.0
      v = Float (j) / 100.0
      f = Perlin.Noise2 (x + u, y + v)
      r = f * 128.0
      g = 128 - f * 128.0
      b = f * 255.0
      SetColor r, g, b
      DrawRect (i, j, 1, 1)
    Next
  Next
  Flip ()
  x :+ 0.1
  y :+ 0.1
Until AppTerminate () Or KeyHit (KEY_ESCAPE)
EndGraphics