Perlin Noise

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
Line 1: Line 1:
 +
== Description ==
 +
 +
The following snippet shows how to smoothly randomly move a transform around.
 +
 +
== Usage ==
 +
 +
Add this script anywhere in your project folder.
 +
Attach the javascript to any transform to make that transform smoothly and randomly move around.
 +
 
<javascript>
 
<javascript>
 
// Moves the object along as far as range units randomly but in a smooth way.
 
// Moves the object along as far as range units randomly but in a smooth way.
Line 18: Line 27:
 
</javascript>
 
</javascript>
  
 +
 +
Place this script in a folder called Plugins as a sub folder of the Assets folder. This will allow you to access the PerlinNoise class which is written in C# from Javascript.
  
 
<csharp>
 
<csharp>

Revision as of 20:54, 14 April 2006

Description

The following snippet shows how to smoothly randomly move a transform around.

Usage

Add this script anywhere in your project folder. Attach the javascript to any transform to make that transform smoothly and randomly move around.

<javascript> // Moves the object along as far as range units randomly but in a smooth way. // This script requires the Noise.cs script. var speed = 1.0; var range = Vector3 (1.0, 1.0, 1.0);

private var noise = new Noise(); private var position : Vector3;

function Start() { position = transform.position; }

function Update () { transform.position = position + Vector3.Scale(SmoothRandom.GetVector3(speed), range); } </javascript>


Place this script in a folder called Plugins as a sub folder of the Assets folder. This will allow you to access the PerlinNoise class which is written in C# from Javascript.

<csharp> using System.Collections; using System; using UnityEngine;

public class Perlin { const int B = 0x100; const int BM = 0xff; const int N = 0x1000;

int[] p = new int[B + B + 2]; float[,] g3 = new float [B + B + 2 , 3]; float[,] g2 = new float[B + B + 2,2]; float[] g1 = new float[B + B + 2];

float s_curve(float t) { return t * t * (3.0F - 2.0F * t); }

float lerp (float t, float a, float b) { return a + t * (b - a); }

void setup (float value, out int b0, out int b1, out float r0, out float r1) {

       float t = value + N;
       b0 = ((int)t) & BM;
       b1 = (b0+1) & BM;
       r0 = t - (int)t;
       r1 = r0 - 1.0F;

}

float at2(float rx, float ry, float x, float y) { return rx * x + ry * y; }

public float Noise1D(float arg) { int bx0, bx1; float rx0, rx1, sx, u, v; setup(arg, out bx0, out bx1, out rx0, out rx1);

sx = s_curve(rx0); u = rx0 * g1[ p[ bx0 ] ]; v = rx1 * g1[ p[ bx1 ] ];

return(lerp(sx, u, v)); }

public float Noise2D(float x, float y) { int bx0, bx1, by0, by1, b00, b10, b01, b11; float rx0, rx1, ry0, ry1, sx, sy, a, b, u, v; int i, j;

setup(x, out bx0, out bx1, out rx0, out rx1); setup(y, out by0, out by1, out ry0, out ry1);

i = p[ bx0 ]; j = p[ bx1 ];

b00 = p[ i + by0 ]; b10 = p[ j + by0 ]; b01 = p[ i + by1 ]; b11 = p[ j + by1 ];

sx = s_curve(rx0); sy = s_curve(ry0);

u = at2(rx0,ry0, g2[ b00, 0 ], g2[ b00, 1 ]); v = at2(rx1,ry0, g2[ b10, 0 ], g2[ b10, 1 ]); a = lerp(sx, u, v);

u = at2(rx0,ry1, g2[ b01, 0 ], g2[ b01, 1 ]); v = at2(rx1,ry1, g2[ b11, 0 ], g2[ b11, 1 ]); b = lerp(sx, u, v);

return lerp(sy, a, b); } /* double noise3(double vec[3]) { int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v; int i, j;

if (start) { start = 0; init(); }

setup(0, bx0,bx1, rx0,rx1); setup(1, by0,by1, ry0,ry1); setup(2, bz0,bz1, rz0,rz1);

i = p[ bx0 ]; j = p[ bx1 ];

b00 = p[ i + by0 ]; b10 = p[ j + by0 ]; b01 = p[ i + by1 ]; b11 = p[ j + by1 ];

t = s_curve(rx0); sy = s_curve(ry0); sz = s_curve(rz0);

q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0); q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0); a = lerp(t, u, v);

q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0); q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0); b = lerp(t, u, v);

c = lerp(sy, a, b);

q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1); q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1); a = lerp(t, u, v);

q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1); q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1); b = lerp(t, u, v);

d = lerp(sy, a, b);

return lerp(sz, c, d); } */ void normalize2(ref float x, ref float y) { float s;

s = (float)Math.Sqrt(x * x + y * y); x = y / s; y = y / s; }

void normalize3(ref float x, ref float y, ref float z) { float s; s = (float)Math.Sqrt(x * x + y * y + z * z); x = y / s; y = y / s; z = z / s; }

public Perlin() { int i, j, k; System.Random rnd = new System.Random();

for (i = 0 ; i < B ; i++) { p[i] = i; g1[i] = (float)(rnd.Next(B + B) - B) / B;

for (j = 0 ; j < 2 ; j++) g2[i,j] = (float)(rnd.Next(B + B) - B) / B; normalize2(ref g2[i, 0], ref g2[i, 1]);

for (j = 0 ; j < 3 ; j++) g3[i,j] = (float)(rnd.Next(B + B) - B) / B;


normalize3(ref g3[i, 0], ref g3[i, 1], ref g3[i, 2]); }

while (--i != 0) { k = p[i]; p[i] = p[j = rnd.Next(B)]; p[j] = k; }

for (i = 0 ; i < B + 2 ; i++) { p[B + i] = p[i]; g1[B + i] = g1[i]; for (j = 0 ; j < 2 ; j++) g2[B + i,j] = g2[i,j]; for (j = 0 ; j < 3 ; j++) g3[B + i,j] = g3[i,j]; } } }


