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 #ifdef __SSE4_1__
20 #include <smmintrin.h>
21 #endif
22 #include "ExprBuiltins.h"
23 
24 namespace {
25 #include "NoiseTables.h"
26 }
27 #include "Noise.h"
28 namespace SeExpr2 {
29 
30 #ifdef __SSE4_1__
31 inline double floorSSE(double val) { return _mm_floor_sd(_mm_set_sd(0.0), _mm_set_sd(val))[0]; }
32 
33 inline double roundSSE(double val) {
34  return _mm_round_sd(_mm_set_sd(0.0), _mm_set_sd(val), _MM_FROUND_TO_NEAREST_INT)[0];
35 }
36 #else
37 #define floorSSE floor
38 #define roundSSE round
39 #endif
40 
42 double s_curve(double t) { return t * t * t * (t * (6 * t - 15) + 10); }
43 
45 template <int d>
46 unsigned char hashReduceChar(int index[d]) {
47  uint32_t seed = 0;
48  // blend with seed (constants from Numerical Recipes, attrib. from Knuth)
49  for (int k = 0; k < d; k++) {
50  static const uint32_t M = 1664525, C = 1013904223;
51  seed = seed * M + index[k] + C;
52  }
53  // tempering (from Matsumoto)
54  seed ^= (seed >> 11);
55  seed ^= (seed << 7) & 0x9d2c5680UL;
56  seed ^= (seed << 15) & 0xefc60000UL;
57  seed ^= (seed >> 18);
58  // compute one byte by mixing third and first bytes
59  return (((seed & 0xff0000) >> 4) + (seed & 0xff)) & 0xff;
60 }
61 
63 template <int d>
64 uint32_t hashReduce(uint32_t index[d]) {
65  union {
66  uint32_t i;
67  unsigned char c[4];
68  } u1, u2;
69  // blend with seed (constants from Numerical Recipes, attrib. from Knuth)
70  u1.i = 0;
71  for (int k = 0; k < d; k++) {
72  static const uint32_t M = 1664525, C = 1013904223;
73  u1.i = u1.i * M + index[k] + C;
74  }
75  // tempering (from Matsumoto)
76  u1.i ^= (u1.i >> 11);
77  u1.i ^= (u1.i << 7) & 0x9d2c5680U;
78  u1.i ^= (u1.i << 15) & 0xefc60000U;
79  u1.i ^= (u1.i >> 18);
80  // permute bytes (shares perlin noise permutation table)
81  u2.c[3] = p[u1.c[0]];
82  u2.c[2] = p[u1.c[1] + u2.c[3]];
83  u2.c[1] = p[u1.c[2] + u2.c[2]];
84  u2.c[0] = p[u1.c[3] + u2.c[1]];
85 
86  return u2.i;
87 }
88 
90 template <int d, class T, bool periodic>
91 T noiseHelper(const T* X, const int* period = 0) {
92  // find lattice index
93  T weights[2][d]; // lower and upper weights
94  int index[d];
95  for (int k = 0; k < d; k++) {
96  T f = floorSSE(X[k]);
97  index[k] = (int)f;
98  if (periodic) {
99  index[k] %= period[k];
100  if (index[k] < 0) index[k] += period[k];
101  }
102  weights[0][k] = X[k] - f;
103  weights[1][k] = weights[0][k] - 1; // dist to cell with index one above
104  }
105  // compute function values propagated from zero from each node
106  const int num = 1 << d;
107  T vals[num];
108  for (int dummy = 0; dummy < num; dummy++) {
109  int latticeIndex[d];
110  int offset[d];
111  for (int k = 0; k < d; k++) {
112  offset[k] = ((dummy & (1 << k)) != 0);
113  latticeIndex[k] = index[k] + offset[k];
114  }
115  // hash to get representative gradient vector
116  int lookup = hashReduceChar<d>(latticeIndex);
117  T val = 0;
118  for (int k = 0; k < d; k++) {
119  double grad = NOISE_TABLES<d>::g[lookup][k];
120  double weight = weights[offset[k]][k];
121  val += grad * weight;
122  }
123  vals[dummy] = val;
124  }
125  // compute linear interpolation coefficients
126  T alphas[d];
127  for (int k = 0; k < d; k++) alphas[k] = s_curve(weights[0][k]);
128  // perform multilinear interpolation (i.e. linear, bilinear, trilinear, quadralinear)
129  for (int newd = d - 1; newd >= 0; newd--) {
130  int newnum = 1 << newd;
131  int k = (d - newd - 1);
132  T alpha = alphas[k];
133  T beta = T(1) - alphas[k];
134  for (int dummy = 0; dummy < newnum; dummy++) {
135  int index = dummy * (1 << (d - newd));
136  int otherIndex = index + (1 << k);
137  // T alpha=s_curve(weights[0][k]);
138  vals[index] = beta * vals[index] + alpha * vals[otherIndex];
139  }
140  }
141  // return reduced version
142  return vals[0];
143 }
144 }
145 
146 namespace SeExpr2 {
147 
149 template <int d_in, int d_out, class T>
150 void CellNoise(const T* in, T* out) {
151  uint32_t index[d_in];
152  int dim = 0;
153  for (int k = 0; k < d_in; k++) index[k] = uint32_t(floorSSE(in[k]));
154  while (1) {
155  out[dim] = hashReduce<d_in>(index) * (1.0 / 0xffffffffu);
156  if (++dim >= d_out) break;
157  for (int k = 0; k < d_in; k++) index[k] += 1000;
158  }
159 }
160 
162 template <int d_in, int d_out, class T>
163 void Noise(const T* in, T* out) {
164  T P[d_in];
165  for (int i = 0; i < d_in; i++) P[i] = in[i];
166 
167  int i = 0;
168  while (1) {
169  out[i] = noiseHelper<d_in, T, false>(P);
170  if (++i >= d_out) break;
171  for (int k = 0; k < d_out; k++) P[k] += (T)1000;
172  }
173 }
174 
176 template <int d_in, int d_out, class T>
177 void PNoise(const T* in, const int* period, T* out) {
178  T P[d_in];
179  for (int i = 0; i < d_in; i++) P[i] = in[i];
180 
181  int i = 0;
182  while (1) {
183  out[i] = noiseHelper<d_in, T, true>(P, period);
184  if (++i >= d_out) break;
185  for (int k = 0; k < d_out; k++) P[k] += (T)1000;
186  }
187 }
188 
191 template <int d_in, int d_out, bool turbulence, class T>
192 void FBM(const T* in, T* out, int octaves, T lacunarity, T gain) {
193  T P[d_in];
194  for (int i = 0; i < d_in; i++) P[i] = in[i];
195 
196  T scale = 1;
197  for (int k = 0; k < d_out; k++) out[k] = 0;
198  int octave = 0;
199  while (1) {
200  T localResult[d_out];
201  Noise<d_in, d_out>(P, localResult);
202  if (turbulence)
203  for (int k = 0; k < d_out; k++) out[k] += fabs(localResult[k]) * scale;
204  else
205  for (int k = 0; k < d_out; k++) out[k] += localResult[k] * scale;
206  if (++octave >= octaves) break;
207  scale *= gain;
208  for (int k = 0; k < d_in; k++) {
209  P[k] *= lacunarity;
210  P[k] += (T)1234;
211  }
212  }
213 }
214 
215 // Explicit instantiations
216 template void CellNoise<3, 1, double>(const double*, double*);
217 template void CellNoise<3, 3, double>(const double*, double*);
218 template void Noise<1, 1, double>(const double*, double*);
219 template void Noise<2, 1, double>(const double*, double*);
220 template void Noise<3, 1, double>(const double*, double*);
221 template void PNoise<3, 1, double>(const double*, const int*, double*);
222 template void Noise<4, 1, double>(const double*, double*);
223 template void Noise<3, 3, double>(const double*, double*);
224 template void Noise<4, 3, double>(const double*, double*);
225 template void FBM<3, 1, false, double>(const double*, double*, int, double, double);
226 template void FBM<3, 1, true, double>(const double*, double*, int, double, double);
227 template void FBM<3, 3, false, double>(const double*, double*, int, double, double);
228 template void FBM<3, 3, true, double>(const double*, double*, int, double, double);
229 template void FBM<4, 1, false, double>(const double*, double*, int, double, double);
230 template void FBM<4, 3, false, double>(const double*, double*, int, double, double);
231 }
232 
233 #ifdef MAINTEST
234 int main(int argc, char* argv[]) {
235  typedef double T;
236  T sum = 0;
237  for (int i = 0; i < 10000000; i++) {
238  T foo[3] = {.3, .3, .3};
239  // for(int k=0;k<3;k++) foo[k]=(double)rand()/double(RAND_MAX)*100.;
240  sum += SeExpr2::noiseHelper<3, T, false>(foo);
241  }
242 }
243 #endif
index
The result is computed int int< br >< div style="margin-left: 40px;"> Picks values randomly between loRange and hiRange based on supplied index(which is automatically hashed). &nbsp
f
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
SeExpr2::FBM< 4, 3, false, double >
template void FBM< 4, 3, false, double >(const double *, double *, int, double, double)
SeExpr2::noiseHelper
T noiseHelper(const T *X, const int *period=0)
Noise with d_in dimensional domain, 1 dimensional abcissa.
Definition: Noise.cpp:91
roundSSE
#define roundSSE
Definition: Noise.cpp:38
SeExpr2::CellNoise
void CellNoise(const T *in, T *out)
Computes cellular noise (non-interpolated piecewise constant cell random values)
Definition: Noise.cpp:150
SeExpr2::FBM< 3, 1, false, double >
template void FBM< 3, 1, false, double >(const double *, double *, int, double, double)
SeExpr2::PNoise< 3, 1, double >
template void PNoise< 3, 1, double >(const double *, const int *, double *)
SeExpr2::PNoise
void PNoise(const T *in, const int *period, T *out)
Periodic Noise with d_in dimensional domain, d_out dimensional abcissa.
Definition: Noise.cpp:177
NoiseTables.h
NOISE_TABLES
Definition: NoiseTables.h:46
SeExpr2
Definition: Context.h:22
SeExpr2::FBM< 3, 1, true, double >
template void FBM< 3, 1, true, double >(const double *, double *, int, double, double)
SeExpr2::CellNoise< 3, 1, double >
template void CellNoise< 3, 1, double >(const double *, double *)
ExprBuiltins.h
SeExpr2::Noise< 3, 3, double >
template void Noise< 3, 3, double >(const double *, double *)
SeExpr2::Noise
void Noise(const T *in, T *out)
Noise with d_in dimensional domain, d_out dimensional abcissa.
Definition: Noise.cpp:163
floorSSE
#define floorSSE
Definition: Noise.cpp:37
SeExpr2::FBM< 3, 3, false, double >
template void FBM< 3, 3, false, double >(const double *, double *, int, double, double)
SeExpr2::FBM< 3, 3, true, double >
template void FBM< 3, 3, true, double >(const double *, double *, int, double, double)
SeExpr2::hashReduce
uint32_t hashReduce(uint32_t index[d])
Does a hash reduce to an integer.
Definition: Noise.cpp:64
SeExpr2::FBM
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:192
SeExpr2::Noise< 1, 1, double >
template void Noise< 1, 1, double >(const double *, double *)
SeExpr2::Noise< 4, 1, double >
template void Noise< 4, 1, double >(const double *, double *)
p
static const int p[514]
Definition: NoiseTables.h:20
SeExpr2::Noise< 4, 3, double >
template void Noise< 4, 3, double >(const double *, double *)
SeExpr2::FBM< 4, 1, false, double >
template void FBM< 4, 1, false, double >(const double *, double *, int, double, double)
SeExpr2::Noise< 3, 1, double >
template void Noise< 3, 1, double >(const double *, double *)
main
int main(int argc, char *argv[])
Definition: EditMain.cpp:24
Noise.h
SeExpr2::turbulence
double turbulence(int n, const Vec3d *args)
Definition: ExprBuiltins.cpp:551
SeExpr2::s_curve
double s_curve(double t)
This is the Quintic interpolant from Perlin's Improved Noise Paper.
Definition: Noise.cpp:42
SeExpr2::Noise< 2, 1, double >
template void Noise< 2, 1, double >(const double *, double *)
SeExpr2::CellNoise< 3, 3, double >
template void CellNoise< 3, 3, double >(const double *, double *)
SeExpr2::hashReduceChar
unsigned char hashReduceChar(int index[d])
Does a hash reduce to a character.
Definition: Noise.cpp:46