llwind.cpp

Go to the documentation of this file.
00001 
00032 // Wind is a lattice.  It is computed on the simulator, and transmitted to the viewer.
00033 // It drives special effects like smoke blowing, trees bending, and grass wiggling.
00034 //
00035 // Currently wind lattice does not interpolate correctly to neighbors.  This will need 
00036 // work.
00037 
00038 #include "llviewerprecompiledheaders.h"
00039 #include "indra_constants.h"
00040 
00041 #include "llwind.h"
00042 
00043 // linden libraries
00044 #include "llgl.h"
00045 #include "patch_dct.h"
00046 #include "patch_code.h"
00047 
00048 // viewer
00049 #include "noise.h"
00050 #include "v4color.h"
00051 #include "viewer.h"
00052 #include "llagent.h"
00053 #include "llworld.h"
00054 
00055 
00056 const F32 CLOUD_DIVERGENCE_COEF = 0.5f; 
00057 
00058 
00060 // Construction/Destruction
00062 
00063 LLWind::LLWind()
00064 :       mSize(16),
00065         mCloudDensityp(NULL)
00066 {
00067         init();
00068 }
00069 
00070 
00071 LLWind::~LLWind()
00072 {
00073         delete [] mVelX;
00074         delete [] mVelY;
00075         delete [] mCloudVelX;
00076         delete [] mCloudVelY;
00077 }
00078 
00079 
00081 // Public Methods
00083 
00084 
00085 void LLWind::init()
00086 {
00087         // Initialize vector data
00088         mVelX = new F32[mSize*mSize];
00089         mVelY = new F32[mSize*mSize];
00090 
00091         mCloudVelX = new F32[mSize*mSize];
00092         mCloudVelY = new F32[mSize*mSize];
00093 
00094         S32 i;
00095         for (i = 0; i < mSize*mSize; i++)
00096         {
00097                 mVelX[i] = 0.5f;
00098                 mVelY[i] = 0.5f;
00099                 mCloudVelX[i] = 0.0f;
00100                 mCloudVelY[i] = 0.0f;
00101         }
00102 }
00103 
00104 
00105 void LLWind::decompress(LLBitPack &bitpack, LLGroupHeader *group_headerp)
00106 {
00107         if (!mCloudDensityp)
00108         {
00109                 return;
00110         }
00111 
00112         LLPatchHeader  patch_header;
00113         S32 buffer[16*16];
00114 
00115         init_patch_decompressor(group_headerp->patch_size);
00116 
00117         // Don't use the packed group_header stride because the strides used on
00118         // simulator and viewer are not equal.
00119         group_headerp->stride = group_headerp->patch_size;      
00120         set_group_of_patch_header(group_headerp);
00121 
00122         // X component
00123         decode_patch_header(bitpack, &patch_header);
00124         decode_patch(bitpack, buffer);
00125         decompress_patch(mVelX, buffer, &patch_header);
00126 
00127         // Y component
00128         decode_patch_header(bitpack, &patch_header);
00129         decode_patch(bitpack, buffer);
00130         decompress_patch(mVelY, buffer, &patch_header);
00131 
00132 
00133 
00134         S32 i, j, k;
00135         // HACK -- mCloudVelXY is the same as mVelXY, except we add a divergence
00136         // that is proportional to the gradient of the cloud density 
00137         // ==> this helps to clump clouds together
00138         // NOTE ASSUMPTION: cloud density has the same dimensions as the wind field
00139         // This needs to be fixed... causes discrepency at region boundaries
00140 
00141         for (j=1; j<mSize-1; j++)
00142         {
00143                 for (i=1; i<mSize-1; i++)
00144                 {
00145                         k = i + j * mSize;
00146                         *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k - 1));
00147                         *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k - mSize));
00148                 }
00149         }
00150 
00151         i = mSize - 1;
00152         for (j=1; j<mSize-1; j++)
00153         {
00154                 k = i + j * mSize;
00155                 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k) - *(mCloudDensityp + k - 2));
00156                 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k - mSize));
00157         }
00158         i = 0;
00159         for (j=1; j<mSize-1; j++)
00160         {
00161                 k = i + j * mSize;
00162                 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 2) - *(mCloudDensityp + k));
00163                 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + mSize) - *(mCloudDensityp + k + mSize));
00164         }
00165         j = mSize - 1;
00166         for (i=1; i<mSize-1; i++)
00167         {
00168                 k = i + j * mSize;
00169                 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k - 1));
00170                 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k) - *(mCloudDensityp + k - 2*mSize));
00171         }
00172         j = 0;
00173         for (i=1; i<mSize-1; i++)
00174         {
00175                 k = i + j * mSize;
00176                 *(mCloudVelX + k) = *(mVelX + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 1) - *(mCloudDensityp + k -1));
00177                 *(mCloudVelY + k) = *(mVelY + k) + CLOUD_DIVERGENCE_COEF * (*(mCloudDensityp + k + 2*mSize) - *(mCloudDensityp + k));
00178         }
00179 }
00180 
00181 
00182 LLVector3 LLWind::getAverage()
00183 {
00184         //  Returns in average_wind the average wind velocity 
00185         LLVector3 average(0.0f, 0.0f, 0.0f);    
00186         S32 i, grid_count;
00187         grid_count = mSize * mSize;
00188         for (i = 0; i < grid_count; i++)
00189         {
00190                 average.mV[VX] += mVelX[i];
00191                 average.mV[VY] += mVelY[i];
00192         }
00193 
00194         average *= 1.f/((F32)(grid_count)) * WIND_SCALE_HACK;
00195         return average;
00196 }
00197 
00198 
00199 LLVector3 LLWind::getVelocityNoisy(const LLVector3 &pos_region, const F32 dim)
00200 {
00201         //  Resolve a value, using fractal summing to perturb the returned value 
00202         LLVector3 r_val(0,0,0);
00203         F32 norm = 1.0f;
00204         if (dim == 8)
00205         {
00206                 norm = 1.875;
00207         }
00208         else if (dim == 4)
00209         {
00210                 norm = 1.75;
00211         }
00212         else if (dim == 2)
00213         {
00214                 norm = 1.5;
00215         }
00216 
00217         F32 temp_dim = dim;
00218         while (temp_dim >= 1.0)
00219         {
00220                 LLVector3 pos_region_scaled(pos_region * temp_dim);
00221                 r_val += getVelocity(pos_region_scaled) * (1.0f/temp_dim);
00222                 temp_dim /= 2.0;
00223         }
00224         
00225         return r_val * (1.0f/norm) * WIND_SCALE_HACK;
00226 }
00227 
00228 
00229 LLVector3 LLWind::getVelocity(const LLVector3 &pos_region)
00230 {
00231         llassert(mSize == 16);
00232         // Resolves value of wind at a location relative to SW corner of region
00233         //  
00234         // Returns wind magnitude in X,Y components of vector3
00235         LLVector3 r_val;
00236         F32 dx,dy;
00237         S32 k;
00238 
00239         LLVector3 pos_clamped_region(pos_region);
00240         
00241         F32 region_width_meters = gWorldPointer->getRegionWidthInMeters();
00242 
00243         if (pos_clamped_region.mV[VX] < 0.f)
00244         {
00245                 pos_clamped_region.mV[VX] = 0.f;
00246         }
00247         else if (pos_clamped_region.mV[VX] >= region_width_meters)
00248         {
00249                 pos_clamped_region.mV[VX] = (F32) fmod(pos_clamped_region.mV[VX], region_width_meters);
00250         }
00251 
00252         if (pos_clamped_region.mV[VY] < 0.f)
00253         {
00254                 pos_clamped_region.mV[VY] = 0.f;
00255         }
00256         else if (pos_clamped_region.mV[VY] >= region_width_meters)
00257         {
00258                 pos_clamped_region.mV[VY] = (F32) fmod(pos_clamped_region.mV[VY], region_width_meters);
00259         }
00260         
00261         
00262         S32 i = llfloor(pos_clamped_region.mV[VX] * mSize / region_width_meters);
00263         S32 j = llfloor(pos_clamped_region.mV[VY] * mSize / region_width_meters);
00264         k = i + j*mSize;
00265         dx = ((pos_clamped_region.mV[VX] * mSize / region_width_meters) - (F32) i);
00266         dy = ((pos_clamped_region.mV[VY] * mSize / region_width_meters) - (F32) j);
00267 
00268         if ((i < mSize-1) && (j < mSize-1))
00269         {
00270                 //  Interior points, no edges
00271                 r_val.mV[VX] =  mVelX[k]*(1.0f - dx)*(1.0f - dy) + 
00272                                                 mVelX[k + 1]*dx*(1.0f - dy) + 
00273                                                 mVelX[k + mSize]*dy*(1.0f - dx) + 
00274                                                 mVelX[k + mSize + 1]*dx*dy;
00275                 r_val.mV[VY] =  mVelY[k]*(1.0f - dx)*(1.0f - dy) + 
00276                                                 mVelY[k + 1]*dx*(1.0f - dy) + 
00277                                                 mVelY[k + mSize]*dy*(1.0f - dx) + 
00278                                                 mVelY[k + mSize + 1]*dx*dy;
00279         }
00280         else 
00281         {
00282                 r_val.mV[VX] = mVelX[k];
00283                 r_val.mV[VY] = mVelY[k];
00284         }
00285 
00286         r_val.mV[VZ] = 0.f;
00287         return r_val * WIND_SCALE_HACK;
00288 }
00289 
00290 
00291 LLVector3 LLWind::getCloudVelocity(const LLVector3 &pos_region)
00292 {
00293         llassert(mSize == 16);
00294         // Resolves value of wind at a location relative to SW corner of region
00295         //  
00296         // Returns wind magnitude in X,Y components of vector3
00297         LLVector3 r_val;
00298         F32 dx,dy;
00299         S32 k;
00300 
00301         LLVector3 pos_clamped_region(pos_region);
00302         
00303         F32 region_width_meters = gWorldPointer->getRegionWidthInMeters();
00304 
00305         if (pos_clamped_region.mV[VX] < 0.f)
00306         {
00307                 pos_clamped_region.mV[VX] = 0.f;
00308         }
00309         else if (pos_clamped_region.mV[VX] >= region_width_meters)
00310         {
00311                 pos_clamped_region.mV[VX] = (F32) fmod(pos_clamped_region.mV[VX], region_width_meters);
00312         }
00313 
00314         if (pos_clamped_region.mV[VY] < 0.f)
00315         {
00316                 pos_clamped_region.mV[VY] = 0.f;
00317         }
00318         else if (pos_clamped_region.mV[VY] >= region_width_meters)
00319         {
00320                 pos_clamped_region.mV[VY] = (F32) fmod(pos_clamped_region.mV[VY], region_width_meters);
00321         }
00322         
00323         
00324         S32 i = llfloor(pos_clamped_region.mV[VX] * mSize / region_width_meters);
00325         S32 j = llfloor(pos_clamped_region.mV[VY] * mSize / region_width_meters);
00326         k = i + j*mSize;
00327         dx = ((pos_clamped_region.mV[VX] * mSize / region_width_meters) - (F32) i);
00328         dy = ((pos_clamped_region.mV[VY] * mSize / region_width_meters) - (F32) j);
00329 
00330         if ((i < mSize-1) && (j < mSize-1))
00331         {
00332                 //  Interior points, no edges
00333                 r_val.mV[VX] =  mCloudVelX[k]*(1.0f - dx)*(1.0f - dy) + 
00334                                                 mCloudVelX[k + 1]*dx*(1.0f - dy) + 
00335                                                 mCloudVelX[k + mSize]*dy*(1.0f - dx) + 
00336                                                 mCloudVelX[k + mSize + 1]*dx*dy;
00337                 r_val.mV[VY] =  mCloudVelY[k]*(1.0f - dx)*(1.0f - dy) + 
00338                                                 mCloudVelY[k + 1]*dx*(1.0f - dy) + 
00339                                                 mCloudVelY[k + mSize]*dy*(1.0f - dx) + 
00340                                                 mCloudVelY[k + mSize + 1]*dx*dy;
00341         }
00342         else 
00343         {
00344                 r_val.mV[VX] = mCloudVelX[k];
00345                 r_val.mV[VY] = mCloudVelY[k];
00346         }
00347 
00348         r_val.mV[VZ] = 0.f;
00349         return r_val * WIND_SCALE_HACK;
00350 }
00351 
00352 
00353 void LLWind::setCloudDensityPointer(F32 *densityp)
00354 {
00355         mCloudDensityp = densityp;
00356 }
00357 
00358 void LLWind::setOriginGlobal(const LLVector3d &origin_global)
00359 {
00360         mOriginGlobal = origin_global;
00361 }
00362 
00363 

Generated on Thu Jul 1 06:09:45 2010 for Second Life Viewer by  doxygen 1.4.7