コード例 #1
0
LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b)
{
	// Operate "to the left" on row-vector a
	return LLVector4(a.mV[VX] * b.mMatrix[VX][VX] + 
					 a.mV[VY] * b.mMatrix[VY][VX] + 
					 a.mV[VZ] * b.mMatrix[VZ][VX] +
					 a.mV[VW] * b.mMatrix[VW][VX],

					 a.mV[VX] * b.mMatrix[VX][VY] + 
					 a.mV[VY] * b.mMatrix[VY][VY] + 
					 a.mV[VZ] * b.mMatrix[VZ][VY] +
					 a.mV[VW] * b.mMatrix[VW][VY],

					 a.mV[VX] * b.mMatrix[VX][VZ] + 
					 a.mV[VY] * b.mMatrix[VY][VZ] + 
					 a.mV[VZ] * b.mMatrix[VZ][VZ] +
					 a.mV[VW] * b.mMatrix[VW][VZ],

					 a.mV[VX] * b.mMatrix[VX][VW] + 
					 a.mV[VY] * b.mMatrix[VY][VW] + 
					 a.mV[VZ] * b.mMatrix[VZ][VW] +
					 a.mV[VW] * b.mMatrix[VW][VW]);
}
コード例 #2
0
void LLWLParamManager::propagateParameters(void)
{
	LLFastTimer ftm(FTM_UPDATE_WLPARAM);
	
	LLVector4 sunDir;
	LLVector4 moonDir;

	// set the sun direction from SunAngle and EastAngle
	F32 sinTheta = sin(mCurParams.getEastAngle());
	F32 cosTheta = cos(mCurParams.getEastAngle());

	F32 sinPhi = sin(mCurParams.getSunAngle());
	F32 cosPhi = cos(mCurParams.getSunAngle());

	sunDir.mV[0] = -sinTheta * cosPhi;
	sunDir.mV[1] = sinPhi;
	sunDir.mV[2] = cosTheta * cosPhi;
	sunDir.mV[3] = 0;

	moonDir = -sunDir;

	// is the normal from the sun or the moon
	if(sunDir.mV[1] >= 0)
	{
		mLightDir = sunDir;
	}
	else if(sunDir.mV[1] < 0 && sunDir.mV[1] > LLSky::NIGHTTIME_ELEVATION_COS)
	{
		// clamp v1 to 0 so sun never points up and causes weirdness on some machines
		LLVector3 vec(sunDir.mV[0], sunDir.mV[1], sunDir.mV[2]);
		vec.mV[1] = 0;
		vec.normVec();
		mLightDir = LLVector4(vec, 0.f);
	}
	else
	{
		mLightDir = moonDir;
	}

	// calculate the clamp lightnorm for sky (to prevent ugly banding in sky
	// when haze goes below the horizon
	mClampedLightDir = sunDir;

	if (mClampedLightDir.mV[1] < -0.1f)
	{
		mClampedLightDir.mV[1] = -0.1f;
	}

	mCurParams.set("lightnorm", mLightDir);

	// bind the variables for all shaders only if we're using WindLight
	std::vector<LLGLSLShader*>::iterator shaders_iter=mShaderList.begin();
	for(; shaders_iter != mShaderList.end(); ++shaders_iter)
	{
		(*shaders_iter)->mUniformsDirty = TRUE;
	}

	// get the cfr version of the sun's direction
	LLVector3 cfrSunDir(sunDir.mV[2], sunDir.mV[0], sunDir.mV[1]);

	// set direction and don't allow overriding
	gSky.setSunDirection(cfrSunDir, LLVector3(0,0,0));
	gSky.setOverrideSun(TRUE);
}
コード例 #3
0
//-----------------------------------------------------------------------------
// apply()
//-----------------------------------------------------------------------------
void LLPolyMorphTarget::apply( ESex avatar_sex )
{
	if (!mMorphData || mNumMorphMasksPending > 0)
	{
		return;
	}

	mLastSex = avatar_sex;

	// Check for NaN condition (NaN is detected if a variable doesn't equal itself.
	if (mCurWeight != mCurWeight)
	{
		mCurWeight = 0.0;
	}
	if (mLastWeight != mLastWeight)
	{
		mLastWeight = mCurWeight+.001;
	}

	// perform differential update of morph
	F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight);
	// store last weight
	mLastWeight += delta_weight;

	if (delta_weight != 0.f)
	{
		llassert(!mMesh->isLOD());
		LLVector4 *coords = mMesh->getWritableCoords();

		LLVector3 *scaled_normals = mMesh->getScaledNormals();
		LLVector4 *normals = mMesh->getWritableNormals();

		LLVector3 *scaled_binormals = mMesh->getScaledBinormals();
		LLVector3 *binormals = mMesh->getWritableBinormals();

		LLVector4 *clothing_weights = mMesh->getWritableClothingWeights();
		LLVector2 *tex_coords = mMesh->getWritableTexCoords();

		F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL;

		for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++)
		{
			S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph];

			F32 maskWeight = 1.f;
			if (maskWeightArray)
			{
				maskWeight = maskWeightArray[vert_index_morph];
			}

			coords[vert_index_mesh] += LLVector4(mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight);

			if (getInfo()->mIsClothingMorph && clothing_weights)
			{
				LLVector3 clothing_offset = mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight;
				LLVector4* clothing_weight = &clothing_weights[vert_index_mesh];
				clothing_weight->mV[VX] += clothing_offset.mV[VX];
				clothing_weight->mV[VY] += clothing_offset.mV[VY];
				clothing_weight->mV[VZ] += clothing_offset.mV[VZ];
				clothing_weight->mV[VW] = maskWeight;
			}

			// calculate new normals based on half angles
			scaled_normals[vert_index_mesh] += mMorphData->mNormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR;
			LLVector3 normalized_normal = scaled_normals[vert_index_mesh];
			normalized_normal.normVec();
			normals[vert_index_mesh] = LLVector4(normalized_normal);

			// calculate new binormals
			scaled_binormals[vert_index_mesh] += mMorphData->mBinormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR;
			LLVector3 tangent = scaled_binormals[vert_index_mesh] % normalized_normal;
			LLVector3 normalized_binormal = normalized_normal % tangent; 
			normalized_binormal.normVec();
			binormals[vert_index_mesh] = normalized_binormal;

			tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight;
		}

		// now apply volume changes
		for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ )
		{
			LLPolyVolumeMorph* volume_morph = &(*iter);
			LLVector3 scale_delta = volume_morph->mScale * delta_weight;
			LLVector3 pos_delta = volume_morph->mPos * delta_weight;
			
			volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta);
			volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta);
		}
	}

	if (mNext)
	{
		mNext->apply(avatar_sex);
	}
}
コード例 #4
0
void LLWLParamManager::propagateParameters(void)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
	
	LLVector4 sunDir;
	LLVector4 moonDir;

	// set the sun direction from SunAngle and EastAngle
	F32 sinTheta = sin(mCurParams.getEastAngle());
	F32 cosTheta = cos(mCurParams.getEastAngle());

	F32 sinPhi = sin(mCurParams.getSunAngle());
	F32 cosPhi = cos(mCurParams.getSunAngle());

	sunDir.mV[0] = -sinTheta * cosPhi;
	sunDir.mV[1] = sinPhi;
	sunDir.mV[2] = cosTheta * cosPhi;
	sunDir.mV[3] = 0;

	moonDir = -sunDir;

	// is the normal from the sun or the moon
	if(sunDir.mV[1] >= 0)
	{
		mLightDir = sunDir;
	}
	else if(sunDir.mV[1] < 0 && sunDir.mV[1] > NIGHTTIME_ELEVATION_COS)
	{
		// clamp v1 to 0 so sun never points up and causes weirdness on some machines
		LLVector3 vec(sunDir.mV[0], sunDir.mV[1], sunDir.mV[2]);
		vec.mV[1] = 0;
		vec.normVec();
		mLightDir = LLVector4(vec, 0.f);
	}
	else
	{
		mLightDir = moonDir;
	}

	// calculate the clamp lightnorm for sky (to prevent ugly banding in sky
	// when haze goes below the horizon
	mClampedLightDir = sunDir;

	if (mClampedLightDir.mV[1] < -0.1f)
	{
		mClampedLightDir.mV[1] = -0.1f;
	}

	mCurParams.set("lightnorm", mLightDir);

	// bind the variables for all shaders only if we're using WindLight
	LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
	end_shaders = LLViewerShaderMgr::instance()->endShaders();
	for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) 
	{
		if (shaders_iter->mProgramObject != 0
			&& (gPipeline.canUseWindLightShaders()
				|| shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
		{
			shaders_iter->mUniformsDirty = TRUE;
		}
	}

	// get the cfr version of the sun's direction
	LLVector3 cfrSunDir(sunDir.mV[2], sunDir.mV[0], sunDir.mV[1]);

	// set direction and don't allow overriding
	gSky.setSunDirection(cfrSunDir, LLVector3(0,0,0));
	gSky.setOverrideSun(TRUE);
}
コード例 #5
0
BOOL QToolAlign::findSelectedManipulator(S32 x, S32 y)
{
	mHighlightedAxis = -1;
	mHighlightedDirection = 0;

	LLMatrix4 transform;
	if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD)
	{
		LLVector4 translation(mBBox.getCenterAgent());
		transform.initRotTrans(mBBox.getRotation(), translation);
		LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
		transform *= cfr;
		LLMatrix4 window_scale;
		F32 zoom_level = 2.f * gAgentCamera.mHUDCurZoom;
		window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f),
							 LLQuaternion::DEFAULT,
							 LLVector3::zero);
		transform *= window_scale;
	}
	else
	{
		transform.initAll(LLVector3(1.f, 1.f, 1.f), mBBox.getRotation(), mBBox.getCenterAgent());

		LLMatrix4 projection_matrix = LLViewerCamera::getInstance()->getProjection();
		LLMatrix4 model_matrix = LLViewerCamera::getInstance()->getModelview();

		transform *= model_matrix;
		transform *= projection_matrix;
	}


	LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled();
	F32 half_width = (F32)world_view_rect.getWidth() / 2.f;
	F32 half_height = (F32)world_view_rect.getHeight() / 2.f;
	LLVector2 manip2d;
	LLVector2 mousePos((F32)x - half_width, (F32)y - half_height);
	LLVector2 delta;

	LLVector3 bbox_scale = mBBox.getMaxLocal() - mBBox.getMinLocal();
	
	for (S32 axis = VX; axis <= VZ; axis++)
	{
		for (F32 direction = -1.0; direction <= 1.0; direction += 2.0)
		{
			LLVector3 axis_vector = LLVector3(0,0,0);
			axis_vector.mV[axis] = direction * bbox_scale.mV[axis] / 2.0;
			
			LLVector4 manipulator_center = 	LLVector4(axis_vector);

			LLVector4 screen_center = manipulator_center * transform;
			screen_center /= screen_center.mV[VW];

			manip2d.setVec(screen_center.mV[VX] * half_width, screen_center.mV[VY] * half_height);

			delta = manip2d - mousePos;

			if (delta.magVecSquared() < MANIPULATOR_SELECT_SIZE * MANIPULATOR_SELECT_SIZE)
			{
				mHighlightedAxis = axis;
				mHighlightedDirection = direction;
				return TRUE;
			}

		}
	}

	return FALSE;
}
コード例 #6
0
//static
void LLDrawPoolBump::beginShiny(bool invisible)
{
	LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY);
	if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| 
		invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
	{
		return;
	}

	mShiny = TRUE;
	sVertexMask = VERTEX_MASK_SHINY;
	// Second pass: environment map
	if (!invisible && mVertexShaderLevel > 1)
	{
		sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
	}
	
	if (LLPipeline::sUnderWaterRender)
	{
		shader = &gObjectShinyWaterProgram;
	}
	else
	{
		shader = &gObjectShinyProgram;
	}

	LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
	if( cube_map )
	{
		if (!invisible && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0 )
		{
			LLMatrix4 mat;
			mat.initRows(LLVector4(gGLModelView+0),
						 LLVector4(gGLModelView+4),
						 LLVector4(gGLModelView+8),
						 LLVector4(gGLModelView+12));
			shader->bind();
			LLVector3 vec = LLVector3(gShinyOrigin) * mat;
			LLVector4 vec4(vec, gShinyOrigin.mV[3]);
			shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);			
			if (mVertexShaderLevel > 1)
			{
				cube_map->setMatrix(1);
				// Make sure that texture coord generation happens for tex unit 1, as that's the one we use for 
				// the cube map in the one pass shiny shaders
				cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
				cube_map->enableTexture(cube_channel);
				cube_map->enableTextureCoords(1);
				diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
			}
			else
			{
				cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
				diffuse_channel = -1;
				cube_map->setMatrix(0);
				cube_map->enable(cube_channel);
			}			
			gGL.getTexUnit(cube_channel)->bind(cube_map);
			gGL.getTexUnit(0)->activate();
		}
		else
		{
			cube_channel = 0;
			diffuse_channel = -1;
			gGL.getTexUnit(0)->disable();
			cube_map->enable(0);
			cube_map->setMatrix(0);
			gGL.getTexUnit(0)->bind(cube_map);

			gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
			gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_ALPHA);
		}
	}
}
コード例 #7
0
ファイル: llvotree.cpp プロジェクト: HazimGazov/Sausages
void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices, 
								 LLStrider<LLVector3>& normals, 
								 LLStrider<LLVector2>& tex_coords, 
								 LLStrider<U16>& indices,
								 U16& index_offset,
								 LLMatrix4& matrix, 
								 S32 trunk_LOD, 
								 S32 stop_level, 
								 U16 depth, 
								 U16 trunk_depth,  
								 F32 scale, 
								 F32 twist, 
								 F32 droop,  
								 F32 branches, 
								 F32 alpha)
{
	//
	//  Generates a tree mesh by recursing, generating branches and then a 'leaf' texture.
	
	static F32 constant_twist;
	static F32 width = 0;

	F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength);
	F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect);
	
	constant_twist = 360.f/branches;

	if (stop_level >= 0)
	{
		if (depth > stop_level)
		{
			{
				llassert(sLODIndexCount[trunk_LOD] > 0);
				width = scale * length * aspect;
				LLMatrix4 scale_mat;
				scale_mat.mMatrix[0][0] = width;
				scale_mat.mMatrix[1][1] = width;
				scale_mat.mMatrix[2][2] = scale*length;
				scale_mat *= matrix;

				glh::matrix4f norm((F32*) scale_mat.mMatrix);
				LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m);

				norm_mat.invert();
				appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, 
							sLODVertexOffset[trunk_LOD], sLODVertexCount[trunk_LOD], sLODIndexCount[trunk_LOD], sLODIndexOffset[trunk_LOD]);
			}
			
			// Recurse to create more branches
			for (S32 i=0; i < (S32)branches; i++) 
			{
				LLMatrix4 trans_mat;
				trans_mat.setTranslation(0,0,scale*length);
				trans_mat *= matrix;

				LLQuaternion rot = 
					LLQuaternion(20.f*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)) *
					LLQuaternion(droop*DEG_TO_RAD, LLVector4(0.f, 1.f, 0.f)) *
					LLQuaternion(((constant_twist + ((i%2==0)?twist:-twist))*i)*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f));
				
				LLMatrix4 rot_mat(rot);
				rot_mat *= trans_mat;

				genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
			}
			//  Recurse to continue trunk
			if (trunk_depth)
			{
				LLMatrix4 trans_mat;
				trans_mat.setTranslation(0,0,scale*length);
				trans_mat *= matrix;

				LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1));
				rot_mat *= trans_mat; // rotate a bit around Z when ascending 
				genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
			}
		}
		else
		{
			//
			//  Append leaves as two 90 deg crossed quads with leaf textures
			//
			{
				LLMatrix4 scale_mat;
				scale_mat.mMatrix[0][0] = 
					scale_mat.mMatrix[1][1] =
					scale_mat.mMatrix[2][2] = scale*mLeafScale;

				scale_mat *= matrix;

				glh::matrix4f norm((F32*) scale_mat.mMatrix);
				LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m);

				appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, 0, LEAF_VERTICES, LEAF_INDICES, 0);	
			}
		}
	}
}
コード例 #8
0
//-----------------------------------------------------------------------------
// setMorphFromMesh()
//-----------------------------------------------------------------------------
BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph)
{
	if (!morph)
		return FALSE;

	LLVector4 *morph_coords     = morph->getWritableCoords();
	LLVector4 *morph_normals    = morph->getWritableNormals();
	LLVector3 *morph_binormals  = morph->getWritableBinormals();
	LLVector2 *morph_tex_coords = morph->getWritableTexCoords();

	// We now have the morph loaded as a mesh.  We have to subtract the
	// base mesh to get the delta morph.

	LLPolyMesh delta(mMesh, NULL);
	U32 nverts = delta.getNumVertices();

	LLVector4 *delta_coords     = delta.getWritableCoords();
	LLVector4 *delta_normals    = delta.getWritableNormals();
	LLVector3 *delta_binormals  = delta.getWritableBinormals();
	LLVector2 *delta_tex_coords = delta.getWritableTexCoords();

	U32 num_significant = 0;
	U32 vert_index;
	for( vert_index = 0; vert_index < nverts; vert_index++)
	{
		delta_coords[vert_index]     = morph_coords[vert_index] - delta_coords[vert_index];
		delta_normals[vert_index]    = morph_normals[vert_index] - delta_normals[vert_index];
		delta_binormals[vert_index]  = morph_binormals[vert_index] - delta_binormals[vert_index];
		delta_tex_coords[vert_index] = morph_tex_coords[vert_index] - delta_tex_coords[vert_index];

		// For the normals and binormals, we really want the deltas
		// to be perpendicular to the mesh (bi)normals in the plane
		// that contains both the mesh and morph (bi)normals, such
		// that the morph (bi)normals form the hypotenuses of right
		// triangles. Right now, we just compute the difference vector.

		if (delta_coords[vert_index].length()     > SIGNIFICANT_DELTA
		||  delta_normals[vert_index].length()    > SIGNIFICANT_DELTA
		||  delta_binormals[vert_index].length()  > SIGNIFICANT_DELTA
		||  delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA)
		{
			num_significant++;
		}
	}

	//-------------------------------------------------------------------------
	// compute new morph
	//-------------------------------------------------------------------------

	// If the morph matches the base mesh, we store one vertex to prevent
	// zero length vectors.

	U32 nindices = num_significant;
	if (num_significant == 0)
		nindices = 1;

	LLVector3* new_coords     = new LLVector3[nindices];
	LLVector3* new_normals    = new LLVector3[nindices];
	LLVector3* new_binormals  = new LLVector3[nindices];
	LLVector2* new_tex_coords = new LLVector2[nindices];
	U32* new_vertex_indices   = new U32[nindices];

    // We'll set the distortion directly
	mTotalDistortion = 0.f;
	mMaxDistortion   = 0.f;
	mAvgDistortion.zeroVec();

	U32 morph_index = 0;
	for( vert_index = 0; vert_index < nverts; vert_index++)
	{
		if (delta_coords[vert_index].length()     > SIGNIFICANT_DELTA
		||  delta_normals[vert_index].length()    > SIGNIFICANT_DELTA
		||  delta_binormals[vert_index].length()  > SIGNIFICANT_DELTA
		||  delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA
		||  num_significant == 0)
		{
			new_vertex_indices[morph_index] = vert_index;

			new_coords[morph_index]     = LLVector3(delta_coords[vert_index]);
			new_normals[morph_index]    = LLVector3(delta_normals[vert_index]);
			new_binormals[morph_index]  = delta_binormals[vert_index];
			new_tex_coords[morph_index] = delta_tex_coords[vert_index];

			F32 magnitude = new_coords[morph_index].magVec();

			mTotalDistortion += magnitude;
			mAvgDistortion.mV[VX] += fabs(new_coords[morph_index].mV[VX]);
			mAvgDistortion.mV[VY] += fabs(new_coords[morph_index].mV[VY]);
			mAvgDistortion.mV[VZ] += fabs(new_coords[morph_index].mV[VZ]);

			if (magnitude > mMaxDistortion)
			{
				mMaxDistortion = magnitude;
			}

			morph_index++;
			num_significant = 1;
		}
	}

	mAvgDistortion = mAvgDistortion * (1.f/(F32)nindices);
	mAvgDistortion.normVec();

	//-------------------------------------------------------------------------
	// compute the change in the morph
	//-------------------------------------------------------------------------

	// Because meshes are set by continually updating morph weights
	// there is no easy way to reapply the morphs, so we just compute
	// the change in this morph and apply that appropriately weighted.

	for( morph_index = 0; morph_index < mNumIndices; morph_index++)
	{
		vert_index = mVertexIndices[morph_index];

		delta_coords[vert_index]     -= LLVector4(mCoords[morph_index]);
		delta_normals[vert_index]    -= LLVector4(mNormals[morph_index]);
		delta_binormals[vert_index]  -= mBinormals[morph_index];
		delta_tex_coords[vert_index] -= mTexCoords[morph_index];
	}

	//-------------------------------------------------------------------------
	// Update all avatars
	//-------------------------------------------------------------------------

	std::vector< LLCharacter* >::iterator avatar_it;
	for(avatar_it = LLCharacter::sInstances.begin(); avatar_it != LLCharacter::sInstances.end(); ++avatar_it)
	{
		LLVOAvatar* avatarp = (LLVOAvatar*)*avatar_it;

		LLPolyMorphTarget* param = (LLPolyMorphTarget*) avatarp->getVisualParam(mName.c_str());
		if (!param)
		{
			continue;
		}

		F32 weight = param->getLastWeight();
		if (weight == 0.0f)
		{
			continue;
		}

		LLPolyMesh* mesh = avatarp->getMesh(mMesh);
		if (!mesh)
		{
			continue;
		}

		// If we have a vertex mask, just remove it.  It will be recreated.
		/*if (param->undoMask(TRUE))
		{
			continue;
		}*/

		LLVector4 *mesh_coords           = mesh->getWritableCoords();
		LLVector4 *mesh_normals          = mesh->getWritableNormals();
		LLVector3 *mesh_binormals        = mesh->getWritableBinormals();
		LLVector2 *mesh_tex_coords       = mesh->getWritableTexCoords();
		LLVector3 *mesh_scaled_normals   = mesh->getScaledNormals();
		LLVector3 *mesh_scaled_binormals = mesh->getScaledBinormals();

		for( vert_index = 0; vert_index < nverts; vert_index++)
		{
			mesh_coords[vert_index]           += delta_coords[vert_index] * weight;
			mesh_tex_coords[vert_index]       += delta_tex_coords[vert_index] * weight;

			mesh_scaled_normals[vert_index]   += LLVector3(delta_normals[vert_index] * weight * NORMAL_SOFTEN_FACTOR);
			LLVector3 normalized_normal        = mesh_scaled_normals[vert_index];
			normalized_normal.normVec();
			mesh_normals[vert_index]           = LLVector4(normalized_normal);

			mesh_scaled_binormals[vert_index] += delta_binormals[vert_index] * weight * NORMAL_SOFTEN_FACTOR;
			LLVector3 tangent                  = mesh_scaled_binormals[vert_index] % normalized_normal;
			LLVector3 normalized_binormal      = normalized_normal % tangent;
			normalized_binormal.normVec();
			mesh_binormals[vert_index]         = normalized_binormal;
		}

		avatarp->dirtyMesh();
	}

	//-------------------------------------------------------------------------
	// reallocate vertices
	//-------------------------------------------------------------------------
	delete [] mVertexIndices;
	delete [] mCoords;
	delete [] mNormals;
	delete [] mBinormals;
	delete [] mTexCoords;

	mVertexIndices = new_vertex_indices;
	mCoords        = new_coords;
	mNormals       = new_normals;
	mBinormals     = new_binormals;
	mTexCoords     = new_tex_coords;
	mNumIndices    = nindices;

	return TRUE;
}
コード例 #9
0
ファイル: llvotree.cpp プロジェクト: HazimGazov/Sausages
U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth,  F32 scale, F32 twist, F32 droop,  F32 branches, F32 alpha)
{
	U32 ret = 0;
	//
	//  Draws a tree by recursing, drawing branches and then a 'leaf' texture.
	//  If stop_level = -1, simply draws the whole tree as a billboarded texture
	//
	
	static F32 constant_twist;
	static F32 width = 0;

	//F32 length = ((scale == 1.f)? mTrunkLength:mBranchLength);
	//F32 aspect = ((scale == 1.f)? mTrunkAspect:mBranchAspect);
	F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength);
	F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect);
	
	constant_twist = 360.f/branches;

	if (!LLPipeline::sReflectionRender && stop_level >= 0)
	{
		//
		//  Draw the tree using recursion
		//
		if (depth > stop_level)
		{
			{
				llassert(sLODIndexCount[trunk_LOD] > 0);
				width = scale * length * aspect;
				LLMatrix4 scale_mat;
				scale_mat.mMatrix[0][0] = width;
				scale_mat.mMatrix[1][1] = width;
				scale_mat.mMatrix[2][2] = scale*length;
				scale_mat *= matrix;

				glLoadMatrixf((F32*) scale_mat.mMatrix);
 				glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_SHORT, indicesp + sLODIndexOffset[trunk_LOD]);
				gPipeline.addTrianglesDrawn(LEAF_INDICES/3);
				stop_glerror();
				ret += sLODIndexCount[trunk_LOD];
			}
			
			// Recurse to create more branches
			for (S32 i=0; i < (S32)branches; i++) 
			{
				LLMatrix4 trans_mat;
				trans_mat.setTranslation(0,0,scale*length);
				trans_mat *= matrix;

				LLQuaternion rot = 
					LLQuaternion(20.f*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)) *
					LLQuaternion(droop*DEG_TO_RAD, LLVector4(0.f, 1.f, 0.f)) *
					LLQuaternion(((constant_twist + ((i%2==0)?twist:-twist))*i)*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f));
				
				LLMatrix4 rot_mat(rot);
				rot_mat *= trans_mat;

				ret += drawBranchPipeline(rot_mat, indicesp, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
			}
			//  Recurse to continue trunk
			if (trunk_depth)
			{
				LLMatrix4 trans_mat;
				trans_mat.setTranslation(0,0,scale*length);
				trans_mat *= matrix;

				LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1));
				rot_mat *= trans_mat; // rotate a bit around Z when ascending 
				ret += drawBranchPipeline(rot_mat, indicesp, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
			}
		}
		else
		{
			//
			//  Draw leaves as two 90 deg crossed quads with leaf textures
			//
			{
				LLMatrix4 scale_mat;
				scale_mat.mMatrix[0][0] = 
					scale_mat.mMatrix[1][1] =
					scale_mat.mMatrix[2][2] = scale*mLeafScale;

				scale_mat *= matrix;

			
				glLoadMatrixf((F32*) scale_mat.mMatrix);
				glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp);
				gPipeline.addTrianglesDrawn(LEAF_INDICES/3);							
				stop_glerror();
				ret += LEAF_INDICES;
			}
		}
	}
	else
	{
		//
		//  Draw the tree as a single billboard texture 
		//

		LLMatrix4 scale_mat;
		scale_mat.mMatrix[0][0] = 
			scale_mat.mMatrix[1][1] =
			scale_mat.mMatrix[2][2] = mBillboardScale*mBillboardRatio;

		scale_mat *= matrix;
	
		glMatrixMode(GL_TEXTURE);
		glTranslatef(0.0, -0.5, 0.0);
		glMatrixMode(GL_MODELVIEW);
					
		glLoadMatrixf((F32*) scale_mat.mMatrix);
		glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp);
		gPipeline.addTrianglesDrawn(LEAF_INDICES/3);
		stop_glerror();
		ret += LEAF_INDICES;

		glMatrixMode(GL_TEXTURE);
		glLoadIdentity();
		glMatrixMode(GL_MODELVIEW);
	}

	return ret;
}
コード例 #10
0
void LLWaterParamManager::update(LLViewerCamera * cam)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
	
	// update the shaders and the menu
	propagateParameters();
	
	// sync menus if they exist
	if(LLFloaterWater::isOpen()) 
	{
		LLFloaterWater::instance()->syncMenu();
	}

	stop_glerror();

	// only do this if we're dealing with shaders
	if(gPipeline.canUseVertexShaders()) 
	{
		//transform water plane to eye space
		glh::vec3f norm(0.f, 0.f, 1.f);
		glh::vec3f p(0.f, 0.f, gAgent.getRegion()->getWaterHeight()+0.1f);
		
		F32 modelView[16];
		for (U32 i = 0; i < 16; i++)
		{
			modelView[i] = (F32) gGLModelView[i];
		}

		glh::matrix4f mat(modelView);
		glh::matrix4f invtrans = mat.inverse().transpose();
		glh::vec3f enorm;
		glh::vec3f ep;
		invtrans.mult_matrix_vec(norm, enorm);
		enorm.normalize();
		mat.mult_matrix_vec(p, ep);

		mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));

		LLVector3 sunMoonDir;
		if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS) 	 
		{ 	 
			sunMoonDir = gSky.getSunDirection(); 	 
		} 	 
		else  	 
		{ 	 
			sunMoonDir = gSky.getMoonDirection(); 	 
		}
		sunMoonDir.normVec();
		mWaterFogKS = 1.f/llmax(sunMoonDir.mV[2], WATER_FOG_LIGHT_CLAMP);

		LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
		end_shaders = LLViewerShaderMgr::instance()->endShaders();
		for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
		{
			if (shaders_iter->mProgramObject != 0
				&& shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
			{
				shaders_iter->mUniformsDirty = TRUE;
			}
		}
	}
}
コード例 #11
0
ファイル: v4math.cpp プロジェクト: AlchemyDev/Carbon
LLVector4 vec3to4(const LLVector3 &vec)
{
	return LLVector4(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
}
コード例 #12
0
LLVector4 LLMatrix4::getUpRow4() const
{
	return LLVector4(mMatrix[VZ][VX], mMatrix[VZ][VY], mMatrix[VZ][VZ], mMatrix[VZ][VW]);
}
コード例 #13
0
void LLWaterParamManager::update(LLViewerCamera * cam)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
	
	// update the shaders and the menu
	propagateParameters();
	
	// sync menus if they exist
	if(LLFloaterWater::isOpen()) 
	{
		LLFloaterWater::instance()->syncMenu();
	}

	stop_glerror();

	// only do this if we're dealing with shaders
	if(gPipeline.canUseVertexShaders()) 
	{
		//transform water plane to eye space
		glh::vec3f norm(0.f, 0.f, 1.f);
		glh::vec3f p(0.f, 0.f, gAgent.getRegion()->getWaterHeight()+0.1f);
		
		F32 modelView[16];
		for (U32 i = 0; i < 16; i++)
		{
			modelView[i] = (F32) gGLModelView[i];
		}

		glh::matrix4f mat(modelView);
		glh::matrix4f invtrans = mat.inverse().transpose();
		glh::vec3f enorm;
		glh::vec3f ep;
		invtrans.mult_matrix_vec(norm, enorm);
		enorm.normalize();
		mat.mult_matrix_vec(p, ep);

		mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));

		if((mWaterPlane.mV[3] >= 0.f) == LLViewerCamera::getInstance()->cameraUnderWater()) //Sign borkage..
		{
			mWaterPlane.scaleVec(LLVector4(-1.f,-1.f,-1.f,-1.f));
		}

		LLVector3 sunMoonDir;
		if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) 	 
		{ 	 
			sunMoonDir = gSky.getSunDirection(); 	 
		} 	 
		else  	 
		{ 	 
			sunMoonDir = gSky.getMoonDirection(); 	 
		}
		sunMoonDir.normVec();
		mWaterFogKS = 1.f/llmax(sunMoonDir.mV[2], WATER_FOG_LIGHT_CLAMP);

		std::vector<LLGLSLShader*>::iterator shaders_iter=mShaderList.begin();
		for(; shaders_iter != mShaderList.end(); ++shaders_iter)
		{
			(*shaders_iter)->mUniformsDirty = TRUE;
		}
	}
}
コード例 #14
0
ファイル: lldrawpoolbump.cpp プロジェクト: Belxjander/Kirito
void LLDrawPoolBump::beginFullbrightShiny()
{
	LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
	if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
	{
		return;
	}

	sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;

	// Second pass: environment map
	
	if (LLPipeline::sUnderWaterRender)
	{
		shader = &gObjectFullbrightShinyWaterProgram;
	}
	else
	{
		if (LLPipeline::sRenderDeferred)
		{
			shader = &gDeferredFullbrightShinyProgram;
		}
		else
		{
			shader = &gObjectFullbrightShinyProgram;
		}
	}

	LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
	if( cube_map )
	{
		LLMatrix4 mat;
		mat.initRows(LLVector4(gGLModelView+0),
					 LLVector4(gGLModelView+4),
					 LLVector4(gGLModelView+8),
					 LLVector4(gGLModelView+12));
		shader->bind();
		LLVector3 vec = LLVector3(gShinyOrigin) * mat;
		LLVector4 vec4(vec, gShinyOrigin.mV[3]);
		shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);			

		cube_map->setMatrix(1);
		// Make sure that texture coord generation happens for tex unit 1, as that's the one we use for 
		// the cube map in the one pass shiny shaders
		gGL.getTexUnit(1)->disable();
		cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
		cube_map->enableTexture(cube_channel);
		cube_map->enableTextureCoords(1);
		diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);

		gGL.getTexUnit(cube_channel)->bind(cube_map);
		gGL.getTexUnit(0)->activate();
	}

	if (mVertexShaderLevel > 1)
	{ //indexed texture rendering, channel 0 is always diffuse
		diffuse_channel = 0;
	}

	mShiny = TRUE;
}
コード例 #15
0
ファイル: llvotree.cpp プロジェクト: HazimGazov/Sausages
void LLVOTree::updateMesh()
{
	LLMatrix4 matrix;
	
	// Translate to tree base  HACK - adjustment in Z plants tree underground
	const LLVector3 &pos_agent = getPositionAgent();
	//glTranslatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
	LLMatrix4 trans_mat;
	trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
	trans_mat *= matrix;
	
	// Rotate to tree position and bend for current trunk/wind
	// Note that trunk stiffness controls the amount of bend at the trunk as 
	// opposed to the crown of the tree
	// 
	const F32 TRUNK_STIFF = 22.f;
	
	LLQuaternion rot = 
		LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) *
		LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) *
		getRotation();

	LLMatrix4 rot_mat(rot);
	rot_mat *= trans_mat;

	F32 radius = getScale().magVec()*0.05f;
	LLMatrix4 scale_mat;
	scale_mat.mMatrix[0][0] = 
		scale_mat.mMatrix[1][1] =
		scale_mat.mMatrix[2][2] = radius;

	scale_mat *= rot_mat;

