diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index a663f8549..67a7c997e 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -537,7 +537,7 @@ public: OctreeStats::getInstance()->realloc(old_cap,mData.capacity()); #endif - this->notifyAddition(data); + LLOctreeNode::notifyAddition(data); return true; } else @@ -593,7 +593,7 @@ public: OctreeStats::getInstance()->realloc(old_cap,mData.capacity()); #endif - this->notifyAddition(data); + LLOctreeNode::notifyAddition(data); return true; } diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index a254f3899..19c5d6457 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -1149,6 +1149,7 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() //must be an active volume if (!mSpatialBridge) { + // Spatial bridge ctors self-register... if (mVObjp->isHUDAttachment()) { setSpatialBridge(new LLHUDBridge(this, getRegion())); @@ -1615,9 +1616,9 @@ void LLSpatialBridge::cleanupReferences() } }*/ - LLDrawable* drawablep = mDrawable; - mDrawable = NULL; - drawablep->setSpatialBridge(NULL); + LLPointer drawablep = mDrawable; + mDrawable = nullptr; + drawablep->setSpatialBridge(nullptr); } } diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index 0f10e1e13..560cf7653 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -71,7 +71,6 @@ LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) : mGridsPerEdge(0), mOOGridsPerEdge(0.f), mPatchesPerEdge(0), - mNumberOfPatches(0), mType(type), mDetailTextureScale(0.f), mOriginGlobal(0.0, 0.0, 0.0), @@ -86,9 +85,6 @@ LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) : mSurfaceZ = NULL; mNorm = NULL; - // Patch data - mPatchList = NULL; - // One of each for each camera mVisiblePatchCount = 0; @@ -119,7 +115,6 @@ LLSurface::~LLSurface() mGridsPerEdge = 0; mGridsPerPatchEdge = 0; mPatchesPerEdge = 0; - mNumberOfPatches = 0; destroyPatchData(); LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep); @@ -168,7 +163,6 @@ void LLSurface::create(const S32 grids_per_edge, mOOGridsPerEdge = 1.f / mGridsPerEdge; mGridsPerPatchEdge = grids_per_patch_edge; mPatchesPerEdge = grids_per_edge / mGridsPerPatchEdge; - mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge; mMetersPerGrid = width / (F32)grids_per_edge; mMetersPerEdge = mMetersPerGrid * grids_per_edge; // Aurora Sim @@ -310,14 +304,13 @@ void LLSurface::setOriginGlobal(const LLVector3d &origin_global) { LLVector3d new_origin_global; mOriginGlobal = origin_global; - LLSurfacePatch *patchp; S32 i, j; // Need to update the southwest corners of the patches for (j=0; jgetOriginGlobal(); @@ -369,353 +362,122 @@ void LLSurface::getNeighboringRegionsStatus( std::vector& regions ) } } -void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction) +void LLSurface::connectNeighbor(LLSurface* neighborp, U32 direction) { - S32 i; - LLSurfacePatch *patchp, *neighbor_patchp; -// Aurora Sim - S32 neighborPatchesPerEdge = neighborp->mPatchesPerEdge; -// Aurora Sim + // Constraints: + // - Regions width must equal height + // - Region width divisible by mGridsPerPatchEdge (16) + // - Region can only neighbor one other per side and coner (8 total, N, S, E, W, NW, NE, SW, SE) + // - Non-power-of-2 regions should work here, but the rest of the viewer code will probably choke on them. + surface_patch_ref patchp, neighbor_patchp; mNeighbors[direction] = neighborp; - neighborp->mNeighbors[gDirOpposite[direction]] = this; -// Aurora Sim - S32 ppe[2]; - S32 own_offset[2] = {0, 0}; - S32 neighbor_offset[2] = {0, 0}; - U32 own_xpos, own_ypos, neighbor_xpos, neighbor_ypos; - - ppe[0] = (mPatchesPerEdge < neighborPatchesPerEdge) ? mPatchesPerEdge : neighborPatchesPerEdge; // used for x - ppe[1] = ppe[0]; // used for y - - from_region_handle(mRegionp->getHandle(), &own_xpos, &own_ypos); - from_region_handle(neighborp->getRegion()->getHandle(), &neighbor_xpos, &neighbor_ypos); - - if(own_ypos >= neighbor_ypos) - { - neighbor_offset[1] = (own_ypos - neighbor_ypos) / mGridsPerPatchEdge; - ppe[1] = llmin(mPatchesPerEdge, neighborPatchesPerEdge-neighbor_offset[1]); - } - else - { - own_offset[1] = (neighbor_ypos - own_ypos) / mGridsPerPatchEdge; - ppe[1] = llmin(mPatchesPerEdge-own_offset[1], neighborPatchesPerEdge); - } - - if(own_xpos >= neighbor_xpos) - { - neighbor_offset[0] = (own_xpos - neighbor_xpos) / mGridsPerPatchEdge; - ppe[0] = llmin(mPatchesPerEdge, neighborPatchesPerEdge-neighbor_offset[0]); - } - else - { - own_offset[0] = (neighbor_xpos - own_xpos) / mGridsPerPatchEdge; - ppe[0] = llmin(mPatchesPerEdge-own_offset[0], neighborPatchesPerEdge); - } -// Aurora Sim + const S32 max_idx = mPatchesPerEdge - 1; + const S32 neighbor_max_idx = neighborp->mPatchesPerEdge - 1; // Connect patches - if (NORTHEAST == direction) + if (direction >= 4) { - patchp = getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1); -// Aurora Sim - //neighbor_patchp = neighborp->getPatch(0, 0); - neighbor_patchp = neighborp->getPatch(neighbor_offset[0], neighbor_offset[1]); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateNorthEdge(); // Only update one of north or east. - patchp->dirtyZ(); - } - else if (NORTHWEST == direction) + // Corner stitch + S32 patches[4][2] = { + {max_idx, max_idx}, //NORTHEAST + {0, max_idx}, //NORTHWEST + {0, 0}, //SOUTHWEST + {max_idx, 0}, //SOUTHEAST + }; + const S32* p = patches[direction - 4]; + surface_patch_ref patchp = getPatch(p[0], p[1]); + patchp->connectNeighbor(neighborp->getPatch(max_idx - p[0], max_idx - p[1]), direction); + if (NORTHEAST == direction) + { + patchp->updateNorthEdge(); // Only update one of north or east. + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } + } +} + else { -// Aurora Sim - S32 off = mPatchesPerEdge + neighbor_offset[1] - own_offset[1]; -// Aurora Sim - patchp = getPatch(0, mPatchesPerEdge - 1); -// Aurora Sim - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, 0); - neighbor_patchp = neighborp->getPatch(neighbor_offset[0] - 1, off); //neighborPatchesPerEdge - 1 - if (!neighbor_patchp) + // Edge stitch + // Aurora complicates this logic. + U32 pos[2][2] = { {0,0},{0,0} }; + from_region_handle(mRegionp->getHandle(), &pos[0][0], &pos[0][1]); + from_region_handle(neighborp->getRegion()->getHandle(), &pos[1][0], &pos[1][1]); + S32 width[2] = { (S32)mRegionp->getWidth(), (S32)neighborp->getRegion()->getWidth() }; + U32 mins[2] = { llmax(pos[0][0], pos[1][0]), llmax(pos[0][1], pos[1][1]) }; + U32 maxs[2] = { llmin(pos[0][0] + width[0], pos[1][0] + width[1]), llmin(pos[0][1] + width[0], pos[1][1] + width[1]) }; + S32 start[2][2] = { + {S32((mins[0] - pos[0][0]) / mGridsPerPatchEdge) - 1, S32((mins[1] - pos[0][1]) / mGridsPerPatchEdge) - 1}, + {S32((mins[0] - pos[1][0]) / neighborp->mGridsPerPatchEdge) - 1,S32((mins[1] - pos[1][1]) / neighborp->mGridsPerPatchEdge) - 1} + }; + + S32 end[2] = { llmin(S32((maxs[0] - pos[0][0]) / mGridsPerPatchEdge), max_idx), llmin(S32((maxs[1] - pos[0][1]) / mGridsPerPatchEdge), max_idx) }; + const U32& neighbor_direction = gDirOpposite[direction]; + S32 stride[4][4][2] = { + {{0, 1}, {max_idx, 0}, {neighbor_max_idx, 0}, {NORTHEAST, SOUTHEAST}}, //EAST + {{1, 0}, {0, max_idx}, {0, neighbor_max_idx}, {NORTHEAST, NORTHWEST} }, //NORTH + {{0, 1}, {0, 0}, {0, 0}, {NORTHWEST, SOUTHWEST}}, //WEST + {{1, 0}, {0, 0}, {0, 0}, {SOUTHEAST, SOUTHWEST}} //SOUTH + }; + const S32 offs[2][2] = { + {stride[direction][0][0], stride[direction][0][1]}, + {stride[neighbor_direction][0][0], stride[neighbor_direction][0][1]} + }; + + S32 x[2], y[2]; + x[0] = stride[direction][1][0] + offs[0][0] * start[0][0]; + y[0] = stride[direction][1][1] + offs[0][1] * start[0][1]; + x[1] = stride[neighbor_direction][2][0] + offs[1][0] * start[1][0]; + y[1] = stride[neighbor_direction][2][1] + offs[1][1] * start[1][1]; + + for ( + x[0] = stride[direction][1][0] + offs[0][0] * start[0][0], + y[0] = stride[direction][1][1] + offs[0][1] * start[0][1], + x[1] = stride[neighbor_direction][2][0] + offs[1][0] * start[1][0], + y[1] = stride[neighbor_direction][2][1] + offs[1][1] * start[1][1]; + (!offs[0][0] || x[0] <= end[0]) && (!offs[0][1] || (y[0] <= end[1])); + x[0] += offs[0][0], y[0] += offs[0][1], + x[1] += offs[1][0], y[1] += offs[1][1]) { - mNeighbors[direction] = NULL; - return; - } -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - } - else if (SOUTHWEST == direction) - { - patchp = getPatch(0, 0); -// Aurora Sim - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(neighbor_offset[0] - 1, neighbor_offset[1] - 1); - if (!neighbor_patchp) - { - mNeighbors[direction] = NULL; - return; - } -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - -// Aurora Sim - //neighbor_patchp->updateNorthEdge(); // Only update one of north or east. - neighbor_patchp->updateEastEdge(); // Only update one of north or east. -// Aurora Sim - neighbor_patchp->dirtyZ(); - } - else if (SOUTHEAST == direction) - { -// Aurora Sim - S32 off = mPatchesPerEdge + neighbor_offset[0] - own_offset[0]; -// Aurora Sim - - patchp = getPatch(mPatchesPerEdge - 1, 0); -// Aurora Sim - //neighbor_patchp = neighborp->getPatch(0, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(off, neighbor_offset[1] - 1); //0 - if (!neighbor_patchp) - { - mNeighbors[direction] = NULL; - return; - } -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - } - else if (EAST == direction) - { - // Do east/west connections, first -// Aurora Sim - //for (i = 0; i < (S32)mPatchesPerEdge; i++) - for (i = 0; i < ppe[1]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(mPatchesPerEdge - 1, i); - //neighbor_patchp = neighborp->getPatch(0, i); - patchp = getPatch(mPatchesPerEdge - 1, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(0, i + neighbor_offset[1]); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateEastEdge(); - patchp->dirtyZ(); - } - - // Now do northeast/southwest connections -// Aurora Sim - //for (i = 0; i < (S32)mPatchesPerEdge - 1; i++) - for (i = 0; i < ppe[1] - 1; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(mPatchesPerEdge - 1, i); - //neighbor_patchp = neighborp->getPatch(0, i+1); - patchp = getPatch(mPatchesPerEdge - 1, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(0, i+1 + neighbor_offset[1]); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, NORTHEAST); - neighbor_patchp->connectNeighbor(patchp, SOUTHWEST); - } - // Now do southeast/northwest connections -// Aurora Sim - //for (i = 1; i < (S32)mPatchesPerEdge; i++) - for (i = 1; i < ppe[1]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(mPatchesPerEdge - 1, i); - //neighbor_patchp = neighborp->getPatch(0, i-1); - patchp = getPatch(mPatchesPerEdge - 1, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(0, i-1 + neighbor_offset[1]); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, SOUTHEAST); - neighbor_patchp->connectNeighbor(patchp, NORTHWEST); + if (x[0] < 0 || y[0] < 0) { + continue; + } + surface_patch_ref patchp = getPatch(x[0], y[0]); + // diagonal stitch 1 + if ((offs[1][0] > 0 && x[1] > 0) || (offs[1][1] > 0 && y[1] > 0)) + { + patchp->connectNeighbor(neighborp->getPatch(x[1] - offs[1][0], y[1] - offs[1][1]), stride[direction][3][1]); + } + // edge stitch + if (x[1] >= 0 && y[1] >= 0 && x[1] <= neighbor_max_idx && y[1] <= neighbor_max_idx) + { + patchp->connectNeighbor(neighborp->getPatch(x[1], y[1]), direction); + } + // diagonal stitch 2 + if (x[1] + offs[1][0] <= neighbor_max_idx && y[1] + offs[1][1] <= neighbor_max_idx) + { + patchp->connectNeighbor(neighborp->getPatch(x[1] + offs[1][0], y[1] + offs[1][1]), stride[direction][3][0]); + } + if (direction == EAST) + { + patchp->updateEastEdge(); + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } + } + else if (direction == NORTH) + { + patchp->updateNorthEdge(); + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } + } } } - else if (NORTH == direction) - { - // Do north/south connections, first -// Aurora Sim - //for (i = 0; i < (S32)mPatchesPerEdge; i++) - for (i = 0; i < ppe[0]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, mPatchesPerEdge - 1); - //neighbor_patchp = neighborp->getPatch(i, 0); - patchp = getPatch(i + own_offset[0], mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i + neighbor_offset[0], 0); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateNorthEdge(); - patchp->dirtyZ(); - } - - // Do northeast/southwest connections -// Aurora Sim - //for (i = 0; i < (S32)mPatchesPerEdge - 1; i++) - for (i = 0; i < ppe[0] - 1; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, mPatchesPerEdge - 1); - //neighbor_patchp = neighborp->getPatch(i+1, 0); - patchp = getPatch(i + own_offset[0], mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i+1 + neighbor_offset[0], 0); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, NORTHEAST); - neighbor_patchp->connectNeighbor(patchp, SOUTHWEST); - } - // Do southeast/northwest connections -// Aurora Sim - //for (i = 1; i < (S32)mPatchesPerEdge; i++) - for (i = 1; i < ppe[0]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, mPatchesPerEdge - 1); - //neighbor_patchp = neighborp->getPatch(i-1, 0); - patchp = getPatch(i + own_offset[0], mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i-1 + neighbor_offset[0], 0); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, NORTHWEST); - neighbor_patchp->connectNeighbor(patchp, SOUTHEAST); - } - } - else if (WEST == direction) - { - // Do east/west connections, first -// Aurora Sim - //for (i = 0; i < mPatchesPerEdge; i++) - for (i = 0; i < ppe[1]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(0, i); - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i); - patchp = getPatch(0, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(neighborPatchesPerEdge - 1, i + neighbor_offset[1]); - if (!neighbor_patchp) continue; -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - neighbor_patchp->updateEastEdge(); - neighbor_patchp->dirtyZ(); - } - - // Now do northeast/southwest connections -// Aurora Sim - //for (i = 1; i < mPatchesPerEdge; i++) - for (i = 1; i < ppe[1]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(0, i); - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i - 1); - patchp = getPatch(0, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(neighborPatchesPerEdge - 1, i - 1 + neighbor_offset[1]); - if (!neighbor_patchp) continue; -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, SOUTHWEST); - neighbor_patchp->connectNeighbor(patchp, NORTHEAST); - } - - // Now do northwest/southeast connections -// Aurora Sim - //for (i = 0; i < mPatchesPerEdge - 1; i++) - for (i = 0; i < ppe[1] - 1; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(0, i); - //neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i + 1); - patchp = getPatch(0, i + own_offset[1]); - neighbor_patchp = neighborp->getPatch(neighborPatchesPerEdge - 1, i + 1 + neighbor_offset[1]); - if (!neighbor_patchp) continue; -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, NORTHWEST); - neighbor_patchp->connectNeighbor(patchp, SOUTHEAST); - } - } - else if (SOUTH == direction) - { - // Do north/south connections, first -// Aurora Sim - //for (i = 0; i < mPatchesPerEdge; i++) - for (i = 0; i < ppe[0]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, 0); - //neighbor_patchp = neighborp->getPatch(i, mPatchesPerEdge - 1); - patchp = getPatch(i + own_offset[0], 0); - neighbor_patchp = neighborp->getPatch(i + neighbor_offset[0], neighborPatchesPerEdge - 1); - if (!neighbor_patchp) continue; -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - neighbor_patchp->updateNorthEdge(); - neighbor_patchp->dirtyZ(); - } - - // Now do northeast/southwest connections -// Aurora Sim - //for (i = 1; i < mPatchesPerEdge; i++) - for (i = 1; i < ppe[0]; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, 0); - //neighbor_patchp = neighborp->getPatch(i - 1, mPatchesPerEdge - 1); - patchp = getPatch(i + own_offset[0], 0); - neighbor_patchp = neighborp->getPatch(i - 1 + neighbor_offset[0], neighborPatchesPerEdge - 1); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, SOUTHWEST); - neighbor_patchp->connectNeighbor(patchp, NORTHEAST); - } - // Now do northeast/southwest connections -// Aurora Sim - //for (i = 0; i < mPatchesPerEdge - 1; i++) - for (i = 0; i < ppe[0] - 1; i++) -// Aurora Sim - { -// Aurora Sim - //patchp = getPatch(i, 0); - //neighbor_patchp = neighborp->getPatch(i + 1, mPatchesPerEdge - 1); - patchp = getPatch(i + own_offset[0], 0); - neighbor_patchp = neighborp->getPatch(i + 1 + neighbor_offset[0], neighborPatchesPerEdge - 1); -// Aurora Sim - - patchp->connectNeighbor(neighbor_patchp, SOUTHEAST); - neighbor_patchp->connectNeighbor(patchp, NORTHWEST); - } - } } void LLSurface::disconnectNeighbor(LLSurface *surfacep) @@ -730,10 +492,9 @@ void LLSurface::disconnectNeighbor(LLSurface *surfacep) } // Iterate through surface patches, removing any connectivity to removed surface. - if (mPatchList) // Don't crash if removed before - for (i = 0; i < mNumberOfPatches; i++) + for (auto& patchp : mPatchList) { - (mPatchList + i)->disconnectNeighbor(surfacep); + patchp->disconnectNeighbor(surfacep); } } @@ -802,13 +563,9 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent) LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal()); - LLSurfacePatch *patchp; - mVisiblePatchCount = 0; - for (S32 i=0; iupdateVisibility(); if (patchp->getVisible()) { @@ -832,19 +589,29 @@ BOOL LLSurface::idleUpdate(F32 max_update_time) // If the Z height data has changed, we need to rebuild our // property line vertex arrays. - if (mDirtyPatchList.size() > 0) + if (!mDirtyPatchList.empty()) { getRegion()->dirtyHeights(); } // Always call updateNormals() / updateVerticalStats() // every frame to avoid artifacts - for(std::set::iterator iter = mDirtyPatchList.begin(); - iter != mDirtyPatchList.end(); ) + for (auto& it = mDirtyPatchList.cbegin(); it != mDirtyPatchList.cend();) { - std::set::iterator curiter = iter++; - LLSurfacePatch *patchp = *curiter; - patchp->updateNormals(); + if (it->second.expired()) + { + LL_WARNS() << "Expired dirty patch detected. Side " << it->first << LL_ENDL; + } + surface_patch_ref patchp = it->second.lock(); + if (!patchp) + { + it = mDirtyPatchList.erase(it); + continue; + } + if (patchp->updateNormals()) + { + patchp->getSurface()->dirtySurfacePatch(patchp); + } patchp->updateVerticalStats(); if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time) { @@ -852,9 +619,11 @@ BOOL LLSurface::idleUpdate(F32 max_update_time) { did_update = TRUE; patchp->clearDirty(); - mDirtyPatchList.erase(curiter); + it = mDirtyPatchList.erase(it); + continue; } } + ++it; } return did_update; } @@ -865,7 +634,6 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL LLPatchHeader ph; S32 j, i; S32 patch[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE]; - LLSurfacePatch *patchp; init_patch_decompressor(gopp->patch_size); gopp->stride = mGridsPerEdge; @@ -912,8 +680,7 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL return; } - patchp = &mPatchList[j*mPatchesPerEdge + i]; - + const surface_patch_ref& patchp = mPatchList[j * mPatchesPerEdge + i]; decode_patch(bitpack, patch); decompress_patch(patchp->getDataZ(), patch, &ph); @@ -921,22 +688,26 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL // Update edges for neighbors. Need to guarantee that this gets done before we generate vertical stats. patchp->updateNorthEdge(); patchp->updateEastEdge(); - if (patchp->getNeighborPatch(WEST)) + LLSurfacePatch* neighborPatch; + if (neighborPatch = patchp->getNeighborPatch(WEST)) { - patchp->getNeighborPatch(WEST)->updateEastEdge(); + neighborPatch->updateEastEdge(); } - if (patchp->getNeighborPatch(SOUTHWEST)) + if (neighborPatch = patchp->getNeighborPatch(SOUTHWEST)) { - patchp->getNeighborPatch(SOUTHWEST)->updateEastEdge(); - patchp->getNeighborPatch(SOUTHWEST)->updateNorthEdge(); + neighborPatch->updateEastEdge(); + neighborPatch->updateNorthEdge(); } - if (patchp->getNeighborPatch(SOUTH)) + if (neighborPatch = patchp->getNeighborPatch(SOUTH)) { - patchp->getNeighborPatch(SOUTH)->updateNorthEdge(); + neighborPatch->updateNorthEdge(); } // Dirty patch statistics, and flag that the patch has data. - patchp->dirtyZ(); + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } patchp->setHasReceivedData(); } } @@ -1089,8 +860,13 @@ LLVector3 LLSurface::resolveNormalGlobal(const LLVector3d& pos_global) const } -LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const +const surface_patch_ref& LLSurface::resolvePatchRegion(const F32 x, const F32 y) const { + if (mPatchList.empty()) { + LL_WARNS() << "No patches for current region!" << LL_ENDL; + static surface_patch_ref empty; + return empty; + } // x and y should be region-local coordinates. // If x and y are outside of the surface, then the returned // index will be for the nearest boundary patch. @@ -1141,29 +917,24 @@ LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const // *NOTE: Super paranoia code follows. S32 index = i + j * mPatchesPerEdge; - if((index < 0) || (index >= mNumberOfPatches)) + if((index < 0) || (index >= mPatchList.size())) { - if(0 == mNumberOfPatches) - { - LL_WARNS() << "No patches for current region!" << LL_ENDL; - return NULL; - } S32 old_index = index; - index = llclamp(old_index, 0, (mNumberOfPatches - 1)); + index = llclamp(old_index, 0, ((S32)mPatchList.size() - 1)); LL_WARNS() << "Clamping out of range patch index " << old_index << " to " << index << LL_ENDL; } - return &(mPatchList[index]); + return mPatchList[index]; } -LLSurfacePatch *LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const +const surface_patch_ref& LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const { return resolvePatchRegion(pos_region.mV[VX], pos_region.mV[VY]); } -LLSurfacePatch *LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const +const surface_patch_ref& LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const { llassert(mRegionp); LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(pos_global); @@ -1192,37 +963,28 @@ void LLSurface::createPatchData() // Assumes mGridsPerEdge, mGridsPerPatchEdge, and mPatchesPerEdge have been properly set // TODO -- check for create() called when surface is not empty S32 i, j; - LLSurfacePatch *patchp; // Allocate memory - mPatchList = new LLSurfacePatch[mNumberOfPatches]; - - // One of each for each camera - mVisiblePatchCount = mNumberOfPatches; - - for (j=0; jsetSurface(this); - } + mPatchList[i] = std::make_shared(this, i); } + // One of each for each camera + mVisiblePatchCount = mPatchList.size(); + for (j=0; jmHasReceivedData = FALSE; - patchp->mSTexUpdate = TRUE; + const auto& patchp = getPatch(i, j); S32 data_offset = i * mGridsPerPatchEdge + j * mGridsPerPatchEdge * mGridsPerEdge; patchp->setDataZ(mSurfaceZ + data_offset); patchp->setDataNorm(mNorm + data_offset); - // We make each patch point to its neighbors so we can do resolution checking // when butting up different resolutions. Patches that don't have neighbors // somewhere will point to NULL on that side. @@ -1311,9 +1073,7 @@ void LLSurface::createPatchData() void LLSurface::destroyPatchData() { // Delete all of the cached patch data for these patches. - - delete [] mPatchList; - mPatchList = NULL; + mPatchList.clear(); mVisiblePatchCount = 0; } @@ -1336,36 +1096,50 @@ U32 LLSurface::getRenderStride(const U32 render_level) const } -LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const +const surface_patch_ref& LLSurface::getPatch(const S32 x, const S32 y) const { + static surface_patch_ref empty(nullptr); if ((x < 0) || (x >= mPatchesPerEdge)) { LL_WARNS() << "Asking for patch out of bounds" << LL_ENDL; - return NULL; + return empty; } if ((y < 0) || (y >= mPatchesPerEdge)) { LL_WARNS() << "Asking for patch out of bounds" << LL_ENDL; - return NULL; + return empty; } - return mPatchList + x + y*mPatchesPerEdge; + return mPatchList[x + y*mPatchesPerEdge]; } void LLSurface::dirtyAllPatches() { - S32 i; - for (i = 0; i < mNumberOfPatches; i++) + for (auto& patchp : mPatchList) { - mPatchList[i].dirtyZ(); + if (patchp->dirtyZ()) + { + dirtySurfacePatch(patchp); + } } } -void LLSurface::dirtySurfacePatch(LLSurfacePatch *patchp) +void LLSurface::dirtySurfacePatch(const surface_patch_ref& patchp) { + if (!patchp) + { + return; + } + // Put surface patch on dirty surface patch list - mDirtyPatchList.insert(patchp); + if (std::find_if(mDirtyPatchList.begin(), mDirtyPatchList.end(), + [&patchp](std::pair >& entry) -> bool { + return entry.second.lock().get() == patchp.get(); + }) == mDirtyPatchList.end()) + { + mDirtyPatchList.push_back(std::make_pair(patchp->getSide(), patchp)); + } } diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h index aedac01a3..16d96c467 100644 --- a/indra/newview/llsurface.h +++ b/indra/newview/llsurface.h @@ -60,9 +60,12 @@ static const S32 ONE_LESS_THAN_NEIGHBOR = -1; const S32 ABOVE_WATERLINE_ALPHA = 32; // The alpha of water when the land elevation is above the waterline. class LLViewerRegion; -class LLSurfacePatch; class LLBitPack; class LLGroupHeader; +class LLSurfacePatch; + +typedef std::shared_ptr surface_patch_ref; +typedef std::weak_ptr surface_patch_weak_ref; class LLSurface { @@ -111,9 +114,9 @@ public: F32 resolveHeightGlobal(const LLVector3d &position_global) const; LLVector3 resolveNormalGlobal(const LLVector3d& v) const; // Returns normal to surface - LLSurfacePatch *resolvePatchRegion(const F32 x, const F32 y) const; - LLSurfacePatch *resolvePatchRegion(const LLVector3 &position_region) const; - LLSurfacePatch *resolvePatchGlobal(const LLVector3d &position_global) const; + const surface_patch_ref& resolvePatchRegion(const F32 x, const F32 y) const; + const surface_patch_ref& resolvePatchRegion(const LLVector3 &position_region) const; + const surface_patch_ref& resolvePatchGlobal(const LLVector3d &position_global) const; // Update methods (called during idle, normally) BOOL idleUpdate(F32 max_update_time); @@ -136,7 +139,7 @@ public: void dirtyAllPatches(); // Use this to dirty all patches when changing terrain parameters - void dirtySurfacePatch(LLSurfacePatch *patchp); + void dirtySurfacePatch(const surface_patch_ref& patchp); LLVOWater *getWaterObj() { return mWaterObjp; } static void setTextureSize(const S32 texture_size); @@ -155,8 +158,6 @@ public: F32 mOOGridsPerEdge; // Inverse of grids per edge S32 mPatchesPerEdge; // Number of patches on one side of a region - S32 mNumberOfPatches; // Total number of patches - // Each surface points at 8 neighbors (or NULL) // +---+---+---+ @@ -191,11 +192,11 @@ protected: //F32 updateTexture(LLSurfacePatch *ppatch); - LLSurfacePatch *getPatch(const S32 x, const S32 y) const; + const surface_patch_ref& getPatch(const S32 x, const S32 y) const; protected: LLVector3d mOriginGlobal; // In absolute frame - LLSurfacePatch *mPatchList; // Array of all patches + std::vector< surface_patch_ref > mPatchList; // Array of all patches // Array of grid data, mGridsPerEdge * mGridsPerEdge F32 *mSurfaceZ; @@ -203,7 +204,7 @@ protected: // Array of grid normals, mGridsPerEdge * mGridsPerEdge LLVector3 *mNorm; - std::set mDirtyPatchList; + std::vector< std::pair > mDirtyPatchList; // The textures should never be directly initialized - use the setter methods! diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 9112aa9fd..c999fff22 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -47,9 +47,9 @@ extern bool gShiftFrame; extern U64MicrosecondsImplicit gFrameTime; extern LLPipeline gPipeline; -LLSurfacePatch::LLSurfacePatch() +LLSurfacePatch::LLSurfacePatch(LLSurface* surface, U32 side) : mHasReceivedData(FALSE), - mSTexUpdate(FALSE), + mSTexUpdate(TRUE), mDirty(FALSE), mDirtyZStats(TRUE), mHeightsGenerated(FALSE), @@ -70,17 +70,12 @@ LLSurfacePatch::LLSurfacePatch() // set to non-zero values by higher classes. mConnectedEdge(NO_EDGE), mLastUpdateTime(0), - mSurfacep(NULL) -{ - S32 i; - for (i = 0; i < 8; i++) - { - setNeighborPatch(i, NULL); - } - for (i = 0; i < 9; i++) - { - mNormalsInvalid[i] = TRUE; - } + mSurfacep(NULL), + mNeighborPatches{ 0,0,0,0,0,0,0,0 }, + mNormalsInvalid{ 1,1,1,1,1,1,1,1,1 }, + mSide(side) +{ + setSurface(surface); } @@ -90,7 +85,7 @@ LLSurfacePatch::~LLSurfacePatch() } -void LLSurfacePatch::dirty() +bool LLSurfacePatch::dirty() { // These are outside of the loop in case we're still waiting for a dirty from the // texture being updated... @@ -109,8 +104,9 @@ void LLSurfacePatch::dirty() if (!mDirty) { mDirty = TRUE; - mSurfacep->dirtySurfacePatch(this); + return true; } + return false; } @@ -133,45 +129,31 @@ void LLSurfacePatch::disconnectNeighbor(LLSurface *surfacep) U32 i; for (i = 0; i < 8; i++) { - if (getNeighborPatch(i)) + const auto& patch = getNeighborPatch(i); + if (patch) { - if (getNeighborPatch(i)->mSurfacep == surfacep) + if (patch->mSurfacep == surfacep) { + if (EAST == i) + { + mConnectedEdge &= EAST_EDGE; + } + else if (NORTH == i) + { + mConnectedEdge &= NORTH_EDGE; + } + else if (WEST == i) + { + mConnectedEdge &= WEST_EDGE; + } + else if (SOUTH == i) + { + mConnectedEdge &= SOUTH_EDGE; + } setNeighborPatch(i, NULL); - mNormalsInvalid[i] = TRUE; } } } - - // Clean up connected edges - if (getNeighborPatch(EAST)) - { - if (getNeighborPatch(EAST)->mSurfacep == surfacep) - { - mConnectedEdge &= ~EAST_EDGE; - } - } - if (getNeighborPatch(NORTH)) - { - if (getNeighborPatch(NORTH)->mSurfacep == surfacep) - { - mConnectedEdge &= ~NORTH_EDGE; - } - } - if (getNeighborPatch(WEST)) - { - if (getNeighborPatch(WEST)->mSurfacep == surfacep) - { - mConnectedEdge &= ~WEST_EDGE; - } - } - if (getNeighborPatch(SOUTH)) - { - if (getNeighborPatch(SOUTH)->mSurfacep == surfacep) - { - mConnectedEdge &= ~SOUTH_EDGE; - } - } } LLVector3 LLSurfacePatch::getPointAgent(const U32 x, const U32 y) const @@ -283,64 +265,65 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride) { for (j = 0; j < 2; j++) { + LLSurfacePatch* patch; if (poffsets[i][j][0] < 0) { - if (!ppatches[i][j]->getNeighborPatch(WEST)) + if (patch = ppatches[i][j]->getNeighborPatch(WEST)) { - poffsets[i][j][0] = 0; + // Aurora Sim + ppatches[i][j] = patch; + poffsets[i][j][0] += patch_width; + poffsets[i][j][2] = patch->getSurface()->getGridsPerEdge(); +// Aurora Sim } else { -// Aurora Sim - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST); - poffsets[i][j][0] += patch_width; - poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge(); -// Aurora Sim + poffsets[i][j][0] = 0; } } if (poffsets[i][j][1] < 0) { - if (!ppatches[i][j]->getNeighborPatch(SOUTH)) + if (patch = ppatches[i][j]->getNeighborPatch(SOUTH)) { - poffsets[i][j][1] = 0; +// Aurora Sim + ppatches[i][j] = patch; + poffsets[i][j][1] += patch_width; + poffsets[i][j][2] = patch->getSurface()->getGridsPerEdge(); +// CR> Aurora Sim } else { -// Aurora Sim - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH); - poffsets[i][j][1] += patch_width; - poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge(); -// CR> Aurora Sim + poffsets[i][j][1] = 0; } } if (poffsets[i][j][0] >= (S32)patch_width) { - if (!ppatches[i][j]->getNeighborPatch(EAST)) + if (patch = ppatches[i][j]->getNeighborPatch(EAST)) { - poffsets[i][j][0] = patch_width - 1; +// Aurora Sim + ppatches[i][j] = patch; + poffsets[i][j][0] -= patch_width; + poffsets[i][j][2] = patch->getSurface()->getGridsPerEdge(); +// Aurora Sim } else { -// Aurora Sim - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST); - poffsets[i][j][0] -= patch_width; - poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge(); -// Aurora Sim + poffsets[i][j][0] = patch_width - 1; } } if (poffsets[i][j][1] >= (S32)patch_width) { - if (!ppatches[i][j]->getNeighborPatch(NORTH)) + if (patch = ppatches[i][j]->getNeighborPatch(NORTH)) { - poffsets[i][j][1] = patch_width - 1; +// Aurora Sim + ppatches[i][j] = patch; + poffsets[i][j][1] -= patch_width; + poffsets[i][j][2] = patch->getSurface()->getGridsPerEdge(); +// Aurora Sim } else { -// Aurora Sim - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH); - poffsets[i][j][1] -= patch_width; - poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge(); -// Aurora Sim + poffsets[i][j][1] = patch_width - 1; } } } @@ -474,11 +457,11 @@ void LLSurfacePatch::updateVerticalStats() } -void LLSurfacePatch::updateNormals() +bool LLSurfacePatch::updateNormals() { if (mSurfacep->mType == 'w') { - return; + return false; } U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); U32 grids_per_edge = mSurfacep->getGridsPerEdge(); @@ -515,10 +498,12 @@ void LLSurfacePatch::updateNormals() // update the west edge if (mNormalsInvalid[NORTHWEST] || mNormalsInvalid[WEST] || mNormalsInvalid[SOUTHWEST]) { + LLSurfacePatch* northwest_patchp = getNeighborPatch(NORTHWEST); + LLSurfacePatch* north_patchp = getNeighborPatch(NORTH); // Aurora Sim - if (!getNeighborPatch(NORTH) && getNeighborPatch(NORTHWEST) && getNeighborPatch(NORTHWEST)->getHasReceivedData()) + if (!north_patchp && northwest_patchp && northwest_patchp->getHasReceivedData()) { - *(mDataZ + grids_per_patch_edge*grids_per_edge) = *(getNeighborPatch(NORTHWEST)->mDataZ + grids_per_patch_edge); + *(mDataZ + grids_per_patch_edge*grids_per_edge) = *(northwest_patchp->mDataZ + grids_per_patch_edge); } // Aurora Sim @@ -533,10 +518,12 @@ void LLSurfacePatch::updateNormals() // update the south edge if (mNormalsInvalid[SOUTHWEST] || mNormalsInvalid[SOUTH] || mNormalsInvalid[SOUTHEAST]) { + LLSurfacePatch* southeast_patchp = getNeighborPatch(SOUTHEAST); + LLSurfacePatch* east_patchp = getNeighborPatch(EAST); // Aurora Sim - if (!getNeighborPatch(EAST) && getNeighborPatch(SOUTHEAST) && getNeighborPatch(SOUTHEAST)->getHasReceivedData()) + if (!east_patchp && southeast_patchp && southeast_patchp->getHasReceivedData()) { - *(mDataZ + grids_per_patch_edge) = *(getNeighborPatch(SOUTHEAST)->mDataZ + grids_per_patch_edge * getNeighborPatch(SOUTHEAST)->getSurface()->getGridsPerEdge()); + *(mDataZ + grids_per_patch_edge) = *(southeast_patchp->mDataZ + grids_per_patch_edge * southeast_patchp->getSurface()->getGridsPerEdge()); } // Aurora Sim @@ -552,11 +539,14 @@ void LLSurfacePatch::updateNormals() // we'll want to do different things. if (mNormalsInvalid[NORTHEAST]) { - if (!getNeighborPatch(NORTHEAST)) + LLSurfacePatch* northeast_patchp = getNeighborPatch(NORTHEAST); + LLSurfacePatch* north_patchp = getNeighborPatch(NORTH); + LLSurfacePatch* east_patchp = getNeighborPatch(EAST); + if (!northeast_patchp) { - if (!getNeighborPatch(NORTH)) + if (!north_patchp) { - if (!getNeighborPatch(EAST)) + if (!east_patchp) { // No north or east neighbors. Pull from the diagonal in your own patch. *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = @@ -564,13 +554,13 @@ void LLSurfacePatch::updateNormals() } else { - if (getNeighborPatch(EAST)->getHasReceivedData()) + if (east_patchp->getHasReceivedData()) { // East, but not north. Pull from your east neighbor's northwest point. *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = // Aurora Sim //*(getNeighborPatch(EAST)->mDataZ + (grids_per_patch_edge - 1)*grids_per_edge); - *(getNeighborPatch(EAST)->mDataZ + (getNeighborPatch(EAST)->getSurface()->getGridsPerPatchEdge() - 1)*getNeighborPatch(EAST)->getSurface()->getGridsPerEdge()); + *(east_patchp->mDataZ + (east_patchp->getSurface()->getGridsPerPatchEdge() - 1)* east_patchp->getSurface()->getGridsPerEdge()); // Aurora Sim } else @@ -583,7 +573,7 @@ void LLSurfacePatch::updateNormals() else { // We have a north. - if (getNeighborPatch(EAST)) + if (east_patchp) { // North and east neighbors, but not northeast. // Pull from diagonal in your own patch. @@ -592,13 +582,13 @@ void LLSurfacePatch::updateNormals() } else { - if (getNeighborPatch(NORTH)->getHasReceivedData()) + if (north_patchp->getHasReceivedData()) { // North, but not east. Pull from your north neighbor's southeast corner. *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = // Aurora Sim //*(getNeighborPatch(NORTH)->mDataZ + (grids_per_patch_edge - 1)); - *(getNeighborPatch(NORTH)->mDataZ + (getNeighborPatch(NORTH)->getSurface()->getGridsPerPatchEdge() - 1)); + *(north_patchp->mDataZ + (north_patchp->getSurface()->getGridsPerPatchEdge() - 1)); // Aurora Sim } else @@ -609,25 +599,25 @@ void LLSurfacePatch::updateNormals() } } } - else if (getNeighborPatch(NORTHEAST)->mSurfacep != mSurfacep) + else if (northeast_patchp->mSurfacep != mSurfacep) { if ( - (!getNeighborPatch(NORTH) || (getNeighborPatch(NORTH)->mSurfacep != mSurfacep)) + (!north_patchp || (north_patchp->mSurfacep != mSurfacep)) && - (!getNeighborPatch(EAST) || (getNeighborPatch(EAST)->mSurfacep != mSurfacep))) + (!east_patchp || (east_patchp->mSurfacep != mSurfacep))) { // Aurora Sim U32 own_xpos, own_ypos, neighbor_xpos, neighbor_ypos; S32 own_offset = 0, neighbor_offset = 0; from_region_handle(mSurfacep->getRegion()->getHandle(), &own_xpos, &own_ypos); - from_region_handle(getNeighborPatch(NORTHEAST)->mSurfacep->getRegion()->getHandle(), &neighbor_xpos, &neighbor_ypos); + from_region_handle(northeast_patchp->mSurfacep->getRegion()->getHandle(), &neighbor_xpos, &neighbor_ypos); if (own_ypos >= neighbor_ypos) neighbor_offset = own_ypos - neighbor_ypos; else own_offset = neighbor_ypos - own_ypos; *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(getNeighborPatch(NORTHEAST)->mDataZ + (grids_per_edge + neighbor_offset - own_offset - 1) * getNeighborPatch(NORTHEAST)->getSurface()->getGridsPerEdge()); + *(northeast_patchp->mDataZ + (grids_per_edge + neighbor_offset - own_offset - 1) * northeast_patchp->getSurface()->getGridsPerEdge()); // Aurora Sim } } @@ -656,15 +646,12 @@ void LLSurfacePatch::updateNormals() dirty_patch = TRUE; } - if (dirty_patch) - { - mSurfacep->dirtySurfacePatch(this); - } - for (i = 0; i < 9; i++) { mNormalsInvalid[i] = FALSE; } + + return dirty_patch; } void LLSurfacePatch::updateEastEdge() @@ -719,7 +706,8 @@ void LLSurfacePatch::updateNorthEdge() U32 i; F32 *south_surface, *north_surface; - if (!getNeighborPatch(NORTH)) + LLSurfacePatch* patchp = getNeighborPatch(NORTH); + if (!patchp) { south_surface = mDataZ + grids_per_patch_edge*grids_per_edge; north_surface = mDataZ + (grids_per_patch_edge - 1) * grids_per_edge; @@ -727,7 +715,7 @@ void LLSurfacePatch::updateNorthEdge() else if (mConnectedEdge & NORTH_EDGE) { south_surface = mDataZ + grids_per_patch_edge*grids_per_edge; - north_surface = getNeighborPatch(NORTH)->mDataZ; + north_surface = patchp->mDataZ; } else { @@ -748,10 +736,11 @@ BOOL LLSurfacePatch::updateTexture() F32 meters_per_grid = getSurface()->getMetersPerGrid(); F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); - if ((!getNeighborPatch(EAST) || getNeighborPatch(EAST)->getHasReceivedData()) - && (!getNeighborPatch(WEST) || getNeighborPatch(WEST)->getHasReceivedData()) - && (!getNeighborPatch(SOUTH) || getNeighborPatch(SOUTH)->getHasReceivedData()) - && (!getNeighborPatch(NORTH) || getNeighborPatch(NORTH)->getHasReceivedData())) + LLSurfacePatch* patchp; + if ((!(patchp = getNeighborPatch(EAST)) || patchp->getHasReceivedData()) + && (!(patchp = getNeighborPatch(WEST)) || patchp->getHasReceivedData()) + && (!(patchp = getNeighborPatch(SOUTH)) || patchp->getHasReceivedData()) + && (!(patchp = getNeighborPatch(NORTH)) || patchp->getHasReceivedData())) { LLViewerRegion *regionp = getSurface()->getRegion(); LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); @@ -813,7 +802,7 @@ void LLSurfacePatch::updateGL() } } -void LLSurfacePatch::dirtyZ() +bool LLSurfacePatch::dirtyZ() { mSTexUpdate = TRUE; @@ -827,20 +816,36 @@ void LLSurfacePatch::dirtyZ() // Invalidate normals in this and neighboring patches for (i = 0; i < 8; i++) { - if (getNeighborPatch(i)) + if (mNeighborPatches[i] == nullptr) { - getNeighborPatch(i)->mNormalsInvalid[gDirOpposite[i]] = TRUE; - getNeighborPatch(i)->dirty(); + continue; + } + if (mNeighborPatches[i]->expired()) + { + LL_WARNS() << "Expired neighbor patch detected. Side " << i << LL_ENDL; + delete mNeighborPatches[i]; + mNeighborPatches[i] = nullptr; + continue; + } + const surface_patch_ref& patchp = mNeighborPatches[i]->lock(); + if (patchp) + { + patchp->mNormalsInvalid[gDirOpposite[i]] = TRUE; + if (patchp->dirty()) + { + patchp->getSurface()->dirtySurfacePatch(patchp); + } if (i < 4) { - getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE; - getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE; + patchp->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE; + patchp->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE; } } } - dirty(); mLastUpdateTime = gFrameTime; + + return dirty(); } @@ -877,35 +882,29 @@ void LLSurfacePatch::setOriginGlobal(const LLVector3d &origin_global) } -void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32 direction) +void LLSurfacePatch::connectNeighbor(const surface_patch_ref& neighbor_patchp, const U32 direction) { llassert(neighbor_patchp); if (!neighbor_patchp) return; mNormalsInvalid[direction] = TRUE; - neighbor_patchp->mNormalsInvalid[gDirOpposite[direction]] = TRUE; setNeighborPatch(direction, neighbor_patchp); - neighbor_patchp->setNeighborPatch(gDirOpposite[direction], this); if (EAST == direction) { mConnectedEdge |= EAST_EDGE; - neighbor_patchp->mConnectedEdge |= WEST_EDGE; } else if (NORTH == direction) { mConnectedEdge |= NORTH_EDGE; - neighbor_patchp->mConnectedEdge |= SOUTH_EDGE; } else if (WEST == direction) { mConnectedEdge |= WEST_EDGE; - neighbor_patchp->mConnectedEdge |= EAST_EDGE; } else if (SOUTH == direction) { mConnectedEdge |= SOUTH_EDGE; - neighbor_patchp->mConnectedEdge |= NORTH_EDGE; } } @@ -963,13 +962,14 @@ void LLSurfacePatch::updateVisibility() if (mVObjp) { mVObjp->dirtyGeom(); - if (getNeighborPatch(WEST)) + LLSurfacePatch* patchp; + if (patchp = getNeighborPatch(WEST)) { - getNeighborPatch(WEST)->mVObjp->dirtyGeom(); + patchp->mVObjp->dirtyGeom(); } - if (getNeighborPatch(SOUTH)) + if (patchp = getNeighborPatch(SOUTH)) { - getNeighborPatch(SOUTH)->mVObjp->dirtyGeom(); + patchp->mVObjp->dirtyGeom(); } } } @@ -1074,9 +1074,21 @@ F32 LLSurfacePatch::getMaxComposition() const return mMaxComposition; } -void LLSurfacePatch::setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp) +void LLSurfacePatch::setNeighborPatch(const U32 direction, const surface_patch_ref& neighborp) { - mNeighborPatches[direction] = neighborp; + if (!neighborp) + { + delete mNeighborPatches[direction]; + mNeighborPatches[direction] = nullptr; + } + else + { + if (mNeighborPatches[direction] == nullptr) + { + mNeighborPatches[direction] = new surface_patch_weak_ref(); + } + *mNeighborPatches[direction] = neighborp; + } mNormalsInvalid[direction] = TRUE; if (direction < 4) { @@ -1087,7 +1099,15 @@ void LLSurfacePatch::setNeighborPatch(const U32 direction, LLSurfacePatch *neigh LLSurfacePatch *LLSurfacePatch::getNeighborPatch(const U32 direction) const { - return mNeighborPatches[direction]; + if (mNeighborPatches[direction] == nullptr) + { + return nullptr; + } + else if (mNeighborPatches[direction]->expired()) + { + LL_WARNS() << "Expired neighbor patch detected. Side " << direction << LL_ENDL; + } + return mNeighborPatches[direction]->lock().get(); } void LLSurfacePatch::clearVObj() diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h index ebfb64c1d..8d6447e7f 100644 --- a/indra/newview/llsurfacepatch.h +++ b/indra/newview/llsurfacepatch.h @@ -43,6 +43,10 @@ class LLVector2; class LLColor4U; class LLAgent; +class LLSurfacePatch; +typedef std::shared_ptr surface_patch_ref; +typedef std::weak_ptr surface_patch_weak_ref; + // A patch shouldn't know about its visibility since that really depends on the // camera that is looking (or not looking) at it. So, anything about a patch // that is specific to a camera should be in the class below. @@ -64,26 +68,23 @@ public: -class LLSurfacePatch +class LLSurfacePatch { public: - LLSurfacePatch(); + LLSurfacePatch(LLSurface* surface, U32 side); ~LLSurfacePatch(); - void reset(const U32 id); - void connectNeighbor(LLSurfacePatch *neighborp, const U32 direction); + void connectNeighbor(const surface_patch_ref& neighbor_patchp, const U32 direction); void disconnectNeighbor(LLSurface *surfacep); - void setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp); + void setNeighborPatch(const U32 direction, const surface_patch_ref& neighborp); LLSurfacePatch *getNeighborPatch(const U32 direction) const; - void colorPatch(const U8 r, const U8 g, const U8 b); - BOOL updateTexture(); void updateVerticalStats(); void updateCompositionStats(); - void updateNormals(); + bool updateNormals(); void updateEastEdge(); void updateNorthEdge(); @@ -92,7 +93,7 @@ public: void updateVisibility(); void updateGL(); - void dirtyZ(); // Dirty the z values of this patch + bool dirtyZ(); // Dirty the z values of this patch void setHasReceivedData(); BOOL getHasReceivedData() const; @@ -139,17 +140,19 @@ public: void setDataNorm(LLVector3 *data_norm) { mDataNorm = data_norm; } F32 *getDataZ() const { return mDataZ; } - void dirty(); // Mark this surface patch as dirty... + bool dirty(); // Mark this surface patch as dirty... void clearDirty() { mDirty = FALSE; } void clearVObj(); + U32 getSide() const { return mSide; } + public: BOOL mHasReceivedData; // has the patch EVER received height data? BOOL mSTexUpdate; // Does the surface texture need to be updated? protected: - LLSurfacePatch *mNeighborPatches[8]; // Adjacent patches + std::weak_ptr* mNeighborPatches[8]; // Adjacent patches BOOL mNormalsInvalid[9]; // Which normals are invalid BOOL mDirty; @@ -184,6 +187,8 @@ protected: // of LLSurface that is "connected" to another LLSurface U64 mLastUpdateTime; // Time patch was last updated + U32 mSide; // Side relative to parent surface. + LLSurface *mSurfacep; // Pointer to "parent" surface }; diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp index e5cfdc1ae..79a9d6c6c 100644 --- a/indra/newview/lltoolbrush.cpp +++ b/indra/newview/lltoolbrush.cpp @@ -164,10 +164,10 @@ void LLToolBrushLand::modifyLandAtPointGlobal(const LLVector3d &pos_global, //if(!is_changed) continue; // Now to update the patch information so it will redraw correctly. - LLSurfacePatch *patchp= land.resolvePatchRegion(pos_region); - if (patchp) + auto& patchp = land.resolvePatchRegion(pos_region); + if (patchp && patchp->dirtyZ()) { - patchp->dirtyZ(); + patchp->getSurface()->dirtySurfacePatch(patchp); } // Also force the property lines to update, normals to recompute, etc. @@ -305,10 +305,10 @@ void LLToolBrushLand::modifyLandInSelectionGlobal() //if(!is_changed) continue; // Now to update the patch information so it will redraw correctly. - LLSurfacePatch *patchp= land.resolvePatchRegion(min_region); - if (patchp) + auto& patchp = land.resolvePatchRegion(min_region); + if (patchp && patchp->dirtyZ()) { - patchp->dirtyZ(); + patchp->getSurface()->dirtySurfacePatch(patchp); } // Also force the property lines to update, normals to recompute, etc. diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index c6f684685..1432e4df7 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -575,6 +575,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t bool handleEvent(LLPointer event, const LLSD& userdata) { LLPointer raw = new LLImageRaw; + raw->enableOverSize(); S32 width = gViewerWindow->getWindowDisplayWidth(); S32 height = gViewerWindow->getWindowDisplayHeight(); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index b18dc5de9..ca1eb74ab 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -965,6 +965,7 @@ void LLViewerRegion::forceUpdate() void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction) { mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction); + neighborp->mImpl->mLandp->connectNeighbor(mImpl->mLandp, gDirOpposite[direction]); #if ENABLE_CLASSIC_CLOUDS mCloudLayer.connectNeighbor(&(neighborp->mCloudLayer), direction); #endif diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 31d6db341..e39dedba4 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -81,7 +81,6 @@ LLVOGrass::SpeciesNames LLVOGrass::sSpeciesNames; LLVOGrass::LLVOGrass(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLAlphaObject(id, pcode, regionp) { - mPatch = NULL; mLastPatchUpdateTime = 0; mGrassVel.clearVec(); mGrassBend.clearVec(); @@ -331,7 +330,8 @@ void LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return; } - if (mPatch && (mLastPatchUpdateTime != mPatch->getLastUpdateTime())) + const auto& patch = mPatch.lock(); + if (patch && (mLastPatchUpdateTime != patch->getLastUpdateTime())) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } @@ -507,9 +507,10 @@ void LLVOGrass::getGeometry(S32 idx, return ; } - mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion()); - if (mPatch) - mLastPatchUpdateTime = mPatch->getLastUpdateTime(); + const auto& patch = mRegionp->getLand().resolvePatchRegion(getPositionRegion()); + if (patch) + mLastPatchUpdateTime = patch->getLastUpdateTime(); + mPatch = patch; LLVector3 position; // Create random blades of grass with gaussian distribution diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index 90911de7f..f4f1da6fe 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -108,7 +108,7 @@ public: F32 mBladeSizeX; F32 mBladeSizeY; - LLSurfacePatch *mPatch; // Stores the land patch where the grass is centered + std::weak_ptr mPatch; // Stores the land patch where the grass is centered U64 mLastPatchUpdateTime; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 4907c944b..99312e1ca 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -267,18 +267,19 @@ BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) length = patch_width / render_stride; - if (mPatchp->getNeighborPatch(NORTH)) + LLSurfacePatch* neighborPatch; + if (neighborPatch = mPatchp->getNeighborPatch(NORTH)) { - north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride(); + north_stride = neighborPatch->getRenderStride(); } else { north_stride = render_stride; } - if (mPatchp->getNeighborPatch(EAST)) + if (neighborPatch = mPatchp->getNeighborPatch(EAST)) { - east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride(); + east_stride = neighborPatch->getRenderStride(); } else { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b62f653f3..722aaca16 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5569,15 +5569,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) else { - if( type == LLDrawPool::POOL_FULLBRIGHT || type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) - { - pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); - } //Annoying exception to the rule. getPoolTypeFromTE will return POOL_ALPHA_MASK for legacy bumpmaps, but there is no POOL_ALPHA_MASK in deferred. - else if(type == LLDrawPool::POOL_MATERIALS || (type == LLDrawPool::POOL_ALPHA_MASK && mat)) + if (type == LLDrawPool::POOL_MATERIALS || ((type == LLDrawPool::POOL_ALPHA_MASK || type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) && mat)) { pool->addRiggedFace(facep, mat->getShaderMask()); } + else if (type == LLDrawPool::POOL_FULLBRIGHT || type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } else if (type == LLDrawPool::POOL_BUMP && te->getBumpmap()) { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); @@ -5674,7 +5674,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) type = LLDrawPool::POOL_FULLBRIGHT; } } - else if(force_simple && type != LLDrawPool::POOL_FULLBRIGHT && type != LLDrawPool::POOL_ALPHA_MASK && type != LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) + else if(force_simple && type != LLDrawPool::POOL_FULLBRIGHT && (!LLPipeline::sRenderDeferred && (type != LLDrawPool::POOL_ALPHA_MASK && type != LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK))) { type = LLDrawPool::POOL_SIMPLE; } diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 4e94ce3b2..23cf8ab6d 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -673,7 +673,7 @@ LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global) return NULL; } - return regionp->getLand().resolvePatchGlobal(pos_global); + return regionp->getLand().resolvePatchGlobal(pos_global).get(); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ee4c4c25d..887faf733 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2667,6 +2667,9 @@ void LLPipeline::clearRebuildGroups() iter != mGroupQ2.end(); ++iter) { LLSpatialGroup* group = *iter; + if (group == nullptr) { + LL_WARNS() << "Null spatial group in Pipeline::mGroupQ2." << LL_ENDL; + } // If the group contains HUD objects, save the group if (group->isHUDGroup())