00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llsurfacepatch.h"
00035 #include "llpatchvertexarray.h"
00036 #include "llviewerobjectlist.h"
00037 #include "llvosurfacepatch.h"
00038 #include "llsurface.h"
00039 #include "pipeline.h"
00040 #include "llagent.h"
00041 #include "timing.h"
00042 #include "llsky.h"
00043 #include "llviewercamera.h"
00044
00045
00046 #include "llviewerregion.h"
00047 #include "llvlcomposition.h"
00048 #include "lldrawpool.h"
00049 #include "noise.h"
00050
00051 extern U64 gFrameTime;
00052 extern LLPipeline gPipeline;
00053
00054 LLSurfacePatch::LLSurfacePatch() :
00055 mDataZ(NULL),
00056 mVObjp(NULL),
00057 mLastUpdateTime(0),
00058 mSurfacep(NULL)
00059 {
00060
00061
00062 mConnectedEdge = NO_EDGE;
00063 mCenterRegion = LLVector3(0.f, 0.f, 0.f);
00064 mOriginRegion = LLVector3(0.f, 0.f, 0.f);
00065 mHasReceivedData = FALSE;
00066 mMinZ = 0.0f;
00067 mMaxZ = 0.0f;
00068 mMeanZ = 0.0f;
00069 mMinComposition = 0.f;
00070 mMeanComposition = 0.f;
00071 mMaxComposition = 0.f;
00072 mRadius = 0.f;
00073 mDirty = FALSE;
00074 mDirtyZStats = TRUE;
00075 mHeightsGenerated = FALSE;
00076
00077 S32 i;
00078 for (i = 0; i < 8; i++)
00079 {
00080 setNeighborPatch(i, NULL);
00081 }
00082 for (i = 0; i < 9; i++)
00083 {
00084 mNormalsInvalid[i] = TRUE;
00085 }
00086 }
00087
00088
00089 LLSurfacePatch::~LLSurfacePatch()
00090 {
00091 mVObjp = NULL;
00092 }
00093
00094
00095 void LLSurfacePatch::dirty()
00096 {
00097
00098
00099 if (mVObjp)
00100 {
00101 mVObjp->dirtyGeom();
00102 }
00103 else
00104 {
00105 llwarns << "No viewer object for this surface patch!" << llendl;
00106 }
00107
00108 mDirtyZStats = TRUE;
00109 mHeightsGenerated = FALSE;
00110
00111 if (!mDirty)
00112 {
00113 mDirty = TRUE;
00114 mSurfacep->dirtySurfacePatch(this);
00115 }
00116 }
00117
00118
00119 void LLSurfacePatch::setSurface(LLSurface *surfacep)
00120 {
00121 mSurfacep = surfacep;
00122 if (mVObjp == (LLVOSurfacePatch *)NULL)
00123 {
00124 llassert(mSurfacep->mType == 'l');
00125
00126 mVObjp = (LLVOSurfacePatch *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SURFACE_PATCH, mSurfacep->getRegion());
00127 mVObjp->setPatch(this);
00128 mVObjp->setPositionRegion(mCenterRegion);
00129 gPipeline.addObject(mVObjp);
00130 }
00131 }
00132
00133 void LLSurfacePatch::disconnectNeighbor(LLSurface *surfacep)
00134 {
00135 U32 i;
00136 for (i = 0; i < 8; i++)
00137 {
00138 if (getNeighborPatch(i))
00139 {
00140 if (getNeighborPatch(i)->mSurfacep == surfacep)
00141 {
00142 setNeighborPatch(i, NULL);
00143 mNormalsInvalid[i] = TRUE;
00144 }
00145 }
00146 }
00147
00148
00149 if (getNeighborPatch(EAST))
00150 {
00151 if (getNeighborPatch(EAST)->mSurfacep == surfacep)
00152 {
00153 mConnectedEdge &= ~EAST_EDGE;
00154 }
00155 }
00156 if (getNeighborPatch(NORTH))
00157 {
00158 if (getNeighborPatch(NORTH)->mSurfacep == surfacep)
00159 {
00160 mConnectedEdge &= ~NORTH_EDGE;
00161 }
00162 }
00163 if (getNeighborPatch(WEST))
00164 {
00165 if (getNeighborPatch(WEST)->mSurfacep == surfacep)
00166 {
00167 mConnectedEdge &= ~WEST_EDGE;
00168 }
00169 }
00170 if (getNeighborPatch(SOUTH))
00171 {
00172 if (getNeighborPatch(SOUTH)->mSurfacep == surfacep)
00173 {
00174 mConnectedEdge &= ~SOUTH_EDGE;
00175 }
00176 }
00177 }
00178
00179 LLVector3 LLSurfacePatch::getPointAgent(const U32 x, const U32 y) const
00180 {
00181 U32 surface_stride = mSurfacep->getGridsPerEdge();
00182 U32 point_offset = x + y*surface_stride;
00183 LLVector3 pos;
00184 pos = getOriginAgent();
00185 pos.mV[VX] += x * mSurfacep->getMetersPerGrid();
00186 pos.mV[VY] += y * mSurfacep->getMetersPerGrid();
00187 pos.mV[VZ] = *(mDataZ + point_offset);
00188 return pos;
00189 }
00190
00191 LLVector2 LLSurfacePatch::getTexCoords(const U32 x, const U32 y) const
00192 {
00193 U32 surface_stride = mSurfacep->getGridsPerEdge();
00194 U32 point_offset = x + y*surface_stride;
00195 LLVector3 pos, rel_pos;
00196 pos = getOriginAgent();
00197 pos.mV[VX] += x * mSurfacep->getMetersPerGrid();
00198 pos.mV[VY] += y * mSurfacep->getMetersPerGrid();
00199 pos.mV[VZ] = *(mDataZ + point_offset);
00200 rel_pos = pos - mSurfacep->getOriginAgent();
00201 rel_pos *= 1.f/surface_stride;
00202 return LLVector2(rel_pos.mV[VX], rel_pos.mV[VY]);
00203 }
00204
00205
00206 void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex, LLVector3 *normal,
00207 LLVector2 *tex0, LLVector2 *tex1)
00208 {
00209 if (!mSurfacep || !mSurfacep->getRegion())
00210 {
00211 return;
00212 }
00213
00214 U32 surface_stride = mSurfacep->getGridsPerEdge();
00215 U32 point_offset = x + y*surface_stride;
00216
00217 *normal = getNormal(x, y);
00218
00219 LLVector3 pos_agent = getOriginAgent();
00220 pos_agent.mV[VX] += x * mSurfacep->getMetersPerGrid();
00221 pos_agent.mV[VY] += y * mSurfacep->getMetersPerGrid();
00222 pos_agent.mV[VZ] = *(mDataZ + point_offset);
00223 *vertex = pos_agent;
00224
00225 LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent();
00226 LLVector3 tex_pos = rel_pos * (1.f/surface_stride);
00227 tex0->mV[0] = tex_pos.mV[0];
00228 tex0->mV[1] = tex_pos.mV[1];
00229 tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y);
00230
00231 const F32 xyScale = 4.9215f*7.f;
00232 const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f);
00233
00234 F32 vec[3] = {
00235 fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f),
00236 fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),
00237 0.f
00238 };
00239 F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f);
00240 tex1->mV[1] = rand_val;
00241
00242
00243 }
00244
00245
00246 void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
00247 {
00248 U32 patch_width = mSurfacep->mPVArray.mPatchWidth;
00249 U32 surface_stride = mSurfacep->getGridsPerEdge();
00250
00251 const F32 mpg = mSurfacep->getMetersPerGrid() * stride;
00252
00253 S32 poffsets[2][2][2];
00254 poffsets[0][0][0] = x - stride;
00255 poffsets[0][0][1] = y - stride;
00256
00257 poffsets[0][1][0] = x - stride;
00258 poffsets[0][1][1] = y + stride;
00259
00260 poffsets[1][0][0] = x + stride;
00261 poffsets[1][0][1] = y - stride;
00262
00263 poffsets[1][1][0] = x + stride;
00264 poffsets[1][1][1] = y + stride;
00265
00266 const LLSurfacePatch *ppatches[2][2];
00267
00268
00269
00270 ppatches[0][0] = this;
00271 ppatches[0][1] = this;
00272 ppatches[1][0] = this;
00273 ppatches[1][1] = this;
00274
00275 U32 i, j;
00276 for (i = 0; i < 2; i++)
00277 {
00278 for (j = 0; j < 2; j++)
00279 {
00280 if (poffsets[i][j][0] < 0)
00281 {
00282 if (!ppatches[i][j]->getNeighborPatch(WEST))
00283 {
00284 poffsets[i][j][0] = 0;
00285 }
00286 else
00287 {
00288 poffsets[i][j][0] += patch_width;
00289 ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST);
00290 }
00291 }
00292 if (poffsets[i][j][1] < 0)
00293 {
00294 if (!ppatches[i][j]->getNeighborPatch(SOUTH))
00295 {
00296 poffsets[i][j][1] = 0;
00297 }
00298 else
00299 {
00300 poffsets[i][j][1] += patch_width;
00301 ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH);
00302 }
00303 }
00304 if (poffsets[i][j][0] >= (S32)patch_width)
00305 {
00306 if (!ppatches[i][j]->getNeighborPatch(EAST))
00307 {
00308 poffsets[i][j][0] = patch_width - 1;
00309 }
00310 else
00311 {
00312 poffsets[i][j][0] -= patch_width;
00313 ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST);
00314 }
00315 }
00316 if (poffsets[i][j][1] >= (S32)patch_width)
00317 {
00318 if (!ppatches[i][j]->getNeighborPatch(NORTH))
00319 {
00320 poffsets[i][j][1] = patch_width - 1;
00321 }
00322 else
00323 {
00324 poffsets[i][j][1] -= patch_width;
00325 ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH);
00326 }
00327 }
00328 }
00329 }
00330
00331 LLVector3 p00(-mpg,-mpg,
00332 *(ppatches[0][0]->mDataZ
00333 + poffsets[0][0][0]
00334 + poffsets[0][0][1]*surface_stride));
00335 LLVector3 p01(-mpg,+mpg,
00336 *(ppatches[0][1]->mDataZ
00337 + poffsets[0][1][0]
00338 + poffsets[0][1][1]*surface_stride));
00339 LLVector3 p10(+mpg,-mpg,
00340 *(ppatches[1][0]->mDataZ
00341 + poffsets[1][0][0]
00342 + poffsets[1][0][1]*surface_stride));
00343 LLVector3 p11(+mpg,+mpg,
00344 *(ppatches[1][1]->mDataZ
00345 + poffsets[1][1][0]
00346 + poffsets[1][1][1]*surface_stride));
00347
00348 LLVector3 c1 = p11 - p00;
00349 LLVector3 c2 = p01 - p10;
00350
00351 LLVector3 normal = c1;
00352 normal %= c2;
00353 normal.normVec();
00354
00355 *(mDataNorm + surface_stride * y + x) = normal;
00356 }
00357
00358 const LLVector3 &LLSurfacePatch::getNormal(const U32 x, const U32 y) const
00359 {
00360 U32 surface_stride = mSurfacep->getGridsPerEdge();
00361 return *(mDataNorm + surface_stride * y + x);
00362 }
00363
00364
00365 void LLSurfacePatch::updateCameraDistanceRegion(const LLVector3 &pos_region)
00366 {
00367 if (LLPipeline::sDynamicLOD)
00368 {
00369 LLVector3 dv = pos_region;
00370 dv -= mCenterRegion;
00371 mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/
00372 llmax(LLVOSurfacePatch::sLODFactor, 0.1f);
00373 }
00374 else
00375 {
00376 mVisInfo.mDistance = 0.f;
00377 }
00378 }
00379
00380 F32 LLSurfacePatch::getDistance() const
00381 {
00382 return mVisInfo.mDistance;
00383 }
00384
00385
00386
00387
00388 void LLSurfacePatch::updateVerticalStats()
00389 {
00390 if (!mDirtyZStats)
00391 {
00392 return;
00393 }
00394
00395 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00396 U32 grids_per_edge = mSurfacep->getGridsPerEdge();
00397 F32 meters_per_grid = mSurfacep->getMetersPerGrid();
00398
00399 U32 i, j, k;
00400 F32 z, total;
00401
00402 z = *(mDataZ);
00403
00404 mMinZ = z;
00405 mMaxZ = z;
00406
00407 k = 0;
00408 total = 0.0f;
00409
00410
00411 for (j=0; j<(grids_per_patch_edge+1); j++)
00412 {
00413 for (i=0; i<(grids_per_patch_edge+1); i++)
00414 {
00415 z = *(mDataZ + i + j*grids_per_edge);
00416
00417 if (z < mMinZ)
00418 {
00419 mMinZ = z;
00420 }
00421 if (z > mMaxZ)
00422 {
00423 mMaxZ = z;
00424 }
00425 total += z;
00426 k++;
00427 }
00428 }
00429 mMeanZ = total / (F32) k;
00430 mCenterRegion.mV[VZ] = 0.5f * (mMinZ + mMaxZ);
00431
00432 LLVector3 diam_vec(meters_per_grid*grids_per_patch_edge,
00433 meters_per_grid*grids_per_patch_edge,
00434 mMaxZ - mMinZ);
00435 mRadius = diam_vec.magVec() * 0.5f;
00436
00437 mSurfacep->mMaxZ = llmax(mMaxZ, mSurfacep->mMaxZ);
00438 mSurfacep->mMinZ = llmin(mMinZ, mSurfacep->mMinZ);
00439 mSurfacep->mHasZData = TRUE;
00440 mSurfacep->getRegion()->calculateCenterGlobal();
00441
00442 if (mVObjp)
00443 {
00444 mVObjp->dirtyPatch();
00445 }
00446 mDirtyZStats = FALSE;
00447 }
00448
00449
00450 void LLSurfacePatch::updateNormals()
00451 {
00452 if (mSurfacep->mType == 'w')
00453 {
00454 return;
00455 }
00456 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00457 U32 grids_per_edge = mSurfacep->getGridsPerEdge();
00458
00459 BOOL dirty_patch = FALSE;
00460
00461 U32 i, j;
00462
00463 if (mNormalsInvalid[EAST] || mNormalsInvalid[NORTHEAST] || mNormalsInvalid[SOUTHEAST])
00464 {
00465 for (j = 0; j <= grids_per_patch_edge; j++)
00466 {
00467 calcNormal(grids_per_patch_edge, j, 2);
00468 calcNormal(grids_per_patch_edge - 1, j, 2);
00469 calcNormal(grids_per_patch_edge - 2, j, 2);
00470 }
00471
00472 dirty_patch = TRUE;
00473 }
00474
00475
00476 if (mNormalsInvalid[NORTHEAST] || mNormalsInvalid[NORTH] || mNormalsInvalid[NORTHWEST])
00477 {
00478 for (i = 0; i <= grids_per_patch_edge; i++)
00479 {
00480 calcNormal(i, grids_per_patch_edge, 2);
00481 calcNormal(i, grids_per_patch_edge - 1, 2);
00482 calcNormal(i, grids_per_patch_edge - 2, 2);
00483 }
00484
00485 dirty_patch = TRUE;
00486 }
00487
00488
00489 if (mNormalsInvalid[NORTHWEST] || mNormalsInvalid[WEST] || mNormalsInvalid[SOUTHWEST])
00490 {
00491 for (j = 0; j < grids_per_patch_edge; j++)
00492 {
00493 calcNormal(0, j, 2);
00494 calcNormal(1, j, 2);
00495 }
00496 dirty_patch = TRUE;
00497 }
00498
00499
00500 if (mNormalsInvalid[SOUTHWEST] || mNormalsInvalid[SOUTH] || mNormalsInvalid[SOUTHEAST])
00501 {
00502 for (i = 0; i < grids_per_patch_edge; i++)
00503 {
00504 calcNormal(i, 0, 2);
00505 calcNormal(i, 1, 2);
00506 }
00507 dirty_patch = TRUE;
00508 }
00509
00510
00511
00512 if (mNormalsInvalid[NORTHEAST])
00513 {
00514 if (!getNeighborPatch(NORTHEAST))
00515 {
00516 if (!getNeighborPatch(NORTH))
00517 {
00518 if (!getNeighborPatch(EAST))
00519 {
00520
00521 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00522 *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
00523 }
00524 else
00525 {
00526 if (getNeighborPatch(EAST)->getHasReceivedData())
00527 {
00528
00529 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00530 *(getNeighborPatch(EAST)->mDataZ + (grids_per_patch_edge - 1)*grids_per_edge);
00531 }
00532 else
00533 {
00534 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00535 *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
00536 }
00537 }
00538 }
00539 else
00540 {
00541
00542 if (getNeighborPatch(EAST))
00543 {
00544
00545
00546 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00547 *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
00548 }
00549 else
00550 {
00551 if (getNeighborPatch(NORTH)->getHasReceivedData())
00552 {
00553
00554 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00555 *(getNeighborPatch(NORTH)->mDataZ + (grids_per_patch_edge - 1));
00556 }
00557 else
00558 {
00559 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00560 *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
00561 }
00562 }
00563 }
00564 }
00565 else if (getNeighborPatch(NORTHEAST)->mSurfacep != mSurfacep)
00566 {
00567 if (
00568 (!getNeighborPatch(NORTH) || (getNeighborPatch(NORTH)->mSurfacep != mSurfacep))
00569 &&
00570 (!getNeighborPatch(EAST) || (getNeighborPatch(EAST)->mSurfacep != mSurfacep)))
00571 {
00572 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00573 *(getNeighborPatch(NORTHEAST)->mDataZ);
00574 }
00575 }
00576 else
00577 {
00578
00579
00580 }
00581 calcNormal(grids_per_patch_edge, grids_per_patch_edge, 2);
00582 calcNormal(grids_per_patch_edge, grids_per_patch_edge - 1, 2);
00583 calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge, 2);
00584 calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2);
00585 dirty_patch = TRUE;
00586 }
00587
00588
00589 if (mNormalsInvalid[MIDDLE])
00590 {
00591 for (j=2; j < grids_per_patch_edge - 2; j++)
00592 {
00593 for (i=2; i < grids_per_patch_edge - 2; i++)
00594 {
00595 calcNormal(i, j, 2);
00596 }
00597 }
00598 dirty_patch = TRUE;
00599 }
00600
00601 if (dirty_patch)
00602 {
00603 mSurfacep->dirtySurfacePatch(this);
00604 }
00605
00606 for (i = 0; i < 9; i++)
00607 {
00608 mNormalsInvalid[i] = FALSE;
00609 }
00610 }
00611
00612 void LLSurfacePatch::updateEastEdge()
00613 {
00614 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00615 U32 grids_per_edge = mSurfacep->getGridsPerEdge();
00616
00617 U32 j, k;
00618 F32 *west_surface, *east_surface;
00619
00620 if (!getNeighborPatch(EAST))
00621 {
00622 west_surface = mDataZ + grids_per_patch_edge;
00623 east_surface = mDataZ + grids_per_patch_edge - 1;
00624 }
00625 else if (mConnectedEdge & EAST_EDGE)
00626 {
00627 west_surface = mDataZ + grids_per_patch_edge;
00628 east_surface = getNeighborPatch(EAST)->mDataZ;
00629 }
00630 else
00631 {
00632 return;
00633 }
00634
00635
00636
00637 for (j=0; j < grids_per_patch_edge; j++)
00638 {
00639 k = j * grids_per_edge;
00640 *(west_surface + k) = *(east_surface + k);
00641 }
00642 }
00643
00644
00645 void LLSurfacePatch::updateNorthEdge()
00646 {
00647 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00648 U32 grids_per_edge = mSurfacep->getGridsPerEdge();
00649
00650 U32 i;
00651 F32 *south_surface, *north_surface;
00652
00653 if (!getNeighborPatch(NORTH))
00654 {
00655 south_surface = mDataZ + grids_per_patch_edge*grids_per_edge;
00656 north_surface = mDataZ + (grids_per_patch_edge - 1) * grids_per_edge;
00657 }
00658 else if (mConnectedEdge & NORTH_EDGE)
00659 {
00660 south_surface = mDataZ + grids_per_patch_edge*grids_per_edge;
00661 north_surface = getNeighborPatch(NORTH)->mDataZ;
00662 }
00663 else
00664 {
00665 return;
00666 }
00667
00668
00669 for (i=0; i<grids_per_patch_edge; i++)
00670 {
00671 *(south_surface + i) = *(north_surface + i);
00672 }
00673 }
00674
00675
00676 BOOL LLSurfacePatch::updateTexture()
00677 {
00678 if (mSTexUpdate)
00679 {
00680 F32 meters_per_grid = getSurface()->getMetersPerGrid();
00681 F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge();
00682
00683 if ((!getNeighborPatch(EAST) || getNeighborPatch(EAST)->getHasReceivedData())
00684 && (!getNeighborPatch(WEST) || getNeighborPatch(WEST)->getHasReceivedData())
00685 && (!getNeighborPatch(SOUTH) || getNeighborPatch(SOUTH)->getHasReceivedData())
00686 && (!getNeighborPatch(NORTH) || getNeighborPatch(NORTH)->getHasReceivedData()))
00687 {
00688 LLViewerRegion *regionp = getSurface()->getRegion();
00689 LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal();
00690
00691
00692 LLVLComposition* comp = regionp->getComposition();
00693 if (!mHeightsGenerated)
00694 {
00695 F32 patch_size = meters_per_grid*(grids_per_patch_edge+1);
00696 if (comp->generateHeights((F32)origin_region[VX], (F32)origin_region[VY],
00697 patch_size, patch_size))
00698 {
00699 mHeightsGenerated = TRUE;
00700 }
00701 else
00702 {
00703 return FALSE;
00704 }
00705 }
00706
00707 if (comp->generateComposition())
00708 {
00709 if (mVObjp)
00710 {
00711 mVObjp->dirtyGeom();
00712 }
00713 updateCompositionStats();
00714 F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
00715 if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY],
00716 tex_patch_size, tex_patch_size))
00717 {
00718 mSTexUpdate = FALSE;
00719
00720
00721 mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
00722 tex_patch_size, tex_patch_size);
00723 return TRUE;
00724 }
00725 }
00726 }
00727 return FALSE;
00728 }
00729 else
00730 {
00731 return TRUE;
00732 }
00733 }
00734
00735
00736 void LLSurfacePatch::dirtyZ()
00737 {
00738 mSTexUpdate = TRUE;
00739
00740
00741 U32 i;
00742 for (i = 0; i < 9; i++)
00743 {
00744 mNormalsInvalid[i] = TRUE;
00745 }
00746
00747
00748 for (i = 0; i < 8; i++)
00749 {
00750 if (getNeighborPatch(i))
00751 {
00752 getNeighborPatch(i)->mNormalsInvalid[gDirOpposite[i]] = TRUE;
00753 getNeighborPatch(i)->dirty();
00754 if (i < 4)
00755 {
00756 getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE;
00757 getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE;
00758 }
00759 }
00760 }
00761
00762 dirty();
00763 mLastUpdateTime = gFrameTime;
00764 }
00765
00766
00767 const U64 &LLSurfacePatch::getLastUpdateTime() const
00768 {
00769 return mLastUpdateTime;
00770 }
00771
00772 F32 LLSurfacePatch::getMaxZ() const
00773 {
00774 return mMaxZ;
00775 }
00776
00777 F32 LLSurfacePatch::getMinZ() const
00778 {
00779 return mMinZ;
00780 }
00781
00782 void LLSurfacePatch::setOriginGlobal(const LLVector3d &origin_global)
00783 {
00784 mOriginGlobal = origin_global;
00785
00786 LLVector3 origin_region;
00787 origin_region.setVec(mOriginGlobal - mSurfacep->getOriginGlobal());
00788
00789 mOriginRegion = origin_region;
00790 mCenterRegion.mV[VX] = origin_region.mV[VX] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid();
00791 mCenterRegion.mV[VY] = origin_region.mV[VY] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid();
00792
00793 mVisInfo.mbIsVisible = FALSE;
00794 mVisInfo.mDistance = 512.0f;
00795 mVisInfo.mRenderLevel = 0;
00796 mVisInfo.mRenderStride = mSurfacep->getGridsPerPatchEdge();
00797
00798 }
00799
00800 void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32 direction)
00801 {
00802 llassert(neighbor_patchp);
00803 mNormalsInvalid[direction] = TRUE;
00804 neighbor_patchp->mNormalsInvalid[gDirOpposite[direction]] = TRUE;
00805
00806 setNeighborPatch(direction, neighbor_patchp);
00807 neighbor_patchp->setNeighborPatch(gDirOpposite[direction], this);
00808
00809 if (EAST == direction)
00810 {
00811 mConnectedEdge |= EAST_EDGE;
00812 neighbor_patchp->mConnectedEdge |= WEST_EDGE;
00813 }
00814 else if (NORTH == direction)
00815 {
00816 mConnectedEdge |= NORTH_EDGE;
00817 neighbor_patchp->mConnectedEdge |= SOUTH_EDGE;
00818 }
00819 else if (WEST == direction)
00820 {
00821 mConnectedEdge |= WEST_EDGE;
00822 neighbor_patchp->mConnectedEdge |= EAST_EDGE;
00823 }
00824 else if (SOUTH == direction)
00825 {
00826 mConnectedEdge |= SOUTH_EDGE;
00827 neighbor_patchp->mConnectedEdge |= NORTH_EDGE;
00828 }
00829 }
00830
00831 void LLSurfacePatch::updateVisibility()
00832 {
00833 if (mVObjp.isNull())
00834 {
00835 return;
00836 }
00837
00838 const F32 DEFAULT_DELTA_ANGLE = (0.15f);
00839 U32 old_render_stride, max_render_stride;
00840 U32 new_render_level;
00841 F32 stride_per_distance = DEFAULT_DELTA_ANGLE / mSurfacep->getMetersPerGrid();
00842 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00843
00844 LLVector3 center = mCenterRegion + mSurfacep->getOriginAgent();
00845 LLVector3 radius = LLVector3(mRadius, mRadius, mRadius);
00846
00847
00848 if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, radius))
00849 {
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864 old_render_stride = mVisInfo.mRenderStride;
00865
00866
00867 max_render_stride = lltrunc(mVisInfo.mDistance * stride_per_distance);
00868 max_render_stride = llmin(max_render_stride , 2*grids_per_patch_edge);
00869
00870
00871
00872 new_render_level = mVisInfo.mRenderLevel = mSurfacep->getRenderLevel(max_render_stride);
00873 mVisInfo.mRenderStride = mSurfacep->getRenderStride(new_render_level);
00874
00875 if ((mVisInfo.mRenderStride != old_render_stride))
00876
00877
00878
00879 {
00880 if (mVObjp)
00881 {
00882 mVObjp->dirtyGeom();
00883 if (getNeighborPatch(WEST))
00884 {
00885 getNeighborPatch(WEST)->mVObjp->dirtyGeom();
00886 }
00887 if (getNeighborPatch(SOUTH))
00888 {
00889 getNeighborPatch(SOUTH)->mVObjp->dirtyGeom();
00890 }
00891 }
00892 }
00893 mVisInfo.mbIsVisible = TRUE;
00894 }
00895 else
00896 {
00897 mVisInfo.mbIsVisible = FALSE;
00898 }
00899 }
00900
00901
00902 const LLVector3d &LLSurfacePatch::getOriginGlobal() const
00903 {
00904 return mOriginGlobal;
00905 }
00906
00907 LLVector3 LLSurfacePatch::getOriginAgent() const
00908 {
00909 return gAgent.getPosAgentFromGlobal(mOriginGlobal);
00910 }
00911
00912 BOOL LLSurfacePatch::getVisible() const
00913 {
00914 return mVisInfo.mbIsVisible;
00915 }
00916
00917 U32 LLSurfacePatch::getRenderStride() const
00918 {
00919 return mVisInfo.mRenderStride;
00920 }
00921
00922 S32 LLSurfacePatch::getRenderLevel() const
00923 {
00924 return mVisInfo.mRenderLevel;
00925 }
00926
00927 void LLSurfacePatch::setHasReceivedData()
00928 {
00929 mHasReceivedData = TRUE;
00930 }
00931
00932 BOOL LLSurfacePatch::getHasReceivedData() const
00933 {
00934 return mHasReceivedData;
00935 }
00936
00937 const LLVector3 &LLSurfacePatch::getCenterRegion() const
00938 {
00939 return mCenterRegion;
00940 }
00941
00942
00943 void LLSurfacePatch::updateCompositionStats()
00944 {
00945 LLViewerLayer *vlp = mSurfacep->getRegion()->getComposition();
00946
00947 F32 x, y, width, height, mpg, min, mean, max;
00948
00949 LLVector3 origin = getOriginAgent() - mSurfacep->getOriginAgent();
00950 mpg = mSurfacep->getMetersPerGrid();
00951 x = origin.mV[VX];
00952 y = origin.mV[VY];
00953 width = mpg*(mSurfacep->getGridsPerPatchEdge()+1);
00954 height = mpg*(mSurfacep->getGridsPerPatchEdge()+1);
00955
00956 mean = 0.f;
00957 min = vlp->getValueScaled(x, y);
00958 max= min;
00959 U32 count = 0;
00960 F32 i, j;
00961 for (j = 0; j < height; j += mpg)
00962 {
00963 for (i = 0; i < width; i += mpg)
00964 {
00965 F32 comp = vlp->getValueScaled(x + i, y + j);
00966 mean += comp;
00967 min = llmin(min, comp);
00968 max = llmax(max, comp);
00969 count++;
00970 }
00971 }
00972 mean /= count;
00973
00974 mMinComposition = min;
00975 mMeanComposition = mean;
00976 mMaxComposition = max;
00977 }
00978
00979 F32 LLSurfacePatch::getMeanComposition() const
00980 {
00981 return mMeanComposition;
00982 }
00983
00984 F32 LLSurfacePatch::getMinComposition() const
00985 {
00986 return mMinComposition;
00987 }
00988
00989 F32 LLSurfacePatch::getMaxComposition() const
00990 {
00991 return mMaxComposition;
00992 }
00993
00994 void LLSurfacePatch::setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp)
00995 {
00996 mNeighborPatches[direction] = neighborp;
00997 mNormalsInvalid[direction] = TRUE;
00998 if (direction < 4)
00999 {
01000 mNormalsInvalid[gDirAdjacent[direction][0]] = TRUE;
01001 mNormalsInvalid[gDirAdjacent[direction][1]] = TRUE;
01002 }
01003 }
01004
01005 LLSurfacePatch *LLSurfacePatch::getNeighborPatch(const U32 direction) const
01006 {
01007 return mNeighborPatches[direction];
01008 }
01009
01010 void LLSurfacePatch::clearVObj()
01011 {
01012 mVObjp = NULL;
01013 }