From d3a8367053ad6bb4d044171de5d343f75c56b8ca Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Fri, 4 Mar 2022 21:58:16 -0500
Subject: [PATCH] More var region support

---
 indra/newview/llsurface.cpp         | 165 +++++++++++++++++++---------
 indra/newview/llsurfacepatch.cpp    |  72 +++++++++---
 indra/newview/llviewerparcelmgr.cpp |   9 +-
 indra/newview/llviewerstats.cpp     |   2 +-
 indra/newview/llvlcomposition.cpp   |   2 +-
 indra/newview/llvlmanager.cpp       |  38 +++++--
 indra/newview/llvlmanager.h         |   2 +
 indra/newview/llvowater.cpp         |   2 +-
 8 files changed, 211 insertions(+), 81 deletions(-)

diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp
index c95c7b8cde9..a306569ca5e 100644
--- a/indra/newview/llsurface.cpp
+++ b/indra/newview/llsurface.cpp
@@ -169,6 +169,7 @@ void LLSurface::create(const S32 grids_per_edge,
 	mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge;
 	mMetersPerGrid = width / ((F32)(mGridsPerEdge - 1));
 	mMetersPerEdge = mMetersPerGrid * (mGridsPerEdge - 1);
+	sTextureSize = width;
 
 	mOriginGlobal.setVec(origin_global);
 
@@ -293,7 +294,7 @@ void LLSurface::initTextures()
 		mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp);
 		gPipeline.createObject(mWaterObjp);
 		LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle());
-		water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT);		// region doesn't have a valid water height yet
+		water_pos_global += LLVector3d(mRegionp->getWidth()/2.0, mRegionp->getWidth()/2.0, DEFAULT_WATER_HEIGHT);
 		mWaterObjp->setPositionGlobal(water_pos_global);
 	}
 }
@@ -323,8 +324,8 @@ void LLSurface::setOriginGlobal(const LLVector3d &origin_global)
 	// Hack!
 	if (mWaterObjp.notNull() && mWaterObjp->mDrawable.notNull())
 	{
-		const F64 x = origin_global.mdV[VX] + 128.0;
-		const F64 y = origin_global.mdV[VY] + 128.0;
+		const F64 x = origin_global.mdV[VX] + (F64)mRegionp->getWidth() / 2.0;
+		const F64 y = origin_global.mdV[VY] + (F64)mRegionp->getWidth() / 2.0;
 		const F64 z = mWaterObjp->getPositionGlobal().mdV[VZ];
 
 		LLVector3d water_origin_global(x, y, z);
@@ -362,15 +363,48 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 {
 	S32 i;
 	LLSurfacePatch *patchp, *neighbor_patchp;
+	S32 neighborPatchesPerEdge = neighborp->mPatchesPerEdge;
 
 	mNeighbors[direction] = neighborp;
 	neighborp->mNeighbors[gDirOpposite[direction]] = this;
 
+	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);
+	}
 	// Connect patches
 	if (NORTHEAST == direction)
 	{
 		patchp = getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1);
-		neighbor_patchp = neighborp->getPatch(0, 0);
+		neighbor_patchp = neighborp->getPatch(neighbor_offset[0], neighbor_offset[1]);
 
 		patchp->connectNeighbor(neighbor_patchp, direction);
 		neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
@@ -380,8 +414,14 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 	}
 	else if (NORTHWEST == direction)
 	{
+		S32 off = mPatchesPerEdge + neighbor_offset[1] - own_offset[1];
 		patchp = getPatch(0, mPatchesPerEdge - 1);
-		neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, 0);
+		neighbor_patchp = neighborp->getPatch(neighbor_offset[0] - 1, off); //neighborPatchesPerEdge - 1
+		if (!neighbor_patchp)
+		{
+			mNeighbors[direction] = NULL;
+			return;
+		}
 
 		patchp->connectNeighbor(neighbor_patchp, direction);
 		neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
@@ -389,18 +429,29 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 	else if (SOUTHWEST == direction)
 	{
 		patchp = getPatch(0, 0);
-		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;
+		}
 
 		patchp->connectNeighbor(neighbor_patchp, direction);
 		neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 
