diff options
Diffstat (limited to 'indra/newview')
25 files changed, 417 insertions, 147 deletions
| diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 583bb54160..8106fada11 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -358,6 +358,7 @@ void LLDrawable::makeActive()  	{  		U32 pcode = mVObjp->getPCode();  		if (pcode == LLViewerObject::LL_VO_WATER || +			pcode == LLViewerObject::LL_VO_VOID_WATER ||  			pcode == LLViewerObject::LL_VO_SURFACE_PATCH ||  			pcode == LLViewerObject::LL_VO_PART_GROUP ||  			pcode == LLViewerObject::LL_VO_HUD_PART_GROUP || diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index cb651f9d3a..ba576ff97f 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -89,6 +89,7 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)  	case POOL_SKY:  		poolp = new LLDrawPoolSky();  		break; +	case POOL_VOIDWATER:  	case POOL_WATER:  		poolp = new LLDrawPoolWater();  		break; diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 221f81ec25..e394aeaaf1 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -57,6 +57,7 @@ public:  		POOL_BUMP,  		POOL_INVISIBLE, // see below *  		POOL_AVATAR, +		POOL_VOIDWATER,  		POOL_WATER,  		POOL_GLOW,  		POOL_ALPHA, diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp index e950fbfa82..b4dc0c26a6 100644 --- a/indra/newview/lldrawpoolground.cpp +++ b/indra/newview/lldrawpoolground.cpp @@ -68,7 +68,7 @@ void LLDrawPoolGround::render(S32 pass)  	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); -	LLGLClampToFarClip far_clip(glh_get_current_projection()); +	LLGLSquashToFarClip far_clip(glh_get_current_projection());  	F32 water_height = gAgent.getRegion()->getWaterHeight();  	glPushMatrix(); diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index d811ab8c54..9eb45a952c 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -97,7 +97,7 @@ void LLDrawPoolSky::render(S32 pass)  	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); -	LLGLClampToFarClip far_clip(glh_get_current_projection()); +	LLGLSquashToFarClip far_clip(glh_get_current_projection());  	LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0); diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index ce1b899d55..6126908231 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -532,6 +532,7 @@ void LLDrawPoolWater::shade()  	glColor4fv(water_color.mV);  	{ +		LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0);  		LLGLDisable cullface(GL_CULL_FACE);  		for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();  			iter != mDrawFace.end(); iter++) @@ -548,30 +549,19 @@ void LLDrawPoolWater::shade()  			sNeedsReflectionUpdate = TRUE; -			if (water->getUseTexture()) +			if (water->getUseTexture() || !water->getIsEdgePatch())  			{  				sNeedsDistortionUpdate = TRUE;  				face->renderIndexed();  			} +			else if (gGLManager.mHasDepthClamp || deferred_render) +			{ +				face->renderIndexed(); +			}  			else -			{ //smash background faces to far clip plane -				if (water->getIsEdgePatch()) -				{ -					if (deferred_render) -					{ -						face->renderIndexed(); -					} -					else -					{ -						LLGLClampToFarClip far_clip(glh_get_current_projection()); -						face->renderIndexed(); -					} -				} -				else -				{ -					sNeedsDistortionUpdate = TRUE; -					face->renderIndexed(); -				} +			{ +				LLGLSquashToFarClip far_clip(glh_get_current_projection()); +				face->renderIndexed();  			}  		}  	} diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 41a299151e..eaa6aa7e37 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -260,7 +260,7 @@ void LLDrawPoolWLSky::render(S32 pass)  	LLGLDepthTest depth(GL_TRUE, GL_FALSE);  	LLGLDisable clip(GL_CLIP_PLANE0); -	LLGLClampToFarClip far_clip(glh_get_current_projection()); +	LLGLSquashToFarClip far_clip(glh_get_current_projection());  	renderSkyHaze(camHeightLocal); diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index f95112a8ab..087e4abe7e 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -210,13 +210,6 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)  	llassert(msg);  	if (!msg) return; -	LLHost host = msg->getSender(); -	if (host != gAgent.getRegionHost()) -	{ -		// update is for a different region than the one we're in -		return; -	} -  	//const S32 SIM_NAME_BUF = 256;  	U32 region_flags;  	U8 sim_access; @@ -234,6 +227,8 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)  	S32 redirect_grid_y;  	LLUUID cache_id; +	LLHost host = msg->getSender(); +  	msg->getStringFast(_PREHASH_RegionInfo, _PREHASH_SimName, sim_name);  	msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID, estate_id);  	msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID, parent_estate_id); @@ -243,6 +238,15 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)  	msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor, object_bonus_factor);  	msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_BillableFactor, billable_factor);  	msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height); + +	if (host != gAgent.getRegionHost()) +	{ +		// Update is for a different region than the one we're in. +		// Just check for a waterheight change. +		LLWorld::getInstance()->waterHeightRegionInfo(sim_name, water_height); +		return; +	} +  	msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, terrain_raise_limit);  	msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, terrain_lower_limit);  	msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_PricePerMeter, price_per_meter); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index fb984a7c62..960e72ee42 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1555,7 +1555,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)  {  	if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)  	{ -		if (earlyFail(camera, this)) +		// Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension +		if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) || +			earlyFail(camera, this))  		{  			setOcclusionState(LLSpatialGroup::DISCARD_QUERY);  			assert_states_valid(this); @@ -1576,7 +1578,18 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)  				{  					buildOcclusion();  				} - +				 +				// Depth clamp all water to avoid it being culled as a result of being +				// behind the far clip plane, and in the case of edge water to avoid +				// it being culled while still visible. +				bool const use_depth_clamp = gGLManager.mHasDepthClamp && +											(mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || +											mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); +				if (use_depth_clamp) +				{ +					glEnable(GL_DEPTH_CLAMP); +				} +				  				glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]);					  				glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);  				if (camera->getOrigin().isExactlyZero()) @@ -1592,6 +1605,11 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)  								GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));  				}  				glEndQueryARB(GL_SAMPLES_PASSED_ARB); +				 +				if (use_depth_clamp) +				{ +					glDisable(GL_DEPTH_CLAMP); +				}  			}  			setOcclusionState(LLSpatialGroup::QUERY_PENDING); @@ -2591,9 +2609,10 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)  						gGL.color4f(0.5f,0.5f,0.5f,1.0f);  						break;  				case LLViewerObject::LL_VO_PART_GROUP: -			case LLViewerObject::LL_VO_HUD_PART_GROUP: +				case LLViewerObject::LL_VO_HUD_PART_GROUP:  						gGL.color4f(0,0,1,1);  						break; +				case LLViewerObject::LL_VO_VOID_WATER:  				case LLViewerObject::LL_VO_WATER:  						gGL.color4f(0,0.5f,1,1);  						break; diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 1a25f3f85d..2b9cf6c630 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -551,6 +551,13 @@ public:  	virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }  }; +//spatial partition for hole and edge water (implemented in LLVOWater.cpp) +class LLVoidWaterPartition : public LLWaterPartition +{ +public: +	LLVoidWaterPartition(); +}; +  //spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp)  class LLTerrainPartition : public LLSpatialPartition  { diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index af4d9fa7b9..6fc8153b77 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -1162,8 +1162,13 @@ void LLSurface::setWaterHeight(F32 height)  	if (!mWaterObjp.isNull())  	{  		LLVector3 water_pos_region = mWaterObjp->getPositionRegion(); +		bool changed = water_pos_region.mV[VZ] != height;  		water_pos_region.mV[VZ] = height;  		mWaterObjp->setPositionRegion(water_pos_region); +		if (changed) +		{ +			LLWorld::getInstance()->updateWaterObjects(); +		}  	}  	else  	{ diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 916cbe2267..10c5a27aa7 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -573,7 +573,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  		S32 water_clip = 0;  		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && -			 gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER)) +			 (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) ||  +			  gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))  		{  			if (LLViewerCamera::getInstance()->cameraUnderWater())  			{ diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 741a9e6ec4..4ef1853095 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -167,8 +167,10 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco  	  res = new LLVOSurfacePatch(id, pcode, regionp); break;  	case LL_VO_SKY:  	  res = new LLVOSky(id, pcode, regionp); break; +	case LL_VO_VOID_WATER: +		res = new LLVOVoidWater(id, pcode, regionp); break;  	case LL_VO_WATER: -	  res = new LLVOWater(id, pcode, regionp); break; +		res = new LLVOWater(id, pcode, regionp); break;  	case LL_VO_GROUND:  	  res = new LLVOGround(id, pcode, regionp); break;  	case LL_VO_PART_GROUP: diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index bcc2cb164f..10683618cc 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -131,7 +131,7 @@ public:  	typedef const child_list_t const_child_list_t; -	LLViewerObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp, BOOL is_global = FALSE); +	LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global = FALSE);  	MEM_TYPE_NEW(LLMemType::MTYPE_OBJECT);  	virtual void markDead();				// Mark this object as dead, and clean up its references @@ -518,14 +518,14 @@ public:  	{  		LL_VO_CLOUDS =				LL_PCODE_APP | 0x20,  		LL_VO_SURFACE_PATCH =		LL_PCODE_APP | 0x30, -		//LL_VO_STARS =				LL_PCODE_APP | 0x40, +		LL_VO_WL_SKY =				LL_PCODE_APP | 0x40,  		LL_VO_SQUARE_TORUS =		LL_PCODE_APP | 0x50,  		LL_VO_SKY =					LL_PCODE_APP | 0x60, -		LL_VO_WATER =				LL_PCODE_APP | 0x70, -		LL_VO_GROUND =				LL_PCODE_APP | 0x80, -		LL_VO_PART_GROUP =			LL_PCODE_APP | 0x90, -		LL_VO_TRIANGLE_TORUS =		LL_PCODE_APP | 0xa0, -		LL_VO_WL_SKY =				LL_PCODE_APP | 0xb0, // should this be moved to 0x40? +		LL_VO_VOID_WATER =			LL_PCODE_APP | 0x70, +		LL_VO_WATER =				LL_PCODE_APP | 0x80, +		LL_VO_GROUND =				LL_PCODE_APP | 0x90, +		LL_VO_PART_GROUP =			LL_PCODE_APP | 0xa0, +		LL_VO_TRIANGLE_TORUS =		LL_PCODE_APP | 0xb0,  		LL_VO_HUD_PART_GROUP =		LL_PCODE_APP | 0xc0,  	} EVOType; @@ -717,8 +717,8 @@ public:  class LLAlphaObject : public LLViewerObject  {  public: -	LLAlphaObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp) -	: LLViewerObject(id,type,regionp)  +	LLAlphaObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) +	: LLViewerObject(id,pcode,regionp)   	{ mDepth = 0.f; }  	virtual F32 getPartSize(S32 idx); @@ -735,8 +735,8 @@ public:  class LLStaticViewerObject : public LLViewerObject  {  public: -	LLStaticViewerObject(const LLUUID& id, const LLPCode type, LLViewerRegion* regionp, BOOL is_global = FALSE) -		: LLViewerObject(id,type,regionp, is_global) +	LLStaticViewerObject(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp, BOOL is_global = FALSE) +		: LLViewerObject(id,pcode,regionp, is_global)  	{ }  	virtual void updateDrawable(BOOL force_damped); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 98f16757b2..74e9b9f4a2 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -261,6 +261,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,  	//MUST MATCH declaration of eObjectPartitions  	mObjectPartition.push_back(new LLHUDPartition());		//PARTITION_HUD  	mObjectPartition.push_back(new LLTerrainPartition());	//PARTITION_TERRAIN +	mObjectPartition.push_back(new LLVoidWaterPartition());	//PARTITION_VOIDWATER  	mObjectPartition.push_back(new LLWaterPartition());		//PARTITION_WATER  	mObjectPartition.push_back(new LLTreePartition());		//PARTITION_TREE  	mObjectPartition.push_back(new LLParticlePartition());	//PARTITION_PARTICLE diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 038c831e59..bf3948bef1 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -73,6 +73,7 @@ public:  	{  		PARTITION_HUD=0,  		PARTITION_TERRAIN, +		PARTITION_VOIDWATER,  		PARTITION_WATER,  		PARTITION_TREE,  		PARTITION_PARTICLE, diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index d078c15316..c1abead36e 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -335,8 +335,8 @@ void LLViewerShaderMgr::setShaders()  	}  	else  	{ -			LLPipeline::sRenderGlow =  -			LLPipeline::sWaterReflections = FALSE; +		LLPipeline::sRenderGlow = FALSE; +		LLPipeline::sWaterReflections = FALSE;  	}  	//hack to reset buffers that change behavior with shaders diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 43d18c6d83..66b8d7cd69 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1406,6 +1406,11 @@ LLViewerWindow::LLViewerWindow(  		gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);  	} +	if (!gGLManager.mHasDepthClamp) +	{ +		LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL; +	} +	  	// If we crashed while initializng GL stuff last time, disable certain features  	if (gSavedSettings.getBOOL("RenderInitError"))  	{ diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index eba600b50a..2eb4398488 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -80,7 +80,7 @@ public:  //============================================================================  LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -	:	LLStaticViewerObject(id, LL_VO_SURFACE_PATCH, regionp), +	:	LLStaticViewerObject(id, pcode, regionp),  		mDirtiedPatch(FALSE),  		mPool(NULL),  		mBaseComp(0), diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 598938b710..9280eb8fa4 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -61,7 +61,8 @@ const F32 WAVE_STEP_INV	= (1. / WAVE_STEP);  LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -:	LLStaticViewerObject(id, LL_VO_WATER, regionp) +:	LLStaticViewerObject(id, pcode, regionp), +	mRenderType(LLPipeline::RENDER_TYPE_WATER)  {  	// Terrain must draw during selection passes so it can block objects behind it.  	mbCanSelect = FALSE; @@ -114,7 +115,7 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)  {  	pipeline->allocDrawable(this);  	mDrawable->setLit(FALSE); -	mDrawable->setRenderType(LLPipeline::RENDER_TYPE_WATER); +	mDrawable->setRenderType(mRenderType);  	LLDrawPoolWater *pool = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); @@ -268,6 +269,11 @@ U32 LLVOWater::getPartitionType() const  	return LLViewerRegion::PARTITION_WATER;   } +U32 LLVOVoidWater::getPartitionType() const +{ +	return LLViewerRegion::PARTITION_VOIDWATER; +} +  LLWaterPartition::LLWaterPartition()  : LLSpatialPartition(0, FALSE, 0)  { @@ -275,3 +281,9 @@ LLWaterPartition::LLWaterPartition()  	mDrawableType = LLPipeline::RENDER_TYPE_WATER;  	mPartitionType = LLViewerRegion::PARTITION_WATER;  } + +LLVoidWaterPartition::LLVoidWaterPartition() +{ +	mDrawableType = LLPipeline::RENDER_TYPE_VOIDWATER; +	mPartitionType = LLViewerRegion::PARTITION_VOIDWATER; +} diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h index beefc3f17f..cb9584cabf 100644 --- a/indra/newview/llvowater.h +++ b/indra/newview/llvowater.h @@ -29,6 +29,7 @@  #include "llviewerobject.h"  #include "llviewertexture.h" +#include "pipeline.h"  #include "v2math.h"  const U32 N_RES	= 16; //32			// number of subdivisions of wave tile @@ -77,6 +78,19 @@ public:  protected:  	BOOL mUseTexture;  	BOOL mIsEdgePatch; +	S32  mRenderType;   }; +class LLVOVoidWater : public LLVOWater +{ +public: +	LLVOVoidWater(LLUUID const& id, LLPCode pcode, LLViewerRegion* regionp) : LLVOWater(id, pcode, regionp) +	{ +		mRenderType = LLPipeline::RENDER_TYPE_VOIDWATER; +	} + +	/*virtual*/ U32 getPartitionType() const; +}; + +  #endif // LL_VOSURFACEPATCH_H diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 5760d04a08..8731c9e1a7 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -55,6 +55,11 @@  #include "pipeline.h"  #include "llappviewer.h"		// for do_disconnect() +#include <deque> +#include <queue> +#include <map> +#include <cstring> +  //  // Globals  // @@ -834,10 +839,69 @@ F32 LLWorld::getLandFarClip() const  void LLWorld::setLandFarClip(const F32 far_clip)  { +	static S32 const rwidth = (S32)REGION_WIDTH_U32; +	S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth; +	S32 const n2 = (llceil(far_clip) - 1) / rwidth; +	bool need_water_objects_update = n1 != n2; +  	mLandFarClip = far_clip; + +	if (need_water_objects_update) +	{ +		updateWaterObjects(); +	}  } +// Some region that we're connected to, but not the one we're in, gave us +// a (possibly) new water height. Update it in our local copy. +void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height) +{ +	for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter) +	{ +		if ((*iter)->getName() == sim_name) +		{ +			(*iter)->setWaterHeight(water_height); +			break; +		} +	} +} +// There are three types of water objects: +// Region water objects: the water in a region. +// Hole water objects: water in the void but within current draw distance. +// Edge water objects: the water outside the draw distance, up till the horizon. +// +// For example: +// +// -----------------------horizon------------------------- +// |                 |                 |                 | +// |  Edge Water     |                 |                 | +// |                 |                 |                 | +// |                 |                 |                 | +// |                 |                 |                 | +// |                 |                 |                 | +// |                 |      rwidth     |                 | +// |                 |     <----->     |                 | +// ------------------------------------------------------- +// |                 |Hole |other|     |                 | +// |                 |Water|reg. |     |                 | +// |                 |-----------------|                 | +// |                 |other|cur. |<--> |                 | +// |                 |reg. | reg.|  \__|_ draw distance  | +// |                 |-----------------|                 | +// |                 |     |     |<--->|                 | +// |                 |     |     |  \__|_ range          | +// ------------------------------------------------------- +// |                 |<----width------>|<--horizon ext.->| +// |                 |                 |                 | +// |                 |                 |                 | +// |                 |                 |                 | +// |                 |                 |                 | +// |                 |                 |                 | +// |                 |                 |                 | +// |                 |                 |                 | +// ------------------------------------------------------- +//  void LLWorld::updateWaterObjects()  {  	if (!gAgent.getRegion()) @@ -850,128 +914,265 @@ void LLWorld::updateWaterObjects()  		return;  	} -	// First, determine the min and max "box" of water objects -	S32 min_x = 0; -	S32 min_y = 0; -	S32 max_x = 0; -	S32 max_y = 0; +	// Region width in meters. +	S32 const rwidth = (S32)REGION_WIDTH_U32; + +	// The distance we might see into the void +	// when standing on the edge of a region, in meters. +	S32 const draw_distance = llceil(mLandFarClip); + +	// We can only have "holes" in the water (where there no region) if we +	// can have existing regions around it. Taking into account that this +	// code is only executed when we enter a region, and not when we walk +	// around in it, we (only) need to take into account regions that fall +	// within the draw_distance. +	// +	// Set 'range' to draw_distance, rounded up to the nearest multiple of rwidth. +	S32 const nsims = (draw_distance + rwidth - 1) / rwidth; +	S32 const range = nsims * rwidth; + +	// Get South-West corner of current region. +	LLViewerRegion const* regionp = gAgent.getRegion();  	U32 region_x, region_y; - -	S32 rwidth = 256; - -	// We only want to fill in water for stuff that's near us, say, within 256 or 512m -	S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256; - -	LLViewerRegion* regionp = gAgent.getRegion();  	from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); -	min_x = (S32)region_x - range; -	min_y = (S32)region_y - range; -	max_x = (S32)region_x + range; -	max_y = (S32)region_y + range; +	// The min. and max. coordinates of the South-West corners of the Hole water objects. +	S32 const min_x = (S32)region_x - range; +	S32 const min_y = (S32)region_y - range; +	S32 const max_x = (S32)region_x + range; +	S32 const max_y = (S32)region_y + range; + +	// Attempt to determine a sensible water height for all the +	// Hole Water objects. +	// +	// It make little sense to try to guess what the best water +	// height should be when that isn't completely obvious: if it's +	// impossible to satisfy every region's water height without +	// getting a jump in the water height. +	// +	// In order to keep the reasoning simple, we assume something +	// logical as a group of connected regions, where the coastline +	// is at the outer edge. Anything more complex that would "break" +	// under such an assumption would probably break anyway (would +	// depend on terrain editing and existing mega prims, say, if +	// anything would make sense at all). +	// +	// So, what we do is find all connected regions within the +	// draw distance that border void, and then pick the lowest +	// water height of those (coast) regions. +	S32 const n = 2 * nsims + 1; +	S32 const origin = nsims + nsims * n; +	std::vector<F32> water_heights(n * n); +	std::vector<U8> checked(n * n, 0);		// index = nx + ny * n + origin; +	U8 const region_bit = 1; +	U8 const hole_bit = 2; +	U8 const bordering_hole_bit = 4; +	U8 const bordering_edge_bit = 8; +	// Use the legacy waterheight for the Edge water in the case +	// that we don't find any Hole water at all. +	F32 water_height = DEFAULT_WATER_HEIGHT; +	int max_count = 0; +	LL_DEBUGS("WaterHeight") << "Current region: " << regionp->getName() << "; water height: " << regionp->getWaterHeight() << " m." << LL_ENDL; +	std::map<S32, int> water_height_counts; +	typedef std::queue<std::pair<S32, S32>, std::deque<std::pair<S32, S32> > > nxny_pairs_type; +	nxny_pairs_type nxny_pairs; +	nxny_pairs.push(nxny_pairs_type::value_type(0, 0)); +	water_heights[origin] = regionp->getWaterHeight(); +	checked[origin] = region_bit; +	// For debugging purposes. +	int number_of_connected_regions = 1; +	int uninitialized_regions = 0; +	int bordering_hole = 0; +	int bordering_edge = 0; +	while(!nxny_pairs.empty()) +	{ +		S32 const nx = nxny_pairs.front().first; +		S32 const ny = nxny_pairs.front().second; +		LL_DEBUGS("WaterHeight") << "nx,ny = " << nx << "," << ny << LL_ENDL; +		S32 const index = nx + ny * n + origin; +		nxny_pairs.pop(); +		for (S32 dir = 0; dir < 4; ++dir) +		{ +			S32 const cnx = nx + gDirAxes[dir][0]; +			S32 const cny = ny + gDirAxes[dir][1]; +			LL_DEBUGS("WaterHeight") << "dir = " << dir << "; cnx,cny = " << cnx << "," << cny << LL_ENDL; +			S32 const cindex = cnx + cny * n + origin; +			bool is_hole = false; +			bool is_edge = false; +			LLViewerRegion* new_region_found = NULL; +			if (cnx < -nsims || cnx > nsims || +			    cny < -nsims || cny > nsims) +			{ +				LL_DEBUGS("WaterHeight") << "  Edge Water!" << LL_ENDL; +				// Bumped into Edge water object. +				is_edge = true; +			} +			else if (checked[cindex]) +			{ +				LL_DEBUGS("WaterHeight") << "  Already checked before!" << LL_ENDL; +				// Already checked. +				is_hole = (checked[cindex] & hole_bit); +			} +			else +			{ +				S32 x = (S32)region_x + cnx * rwidth; +				S32 y = (S32)region_y + cny * rwidth; +				U64 region_handle = to_region_handle(x, y); +				new_region_found = getRegionFromHandle(region_handle); +				is_hole = !new_region_found; +				checked[cindex] = is_hole ? hole_bit : region_bit; +			} +			if (is_hole) +			{ +				// This was a region that borders at least one 'hole'. +				// Count the found coastline. +				F32 new_water_height = water_heights[index]; +				LL_DEBUGS("WaterHeight") << "  This is void; counting coastline with water height of " << new_water_height << LL_ENDL; +				S32 new_water_height_cm = llround(new_water_height * 100); +				int count = (water_height_counts[new_water_height_cm] += 1); +				// Just use the lowest water height: this is mainly about the horizon water, +				// and whatever we do, we don't want it to be possible to look under the water +				// when looking in the distance: it is better to make a step downwards in water +				// height when going away from the avie than a step upwards. However, since +				// everyone is used to DEFAULT_WATER_HEIGHT, don't allow a single region +				// to drag the water level below DEFAULT_WATER_HEIGHT on it's own. +				if (bordering_hole == 0 ||			// First time we get here. +				    (new_water_height >= DEFAULT_WATER_HEIGHT && +					 new_water_height < water_height) || +				    (new_water_height < DEFAULT_WATER_HEIGHT && +					 count > max_count) +				   ) +				{ +					water_height = new_water_height; +				} +				if (count > max_count) +				{ +					max_count = count; +				} +				if (!(checked[index] & bordering_hole_bit)) +				{ +					checked[index] |= bordering_hole_bit; +					++bordering_hole; +				} +			} +			else if (is_edge && !(checked[index] & bordering_edge_bit)) +			{ +				checked[index] |= bordering_edge_bit; +				++bordering_edge; +			} +			if (!new_region_found) +			{ +				// Dead end, there is no region here. +				continue; +			} +			// Found a new connected region. +			++number_of_connected_regions; +			if (new_region_found->getName().empty()) +			{ +				// Uninitialized LLViewerRegion, don't use it's water height. +				LL_DEBUGS("WaterHeight") << "  Uninitialized region." << LL_ENDL; +				++uninitialized_regions; +				continue; +			} +			nxny_pairs.push(nxny_pairs_type::value_type(cnx, cny)); +			water_heights[cindex] = new_region_found->getWaterHeight(); +			LL_DEBUGS("WaterHeight") << "  Found a new region (name: " << new_region_found->getName() << "; water height: " << water_heights[cindex] << " m)!" << LL_ENDL; +		} +	} +	llinfos << "Number of connected regions: " << number_of_connected_regions << " (" << uninitialized_regions << +		" uninitialized); number of regions bordering Hole water: " << bordering_hole << +		"; number of regions bordering Edge water: " << bordering_edge << llendl; +	llinfos << "Coastline count (height, count): "; +	bool first = true; +	for (std::map<S32, int>::iterator iter = water_height_counts.begin(); iter != water_height_counts.end(); ++iter) +	{ +		if (!first) llcont << ", "; +		llcont << "(" << (iter->first / 100.f) << ", " << iter->second << ")"; +		first = false; +	} +	llcont << llendl; +	llinfos << "Water height used for Hole and Edge water objects: " << water_height << llendl; -	F32 height = 0.f; -	 -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) +	// Update all Region water objects. +	for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)  	{  		LLViewerRegion* regionp = *iter;  		LLVOWater* waterp = regionp->getLand().getWaterObj(); -		height += regionp->getWaterHeight();  		if (waterp)  		{  			gObjectList.updateActive(waterp);  		}  	} +	// Clean up all existing Hole water objects.  	for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin(); -		 iter != mHoleWaterObjects.end(); ++ iter) +		 iter != mHoleWaterObjects.end(); ++iter)  	{  		LLVOWater* waterp = *iter;  		gObjectList.killObject(waterp);  	}  	mHoleWaterObjects.clear(); -	// Now, get a list of the holes -	S32 x, y; -	for (x = min_x; x <= max_x; x += rwidth) +	// Let the Edge and Hole water boxes be 1024 meter high so that they +	// are never too small to be drawn (A LL_VO_*_WATER box has water +	// rendered on it's bottom surface only), and put their bottom at +	// the current regions water height. +	F32 const box_height = 1024; +	F32 const water_center_z = water_height + box_height / 2; + +	// Create new Hole water objects within 'range' where there is no region. +	for (S32 x = min_x; x <= max_x; x += rwidth)  	{ -		for (y = min_y; y <= max_y; y += rwidth) +		for (S32 y = min_y; y <= max_y; y += rwidth)  		{  			U64 region_handle = to_region_handle(x, y);  			if (!getRegionFromHandle(region_handle))  			{ -				LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); +				LLVOWater* waterp = (LLVOWater*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion());  				waterp->setUseTexture(FALSE); -				waterp->setPositionGlobal(LLVector3d(x + rwidth/2, -													 y + rwidth/2, -													 256.f+DEFAULT_WATER_HEIGHT)); -				waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); +				waterp->setPositionGlobal(LLVector3d(x + rwidth / 2, y + rwidth / 2, water_center_z)); +				waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, box_height));  				gPipeline.createObject(waterp);  				mHoleWaterObjects.push_back(waterp);  			}  		}  	} -	// Update edge water objects -	S32 wx, wy; -	S32 center_x, center_y; -	wx = (max_x - min_x) + rwidth; -	wy = (max_y - min_y) + rwidth; -	center_x = min_x + (wx >> 1); -	center_y = min_y + (wy >> 1); - -	S32 add_boundary[4] = { -		512 - (max_x - region_x), -		512 - (max_y - region_y), -		512 - (region_x - min_x), -		512 - (region_y - min_y) }; +	// Center of the region. +	S32 const center_x = region_x + rwidth / 2; +	S32 const center_y = region_y + rwidth / 2; +	// Width of the area with Hole water objects. +	S32 const width = rwidth + 2 * range; +	S32 const horizon_extend = 2048 + 512 - range;	// Legacy value. +	// The overlap is needed to get rid of sky pixels being visible between the +	// Edge and Hole water object at greater distances (due to floating point +	// round off errors). +	S32 const edge_hole_overlap = 1;		// Twice the actual overlap. -	S32 dir; -	for (dir = 0; dir < 8; dir++) +	for (S32 dir = 0; dir < 8; ++dir)  	{ -		S32 dim[2] = { 0 }; -		switch (gDirAxes[dir][0]) -		{ -		case -1: dim[0] = add_boundary[2]; break; -		case  0: dim[0] = wx; break; -		default: dim[0] = add_boundary[0]; break; -		} -		switch (gDirAxes[dir][1]) -		{ -		case -1: dim[1] = add_boundary[3]; break; -		case  0: dim[1] = wy; break; -		default: dim[1] = add_boundary[1]; break; -		} +		// Size of the Edge water objects. +		S32 const dim_x = (gDirAxes[dir][0] == 0) ? width : (horizon_extend + edge_hole_overlap); +		S32 const dim_y = (gDirAxes[dir][1] == 0) ? width : (horizon_extend + edge_hole_overlap); +		// And their position. +		S32 const water_center_x = center_x + (width + horizon_extend) / 2 * gDirAxes[dir][0]; +		S32 const water_center_y = center_y + (width + horizon_extend) / 2 * gDirAxes[dir][1]; -		// Resize and reshape the water objects -		const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]); -		const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]); -		  		LLVOWater* waterp = mEdgeWaterObjects[dir];  		if (!waterp || waterp->isDead())  		{  			// The edge water objects can be dead because they're attached to the region that the  			// agent was in when they were originally created. -			mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, -																				 gAgent.getRegion()); +			mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion());  			waterp = mEdgeWaterObjects[dir];  			waterp->setUseTexture(FALSE); -			waterp->setIsEdgePatch(TRUE); +			waterp->setIsEdgePatch(TRUE);		// Mark that this is edge water and not hole water.  			gPipeline.createObject(waterp);  		}  		waterp->setRegion(gAgent.getRegion()); -		LLVector3d water_pos(water_center_x, water_center_y,  -			DEFAULT_WATER_HEIGHT+256.f); -		LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f); - -		//stretch out to horizon -		water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]); -		water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]); - -		water_pos.mdV[0] += 1024.f * gDirAxes[dir][0]; -		water_pos.mdV[1] += 1024.f * gDirAxes[dir][1]; +		LLVector3d water_pos(water_center_x, water_center_y, water_center_z); +		LLVector3 water_scale((F32) dim_x, (F32) dim_y, box_height);  		waterp->setPositionGlobal(water_pos);  		waterp->setScale(water_scale); diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index 4465fde210..c60dc8dc29 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -137,6 +137,7 @@ public:  	LLViewerTexture *getDefaultWaterTexture();  	void updateWaterObjects(); +	void waterHeightRegionInfo(std::string const& sim_name, F32 water_height);  	void shiftRegions(const LLVector3& offset);  	void setSpaceTimeUSec(const U64 space_time_usec); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1ee3b84b5e..272682710c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -628,14 +628,14 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)  //static  void LLPipeline::updateRenderDeferred()  { -	BOOL deferred = (gSavedSettings.getBOOL("RenderDeferred") &&  -		LLRenderTarget::sUseFBO && -			 LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && -		gSavedSettings.getBOOL("VertexShaderEnable") &&  -		gSavedSettings.getBOOL("RenderAvatarVP") && -			 (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) && -		!gUseWireframe; -	 +	BOOL deferred = ((gSavedSettings.getBOOL("RenderDeferred") &&  +					 LLRenderTarget::sUseFBO && +					 LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && +					 gSavedSettings.getBOOL("VertexShaderEnable") &&  +					 gSavedSettings.getBOOL("RenderAvatarVP") && +					 gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) && +					!gUseWireframe; +  	sRenderDeferred = deferred;			  } @@ -1632,20 +1632,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl  	camera.disableUserClipPlane(); -	if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull()) +	if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) &&  +		gSky.mVOSkyp.notNull() &&  +		gSky.mVOSkyp->mDrawable.notNull())  	{ -		// Hack for sky - always visible. -		if (hasRenderType(LLPipeline::RENDER_TYPE_SKY))  -		{ -			gSky.mVOSkyp->mDrawable->setVisible(camera); -			sCull->pushDrawable(gSky.mVOSkyp->mDrawable); -			gSky.updateCull(); -			stop_glerror(); -		} -	} -	else -	{ -		llinfos << "No sky drawable!" << llendl; +		gSky.mVOSkyp->mDrawable->setVisible(camera); +		sCull->pushDrawable(gSky.mVOSkyp->mDrawable); +		gSky.updateCull(); +		stop_glerror();  	}  	if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) &&  @@ -2214,6 +2208,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)  					  LLPipeline::RENDER_TYPE_TERRAIN,  					  LLPipeline::RENDER_TYPE_TREE,  					  LLPipeline::RENDER_TYPE_SKY, +					  LLPipeline::RENDER_TYPE_VOIDWATER,  					  LLPipeline::RENDER_TYPE_WATER,  					  LLPipeline::END_RENDER_TYPES))  	{ @@ -5005,6 +5000,10 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)  void LLPipeline::toggleRenderType(U32 type)  {  	gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type]; +	if (type == LLPipeline::RENDER_TYPE_WATER) +	{ +		gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER]; +	}  }  //static @@ -7331,6 +7330,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)  				gPipeline.pushRenderTypeMask();  				clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER, +									LLPipeline::RENDER_TYPE_VOIDWATER,  									LLPipeline::RENDER_TYPE_GROUND,  									LLPipeline::RENDER_TYPE_SKY,  									LLPipeline::RENDER_TYPE_CLOUDS, @@ -7383,6 +7383,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)  		{  			camera.setFar(camera_in.getFar());  			clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER, +								LLPipeline::RENDER_TYPE_VOIDWATER,  								LLPipeline::RENDER_TYPE_GROUND,  								END_RENDER_TYPES);	  			stop_glerror(); @@ -7899,6 +7900,7 @@ void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<L  								 LLPipeline::RENDER_TYPE_TREE,   								 LLPipeline::RENDER_TYPE_TERRAIN,  								 LLPipeline::RENDER_TYPE_WATER, +								 LLPipeline::RENDER_TYPE_VOIDWATER,  								 LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,  								 LLPipeline::RENDER_TYPE_AVATAR,  								 LLPipeline::RENDER_TYPE_PASS_SIMPLE, @@ -8082,6 +8084,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)  					LLPipeline::RENDER_TYPE_TREE,   					LLPipeline::RENDER_TYPE_TERRAIN,  					LLPipeline::RENDER_TYPE_WATER, +					LLPipeline::RENDER_TYPE_VOIDWATER,  					LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,  					LLPipeline::RENDER_TYPE_PASS_SIMPLE,  					LLPipeline::RENDER_TYPE_PASS_BUMP, diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index fe0683d29f..74e1cf6d7e 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -358,6 +358,7 @@ public:  		RENDER_TYPE_AVATAR						= LLDrawPool::POOL_AVATAR,  		RENDER_TYPE_TREE						= LLDrawPool::POOL_TREE,  		RENDER_TYPE_INVISIBLE					= LLDrawPool::POOL_INVISIBLE, +		RENDER_TYPE_VOIDWATER					= LLDrawPool::POOL_VOIDWATER,  		RENDER_TYPE_WATER						= LLDrawPool::POOL_WATER,   		RENDER_TYPE_ALPHA						= LLDrawPool::POOL_ALPHA,  		RENDER_TYPE_GLOW						= LLDrawPool::POOL_GLOW, | 