public class SmoothRandom { public static Vector3 GetVector3 (float speed) { float time = Time.time * 0.01F * speed; return new Vector3(Get().HybridMultifractal(time, 15.73F, 0.65F), Get().HybridMultifractal(time, 63.94F, 0.65F), Get().HybridMultifractal(time, 0.2F, 0.65F)); }

public static float Get (float speed) { float time = Time.time * 0.01F * speed; return Get().HybridMultifractal(time * 0.01F, 15.7F, 0.65F); }

private static FractalNoise Get () { if (s_Noise == null) s_Noise = new FractalNoise (1.27F, 2.06F, 8.36F); return s_Noise; }

private static FractalNoise s_Noise; }


public class FractalNoise { public FractalNoise (float inH, float inLacunarity, float inOctaves) : this (inH, inLacunarity, inOctaves, null) {

}

public FractalNoise (float inH, float inLacunarity, float inOctaves, Perlin noise) { m_Lacunarity = inLacunarity; m_Octaves = inOctaves; m_IntOctaves = (int)inOctaves; m_Exponent = new float[m_IntOctaves+1]; float frequency = 1.0F; for (int i = 0; i < m_IntOctaves+1; i++) { m_Exponent[i] = (float)Math.Pow (m_Lacunarity, -inH); frequency *= m_Lacunarity; }

if (noise == null) m_Noise = new Perlin(); else m_Noise = noise; }


public float HybridMultifractal(float x, float y, float offset) { float weight, signal, remainder, result;

result = (m_Noise.Noise2D (x, y)+offset) * m_Exponent[0]; weight = result; x *= m_Lacunarity; y *= m_Lacunarity; int i; for (i=1;i<m_IntOctaves;i++) { if (weight > 1.0F) weight = 1.0F; signal = (m_Noise.Noise2D (x, y) + offset) * m_Exponent[i]; result += weight * signal; weight *= signal; x *= m_Lacunarity; y *= m_Lacunarity; } remainder = m_Octaves - m_IntOctaves; if (remainder != 0.0F) result += remainder * m_Noise.Noise2D (x,y) * m_Exponent[i];

return result; }

Perlin m_Noise; float[] m_Exponent; int m_IntOctaves; float m_Octaves; float m_Lacunarity; }