-		neighbor_patchp->updateNorthEdge(); // Only update one of north or east.
+		neighbor_patchp->updateEastEdge(); // Only update one of north or east.
 		neighbor_patchp->dirtyZ();
 	}
 	else if (SOUTHEAST == direction)
 	{
+		S32 off = mPatchesPerEdge + neighbor_offset[0] - own_offset[0];
 		patchp = getPatch(mPatchesPerEdge - 1, 0);
-		neighbor_patchp = neighborp->getPatch(0, mPatchesPerEdge - 1);
+		neighbor_patchp = neighborp->getPatch(off, neighbor_offset[1] - 1); //0
+		if (!neighbor_patchp)
+		{
+			mNeighbors[direction] = NULL;
+			return;
+		}
 
 		patchp->connectNeighbor(neighbor_patchp, direction);
 		neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
@@ -408,10 +459,10 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 	else if (EAST == direction)
 	{
 		// Do east/west connections, first
-		for (i = 0; i < (S32)mPatchesPerEdge; i++)
+		for (i = 0; i < ppe[1]; i++)
 		{
-			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]);
 
 			patchp->connectNeighbor(neighbor_patchp, direction);
 			neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
@@ -421,19 +472,19 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 		}
 
 		// Now do northeast/southwest connections
-		for (i = 0; i < (S32)mPatchesPerEdge - 1; i++)
+		for (i = 0; i < ppe[1] - 1; i++)
 		{
-			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]);
 
 			patchp->connectNeighbor(neighbor_patchp, NORTHEAST);
 			neighbor_patchp->connectNeighbor(patchp, SOUTHWEST);
 		}
 		// Now do southeast/northwest connections
-		for (i = 1; i < (S32)mPatchesPerEdge; i++)
+		for (i = 1; i < ppe[1]; i++)
 		{
-			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]);
 
 			patchp->connectNeighbor(neighbor_patchp, SOUTHEAST);
 			neighbor_patchp->connectNeighbor(patchp, NORTHWEST);
@@ -442,10 +493,10 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 	else if (NORTH == direction)
 	{
 		// Do north/south connections, first
-		for (i = 0; i < (S32)mPatchesPerEdge; i++)
+		for (i = 0; i < ppe[0]; i++)
 		{
-			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);
 
 			patchp->connectNeighbor(neighbor_patchp, direction);
 			neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
@@ -455,19 +506,19 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 		}
 
 		// Do northeast/southwest connections
-		for (i = 0; i < (S32)mPatchesPerEdge - 1; i++)
+		for (i = 0; i < ppe[0] - 1; i++)
 		{
-			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);
 
 			patchp->connectNeighbor(neighbor_patchp, NORTHEAST);
 			neighbor_patchp->connectNeighbor(patchp, SOUTHWEST);
 		}
 		// Do southeast/northwest connections
-		for (i = 1; i < (S32)mPatchesPerEdge; i++)
+		for (i = 1; i < ppe[0]; i++)
 		{
-			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);
 
 			patchp->connectNeighbor(neighbor_patchp, NORTHWEST);
 			neighbor_patchp->connectNeighbor(patchp, SOUTHEAST);
