PageRenderTime 59ms CodeModel.GetById 34ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmath/llperlin.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 294 lines | 203 code | 59 blank | 32 comment | 13 complexity | 104c013c96edf81f6a0d872a106b618e MD5 | raw file
  1/** 
  2 * @file llperlin.cpp
  3 *
  4 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  5 * Second Life Viewer Source Code
  6 * Copyright (C) 2010, Linden Research, Inc.
  7 * 
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation;
 11 * version 2.1 of the License only.
 12 * 
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16 * Lesser General Public License for more details.
 17 * 
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 21 * 
 22 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 23 * $/LicenseInfo$
 24 */
 25
 26#include "linden_common.h"
 27#include "llmath.h"
 28
 29#include "llperlin.h"
 30
 31#define B 0x100
 32#define BM 0xff
 33#define N 0x1000
 34#define NF32 (4096.f)
 35#define NP 12   /* 2^N */
 36#define NM 0xfff
 37
 38static S32 p[B + B + 2];
 39static F32 g3[B + B + 2][3];
 40static F32 g2[B + B + 2][2];
 41static F32 g1[B + B + 2];
 42
 43bool LLPerlinNoise::sInitialized = 0;
 44
 45static void normalize2(F32 v[2])
 46{
 47	F32 s = 1.f/(F32)sqrt(v[0] * v[0] + v[1] * v[1]);
 48	v[0] = v[0] * s;
 49	v[1] = v[1] * s;
 50}
 51
 52static void normalize3(F32 v[3])
 53{
 54	F32 s = 1.f/(F32)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
 55	v[0] = v[0] * s;
 56	v[1] = v[1] * s;
 57	v[2] = v[2] * s;
 58}
 59
 60static void fast_setup(F32 vec, U8 &b0, U8 &b1, F32 &r0, F32 &r1)
 61{
 62	S32 t_S32;
 63
 64	r1	= vec + NF32;
 65	t_S32 = lltrunc(r1);
 66	b0 = (U8)t_S32;
 67	b1 = b0 + 1;
 68	r0 = r1 - t_S32;
 69	r1 = r0 - 1.f;
 70}
 71
 72
 73void LLPerlinNoise::init(void)
 74{
 75	int i, j, k;
 76
 77	for (i = 0 ; i < B ; i++)
 78	{
 79		p[i] = i;
 80
 81		g1[i] = (F32)((rand() % (B + B)) - B) / B;
 82
 83		for (j = 0 ; j < 2 ; j++)
 84			g2[i][j] = (F32)((rand() % (B + B)) - B) / B;
 85		normalize2(g2[i]);
 86
 87		for (j = 0 ; j < 3 ; j++)
 88			g3[i][j] = (F32)((rand() % (B + B)) - B) / B;
 89		normalize3(g3[i]);
 90	}
 91
 92	while (--i)
 93	{
 94		k = p[i];
 95		p[i] = p[j = rand() % B];
 96		p[j] = k;
 97	}
 98
 99	for (i = 0 ; i < B + 2 ; i++)
100	{
101		p[B + i] = p[i];
102		g1[B + i] = g1[i];
103		for (j = 0 ; j < 2 ; j++)
104			g2[B + i][j] = g2[i][j];
105		for (j = 0 ; j < 3 ; j++)
106			g3[B + i][j] = g3[i][j];
107	}
108
109	sInitialized = true;
110}
111
112
113//============================================================================
114// Noise functions
115
116#define s_curve(t) ( t * t * (3.f - 2.f * t) )
117
118#define lerp_m(t, a, b) ( a + t * (b - a) )
119
120F32 LLPerlinNoise::noise1(F32 x)
121{
122	int bx0, bx1;
123	F32 rx0, rx1, sx, t, u, v;
124
125	if (!sInitialized)
126		init();
127
128	t = x + N;
129	bx0 = (lltrunc(t)) & BM;
130	bx1 = (bx0+1) & BM;
131	rx0 = t - lltrunc(t);
132	rx1 = rx0 - 1.f;
133
134	sx = s_curve(rx0);
135
136	u = rx0 * g1[ p[ bx0 ] ];
137	v = rx1 * g1[ p[ bx1 ] ];
138
139	return lerp_m(sx, u, v);
140}
141
142static F32 fast_at2(F32 rx, F32 ry, F32 *q)
143{
144	return rx * q[0] + ry * q[1];
145}
146
147F32 LLPerlinNoise::noise2(F32 x, F32 y)
148{
149	U8 bx0, bx1, by0, by1;
150	U32 b00, b10, b01, b11;
151	F32 rx0, rx1, ry0, ry1, *q, sx, sy, a, b, u, v;
152	S32 i, j;
153
154	if (!sInitialized)
155		init();
156
157	fast_setup(x, bx0, bx1, rx0, rx1);
158	fast_setup(y, by0, by1, ry0, ry1);
159
160	i = *(p + bx0);
161	j = *(p + bx1);
162
163	b00 = *(p + i + by0);
164	b10 = *(p + j + by0);
165	b01 = *(p + i + by1);
166	b11 = *(p + j + by1);
167
168	sx = s_curve(rx0);
169	sy = s_curve(ry0);
170
171
172	q = *(g2 + b00);
173	u = fast_at2(rx0, ry0, q);
174	q = *(g2 + b10); 
175	v = fast_at2(rx1, ry0, q);
176	a = lerp_m(sx, u, v);
177
178	q = *(g2 + b01); 
179	u = fast_at2(rx0,ry1,q);
180	q = *(g2 + b11); 
181	v = fast_at2(rx1,ry1,q);
182	b = lerp_m(sx, u, v);
183
184	return lerp_m(sy, a, b);
185}
186
187static F32 fast_at3(F32 rx, F32 ry, F32 rz, F32 *q)
188{
189	return rx * q[0] + ry * q[1] + rz * q[2];
190}
191
192F32 LLPerlinNoise::noise3(F32 x, F32 y, F32 z)
193{
194	U8 bx0, bx1, by0, by1, bz0, bz1;
195	S32 b00, b10, b01, b11;
196	F32 rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
197	S32 i, j;
198
199	if (!sInitialized)
200		init();
201
202	fast_setup(x, bx0,bx1, rx0,rx1);
203	fast_setup(y, by0,by1, ry0,ry1);
204	fast_setup(z, bz0,bz1, rz0,rz1);
205
206	i = p[ bx0 ];
207	j = p[ bx1 ];
208
209	b00 = p[ i + by0 ];
210	b10 = p[ j + by0 ];
211	b01 = p[ i + by1 ];
212	b11 = p[ j + by1 ];
213
214	t  = s_curve(rx0);
215	sy = s_curve(ry0);
216	sz = s_curve(rz0);
217
218	q = g3[ b00 + bz0 ]; 
219	u = fast_at3(rx0,ry0,rz0,q);
220	q = g3[ b10 + bz0 ];
221	v = fast_at3(rx1,ry0,rz0,q);
222	a = lerp_m(t, u, v);
223
224	q = g3[ b01 + bz0 ];
225	u = fast_at3(rx0,ry1,rz0,q);
226	q = g3[ b11 + bz0 ];
227	v = fast_at3(rx1,ry1,rz0,q);
228	b = lerp_m(t, u, v);
229
230	c = lerp_m(sy, a, b);
231
232	q = g3[ b00 + bz1 ];
233	u = fast_at3(rx0,ry0,rz1,q);
234	q = g3[ b10 + bz1 ];
235	v = fast_at3(rx1,ry0,rz1,q);
236	a = lerp_m(t, u, v);
237
238	q = g3[ b01 + bz1 ];
239	u = fast_at3(rx0,ry1,rz1,q);
240	q = g3[ b11 + bz1 ];
241	v = fast_at3(rx1,ry1,rz1,q);
242	b = lerp_m(t, u, v);
243
244	d = lerp_m(sy, a, b);
245
246	return lerp_m(sz, c, d);
247}
248
249F32 LLPerlinNoise::turbulence2(F32 x, F32 y, F32 freq)
250{
251	F32 t, lx, ly;
252
253	for (t = 0.f ; freq >= 1.f ; freq *= 0.5f)
254	{
255		lx = freq * x;
256		ly = freq * y;
257		t += noise2(lx, ly)/freq;
258	}
259	return t;
260}
261
262F32 LLPerlinNoise::turbulence3(F32 x, F32 y, F32 z, F32 freq)
263{
264	F32 t, lx, ly, lz;
265
266	for (t = 0.f ; freq >= 1.f ; freq *= 0.5f)
267	{
268		lx = freq * x;
269		ly = freq * y;
270		lz = freq * z;
271		t += noise3(lx,ly,lz)/freq;
272//		t += fabs(noise3(lx,ly,lz)) / freq;					// Like snow - bubbly at low frequencies
273//		t += sqrt(fabs(noise3(lx,ly,lz))) / freq;			// Better at low freq
274//		t += (noise3(lx,ly,lz)*noise3(lx,ly,lz)) / freq;		
275	}
276	return t;
277}
278
279F32 LLPerlinNoise::clouds3(F32 x, F32 y, F32 z, F32 freq)
280{
281	F32 t, lx, ly, lz;
282
283	for (t = 0.f ; freq >= 1.f ; freq *= 0.5f)
284	{
285		lx = freq * x;
286		ly = freq * y;
287		lz = freq * z;
288//		t += noise3(lx,ly,lz)/freq;
289//		t += fabs(noise3(lx,ly,lz)) / freq;					// Like snow - bubbly at low frequencies
290//		t += sqrt(fabs(noise3(lx,ly,lz))) / freq;			// Better at low freq
291		t += (noise3(lx,ly,lz)*noise3(lx,ly,lz)) / freq;		
292	}
293	return t;
294}