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 LLVector3 dv = pos_region;
00368 dv -= mCenterRegion;
00369 mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius));
00370 }
00371
00372 F32 LLSurfacePatch::getDistance() const
00373 {
00374 return mVisInfo.mDistance;
00375 }
00376
00377
00378
00379
00380 void LLSurfacePatch::updateVerticalStats()
00381 {
00382 if (!mDirtyZStats)
00383 {
00384 return;
00385 }
00386
00387 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00388 U32 grids_per_edge = mSurfacep->getGridsPerEdge();
00389 F32 meters_per_grid = mSurfacep->getMetersPerGrid();
00390
00391 U32 i, j, k;
00392 F32 z, total;
00393
00394 z = *(mDataZ);
00395
00396 mMinZ = z;
00397 mMaxZ = z;
00398
00399 k = 0;
00400 total = 0.0f;
00401
00402
00403 for (j=0; j<(grids_per_patch_edge+1); j++)
00404 {
00405 for (i=0; i<(grids_per_patch_edge+1); i++)
00406 {
00407 z = *(mDataZ + i + j*grids_per_edge);
00408
00409 if (z < mMinZ)
00410 {
00411 mMinZ = z;
00412 }
00413 if (z > mMaxZ)
00414 {
00415 mMaxZ = z;
00416 }
00417 total += z;
00418 k++;
00419 }
00420 }
00421 mMeanZ = total / (F32) k;
00422 mCenterRegion.mV[VZ] = 0.5f * (mMinZ + mMaxZ);
00423
00424 LLVector3 diam_vec(meters_per_grid*grids_per_patch_edge,
00425 meters_per_grid*grids_per_patch_edge,
00426 mMaxZ - mMinZ);
00427 mRadius = diam_vec.magVec() * 0.5f;
00428
00429 mSurfacep->mMaxZ = llmax(mMaxZ, mSurfacep->mMaxZ);
00430 mSurfacep->mMinZ = llmin(mMinZ, mSurfacep->mMinZ);
00431 mSurfacep->mHasZData = TRUE;
00432 mSurfacep->getRegion()->calculateCenterGlobal();
00433
00434 if (mVObjp)
00435 {
00436 mVObjp->dirtyPatch();
00437 }
00438 mDirtyZStats = FALSE;
00439 }
00440
00441
00442 void LLSurfacePatch::updateNormals()
00443 {
00444 if (mSurfacep->mType == 'w')
00445 {
00446 return;
00447 }
00448 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00449 U32 grids_per_edge = mSurfacep->getGridsPerEdge();
00450
00451 BOOL dirty_patch = FALSE;
00452
00453 U32 i, j;
00454
00455 if (mNormalsInvalid[EAST] || mNormalsInvalid[NORTHEAST] || mNormalsInvalid[SOUTHEAST])
00456 {
00457 for (j = 0; j <= grids_per_patch_edge; j++)
00458 {
00459 calcNormal(grids_per_patch_edge, j, 2);
00460 calcNormal(grids_per_patch_edge - 1, j, 2);
00461 calcNormal(grids_per_patch_edge - 2, j, 2);
00462 }
00463
00464 dirty_patch = TRUE;
00465 }
00466
00467
00468 if (mNormalsInvalid[NORTHEAST] || mNormalsInvalid[NORTH] || mNormalsInvalid[NORTHWEST])
00469 {
00470 for (i = 0; i <= grids_per_patch_edge; i++)
00471 {
00472 calcNormal(i, grids_per_patch_edge, 2);
00473 calcNormal(i, grids_per_patch_edge - 1, 2);
00474 calcNormal(i, grids_per_patch_edge - 2, 2);
00475 }
00476
00477 dirty_patch = TRUE;
00478 }
00479
00480
00481 if (mNormalsInvalid[NORTHWEST] || mNormalsInvalid[WEST] || mNormalsInvalid[SOUTHWEST])
00482 {
00483 for (j = 0; j < grids_per_patch_edge; j++)
00484 {
00485 calcNormal(0, j, 2);
00486 calcNormal(1, j, 2);
00487 }
00488 dirty_patch = TRUE;
00489 }
00490
00491
00492 if (mNormalsInvalid[SOUTHWEST] || mNormalsInvalid[SOUTH] || mNormalsInvalid[SOUTHEAST])
00493 {
00494 for (i = 0; i < grids_per_patch_edge; i++)
00495 {
00496 calcNormal(i, 0, 2);
00497 calcNormal(i, 1, 2);
00498 }
00499 dirty_patch = TRUE;
00500 }
00501
00502
00503
00504 if (mNormalsInvalid[NORTHEAST])
00505 {
00506 if (!getNeighborPatch(NORTHEAST))
00507 {
00508 if (!getNeighborPatch(NORTH))
00509 {
00510 if (!getNeighborPatch(EAST))
00511 {
00512
00513 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00514 *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
00515 }
00516 else
00517 {
00518 if (getNeighborPatch(EAST)->getHasReceivedData())
00519 {
00520
00521 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00522 *(getNeighborPatch(EAST)->mDataZ + (grids_per_patch_edge - 1)*grids_per_edge);
00523 }
00524 else
00525 {
00526 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00527 *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
00528 }
00529 }
00530 }
00531 else
00532 {
00533
00534 if (getNeighborPatch(EAST))
00535 {
00536
00537
00538 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00539 *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
00540 }
00541 else
00542 {
00543 if (getNeighborPatch(NORTH)->getHasReceivedData())
00544 {
00545
00546 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00547 *(getNeighborPatch(NORTH)->mDataZ + (grids_per_patch_edge - 1));
00548 }
00549 else
00550 {
00551 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00552 *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
00553 }
00554 }
00555 }
00556 }
00557 else if (getNeighborPatch(NORTHEAST)->mSurfacep != mSurfacep)
00558 {
00559 if (
00560 (!getNeighborPatch(NORTH) || (getNeighborPatch(NORTH)->mSurfacep != mSurfacep))
00561 &&
00562 (!getNeighborPatch(EAST) || (getNeighborPatch(EAST)->mSurfacep != mSurfacep)))
00563 {
00564 *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
00565 *(getNeighborPatch(NORTHEAST)->mDataZ);
00566 }
00567 }
00568 else
00569 {
00570
00571
00572 }
00573 calcNormal(grids_per_patch_edge, grids_per_patch_edge, 2);
00574 calcNormal(grids_per_patch_edge, grids_per_patch_edge - 1, 2);
00575 calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge, 2);
00576 calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2);
00577 dirty_patch = TRUE;
00578 }
00579
00580
00581 if (mNormalsInvalid[MIDDLE])
00582 {
00583 for (j=2; j < grids_per_patch_edge - 2; j++)
00584 {
00585 for (i=2; i < grids_per_patch_edge - 2; i++)
00586 {
00587 calcNormal(i, j, 2);
00588 }
00589 }
00590 dirty_patch = TRUE;
00591 }
00592
00593 if (dirty_patch)
00594 {
00595 mSurfacep->dirtySurfacePatch(this);
00596 }
00597
00598 for (i = 0; i < 9; i++)
00599 {
00600 mNormalsInvalid[i] = FALSE;
00601 }
00602 }
00603
00604 void LLSurfacePatch::updateEastEdge()
00605 {
00606 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00607 U32 grids_per_edge = mSurfacep->getGridsPerEdge();
00608
00609 U32 j, k;
00610 F32 *west_surface, *east_surface;
00611
00612 if (!getNeighborPatch(EAST))
00613 {
00614 west_surface = mDataZ + grids_per_patch_edge;
00615 east_surface = mDataZ + grids_per_patch_edge - 1;
00616 }
00617 else if (mConnectedEdge & EAST_EDGE)
00618 {
00619 west_surface = mDataZ + grids_per_patch_edge;
00620 east_surface = getNeighborPatch(EAST)->mDataZ;
00621 }
00622 else
00623 {
00624 return;
00625 }
00626
00627
00628
00629 for (j=0; j < grids_per_patch_edge; j++)
00630 {
00631 k = j * grids_per_edge;
00632 *(west_surface + k) = *(east_surface + k);
00633 }
00634 }
00635
00636
00637 void LLSurfacePatch::updateNorthEdge()
00638 {
00639 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00640 U32 grids_per_edge = mSurfacep->getGridsPerEdge();
00641
00642 U32 i;
00643 F32 *south_surface, *north_surface;
00644
00645 if (!getNeighborPatch(NORTH))
00646 {
00647 south_surface = mDataZ + grids_per_patch_edge*grids_per_edge;
00648 north_surface = mDataZ + (grids_per_patch_edge - 1) * grids_per_edge;
00649 }
00650 else if (mConnectedEdge & NORTH_EDGE)
00651 {
00652 south_surface = mDataZ + grids_per_patch_edge*grids_per_edge;
00653 north_surface = getNeighborPatch(NORTH)->mDataZ;
00654 }
00655 else
00656 {
00657 return;
00658 }
00659
00660
00661 for (i=0; i<grids_per_patch_edge; i++)
00662 {
00663 *(south_surface + i) = *(north_surface + i);
00664 }
00665 }
00666
00667
00668 BOOL LLSurfacePatch::updateTexture()
00669 {
00670 if (mSTexUpdate)
00671 {
00672 F32 meters_per_grid = getSurface()->getMetersPerGrid();
00673 F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge();
00674
00675 if ((!getNeighborPatch(EAST) || getNeighborPatch(EAST)->getHasReceivedData())
00676 && (!getNeighborPatch(WEST) || getNeighborPatch(WEST)->getHasReceivedData())
00677 && (!getNeighborPatch(SOUTH) || getNeighborPatch(SOUTH)->getHasReceivedData())
00678 && (!getNeighborPatch(NORTH) || getNeighborPatch(NORTH)->getHasReceivedData()))
00679 {
00680 LLViewerRegion *regionp = getSurface()->getRegion();
00681 LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal();
00682
00683
00684 LLVLComposition* comp = regionp->getComposition();
00685 if (!mHeightsGenerated)
00686 {
00687 F32 patch_size = meters_per_grid*(grids_per_patch_edge+1);
00688 if (comp->generateHeights((F32)origin_region[VX], (F32)origin_region[VY],
00689 patch_size, patch_size))
00690 {
00691 mHeightsGenerated = TRUE;
00692 }
00693 else
00694 {
00695 return FALSE;
00696 }
00697 }
00698
00699 if (comp->generateComposition())
00700 {
00701 if (mVObjp)
00702 {
00703 mVObjp->dirtyGeom();
00704 }
00705 updateCompositionStats();
00706 F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
00707 if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY],
00708 tex_patch_size, tex_patch_size))
00709 {
00710 mSTexUpdate = FALSE;
00711
00712
00713 mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
00714 tex_patch_size, tex_patch_size);
00715 return TRUE;
00716 }
00717 }
00718 }
00719 return FALSE;
00720 }
00721 else
00722 {
00723 return TRUE;
00724 }
00725 }
00726
00727
00728 void LLSurfacePatch::dirtyZ()
00729 {
00730 mSTexUpdate = TRUE;
00731
00732
00733 U32 i;
00734 for (i = 0; i < 9; i++)
00735 {
00736 mNormalsInvalid[i] = TRUE;
00737 }
00738
00739
00740 for (i = 0; i < 8; i++)
00741 {
00742 if (getNeighborPatch(i))
00743 {
00744 getNeighborPatch(i)->mNormalsInvalid[gDirOpposite[i]] = TRUE;
00745 getNeighborPatch(i)->dirty();
00746 if (i < 4)
00747 {
00748 getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE;
00749 getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE;
00750 }
00751 }
00752 }
00753
00754 dirty();
00755 mLastUpdateTime = gFrameTime;
00756 }
00757
00758
00759 const U64 &LLSurfacePatch::getLastUpdateTime() const
00760 {
00761 return mLastUpdateTime;
00762 }
00763
00764 F32 LLSurfacePatch::getMaxZ() const
00765 {
00766 return mMaxZ;
00767 }
00768
00769 F32 LLSurfacePatch::getMinZ() const
00770 {
00771 return mMinZ;
00772 }
00773
00774 void LLSurfacePatch::setOriginGlobal(const LLVector3d &origin_global)
00775 {
00776 mOriginGlobal = origin_global;
00777
00778 LLVector3 origin_region;
00779 origin_region.setVec(mOriginGlobal - mSurfacep->getOriginGlobal());
00780
00781 mOriginRegion = origin_region;
00782 mCenterRegion.mV[VX] = origin_region.mV[VX] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid();
00783 mCenterRegion.mV[VY] = origin_region.mV[VY] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid();
00784
00785 mVisInfo.mbIsVisible = FALSE;
00786 mVisInfo.mDistance = 512.0f;
00787 mVisInfo.mRenderLevel = 0;
00788 mVisInfo.mRenderStride = mSurfacep->getGridsPerPatchEdge();
00789
00790 }
00791
00792 void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32 direction)
00793 {
00794 llassert(neighbor_patchp);
00795 mNormalsInvalid[direction] = TRUE;
00796 neighbor_patchp->mNormalsInvalid[gDirOpposite[direction]] = TRUE;
00797
00798 setNeighborPatch(direction, neighbor_patchp);
00799 neighbor_patchp->setNeighborPatch(gDirOpposite[direction], this);
00800
00801 if (EAST == direction)
00802 {
00803 mConnectedEdge |= EAST_EDGE;
00804 neighbor_patchp->mConnectedEdge |= WEST_EDGE;
00805 }
00806 else if (NORTH == direction)
00807 {
00808 mConnectedEdge |= NORTH_EDGE;
00809 neighbor_patchp->mConnectedEdge |= SOUTH_EDGE;
00810 }
00811 else if (WEST == direction)
00812 {
00813 mConnectedEdge |= WEST_EDGE;
00814 neighbor_patchp->mConnectedEdge |= EAST_EDGE;
00815 }
00816 else if (SOUTH == direction)
00817 {
00818 mConnectedEdge |= SOUTH_EDGE;
00819 neighbor_patchp->mConnectedEdge |= NORTH_EDGE;
00820 }
00821 }
00822
00823 void LLSurfacePatch::updateVisibility()
00824 {
00825 if (mVObjp.isNull())
00826 {
00827 return;
00828 }
00829
00830 const F32 DEFAULT_DELTA_ANGLE = (0.15f);
00831 U32 old_render_stride, max_render_stride;
00832 U32 new_render_level;
00833 F32 stride_per_distance = DEFAULT_DELTA_ANGLE / mSurfacep->getMetersPerGrid();
00834 U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
00835
00836
00837 if (gCamera->sphereInFrustum(mCenterRegion + mSurfacep->getOriginAgent(), mRadius) )
00838 {
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853 old_render_stride = mVisInfo.mRenderStride;
00854
00855
00856 max_render_stride = lltrunc(mVisInfo.mDistance * stride_per_distance);
00857 max_render_stride = llmin(max_render_stride , 2*grids_per_patch_edge);
00858
00859
00860
00861 new_render_level = mVisInfo.mRenderLevel = mSurfacep->getRenderLevel(max_render_stride);
00862 mVisInfo.mRenderStride = mSurfacep->getRenderStride(new_render_level);
00863
00864 if ((mVisInfo.mRenderStride != old_render_stride))
00865
00866
00867
00868 {
00869 if (mVObjp)
00870 {
00871 mVObjp->dirtyGeom();
00872 if (getNeighborPatch(WEST))
00873 {
00874 getNeighborPatch(WEST)->mVObjp->dirtyGeom();
00875 }
00876 if (getNeighborPatch(SOUTH))
00877 {
00878 getNeighborPatch(SOUTH)->mVObjp->dirtyGeom();
00879 }
00880 }
00881 }
00882 mVisInfo.mbIsVisible = TRUE;
00883 }
00884 else
00885 {
00886 mVisInfo.mbIsVisible = FALSE;
00887 }
00888 }
00889
00890
00891 const LLVector3d &LLSurfacePatch::getOriginGlobal() const
00892 {
00893 return mOriginGlobal;
00894 }
00895
00896 LLVector3 LLSurfacePatch::getOriginAgent() const
00897 {
00898 return gAgent.getPosAgentFromGlobal(mOriginGlobal);
00899 }
00900
00901 BOOL LLSurfacePatch::getVisible() const
00902 {
00903 return mVisInfo.mbIsVisible;
00904 }
00905
00906 U32 LLSurfacePatch::getRenderStride() const
00907 {
00908 return mVisInfo.mRenderStride;
00909 }
00910
00911 S32 LLSurfacePatch::getRenderLevel() const
00912 {
00913 return mVisInfo.mRenderLevel;
00914 }
00915
00916 void LLSurfacePatch::setHasReceivedData()
00917 {
00918 mHasReceivedData = TRUE;
00919 }
00920
00921 BOOL LLSurfacePatch::getHasReceivedData() const
00922 {
00923 return mHasReceivedData;
00924 }
00925
00926 const LLVector3 &LLSurfacePatch::getCenterRegion() const
00927 {
00928 return mCenterRegion;
00929 }
00930
00931
00932 void LLSurfacePatch::updateCompositionStats()
00933 {
00934 LLViewerLayer *vlp = mSurfacep->getRegion()->getComposition();
00935
00936 F32 x, y, width, height, mpg, min, mean, max;
00937
00938 LLVector3 origin = getOriginAgent() - mSurfacep->getOriginAgent();
00939 mpg = mSurfacep->getMetersPerGrid();
00940 x = origin.mV[VX];
00941 y = origin.mV[VY];
00942 width = mpg*(mSurfacep->getGridsPerPatchEdge()+1);
00943 height = mpg*(mSurfacep->getGridsPerPatchEdge()+1);
00944
00945 mean = 0.f;
00946 min = vlp->getValueScaled(x, y);
00947 max= min;
00948 U32 count = 0;
00949 F32 i, j;
00950 for (j = 0; j < height; j += mpg)
00951 {
00952 for (i = 0; i < width; i += mpg)
00953 {
00954 F32 comp = vlp->getValueScaled(x + i, y + j);
00955 mean += comp;
00956 min = llmin(min, comp);
00957 max = llmax(max, comp);
00958 count++;
00959 }
00960 }
00961 mean /= count;
00962
00963 mMinComposition = min;
00964 mMeanComposition = mean;
00965 mMaxComposition = max;
00966 }
00967
00968 F32 LLSurfacePatch::getMeanComposition() const
00969 {
00970 return mMeanComposition;
00971 }
00972
00973 F32 LLSurfacePatch::getMinComposition() const
00974 {
00975 return mMinComposition;
00976 }
00977
00978 F32 LLSurfacePatch::getMaxComposition() const
00979 {
00980 return mMaxComposition;
00981 }
00982
00983 void LLSurfacePatch::setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp)
00984 {
00985 mNeighborPatches[direction] = neighborp;
00986 mNormalsInvalid[direction] = TRUE;
00987 if (direction < 4)
00988 {
00989 mNormalsInvalid[gDirAdjacent[direction][0]] = TRUE;
00990 mNormalsInvalid[gDirAdjacent[direction][1]] = TRUE;
00991 }
00992 }
00993
00994 LLSurfacePatch *LLSurfacePatch::getNeighborPatch(const U32 direction) const
00995 {
00996 return mNeighborPatches[direction];
00997 }
00998
00999 void LLSurfacePatch::clearVObj()
01000 {
01001 mVObjp = NULL;
01002 }