@@ -476,10 +527,11 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 	else if (WEST == direction)
 	{
 		// Do east/west connections, first
-		for (i = 0; i < mPatchesPerEdge; i++)
+		for (i = 0; i < ppe[1]; i++)
 		{
-			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;
 
 			patchp->connectNeighbor(neighbor_patchp, direction);
 			neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
@@ -489,20 +541,22 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 		}
 
 		// Now do northeast/southwest connections
-		for (i = 1; i < mPatchesPerEdge; i++)
+		for (i = 1; i < ppe[1]; i++)
 		{
-			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;
 
 			patchp->connectNeighbor(neighbor_patchp, SOUTHWEST);
 			neighbor_patchp->connectNeighbor(patchp, NORTHEAST);
 		}
 
 		// Now do northwest/southeast connections
-		for (i = 0; i < mPatchesPerEdge - 1; i++)
+		for (i = 0; i < ppe[1] - 1; i++)
 		{
-			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;
 
 			patchp->connectNeighbor(neighbor_patchp, NORTHWEST);
 			neighbor_patchp->connectNeighbor(patchp, SOUTHEAST);
@@ -511,10 +565,11 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 	else if (SOUTH == direction)
 	{
 		// Do north/south connections, first
-		for (i = 0; i < mPatchesPerEdge; i++)
+		for (i = 0; i < ppe[0]; i++)
 		{
-			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;
 
 			patchp->connectNeighbor(neighbor_patchp, direction);
 			neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
@@ -524,19 +579,19 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 		}
 
 		// Now do northeast/southwest connections
-		for (i = 1; i < mPatchesPerEdge; i++)
+		for (i = 1; i < ppe[0]; i++)
 		{
-			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);
 
 			patchp->connectNeighbor(neighbor_patchp, SOUTHWEST);
 			neighbor_patchp->connectNeighbor(patchp, NORTHEAST);
 		}
 		// Now do northeast/southwest connections
-		for (i = 0; i < mPatchesPerEdge - 1; i++)
+		for (i = 0; i < ppe[0] - 1; i++)
 		{
-			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);
 
 			patchp->connectNeighbor(neighbor_patchp, SOUTHEAST);
 			neighbor_patchp->connectNeighbor(patchp, NORTHWEST);
@@ -657,7 +712,7 @@ 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();
 	}
@@ -698,14 +753,22 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL
 
 	while (1)
 	{
-		decode_patch_header(bitpack, &ph);
+		decode_patch_header(bitpack, &ph, b_large_patch);
 		if (ph.quant_wbits == END_OF_PATCHES)
 		{
 			break;
 		}
 
-		i = ph.patchids >> 5;
-		j = ph.patchids & 0x1F;
+		if (b_large_patch)
+		{
+			i = ph.patchids >> 16; //x
+			j = ph.patchids & 0xFFFF; //y
+		}
+		else
+		{
+			i = ph.patchids >> 5; //x
+			j = ph.patchids & 0x1F; //y
+		}
 
 		if ((i >= mPatchesPerEdge) || (j >= mPatchesPerEdge))
 		{
@@ -1149,12 +1212,12 @@ LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const
 {
 	if ((x < 0) || (x >= mPatchesPerEdge))
 	{
-		LL_ERRS() << "Asking for patch out of bounds" << LL_ENDL;
+		LL_WARNS() << "Asking for patch out of bounds" << LL_ENDL;
 		return NULL;
 	}
 	if ((y < 0) || (y >= mPatchesPerEdge))
 	{
-		LL_ERRS() << "Asking for patch out of bounds" << LL_ENDL;
+		LL_WARNS() << "Asking for patch out of bounds" << LL_ENDL;
 		return NULL;
 	}
 
@@ -1226,7 +1289,7 @@ BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y,
 	LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
 	U8 *rawp = raw->getData();
 
-	F32 scale = 256.f * getMetersPerGrid() / (F32)tex_width;
+	F32 scale = getRegion()->getWidth() * getMetersPerGrid() / (F32)tex_width;
 	F32 scale_inv = 1.f / scale;
 
 	S32 x_begin, y_begin, x_end, y_end;
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index e158db196bc..3e78656a7ad 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -28,6 +28,7 @@
 
 #include "llsurfacepatch.h"
 #include "llpatchvertexarray.h"
+#include "llregionhandle.h"
 #include "llviewerobjectlist.h"
 #include "llvosurfacepatch.h"
 #include "llsurface.h"
@@ -248,18 +249,22 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
 
 	const F32 mpg = mSurfacep->getMetersPerGrid() * stride;
 
-	S32 poffsets[2][2][2];
+	S32 poffsets[2][2][3];
 	poffsets[0][0][0] = x - stride;
 	poffsets[0][0][1] = y - stride;
+	poffsets[0][0][2] = surface_stride;
 
 	poffsets[0][1][0] = x - stride;
 	poffsets[0][1][1] = y + stride;
+	poffsets[0][1][2] = surface_stride;
 
 	poffsets[1][0][0] = x + stride;
 	poffsets[1][0][1] = y - stride;
+	poffsets[1][0][2] = surface_stride;
 
 	poffsets[1][1][0] = x + stride;
 	poffsets[1][1][1] = y + stride;
+	poffsets[1][1][2] = surface_stride;
 
 	const LLSurfacePatch *ppatches[2][2];
 
@@ -283,8 +288,9 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
 				}
 				else
 				{
-					poffsets[i][j][0] += patch_width;
 					ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST);
+					poffsets[i][j][0] += patch_width;
+					poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge();
 				}
 			}
 			if (poffsets[i][j][1] < 0)
@@ -295,8 +301,9 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
 				}
 				else
 				{
-					poffsets[i][j][1] += patch_width;
 					ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH);
