File: noise.cpp

package info (click to toggle)
evolvotron 0.8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,444 kB
  • sloc: cpp: 9,855; sh: 258; python: 162; makefile: 11; sed: 6
file content (128 lines) | stat: -rw-r--r-- 3,769 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**************************************************************************/
/*  Copyright 2012 Tim Day                                                */
/*                                                                        */
/*  This file is part of Evolvotron                                       */
/*                                                                        */
/*  Evolvotron is free software: you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by  */
/*  the Free Software Foundation, either version 3 of the License, or     */
/*  (at your option) any later version.                                   */
/*                                                                        */
/*  Evolvotron is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
/*  GNU General Public License for more details.                          */
/*                                                                        */
/*  You should have received a copy of the GNU General Public License     */
/*  along with Evolvotron.  If not, see <http://www.gnu.org/licenses/>.   */
/**************************************************************************/

/*! \file
  \brief Implementation of Noise class
*/



#include "noise.h"
#include "random.h"

Noise::Noise(uint seed)
{
  // We use our own random number generator so saved pictures will be the same when reloaded!
  // (Besides, one isn't actually conveniently available)
  Random01 r_01(seed);

  // Create an array of random gradient vectors uniformly on the unit sphere

  int i;
  
  for (i=0;i<N;i++)
    _g[i]=RandomXYZSphereNormal(r_01);
  
  // Create a pseudorandom permutation of [1..B] 
  
  for (i=0;i<=N;i++)
    _p[i]=i;
  
  for (i=N;i>0;i-=2) 
    {
      int j=((int)(r_01()*N));
      int k=_p[i];
      _p[i]=_p[j];
      _p[j]=k;
    }
  
  // Extend g and p arrays to allow for faster indexing
  
  for (i=0;i<N+2;i++)
    {
      _p[N+i]=_p[i];
      _g[N+i]=_g[i];
    }
}

inline real value(const XYZ& q,real rx,real ry,real rz)
{
  return rx*q.x()+ry*q.y()+rz*q.z();
}

inline real surve(real t)
{
  return t*t*(3.0-2.0*t);
}

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

real Noise::operator()(const XYZ& p) const
{
  // Crank up the frequency a bit otherwise don't see much variation in base case
  const real tx=2.0*p.x()+10000.0;
  const real ty=2.0*p.y()+10000.0;
  const real tz=2.0*p.z()+10000.0;
  
  const int itx=(int)tx;
  const int ity=(int)ty;
  const int itz=(int)tz;

  const real rx0=tx-itx;
  const real ry0=ty-ity;
  const real rz0=tz-itz;

  const real rx1=rx0-1.0;
  const real ry1=ry0-1.0;
  const real rz1=rz0-1.0;

  const int bx0=(itx&(N-1));
  const int bx1=((bx0+1)&(N-1));
  const int by0=(ity&(N-1));
  const int by1=((by0+1)&(N-1));
  const int bz0=(itz&(N-1));
  const int bz1=((bz0+1)&(N-1));
      
  const int i=_p[bx0];
  const int b00=_p[i+by0];
  const int b01=_p[i+by1];
      
  const int j=_p[bx1];
  const int b10=_p[j+by0];
  const int b11=_p[j+by1];
  
  const real sx=surve(rx0);

  const real a0=lerp(sx,value(_g[b00+bz0],rx0,ry0,rz0),value(_g[b10+bz0],rx1,ry0,rz0));
  const real b0=lerp(sx,value(_g[b01+bz0],rx0,ry1,rz0),value(_g[b11+bz0],rx1,ry1,rz0));
  const real a1=lerp(sx,value(_g[b00+bz1],rx0,ry0,rz1),value(_g[b10+bz1],rx1,ry0,rz1));
  const real b1=lerp(sx,value(_g[b01+bz1],rx0,ry1,rz1),value(_g[b11+bz1],rx1,ry1,rz1));

  const real sy=surve(ry0);
      
  const real c=lerp(sy,a0,b0);  
  const real d=lerp(sy,a1,b1);

  const real sz=surve(rz0);
  
  return 1.5*lerp(sz,c,d);
}