PageRenderTime 816ms CodeModel.GetById 121ms app.highlight 537ms RepoModel.GetById 127ms app.codeStats 1ms

/indra/newview/llsurface.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1293 lines | 933 code | 201 blank | 159 comment | 149 complexity | 9ae2007a2c00774d369894a49f9c5f33 MD5 | raw file
   1/** 
   2 * @file llsurface.cpp
   3 * @brief Implementation of LLSurface class
   4 *
   5 * $LicenseInfo:firstyear=2000&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 "llsurface.h"
  30
  31#include "llrender.h"
  32
  33#include "llviewertexturelist.h"
  34#include "llpatchvertexarray.h"
  35#include "patch_dct.h"
  36#include "patch_code.h"
  37#include "bitpack.h"
  38#include "llviewerobjectlist.h"
  39#include "llregionhandle.h"
  40#include "llagent.h"
  41#include "llagentcamera.h"
  42#include "llappviewer.h"
  43#include "llworld.h"
  44#include "llviewercontrol.h"
  45#include "llviewertexture.h"
  46#include "llsurfacepatch.h"
  47#include "llvosurfacepatch.h"
  48#include "llvowater.h"
  49#include "pipeline.h"
  50#include "llviewerregion.h"
  51#include "llvlcomposition.h"
  52#include "noise.h"
  53#include "llviewercamera.h"
  54#include "llglheaders.h"
  55#include "lldrawpoolterrain.h"
  56#include "lldrawable.h"
  57
  58extern LLPipeline gPipeline;
  59
  60LLColor4U MAX_WATER_COLOR(0, 48, 96, 240);
  61
  62
  63S32 LLSurface::sTextureSize = 256;
  64S32 LLSurface::sTexelsUpdated = 0;
  65F32 LLSurface::sTextureUpdateTime = 0.f;
  66
  67// ---------------- LLSurface:: Public Members ---------------
  68
  69LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) :
  70	mGridsPerEdge(0),
  71	mOOGridsPerEdge(0.f),
  72	mPatchesPerEdge(0),
  73	mNumberOfPatches(0),
  74	mType(type),
  75	mDetailTextureScale(0.f),
  76	mOriginGlobal(0.0, 0.0, 0.0),
  77	mSTexturep(NULL),
  78	mWaterTexturep(NULL),
  79	mGridsPerPatchEdge(0),
  80	mMetersPerGrid(1.0f),
  81	mMetersPerEdge(1.0f),
  82	mRegionp(regionp)
  83{
  84	// Surface data
  85	mSurfaceZ = NULL;
  86	mNorm = NULL;
  87
  88	// Patch data
  89	mPatchList = NULL;
  90
  91	// One of each for each camera
  92	mVisiblePatchCount = 0;
  93
  94	mHasZData = FALSE;
  95	// "uninitialized" min/max z
  96	mMinZ = 10000.f;
  97	mMaxZ = -10000.f;
  98
  99	mWaterObjp = NULL;
 100
 101	// In here temporarily.
 102	mSurfacePatchUpdateCount = 0;
 103
 104	for (S32 i = 0; i < 8; i++)
 105	{
 106		mNeighbors[i] = NULL;
 107	}
 108}
 109
 110
 111LLSurface::~LLSurface()
 112{
 113	delete [] mSurfaceZ;
 114	mSurfaceZ = NULL;
 115
 116	delete [] mNorm;
 117
 118	mGridsPerEdge = 0;
 119	mGridsPerPatchEdge = 0;
 120	mPatchesPerEdge = 0;
 121	mNumberOfPatches = 0;
 122	destroyPatchData();
 123
 124	LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep);
 125	if (!poolp)
 126	{
 127		llwarns << "No pool for terrain on destruction!" << llendl;
 128	}
 129	else if (poolp->mReferences.empty())
 130	{
 131		gPipeline.removePool(poolp);
 132		// Don't enable this until we blitz the draw pool for it as well.  -- djs
 133		if (mSTexturep)
 134		{
 135			mSTexturep = NULL;
 136		}
 137		if (mWaterTexturep)
 138		{
 139			mWaterTexturep = NULL;
 140		}
 141	}
 142	else
 143	{
 144		llerrs << "Terrain pool not empty!" << llendl;
 145	}
 146}
 147
 148void LLSurface::initClasses()
 149{
 150}
 151
 152void LLSurface::setRegion(LLViewerRegion *regionp)
 153{
 154	mRegionp = regionp;
 155	mWaterObjp = NULL; // depends on regionp, needs recreating
 156}
 157
 158// Assumes that arguments are powers of 2, and that
 159// grids_per_edge / grids_per_patch_edge = power of 2 
 160void LLSurface::create(const S32 grids_per_edge,
 161					   const S32 grids_per_patch_edge,
 162					   const LLVector3d &origin_global,
 163					   const F32 width) 
 164{
 165	// Initialize various constants for the surface
 166	mGridsPerEdge = grids_per_edge + 1;  // Add 1 for the east and north buffer
 167	mOOGridsPerEdge = 1.f / mGridsPerEdge;
 168	mGridsPerPatchEdge = grids_per_patch_edge;
 169	mPatchesPerEdge = (mGridsPerEdge - 1) / mGridsPerPatchEdge;
 170	mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge;
 171	mMetersPerGrid = width / ((F32)(mGridsPerEdge - 1));
 172	mMetersPerEdge = mMetersPerGrid * (mGridsPerEdge - 1);
 173
 174	mOriginGlobal.setVec(origin_global);
 175
 176	mPVArray.create(mGridsPerEdge, mGridsPerPatchEdge, LLWorld::getInstance()->getRegionScale());
 177
 178	S32 number_of_grids = mGridsPerEdge * mGridsPerEdge;
 179
 180	/////////////////////////////////////
 181	//
 182	// Initialize data arrays for surface
 183	///
 184	mSurfaceZ = new F32[number_of_grids];
 185	mNorm = new LLVector3[number_of_grids];
 186
 187	// Reset the surface to be a flat square grid
 188	for(S32 i=0; i < number_of_grids; i++) 
 189	{
 190		// Surface is flat and zero
 191		// Normals all point up
 192		mSurfaceZ[i] = 0.0f;
 193		mNorm[i].setVec(0.f, 0.f, 1.f);
 194	}
 195
 196
 197	mVisiblePatchCount = 0;
 198
 199
 200	///////////////////////
 201	//
 202	// Initialize textures
 203	//
 204
 205	initTextures();
 206
 207	// Has to be done after texture initialization
 208	createPatchData();
 209}
 210
 211LLViewerTexture* LLSurface::getSTexture()
 212{
 213	if (mSTexturep.notNull() && !mSTexturep->hasGLTexture())
 214	{
 215		createSTexture();
 216	}
 217	return mSTexturep;
 218}
 219
 220LLViewerTexture* LLSurface::getWaterTexture()
 221{
 222	if (mWaterTexturep.notNull() && !mWaterTexturep->hasGLTexture())
 223	{
 224		createWaterTexture();
 225	}
 226	return mWaterTexturep;
 227}
 228
 229void LLSurface::createSTexture()
 230{
 231	if (!mSTexturep)
 232	{
 233		// Fill with dummy gray data.	
 234		// GL NOT ACTIVE HERE
 235		LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3);
 236		U8 *default_texture = raw->getData();
 237		for (S32 i = 0; i < sTextureSize; i++)
 238		{
 239			for (S32 j = 0; j < sTextureSize; j++)
 240			{
 241				*(default_texture + (i*sTextureSize + j)*3) = 128;
 242				*(default_texture + (i*sTextureSize + j)*3 + 1) = 128;
 243				*(default_texture + (i*sTextureSize + j)*3 + 2) = 128;
 244			}
 245		}
 246
 247		mSTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
 248		mSTexturep->dontDiscard();
 249		gGL.getTexUnit(0)->bind(mSTexturep);
 250		mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);		
 251	}
 252}
 253
 254void LLSurface::createWaterTexture()
 255{
 256	if (!mWaterTexturep)
 257	{
 258		// Create the water texture
 259		LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4);
 260		U8 *default_texture = raw->getData();
 261		for (S32 i = 0; i < sTextureSize/2; i++)
 262		{
 263			for (S32 j = 0; j < sTextureSize/2; j++)
 264			{
 265				*(default_texture + (i*sTextureSize/2 + j)*4) = MAX_WATER_COLOR.mV[0];
 266				*(default_texture + (i*sTextureSize/2 + j)*4 + 1) = MAX_WATER_COLOR.mV[1];
 267				*(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2];
 268				*(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3];
 269			}
 270		}		
 271		
 272		mWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
 273		mWaterTexturep->dontDiscard();
 274		gGL.getTexUnit(0)->bind(mWaterTexturep);
 275		mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
 276	}
 277}
 278
 279void LLSurface::initTextures()
 280{
 281	///////////////////////
 282	//
 283	// Main surface texture
 284	//
 285	createSTexture();
 286
 287	///////////////////////
 288	//
 289	// Water texture
 290	//
 291	if (gSavedSettings.getBOOL("RenderWater") )
 292	{
 293		createWaterTexture();
 294		mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp);
 295		gPipeline.createObject(mWaterObjp);
 296		LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle());
 297		water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT);
 298		mWaterObjp->setPositionGlobal(water_pos_global);
 299	}
 300}
 301
 302
 303void LLSurface::setOriginGlobal(const LLVector3d &origin_global) 
 304{
 305	LLVector3d new_origin_global;
 306	mOriginGlobal = origin_global;
 307	LLSurfacePatch *patchp;
 308	S32 i, j;
 309	// Need to update the southwest corners of the patches
 310	for (j=0; j<mPatchesPerEdge; j++) 
 311	{
 312		for (i=0; i<mPatchesPerEdge; i++) 
 313		{
 314			patchp = getPatch(i, j);
 315
 316			new_origin_global = patchp->getOriginGlobal();
 317			
 318			new_origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge;
 319			new_origin_global.mdV[1] = mOriginGlobal.mdV[1] + j * mMetersPerGrid * mGridsPerPatchEdge;
 320			patchp->setOriginGlobal(new_origin_global);
 321		}
 322	}
 323
 324	// Hack!
 325	if (mWaterObjp.notNull() && mWaterObjp->mDrawable.notNull())
 326	{
 327		const F64 x = origin_global.mdV[VX] + 128.0;
 328		const F64 y = origin_global.mdV[VY] + 128.0;
 329		const F64 z = mWaterObjp->getPositionGlobal().mdV[VZ];
 330
 331		LLVector3d water_origin_global(x, y, z);
 332
 333		mWaterObjp->setPositionGlobal(water_origin_global);
 334	}
 335}
 336
 337void LLSurface::getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions )
 338{
 339	S32 i;
 340	for (i = 0; i < 8; i++)
 341	{
 342		if ( mNeighbors[i] != NULL )
 343		{
 344			uniqueRegions.push_back( mNeighbors[i]->getRegion() );
 345		}
 346	}	
 347}
 348
 349void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
 350{
 351	S32 i;
 352	LLSurfacePatch *patchp, *neighbor_patchp;
 353
 354	mNeighbors[direction] = neighborp;
 355	neighborp->mNeighbors[gDirOpposite[direction]] = this;
 356
 357	// Connect patches
 358	if (NORTHEAST == direction)
 359	{
 360		patchp = getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1);
 361		neighbor_patchp = neighborp->getPatch(0, 0);
 362
 363		patchp->connectNeighbor(neighbor_patchp, direction);
 364		neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 365
 366		patchp->updateNorthEdge(); // Only update one of north or east.
 367		patchp->dirtyZ();
 368	}
 369	else if (NORTHWEST == direction)
 370	{
 371		patchp = getPatch(0, mPatchesPerEdge - 1);
 372		neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, 0);
 373
 374		patchp->connectNeighbor(neighbor_patchp, direction);
 375		neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 376	}
 377	else if (SOUTHWEST == direction)
 378	{
 379		patchp = getPatch(0, 0);
 380		neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1);
 381
 382		patchp->connectNeighbor(neighbor_patchp, direction);
 383		neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 384
 385		neighbor_patchp->updateNorthEdge(); // Only update one of north or east.
 386		neighbor_patchp->dirtyZ();
 387	}
 388	else if (SOUTHEAST == direction)
 389	{
 390		patchp = getPatch(mPatchesPerEdge - 1, 0);
 391		neighbor_patchp = neighborp->getPatch(0, mPatchesPerEdge - 1);
 392
 393		patchp->connectNeighbor(neighbor_patchp, direction);
 394		neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 395	}
 396	else if (EAST == direction)
 397	{
 398		// Do east/west connections, first
 399		for (i = 0; i < (S32)mPatchesPerEdge; i++)
 400		{
 401			patchp = getPatch(mPatchesPerEdge - 1, i);
 402			neighbor_patchp = neighborp->getPatch(0, i);
 403
 404			patchp->connectNeighbor(neighbor_patchp, direction);
 405			neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 406
 407			patchp->updateEastEdge();
 408			patchp->dirtyZ();
 409		}
 410
 411		// Now do northeast/southwest connections
 412		for (i = 0; i < (S32)mPatchesPerEdge - 1; i++)
 413		{
 414			patchp = getPatch(mPatchesPerEdge - 1, i);
 415			neighbor_patchp = neighborp->getPatch(0, i+1);
 416
 417			patchp->connectNeighbor(neighbor_patchp, NORTHEAST);
 418			neighbor_patchp->connectNeighbor(patchp, SOUTHWEST);
 419		}
 420		// Now do southeast/northwest connections
 421		for (i = 1; i < (S32)mPatchesPerEdge; i++)
 422		{
 423			patchp = getPatch(mPatchesPerEdge - 1, i);
 424			neighbor_patchp = neighborp->getPatch(0, i-1);
 425
 426			patchp->connectNeighbor(neighbor_patchp, SOUTHEAST);
 427			neighbor_patchp->connectNeighbor(patchp, NORTHWEST);
 428		}
 429	}
 430	else if (NORTH == direction)
 431	{
 432		// Do north/south connections, first
 433		for (i = 0; i < (S32)mPatchesPerEdge; i++)
 434		{
 435			patchp = getPatch(i, mPatchesPerEdge - 1);
 436			neighbor_patchp = neighborp->getPatch(i, 0);
 437
 438			patchp->connectNeighbor(neighbor_patchp, direction);
 439			neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 440
 441			patchp->updateNorthEdge();
 442			patchp->dirtyZ();
 443		}
 444
 445		// Do northeast/southwest connections
 446		for (i = 0; i < (S32)mPatchesPerEdge - 1; i++)
 447		{
 448			patchp = getPatch(i, mPatchesPerEdge - 1);
 449			neighbor_patchp = neighborp->getPatch(i+1, 0);
 450
 451			patchp->connectNeighbor(neighbor_patchp, NORTHEAST);
 452			neighbor_patchp->connectNeighbor(patchp, SOUTHWEST);
 453		}
 454		// Do southeast/northwest connections
 455		for (i = 1; i < (S32)mPatchesPerEdge; i++)
 456		{
 457			patchp = getPatch(i, mPatchesPerEdge - 1);
 458			neighbor_patchp = neighborp->getPatch(i-1, 0);
 459
 460			patchp->connectNeighbor(neighbor_patchp, NORTHWEST);
 461			neighbor_patchp->connectNeighbor(patchp, SOUTHEAST);
 462		}
 463	}
 464	else if (WEST == direction)
 465	{
 466		// Do east/west connections, first
 467		for (i = 0; i < mPatchesPerEdge; i++)
 468		{
 469			patchp = getPatch(0, i);
 470			neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i);
 471
 472			patchp->connectNeighbor(neighbor_patchp, direction);
 473			neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 474
 475			neighbor_patchp->updateEastEdge();
 476			neighbor_patchp->dirtyZ();
 477		}
 478
 479		// Now do northeast/southwest connections
 480		for (i = 1; i < mPatchesPerEdge; i++)
 481		{
 482			patchp = getPatch(0, i);
 483			neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i - 1);
 484
 485			patchp->connectNeighbor(neighbor_patchp, SOUTHWEST);
 486			neighbor_patchp->connectNeighbor(patchp, NORTHEAST);
 487		}
 488
 489		// Now do northwest/southeast connections
 490		for (i = 0; i < mPatchesPerEdge - 1; i++)
 491		{
 492			patchp = getPatch(0, i);
 493			neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i + 1);
 494
 495			patchp->connectNeighbor(neighbor_patchp, NORTHWEST);
 496			neighbor_patchp->connectNeighbor(patchp, SOUTHEAST);
 497		}
 498	}
 499	else if (SOUTH == direction)
 500	{
 501		// Do north/south connections, first
 502		for (i = 0; i < mPatchesPerEdge; i++)
 503		{
 504			patchp = getPatch(i, 0);
 505			neighbor_patchp = neighborp->getPatch(i, mPatchesPerEdge - 1);
 506
 507			patchp->connectNeighbor(neighbor_patchp, direction);
 508			neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]);
 509
 510			neighbor_patchp->updateNorthEdge();
 511			neighbor_patchp->dirtyZ();
 512		}
 513
 514		// Now do northeast/southwest connections
 515		for (i = 1; i < mPatchesPerEdge; i++)
 516		{
 517			patchp = getPatch(i, 0);
 518			neighbor_patchp = neighborp->getPatch(i - 1, mPatchesPerEdge - 1);
 519
 520			patchp->connectNeighbor(neighbor_patchp, SOUTHWEST);
 521			neighbor_patchp->connectNeighbor(patchp, NORTHEAST);
 522		}
 523		// Now do northeast/southwest connections
 524		for (i = 0; i < mPatchesPerEdge - 1; i++)
 525		{
 526			patchp = getPatch(i, 0);
 527			neighbor_patchp = neighborp->getPatch(i + 1, mPatchesPerEdge - 1);
 528
 529			patchp->connectNeighbor(neighbor_patchp, SOUTHEAST);
 530			neighbor_patchp->connectNeighbor(patchp, NORTHWEST);
 531		}
 532	}		
 533}
 534
 535void LLSurface::disconnectNeighbor(LLSurface *surfacep)
 536{
 537	S32 i;
 538	for (i = 0; i < 8; i++)
 539	{
 540		if (surfacep == mNeighbors[i])
 541		{
 542			mNeighbors[i] = NULL;
 543		}
 544	}
 545
 546	// Iterate through surface patches, removing any connectivity to removed surface.
 547	for (i = 0; i < mNumberOfPatches; i++)
 548	{
 549		(mPatchList + i)->disconnectNeighbor(surfacep);
 550	}
 551}
 552
 553
 554void LLSurface::disconnectAllNeighbors()
 555{
 556	S32 i;
 557	for (i = 0; i < 8; i++)
 558	{
 559		if (mNeighbors[i])
 560		{
 561			mNeighbors[i]->disconnectNeighbor(this);
 562			mNeighbors[i] = NULL;
 563		}
 564	}
 565}
 566
 567
 568
 569const LLVector3d &LLSurface::getOriginGlobal() const
 570{
 571	return mOriginGlobal;
 572}
 573
 574LLVector3 LLSurface::getOriginAgent() const
 575{
 576	return gAgent.getPosAgentFromGlobal(mOriginGlobal);
 577}
 578
 579F32 LLSurface::getMetersPerGrid() const
 580{
 581	return mMetersPerGrid;
 582}
 583
 584S32 LLSurface::getGridsPerEdge() const
 585{
 586	return mGridsPerEdge;
 587}
 588
 589S32 LLSurface::getPatchesPerEdge() const
 590{
 591	return mPatchesPerEdge;
 592}
 593
 594S32 LLSurface::getGridsPerPatchEdge() const
 595{
 596	return mGridsPerPatchEdge;
 597}
 598
 599void LLSurface::moveZ(const S32 x, const S32 y, const F32 delta)
 600{
 601	llassert(x >= 0);
 602	llassert(y >= 0);
 603	llassert(x < mGridsPerEdge);
 604	llassert(y < mGridsPerEdge);
 605	mSurfaceZ[x + y*mGridsPerEdge] += delta;
 606}
 607
 608
 609void LLSurface::updatePatchVisibilities(LLAgent &agent) 
 610{
 611	LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal());
 612
 613	LLSurfacePatch *patchp;
 614	
 615	mVisiblePatchCount = 0;
 616	for (S32 i=0; i<mNumberOfPatches; i++) 
 617	{
 618		patchp = mPatchList + i;
 619
 620		patchp->updateVisibility();
 621		if (patchp->getVisible())
 622		{
 623			mVisiblePatchCount++;
 624			patchp->updateCameraDistanceRegion(pos_region);
 625		}
 626	}
 627}
 628
 629BOOL LLSurface::idleUpdate(F32 max_update_time)
 630{
 631	LLMemType mt_ius(LLMemType::MTYPE_IDLE_UPDATE_SURFACE);
 632	if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN))
 633	{
 634		return FALSE;
 635	}
 636	
 637	// Perform idle time update of non-critical stuff.
 638	// In this case, texture and normal updates.
 639	LLTimer update_timer;
 640	BOOL did_update = FALSE;
 641
 642	// If the Z height data has changed, we need to rebuild our
 643	// property line vertex arrays.
 644	if (mDirtyPatchList.size() > 0)
 645	{
 646		getRegion()->dirtyHeights();
 647	}
 648
 649	// Always call updateNormals() / updateVerticalStats()
 650	//  every frame to avoid artifacts
 651	for(std::set<LLSurfacePatch *>::iterator iter = mDirtyPatchList.begin();
 652		iter != mDirtyPatchList.end(); )
 653	{
 654		std::set<LLSurfacePatch *>::iterator curiter = iter++;
 655		LLSurfacePatch *patchp = *curiter;
 656		patchp->updateNormals();
 657		patchp->updateVerticalStats();
 658		if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time)
 659		{
 660			if (patchp->updateTexture())
 661			{
 662				did_update = TRUE;
 663				patchp->clearDirty();
 664				mDirtyPatchList.erase(curiter);
 665			}
 666		}
 667	}
 668	return did_update;
 669}
 670
 671void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch) 
 672{
 673
 674	LLPatchHeader  ph;
 675	S32 j, i;
 676	S32 patch[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
 677	LLSurfacePatch *patchp;
 678
 679	init_patch_decompressor(gopp->patch_size);
 680	gopp->stride = mGridsPerEdge;
 681	set_group_of_patch_header(gopp);
 682
 683	while (1)
 684	{
 685		decode_patch_header(bitpack, &ph);
 686		if (ph.quant_wbits == END_OF_PATCHES)
 687		{
 688			break;
 689		}
 690
 691		i = ph.patchids >> 5;
 692		j = ph.patchids & 0x1F;
 693
 694		if ((i >= mPatchesPerEdge) || (j >= mPatchesPerEdge))
 695		{
 696			llwarns << "Received invalid terrain packet - patch header patch ID incorrect!" 
 697				<< " patches per edge " << mPatchesPerEdge
 698				<< " i " << i
 699				<< " j " << j
 700				<< " dc_offset " << ph.dc_offset
 701				<< " range " << (S32)ph.range
 702				<< " quant_wbits " << (S32)ph.quant_wbits
 703				<< " patchids " << (S32)ph.patchids
 704				<< llendl;
 705            LLAppViewer::instance()->badNetworkHandler();
 706			return;
 707		}
 708
 709		patchp = &mPatchList[j*mPatchesPerEdge + i];
 710
 711
 712		decode_patch(bitpack, patch);
 713		decompress_patch(patchp->getDataZ(), patch, &ph);
 714
 715		// Update edges for neighbors.  Need to guarantee that this gets done before we generate vertical stats.
 716		patchp->updateNorthEdge();
 717		patchp->updateEastEdge();
 718		if (patchp->getNeighborPatch(WEST))
 719		{
 720			patchp->getNeighborPatch(WEST)->updateEastEdge();
 721		}
 722		if (patchp->getNeighborPatch(SOUTHWEST))
 723		{
 724			patchp->getNeighborPatch(SOUTHWEST)->updateEastEdge();
 725			patchp->getNeighborPatch(SOUTHWEST)->updateNorthEdge();
 726		}
 727		if (patchp->getNeighborPatch(SOUTH))
 728		{
 729			patchp->getNeighborPatch(SOUTH)->updateNorthEdge();
 730		}
 731
 732		// Dirty patch statistics, and flag that the patch has data.
 733		patchp->dirtyZ();
 734		patchp->setHasReceivedData();
 735	}
 736}
 737
 738
 739// Retrurns TRUE if "position" is within the bounds of surface.
 740// "position" is region-local
 741BOOL LLSurface::containsPosition(const LLVector3 &position)
 742{
 743	if (position.mV[VX] < 0.0f  ||  position.mV[VX] > mMetersPerEdge ||
 744		position.mV[VY] < 0.0f  ||  position.mV[VY] > mMetersPerEdge)
 745	{
 746		return FALSE;
 747	}
 748	return TRUE;
 749}
 750
 751
 752F32 LLSurface::resolveHeightRegion(const F32 x, const F32 y) const
 753{
 754	F32 height = 0.0f;
 755	F32 oometerspergrid = 1.f/mMetersPerGrid;
 756
 757	// Check to see if v is actually above surface 
 758	// We use (mGridsPerEdge-1) below rather than (mGridsPerEdge) 
 759	// becuase of the east and north buffers 
 760
 761	if (x >= 0.f  &&  
 762		x <= mMetersPerEdge  &&
 763		y >= 0.f  &&  
 764		y <= mMetersPerEdge)
 765	{
 766		const S32 left   = llfloor(x * oometerspergrid);
 767		const S32 bottom = llfloor(y * oometerspergrid);
 768
 769		// Don't walk off the edge of the array!
 770		const S32 right  = ( left+1   < (S32)mGridsPerEdge-1 ? left+1   : left );
 771		const S32 top    = ( bottom+1 < (S32)mGridsPerEdge-1 ? bottom+1 : bottom );
 772
 773		// Figure out if v is in first or second triangle of the square
 774		// and calculate the slopes accordingly
 775		//    |       |
 776		// -(i,j+1)---(i+1,j+1)--   
 777		//    |  1   /  |          ^
 778		//    |    /  2 |          |
 779		//    |  /      |          j
 780		// --(i,j)----(i+1,j)--
 781		//    |       |
 782		// 
 783		//      i ->
 784		// where N = mGridsPerEdge
 785
 786		const F32 left_bottom  = getZ( left,  bottom );
 787		const F32 right_bottom = getZ( right, bottom );
 788		const F32 left_top     = getZ( left,  top );
 789		const F32 right_top    = getZ( right, top );
 790
 791		// dx and dy are incremental steps from (mSurface + k)
 792		F32 dx = x - left   * mMetersPerGrid;
 793		F32 dy = y - bottom * mMetersPerGrid;
 794
 795		if (dy > dx) 
 796		{
 797			// triangle 1
 798			dy *= left_top  - left_bottom;
 799			dx *= right_top - left_top;
 800		}
 801		else 
 802		{
 803			// triangle 2
 804			dx *= right_bottom - left_bottom;
 805			dy *= right_top    - right_bottom;
 806		}
 807		height = left_bottom + (dx + dy) * oometerspergrid;
 808	}
 809	return height;
 810}
 811
 812
 813F32 LLSurface::resolveHeightGlobal(const LLVector3d& v) const
 814{
 815	if (!mRegionp)
 816	{
 817		return 0.f;
 818	}
 819	
 820	LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(v);
 821
 822	return resolveHeightRegion(pos_region);
 823}
 824
 825
 826LLVector3 LLSurface::resolveNormalGlobal(const LLVector3d& pos_global) const
 827{
 828	if (!mSurfaceZ)
 829	{
 830		// Hmm.  Uninitialized surface!
 831		return LLVector3::z_axis;
 832	}
 833	//
 834	// Returns the vector normal to a surface at location specified by vector v
 835	//
 836	F32 oometerspergrid = 1.f/mMetersPerGrid;
 837	LLVector3 normal;
 838	F32 dzx, dzy;
 839
 840	if (pos_global.mdV[VX] >= mOriginGlobal.mdV[VX]  &&  
 841		pos_global.mdV[VX] < mOriginGlobal.mdV[VX] + mMetersPerEdge  &&
 842		pos_global.mdV[VY] >= mOriginGlobal.mdV[VY]  &&  
 843		pos_global.mdV[VY] < mOriginGlobal.mdV[VY] + mMetersPerEdge)
 844	{
 845		U32 i, j, k;
 846		F32 dx, dy;
 847		i = (U32) ((pos_global.mdV[VX] - mOriginGlobal.mdV[VX]) * oometerspergrid);
 848		j = (U32) ((pos_global.mdV[VY] - mOriginGlobal.mdV[VY]) * oometerspergrid );
 849		k = i + j*mGridsPerEdge;
 850
 851		// Figure out if v is in first or second triangle of the square
 852		// and calculate the slopes accordingly
 853		//    |       |
 854		// -(k+N)---(k+1+N)--   
 855		//    |  1 /  |          ^
 856		//    |   / 2 |          |
 857		//    |  /    |          j
 858		// --(k)----(k+1)--
 859		//    |       |
 860		// 
 861		//      i ->
 862		// where N = mGridsPerEdge
 863
 864		// dx and dy are incremental steps from (mSurface + k)
 865		dx = (F32)(pos_global.mdV[VX] - i*mMetersPerGrid - mOriginGlobal.mdV[VX]);
 866		dy = (F32)(pos_global.mdV[VY] - j*mMetersPerGrid - mOriginGlobal.mdV[VY]);
 867		if (dy > dx) 
 868		{  // triangle 1
 869			dzx = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + mGridsPerEdge);
 870			dzy = *(mSurfaceZ + k) - *(mSurfaceZ + k + mGridsPerEdge);
 871			normal.setVec(-dzx,dzy,1);
 872		}
 873		else 
 874		{	// triangle 2
 875			dzx = *(mSurfaceZ + k) - *(mSurfaceZ + k + 1);
 876			dzy = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + 1);
 877			normal.setVec(dzx,-dzy,1);
 878		}
 879	}
 880	normal.normVec();
 881	return normal;
 882
 883
 884}
 885
 886LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const
 887{
 888// x and y should be region-local coordinates. 
 889// If x and y are outside of the surface, then the returned
 890// index will be for the nearest boundary patch.
 891//
 892// 12      | 13| 14|       15
 893//         |   |   |    
 894//     +---+---+---+---+
 895//     | 12| 13| 14| 15|
 896// ----+---+---+---+---+-----
 897// 8   | 8 | 9 | 10| 11|   11
 898// ----+---+---+---+---+-----
 899// 4   | 4 | 5 | 6 | 7 |    7
 900// ----+---+---+---+---+-----
 901//     | 0 | 1 | 2 | 3 |
 902//     +---+---+---+---+
 903//         |   |   |    
 904// 0       | 1 | 2 |        3
 905//
 906
 907// When x and y are not region-local do the following first
 908
 909	S32 i, j;
 910	if (x < 0.0f)
 911	{
 912		i = 0;
 913	}
 914	else if (x >= mMetersPerEdge)
 915	{
 916		i = mPatchesPerEdge - 1;
 917	}
 918	else
 919	{
 920		i = (U32) (x / (mMetersPerGrid * mGridsPerPatchEdge));
 921	}
 922
 923	if (y < 0.0f)
 924	{
 925		j = 0;
 926	}
 927	else if (y >= mMetersPerEdge)
 928	{
 929		j = mPatchesPerEdge - 1;
 930	}
 931	else
 932	{
 933		j = (U32) (y / (mMetersPerGrid * mGridsPerPatchEdge));
 934	}
 935
 936	// *NOTE: Super paranoia code follows.
 937	S32 index = i + j * mPatchesPerEdge;
 938	if((index < 0) || (index >= mNumberOfPatches))
 939	{
 940		if(0 == mNumberOfPatches)
 941		{
 942			llwarns << "No patches for current region!" << llendl;
 943			return NULL;
 944		}
 945		S32 old_index = index;
 946		index = llclamp(old_index, 0, (mNumberOfPatches - 1));
 947		llwarns << "Clamping out of range patch index " << old_index
 948				<< " to " << index << llendl;
 949	}
 950	return &(mPatchList[index]);
 951}
 952
 953
 954LLSurfacePatch *LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const
 955{
 956	return resolvePatchRegion(pos_region.mV[VX], pos_region.mV[VY]);
 957}
 958
 959
 960LLSurfacePatch *LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const
 961{
 962	llassert(mRegionp);
 963	LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(pos_global);
 964	return resolvePatchRegion(pos_region);
 965}
 966
 967
 968std::ostream& operator<<(std::ostream &s, const LLSurface &S) 
 969{
 970	s << "{ \n";
 971	s << "  mGridsPerEdge = " << S.mGridsPerEdge - 1 << " + 1\n";
 972	s << "  mGridsPerPatchEdge = " << S.mGridsPerPatchEdge << "\n";
 973	s << "  mPatchesPerEdge = " << S.mPatchesPerEdge << "\n";
 974	s << "  mOriginGlobal = " << S.mOriginGlobal << "\n";
 975	s << "  mMetersPerGrid = " << S.mMetersPerGrid << "\n";
 976	s << "  mVisiblePatchCount = " << S.mVisiblePatchCount << "\n";
 977	s << "}";
 978	return s;
 979}
 980
 981
 982// ---------------- LLSurface:: Protected ----------------
 983
 984void LLSurface::createPatchData() 
 985{
 986	// Assumes mGridsPerEdge, mGridsPerPatchEdge, and mPatchesPerEdge have been properly set
 987	// TODO -- check for create() called when surface is not empty
 988	S32 i, j;
 989	LLSurfacePatch *patchp;
 990
 991	// Allocate memory
 992	mPatchList = new LLSurfacePatch[mNumberOfPatches];
 993
 994	// One of each for each camera
 995	mVisiblePatchCount = mNumberOfPatches;
 996
 997	for (j=0; j<mPatchesPerEdge; j++) 
 998	{
 999		for (i=0; i<mPatchesPerEdge; i++) 
1000		{
1001			patchp = getPatch(i, j);
1002			patchp->setSurface(this);
1003		}
1004	}
1005
1006	for (j=0; j<mPatchesPerEdge; j++) 
1007	{
1008		for (i=0; i<mPatchesPerEdge; i++) 
1009		{
1010			patchp = getPatch(i, j);
1011			patchp->mHasReceivedData = FALSE;
1012			patchp->mSTexUpdate = TRUE;
1013
1014			S32 data_offset = i * mGridsPerPatchEdge + j * mGridsPerPatchEdge * mGridsPerEdge;
1015
1016			patchp->setDataZ(mSurfaceZ + data_offset);
1017			patchp->setDataNorm(mNorm + data_offset);
1018
1019
1020			// We make each patch point to its neighbors so we can do resolution checking 
1021			// when butting up different resolutions.  Patches that don't have neighbors
1022			// somewhere will point to NULL on that side.
1023			if (i < mPatchesPerEdge-1)  
1024			{
1025				patchp->setNeighborPatch(EAST,getPatch(i+1, j));
1026			}
1027			else 
1028			{
1029				patchp->setNeighborPatch(EAST, NULL);
1030			}
1031
1032			if (j < mPatchesPerEdge-1)  
1033			{
1034				patchp->setNeighborPatch(NORTH, getPatch(i, j+1));
1035			}
1036			else 
1037			{
1038				patchp->setNeighborPatch(NORTH, NULL);
1039			}
1040
1041			if (i > 0) 
1042			{
1043				patchp->setNeighborPatch(WEST, getPatch(i - 1, j));
1044			}
1045			else 
1046			{
1047				patchp->setNeighborPatch(WEST, NULL);
1048			}
1049
1050			if (j > 0)  
1051			{
1052				patchp->setNeighborPatch(SOUTH, getPatch(i, j-1));
1053			}
1054			else 
1055			{
1056				patchp->setNeighborPatch(SOUTH, NULL);
1057			}
1058
1059			if (i < (mPatchesPerEdge-1)  &&  j < (mPatchesPerEdge-1)) 
1060			{
1061				patchp->setNeighborPatch(NORTHEAST, getPatch(i + 1, j + 1));
1062			}
1063			else 
1064			{
1065				patchp->setNeighborPatch(NORTHEAST, NULL);		
1066			}
1067
1068			if (i > 0  &&  j < (mPatchesPerEdge-1)) 
1069			{
1070				patchp->setNeighborPatch(NORTHWEST, getPatch(i - 1, j + 1));
1071			}
1072			else 
1073			{
1074				patchp->setNeighborPatch(NORTHWEST, NULL);
1075			}
1076
1077			if (i > 0  &&  j > 0) 
1078			{
1079				patchp->setNeighborPatch(SOUTHWEST, getPatch(i - 1, j - 1));
1080			}
1081			else 
1082			{
1083				patchp->setNeighborPatch(SOUTHWEST, NULL);
1084			}
1085
1086			if (i < (mPatchesPerEdge-1)  &&  j > 0) 
1087			{
1088				patchp->setNeighborPatch(SOUTHEAST, getPatch(i + 1, j - 1));
1089			}
1090			else 
1091			{
1092				patchp->setNeighborPatch(SOUTHEAST, NULL);
1093			}
1094
1095			LLVector3d origin_global;
1096			origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge;
1097			origin_global.mdV[1] = mOriginGlobal.mdV[0] + j * mMetersPerGrid * mGridsPerPatchEdge;
1098			origin_global.mdV[2] = 0.f;
1099			patchp->setOriginGlobal(origin_global);
1100		}
1101	}
1102}
1103
1104
1105void LLSurface::destroyPatchData()
1106{
1107	// Delete all of the cached patch data for these patches.
1108
1109	delete [] mPatchList;
1110	mPatchList = NULL;
1111	mVisiblePatchCount = 0;
1112}
1113
1114
1115void LLSurface::setTextureSize(const S32 texture_size)
1116{
1117	sTextureSize = texture_size;
1118}
1119
1120
1121U32 LLSurface::getRenderLevel(const U32 render_stride) const
1122{
1123	return mPVArray.mRenderLevelp[render_stride];
1124}
1125
1126
1127U32 LLSurface::getRenderStride(const U32 render_level) const
1128{
1129	return mPVArray.mRenderStridep[render_level];
1130}
1131
1132
1133LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const
1134{
1135	if ((x < 0) || (x >= mPatchesPerEdge))
1136	{
1137		llerrs << "Asking for patch out of bounds" << llendl;
1138		return NULL;
1139	}
1140	if ((y < 0) || (y >= mPatchesPerEdge))
1141	{
1142		llerrs << "Asking for patch out of bounds" << llendl;
1143		return NULL;
1144	}
1145
1146	return mPatchList + x + y*mPatchesPerEdge;
1147}
1148
1149
1150void LLSurface::dirtyAllPatches()
1151{
1152	S32 i;
1153	for (i = 0; i < mNumberOfPatches; i++)
1154	{
1155		mPatchList[i].dirtyZ();
1156	}
1157}
1158
1159void LLSurface::dirtySurfacePatch(LLSurfacePatch *patchp)
1160{
1161	// Put surface patch on dirty surface patch list
1162	mDirtyPatchList.insert(patchp);
1163}
1164
1165
1166void LLSurface::setWaterHeight(F32 height)
1167{
1168	if (!mWaterObjp.isNull())
1169	{
1170		LLVector3 water_pos_region = mWaterObjp->getPositionRegion();
1171		bool changed = water_pos_region.mV[VZ] != height;
1172		water_pos_region.mV[VZ] = height;
1173		mWaterObjp->setPositionRegion(water_pos_region);
1174		if (changed)
1175		{
1176			LLWorld::getInstance()->updateWaterObjects();
1177		}
1178	}
1179	else
1180	{
1181		llwarns << "LLSurface::setWaterHeight with no water object!" << llendl;
1182	}
1183}
1184
1185F32 LLSurface::getWaterHeight() const
1186{
1187	if (!mWaterObjp.isNull())
1188	{
1189		// we have a water object, the usual case
1190		return mWaterObjp->getPositionRegion().mV[VZ];
1191	}
1192	else
1193	{
1194		return DEFAULT_WATER_HEIGHT;
1195	}
1196}
1197
1198
1199BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y,
1200									 const F32 width, const F32 height)
1201{
1202	if (!getWaterTexture())
1203	{
1204		return FALSE;
1205	}
1206
1207	S32 tex_width = mWaterTexturep->getWidth();
1208	S32 tex_height = mWaterTexturep->getHeight();
1209	S32 tex_comps = mWaterTexturep->getComponents();
1210	S32 tex_stride = tex_width * tex_comps;
1211	LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
1212	U8 *rawp = raw->getData();
1213
1214	F32 scale = 256.f * getMetersPerGrid() / (F32)tex_width;
1215	F32 scale_inv = 1.f / scale;
1216
1217	S32 x_begin, y_begin, x_end, y_end;
1218
1219	x_begin = llround(x * scale_inv);
1220	y_begin = llround(y * scale_inv);
1221	x_end = llround((x + width) * scale_inv);
1222	y_end = llround((y + width) * scale_inv);
1223
1224	if (x_end > tex_width)
1225	{
1226		x_end = tex_width;
1227	}
1228	if (y_end > tex_width)
1229	{
1230		y_end = tex_width;
1231	}
1232
1233	LLVector3d origin_global = from_region_handle(getRegion()->getHandle());
1234
1235	// OK, for now, just have the composition value equal the height at the point.
1236	LLVector3 location;
1237	LLColor4U coloru;
1238
1239	const F32 WATER_HEIGHT = getWaterHeight();
1240
1241	S32 i, j, offset;
1242	for (j = y_begin; j < y_end; j++)
1243	{
1244		for (i = x_begin; i < x_end; i++)
1245		{
1246			//F32 nv[2];
1247			//nv[0] = i/256.f;
1248			//nv[1] = j/256.f;
1249			// const S32 modulation = noise2(nv)*40;
1250			offset = j*tex_stride + i*tex_comps;
1251			location.mV[VX] = i*scale;
1252			location.mV[VY] = j*scale;
1253
1254			// Sample multiple points
1255			const F32 height = resolveHeightRegion(location);
1256
1257			if (height > WATER_HEIGHT)
1258			{
1259				// Above water...
1260				coloru = MAX_WATER_COLOR;
1261				coloru.mV[3] = ABOVE_WATERLINE_ALPHA;
1262				*(rawp + offset++) = coloru.mV[0];
1263				*(rawp + offset++) = coloru.mV[1];
1264				*(rawp + offset++) = coloru.mV[2];
1265				*(rawp + offset++) = coloru.mV[3];
1266			}
1267			else
1268			{
1269				// Want non-linear curve for transparency gradient
1270				coloru = MAX_WATER_COLOR;
1271				const F32 frac = 1.f - 2.f/(2.f - (height - WATER_HEIGHT));
1272				S32 alpha = 64 + llround((255-64)*frac);
1273
1274				alpha = llmin(llround((F32)MAX_WATER_COLOR.mV[3]), alpha);
1275				alpha = llmax(64, alpha);
1276
1277				coloru.mV[3] = alpha;
1278				*(rawp + offset++) = coloru.mV[0];
1279				*(rawp + offset++) = coloru.mV[1];
1280				*(rawp + offset++) = coloru.mV[2];
1281				*(rawp + offset++) = coloru.mV[3];
1282			}
1283		}
1284	}
1285
1286	if (!mWaterTexturep->hasGLTexture())
1287	{
1288		mWaterTexturep->createGLTexture(0, raw);
1289	}
1290
1291	mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin);
1292	return TRUE;
1293}