+					poffsets[i][j][1] += patch_width;
+					poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge();
 				}
 			}
 			if (poffsets[i][j][0] >= (S32)patch_width)
@@ -307,8 +314,9 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
 				}
 				else
 				{
-					poffsets[i][j][0] -= patch_width;
 					ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST);
+					poffsets[i][j][0] -= patch_width;
+					poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge();
 				}
 			}
 			if (poffsets[i][j][1] >= (S32)patch_width)
@@ -319,8 +327,9 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
 				}
 				else
 				{
-					poffsets[i][j][1] -= patch_width;
 					ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH);
+					poffsets[i][j][1] -= patch_width;
+					poffsets[i][j][2] = ppatches[i][j]->getSurface()->getGridsPerEdge();
 				}
 			}
 		}
@@ -329,19 +338,19 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
 	LLVector3 p00(-mpg,-mpg,
 				  *(ppatches[0][0]->mDataZ
 				  + poffsets[0][0][0]
-				  + poffsets[0][0][1]*surface_stride));
+				  + poffsets[0][0][1]*poffsets[0][0][2]));
 	LLVector3 p01(-mpg,+mpg,
 				  *(ppatches[0][1]->mDataZ
 				  + poffsets[0][1][0]
-				  + poffsets[0][1][1]*surface_stride));
+				  + poffsets[0][1][1]*poffsets[0][1][2]));
 	LLVector3 p10(+mpg,-mpg,
 				  *(ppatches[1][0]->mDataZ
 				  + poffsets[1][0][0]
-				  + poffsets[1][0][1]*surface_stride));
+				  + poffsets[1][0][1]*poffsets[1][0][2]));
 	LLVector3 p11(+mpg,+mpg,
 				  *(ppatches[1][1]->mDataZ
 				  + poffsets[1][1][0]
-				  + poffsets[1][1][1]*surface_stride));
+				  + poffsets[1][1][1]*poffsets[1][1][2]));
 
 	LLVector3 c1 = p11 - p00;
 	LLVector3 c2 = p01 - p10;
