00001
00032
00033
00034
00035
00036
00037
00038 #include "llviewerprecompiledheaders.h"
00039 #include "indra_constants.h"
00040
00041 #include "llwind.h"
00042
00043
00044 #include "llgl.h"
00045 #include "patch_dct.h"
00046 #include "patch_code.h"
00047
00048
00049 #include "noise.h"
00050 #include "v4color.h"
00051 #include "llagent.h"
00052 #include "llworld.h"
00053
00054
00055 const F32 CLOUD_DIVERGENCE_COEF = 0.5f;
00056
00057
00059
00061
00062 LLWind::LLWind()
00063 : mSize(16),
00064 mCloudDensityp(NULL)
00065 {
00066 init();
00067 }
00068
00069
00070 LLWind::~LLWind()
00071 {
00072 delete [] mVelX;
00073 delete [] mVelY;
00074 delete [] mCloudVelX;
00075 delete [] mCloudVelY;
00076 }
00077
00078
00080
00082
00083
00084 void LLWind::init()
00085 {
00086
00087 mVelX = new F32[mSize*mSize];
00088 mVelY = new F32[mSize*mSize];
00089
00090 mCloudVelX = new F32[mSize*mSize];
00091 mCloudVelY = new F32[mSize*mSize];
00092
00093 S32 i;
00094 for (i = 0; i < mSize*mSize; i++)
00095 {
00096 mVelX[i] = 0.5f;
00097 mVelY[i] = 0.5f;
00098 mCloudVelX[i] = 0.0f;
00099 mCloudVelY[i] = 0.0f;
00100 }
00101 }
00102
00103
00104 void LLWind::decompress(LLBitPack &bitpack, LLGroupHeader *group_headerp)
00105 {
00106 if (!mCloudDensityp)
00107 {
00108 return;
00109 }
00110
00111 LLPatchHeader patch_header;
00112 S32 buffer[16*16];
00113
00114 init_patch_decompressor(group_headerp->patch_size);
00115
00116
00117
00118 group_headerp->stride = group_headerp->patch_size;
00119 set_group_of_patch_header(group_headerp);
00120
00121
00122 decode_patch_header(bitpack, &patch_header);
00123 decode_patch(bitpack, buffer);
00124 decompress_patch(mVelX, buffer, &patch_header);
00125
00126
00127 decode_patch_header(bitpack, &patch_header);
00128 decode_patch(bitpack, buffer);
00129 decompress_patch(mVelY, buffer, &patch_header);
00130
00131
00132
00133 S32 i, j, k;
00134
00135
00136
00137
00138
00139
00140 for (j=1; j<mSize-1; j++)
00141 {
00142 for (i=1; i<mSize-1; i++)
00143 {
00144 k = i + j * mSize;
00145 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k - 1));
00146 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k - mSize));
00147 }
00148 }
00149
00150 i = mSize - 1;
00151 for (j=1; j<mSize-1; j++)
00152 {
00153 k = i + j * mSize;
00154 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k) - *(mCloudDensityp + k - 2));
00155 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k - mSize));
00156 }
00157 i = 0;
00158 for (j=1; j<mSize-1; j++)
00159 {
00160 k = i + j * mSize;
00161 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 2) - *(mCloudDensityp + k));
00162 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k + mSize));
00163 }
00164 j = mSize - 1;
00165 for (i=1; i<mSize-1; i++)
00166 {
00167 k = i + j * mSize;
00168 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k - 1));
00169 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k) - *(mCloudDensityp + k - 2*mSize));
00170 }
00171 j = 0;
00172 for (i=1; i<mSize-1; i++)
00173 {
00174 k = i + j * mSize;
00175 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k -1));
00176 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 2*mSize) - *(mCloudDensityp + k));
00177 }
00178 }
00179
00180
00181 LLVector3 LLWind::getAverage()
00182 {
00183
00184 LLVector3 average(0.0f, 0.0f, 0.0f);
00185 S32 i, grid_count;
00186 grid_count = mSize * mSize;
00187 for (i = 0; i < grid_count; i++)
00188 {
00189 average.mV[VX] += mVelX[i];
00190 average.mV[VY] += mVelY[i];
00191 }
00192
00193 average *= 1.f/((F32)(grid_count)) * WIND_SCALE_HACK;
00194 return average;
00195 }
00196
00197
00198 LLVector3 LLWind::getVelocityNoisy(const LLVector3 &pos_region, const F32 dim)
00199 {
00200
00201 LLVector3 r_val(0,0,0);
00202 F32 norm = 1.0f;
00203 if (dim == 8)
00204 {
00205 norm = 1.875;
00206 }
00207 else if (dim == 4)
00208 {
00209 norm = 1.75;
00210 }
00211 else if (dim == 2)
00212 {
00213 norm = 1.5;
00214 }
00215
00216 F32 temp_dim = dim;
00217 while (temp_dim >= 1.0)
00218 {
00219 LLVector3 pos_region_scaled(pos_region * temp_dim);
00220 r_val += getVelocity(pos_region_scaled) * (1.0f/temp_dim);
00221 temp_dim /= 2.0;
00222 }
00223
00224 return r_val * (1.0f/norm) * WIND_SCALE_HACK;
00225 }
00226
00227
00228 LLVector3 LLWind::getVelocity(const LLVector3 &pos_region)
00229 {
00230 llassert(mSize == 16);
00231
00232
00233
00234 LLVector3 r_val;
00235 F32 dx,dy;
00236 S32 k;
00237
00238 LLVector3 pos_clamped_region(pos_region);
00239
00240 F32 region_width_meters = LLWorld::getInstance()->getRegionWidthInMeters();
00241
00242 if (pos_clamped_region.mV[VX] < 0.f)
00243 {
00244 pos_clamped_region.mV[VX] = 0.f;
00245 }
00246 else if (pos_clamped_region.mV[VX] >= region_width_meters)
00247 {
00248 pos_clamped_region.mV[VX] = (F32) fmod(pos_clamped_region.mV[VX], region_width_meters);
00249 }
00250
00251 if (pos_clamped_region.mV[VY] < 0.f)
00252 {
00253 pos_clamped_region.mV[VY] = 0.f;
00254 }
00255 else if (pos_clamped_region.mV[VY] >= region_width_meters)
00256 {
00257 pos_clamped_region.mV[VY] = (F32) fmod(pos_clamped_region.mV[VY], region_width_meters);
00258 }
00259
00260
00261 S32 i = llfloor(pos_clamped_region.mV[VX] * mSize / region_width_meters);
00262 S32 j = llfloor(pos_clamped_region.mV[VY] * mSize / region_width_meters);
00263 k = i + j*mSize;
00264 dx = ((pos_clamped_region.mV[VX] * mSize / region_width_meters) - (F32) i);
00265 dy = ((pos_clamped_region.mV[VY] * mSize / region_width_meters) - (F32) j);
00266
00267 if ((i < mSize-1) && (j < mSize-1))
00268 {
00269
00270 r_val.mV[VX] = mVelX[k]*(1.0f - dx)*(1.0f - dy) +
00271 mVelX[k + 1]*dx*(1.0f - dy) +
00272 mVelX[k + mSize]*dy*(1.0f - dx) +
00273 mVelX[k + mSize + 1]*dx*dy;
00274 r_val.mV[VY] = mVelY[k]*(1.0f - dx)*(1.0f - dy) +
00275 mVelY[k + 1]*dx*(1.0f - dy) +
00276 mVelY[k + mSize]*dy*(1.0f - dx) +
00277 mVelY[k + mSize + 1]*dx*dy;
00278 }
00279 else
00280 {
00281 r_val.mV[VX] = mVelX[k];
00282 r_val.mV[VY] = mVelY[k];
00283 }
00284
00285 r_val.mV[VZ] = 0.f;
00286 return r_val * WIND_SCALE_HACK;
00287 }
00288
00289
00290 LLVector3 LLWind::getCloudVelocity(const LLVector3 &pos_region)
00291 {
00292 llassert(mSize == 16);
00293
00294
00295
00296 LLVector3 r_val;
00297 F32 dx,dy;
00298 S32 k;
00299
00300 LLVector3 pos_clamped_region(pos_region);
00301
00302 F32 region_width_meters = LLWorld::getInstance()->getRegionWidthInMeters();
00303
00304 if (pos_clamped_region.mV[VX] < 0.f)
00305 {
00306 pos_clamped_region.mV[VX] = 0.f;
00307 }
00308 else if (pos_clamped_region.mV[VX] >= region_width_meters)
00309 {
00310 pos_clamped_region.mV[VX] = (F32) fmod(pos_clamped_region.mV[VX], region_width_meters);
00311 }
00312
00313 if (pos_clamped_region.mV[VY] < 0.f)
00314 {
00315 pos_clamped_region.mV[VY] = 0.f;
00316 }
00317 else if (pos_clamped_region.mV[VY] >= region_width_meters)
00318 {
00319 pos_clamped_region.mV[VY] = (F32) fmod(pos_clamped_region.mV[VY], region_width_meters);
00320 }
00321
00322
00323 S32 i = llfloor(pos_clamped_region.mV[VX] * mSize / region_width_meters);
00324 S32 j = llfloor(pos_clamped_region.mV[VY] * mSize / region_width_meters);
00325 k = i + j*mSize;
00326 dx = ((pos_clamped_region.mV[VX] * mSize / region_width_meters) - (F32) i);
00327 dy = ((pos_clamped_region.mV[VY] * mSize / region_width_meters) - (F32) j);
00328
00329 if ((i < mSize-1) && (j < mSize-1))
00330 {
00331
00332 r_val.mV[VX] = mCloudVelX[k]*(1.0f - dx)*(1.0f - dy) +
00333 mCloudVelX[k + 1]*dx*(1.0f - dy) +
00334 mCloudVelX[k + mSize]*dy*(1.0f - dx) +
00335 mCloudVelX[k + mSize + 1]*dx*dy;
00336 r_val.mV[VY] = mCloudVelY[k]*(1.0f - dx)*(1.0f - dy) +
00337 mCloudVelY[k + 1]*dx*(1.0f - dy) +
00338 mCloudVelY[k + mSize]*dy*(1.0f - dx) +
00339 mCloudVelY[k + mSize + 1]*dx*dy;
00340 }
00341 else
00342 {
00343 r_val.mV[VX] = mCloudVelX[k];
00344 r_val.mV[VY] = mCloudVelY[k];
00345 }
00346
00347 r_val.mV[VZ] = 0.f;
00348 return r_val * WIND_SCALE_HACK;
00349 }
00350
00351
00352 void LLWind::setCloudDensityPointer(F32 *densityp)
00353 {
00354 mCloudDensityp = densityp;
00355 }
00356
00357 void LLWind::setOriginGlobal(const LLVector3d &origin_global)
00358 {
00359 mOriginGlobal = origin_global;
00360 }
00361
00362