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 "llagent.h"
00052 #include "llworld.h"
00053 
00054 
00055 const F32 CLOUD_DIVERGENCE_COEF = 0.5f; 
00056 
00057 
00059 // Construction/Destruction
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 // Public Methods
00082 
00083 
00084 void LLWind::init()
00085 {
00086         // Initialize vector data
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         // Don't use the packed group_header stride because the strides used on
00117         // simulator and viewer are not equal.
00118         group_headerp->stride = group_headerp->patch_size;      
00119         set_group_of_patch_header(group_headerp);
00120 
00121         // X component
00122         decode_patch_header(bitpack, &patch_header);
00123         decode_patch(bitpack, buffer);
00124         decompress_patch(mVelX, buffer, &patch_header);
00125 
00126         // Y component
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         // HACK -- mCloudVelXY is the same as mVelXY, except we add a divergence
00135         // that is proportional to the gradient of the cloud density 
00136         // ==> this helps to clump clouds together
00137         // NOTE ASSUMPTION: cloud density has the same dimensions as the wind field
00138         // This needs to be fixed... causes discrepency at region boundaries
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         //  Returns in average_wind the average wind velocity 
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         //  Resolve a value, using fractal summing to perturb the returned value 
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         // Resolves value of wind at a location relative to SW corner of region
00232         //  
00233         // Returns wind magnitude in X,Y components of vector3
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                 //  Interior points, no edges
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         // Resolves value of wind at a location relative to SW corner of region
00294         //  
00295         // Returns wind magnitude in X,Y components of vector3
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                 //  Interior points, no edges
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 

Generated on Fri May 16 08:34:25 2008 for SecondLife by  doxygen 1.5.5