@@ -492,6 +501,11 @@ void LLSurfacePatch::updateNormals()
 	// update the west edge
 	if (mNormalsInvalid[NORTHWEST] || mNormalsInvalid[WEST] || mNormalsInvalid[SOUTHWEST])
 	{
+		if (!getNeighborPatch(NORTH) && getNeighborPatch(NORTHWEST) && getNeighborPatch(NORTHWEST)->getHasReceivedData())
+		{
+			*(mDataZ + grids_per_patch_edge*grids_per_edge) = *(getNeighborPatch(NORTHWEST)->mDataZ + grids_per_patch_edge);
+		}
+
 		for (j = 0; j < grids_per_patch_edge; j++)
 		{
 			calcNormal(0, j, 2);
@@ -503,6 +517,11 @@ void LLSurfacePatch::updateNormals()
 	// update the south edge
 	if (mNormalsInvalid[SOUTHWEST] || mNormalsInvalid[SOUTH] || mNormalsInvalid[SOUTHEAST])
 	{
+		if (!getNeighborPatch(EAST) && getNeighborPatch(SOUTHEAST) && getNeighborPatch(SOUTHEAST)->getHasReceivedData())
+		{
+			*(mDataZ + grids_per_patch_edge) = *(getNeighborPatch(SOUTHEAST)->mDataZ + grids_per_patch_edge * getNeighborPatch(SOUTHEAST)->getSurface()->getGridsPerEdge());
+		}
+
 		for (i = 0; i < grids_per_patch_edge; i++)
 		{
 			calcNormal(i, 0, 2);
@@ -531,7 +550,8 @@ void LLSurfacePatch::updateNormals()
 					{
 						// East, but not north.  Pull from your east neighbor's northwest point.
 						*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
-							*(getNeighborPatch(EAST)->mDataZ + (grids_per_patch_edge - 1)*grids_per_edge);
+							*(getNeighborPatch(EAST)->mDataZ + (getNeighborPatch(EAST)->getSurface()->getGridsPerPatchEdge() - 1)
+							*getNeighborPatch(EAST)->getSurface()->getGridsPerEdge());
 					}
 					else
 					{
@@ -556,7 +576,7 @@ void LLSurfacePatch::updateNormals()
 					{
 						// North, but not east.  Pull from your north neighbor's southeast corner.
 						*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
-							*(getNeighborPatch(NORTH)->mDataZ + (grids_per_patch_edge - 1));
+							*(getNeighborPatch(NORTH)->mDataZ + (getNeighborPatch(NORTH)->getSurface()->getGridsPerPatchEdge() - 1));
 					}
 					else
 					{
@@ -573,8 +593,17 @@ void LLSurfacePatch::updateNormals()
 				&&
 				(!getNeighborPatch(EAST) || (getNeighborPatch(EAST)->mSurfacep != mSurfacep)))
 			{
+				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);
+				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);
+					*(getNeighborPatch(NORTHEAST)->mDataZ + (grids_per_edge + neighbor_offset - own_offset - 1) * getNeighborPatch(NORTHEAST)->getSurface()->getGridsPerEdge());
 			}
 		}
 		else
@@ -618,7 +647,9 @@ void LLSurfacePatch::updateEastEdge()
 	U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
 	U32 grids_per_edge = mSurfacep->getGridsPerEdge();
 
-	U32 j, k;
+	U32 grids_per_edge_east = grids_per_edge;
+
+	U32 j, k, h;
 	F32 *west_surface, *east_surface;
 
 	if (!getNeighborPatch(EAST))
@@ -630,6 +661,7 @@ void LLSurfacePatch::updateEastEdge()
 	{
 		west_surface = mDataZ + grids_per_patch_edge;
 		east_surface = getNeighborPatch(EAST)->mDataZ;
+		grids_per_edge_east = getNeighborPatch(EAST)->getSurface()->getGridsPerEdge();
 	}
 	else
 	{
@@ -641,7 +673,8 @@ void LLSurfacePatch::updateEastEdge()
 	for (j=0; j < grids_per_patch_edge; j++)
 	{
 		k = j * grids_per_edge;
-		*(west_surface + k) = *(east_surface + k);	// update buffer Z
+		h = j * grids_per_edge_east;
+		*(west_surface + k) = *(east_surface + h);	// update buffer Z
 	}
 }
 
@@ -816,6 +849,7 @@ void LLSurfacePatch::setOriginGlobal(const LLVector3d &origin_global)
 void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32 direction)
 {
 	llassert(neighbor_patchp);
+	if (!neighbor_patchp) return;
 	mNormalsInvalid[direction] = TRUE;
 	neighbor_patchp->mNormalsInvalid[gDirOpposite[direction]] = TRUE;
 
@@ -898,13 +932,15 @@ void LLSurfacePatch::updateVisibility()
 			if (mVObjp)
 			{
 				mVObjp->dirtyGeom();
-				if (getNeighborPatch(WEST))
+				LLSurfacePatch* neighbor = getNeighborPatch(WEST);
+				if (neighbor && neighbor->mVObjp.notNull())
 				{
-					getNeighborPatch(WEST)->mVObjp->dirtyGeom();
+					neighbor->mVObjp->dirtyGeom();
 				}
-				if (getNeighborPatch(SOUTH))
+				neighbor = getNeighborPatch(SOUTH);
+				if (neighbor && neighbor->mVObjp.notNull())
 				{
-					getNeighborPatch(SOUTH)->mVObjp->dirtyGeom();
+					neighbor->mVObjp->dirtyGeom();
 				}
 			}
 		}
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 65b8959b738..585adacc7db 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -462,9 +462,10 @@ LLParcelSelectionHandle LLViewerParcelMgr::selectParcelInRectangle()
 void LLViewerParcelMgr::selectCollisionParcel()
 {
 	// BUG: Claim to be in the agent's region
-	mWestSouth = gAgent.getRegion()->getOriginGlobal();
+	mWestSouth = getSelectionRegion()->getOriginGlobal();
 	mEastNorth = mWestSouth;
-	mEastNorth += LLVector3d(PARCEL_GRID_STEP_METERS, PARCEL_GRID_STEP_METERS, 0.0);
+	mEastNorth += LLVector3d((getSelectionRegion()->getWidth() / REGION_WIDTH_METERS) * PARCEL_GRID_STEP_METERS, 
+		                     (getSelectionRegion()->getWidth() / REGION_WIDTH_METERS) * PARCEL_GRID_STEP_METERS, 0.0);
 
 	// BUG: must be in the sim you are in
 	LLMessageSystem *msg = gMessageSystem;
@@ -1582,6 +1583,10 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
     if(msg_region)
         parcel_mgr.mParcelsPerEdge = S32(msg_region->getWidth() / PARCEL_GRID_STEP_METERS);
     else
+		if (!gAgent.getRegion())
+		{
+			return;
+		}
         parcel_mgr.mParcelsPerEdge = S32(gAgent.getRegion()->getWidth() / PARCEL_GRID_STEP_METERS);
 
     msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_RequestResult, request_result);
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 0730bacca4b..19eb6b3ae7b 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -380,7 +380,7 @@ void update_statistics()
 	}
 	add(LLStatViewer::FPS, 1);
 
