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