aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llwind.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llwind.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llwind.cpp359
1 files changed, 359 insertions, 0 deletions
diff --git a/linden/indra/newview/llwind.cpp b/linden/indra/newview/llwind.cpp
new file mode 100644
index 0000000..5180b8f
--- /dev/null
+++ b/linden/indra/newview/llwind.cpp
@@ -0,0 +1,359 @@
1/**
2 * @file llwind.cpp
3 * @brief LLWind class implementation
4 *
5 * Copyright (c) 2000-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28// Wind is a lattice. It is computed on the simulator, and transmitted to the viewer.
29// It drives special effects like smoke blowing, trees bending, and grass wiggling.
30//
31// Currently wind lattice does not interpolate correctly to neighbors. This will need
32// work.
33
34#include "llviewerprecompiledheaders.h"
35#include "indra_constants.h"
36
37#include "llwind.h"
38
39// linden libraries
40#include "llgl.h"
41#include "patch_dct.h"
42#include "patch_code.h"
43
44// viewer
45#include "noise.h"
46#include "v4color.h"
47#include "viewer.h"
48#include "llagent.h"
49#include "llworld.h"
50
51
52const F32 CLOUD_DIVERGENCE_COEF = 0.5f;
53
54
55//////////////////////////////////////////////////////////////////////
56// Construction/Destruction
57//////////////////////////////////////////////////////////////////////
58
59LLWind::LLWind()
60: mSize(16),
61 mCloudDensityp(NULL)
62{
63 init();
64}
65
66
67LLWind::~LLWind()
68{
69 delete [] mVelX;
70 delete [] mVelY;
71 delete [] mCloudVelX;
72 delete [] mCloudVelY;
73}
74
75
76//////////////////////////////////////////////////////////////////////
77// Public Methods
78//////////////////////////////////////////////////////////////////////
79
80
81void LLWind::init()
82{
83 // Initialize vector data
84 mVelX = new F32[mSize*mSize];
85 mVelY = new F32[mSize*mSize];
86
87 mCloudVelX = new F32[mSize*mSize];
88 mCloudVelY = new F32[mSize*mSize];
89
90 S32 i;
91 for (i = 0; i < mSize*mSize; i++)
92 {
93 mVelX[i] = 0.5f;
94 mVelY[i] = 0.5f;
95 mCloudVelX[i] = 0.0f;
96 mCloudVelY[i] = 0.0f;
97 }
98}
99
100
101void LLWind::decompress(LLBitPack &bitpack, LLGroupHeader *group_headerp)
102{
103 if (!mCloudDensityp)
104 {
105 return;
106 }
107
108 LLPatchHeader patch_header;
109 S32 buffer[16*16];
110
111 init_patch_decompressor(group_headerp->patch_size);
112
113 // Don't use the packed group_header stride because the strides used on
114 // simulator and viewer are not equal.
115 group_headerp->stride = group_headerp->patch_size;
116 set_group_of_patch_header(group_headerp);
117
118 // X component
119 decode_patch_header(bitpack, &patch_header);
120 decode_patch(bitpack, buffer);
121 decompress_patch(mVelX, buffer, &patch_header);
122
123 // Y component
124 decode_patch_header(bitpack, &patch_header);
125 decode_patch(bitpack, buffer);
126 decompress_patch(mVelY, buffer, &patch_header);
127
128
129
130 S32 i, j, k;
131 // HACK -- mCloudVelXY is the same as mVelXY, except we add a divergence
132 // that is proportional to the gradient of the cloud density
133 // ==> this helps to clump clouds together
134 // NOTE ASSUMPTION: cloud density has the same dimensions as the wind field
135 // This needs to be fixed... causes discrepency at region boundaries
136
137 for (j=1; j<mSize-1; j++)
138 {
139 for (i=1; i<mSize-1; i++)
140 {
141 k = i + j * mSize;
142 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k - 1));
143 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k - mSize));
144 }
145 }
146
147 i = mSize - 1;
148 for (j=1; j<mSize-1; j++)
149 {
150 k = i + j * mSize;
151 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k) - *(mCloudDensityp + k - 2));
152 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k - mSize));
153 }
154 i = 0;
155 for (j=1; j<mSize-1; j++)
156 {
157 k = i + j * mSize;
158 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 2) - *(mCloudDensityp + k));
159 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k + mSize));
160 }
161 j = mSize - 1;
162 for (i=1; i<mSize-1; i++)
163 {
164 k = i + j * mSize;
165 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k - 1));
166 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k) - *(mCloudDensityp + k - 2*mSize));
167 }
168 j = 0;
169 for (i=1; i<mSize-1; i++)
170 {
171 k = i + j * mSize;
172 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k -1));
173 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 2*mSize) - *(mCloudDensityp + k));
174 }
175}
176
177
178LLVector3 LLWind::getAverage()
179{
180 // Returns in average_wind the average wind velocity
181 LLVector3 average(0.0f, 0.0f, 0.0f);
182 S32 i, grid_count;
183 grid_count = mSize * mSize;
184 for (i = 0; i < grid_count; i++)
185 {
186 average.mV[VX] += mVelX[i];
187 average.mV[VY] += mVelY[i];
188 }
189
190 average *= 1.f/((F32)(grid_count)) * WIND_SCALE_HACK;
191 return average;
192}
193
194
195LLVector3 LLWind::getVelocityNoisy(const LLVector3 &pos_region, const F32 dim)
196{
197 // Resolve a value, using fractal summing to perturb the returned value
198 LLVector3 r_val(0,0,0);
199 F32 norm = 1.0f;
200 if (dim == 8)
201 {
202 norm = 1.875;
203 }
204 else if (dim == 4)
205 {
206 norm = 1.75;
207 }
208 else if (dim == 2)
209 {
210 norm = 1.5;
211 }
212
213 F32 temp_dim = dim;
214 while (temp_dim >= 1.0)
215 {
216 LLVector3 pos_region_scaled(pos_region * temp_dim);
217 r_val += getVelocity(pos_region_scaled) * (1.0f/temp_dim);
218 temp_dim /= 2.0;
219 }
220
221 return r_val * (1.0f/norm) * WIND_SCALE_HACK;
222}
223
224
225LLVector3 LLWind::getVelocity(const LLVector3 &pos_region)
226{
227 llassert(mSize == 16);
228 // Resolves value of wind at a location relative to SW corner of region
229 //
230 // Returns wind magnitude in X,Y components of vector3
231 LLVector3 r_val;
232 F32 dx,dy;
233 S32 k;
234
235 LLVector3 pos_clamped_region(pos_region);
236
237 F32 region_width_meters = gWorldPointer->getRegionWidthInMeters();
238
239 if (pos_clamped_region.mV[VX] < 0.f)
240 {
241 pos_clamped_region.mV[VX] = 0.f;
242 }
243 else if (pos_clamped_region.mV[VX] >= region_width_meters)
244 {
245 pos_clamped_region.mV[VX] = (F32) fmod(pos_clamped_region.mV[VX], region_width_meters);
246 }
247
248 if (pos_clamped_region.mV[VY] < 0.f)
249 {
250 pos_clamped_region.mV[VY] = 0.f;
251 }
252 else if (pos_clamped_region.mV[VY] >= region_width_meters)
253 {
254 pos_clamped_region.mV[VY] = (F32) fmod(pos_clamped_region.mV[VY], region_width_meters);
255 }
256
257
258 S32 i = llfloor(pos_clamped_region.mV[VX] * mSize / region_width_meters);
259 S32 j = llfloor(pos_clamped_region.mV[VY] * mSize / region_width_meters);
260 k = i + j*mSize;
261 dx = ((pos_clamped_region.mV[VX] * mSize / region_width_meters) - (F32) i);
262 dy = ((pos_clamped_region.mV[VY] * mSize / region_width_meters) - (F32) j);
263
264 if ((i < mSize-1) && (j < mSize-1))
265 {
266 // Interior points, no edges
267 r_val.mV[VX] = mVelX[k]*(1.0f - dx)*(1.0f - dy) +
268 mVelX[k + 1]*dx*(1.0f - dy) +
269 mVelX[k + mSize]*dy*(1.0f - dx) +
270 mVelX[k + mSize + 1]*dx*dy;
271 r_val.mV[VY] = mVelY[k]*(1.0f - dx)*(1.0f - dy) +
272 mVelY[k + 1]*dx*(1.0f - dy) +
273 mVelY[k + mSize]*dy*(1.0f - dx) +
274 mVelY[k + mSize + 1]*dx*dy;
275 }
276 else
277 {
278 r_val.mV[VX] = mVelX[k];
279 r_val.mV[VY] = mVelY[k];
280 }
281
282 r_val.mV[VZ] = 0.f;
283 return r_val * WIND_SCALE_HACK;
284}
285
286
287LLVector3 LLWind::getCloudVelocity(const LLVector3 &pos_region)
288{
289 llassert(mSize == 16);
290 // Resolves value of wind at a location relative to SW corner of region
291 //
292 // Returns wind magnitude in X,Y components of vector3
293 LLVector3 r_val;
294 F32 dx,dy;
295 S32 k;
296
297 LLVector3 pos_clamped_region(pos_region);
298
299 F32 region_width_meters = gWorldPointer->getRegionWidthInMeters();
300
301 if (pos_clamped_region.mV[VX] < 0.f)
302 {
303 pos_clamped_region.mV[VX] = 0.f;
304 }
305 else if (pos_clamped_region.mV[VX] >= region_width_meters)
306 {
307 pos_clamped_region.mV[VX] = (F32) fmod(pos_clamped_region.mV[VX], region_width_meters);
308 }
309
310 if (pos_clamped_region.mV[VY] < 0.f)
311 {
312 pos_clamped_region.mV[VY] = 0.f;
313 }
314 else if (pos_clamped_region.mV[VY] >= region_width_meters)
315 {
316 pos_clamped_region.mV[VY] = (F32) fmod(pos_clamped_region.mV[VY], region_width_meters);
317 }
318
319
320 S32 i = llfloor(pos_clamped_region.mV[VX] * mSize / region_width_meters);
321 S32 j = llfloor(pos_clamped_region.mV[VY] * mSize / region_width_meters);
322 k = i + j*mSize;
323 dx = ((pos_clamped_region.mV[VX] * mSize / region_width_meters) - (F32) i);
324 dy = ((pos_clamped_region.mV[VY] * mSize / region_width_meters) - (F32) j);
325
326 if ((i < mSize-1) && (j < mSize-1))
327 {
328 // Interior points, no edges
329 r_val.mV[VX] = mCloudVelX[k]*(1.0f - dx)*(1.0f - dy) +
330 mCloudVelX[k + 1]*dx*(1.0f - dy) +
331 mCloudVelX[k + mSize]*dy*(1.0f - dx) +
332 mCloudVelX[k + mSize + 1]*dx*dy;
333 r_val.mV[VY] = mCloudVelY[k]*(1.0f - dx)*(1.0f - dy) +
334 mCloudVelY[k + 1]*dx*(1.0f - dy) +
335 mCloudVelY[k + mSize]*dy*(1.0f - dx) +
336 mCloudVelY[k + mSize + 1]*dx*dy;
337 }
338 else
339 {
340 r_val.mV[VX] = mCloudVelX[k];
341 r_val.mV[VY] = mCloudVelY[k];
342 }
343
344 r_val.mV[VZ] = 0.f;
345 return r_val * WIND_SCALE_HACK;
346}
347
348
349void LLWind::setCloudDensityPointer(F32 *densityp)
350{
351 mCloudDensityp = densityp;
352}
353
354void LLWind::setOriginGlobal(const LLVector3d &origin_global)
355{
356 mOriginGlobal = origin_global;
357}
358
359