-	F64Bits layer_bits = gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits();
+	F64Bits layer_bits = gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits() + gVLManager.getWaterBits();
 	add(LLStatViewer::LAYERS_NETWORK_DATA_RECEIVED, layer_bits);
 	add(LLStatViewer::OBJECT_NETWORK_DATA_RECEIVED, gObjectData);
 	add(LLStatViewer::ASSET_UDP_DATA_RECEIVED, F64Bits(gTransferManager.getTransferBitsIn(LLTCT_ASSET)));
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index 8b8964560a0..5e055aaa021 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -156,7 +156,7 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
 	const F32 xyScaleInv = (1.f / xyScale);
 	const F32 zScaleInv = (1.f / zScale);
 
-	const F32 inv_width = 1.f/mWidth;
+	const F32 inv_width = 1.f/(F32)mWidth;
 
 	// OK, for now, just have the composition value equal the height at the point.
 	for (S32 j = y_begin; j < y_end; j++)
diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp
index 895ceed8804..c31c048c0cf 100644
--- a/indra/newview/llvlmanager.cpp
+++ b/indra/newview/llvlmanager.cpp
@@ -37,9 +37,15 @@
 #include "llbitpack.h"
 
 const	char	LAND_LAYER_CODE					= 'L';
+const	char	WATER_LAYER_CODE				= 'W';
 const	char	WIND_LAYER_CODE					= '7';
 const	char	CLOUD_LAYER_CODE				= '8';
 
+const	char	AURORA_LAND_LAYER_CODE			= 'M';
+const	char	AURORA_WATER_LAYER_CODE			= 'X';
+const	char	AURORA_WIND_LAYER_CODE			= '9';
+const	char	AURORA_CLOUD_LAYER_CODE			= ':';
+
 LLVLManager gVLManager;
 
 LLVLManager::~LLVLManager()
