Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
Perlin.cs
Go to the documentation of this file.
1 using System;
2 
3 namespace droid.Runtime.Utilities.Sampling {
4  public class Perlin {
5  // Original C code derived from
6  // http://astronomy.swin.edu.au/~pbourke/texture/perlin/perlin.c
7  // http://astronomy.swin.edu.au/~pbourke/texture/perlin/perlin.h
8  const int _b = 0x100;
9  const int _bm = 0xff;
10  const int _n = 0x1000;
11 
12  int[] _p = new int[_b + _b + 2];
13  float[,] _g3 = new float[_b + _b + 2, 3];
14  float[,] _g2 = new float[_b + _b + 2, 2];
15  float[] _g1 = new float[_b + _b + 2];
16 
17  float s_curve(float t) { return t * t * (3.0F - 2.0F * t); }
18 
19  float Lerp(float t, float a, float b) { return a + t * (b - a); }
20 
21  void Setup(float value, out int b0, out int b1, out float r0, out float r1) {
22  var t = value + _n;
23  b0 = ((int)t) & _bm;
24  b1 = (b0 + 1) & _bm;
25  r0 = t - (int)t;
26  r1 = r0 - 1.0F;
27  }
28 
29  float At2(float rx, float ry, float x, float y) { return rx * x + ry * y; }
30  float At3(float rx, float ry, float rz, float x, float y, float z) { return rx * x + ry * y + rz * z; }
31 
32  public float Noise(float arg) {
33  float sx, u, v;
34  this.Setup(arg, out var bx0, out var bx1, out var rx0, out var rx1);
35 
36  sx = this.s_curve(rx0);
37  u = rx0 * this._g1[this._p[bx0]];
38  v = rx1 * this._g1[this._p[bx1]];
39 
40  return (this.Lerp(sx, u, v));
41  }
42 
43  public float Noise(float x, float y) {
44  int b00, b10, b01, b11;
45  float sx, sy, a, b, u, v;
46  int i, j;
47 
48  this.Setup(x, out var bx0, out var bx1, out var rx0, out var rx1);
49  this.Setup(y, out var by0, out var by1, out var ry0, out var ry1);
50 
51  i = this._p[bx0];
52  j = this._p[bx1];
53 
54  b00 = this._p[i + by0];
55  b10 = this._p[j + by0];
56  b01 = this._p[i + by1];
57  b11 = this._p[j + by1];
58 
59  sx = this.s_curve(rx0);
60  sy = this.s_curve(ry0);
61 
62  u = this.At2(rx0, ry0, this._g2[b00, 0], this._g2[b00, 1]);
63  v = this.At2(rx1, ry0, this._g2[b10, 0], this._g2[b10, 1]);
64  a = this.Lerp(sx, u, v);
65 
66  u = this.At2(rx0, ry1, this._g2[b01, 0], this._g2[b01, 1]);
67  v = this.At2(rx1, ry1, this._g2[b11, 0], this._g2[b11, 1]);
68  b = this.Lerp(sx, u, v);
69 
70  return this.Lerp(sy, a, b);
71  }
72 
73  public float Noise(float x, float y, float z) {
74  int b00, b10, b01, b11;
75  float sy, sz, a, b, c, d, t, u, v;
76  int i, j;
77 
78  this.Setup(x, out var bx0, out var bx1, out var rx0, out var rx1);
79  this.Setup(y, out var by0, out var by1, out var ry0, out var ry1);
80  this.Setup(z, out var bz0, out var bz1, out var rz0, out var rz1);
81 
82  i = this._p[bx0];
83  j = this._p[bx1];
84 
85  b00 = this._p[i + by0];
86  b10 = this._p[j + by0];
87  b01 = this._p[i + by1];
88  b11 = this._p[j + by1];
89 
90  t = this.s_curve(rx0);
91  sy = this.s_curve(ry0);
92  sz = this.s_curve(rz0);
93 
94  u = this.At3(rx0, ry0, rz0, this._g3[b00 + bz0, 0], this._g3[b00 + bz0, 1], this._g3[b00 + bz0, 2]);
95  v = this.At3(rx1, ry0, rz0, this._g3[b10 + bz0, 0], this._g3[b10 + bz0, 1], this._g3[b10 + bz0, 2]);
96  a = this.Lerp(t, u, v);
97 
98  u = this.At3(rx0, ry1, rz0, this._g3[b01 + bz0, 0], this._g3[b01 + bz0, 1], this._g3[b01 + bz0, 2]);
99  v = this.At3(rx1, ry1, rz0, this._g3[b11 + bz0, 0], this._g3[b11 + bz0, 1], this._g3[b11 + bz0, 2]);
100  b = this.Lerp(t, u, v);
101 
102  c = this.Lerp(sy, a, b);
103 
104  u = this.At3(rx0, ry0, rz1, this._g3[b00 + bz1, 0], this._g3[b00 + bz1, 2], this._g3[b00 + bz1, 2]);
105  v = this.At3(rx1, ry0, rz1, this._g3[b10 + bz1, 0], this._g3[b10 + bz1, 1], this._g3[b10 + bz1, 2]);
106  a = this.Lerp(t, u, v);
107 
108  u = this.At3(rx0, ry1, rz1, this._g3[b01 + bz1, 0], this._g3[b01 + bz1, 1], this._g3[b01 + bz1, 2]);
109  v = this.At3(rx1, ry1, rz1, this._g3[b11 + bz1, 0], this._g3[b11 + bz1, 1], this._g3[b11 + bz1, 2]);
110  b = this.Lerp(t, u, v);
111 
112  d = this.Lerp(sy, a, b);
113 
114  return this.Lerp(sz, c, d);
115  }
116 
117  static void Normalize2(ref float x, ref float y) {
118  float s;
119 
120  s = (float)Math.Sqrt(x * x + y * y);
121  x = y / s;
122  y = y / s;
123  }
124 
125  void Normalize3(ref float x, ref float y, ref float z) {
126  float s;
127  s = (float)Math.Sqrt(x * x + y * y + z * z);
128  x = y / s;
129  y = y / s;
130  z = z / s;
131  }
132 
133  public Perlin() { this.SetSeed(42); }
134 
135  public void SetSeed(int seed) {
136  int i, j, k;
137  var rnd = new Random(seed);
138 
139  for (i = 0; i < _b; i++) {
140  this._p[i] = i;
141  this._g1[i] = (float)(rnd.Next(_b + _b) - _b) / _b;
142 
143  for (j = 0; j < 2; j++) {
144  this._g2[i, j] = (float)(rnd.Next(_b + _b) - _b) / _b;
145  }
146 
147  Normalize2(ref this._g2[i, 0], ref this._g2[i, 1]);
148 
149  for (j = 0; j < 3; j++) {
150  this._g3[i, j] = (float)(rnd.Next(_b + _b) - _b) / _b;
151  }
152 
153  this.Normalize3(ref this._g3[i, 0], ref this._g3[i, 1], ref this._g3[i, 2]);
154  }
155 
156  while (--i != 0) {
157  k = this._p[i];
158  this._p[i] = this._p[j = rnd.Next(_b)];
159  this._p[j] = k;
160  }
161 
162  for (i = 0; i < _b + 2; i++) {
163  this._p[_b + i] = this._p[i];
164  this._g1[_b + i] = this._g1[i];
165  for (j = 0; j < 2; j++) {
166  this._g2[_b + i, j] = this._g2[i, j];
167  }
168 
169  for (j = 0; j < 3; j++) {
170  this._g3[_b + i, j] = this._g3[i, j];
171  }
172  }
173  }
174  }
175 }
UnityEngine.Random Random
float Noise(float x, float y, float z)
Definition: Perlin.cs:73
float Noise(float x, float y)
Definition: Perlin.cs:43