public class Noise { public float Noise1D(float x) { return Noise2D(x, 0.5F); }

public float Noise2D(float x, float y) { int Xint = (int)x; int Yint = (int)y; float Xfrac = x - Xint; float Yfrac = y - Yint;

float x0y0 = Smooth_Noise(Xint, Yint); //find the noise values of the four corners float x1y0 = Smooth_Noise(Xint+1, Yint); float x0y1 = Smooth_Noise(Xint, Yint+1); float x1y1 = Smooth_Noise(Xint+1, Yint+1);

//interpolate between those values according to the x and y fractions float v1 = Interpolate(x0y0, x1y0, Xfrac); //interpolate in x direction (y) float v2 = Interpolate(x0y1, x1y1, Xfrac); //interpolate in x direction (y+1) float fin = Interpolate(v1, v2, Yfrac); //interpolate in y direction

return fin; }

private float Interpolate(float x, float y, float a) { float b = 1-a; float fac1 = (float)(3*b*b - 2*b*b*b); float fac2 = (float)(3*a*a - 2*a*a*a);

return x*fac1 + y*fac2; //add the weighted factors }

protected float GetRandomValue(int x, int y) { x = (x+m_nNoiseWidth) % m_nNoiseWidth; y = (y+m_nNoiseHeight) % m_nNoiseHeight; float fVal = (float)m_aNoise[(int)(m_fScaleX*x), (int)(m_fScaleY*y)]; return fVal/255*2-1f; }

private float Smooth_Noise(int x, int y) { float corners = ( Noise2d(x-1, y-1) + Noise2d(x+1, y-1) + Noise2d(x-1, y+1) + Noise2d(x+1, y+1) ) / 16.0f; float sides = ( Noise2d(x-1, y) +Noise2d(x+1, y) + Noise2d(x, y-1) + Noise2d(x, y+1) ) / 8.0f; float center = Noise2d(x, y) / 4.0f; return corners + sides + center; }

public float Noise2d(int x, int y) { x = (x+m_nNoiseWidth) % m_nNoiseWidth; y = (y+m_nNoiseHeight) % m_nNoiseHeight;

float fVal = (float)m_aNoise[(int)(m_fScaleX*x), (int)(m_fScaleY*y)];

return fVal/255*2-1f; }

public Noise() { m_nNoiseWidth = 100; m_nNoiseHeight = 100; m_fScaleX = 1.0F; m_fScaleY = 1.0F; System.Random rnd = new System.Random(); m_aNoise = new int[m_nNoiseWidth,m_nNoiseHeight]; for (int x = 0; x<m_nNoiseWidth; x++) { for (int y = 0; y<m_nNoiseHeight; y++) { m_aNoise[x,y] = rnd.Next(255); } } }

private int[,] m_aNoise; protected int m_nNoiseWidth, m_nNoiseHeight; private float m_fScaleX, m_fScaleY; }


/* float noise1[]; float noise2[]; float noise3[]; int indices[];

float PerlinSmoothStep (float t) { return t * t * (3.0f - 2.0f * t); }

float PerlinLerp(float t, float a, float b) { return a + t * (b - a); }

float PerlinRand() { return Random.rand () / float(RAND_MAX) * 2.0f - 1.0f; }


PerlinNoise::PerlinNoise () { long i, j, k; float x, y, z, denom;

Random rnd = new Random();


noise1 = new float[1 * (PERLIN_B + PERLIN_B + 2)]; noise2 = new float[2 * (PERLIN_B + PERLIN_B + 2)]; noise3 = new float[3 * (PERLIN_B + PERLIN_B + 2)]; indices = new long[PERLIN_B + PERLIN_B + 2];

for (i = 0; i < PERLIN_B; i++) { indices[i] = i;

x = PerlinRand(); y = PerlinRand(); z = PerlinRand();

noise1[i] = x;

denom = sqrt(x * x + y * y); if (denom > 0.0001f) denom = 1.0f / denom;

j = i << 1; noise2[j + 0] = x * denom; noise2[j + 1] = y * denom;

denom = sqrt(x * x + y * y + z * z); if (denom > 0.0001f) denom = 1.0f / denom;

j += i; noise3[j + 0] = x * denom; noise3[j + 1] = y * denom; noise3[j + 2] = z * denom; }

while (--i != 0) { j = rand() & PERLIN_BITMASK; std::swap (indices[i], indices[j]); }

for (i = 0; i < PERLIN_B + 2; i++) { j = i + PERLIN_B;

indices[j] = indices[i];

noise1[j] = noise1[i];

j = j << 1; k = i << 1; noise2[j + 0] = noise2[k + 0]; noise2[j + 1] = noise2[k + 1];

j += i + PERLIN_B; k += i + PERLIN_B; noise3[j + 0] = noise3[k + 0]; noise3[j + 1] = noise3[k + 1]; noise3[j + 2] = noise3[k + 2]; } }

PerlinNoise::~PerlinNoise () { delete []noise1; delete []noise2; delete []noise3; delete []indices; }

void PerlinSetup (float v, long& b0, long& b1, float& r0, float& r1); void PerlinSetup( float v, long& b0, long& b1, float& r0, float& r1) { v += PERLIN_N;

long vInt = (long)v;

b0 = vInt & PERLIN_BITMASK; b1 = (b0 + 1) & PERLIN_BITMASK; r0 = v - (float)vInt; r1 = r0 - 1.0f; }


float PerlinNoise::Noise1 (float x) { long bx0, bx1; float rx0, rx1, sx, u, v;

PerlinSetup(x, bx0, bx1, rx0, rx1);

sx = PerlinSmoothStep(rx0);

u = rx0 * noise1[indices[bx0]]; v = rx1 * noise1[indices[bx1]];

return PerlinLerp (sx, u, v); }

float PerlinNoise::Noise2(float x, float y) { long bx0, bx1, by0, by1, b00, b01, b10, b11; float rx0, rx1, ry0, ry1, sx, sy, u, v, a, b;

PerlinSetup (x, bx0, bx1, rx0, rx1); PerlinSetup (y, by0, by1, ry0, ry1);

sx = PerlinSmoothStep (rx0); sy = PerlinSmoothStep (ry0);

b00 = indices[indices[bx0] + by0] << 1; b10 = indices[indices[bx1] + by0] << 1; b01 = indices[indices[bx0] + by1] << 1; b11 = indices[indices[bx1] + by1] << 1;

u = rx0 * noise2[b00 + 0] + ry0 * noise2[b00 + 1]; v = rx1 * noise2[b10 + 0] + ry0 * noise2[b10 + 1]; a = PerlinLerp (sx, u, v);

u = rx0 * noise2[b01 + 0] + ry1 * noise2[b01 + 1]; v = rx1 * noise2[b11 + 0] + ry1 * noise2[b11 + 1]; b = PerlinLerp (sx, u, v);

u = PerlinLerp (sy, a, b);

return u; }

float PerlinNoise::Noise3(float x, float y, float z) { long bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;

PerlinSetup (x, bx0, bx1, rx0, rx1); PerlinSetup (y, by0, by1, ry0, ry1); PerlinSetup (z, bz0, bz1, rz0, rz1);

b00 = indices[indices[bx0] + by0] << 1; b10 = indices[indices[bx1] + by0] << 1; b01 = indices[indices[bx0] + by1] << 1; b11 = indices[indices[bx1] + by1] << 1;

t = PerlinSmoothStep (rx0); sy = PerlinSmoothStep (ry0); sz = PerlinSmoothStep (rz0);

#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )

q = &noise3[b00 + bz0]; u = at3(rx0,ry0,rz0); q = &noise3[b10 + bz0]; v = at3(rx1,ry0,rz0); a = PerlinLerp(t, u, v);

q = &noise3[b01 + bz0]; u = at3(rx0,ry1,rz0); q = &noise3[b11 + bz0]; v = at3(rx1,ry1,rz0); b = PerlinLerp(t, u, v);

c = PerlinLerp(sy, a, b);

q = &noise3[b00 + bz1]; u = at3(rx0,ry0,rz1); q = &noise3[b10 + bz1]; v = at3(rx1,ry0,rz1); a = PerlinLerp(t, u, v);

q = &noise3[b01 + bz1]; u = at3(rx0,ry1,rz1); q = &noise3[b11 + bz1]; v = at3(rx1,ry1,rz1); b = PerlinLerp(t, u, v);

d = PerlinLerp(sy, a, b);

return PerlinLerp (sz, c, d); }

  • /

</csharp>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox