llsurfacepatch.cpp

Go to the documentation of this file.
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 // For getting composition values
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         // This flag is used to communicate between adjacent surfaces and is set
00061         // to non-zero values by higher classes.  
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         // These are outside of the loop in case we're still waiting for a dirty from the
00098         // texture being updated...
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         // Clean up connected edges
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; // failsafe
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; //0.93284f;
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         // LLVector3 p1, p2, p3, p4;
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 // Called when a patch has changed its height field
00379 // data.
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         // Iterate to +1 because we need to do the edges correctly.
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         // update the east edge
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         // update the north edge
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         // update the west edge
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         // update the south edge
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         // Invalidating the northeast corner is different, because depending on what the adjacent neighbors are,
00503         // we'll want to do different things.
00504         if (mNormalsInvalid[NORTHEAST])
00505         {
00506                 if (!getNeighborPatch(NORTHEAST))
00507                 {
00508                         if (!getNeighborPatch(NORTH))
00509                         {
00510                                 if (!getNeighborPatch(EAST))
00511                                 {
00512                                         // No north or east neighbors.  Pull from the diagonal in your own patch.
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                                                 // East, but not north.  Pull from your east neighbor's northwest point.
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                                 // We have a north.
00534                                 if (getNeighborPatch(EAST))
00535                                 {
00536                                         // North and east neighbors, but not northeast.
00537                                         // Pull from diagonal in your own patch.
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                                                 // North, but not east.  Pull from your north neighbor's southeast corner.
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                         // We've got a northeast patch in the same surface.
00571                         // The z and normals will be handled by that patch.
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         // update the middle normals
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         // If patchp is on the east edge of its surface, then we update the east
00628         // side buffer
00629         for (j=0; j < grids_per_patch_edge; j++)
00630         {
00631                 k = j * grids_per_edge;
00632                 *(west_surface + k) = *(east_surface + k);      // update buffer Z
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         // Update patchp's north edge ...
00661         for (i=0; i<grids_per_patch_edge; i++)
00662         {
00663                 *(south_surface + i) = *(north_surface + i);    // update buffer Z
00664         }
00665 }
00666 
00667 
00668 BOOL LLSurfacePatch::updateTexture()
00669 {
00670         if (mSTexUpdate)                //  Update texture as needed
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                         // Have to figure out a better way to deal with these edge conditions...
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                                         // Also generate the water texture
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         // Invalidate all normals in this patch
00733         U32 i;
00734         for (i = 0; i < 9; i++)
00735         {
00736                 mNormalsInvalid[i] = TRUE;
00737         }
00738 
00739         // Invalidate normals in this and neighboring patches
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         // sphere in frustum on global coordinates
00837         if (gCamera->sphereInFrustum(mCenterRegion + mSurfacep->getOriginAgent(), mRadius) )
00838         {
00839                 // We now need to calculate the render stride based on patchp's distance 
00840                 // from LLCamera render_stride is governed by a relation something like this...
00841                 //
00842                 //                       delta_angle * patch.distance
00843                 // render_stride <=  ----------------------------------------
00844                 //                           mMetersPerGrid
00845                 //
00846                 // where 'delta_angle' is the desired solid angle of the average polgon on a patch.
00847                 //
00848                 // Any render_stride smaller than the RHS would be 'satisfactory'.  Smaller 
00849                 // strides give more resolution, but efficiency suggests that we use the largest 
00850                 // of the render_strides that obey the relation.  Flexibility is achieved by 
00851                 // modulating 'delta_angle' until we have an acceptable number of triangles.
00852         
00853                 old_render_stride = mVisInfo.mRenderStride;
00854 
00855                 // Calculate the render_stride using information in agent
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                 // We only use render_strides that are powers of two, so we use look-up tables to figure out
00860                 // the render_level and corresponding render_stride
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                         // The reason we check !mbIsVisible is because non-visible patches normals 
00866                         // are not updated when their data is changed.  When this changes we can get 
00867                         // rid of mbIsVisible altogether.
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 }

Generated on Thu Jul 1 06:09:14 2010 for Second Life Viewer by  doxygen 1.4.7