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