00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llsurface.h"
00035
00036 #include "llviewerimagelist.h"
00037 #include "llpatchvertexarray.h"
00038 #include "patch_dct.h"
00039 #include "patch_code.h"
00040 #include "bitpack.h"
00041 #include "llviewerobjectlist.h"
00042 #include "llregionhandle.h"
00043 #include "llagent.h"
00044 #include "llappviewer.h"
00045 #include "llworld.h"
00046 #include "llviewercontrol.h"
00047 #include "llviewerimage.h"
00048 #include "llsurfacepatch.h"
00049 #include "llvosurfacepatch.h"
00050 #include "llvowater.h"
00051 #include "pipeline.h"
00052 #include "llviewerregion.h"
00053 #include "llvlcomposition.h"
00054 #include "noise.h"
00055 #include "llviewercamera.h"
00056 #include "llglheaders.h"
00057 #include "lldrawpoolterrain.h"
00058 #include "lldrawable.h"
00059
00060 extern LLPipeline gPipeline;
00061
00062 LLColor4U MAX_WATER_COLOR(0, 48, 96, 240);
00063
00064
00065 S32 LLSurface::sTextureSize = 256;
00066 S32 LLSurface::sTexelsUpdated = 0;
00067 F32 LLSurface::sTextureUpdateTime = 0.f;
00068 LLStat LLSurface::sTexelsUpdatedPerSecStat;
00069
00070
00071
00072 LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) :
00073 mGridsPerEdge(0),
00074 mOOGridsPerEdge(0.f),
00075 mPatchesPerEdge(0),
00076 mType(type),
00077 mOriginGlobal(0.0, 0.0, 0.0),
00078 mSTexturep(NULL),
00079 mWaterTexturep(NULL),
00080 mGridsPerPatchEdge(0),
00081 mMetersPerGrid(1.0f),
00082 mMetersPerEdge(1.0f),
00083 mRegionp(regionp)
00084 {
00085
00086 mSurfaceZ = NULL;
00087 mNorm = NULL;
00088
00089
00090 mPatchList = NULL;
00091
00092
00093 mVisiblePatchCount = 0;
00094
00095 mHasZData = FALSE;
00096
00097 mMinZ = 10000.f;
00098 mMaxZ = -10000.f;
00099
00100 mWaterObjp = NULL;
00101
00102
00103 mSurfacePatchUpdateCount = 0;
00104
00105 for (S32 i = 0; i < 8; i++)
00106 {
00107 mNeighbors[i] = NULL;
00108 }
00109 }
00110
00111
00112 LLSurface::~LLSurface()
00113 {
00114 delete [] mSurfaceZ;
00115 mSurfaceZ = NULL;
00116
00117 delete [] mNorm;
00118
00119 mGridsPerEdge = 0;
00120 mGridsPerPatchEdge = 0;
00121 mPatchesPerEdge = 0;
00122 mNumberOfPatches = 0;
00123 destroyPatchData();
00124
00125 LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep);
00126 if (!poolp)
00127 {
00128 llwarns << "No pool for terrain on destruction!" << llendl;
00129 }
00130 else if (poolp->mReferences.empty())
00131 {
00132 gPipeline.removePool(poolp);
00133
00134 if (mSTexturep)
00135 {
00136 gImageList.deleteImage(mSTexturep);
00137 mSTexturep = NULL;
00138 }
00139 if (mWaterTexturep)
00140 {
00141 gImageList.deleteImage(mWaterTexturep);
00142 mWaterTexturep = NULL;
00143 }
00144 }
00145 else
00146 {
00147 llerrs << "Terrain pool not empty!" << llendl;
00148 }
00149 }
00150
00151 void LLSurface::initClasses()
00152 {
00153 }
00154
00155 void LLSurface::setRegion(LLViewerRegion *regionp)
00156 {
00157 mRegionp = regionp;
00158 }
00159
00160
00161
00162 void LLSurface::create(const S32 grids_per_edge,
00163 const S32 grids_per_patch_edge,
00164 const LLVector3d &origin_global,
00165 const F32 width)
00166 {
00167
00168 mGridsPerEdge = grids_per_edge + 1;
00169 mOOGridsPerEdge = 1.f / mGridsPerEdge;
00170 mGridsPerPatchEdge = grids_per_patch_edge;
00171 mPatchesPerEdge = (mGridsPerEdge - 1) / mGridsPerPatchEdge;
00172 mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge;
00173 mMetersPerGrid = width / ((F32)(mGridsPerEdge - 1));
00174 mMetersPerEdge = mMetersPerGrid * (mGridsPerEdge - 1);
00175
00176 mOriginGlobal.setVec(origin_global);
00177
00178 mPVArray.create(mGridsPerEdge, mGridsPerPatchEdge, LLWorld::getInstance()->getRegionScale());
00179
00180 S32 number_of_grids = mGridsPerEdge * mGridsPerEdge;
00181
00183
00184
00186 mSurfaceZ = new F32[number_of_grids];
00187 mNorm = new LLVector3[number_of_grids];
00188
00189
00190 for(S32 i=0; i < number_of_grids; i++)
00191 {
00192
00193
00194 mSurfaceZ[i] = 0.0f;
00195 mNorm[i].setVec(0.f, 0.f, 1.f);
00196 }
00197
00198
00199 mVisiblePatchCount = 0;
00200
00201
00203
00204
00205
00206
00207 initTextures();
00208
00209
00210 createPatchData();
00211 }
00212
00213 LLViewerImage* LLSurface::getSTexture()
00214 {
00215 if (mSTexturep.notNull() && !mSTexturep->getHasGLTexture())
00216 {
00217 createSTexture();
00218 }
00219 return mSTexturep;
00220 }
00221
00222 LLViewerImage* LLSurface::getWaterTexture()
00223 {
00224 if (mWaterTexturep.notNull() && !mWaterTexturep->getHasGLTexture())
00225 {
00226 createWaterTexture();
00227 }
00228 return mWaterTexturep;
00229 }
00230
00231 void LLSurface::createSTexture()
00232 {
00233 if (!mSTexturep)
00234 {
00235
00236 LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3);
00237 U8 *default_texture = raw->getData();
00238 for (S32 i = 0; i < sTextureSize; i++)
00239 {
00240 for (S32 j = 0; j < sTextureSize; j++)
00241 {
00242 *(default_texture + (i*sTextureSize + j)*3) = 128;
00243 *(default_texture + (i*sTextureSize + j)*3 + 1) = 128;
00244 *(default_texture + (i*sTextureSize + j)*3 + 2) = 128;
00245 }
00246 }
00247
00248 mSTexturep = new LLViewerImage(raw, FALSE);
00249 mSTexturep->dontDiscard();
00250 mSTexturep->bind();
00251 mSTexturep->setClamp(TRUE, TRUE);
00252 gImageList.addImage(mSTexturep);
00253 }
00254 }
00255
00256 void LLSurface::createWaterTexture()
00257 {
00258 if (!mWaterTexturep)
00259 {
00260
00261 LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4);
00262 U8 *default_texture = raw->getData();
00263 for (S32 i = 0; i < sTextureSize/2; i++)
00264 {
00265 for (S32 j = 0; j < sTextureSize/2; j++)
00266 {
00267 *(default_texture + (i*sTextureSize/2 + j)*4) = MAX_WATER_COLOR.mV[0];
00268 *(default_texture + (i*sTextureSize/2 + j)*4 + 1) = MAX_WATER_COLOR.mV[1];
00269 *(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2];
00270 *(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3];
00271 }
00272 }
00273 mWaterTexturep = new LLViewerImage(raw, FALSE);
00274 mWaterTexturep->dontDiscard();
00275 mWaterTexturep->bind();
00276 mWaterTexturep->setClamp(TRUE, TRUE);
00277 gImageList.addImage(mWaterTexturep);
00278 }
00279 }
00280
00281 void LLSurface::initTextures()
00282 {
00284
00285
00286
00287 createSTexture();
00288
00290
00291
00292
00293 if (gSavedSettings.getBOOL("RenderWater") )
00294 {
00295 createWaterTexture();
00296 mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp);
00297 gPipeline.addObject(mWaterObjp);
00298 LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle());
00299 water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT);
00300 mWaterObjp->setPositionGlobal(water_pos_global);
00301 }
00302 }
00303
00304
00305 void LLSurface::setOriginGlobal(const LLVector3d &origin_global)
00306 {
00307 LLVector3d new_origin_global;
00308 mOriginGlobal = origin_global;
00309 LLSurfacePatch *patchp;
00310 S32 i, j;
00311
00312 for (j=0; j<mPatchesPerEdge; j++)
00313 {
00314 for (i=0; i<mPatchesPerEdge; i++)
00315 {
00316 patchp = getPatch(i, j);
00317
00318 new_origin_global = patchp->getOriginGlobal();
00319
00320 new_origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge;
00321 new_origin_global.mdV[1] = mOriginGlobal.mdV[1] + j * mMetersPerGrid * mGridsPerPatchEdge;
00322 patchp->setOriginGlobal(new_origin_global);
00323 }
00324 }
00325
00326
00327 if (mWaterObjp.notNull() && mWaterObjp->mDrawable.notNull())
00328 {
00329 const F64 x = origin_global.mdV[VX] + 128.0;
00330 const F64 y = origin_global.mdV[VY] + 128.0;
00331 const F64 z = mWaterObjp->getPositionGlobal().mdV[VZ];
00332
00333 LLVector3d water_origin_global(x, y, z);
00334
00335 mWaterObjp->setPositionGlobal(water_origin_global);
00336 }
00337 }
00338
00339
00340 void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
00341 {
00342 S32 i;
00343 LLSurfacePatch *patchp, *neighbor_patchp;
00344
00345 if (gNoRender)
00346 {
00347 return;
00348 }
00349
00350 mNeighbors[direction] = neighborp;
00351 neighborp->mNeighbors[gDirOpposite[direction]] = this;
00352
00353
00354 if (NORTHEAST == direction)
00355 {
00356 patchp = getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1);
00357 neighbor_patchp = neighborp->getPatch(0, 0);
00358
00359 patchp->connectNeighbor(neighbor_patchp, direction);
00360 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
00361
00362 patchp->updateNorthEdge();
00363 patchp->dirtyZ();
00364 }
00365 else if (NORTHWEST == direction)
00366 {
00367 patchp = getPatch(0, mPatchesPerEdge - 1);
00368 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, 0);
00369
00370 patchp->connectNeighbor(neighbor_patchp, direction);
00371 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
00372 }
00373 else if (SOUTHWEST == direction)
00374 {
00375 patchp = getPatch(0, 0);
00376 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1);
00377
00378 patchp->connectNeighbor(neighbor_patchp, direction);
00379 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
00380
00381 neighbor_patchp->updateNorthEdge();
00382 neighbor_patchp->dirtyZ();
00383 }
00384 else if (SOUTHEAST == direction)
00385 {
00386 patchp = getPatch(mPatchesPerEdge - 1, 0);
00387 neighbor_patchp = neighborp->getPatch(0, mPatchesPerEdge - 1);
00388
00389 patchp->connectNeighbor(neighbor_patchp, direction);
00390 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
00391 }
00392 else if (EAST == direction)
00393 {
00394
00395 for (i = 0; i < (S32)mPatchesPerEdge; i++)
00396 {
00397 patchp = getPatch(mPatchesPerEdge - 1, i);
00398 neighbor_patchp = neighborp->getPatch(0, i);
00399
00400 patchp->connectNeighbor(neighbor_patchp, direction);
00401 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
00402
00403 patchp->updateEastEdge();
00404 patchp->dirtyZ();
00405 }
00406
00407
00408 for (i = 0; i < (S32)mPatchesPerEdge - 1; i++)
00409 {
00410 patchp = getPatch(mPatchesPerEdge - 1, i);
00411 neighbor_patchp = neighborp->getPatch(0, i+1);
00412
00413 patchp->connectNeighbor(neighbor_patchp, NORTHEAST);
00414 neighbor_patchp->connectNeighbor(patchp, SOUTHWEST);
00415 }
00416
00417 for (i = 1; i < (S32)mPatchesPerEdge; i++)
00418 {
00419 patchp = getPatch(mPatchesPerEdge - 1, i);
00420 neighbor_patchp = neighborp->getPatch(0, i-1);
00421
00422 patchp->connectNeighbor(neighbor_patchp, SOUTHEAST);
00423 neighbor_patchp->connectNeighbor(patchp, NORTHWEST);
00424 }
00425 }
00426 else if (NORTH == direction)
00427 {
00428
00429 for (i = 0; i < (S32)mPatchesPerEdge; i++)
00430 {
00431 patchp = getPatch(i, mPatchesPerEdge - 1);
00432 neighbor_patchp = neighborp->getPatch(i, 0);
00433
00434 patchp->connectNeighbor(neighbor_patchp, direction);
00435 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
00436
00437 patchp->updateNorthEdge();
00438 patchp->dirtyZ();
00439 }
00440
00441
00442 for (i = 0; i < (S32)mPatchesPerEdge - 1; i++)
00443 {
00444 patchp = getPatch(i, mPatchesPerEdge - 1);
00445 neighbor_patchp = neighborp->getPatch(i+1, 0);
00446
00447 patchp->connectNeighbor(neighbor_patchp, NORTHEAST);
00448 neighbor_patchp->connectNeighbor(patchp, SOUTHWEST);
00449 }
00450
00451 for (i = 1; i < (S32)mPatchesPerEdge; i++)
00452 {
00453 patchp = getPatch(i, mPatchesPerEdge - 1);
00454 neighbor_patchp = neighborp->getPatch(i-1, 0);
00455
00456 patchp->connectNeighbor(neighbor_patchp, NORTHWEST);
00457 neighbor_patchp->connectNeighbor(patchp, SOUTHEAST);
00458 }
00459 }
00460 else if (WEST == direction)
00461 {
00462
00463 for (i = 0; i < mPatchesPerEdge; i++)
00464 {
00465 patchp = getPatch(0, i);
00466 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i);
00467
00468 patchp->connectNeighbor(neighbor_patchp, direction);
00469 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
00470
00471 neighbor_patchp->updateEastEdge();
00472 neighbor_patchp->dirtyZ();
00473 }
00474
00475
00476 for (i = 1; i < mPatchesPerEdge; i++)
00477 {
00478 patchp = getPatch(0, i);
00479 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i - 1);
00480
00481 patchp->connectNeighbor(neighbor_patchp, SOUTHWEST);
00482 neighbor_patchp->connectNeighbor(patchp, NORTHEAST);
00483 }
00484
00485
00486 for (i = 0; i < mPatchesPerEdge - 1; i++)
00487 {
00488 patchp = getPatch(0, i);
00489 neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i + 1);
00490
00491 patchp->connectNeighbor(neighbor_patchp, NORTHWEST);
00492 neighbor_patchp->connectNeighbor(patchp, SOUTHEAST);
00493 }
00494 }
00495 else if (SOUTH == direction)
00496 {
00497
00498 for (i = 0; i < mPatchesPerEdge; i++)
00499 {
00500 patchp = getPatch(i, 0);
00501 neighbor_patchp = neighborp->getPatch(i, mPatchesPerEdge - 1);
00502
00503 patchp->connectNeighbor(neighbor_patchp, direction);
00504 neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
00505
00506 neighbor_patchp->updateNorthEdge();
00507 neighbor_patchp->dirtyZ();
00508 }
00509
00510
00511 for (i = 1; i < mPatchesPerEdge; i++)
00512 {
00513 patchp = getPatch(i, 0);
00514 neighbor_patchp = neighborp->getPatch(i - 1, mPatchesPerEdge - 1);
00515
00516 patchp->connectNeighbor(neighbor_patchp, SOUTHWEST);
00517 neighbor_patchp->connectNeighbor(patchp, NORTHEAST);
00518 }
00519
00520 for (i = 0; i < mPatchesPerEdge - 1; i++)
00521 {
00522 patchp = getPatch(i, 0);
00523 neighbor_patchp = neighborp->getPatch(i + 1, mPatchesPerEdge - 1);
00524
00525 patchp->connectNeighbor(neighbor_patchp, SOUTHEAST);
00526 neighbor_patchp->connectNeighbor(patchp, NORTHWEST);
00527 }
00528 }
00529 }
00530
00531 void LLSurface::disconnectNeighbor(LLSurface *surfacep)
00532 {
00533 S32 i;
00534 for (i = 0; i < 8; i++)
00535 {
00536 if (surfacep == mNeighbors[i])
00537 {
00538 mNeighbors[i] = NULL;
00539 }
00540 }
00541
00542
00543 for (i = 0; i < mNumberOfPatches; i++)
00544 {
00545 (mPatchList + i)->disconnectNeighbor(surfacep);
00546 }
00547 }
00548
00549
00550 void LLSurface::disconnectAllNeighbors()
00551 {
00552 S32 i;
00553 for (i = 0; i < 8; i++)
00554 {
00555 if (mNeighbors[i])
00556 {
00557 mNeighbors[i]->disconnectNeighbor(this);
00558 mNeighbors[i] = NULL;
00559 }
00560 }
00561 }
00562
00563
00564
00565 const LLVector3d &LLSurface::getOriginGlobal() const
00566 {
00567 return mOriginGlobal;
00568 }
00569
00570 LLVector3 LLSurface::getOriginAgent() const
00571 {
00572 return gAgent.getPosAgentFromGlobal(mOriginGlobal);
00573 }
00574
00575 F32 LLSurface::getMetersPerGrid() const
00576 {
00577 return mMetersPerGrid;
00578 }
00579
00580 S32 LLSurface::getGridsPerEdge() const
00581 {
00582 return mGridsPerEdge;
00583 }
00584
00585 S32 LLSurface::getPatchesPerEdge() const
00586 {
00587 return mPatchesPerEdge;
00588 }
00589
00590 S32 LLSurface::getGridsPerPatchEdge() const
00591 {
00592 return mGridsPerPatchEdge;
00593 }
00594
00595 void LLSurface::moveZ(const S32 x, const S32 y, const F32 delta)
00596 {
00597 llassert(x >= 0);
00598 llassert(y >= 0);
00599 llassert(x < mGridsPerEdge);
00600 llassert(y < mGridsPerEdge);
00601 mSurfaceZ[x + y*mGridsPerEdge] += delta;
00602 }
00603
00604
00605 void LLSurface::updatePatchVisibilities(LLAgent &agent)
00606 {
00607 LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgent.getCameraPositionGlobal());
00608
00609 LLSurfacePatch *patchp;
00610
00611 mVisiblePatchCount = 0;
00612 for (S32 i=0; i<mNumberOfPatches; i++)
00613 {
00614 patchp = mPatchList + i;
00615
00616 patchp->updateVisibility();
00617 if (patchp->getVisible())
00618 {
00619 mVisiblePatchCount++;
00620 patchp->updateCameraDistanceRegion(pos_region);
00621 }
00622 }
00623 }
00624
00625 BOOL LLSurface::idleUpdate(F32 max_update_time)
00626 {
00627 if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN))
00628 {
00629 return FALSE;
00630 }
00631
00632
00633
00634 LLTimer update_timer;
00635 BOOL did_update = FALSE;
00636
00637
00638
00639 if (mDirtyPatchList.size() > 0)
00640 {
00641 getRegion()->dirtyHeights();
00642 }
00643
00644
00645
00646 for(std::set<LLSurfacePatch *>::iterator iter = mDirtyPatchList.begin();
00647 iter != mDirtyPatchList.end(); )
00648 {
00649 std::set<LLSurfacePatch *>::iterator curiter = iter++;
00650 LLSurfacePatch *patchp = *curiter;
00651 patchp->updateNormals();
00652 patchp->updateVerticalStats();
00653 if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time)
00654 {
00655 if (patchp->updateTexture())
00656 {
00657 did_update = TRUE;
00658 patchp->clearDirty();
00659 mDirtyPatchList.erase(curiter);
00660 }
00661 }
00662 }
00663 return did_update;
00664 }
00665
00666 void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch)
00667 {
00668
00669 LLPatchHeader ph;
00670 S32 j, i;
00671 S32 patch[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
00672 LLSurfacePatch *patchp;
00673
00674 init_patch_decompressor(gopp->patch_size);
00675 gopp->stride = mGridsPerEdge;
00676 set_group_of_patch_header(gopp);
00677
00678 while (1)
00679 {
00680 decode_patch_header(bitpack, &ph);
00681 if (ph.quant_wbits == END_OF_PATCHES)
00682 {
00683 break;
00684 }
00685
00686 i = ph.patchids >> 5;
00687 j = ph.patchids & 0x1F;
00688
00689 if ((i >= mPatchesPerEdge) || (j >= mPatchesPerEdge))
00690 {
00691 llwarns << "Received invalid terrain packet - patch header patch ID incorrect!"
00692 << " patches per edge " << mPatchesPerEdge
00693 << " i " << i
00694 << " j " << j
00695 << " dc_offset " << ph.dc_offset
00696 << " range " << (S32)ph.range
00697 << " quant_wbits " << (S32)ph.quant_wbits
00698 << " patchids " << (S32)ph.patchids
00699 << llendl;
00700 LLAppViewer::instance()->badNetworkHandler();
00701 return;
00702 }
00703
00704 patchp = &mPatchList[j*mPatchesPerEdge + i];
00705
00706
00707 decode_patch(bitpack, patch);
00708 decompress_patch(patchp->getDataZ(), patch, &ph);
00709
00710
00711 patchp->updateNorthEdge();
00712 patchp->updateEastEdge();
00713 if (patchp->getNeighborPatch(WEST))
00714 {
00715 patchp->getNeighborPatch(WEST)->updateEastEdge();
00716 }
00717 if (patchp->getNeighborPatch(SOUTHWEST))
00718 {
00719 patchp->getNeighborPatch(SOUTHWEST)->updateEastEdge();
00720 patchp->getNeighborPatch(SOUTHWEST)->updateNorthEdge();
00721 }
00722 if (patchp->getNeighborPatch(SOUTH))
00723 {
00724 patchp->getNeighborPatch(SOUTH)->updateNorthEdge();
00725 }
00726
00727
00728 patchp->dirtyZ();
00729 patchp->setHasReceivedData();
00730 }
00731 }
00732
00733
00734
00735
00736 BOOL LLSurface::containsPosition(const LLVector3 &position)
00737 {
00738 if (position.mV[VX] < 0.0f || position.mV[VX] > mMetersPerEdge ||
00739 position.mV[VY] < 0.0f || position.mV[VY] > mMetersPerEdge)
00740 {
00741 return FALSE;
00742 }
00743 return TRUE;
00744 }
00745
00746
00747 F32 LLSurface::resolveHeightRegion(const F32 x, const F32 y) const
00748 {
00749 F32 height = 0.0f;
00750 F32 oometerspergrid = 1.f/mMetersPerGrid;
00751
00752
00753
00754
00755
00756 if (x >= 0.f &&
00757 x <= mMetersPerEdge &&
00758 y >= 0.f &&
00759 y <= mMetersPerEdge)
00760 {
00761 const S32 left = llfloor(x * oometerspergrid);
00762 const S32 bottom = llfloor(y * oometerspergrid);
00763
00764
00765 const S32 right = ( left+1 < (S32)mGridsPerEdge-1 ? left+1 : left );
00766 const S32 top = ( bottom+1 < (S32)mGridsPerEdge-1 ? bottom+1 : bottom );
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 const F32 left_bottom = getZ( left, bottom );
00782 const F32 right_bottom = getZ( right, bottom );
00783 const F32 left_top = getZ( left, top );
00784 const F32 right_top = getZ( right, top );
00785
00786
00787 F32 dx = x - left * mMetersPerGrid;
00788 F32 dy = y - bottom * mMetersPerGrid;
00789
00790 if (dy > dx)
00791 {
00792
00793 dy *= left_top - left_bottom;
00794 dx *= right_top - left_top;
00795 }
00796 else
00797 {
00798
00799 dx *= right_bottom - left_bottom;
00800 dy *= right_top - right_bottom;
00801 }
00802 height = left_bottom + (dx + dy) * oometerspergrid;
00803 }
00804 return height;
00805 }
00806
00807
00808 F32 LLSurface::resolveHeightGlobal(const LLVector3d& v) const
00809 {
00810 if (!mRegionp)
00811 {
00812 return 0.f;
00813 }
00814
00815 LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(v);
00816
00817 return resolveHeightRegion(pos_region);
00818 }
00819
00820
00821 LLVector3 LLSurface::resolveNormalGlobal(const LLVector3d& pos_global) const
00822 {
00823 if (!mSurfaceZ)
00824 {
00825
00826 return LLVector3::z_axis;
00827 }
00828
00829
00830
00831 F32 oometerspergrid = 1.f/mMetersPerGrid;
00832 LLVector3 normal;
00833 F32 dzx, dzy;
00834
00835 if (pos_global.mdV[VX] >= mOriginGlobal.mdV[VX] &&
00836 pos_global.mdV[VX] < mOriginGlobal.mdV[VX] + mMetersPerEdge &&
00837 pos_global.mdV[VY] >= mOriginGlobal.mdV[VY] &&
00838 pos_global.mdV[VY] < mOriginGlobal.mdV[VY] + mMetersPerEdge)
00839 {
00840 U32 i, j, k;
00841 F32 dx, dy;
00842 i = (U32) ((pos_global.mdV[VX] - mOriginGlobal.mdV[VX]) * oometerspergrid);
00843 j = (U32) ((pos_global.mdV[VY] - mOriginGlobal.mdV[VY]) * oometerspergrid );
00844 k = i + j*mGridsPerEdge;
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860 dx = (F32)(pos_global.mdV[VX] - i*mMetersPerGrid - mOriginGlobal.mdV[VX]);
00861 dy = (F32)(pos_global.mdV[VY] - j*mMetersPerGrid - mOriginGlobal.mdV[VY]);
00862 if (dy > dx)
00863 {
00864 dzx = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + mGridsPerEdge);
00865 dzy = *(mSurfaceZ + k) - *(mSurfaceZ + k + mGridsPerEdge);
00866 normal.setVec(-dzx,dzy,1);
00867 }
00868 else
00869 {
00870 dzx = *(mSurfaceZ + k) - *(mSurfaceZ + k + 1);
00871 dzy = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + 1);
00872 normal.setVec(dzx,-dzy,1);
00873 }
00874 }
00875 normal.normVec();
00876 return normal;
00877
00878
00879 }
00880
00881 LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const
00882 {
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 S32 i, j;
00905 if (x < 0.0f)
00906 {
00907 i = 0;
00908 }
00909 else if (x >= mMetersPerEdge)
00910 {
00911 i = mPatchesPerEdge - 1;
00912 }
00913 else
00914 {
00915 i = (U32) (x / (mMetersPerGrid * mGridsPerPatchEdge));
00916 }
00917
00918 if (y < 0.0f)
00919 {
00920 j = 0;
00921 }
00922 else if (y >= mMetersPerEdge)
00923 {
00924 j = mPatchesPerEdge - 1;
00925 }
00926 else
00927 {
00928 j = (U32) (y / (mMetersPerGrid * mGridsPerPatchEdge));
00929 }
00930
00931
00932 S32 index = i + j * mPatchesPerEdge;
00933 if((index < 0) || (index >= mNumberOfPatches))
00934 {
00935 if(0 == mNumberOfPatches)
00936 {
00937 llwarns << "No patches for current region!" << llendl;
00938 return NULL;
00939 }
00940 S32 old_index = index;
00941 index = llclamp(old_index, 0, (mNumberOfPatches - 1));
00942 llwarns << "Clamping out of range patch index " << old_index
00943 << " to " << index << llendl;
00944 }
00945 return &(mPatchList[index]);
00946 }
00947
00948
00949 LLSurfacePatch *LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const
00950 {
00951 return resolvePatchRegion(pos_region.mV[VX], pos_region.mV[VY]);
00952 }
00953
00954
00955 LLSurfacePatch *LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const
00956 {
00957 LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(pos_global);
00958 return resolvePatchRegion(pos_region);
00959 }
00960
00961
00962 std::ostream& operator<<(std::ostream &s, const LLSurface &S)
00963 {
00964 s << "{ \n";
00965 s << " mGridsPerEdge = " << S.mGridsPerEdge - 1 << " + 1\n";
00966 s << " mGridsPerPatchEdge = " << S.mGridsPerPatchEdge << "\n";
00967 s << " mPatchesPerEdge = " << S.mPatchesPerEdge << "\n";
00968 s << " mOriginGlobal = " << S.mOriginGlobal << "\n";
00969 s << " mMetersPerGrid = " << S.mMetersPerGrid << "\n";
00970 s << " mVisiblePatchCount = " << S.mVisiblePatchCount << "\n";
00971 s << "}";
00972 return s;
00973 }
00974
00975
00976
00977
00978 void LLSurface::createPatchData()
00979 {
00980
00981
00982 S32 i, j;
00983 LLSurfacePatch *patchp;
00984
00985
00986 mPatchList = new LLSurfacePatch[mNumberOfPatches];
00987
00988
00989 mVisiblePatchCount = mNumberOfPatches;
00990
00991 for (j=0; j<mPatchesPerEdge; j++)
00992 {
00993 for (i=0; i<mPatchesPerEdge; i++)
00994 {
00995 patchp = getPatch(i, j);
00996 patchp->setSurface(this);
00997 }
00998 }
00999
01000 for (j=0; j<mPatchesPerEdge; j++)
01001 {
01002 for (i=0; i<mPatchesPerEdge; i++)
01003 {
01004 patchp = getPatch(i, j);
01005 patchp->mHasReceivedData = FALSE;
01006 patchp->mSTexUpdate = TRUE;
01007
01008 S32 data_offset = i * mGridsPerPatchEdge + j * mGridsPerPatchEdge * mGridsPerEdge;
01009
01010 patchp->setDataZ(mSurfaceZ + data_offset);
01011 patchp->setDataNorm(mNorm + data_offset);
01012
01013
01014
01015
01016
01017 if (i < mPatchesPerEdge-1)
01018 {
01019 patchp->setNeighborPatch(EAST,getPatch(i+1, j));
01020 }
01021 else
01022 {
01023 patchp->setNeighborPatch(EAST, NULL);
01024 }
01025
01026 if (j < mPatchesPerEdge-1)
01027 {
01028 patchp->setNeighborPatch(NORTH, getPatch(i, j+1));
01029 }
01030 else
01031 {
01032 patchp->setNeighborPatch(NORTH, NULL);
01033 }
01034
01035 if (i > 0)
01036 {
01037 patchp->setNeighborPatch(WEST, getPatch(i - 1, j));
01038 }
01039 else
01040 {
01041 patchp->setNeighborPatch(WEST, NULL);
01042 }
01043
01044 if (j > 0)
01045 {
01046 patchp->setNeighborPatch(SOUTH, getPatch(i, j-1));
01047 }
01048 else
01049 {
01050 patchp->setNeighborPatch(SOUTH, NULL);
01051 }
01052
01053 if (i < (mPatchesPerEdge-1) && j < (mPatchesPerEdge-1))
01054 {
01055 patchp->setNeighborPatch(NORTHEAST, getPatch(i + 1, j + 1));
01056 }
01057 else
01058 {
01059 patchp->setNeighborPatch(NORTHEAST, NULL);
01060 }
01061
01062 if (i > 0 && j < (mPatchesPerEdge-1))
01063 {
01064 patchp->setNeighborPatch(NORTHWEST, getPatch(i - 1, j + 1));
01065 }
01066 else
01067 {
01068 patchp->setNeighborPatch(NORTHWEST, NULL);
01069 }
01070
01071 if (i > 0 && j > 0)
01072 {
01073 patchp->setNeighborPatch(SOUTHWEST, getPatch(i - 1, j - 1));
01074 }
01075 else
01076 {
01077 patchp->setNeighborPatch(SOUTHWEST, NULL);
01078 }
01079
01080 if (i < (mPatchesPerEdge-1) && j > 0)
01081 {
01082 patchp->setNeighborPatch(SOUTHEAST, getPatch(i + 1, j - 1));
01083 }
01084 else
01085 {
01086 patchp->setNeighborPatch(SOUTHEAST, NULL);
01087 }
01088
01089 LLVector3d origin_global;
01090 origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge;
01091 origin_global.mdV[1] = mOriginGlobal.mdV[0] + j * mMetersPerGrid * mGridsPerPatchEdge;
01092 origin_global.mdV[2] = 0.f;
01093 patchp->setOriginGlobal(origin_global);
01094 }
01095 }
01096 }
01097
01098
01099 void LLSurface::destroyPatchData()
01100 {
01101
01102
01103 delete [] mPatchList;
01104 mPatchList = NULL;
01105 mVisiblePatchCount = 0;
01106 }
01107
01108
01109 void LLSurface::setTextureSize(const S32 texture_size)
01110 {
01111 sTextureSize = texture_size;
01112 }
01113
01114
01115 U32 LLSurface::getRenderLevel(const U32 render_stride) const
01116 {
01117 return mPVArray.mRenderLevelp[render_stride];
01118 }
01119
01120
01121 U32 LLSurface::getRenderStride(const U32 render_level) const
01122 {
01123 return mPVArray.mRenderStridep[render_level];
01124 }
01125
01126
01127 LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const
01128 {
01129 if ((x < 0) || (x >= mPatchesPerEdge))
01130 {
01131 llerrs << "Asking for patch out of bounds" << llendl;
01132 return NULL;
01133 }
01134 if ((y < 0) || (y >= mPatchesPerEdge))
01135 {
01136 llerrs << "Asking for patch out of bounds" << llendl;
01137 return NULL;
01138 }
01139
01140 return mPatchList + x + y*mPatchesPerEdge;
01141 }
01142
01143
01144 void LLSurface::dirtyAllPatches()
01145 {
01146 S32 i;
01147 for (i = 0; i < mNumberOfPatches; i++)
01148 {
01149 mPatchList[i].dirtyZ();
01150 }
01151 }
01152
01153 void LLSurface::dirtySurfacePatch(LLSurfacePatch *patchp)
01154 {
01155
01156 mDirtyPatchList.insert(patchp);
01157 }
01158
01159
01160 void LLSurface::setWaterHeight(F32 height)
01161 {
01162 if (!mWaterObjp.isNull())
01163 {
01164 LLVector3 water_pos_region = mWaterObjp->getPositionRegion();
01165 water_pos_region.mV[VZ] = height;
01166 mWaterObjp->setPositionRegion(water_pos_region);
01167 }
01168 else
01169 {
01170 llwarns << "LLSurface::setWaterHeight with no water object!" << llendl;
01171 }
01172 }
01173
01174 F32 LLSurface::getWaterHeight() const
01175 {
01176 if (!mWaterObjp.isNull())
01177 {
01178
01179 return mWaterObjp->getPositionRegion().mV[VZ];
01180 }
01181 else
01182 {
01183 return DEFAULT_WATER_HEIGHT;
01184 }
01185 }
01186
01187
01188 BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y,
01189 const F32 width, const F32 height)
01190 {
01191 if (!getWaterTexture())
01192 {
01193 return FALSE;
01194 }
01195
01196 S32 tex_width = mWaterTexturep->getWidth();
01197 S32 tex_height = mWaterTexturep->getHeight();
01198 S32 tex_comps = mWaterTexturep->getComponents();
01199 S32 tex_stride = tex_width * tex_comps;
01200 LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
01201 U8 *rawp = raw->getData();
01202
01203 F32 scale = 256.f * getMetersPerGrid() / (F32)tex_width;
01204 F32 scale_inv = 1.f / scale;
01205
01206 S32 x_begin, y_begin, x_end, y_end;
01207
01208 x_begin = llround(x * scale_inv);
01209 y_begin = llround(y * scale_inv);
01210 x_end = llround((x + width) * scale_inv);
01211 y_end = llround((y + width) * scale_inv);
01212
01213 if (x_end > tex_width)
01214 {
01215 x_end = tex_width;
01216 }
01217 if (y_end > tex_width)
01218 {
01219 y_end = tex_width;
01220 }
01221
01222 LLVector3d origin_global = from_region_handle(getRegion()->getHandle());
01223
01224
01225 LLVector3 location;
01226 LLColor4U coloru;
01227
01228 const F32 WATER_HEIGHT = getWaterHeight();
01229
01230 S32 i, j, offset;
01231 for (j = y_begin; j < y_end; j++)
01232 {
01233 for (i = x_begin; i < x_end; i++)
01234 {
01235
01236
01237
01238
01239 offset = j*tex_stride + i*tex_comps;
01240 location.mV[VX] = i*scale;
01241 location.mV[VY] = j*scale;
01242
01243
01244 const F32 height = resolveHeightRegion(location);
01245
01246 if (height > WATER_HEIGHT)
01247 {
01248
01249 coloru = MAX_WATER_COLOR;
01250 coloru.mV[3] = ABOVE_WATERLINE_ALPHA;
01251 *(rawp + offset++) = coloru.mV[0];
01252 *(rawp + offset++) = coloru.mV[1];
01253 *(rawp + offset++) = coloru.mV[2];
01254 *(rawp + offset++) = coloru.mV[3];
01255 }
01256 else
01257 {
01258
01259 coloru = MAX_WATER_COLOR;
01260 const F32 frac = 1.f - 2.f/(2.f - (height - WATER_HEIGHT));
01261 S32 alpha = 64 + llround((255-64)*frac);
01262
01263 alpha = llmin(llround((F32)MAX_WATER_COLOR.mV[3]), alpha);
01264 alpha = llmax(64, alpha);
01265
01266 coloru.mV[3] = alpha;
01267 *(rawp + offset++) = coloru.mV[0];
01268 *(rawp + offset++) = coloru.mV[1];
01269 *(rawp + offset++) = coloru.mV[2];
01270 *(rawp + offset++) = coloru.mV[3];
01271 }
01272 }
01273 }
01274
01275 mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin);
01276 return TRUE;
01277 }