SeExpr
Noise.cpp
Go to the documentation of this file.
1 /*
2  Copyright Disney Enterprises, Inc. All rights reserved.
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License
6  and the following modification to it: Section 6 Trademarks.
7  deleted and replaced with:
8 
9  6. Trademarks. This License does not grant permission to use the
10  trade names, trademarks, service marks, or product names of the
11  Licensor and its affiliates, except as required for reproducing
12  the content of the NOTICE file.
13 
14  You may obtain a copy of the License at
15  http://www.apache.org/licenses/LICENSE-2.0
16 */
17 
18 #include <iostream>
19 #include <smmintrin.h>
20 #include "ExprBuiltins.h"
21 
22 namespace {
23 #include "NoiseTables.h"
24 }
25 #include "Noise.h"
26 namespace SeExpr2 {
27 
28 inline double floorSSE(double val) { return _mm_cvtsd_f64(_mm_floor_sd(_mm_set_sd(0.0), _mm_set_sd(val))); }
29 
30 inline double roundSSE(double val) {
31  return _mm_cvtsd_f64(_mm_round_sd(_mm_set_sd(0.0), _mm_set_sd(val), _MM_FROUND_TO_NEAREST_INT));
32 }
33 
35 double s_curve(double t) { return t * t * t * (t * (6 * t - 15) + 10); }
36 
38 template <int d>
39 unsigned char hashReduceChar(int index[d]) {
40  uint32_t seed = 0;
41  // blend with seed (constants from Numerical Recipes, attrib. from Knuth)
42  for (int k = 0; k < d; k++) {
43  static const uint32_t M = 1664525, C = 1013904223;
44  seed = seed * M + index[k] + C;
45  }
46  // tempering (from Matsumoto)
47  seed ^= (seed >> 11);
48  seed ^= (seed << 7) & 0x9d2c5680UL;
49  seed ^= (seed << 15) & 0xefc60000UL;
50  seed ^= (seed >> 18);
51  // compute one byte by mixing third and first bytes
52  return (((seed & 0xff0000) >> 4) + (seed & 0xff)) & 0xff;
53 }
54 
56 template <int d>
57 uint32_t hashReduce(uint32_t index[d]) {
58  union {
59  uint32_t i;
60  unsigned char c[4];
61  } u1, u2;
62  // blend with seed (constants from Numerical Recipes, attrib. from Knuth)
63  u1.i = 0;
64  for (int k = 0; k < d; k++) {
65  static const uint32_t M = 1664525, C = 1013904223;
66  u1.i = u1.i * M + index[k] + C;
67  }
68  // tempering (from Matsumoto)
69  u1.i ^= (u1.i >> 11);
70  u1.i ^= (u1.i << 7) & 0x9d2c5680U;
71  u1.i ^= (u1.i << 15) & 0xefc60000U;
72  u1.i ^= (u1.i >> 18);
73  // permute bytes (shares perlin noise permutation table)
74  u2.c[3] = p[u1.c[0]];
75  u2.c[2] = p[u1.c[1] + u2.c[3]];
76  u2.c[1] = p[u1.c[2] + u2.c[2]];
77  u2.c[0] = p[u1.c[3] + u2.c[1]];
78 
79  return u2.i;
80 }
81 
83 template <int d, class T, bool periodic>
84 T noiseHelper(const T* X, const int* period = 0) {
85  // find lattice index
86  T weights[2][d]; // lower and upper weights
87  int index[d];
88  for (int k = 0; k < d; k++) {
89  T f = floorSSE(X[k]);
90  index[k] = (int)f;
91  if (periodic) {
92  index[k] %= period[k];
93  if (index[k] < 0) index[k] += period[k];
94  }
95  weights[0][k] = X[k] - f;
96  weights[1][k] = weights[0][k] - 1; // dist to cell with index one above
97  }
98  // compute function values propagated from zero from each node
99  int num = 1 << d;
100  T vals[num];
101  for (int dummy = 0; dummy < num; dummy++) {
102  int latticeIndex[d];
103  int offset[d];
104  for (int k = 0; k < d; k++) {
105  offset[k] = ((dummy & (1 << k)) != 0);
106  latticeIndex[k] = index[k] + offset[k];
107  }
108  // hash to get representative gradient vector
109  int lookup = hashReduceChar<d>(latticeIndex);
110  T val = 0;
111  for (int k = 0; k < d; k++) {
112  double grad = NOISE_TABLES<d>::g[lookup][k];
113  double weight = weights[offset[k]][k];
114  val += grad * weight;
115  }
116  vals[dummy] = val;
117  }
118  // compute linear interpolation coefficients
119  T alphas[d];
120  for (int k = 0; k < d; k++) alphas[k] = s_curve(weights[0][k]);
121  // perform multilinear interpolation (i.e. linear, bilinear, trilinear, quadralinear)
122  for (int newd = d - 1; newd >= 0; newd--) {
123  int newnum = 1 << newd;
124  int k = (d - newd - 1);
125  T alpha = alphas[k];
126  T beta = T(1) - alphas[k];
127  for (int dummy = 0; dummy < newnum; dummy++) {
128  int index = dummy * (1 << (d - newd));
129  int otherIndex = index + (1 << k);
130  // T alpha=s_curve(weights[0][k]);
131  vals[index] = beta * vals[index] + alpha * vals[otherIndex];
132  }
133  }
134  // return reduced version
135  return vals[0];
136 }
137 }
138 
139 namespace SeExpr2 {
140 
142 template <int d_in, int d_out, class T>
143 void CellNoise(const T* in, T* out) {
144  uint32_t index[d_in];
145  int dim = 0;
146  for (int k = 0; k < d_in; k++) index[k] = uint32_t(floorSSE(in[k]));
147  while (1) {
148  out[dim] = hashReduce<d_in>(index) * (1.0 / 0xffffffffu);
149  if (++dim >= d_out) break;
150  for (int k = 0; k < d_in; k++) index[k] += 1000;
151  }
152 }
153 
155 template <int d_in, int d_out, class T>
156 void Noise(const T* in, T* out) {
157  T P[d_in];
158  for (int i = 0; i < d_in; i++) P[i] = in[i];
159 
160  int i = 0;
161  while (1) {
162  out[i] = noiseHelper<d_in, T, false>(P);
163  if (++i >= d_out) break;
164  for (int k = 0; k < d_out; k++) P[k] += (T)1000;
165  }
166 }
167 
169 template <int d_in, int d_out, class T>
170 void PNoise(const T* in, const int* period, T* out) {
171  T P[d_in];
172  for (int i = 0; i < d_in; i++) P[i] = in[i];
173 
174  int i = 0;
175  while (1) {
176  out[i] = noiseHelper<d_in, T, true>(P, period);
177  if (++i >= d_out) break;
178  for (int k = 0; k < d_out; k++) P[k] += (T)1000;
179  }
180 }
181 
184 template <int d_in, int d_out, bool turbulence, class T>
185 void FBM(const T* in, T* out, int octaves, T lacunarity, T gain) {
186  T P[d_in];
187  for (int i = 0; i < d_in; i++) P[i] = in[i];
188 
189  T scale = 1;
190  for (int k = 0; k < d_out; k++) out[k] = 0;
191  int octave = 0;
192  while (1) {
193  T localResult[d_out];
194  Noise<d_in, d_out>(P, localResult);
195  if (turbulence)
196  for (int k = 0; k < d_out; k++) out[k] += fabs(localResult[k]) * scale;
197  else
198  for (int k = 0; k < d_out; k++) out[k] += localResult[k] * scale;
199  if (++octave >= octaves) break;
200  scale *= gain;
201  for (int k = 0; k < d_in; k++) {
202  P[k] *= lacunarity;
203  P[k] += (T)1234;
204  }
205  }
206 }
207 
208 // Explicit instantiations
209 template void CellNoise<3, 1, double>(const double*, double*);
210 template void CellNoise<3, 3, double>(const double*, double*);
211 template void Noise<1, 1, double>(const double*, double*);
212 template void Noise<2, 1, double>(const double*, double*);
213 template void Noise<3, 1, double>(const double*, double*);
214 template void PNoise<3, 1, double>(const double*, const int*, double*);
215 template void Noise<4, 1, double>(const double*, double*);
216 template void Noise<3, 3, double>(const double*, double*);
217 template void Noise<4, 3, double>(const double*, double*);
218 template void FBM<3, 1, false, double>(const double*, double*, int, double, double);
219 template void FBM<3, 1, true, double>(const double*, double*, int, double, double);
220 template void FBM<3, 3, false, double>(const double*, double*, int, double, double);
221 template void FBM<3, 3, true, double>(const double*, double*, int, double, double);
222 template void FBM<4, 1, false, double>(const double*, double*, int, double, double);
223 template void FBM<4, 3, false, double>(const double*, double*, int, double, double);
224 }
225 
226 #ifdef MAINTEST
227 int main(int argc, char* argv[]) {
228  typedef double T;
229  T sum = 0;
230  for (int i = 0; i < 10000000; i++) {
231  T foo[3] = {.3, .3, .3};
232  // for(int k=0;k<3;k++) foo[k]=(double)rand()/double(RAND_MAX)*100.;
233  sum += SeExpr2::noiseHelper<3, T, false>(foo);
234  }
235 }
236 #endif
template void FBM< 4, 1, false, double >(const double *, double *, int, double, double)
T noiseHelper(const T *X, const int *period=0)
Noise with d_in dimensional domain, 1 dimensional abcissa.
Definition: Noise.cpp:84
double s_curve(double t)
This is the Quintic interpolant from Perlin&#39;s Improved Noise Paper.
Definition: Noise.cpp:35
unsigned char hashReduceChar(int index[d])
Does a hash reduce to a character.
Definition: Noise.cpp:39
double floorSSE(double val)
Definition: Noise.cpp:28
template void FBM< 3, 1, false, double >(const double *, double *, int, double, double)
with numParticles numAttributes A variable block contains variable names and types but doesn t care what the values are< pre > void f(const std::string &s, MyParticleData *p, int outputDim=3)
Definition: varblocks.txt:35
template void Noise< 3, 3, double >(const double *, double *)
void CellNoise(const T *in, T *out)
Computes cellular noise (non-interpolated piecewise constant cell random values)
Definition: Noise.cpp:143
template void PNoise< 3, 1, double >(const double *, const int *, double *)
double roundSSE(double val)
Definition: Noise.cpp:30
void PNoise(const T *in, const int *period, T *out)
Periodic Noise with d_in dimensional domain, d_out dimensional abcissa.
Definition: Noise.cpp:170
template void FBM< 3, 1, true, double >(const double *, double *, int, double, double)
template void CellNoise< 3, 1, double >(const double *, double *)
The result is computed int int< br >< divstyle="margin-left:40px;"> Picks values randomly between loRange and hiRange based on supplied index(which is automatically hashed).&nbsp
static const int p[514]
Definition: NoiseTables.h:20
template void FBM< 3, 3, true, double >(const double *, double *, int, double, double)
template void Noise< 4, 1, double >(const double *, double *)
template void FBM< 3, 3, false, double >(const double *, double *, int, double, double)
void FBM(const T *in, T *out, int octaves, T lacunarity, T gain)
Fractional Brownian Motion. If turbulence is true then turbulence computed.
Definition: Noise.cpp:185
uint32_t hashReduce(uint32_t index[d])
Does a hash reduce to an integer.
Definition: Noise.cpp:57
void Noise(const T *in, T *out)
Noise with d_in dimensional domain, d_out dimensional abcissa.
Definition: Noise.cpp:156
double turbulence(int n, const Vec3d *args)
template void Noise< 2, 1, double >(const double *, double *)
template void CellNoise< 3, 3, double >(const double *, double *)
template void Noise< 1, 1, double >(const double *, double *)
int main(int argc, char *argv[])
Definition: EditMain.cpp:24
template void FBM< 4, 3, false, double >(const double *, double *, int, double, double)
template void Noise< 4, 3, double >(const double *, double *)
template void Noise< 3, 1, double >(const double *, double *)