@@ -54,15 +60,19 @@ LLVLManager::~LLVLManager()
 
 void LLVLManager::addLayerData(LLVLData *vl_datap, const S32Bytes mesg_size)
 {
-	if (LAND_LAYER_CODE == vl_datap->mType)
+	if (LAND_LAYER_CODE == vl_datap->mType || AURORA_LAND_LAYER_CODE == vl_datap->mType)
 	{
 		mLandBits += mesg_size;
 	}
-	else if (WIND_LAYER_CODE == vl_datap->mType)
+	else if (WATER_LAYER_CODE == vl_datap->mType || AURORA_WATER_LAYER_CODE == vl_datap->mType)
+	{
+		mWaterBits += mesg_size;
+	}
+	else if (WIND_LAYER_CODE == vl_datap->mType || AURORA_WIND_LAYER_CODE == vl_datap->mType)
 	{
 		mWindBits += mesg_size;
 	}
-	else if (CLOUD_LAYER_CODE == vl_datap->mType)
+	else if (CLOUD_LAYER_CODE == vl_datap->mType || AURORA_CLOUD_LAYER_CODE == vl_datap->mType)
 	{
 		mCloudBits += mesg_size;
 	}
@@ -91,12 +101,21 @@ void LLVLManager::unpackData(const S32 num_packets)
 		{
 			datap->mRegionp->getLand().decompressDCTPatch(bit_pack, &goph, FALSE);
 		}
-		else if (WIND_LAYER_CODE == datap->mType)
+		else if (AURORA_LAND_LAYER_CODE == datap->mType)
+		{
+			datap->mRegionp->getLand().decompressDCTPatch(bit_pack, &goph, TRUE);
+		}
+		else if (WIND_LAYER_CODE == datap->mType || AURORA_WIND_LAYER_CODE == datap->mType)
+
 		{
 			datap->mRegionp->mWind.decompress(bit_pack, &goph);
 
 		}
-		else if (CLOUD_LAYER_CODE == datap->mType)
+		else if (CLOUD_LAYER_CODE == datap->mType || AURORA_CLOUD_LAYER_CODE == datap->mType)
+		{
+
+		}
+		else if (WATER_LAYER_CODE == datap->mType || AURORA_WATER_LAYER_CODE == datap->mType)
 		{
 
 		}
@@ -112,7 +131,7 @@ void LLVLManager::unpackData(const S32 num_packets)
 
 void LLVLManager::resetBitCounts()
 {
-	mLandBits = mWindBits = mCloudBits = (S32Bits)0;
+	mLandBits = mWindBits = mCloudBits = mWaterBits = (S32Bits)0;
 }
 
 U32Bits LLVLManager::getLandBits() const
@@ -130,9 +149,14 @@ U32Bits LLVLManager::getCloudBits() const
 	return mCloudBits;
 }
 
+U32Bits LLVLManager::getWaterBits() const
+{
+	return mWaterBits;
+}
+
 S32Bytes LLVLManager::getTotalBytes() const
 {
-	return mLandBits + mWindBits + mCloudBits;
+	return mLandBits + mWindBits + mCloudBits + mWaterBits;
 }
 
 void LLVLManager::cleanupData(LLViewerRegion *regionp)
diff --git a/indra/newview/llvlmanager.h b/indra/newview/llvlmanager.h
index 5e7fadc5222..338befc1c97 100644
--- a/indra/newview/llvlmanager.h
+++ b/indra/newview/llvlmanager.h
@@ -48,6 +48,7 @@ class LLVLManager
 	U32Bits getLandBits() const;
 	U32Bits getWindBits() const;
 	U32Bits getCloudBits() const;
+	U32Bits getWaterBits() const;
 
 	void resetBitCounts();
 
@@ -58,6 +59,7 @@ class LLVLManager
 	U32Bits mLandBits;
 	U32Bits mWindBits;
 	U32Bits mCloudBits;
+	U32Bits mWaterBits;
 };
 
 class LLVLData
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 9bd588e9d46..509e532cb40 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -58,7 +58,7 @@ LLVOWater::LLVOWater(const LLUUID &id,
 {
 	// Terrain must draw during selection passes so it can block objects behind it.
 	mbCanSelect = FALSE;
-	setScale(LLVector3(256.f, 256.f, 0.f)); // Hack for setting scale for bounding boxes/visibility.
+	setScale(LLVector3(mRegionp->getWidth(), mRegionp->getWidth(), 0.f)); // Hack for setting scale for bounding boxes/visibility.
 
 	mUseTexture = TRUE;
 	mIsEdgePatch = FALSE;
-- 
GitLab