//	const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f;
//	const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f;

	F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec());
	
	S32 stop_depth = 0;
	F32 alpha = 1.0;
	

	U32 vert_count = 0;
	U32 index_count = 0;
	
	calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches);

	LLFace* facep = mDrawable->getFace(0);
	facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
	facep->mVertexBuffer->allocateBuffer(vert_count, index_count, TRUE);
	
	LLStrider<LLVector3> vertices;
	LLStrider<LLVector3> normals;
	LLStrider<LLVector2> tex_coords;
	LLStrider<U16> indices;
	U16 idx_offset = 0;

	facep->mVertexBuffer->getVertexStrider(vertices);
	facep->mVertexBuffer->getNormalStrider(normals);
	facep->mVertexBuffer->getTexCoord0Strider(tex_coords);
	facep->mVertexBuffer->getIndexStrider(indices);

	genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
	
	mReferenceBuffer->setBuffer(0);
	facep->mVertexBuffer->setBuffer(0);

}
コード例 #16
0
void LLDrawPoolTree::renderTree(BOOL selecting)
{
	LLGLState normalize(GL_NORMALIZE, TRUE);
	
	// Bind the texture for this tree.
	gGL.getTexUnit(sDiffTex)->bind(mTexturep.get(), TRUE);
		
	U32 indices_drawn = 0;

	glMatrixMode(GL_MODELVIEW);
	
	for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
		 iter != mDrawFace.end(); iter++)
	{
		LLFace *face = *iter;
		LLDrawable *drawablep = face->getDrawable();

		if (drawablep->isDead() || !face->getVertexBuffer())
		{
			continue;
		}

		face->getVertexBuffer()->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
		U16* indicesp = (U16*) face->getVertexBuffer()->getIndicesPointer();

		// Render each of the trees
		LLVOTree *treep = (LLVOTree *)drawablep->getVObj().get();

		LLColor4U color(255,255,255,255);

		if (!selecting || treep->mGLName != 0)
		{
			if (selecting)
			{
				S32 name = treep->mGLName;
				
				color = LLColor4U((U8)(name >> 16), (U8)(name >> 8), (U8)name, 255);
			}
			
			gGLLastMatrix = NULL;
			glLoadMatrixd(gGLModelView);
			//glPushMatrix();
			F32 mat[16];
			for (U32 i = 0; i < 16; i++)
				mat[i] = (F32) gGLModelView[i];

			LLMatrix4 matrix(mat);
			
			// Translate to tree base  HACK - adjustment in Z plants tree underground
			const LLVector3 &pos_agent = treep->getPositionAgent();
			//glTranslatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
			LLMatrix4 trans_mat;
			trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f);
			trans_mat *= matrix;
			
			// Rotate to tree position and bend for current trunk/wind
			// Note that trunk stiffness controls the amount of bend at the trunk as 
			// opposed to the crown of the tree
			// 
			const F32 TRUNK_STIFF = 22.f;
			
			LLQuaternion rot = 
				LLQuaternion(treep->mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(treep->mTrunkBend.mV[VX], treep->mTrunkBend.mV[VY], 0)) *
				LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) *
				treep->getRotation();

			LLMatrix4 rot_mat(rot);
			rot_mat *= trans_mat;

			F32 radius = treep->getScale().magVec()*0.05f;
			LLMatrix4 scale_mat;
			scale_mat.mMatrix[0][0] = 
				scale_mat.mMatrix[1][1] =
				scale_mat.mMatrix[2][2] = radius;

			scale_mat *= rot_mat;

			const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f;
			const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f;

			F32 droop = treep->mDroop + 25.f*(1.f - treep->mTrunkBend.magVec());
			
			S32 stop_depth = 0;
			F32 app_angle = treep->getAppAngle()*LLVOTree::sTreeFactor;
			F32 alpha = 1.0;
			S32 trunk_LOD = LLVOTree::sMAX_NUM_TREE_LOD_LEVELS;

			for (S32 j = 0; j < 4; j++)
			{

				if (app_angle > LLVOTree::sLODAngles[j])
				{
					trunk_LOD = j;
					break;
				}
			} 
			if(trunk_LOD >= LLVOTree::sMAX_NUM_TREE_LOD_LEVELS)
			{
				continue ; //do not render.
			}

			if (app_angle < (THRESH_ANGLE_FOR_BILLBOARD - BLEND_RANGE_FOR_BILLBOARD))
			{
				//
				//  Draw only the billboard 
				//
				//  Only the billboard, can use closer to normal alpha func.
				stop_depth = -1;
				LLFacePool::LLOverrideFaceColor clr(this, color); 
				indices_drawn += treep->drawBranchPipeline(scale_mat, indicesp, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha);
			}
			else // if (app_angle > (THRESH_ANGLE_FOR_BILLBOARD + BLEND_RANGE_FOR_BILLBOARD))
			{
				//
				//  Draw only the full geometry tree
				//
				//stop_depth = (app_angle < THRESH_ANGLE_FOR_RECURSION_REDUCTION);
				LLFacePool::LLOverrideFaceColor clr(this, color); 
				indices_drawn += treep->drawBranchPipeline(scale_mat, indicesp, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha);
			}
			
			//glPopMatrix();
		}
	}
}
コード例 #17
0
void LLWLParamManager::update(LLViewerCamera * cam)
{
	LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM);
	
	// update clouds, sun, and general
	mCurParams.updateCloudScrolling();
	
	// update only if running
	if(mAnimator.mIsRunning) 
	{
		mAnimator.update(mCurParams);
	}

	// update the shaders and the menu
	propagateParameters();
	
	// sync menus if they exist
	if(LLFloaterWindLight::isOpen()) 
	{
		LLFloaterWindLight::instance()->syncMenu();
	}
	if(LLFloaterDayCycle::isOpen()) 
	{
		LLFloaterDayCycle::instance()->syncMenu();
	}
	if(LLFloaterEnvSettings::isOpen()) 
	{
		LLFloaterEnvSettings::instance()->syncMenu();
	}

	F32 camYaw = cam->getYaw();

	stop_glerror();

	// *TODO: potential optimization - this block may only need to be
	// executed some of the time.  For example for water shaders only.
	{
		F32 camYawDelta = mSunDeltaYaw * DEG_TO_RAD;
		
		LLVector3 lightNorm3(mLightDir);	
		lightNorm3 *= LLQuaternion(-(camYaw + camYawDelta), LLVector3(0.f, 1.f, 0.f));
		mRotatedLightDir = LLVector4(lightNorm3, 0.f);

		LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
		end_shaders = LLViewerShaderMgr::instance()->endShaders();
		for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
		{
			if (shaders_iter->mProgramObject != 0
				&& (gPipeline.canUseWindLightShaders()
				|| shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
			{
				shaders_iter->mUniformsDirty = TRUE;
			}
		}
	}

	//Mix windlight settings if needed
	if(sNeedsMix == TRUE)
	{
		if(sMixSet == NULL)
		{
			sNeedsMix = FALSE;
			return;
		}
		if (wlSmoothTransitionTimer.getElapsedTimeF32() >=
			(sMixTime / 100)) //100 steps inbetween
		{
			wlSmoothTransitionTimer.reset();
			mCurParams.mix(mCurParams, *sMixSet, sMixCount / 100);//.01 to 1.0
		}
		sMixCount++;
		if((sMixCount / 100) == 1)
		{
			//All done
			sNeedsMix = FALSE;
			std::string wlSkyPresetName   = "(Region settings)";
			mCurParams.mName = wlSkyPresetName;
			removeParamSet( wlSkyPresetName, true );
			addParamSet( wlSkyPresetName, mCurParams );
			savePreset( wlSkyPresetName );
			mAnimator.mIsRunning = false;
			mAnimator.mUseLindenTime = false;
			loadPreset( wlSkyPresetName, true );
			sMixSet = NULL;
		}
	}
}