2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Classes and function for generation of PerlinNoise.
8
17/11/14 - PW - Refactored TPerlin3DNoise to TGLPerlin3DNoise, renamed unit
9
31/08/10 - Bugfixed range error in TPerlin3DNoise.Initialize
10
30/03/07 - DaStr - Added $I GLScene.inc
11
14/04/04 - EG - Creation
14
Loosely based on Tom Nuydens's (www.delphi3d.com) Noise.pas unit, itself based on
15
http://students.vassar.edu/mazucker/code/perlin-noise-math-faq.html
16
Darwin Peachey's chapter in "Texturing & Modeling: A Procedural Approach"
17
Further bugs are mine :)
29
cPERLIN_TABLE_SIZE = 256; // must be a power of two
35
{ Generates Perlin Noise in the [-1; 1] range.
36
2D noise requests are taken in the Z=0 slice }
37
TGLPerlin3DNoise = class (TObject)
40
FPermutations : packed array [0..cPERLIN_TABLE_SIZE-1] of Integer;
41
FGradients : packed array [0..cPERLIN_TABLE_SIZE*3-1] of Single;
45
function Lattice(ix, iy, iz : Integer; fx, fy, fz : Single) : Single; overload;
46
function Lattice(ix, iy : Integer; fx, fy : Single) : Single; overload;
50
constructor Create(randomSeed : Integer);
51
procedure Initialize(randomSeed : Integer);
53
function Noise(const x, y : Single) : Single; overload;
54
function Noise(const x, y, z : Single) : Single; overload;
55
function Noise(const v : TAffineVector) : Single; overload;
56
function Noise(const v : TVector) : Single; overload;
59
// ------------------------------------------------------------------
60
// ------------------------------------------------------------------
61
// ------------------------------------------------------------------
64
// ------------------------------------------------------------------
65
// ------------------------------------------------------------------
66
// ------------------------------------------------------------------
69
// ------------------ TGLPerlin3DNoise ------------------
74
constructor TGLPerlin3DNoise.Create(randomSeed : Integer);
77
Initialize(randomSeed);
82
procedure TGLPerlin3DNoise.Initialize(randomSeed : Integer);
84
seedBackup : Cardinal;
91
// Generate random gradient vectors.
92
for i:=0 to cPERLIN_TABLE_SIZE-1 do begin
95
SinCos(c2PI*Random, r, FGradients[i*3], FGradients[i*3+1]);
98
// Initialize permutations table
99
for i:=0 to cPERLIN_TABLE_SIZE-1 do
102
for i:=0 to cPERLIN_TABLE_SIZE-1 do begin
103
j:=Random(cPERLIN_TABLE_SIZE);
105
FPermutations[i]:=FPermutations[j];
109
RandSeed:=seedBackup;
114
function TGLPerlin3DNoise.Lattice(ix, iy, iz : Integer; fx, fy, fz : Single): Single;
116
cMask = cPERLIN_TABLE_SIZE-1;
120
g:=FPermutations[(ix+FPermutations[(iy+FPermutations[iz and cMask]) and cMask]) and cMask]*3;
121
Result:=FGradients[g]*fx+FGradients[g+1]*fy+FGradients[g+2]*fz;
126
function TGLPerlin3DNoise.Lattice(ix, iy : Integer; fx, fy : Single): Single;
128
cMask = cPERLIN_TABLE_SIZE-1;
132
g:=FPermutations[(ix+FPermutations[(iy+FPermutations[0]) and cMask]) and cMask]*3;
133
Result:=FGradients[g]*fx+FGradients[g+1]*fy;
138
function TGLPerlin3DNoise.Noise(const v : TAffineVector) : Single;
140
function Smooth(var x : Single) : Single;
146
ix, iy, iz : Integer;
147
fx0, fx1, fy0, fy1, fz0, fz1 : Single;
149
vy0, vy1, vz0, vz1 : Single;
166
vy0:=Lerp(Lattice(ix, iy, iz, fx0, fy0, fz0),
167
Lattice(ix+1, iy, iz, fx1, fy0, fz0),
169
vy1:=Lerp(Lattice(ix, iy+1, iz, fx0, fy1, fz0),
170
Lattice(ix+1, iy+1, iz, fx1, fy1, fz0),
172
vz0:=Lerp(vy0, vy1, wy);
174
vy0:=Lerp(Lattice(ix, iy, iz+1, fx0, fy0, fz1),
175
Lattice(ix+1, iy, iz+1, fx1, fy0, fz1),
177
vy1:=Lerp(Lattice(ix, iy+1, iz+1, fx0, fy1, fz1),
178
Lattice(ix+1, iy+1, iz+1, fx1, fy1, fz1),
180
vz1:=Lerp(vy0, vy1, wy);
182
Result:=Lerp(vz0, vz1, wz);
185
// Noise (dual single)
187
function TGLPerlin3DNoise.Noise(const x, y : Single) : Single;
189
function Smooth(var x : Single) : Single;
196
fx0, fx1, fy0, fy1 : Single;
210
vy0:=Lerp(Lattice(ix, iy, fx0, fy0),
211
Lattice(ix+1, iy, fx1, fy0),
213
vy1:=Lerp(Lattice(ix, iy+1, fx0, fy1),
214
Lattice(ix+1, iy+1, fx1, fy1),
216
Result:=Lerp(vy0, vy1, wy);
219
// Noise (trio single)
221
function TGLPerlin3DNoise.Noise(const x, y, z : Single) : Single;
223
Result:=Noise(AffineVectorMake(x, y, z));
228
function TGLPerlin3DNoise.Noise(const v : TVector) : Single;
230
Result:=Noise(PAffineVector(@v)^);