PageRenderTime 1611ms CodeModel.GetById 161ms app.highlight 753ms RepoModel.GetById 687ms app.codeStats 1ms

/indra/newview/llsurfacepatch.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1028 lines | 815 code | 136 blank | 77 comment | 131 complexity | 0d1e6b95d83b59dda20b9e9410dbbd78 MD5 | raw file
   1/** 
   2 * @file llsurfacepatch.cpp
   3 * @brief LLSurfacePatch class implementation
   4 *
   5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29#include "llsurfacepatch.h"
  30#include "llpatchvertexarray.h"
  31#include "llviewerobjectlist.h"
  32#include "llvosurfacepatch.h"
  33#include "llsurface.h"
  34#include "pipeline.h"
  35#include "llagent.h"
  36#include "timing.h"
  37#include "llsky.h"
  38#include "llviewercamera.h"
  39
  40// For getting composition values
  41#include "llviewerregion.h"
  42#include "llvlcomposition.h"
  43#include "lldrawpool.h"
  44#include "noise.h"
  45
  46extern U64 gFrameTime;
  47extern LLPipeline gPipeline;
  48
  49LLSurfacePatch::LLSurfacePatch() :
  50	mHasReceivedData(FALSE),
  51	mSTexUpdate(FALSE),
  52	mDirty(FALSE),
  53	mDirtyZStats(TRUE),
  54	mHeightsGenerated(FALSE),
  55	mDataOffset(0),
  56	mDataZ(NULL),
  57	mDataNorm(NULL),
  58	mVObjp(NULL),
  59	mOriginRegion(0.f, 0.f, 0.f),
  60	mCenterRegion(0.f, 0.f, 0.f),
  61	mMinZ(0.f),
  62	mMaxZ(0.f),
  63	mMeanZ(0.f),
  64	mRadius(0.f),
  65	mMinComposition(0.f),
  66	mMaxComposition(0.f),
  67	mMeanComposition(0.f),
  68	// This flag is used to communicate between adjacent surfaces and is
  69	// set to non-zero values by higher classes.  
  70	mConnectedEdge(NO_EDGE),
  71	mLastUpdateTime(0),
  72	mSurfacep(NULL)
  73{	
  74	S32 i;
  75	for (i = 0; i < 8; i++)
  76	{
  77		setNeighborPatch(i, NULL);
  78	}
  79	for (i = 0; i < 9; i++)
  80	{
  81		mNormalsInvalid[i] = TRUE;
  82	}
  83}
  84
  85
  86LLSurfacePatch::~LLSurfacePatch()
  87{
  88	mVObjp = NULL;
  89}
  90
  91
  92void LLSurfacePatch::dirty()
  93{
  94	// These are outside of the loop in case we're still waiting for a dirty from the
  95	// texture being updated...
  96	if (mVObjp)
  97	{
  98		mVObjp->dirtyGeom();
  99	}
 100	else
 101	{
 102		llwarns << "No viewer object for this surface patch!" << llendl;
 103	}
 104
 105	mDirtyZStats = TRUE;
 106	mHeightsGenerated = FALSE;
 107	
 108	if (!mDirty)
 109	{
 110		mDirty = TRUE;
 111		mSurfacep->dirtySurfacePatch(this);
 112	}
 113}
 114
 115
 116void LLSurfacePatch::setSurface(LLSurface *surfacep)
 117{
 118	mSurfacep = surfacep;
 119	if (mVObjp == (LLVOSurfacePatch *)NULL)
 120	{
 121		llassert(mSurfacep->mType == 'l');
 122
 123		mVObjp = (LLVOSurfacePatch *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SURFACE_PATCH, mSurfacep->getRegion());
 124		mVObjp->setPatch(this);
 125		mVObjp->setPositionRegion(mCenterRegion);
 126		gPipeline.createObject(mVObjp);
 127	}
 128} 
 129
 130void LLSurfacePatch::disconnectNeighbor(LLSurface *surfacep)
 131{
 132	U32 i;
 133	for (i = 0; i < 8; i++)
 134	{
 135		if (getNeighborPatch(i))
 136		{
 137			if (getNeighborPatch(i)->mSurfacep == surfacep)
 138			{
 139				setNeighborPatch(i, NULL);
 140				mNormalsInvalid[i] = TRUE;
 141			}
 142		}
 143	}
 144
 145	// Clean up connected edges
 146	if (getNeighborPatch(EAST))
 147	{
 148		if (getNeighborPatch(EAST)->mSurfacep == surfacep)
 149		{
 150			mConnectedEdge &= ~EAST_EDGE;
 151		}
 152	}
 153	if (getNeighborPatch(NORTH))
 154	{
 155		if (getNeighborPatch(NORTH)->mSurfacep == surfacep)
 156		{
 157			mConnectedEdge &= ~NORTH_EDGE;
 158		}
 159	}
 160	if (getNeighborPatch(WEST))
 161	{
 162		if (getNeighborPatch(WEST)->mSurfacep == surfacep)
 163		{
 164			mConnectedEdge &= ~WEST_EDGE;
 165		}
 166	}
 167	if (getNeighborPatch(SOUTH))
 168	{
 169		if (getNeighborPatch(SOUTH)->mSurfacep == surfacep)
 170		{
 171			mConnectedEdge &= ~SOUTH_EDGE;
 172		}
 173	}
 174}
 175
 176LLVector3 LLSurfacePatch::getPointAgent(const U32 x, const U32 y) const
 177{
 178	U32 surface_stride = mSurfacep->getGridsPerEdge();
 179	U32 point_offset = x + y*surface_stride;
 180	LLVector3 pos;
 181	pos = getOriginAgent();
 182	pos.mV[VX] += x	* mSurfacep->getMetersPerGrid();
 183	pos.mV[VY] += y * mSurfacep->getMetersPerGrid();
 184	pos.mV[VZ] = *(mDataZ + point_offset);
 185	return pos;
 186}
 187
 188LLVector2 LLSurfacePatch::getTexCoords(const U32 x, const U32 y) const
 189{
 190	U32 surface_stride = mSurfacep->getGridsPerEdge();
 191	U32 point_offset = x + y*surface_stride;
 192	LLVector3 pos, rel_pos;
 193	pos = getOriginAgent();
 194	pos.mV[VX] += x	* mSurfacep->getMetersPerGrid();
 195	pos.mV[VY] += y * mSurfacep->getMetersPerGrid();
 196	pos.mV[VZ] = *(mDataZ + point_offset);
 197	rel_pos = pos - mSurfacep->getOriginAgent();
 198	rel_pos *= 1.f/surface_stride;
 199	return LLVector2(rel_pos.mV[VX], rel_pos.mV[VY]);
 200}
 201
 202
 203void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex, LLVector3 *normal,
 204						  LLVector2 *tex0, LLVector2 *tex1)
 205{
 206	if (!mSurfacep || !mSurfacep->getRegion() || !mSurfacep->getGridsPerEdge())
 207	{
 208		return; // failsafe
 209	}
 210	llassert_always(vertex && normal && tex0 && tex1);
 211	
 212	U32 surface_stride = mSurfacep->getGridsPerEdge();
 213	U32 point_offset = x + y*surface_stride;
 214
 215	*normal = getNormal(x, y);
 216
 217	LLVector3 pos_agent = getOriginAgent();
 218	pos_agent.mV[VX] += x * mSurfacep->getMetersPerGrid();
 219	pos_agent.mV[VY] += y * mSurfacep->getMetersPerGrid();
 220	pos_agent.mV[VZ]  = *(mDataZ + point_offset);
 221	*vertex     = pos_agent;
 222
 223	LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent();
 224	LLVector3 tex_pos = rel_pos * (1.f/surface_stride);
 225	tex0->mV[0]  = tex_pos.mV[0];
 226	tex0->mV[1]  = tex_pos.mV[1];
 227	tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y);
 228
 229	const F32 xyScale = 4.9215f*7.f; //0.93284f;
 230	const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f);
 231
 232	F32 vec[3] = {
 233					fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f),
 234					fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f),
 235					0.f
 236				};
 237	F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f);
 238	tex1->mV[1] = rand_val;
 239
 240
 241}
 242
 243
 244void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride)
 245{
 246	U32 patch_width = mSurfacep->mPVArray.mPatchWidth;
 247	U32 surface_stride = mSurfacep->getGridsPerEdge();
 248
 249	const F32 mpg = mSurfacep->getMetersPerGrid() * stride;
 250
 251	S32 poffsets[2][2][2];
 252	poffsets[0][0][0] = x - stride;
 253	poffsets[0][0][1] = y - stride;
 254
 255	poffsets[0][1][0] = x - stride;
 256	poffsets[0][1][1] = y + stride;
 257
 258	poffsets[1][0][0] = x + stride;
 259	poffsets[1][0][1] = y - stride;
 260
 261	poffsets[1][1][0] = x + stride;
 262	poffsets[1][1][1] = y + stride;
 263
 264	const LLSurfacePatch *ppatches[2][2];
 265
 266	// LLVector3 p1, p2, p3, p4;
 267
 268	ppatches[0][0] = this;
 269	ppatches[0][1] = this;
 270	ppatches[1][0] = this;
 271	ppatches[1][1] = this;
 272
 273	U32 i, j;
 274	for (i = 0; i < 2; i++)
 275	{
 276		for (j = 0; j < 2; j++)
 277		{
 278			if (poffsets[i][j][0] < 0)
 279			{
 280				if (!ppatches[i][j]->getNeighborPatch(WEST))
 281				{
 282					poffsets[i][j][0] = 0;
 283				}
 284				else
 285				{
 286					poffsets[i][j][0] += patch_width;
 287					ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST);
 288				}
 289			}
 290			if (poffsets[i][j][1] < 0)
 291			{
 292				if (!ppatches[i][j]->getNeighborPatch(SOUTH))
 293				{
 294					poffsets[i][j][1] = 0;
 295				}
 296				else
 297				{
 298					poffsets[i][j][1] += patch_width;
 299					ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH);
 300				}
 301			}
 302			if (poffsets[i][j][0] >= (S32)patch_width)
 303			{
 304				if (!ppatches[i][j]->getNeighborPatch(EAST))
 305				{
 306					poffsets[i][j][0] = patch_width - 1;
 307				}
 308				else
 309				{
 310					poffsets[i][j][0] -= patch_width;
 311					ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST);
 312				}
 313			}
 314			if (poffsets[i][j][1] >= (S32)patch_width)
 315			{
 316				if (!ppatches[i][j]->getNeighborPatch(NORTH))
 317				{
 318					poffsets[i][j][1] = patch_width - 1;
 319				}
 320				else
 321				{
 322					poffsets[i][j][1] -= patch_width;
 323					ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH);
 324				}
 325			}
 326		}
 327	}
 328
 329	LLVector3 p00(-mpg,-mpg,
 330				  *(ppatches[0][0]->mDataZ
 331				  + poffsets[0][0][0]
 332				  + poffsets[0][0][1]*surface_stride));
 333	LLVector3 p01(-mpg,+mpg,
 334				  *(ppatches[0][1]->mDataZ
 335				  + poffsets[0][1][0]
 336				  + poffsets[0][1][1]*surface_stride));
 337	LLVector3 p10(+mpg,-mpg,
 338				  *(ppatches[1][0]->mDataZ
 339				  + poffsets[1][0][0]
 340				  + poffsets[1][0][1]*surface_stride));
 341	LLVector3 p11(+mpg,+mpg,
 342				  *(ppatches[1][1]->mDataZ
 343				  + poffsets[1][1][0]
 344				  + poffsets[1][1][1]*surface_stride));
 345
 346	LLVector3 c1 = p11 - p00;
 347	LLVector3 c2 = p01 - p10;
 348
 349	LLVector3 normal = c1;
 350	normal %= c2;
 351	normal.normVec();
 352
 353	llassert(mDataNorm);
 354	*(mDataNorm + surface_stride * y + x) = normal;
 355}
 356
 357const LLVector3 &LLSurfacePatch::getNormal(const U32 x, const U32 y) const
 358{
 359	U32 surface_stride = mSurfacep->getGridsPerEdge();
 360	llassert(mDataNorm);
 361	return *(mDataNorm + surface_stride * y + x);
 362}
 363
 364
 365void LLSurfacePatch::updateCameraDistanceRegion(const LLVector3 &pos_region)
 366{
 367	if (LLPipeline::sDynamicLOD)
 368	{
 369		LLVector3 dv = pos_region;
 370		dv -= mCenterRegion;
 371		mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/
 372			llmax(LLVOSurfacePatch::sLODFactor, 0.1f);
 373	}
 374	else
 375	{
 376		mVisInfo.mDistance = 0.f;
 377	}
 378}
 379
 380F32 LLSurfacePatch::getDistance() const
 381{
 382	return mVisInfo.mDistance;
 383}
 384
 385
 386// Called when a patch has changed its height field
 387// data.
 388void LLSurfacePatch::updateVerticalStats() 
 389{
 390	if (!mDirtyZStats)
 391	{
 392		return;
 393	}
 394
 395	U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
 396	U32 grids_per_edge = mSurfacep->getGridsPerEdge();
 397	F32 meters_per_grid = mSurfacep->getMetersPerGrid();
 398
 399	U32 i, j, k;
 400	F32 z, total;
 401
 402	llassert(mDataZ);
 403	z = *(mDataZ);
 404
 405	mMinZ = z;
 406	mMaxZ = z;
 407
 408	k = 0;
 409	total = 0.0f;
 410
 411	// Iterate to +1 because we need to do the edges correctly.
 412	for (j=0; j<(grids_per_patch_edge+1); j++) 
 413	{
 414		for (i=0; i<(grids_per_patch_edge+1); i++) 
 415		{
 416			z = *(mDataZ + i + j*grids_per_edge);
 417
 418			if (z < mMinZ)
 419			{
 420				mMinZ = z;
 421			}
 422			if (z > mMaxZ)
 423			{
 424				mMaxZ = z;
 425			}
 426			total += z;
 427			k++;
 428		}
 429	}
 430	mMeanZ = total / (F32) k;
 431	mCenterRegion.mV[VZ] = 0.5f * (mMinZ + mMaxZ);
 432
 433	LLVector3 diam_vec(meters_per_grid*grids_per_patch_edge,
 434						meters_per_grid*grids_per_patch_edge,
 435						mMaxZ - mMinZ);
 436	mRadius = diam_vec.magVec() * 0.5f;
 437
 438	mSurfacep->mMaxZ = llmax(mMaxZ, mSurfacep->mMaxZ);
 439	mSurfacep->mMinZ = llmin(mMinZ, mSurfacep->mMinZ);
 440	mSurfacep->mHasZData = TRUE;
 441	mSurfacep->getRegion()->calculateCenterGlobal();
 442
 443	if (mVObjp)
 444	{
 445		mVObjp->dirtyPatch();
 446	}
 447	mDirtyZStats = FALSE;
 448}
 449
 450
 451void LLSurfacePatch::updateNormals() 
 452{
 453	if (mSurfacep->mType == 'w')
 454	{
 455		return;
 456	}
 457	U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
 458	U32 grids_per_edge = mSurfacep->getGridsPerEdge();
 459
 460	BOOL dirty_patch = FALSE;
 461
 462	U32 i, j;
 463	// update the east edge
 464	if (mNormalsInvalid[EAST] || mNormalsInvalid[NORTHEAST] || mNormalsInvalid[SOUTHEAST])
 465	{
 466		for (j = 0; j <= grids_per_patch_edge; j++)
 467		{
 468			calcNormal(grids_per_patch_edge, j, 2);
 469			calcNormal(grids_per_patch_edge - 1, j, 2);
 470			calcNormal(grids_per_patch_edge - 2, j, 2);
 471		}
 472
 473		dirty_patch = TRUE;
 474	}
 475
 476	// update the north edge
 477	if (mNormalsInvalid[NORTHEAST] || mNormalsInvalid[NORTH] || mNormalsInvalid[NORTHWEST])
 478	{
 479		for (i = 0; i <= grids_per_patch_edge; i++)
 480		{
 481			calcNormal(i, grids_per_patch_edge, 2);
 482			calcNormal(i, grids_per_patch_edge - 1, 2);
 483			calcNormal(i, grids_per_patch_edge - 2, 2);
 484		}
 485
 486		dirty_patch = TRUE;
 487	}
 488
 489	// update the west edge
 490	if (mNormalsInvalid[NORTHWEST] || mNormalsInvalid[WEST] || mNormalsInvalid[SOUTHWEST])
 491	{
 492		for (j = 0; j < grids_per_patch_edge; j++)
 493		{
 494			calcNormal(0, j, 2);
 495			calcNormal(1, j, 2);
 496		}
 497		dirty_patch = TRUE;
 498	}
 499
 500	// update the south edge
 501	if (mNormalsInvalid[SOUTHWEST] || mNormalsInvalid[SOUTH] || mNormalsInvalid[SOUTHEAST])
 502	{
 503		for (i = 0; i < grids_per_patch_edge; i++)
 504		{
 505			calcNormal(i, 0, 2);
 506			calcNormal(i, 1, 2);
 507		}
 508		dirty_patch = TRUE;
 509	}
 510
 511	// Invalidating the northeast corner is different, because depending on what the adjacent neighbors are,
 512	// we'll want to do different things.
 513	if (mNormalsInvalid[NORTHEAST])
 514	{
 515		if (!getNeighborPatch(NORTHEAST))
 516		{
 517			if (!getNeighborPatch(NORTH))
 518			{
 519				if (!getNeighborPatch(EAST))
 520				{
 521					// No north or east neighbors.  Pull from the diagonal in your own patch.
 522					*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
 523						*(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
 524				}
 525				else
 526				{
 527					if (getNeighborPatch(EAST)->getHasReceivedData())
 528					{
 529						// East, but not north.  Pull from your east neighbor's northwest point.
 530						*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
 531							*(getNeighborPatch(EAST)->mDataZ + (grids_per_patch_edge - 1)*grids_per_edge);
 532					}
 533					else
 534					{
 535						*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
 536							*(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
 537					}
 538				}
 539			}
 540			else
 541			{
 542				// We have a north.
 543				if (getNeighborPatch(EAST))
 544				{
 545					// North and east neighbors, but not northeast.
 546					// Pull from diagonal in your own patch.
 547					*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
 548						*(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
 549				}
 550				else
 551				{
 552					if (getNeighborPatch(NORTH)->getHasReceivedData())
 553					{
 554						// North, but not east.  Pull from your north neighbor's southeast corner.
 555						*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
 556							*(getNeighborPatch(NORTH)->mDataZ + (grids_per_patch_edge - 1));
 557					}
 558					else
 559					{
 560						*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
 561							*(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge);
 562					}
 563				}
 564			}
 565		}
 566		else if (getNeighborPatch(NORTHEAST)->mSurfacep != mSurfacep)
 567		{
 568			if (
 569				(!getNeighborPatch(NORTH) || (getNeighborPatch(NORTH)->mSurfacep != mSurfacep))
 570				&&
 571				(!getNeighborPatch(EAST) || (getNeighborPatch(EAST)->mSurfacep != mSurfacep)))
 572			{
 573				*(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) =
 574										*(getNeighborPatch(NORTHEAST)->mDataZ);
 575			}
 576		}
 577		else
 578		{
 579			// We've got a northeast patch in the same surface.
 580			// The z and normals will be handled by that patch.
 581		}
 582		calcNormal(grids_per_patch_edge, grids_per_patch_edge, 2);
 583		calcNormal(grids_per_patch_edge, grids_per_patch_edge - 1, 2);
 584		calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge, 2);
 585		calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2);
 586		dirty_patch = TRUE;
 587	}
 588
 589	// update the middle normals
 590	if (mNormalsInvalid[MIDDLE])
 591	{
 592		for (j=2; j < grids_per_patch_edge - 2; j++)
 593		{
 594			for (i=2; i < grids_per_patch_edge - 2; i++)
 595			{
 596				calcNormal(i, j, 2);
 597			}
 598		}
 599		dirty_patch = TRUE;
 600	}
 601
 602	if (dirty_patch)
 603	{
 604		mSurfacep->dirtySurfacePatch(this);
 605	}
 606
 607	for (i = 0; i < 9; i++)
 608	{
 609		mNormalsInvalid[i] = FALSE;
 610	}
 611}
 612
 613void LLSurfacePatch::updateEastEdge()
 614{
 615	U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
 616	U32 grids_per_edge = mSurfacep->getGridsPerEdge();
 617
 618	U32 j, k;
 619	F32 *west_surface, *east_surface;
 620
 621	if (!getNeighborPatch(EAST))
 622	{
 623		west_surface = mDataZ + grids_per_patch_edge;
 624		east_surface = mDataZ + grids_per_patch_edge - 1;
 625	}
 626	else if (mConnectedEdge & EAST_EDGE)
 627	{
 628		west_surface = mDataZ + grids_per_patch_edge;
 629		east_surface = getNeighborPatch(EAST)->mDataZ;
 630	}
 631	else
 632	{
 633		return;
 634	}
 635
 636	// If patchp is on the east edge of its surface, then we update the east
 637	// side buffer
 638	for (j=0; j < grids_per_patch_edge; j++)
 639	{
 640		k = j * grids_per_edge;
 641		*(west_surface + k) = *(east_surface + k);	// update buffer Z
 642	}
 643}
 644
 645
 646void LLSurfacePatch::updateNorthEdge()
 647{
 648	U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
 649	U32 grids_per_edge = mSurfacep->getGridsPerEdge();
 650
 651	U32 i;
 652	F32 *south_surface, *north_surface;
 653
 654	if (!getNeighborPatch(NORTH))
 655	{
 656		south_surface = mDataZ + grids_per_patch_edge*grids_per_edge;
 657		north_surface = mDataZ + (grids_per_patch_edge - 1) * grids_per_edge;
 658	}
 659	else if (mConnectedEdge & NORTH_EDGE)
 660	{
 661		south_surface = mDataZ + grids_per_patch_edge*grids_per_edge;
 662		north_surface = getNeighborPatch(NORTH)->mDataZ;
 663	}
 664	else
 665	{
 666		return;
 667	}
 668
 669	// Update patchp's north edge ...
 670	for (i=0; i<grids_per_patch_edge; i++)
 671	{
 672		*(south_surface + i) = *(north_surface + i);	// update buffer Z
 673	}
 674}
 675
 676
 677BOOL LLSurfacePatch::updateTexture()
 678{
 679	if (mSTexUpdate)		//  Update texture as needed
 680	{
 681		F32 meters_per_grid = getSurface()->getMetersPerGrid();
 682		F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge();
 683
 684		if ((!getNeighborPatch(EAST) || getNeighborPatch(EAST)->getHasReceivedData())
 685			&& (!getNeighborPatch(WEST) || getNeighborPatch(WEST)->getHasReceivedData())
 686			&& (!getNeighborPatch(SOUTH) || getNeighborPatch(SOUTH)->getHasReceivedData())
 687			&& (!getNeighborPatch(NORTH) || getNeighborPatch(NORTH)->getHasReceivedData()))
 688		{
 689			LLViewerRegion *regionp = getSurface()->getRegion();
 690			LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal();
 691
 692			// Have to figure out a better way to deal with these edge conditions...
 693			LLVLComposition* comp = regionp->getComposition();
 694			if (!mHeightsGenerated)
 695			{
 696				F32 patch_size = meters_per_grid*(grids_per_patch_edge+1);
 697				if (comp->generateHeights((F32)origin_region[VX], (F32)origin_region[VY],
 698										  patch_size, patch_size))
 699				{
 700					mHeightsGenerated = TRUE;
 701				}
 702				else
 703				{
 704					return FALSE;
 705				}
 706			}
 707			
 708			if (comp->generateComposition())
 709			{
 710				if (mVObjp)
 711				{
 712					mVObjp->dirtyGeom();
 713					gPipeline.markGLRebuild(mVObjp);
 714					return TRUE;
 715				}
 716			}
 717		}
 718		return FALSE;
 719	}
 720	else
 721	{
 722		return TRUE;
 723	}
 724}
 725
 726void LLSurfacePatch::updateGL()
 727{
 728	F32 meters_per_grid = getSurface()->getMetersPerGrid();
 729	F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge();
 730
 731	LLViewerRegion *regionp = getSurface()->getRegion();
 732	LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal();
 733
 734	LLVLComposition* comp = regionp->getComposition();
 735	
 736	updateCompositionStats();
 737	F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
 738	if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY],
 739							  tex_patch_size, tex_patch_size))
 740	{
 741		mSTexUpdate = FALSE;
 742
 743		// Also generate the water texture
 744		mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
 745										tex_patch_size, tex_patch_size);
 746	}
 747}
 748
 749void LLSurfacePatch::dirtyZ()
 750{
 751	mSTexUpdate = TRUE;
 752
 753	// Invalidate all normals in this patch
 754	U32 i;
 755	for (i = 0; i < 9; i++)
 756	{
 757		mNormalsInvalid[i] = TRUE;
 758	}
 759
 760	// Invalidate normals in this and neighboring patches
 761	for (i = 0; i < 8; i++)
 762	{
 763		if (getNeighborPatch(i))
 764		{
 765			getNeighborPatch(i)->mNormalsInvalid[gDirOpposite[i]] = TRUE;
 766			getNeighborPatch(i)->dirty();
 767			if (i < 4)
 768			{
 769				getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE;
 770				getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE;
 771			}
 772		}
 773	}
 774
 775	dirty();
 776	mLastUpdateTime = gFrameTime;
 777}
 778
 779
 780const U64 &LLSurfacePatch::getLastUpdateTime() const
 781{
 782	return mLastUpdateTime;
 783}
 784
 785F32 LLSurfacePatch::getMaxZ() const
 786{
 787	return mMaxZ;
 788}
 789
 790F32 LLSurfacePatch::getMinZ() const
 791{
 792	return mMinZ;
 793}
 794
 795void LLSurfacePatch::setOriginGlobal(const LLVector3d &origin_global)
 796{
 797	mOriginGlobal = origin_global;
 798
 799	LLVector3 origin_region;
 800	origin_region.setVec(mOriginGlobal - mSurfacep->getOriginGlobal());
 801
 802	mOriginRegion = origin_region;
 803	mCenterRegion.mV[VX] = origin_region.mV[VX] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid();
 804	mCenterRegion.mV[VY] = origin_region.mV[VY] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid();
 805
 806	mVisInfo.mbIsVisible = FALSE;
 807	mVisInfo.mDistance = 512.0f;
 808	mVisInfo.mRenderLevel = 0;
 809	mVisInfo.mRenderStride = mSurfacep->getGridsPerPatchEdge();
 810	
 811}
 812
 813void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32 direction)
 814{
 815	llassert(neighbor_patchp);
 816	mNormalsInvalid[direction] = TRUE;
 817	neighbor_patchp->mNormalsInvalid[gDirOpposite[direction]] = TRUE;
 818
 819	setNeighborPatch(direction, neighbor_patchp);
 820	neighbor_patchp->setNeighborPatch(gDirOpposite[direction], this);
 821
 822	if (EAST == direction)
 823	{
 824		mConnectedEdge |= EAST_EDGE;
 825		neighbor_patchp->mConnectedEdge |= WEST_EDGE;
 826	}
 827	else if (NORTH == direction)
 828	{
 829		mConnectedEdge |= NORTH_EDGE;
 830		neighbor_patchp->mConnectedEdge |= SOUTH_EDGE;
 831	}
 832	else if (WEST == direction)
 833	{
 834		mConnectedEdge |= WEST_EDGE;
 835		neighbor_patchp->mConnectedEdge |= EAST_EDGE;
 836	}
 837	else if (SOUTH == direction)
 838	{
 839		mConnectedEdge |= SOUTH_EDGE;
 840		neighbor_patchp->mConnectedEdge |= NORTH_EDGE;
 841	}
 842}
 843
 844void LLSurfacePatch::updateVisibility()
 845{
 846	if (mVObjp.isNull())
 847	{
 848		return;
 849	}
 850
 851	const F32 DEFAULT_DELTA_ANGLE 	= (0.15f);
 852	U32 old_render_stride, max_render_stride;
 853	U32 new_render_level;
 854	F32 stride_per_distance = DEFAULT_DELTA_ANGLE / mSurfacep->getMetersPerGrid();
 855	U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge();
 856
 857	LLVector4a center;
 858	center.load3( (mCenterRegion + mSurfacep->getOriginAgent()).mV);
 859	LLVector4a radius;
 860	radius.splat(mRadius);
 861
 862	// sphere in frustum on global coordinates
 863	if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, radius))
 864	{
 865		// We now need to calculate the render stride based on patchp's distance 
 866		// from LLCamera render_stride is governed by a relation something like this...
 867		//
 868		//                       delta_angle * patch.distance
 869		// render_stride <=  ----------------------------------------
 870		//                           mMetersPerGrid
 871		//
 872		// where 'delta_angle' is the desired solid angle of the average polgon on a patch.
 873		//
 874		// Any render_stride smaller than the RHS would be 'satisfactory'.  Smaller 
 875		// strides give more resolution, but efficiency suggests that we use the largest 
 876		// of the render_strides that obey the relation.  Flexibility is achieved by 
 877		// modulating 'delta_angle' until we have an acceptable number of triangles.
 878	
 879		old_render_stride = mVisInfo.mRenderStride;
 880
 881		// Calculate the render_stride using information in agent
 882		max_render_stride = lltrunc(mVisInfo.mDistance * stride_per_distance);
 883		max_render_stride = llmin(max_render_stride , 2*grids_per_patch_edge);
 884
 885		// We only use render_strides that are powers of two, so we use look-up tables to figure out
 886		// the render_level and corresponding render_stride
 887		new_render_level = mVisInfo.mRenderLevel = mSurfacep->getRenderLevel(max_render_stride);
 888		mVisInfo.mRenderStride = mSurfacep->getRenderStride(new_render_level);
 889
 890		if ((mVisInfo.mRenderStride != old_render_stride)) 
 891			// The reason we check !mbIsVisible is because non-visible patches normals 
 892			// are not updated when their data is changed.  When this changes we can get 
 893			// rid of mbIsVisible altogether.
 894		{
 895			if (mVObjp)
 896			{
 897				mVObjp->dirtyGeom();
 898				if (getNeighborPatch(WEST))
 899				{
 900					getNeighborPatch(WEST)->mVObjp->dirtyGeom();
 901				}
 902				if (getNeighborPatch(SOUTH))
 903				{
 904					getNeighborPatch(SOUTH)->mVObjp->dirtyGeom();
 905				}
 906			}
 907		}
 908		mVisInfo.mbIsVisible = TRUE;
 909	}
 910	else
 911	{
 912		mVisInfo.mbIsVisible = FALSE;
 913	}
 914}
 915
 916
 917const LLVector3d &LLSurfacePatch::getOriginGlobal() const
 918{
 919	return mOriginGlobal;
 920}
 921
 922LLVector3 LLSurfacePatch::getOriginAgent() const
 923{
 924	return gAgent.getPosAgentFromGlobal(mOriginGlobal);
 925}
 926
 927BOOL LLSurfacePatch::getVisible() const
 928{
 929	return mVisInfo.mbIsVisible;
 930}
 931
 932U32 LLSurfacePatch::getRenderStride() const
 933{
 934	return mVisInfo.mRenderStride;
 935}
 936
 937S32 LLSurfacePatch::getRenderLevel() const
 938{
 939	return mVisInfo.mRenderLevel;
 940}
 941
 942void LLSurfacePatch::setHasReceivedData()
 943{
 944	mHasReceivedData = TRUE;
 945}
 946
 947BOOL LLSurfacePatch::getHasReceivedData() const
 948{
 949	return mHasReceivedData;
 950}
 951
 952const LLVector3 &LLSurfacePatch::getCenterRegion() const
 953{
 954	return mCenterRegion;
 955}
 956
 957
 958void LLSurfacePatch::updateCompositionStats()
 959{
 960	LLViewerLayer *vlp = mSurfacep->getRegion()->getComposition();
 961
 962	F32 x, y, width, height, mpg, min, mean, max;
 963
 964	LLVector3 origin = getOriginAgent() - mSurfacep->getOriginAgent();
 965	mpg = mSurfacep->getMetersPerGrid();
 966	x = origin.mV[VX];
 967	y = origin.mV[VY];
 968	width = mpg*(mSurfacep->getGridsPerPatchEdge()+1);
 969	height = mpg*(mSurfacep->getGridsPerPatchEdge()+1);
 970
 971	mean = 0.f;
 972	min = vlp->getValueScaled(x, y);
 973	max= min;
 974	U32 count = 0;
 975	F32 i, j;
 976	for (j = 0; j < height; j += mpg)
 977	{
 978		for (i = 0; i < width; i += mpg)
 979		{
 980			F32 comp = vlp->getValueScaled(x + i, y + j);
 981			mean += comp;
 982			min = llmin(min, comp);
 983			max = llmax(max, comp);
 984			count++;
 985		}
 986	}
 987	mean /= count;
 988
 989	mMinComposition = min;
 990	mMeanComposition = mean;
 991	mMaxComposition = max;
 992}
 993
 994F32 LLSurfacePatch::getMeanComposition() const
 995{
 996	return mMeanComposition;
 997}
 998
 999F32 LLSurfacePatch::getMinComposition() const
1000{
1001	return mMinComposition;
1002}
1003
1004F32 LLSurfacePatch::getMaxComposition() const
1005{
1006	return mMaxComposition;
1007}
1008
1009void LLSurfacePatch::setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp)
1010{
1011	mNeighborPatches[direction] = neighborp;
1012	mNormalsInvalid[direction] = TRUE;
1013	if (direction < 4)
1014	{
1015		mNormalsInvalid[gDirAdjacent[direction][0]] = TRUE;
1016		mNormalsInvalid[gDirAdjacent[direction][1]] = TRUE;
1017	}
1018}
1019
1020LLSurfacePatch *LLSurfacePatch::getNeighborPatch(const U32 direction) const
1021{
1022	return mNeighborPatches[direction];
1023}
1024
1025void LLSurfacePatch::clearVObj()
1026{
1027	mVObjp = NULL;
1028}