Exemplo n.º 1
0
LLVector3 LLModel::getTransformedCenter(const LLMatrix4& mat)
{
	LLVector3 ret;

	if (!mVolumeFaces.empty())
	{
		LLMatrix4a m;
		m.loadu(mat);

		LLVector4a minv,maxv;

		LLVector4a t;
		m.affineTransform(mVolumeFaces[0].mPositions[0], t);
		minv = maxv = t;

		for (S32 i = 0; i < (S32)mVolumeFaces.size(); ++i)
		{
			LLVolumeFace& face = mVolumeFaces[i];

			for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
			{
				m.affineTransform(face.mPositions[j],t);
				update_min_max(minv, maxv, t);
			}
		}

		minv.add(maxv);
		minv.mul(0.5f);

		ret.set(minv.getF32ptr());
	}

	return ret;
}
bool get_hud_matrices(const LLRect& screen_region, LLMatrix4a &proj, LLMatrix4a &model)
{
	if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment())
	{
		F32 zoom_level = gAgentCamera.mHUDCurZoom;
		LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
		
		F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
		proj = gGL.genOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
		proj.getRow<2>().copyComponent<2>(LLVector4a(-0.01f));

		F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
		
		F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth();
		F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();

		proj.applyTranslation_affine(
			clamp_rescale((F32)(screen_region.getCenterX() - screen_region.mLeft), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
			clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
			0.f);
		proj.applyScale_affine(scale_x, scale_y, 1.f);

		model = OGL_TO_CFR_ROTATION;
		model.applyTranslation_affine(LLVector3(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
		model.applyScale_affine(zoom_level);

		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
Exemplo n.º 3
0
const LLMatrix4a &LLViewerCamera::getModelview() const
{
	LLMatrix4 modelview;
	getMatrixToLocal(modelview);
	LLMatrix4a modelviewa;
	modelviewa.loadu((F32*)modelview.mMatrix);
	mModelviewMatrix.setMul(OGL_TO_CFR_ROTATION,modelviewa);
	return mModelviewMatrix;
}
Exemplo n.º 4
0
BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
{
	S32 i, num_faces;
	LLDrawable* drawablep = volumep->mDrawable;

	if (!drawablep)
	{
		return FALSE;
	}

	LLVolume* volume = volumep->getVolume();
	if (!volume)
	{
		return FALSE;
	}

	LLVOVolume* vo_volume = (LLVOVolume*) volumep;

	vo_volume->updateRelativeXform();
	LLMatrix4 mat = vo_volume->getRelativeXform();
	
	LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition()));

	LLMatrix4a render_mata;
	render_mata.loadu(render_mat);
	LLMatrix4a mata;
	mata.loadu(mat);

	num_faces = volume->getNumVolumeFaces();
	for (i = 0; i < num_faces; i++)
	{
		const LLVolumeFace& face = volume->getVolumeFace(i);
				
		for (U32 v = 0; v < face.mNumVertices; v++)
		{
			const LLVector4a& src_vec = face.mPositions[v];
			LLVector4a vec;
			mata.affineTransform(src_vec, vec);

			if (drawablep->isActive())
			{
				LLVector4a t = vec;
				render_mata.affineTransform(t, vec);
			}

			BOOL in_frustum = pointInFrustum(LLVector3(vec.getF32ptr())) > 0;

			if (( !in_frustum && all_verts) ||
				 (in_frustum && !all_verts))
			{
				return !all_verts;
			}
		}
	}
	return all_verts;
}
// static
void LLViewerJointMesh::updateGeometry(LLFace *mFace, LLPolyMesh *mMesh)
{
	LLStrider<LLVector3> o_vertices;
	LLStrider<LLVector3> o_normals;

	//get vertex and normal striders
	LLVertexBuffer* buffer = mFace->getVertexBuffer();
	buffer->getVertexStrider(o_vertices,  0);
	buffer->getNormalStrider(o_normals,   0);

	F32* __restrict vert = o_vertices[0].mV;
	F32* __restrict norm = o_normals[0].mV;

	const F32* __restrict weights = mMesh->getWeights();
	const LLVector4a* __restrict coords = (LLVector4a*) mMesh->getCoords();
	const LLVector4a* __restrict normals = (LLVector4a*) mMesh->getNormals();

	U32 offset = mMesh->mFaceVertexOffset*4;
	vert += offset;
	norm += offset;

	for (U32 index = 0; index < mMesh->getNumVertices(); index++)
	{
		// equivalent to joint = floorf(weights[index]);
		S32 joint = _mm_cvtt_ss2si(_mm_load_ss(weights+index));
		F32 w = weights[index] - joint;		

		LLMatrix4a gBlendMat;

		if (w != 0.f)
		{
			// blend between matrices and apply
			gBlendMat.setLerp(gJointMatAligned[joint+0],
							  gJointMatAligned[joint+1], w);

			LLVector4a res;
			gBlendMat.affineTransform(coords[index], res);
			res.store4a(vert+index*4);
			gBlendMat.rotate(normals[index], res);
			res.store4a(norm+index*4);
		}
		else
		{  // No lerp required in this case.
			LLVector4a res;
			gJointMatAligned[joint].affineTransform(coords[index], res);
			res.store4a(vert+index*4);
			gJointMatAligned[joint].rotate(normals[index], res);
			res.store4a(norm+index*4);
		}
	}

	buffer->flush();
}
Exemplo n.º 6
0
//--------------------------------------------------------------------
// setWorldPosition()
//--------------------------------------------------------------------
void LLJoint::setWorldPosition( const LLVector3& pos )
{
	if (mParent == NULL)
	{
		this->setPosition( pos );
		return;
	}

	LLMatrix4a temp_matrix = getWorldMatrix();
	temp_matrix.setTranslate_affine(pos);

	LLMatrix4a invParentWorldMatrix = mParent->getWorldMatrix();
	invParentWorldMatrix.invert();

	invParentWorldMatrix.mul(temp_matrix);

	LLVector3 localPos(	invParentWorldMatrix.getRow<LLMatrix4a::ROW_TRANS>().getF32ptr() );

	setPosition( localPos );
}
Exemplo n.º 7
0
//--------------------------------------------------------------------
// setWorldRotation()
//--------------------------------------------------------------------
void LLJoint::setWorldRotation( const LLQuaternion& rot )
{
	if (mParent == NULL)
	{
		this->setRotation( rot );
		return;
	}
	
	LLMatrix4a parentWorldMatrix = mParent->getWorldMatrix();
	LLQuaternion2 rota(rot);
	LLMatrix4a temp_mat(rota);

	LLMatrix4a invParentWorldMatrix = mParent->getWorldMatrix();
	invParentWorldMatrix.setTranslate_affine(LLVector3(0.f));

	invParentWorldMatrix.invert();

	invParentWorldMatrix.mul(temp_mat);

	setRotation(LLQuaternion(LLMatrix4(invParentWorldMatrix.getF32ptr())));
}
Exemplo n.º 8
0
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, 
													const LLMeshSkinInfo* skin, LLVolume* volume, 
													const LLVolumeFace& vol_face, LLVOVolume* vobj)
{
	LLVector4a* weight = vol_face.mWeights;
	if (!weight)
	{
		return;
	}

	LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
	LLDrawable* drawable = face->getDrawable();

	U32 data_mask = face->getRiggedVertexBufferDataMask();

	if (buffer.isNull() || buffer->getTypeMask() != data_mask ||
		buffer->getRequestedVerts() != vol_face.mNumVertices ||
		buffer->getRequestedIndices() != vol_face.mNumIndices ||
		(drawable && drawable->isState(LLDrawable::REBUILD_ALL)))
	{
		face->setGeomIndex(0);
		face->setIndicesIndex(0);

		if (buffer.isNull() || buffer->getTypeMask() != data_mask)
		{	//make a new buffer
			if (sShaderLevel > 0)
			{
				buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
			}
			else
			{
				buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
			}
			buffer->allocateBuffer(vol_face.mNumVertices,
								   vol_face.mNumIndices, true);
		}
		else
		{	//resize existing buffer
			buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices);
		}

		face->setSize(vol_face.mNumVertices, vol_face.mNumIndices);
		face->setVertexBuffer(buffer);

		U16 offset = 0;

		LLMatrix4 mat_vert = skin->mBindShapeMatrix;
		glh::matrix4f m((F32*) mat_vert.mMatrix);
		m = m.inverse().transpose();

		F32 mat3[] = {	m.m[0], m.m[1], m.m[2],
						m.m[4], m.m[5], m.m[6],
						m.m[8], m.m[9], m.m[10] };

		LLMatrix3 mat_normal(mat3);

		static LLCachedControl<bool> mesh_enable_deformer(gSavedSettings, "MeshEnableDeformer");
		if (mesh_enable_deformer)
		{
			LLDeformedVolume* deformed_volume = vobj->getDeformedVolume();
			deformed_volume->deform(volume, avatar, skin, face->getTEOffset());
			face->getGeometryVolume(*deformed_volume, face->getTEOffset(), mat_vert,
									mat_normal, offset, true);
		}
		else
		{
			face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert,
 									mat_normal, offset, true);
		}
	}

	if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
	{ //perform software vertex skinning for this face
		LLStrider<LLVector3> position;
		LLStrider<LLVector3> normal;

		bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
		buffer->getVertexStrider(position);

		if (has_normal)
		{
			buffer->getNormalStrider(normal);
		}
		LLVector4a* pos = (LLVector4a*) position.get();

		LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL;

		//build matrix palette
		LLMatrix4a mp[64];
		LLMatrix4* mat = (LLMatrix4*) mp;

		for (U32 j = 0; j < skin->mJointNames.size(); ++j)
		{
			LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
			if (joint)
			{
				mat[j] = skin->mInvBindMatrix[j];
				mat[j] *= joint->getWorldMatrix();
			}
		}

		LLMatrix4a bind_shape_matrix;
		bind_shape_matrix.loadu(skin->mBindShapeMatrix);

		for (U32 j = 0; j < buffer->getRequestedVerts(); ++j)
		{
			LLMatrix4a final_mat;
			final_mat.clear();

			S32 idx[4];

			LLVector4 wght;

			F32 scale = 0.f;
			for (U32 k = 0; k < 4; k++)
		{
				F32 w = weight[j][k];

				idx[k] = llclamp((S32) floorf(w), 0, 63);
				wght[k] = w - floorf(w);
				scale += wght[k];
			}

			wght *= 1.f/scale;

			for (U32 k = 0; k < 4; k++)
			{
				F32 w = wght[k];

				LLMatrix4a src;
				src.setMul(mp[idx[k]], w);

				final_mat.add(src);
			}

			LLVector4a& v = vol_face.mPositions[j];
			LLVector4a t;
			LLVector4a dst;
			bind_shape_matrix.affineTransform(v, t);
			final_mat.affineTransform(t, dst);
			pos[j] = dst;

			if (norm)
			{
				LLVector4a& n = vol_face.mNormals[j];
				bind_shape_matrix.rotate(n, t);
				final_mat.rotate(t, dst);
				norm[j] = dst;
			}
		}
	}

	if (drawable && face->getTEOffset() == drawable->getNumFaces() - 1)
	{
		drawable->clearState(LLDrawable::REBUILD_ALL);
	}
}
Exemplo n.º 9
0
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
	if ((avatar->isSelf() && !gAgent.needsRenderAvatar()) || !gMeshRepo.meshRezEnabled())
	{
		return;
	}

	stop_glerror();

	for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
	{
		LLFace* face = mRiggedFace[type][i];
		LLDrawable* drawable = face->getDrawable();
		if (!drawable)
		{
			continue;
		}

		LLVOVolume* vobj = drawable->getVOVolume();

		if (!vobj)
		{
			continue;
		}

		LLVolume* volume = vobj->getVolume();
		S32 te = face->getTEOffset();

		if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded())
		{
			continue;
		}

		LLUUID mesh_id = volume->getParams().getSculptID();
		if (mesh_id.isNull())
		{
			continue;
		}

		const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj);
		if (!skin)
		{
			continue;
		}

		//stop_glerror();

		//const LLVolumeFace& vol_face = volume->getVolumeFace(te);
		//updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face);
		
		//stop_glerror();

		U32 data_mask = LLFace::getRiggedDataMask(type);

		LLVertexBuffer* buff = face->getVertexBuffer();

		if (buff)
		{
			if (sShaderLevel > 0)
			{ //upload matrix palette to shader
				LLMatrix4 mat[JOINT_COUNT];

				U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT);

				for (U32 i = 0; i < count; ++i)
				{
					LLJoint* joint = avatar->getJoint(skin->mJointNames[i]);
					if(!joint)
					{
						joint = avatar->getJoint("mRoot");
					}
					if (joint)
					{
						LLMatrix4a tmp;
						tmp.loadu((F32*)skin->mInvBindMatrix[i].mMatrix);
						tmp.setMul(joint->getWorldMatrix(),tmp);
						mat[i] = LLMatrix4(tmp.getF32ptr());
					}
				}
				
				stop_glerror();

				F32 mp[JOINT_COUNT*12];

				for (U32 i = 0; i < count; ++i)
				{
					F32* m = (F32*) mat[i].mMatrix;

					U32 idx = i*12;

					mp[idx+0] = m[0];
					mp[idx+1] = m[1];
					mp[idx+2] = m[2];
					mp[idx+3] = m[12];

					mp[idx+4] = m[4];
					mp[idx+5] = m[5];
					mp[idx+6] = m[6];
					mp[idx+7] = m[13];

					mp[idx+8] = m[8];
					mp[idx+9] = m[9];
					mp[idx+10] = m[10];
					mp[idx+11] = m[14];
				}

				LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, 
					count,
					FALSE,
					(GLfloat*) mp);

				LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(count-1));
				
				stop_glerror();
			}
			else
			{
				data_mask &= ~LLVertexBuffer::MAP_WEIGHT4;
			}

			U16 start = face->getGeomStart();
			U16 end = start + face->getGeomCount()-1;
			S32 offset = face->getIndicesStart();
			U32 count = face->getIndicesCount();

			/*if (glow)
			{
				gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow());
			}*/

			const LLTextureEntry* te = face->getTextureEntry();
			LLMaterial* mat = te->getMaterialParams().get();

			if (mat && is_deferred_render)
			{
				gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP));
				gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP));
				gGL.getTexUnit(specular_channel)->bind(face->getTexture(LLRender::SPECULAR_MAP));

				LLColor4 col = mat->getSpecularLightColor();
				F32 spec = llmax(0.0001f, mat->getSpecularLightExponent() / 255.f);

				F32 env = mat->getEnvironmentIntensity()/255.f;

				if (mat->getSpecularID().isNull())
				{
					env = te->getShiny()*0.25f;
					col.set(env,env,env,0);
					spec = env;
				}
		
				BOOL fullbright = te->getFullbright();

				sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f);
				sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec);
				sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env);

				if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
				{
					sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f);
				}
				else
				{
					sVertexProgram->setMinimumAlpha(0.004f);
				}

				for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
				{
					LLViewerTexture* tex = face->getTexture(i);
					if (tex)
					{
						tex->addTextureStats(avatar->getPixelArea());
					}
				}
			}
			else
			{
				gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture());

				if(sVertexProgram)
				{
					if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
					{
						sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f);
					}
					else
					{
						sVertexProgram->setMinimumAlpha(0.004f);
					}
				}

				if (normal_channel > -1)
				{
					LLDrawPoolBump::bindBumpMap(face, normal_channel);
				}
			}

			if (face->mTextureMatrix && vobj->mTexAnimMode)
			{
				gGL.matrixMode(LLRender::MM_TEXTURE);
				gGL.loadMatrix(*face->mTextureMatrix);
				buff->setBuffer(data_mask);
				buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
				gGL.loadIdentity();
				gGL.matrixMode(LLRender::MM_MODELVIEW);
			}
			else
			{
				buff->setBuffer(data_mask);
				buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);		
			}

			gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES);
		}
	}
}
Exemplo n.º 10
0
void LLSpatialBridge::updateSpatialExtents()
{
	LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0);
	
	{
		LLFastTimer ftm(FTM_CULL_REBOUND);
		root->rebound();
	}
	
	LLVector4a offset;
	LLVector4a size = root->mBounds[1];
		
	//VECTORIZE THIS
	LLMatrix4a mat;
	mat.loadu(mDrawable->getXform()->getWorldMatrix());

	LLVector4a t;
	t.splat(0.f);

	LLVector4a center;
	mat.affineTransform(t, center);
	
	mat.rotate(root->mBounds[0], offset);
	center.add(offset);
	
	LLVector4a v[4];

	//get 4 corners of bounding box
	mat.rotate(size,v[0]);

	LLVector4a scale;
	
	scale.set(-1.f, -1.f, 1.f);
	scale.mul(size);
	mat.rotate(scale, v[1]);
	
	scale.set(1.f, -1.f, -1.f);
	scale.mul(size);
	mat.rotate(scale, v[2]);
	
	scale.set(-1.f, 1.f, -1.f);
	scale.mul(size);
	mat.rotate(scale, v[3]);

	
	LLVector4a& newMin = mExtents[0];
	LLVector4a& newMax = mExtents[1];
	
	newMin = newMax = center;
	
	for (U32 i = 0; i < 4; i++)
	{
		LLVector4a delta;
		delta.setAbs(v[i]);
		LLVector4a min;
		min.setSub(center, delta);
		LLVector4a max;
		max.setAdd(center, delta);

		newMin.setMin(newMin, min);
		newMax.setMax(newMax, max);
	}
	
	LLVector4a diagonal;
	diagonal.setSub(newMax, newMin);
	mRadius = diagonal.getLength3().getF32() * 0.5f;
	
	mPositionGroup.setAdd(newMin,newMax);
	mPositionGroup.mul(0.5f);
	updateBinRadius();
}
Exemplo n.º 11
0
void LLViewerCamera::setPerspective(BOOL for_selection,
									S32 x, S32 y_from_bot, S32 width, S32 height,
									BOOL limit_select_distance,
									F32 z_near, F32 z_far)
{
	F32 fov_y, aspect;
	fov_y = RAD_TO_DEG * getView();
	BOOL z_default_far = FALSE;
	if (z_far <= 0)
	{
		z_default_far = TRUE;
		z_far = getFar();
	}
	if (z_near <= 0)
	{
		z_near = getNear();
	}
	aspect = getAspect();

	// Load camera view matrix
	gGL.matrixMode( LLRender::MM_PROJECTION );
	gGL.loadIdentity();

	LLMatrix4a proj_mat;
	proj_mat.setIdentity();

	if (for_selection)
	{
		// make a tiny little viewport
		// anything drawn into this viewport will be "selected"

		const LLRect& rect = gViewerWindow->getWorldViewRectRaw();
		
		const F32 scale_x = rect.getWidth() / F32(width);
		const F32 scale_y = rect.getHeight() / F32(height);
		const F32 trans_x = scale_x + (2.f * (rect.mLeft - x)) / F32(width) - 1.f;
		const F32 trans_y = scale_y + (2.f * (rect.mBottom - y_from_bot)) / F32(height) - 1.f;

		//Generate a pick matrix
		proj_mat.applyScale_affine(scale_x, scale_y, 1.f);
		proj_mat.setTranslate_affine(LLVector3(trans_x, trans_y, 0.f));

		if (limit_select_distance)
		{
			// ...select distance from control
//			z_far = gSavedSettings.getF32("MaxSelectDistance");
// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Added: RLVa-1.2.0e
			z_far = (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) ? gSavedSettings.getF32("MaxSelectDistance") : 1.5;
// [/RLVa:KB]
		}
		else
		{
			z_far = gAgentCamera.mDrawDistance;
		}
	}
	else
	{
		// Only override the far clip if it's not passed in explicitly.
		if (z_default_far)
		{
			z_far = MAX_FAR_CLIP;
		}
		glViewport(x, y_from_bot, width, height);
		gGLViewport[0] = x;
		gGLViewport[1] = y_from_bot;
		gGLViewport[2] = width;
		gGLViewport[3] = height;
	}
	
	if (mZoomFactor > 1.f)
	{
		float offset = mZoomFactor - 1.f;
		int pos_y = mZoomSubregion / llceil(mZoomFactor);
		int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor));

		proj_mat.applyTranslation_affine(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f);
		proj_mat.applyScale_affine(mZoomFactor,mZoomFactor,1.f);
	}

	calcProjection(z_far); // Update the projection matrix cache

	proj_mat.mul(gGL.genPersp(fov_y,aspect,z_near,z_far));
	
	gGL.loadMatrix(proj_mat);
	
	gGLProjection = proj_mat;

	gGL.matrixMode(LLRender::MM_MODELVIEW );

	LLMatrix4a ogl_matrix;
	getOpenGLTransform(ogl_matrix.getF32ptr());

	LLMatrix4a modelview;
	modelview.setMul(OGL_TO_CFR_ROTATION, ogl_matrix);
	
	gGL.loadMatrix(modelview);
	
	if (for_selection && (width > 1 || height > 1))
	{
		// NB: as of this writing, i believe the code below is broken (doesn't take into account the world view, assumes entire window)
		// however, it is also unused (the GL matricies are used for selection, (see LLCamera::sphereInFrustum())) and so i'm not
		// comfortable hacking on it.
		calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f,
								(F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f,
								(F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f,
								(F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f);

	}

	// if not picking and not doing a snapshot, cache various GL matrices
	if (!for_selection && mZoomFactor == 1.f)
	{
		// Save GL matrices for access elsewhere in code, especially project_world_to_screen
		//glGetDoublev(GL_MODELVIEW_MATRIX, gGLModelView);
		glh_set_current_modelview(modelview);
	}

	updateFrustumPlanes(*this);

	/*if (gSavedSettings.getBOOL("CameraOffset"))
	{
		gGL.matrixMode(LLRender::MM_PROJECTION);
		gGL.translatef(0,0,-50);
		gGL.rotatef(20.0,1,0,0);
		gGL.matrixMode(LLRender::MM_MODELVIEW);
	}*/
}
void LLPanelPrimMediaControls::updateShape()
{
	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
	LLViewerObject* objectp = getTargetObject();
	
	if(!media_impl || gFloaterTools->getVisible())
	{
		setVisible(FALSE);
		return;
	}

	LLPluginClassMedia* media_plugin = NULL;
	if(media_impl->hasMedia())
	{
		media_plugin = media_impl->getMediaPlugin();
	}
	
	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();

	bool can_navigate = parcel->getMediaAllowNavigate();
	bool enabled = false;
	bool is_zoomed = (mCurrentZoom != ZOOM_NONE) && (mTargetObjectID == mZoomObjectID) && (mTargetObjectFace == mZoomObjectFace);
	// There is no such thing as "has_focus" being different from normal controls set
	// anymore (as of user feedback from bri 10/09).  So we cheat here and force 'has_focus'
	// to 'true' (or, actually, we use a setting)
	bool has_focus = (gSavedSettings.getBOOL("PrimMediaControlsUseHoverControlSet")) ? media_impl->hasFocus() : true;
	setVisible(enabled);

	if (objectp)
	{
		bool mini_controls = false;
		LLMediaEntry *media_data = objectp->getTE(mTargetObjectFace)->getMediaData();
		if (media_data && NULL != dynamic_cast<LLVOVolume*>(objectp))
		{
			// Don't show the media controls if we do not have permissions
			enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
			mini_controls = (LLMediaEntry::MINI == media_data->getControls());
		}
		const bool is_hud = objectp->isHUDAttachment();
		
		//
		// Set the state of the buttons
		//
		
		// XXX RSP: TODO: FIXME: clean this up so that it is clearer what mode we are in,
		// and that only the proper controls get made visible/enabled according to that mode. 
		mBackCtrl->setVisible(has_focus);
		mFwdCtrl->setVisible(has_focus);
		mReloadCtrl->setVisible(has_focus);
		mStopCtrl->setVisible(false);
		mHomeCtrl->setVisible(has_focus);
		mZoomCtrl->setVisible(!is_zoomed);
		mUnzoomCtrl->setVisible(is_zoomed);
		mOpenCtrl->setVisible(true);
		mMediaAddressCtrl->setVisible(has_focus && !mini_controls);
		mMediaPlaySliderPanel->setVisible(has_focus && !mini_controls);
		mVolumeCtrl->setVisible(false);
		
		mWhitelistIcon->setVisible(!mini_controls && (media_data)?media_data->getWhiteListEnable():false);
		// Disable zoom if HUD
		mZoomCtrl->setEnabled(!is_hud);
		mUnzoomCtrl->setEnabled(!is_hud);
		mSecureLockIcon->setVisible(false);
		mCurrentURL = media_impl->getCurrentMediaURL();
		
		mBackCtrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate);
		mFwdCtrl->setEnabled((media_impl != NULL) && media_impl->canNavigateForward() && can_navigate);
		mStopCtrl->setEnabled(has_focus && can_navigate);
		mHomeCtrl->setEnabled(has_focus && can_navigate);
		LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE;
		
		mVolumeCtrl->setVisible(has_focus);
		mVolumeCtrl->setEnabled(has_focus);
		mVolumeSliderCtrl->setEnabled(has_focus && shouldVolumeSliderBeVisible());
		mVolumeSliderCtrl->setVisible(has_focus && shouldVolumeSliderBeVisible());

		if(media_plugin && media_plugin->pluginSupportsMediaTime())
		{
			mReloadCtrl->setEnabled(false);
			mReloadCtrl->setVisible(false);
			mMediaStopCtrl->setVisible(has_focus);
			mHomeCtrl->setVisible(has_focus);
			mBackCtrl->setVisible(false);
			mFwdCtrl->setVisible(false);
			mMediaAddressCtrl->setVisible(false);
			mMediaAddressCtrl->setEnabled(false);
			mMediaPlaySliderPanel->setVisible(has_focus && !mini_controls);
			mMediaPlaySliderPanel->setEnabled(has_focus && !mini_controls);
			mSkipFwdCtrl->setVisible(has_focus && !mini_controls);
			mSkipFwdCtrl->setEnabled(has_focus && !mini_controls);
			mSkipBackCtrl->setVisible(has_focus && !mini_controls);
			mSkipBackCtrl->setEnabled(has_focus && !mini_controls);
			
			mVolumeCtrl->setVisible(has_focus);
			mVolumeCtrl->setEnabled(has_focus);
			mVolumeSliderCtrl->setEnabled(has_focus && shouldVolumeSliderBeVisible());
			mVolumeSliderCtrl->setVisible(has_focus && shouldVolumeSliderBeVisible());
			
			mWhitelistIcon->setVisible(false);
			mSecureLockIcon->setVisible(false);
			if (mMediaPanelScroll)
			{
				mMediaPanelScroll->setVisible(false);
				mScrollUpCtrl->setVisible(false);
				mScrollDownCtrl->setVisible(false);
				mScrollRightCtrl->setVisible(false);
				mScrollDownCtrl->setVisible(false);
			}
			
			F32 volume = media_impl->getVolume();
			// movie's url changed
			if(mCurrentURL!=mPreviousURL)
			{
				mMovieDuration = media_plugin->getDuration();
				mPreviousURL = mCurrentURL;
			}
			
			if(mMovieDuration == 0) 
			{
				mMovieDuration = media_plugin->getDuration();
				mMediaPlaySliderCtrl->setValue(0);
				mMediaPlaySliderCtrl->setEnabled(false);
			}
			// TODO: What if it's not fully loaded
			
			if(mUpdateSlider && mMovieDuration!= 0)
			{
				F64 current_time =  media_plugin->getCurrentTime();
				F32 percent = current_time / mMovieDuration;
				mMediaPlaySliderCtrl->setValue(percent);
				mMediaPlaySliderCtrl->setEnabled(true);
			}
			
			// video vloume
			if(volume <= 0.0)
			{
				mMuteBtn->setToggleState(true);
			}
			else if (volume >= 1.0)
			{
				mMuteBtn->setToggleState(false);
			}
			else
			{
				mMuteBtn->setToggleState(false);
			}
			
			switch(result)
			{
				case LLPluginClassMediaOwner::MEDIA_PLAYING:
					mPlayCtrl->setEnabled(FALSE);
					mPlayCtrl->setVisible(FALSE);
					mPauseCtrl->setEnabled(TRUE);
					mPauseCtrl->setVisible(has_focus);
					
					break;
				case LLPluginClassMediaOwner::MEDIA_PAUSED:
				default:
					mPauseCtrl->setEnabled(FALSE);
					mPauseCtrl->setVisible(FALSE);
					mPlayCtrl->setEnabled(TRUE);
					mPlayCtrl->setVisible(has_focus);
					break;
			}
		}
		else   // web based
		{
			if(media_plugin)
			{
				mCurrentURL = media_plugin->getLocation();
			}
			else
			{
				mCurrentURL.clear();
			}
			
			mPlayCtrl->setVisible(FALSE);
			mPauseCtrl->setVisible(FALSE);
			mMediaStopCtrl->setVisible(FALSE);
			mMediaAddressCtrl->setVisible(has_focus && !mini_controls);
			mMediaAddressCtrl->setEnabled(has_focus && !mini_controls);
			mMediaPlaySliderPanel->setVisible(FALSE);
			mMediaPlaySliderPanel->setEnabled(FALSE);
			mSkipFwdCtrl->setVisible(FALSE);
			mSkipFwdCtrl->setEnabled(FALSE);
			mSkipBackCtrl->setVisible(FALSE);
			mSkipBackCtrl->setEnabled(FALSE);
			
			if(media_impl->getVolume() <= 0.0)
			{
				mMuteBtn->setToggleState(true);
			}
			else
			{
				mMuteBtn->setToggleState(false);
			}

			if (mMediaPanelScroll)
			{
				mMediaPanelScroll->setVisible(has_focus);
				mScrollUpCtrl->setVisible(has_focus);
				mScrollDownCtrl->setVisible(has_focus);
				mScrollRightCtrl->setVisible(has_focus);
				mScrollDownCtrl->setVisible(has_focus);
			}
			// TODO: get the secure lock bool from media plug in
			std::string prefix =  std::string("https://");
			std::string test_prefix = mCurrentURL.substr(0, prefix.length());
			LLStringUtil::toLower(test_prefix);
			if(test_prefix == prefix)
			{
				mSecureLockIcon->setVisible(has_focus);
			}
			
			if(mCurrentURL!=mPreviousURL)
			{
				setCurrentURL();
				mPreviousURL = mCurrentURL;
			}
			
			if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
			{
				mReloadCtrl->setEnabled(FALSE);
				mReloadCtrl->setVisible(FALSE);
				mStopCtrl->setEnabled(TRUE);
				mStopCtrl->setVisible(has_focus);
			}
			else
			{
				mReloadCtrl->setEnabled(TRUE);
				mReloadCtrl->setVisible(has_focus);
				mStopCtrl->setEnabled(FALSE);
				mStopCtrl->setVisible(FALSE);
			}
		}
		
		
		if(media_plugin)
		{
			//
			// Handle progress bar
			//
			if(LLPluginClassMediaOwner::MEDIA_LOADING == media_plugin->getStatus())
			{	
				mMediaProgressPanel->setVisible(true);
				mMediaProgressBar->setValue(media_plugin->getProgressPercent());
			}
			else
			{
				mMediaProgressPanel->setVisible(false);
			}
		}
		
		if(media_impl)
		{
			//
			// Handle Scrolling
			//
			switch (mScrollState) 
			{
				case SCROLL_UP:
					media_impl->scrollWheel(0, -1, MASK_NONE);
					break;
				case SCROLL_DOWN:
					media_impl->scrollWheel(0, 1, MASK_NONE);
					break;
				case SCROLL_LEFT:
					media_impl->scrollWheel(1, 0, MASK_NONE);
					//				media_impl->handleKeyHere(KEY_LEFT, MASK_NONE);
					break;
				case SCROLL_RIGHT:
					media_impl->scrollWheel(-1, 0, MASK_NONE);
					//				media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
					break;
				case SCROLL_NONE:
		default:
					break;
			}
		}
		
		setVisible(enabled);
		
		//
		// Calculate position and shape of the controls
		//
		std::vector<LLVector3>::iterator vert_it;
		std::vector<LLVector3>::iterator vert_end;
		std::vector<LLVector3> vect_face;
		
		LLVolume* volume = objectp->getVolume();
		
		if (volume)
		{
			const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace);
			
			LLVector3 ext[2];
			ext[0].set(vf.mExtents[0].getF32ptr());
			ext[1].set(vf.mExtents[1].getF32ptr());
			
			LLVector3 center = (ext[0]+ext[1])*0.5f;
			LLVector3 size = (ext[1]-ext[0])*0.5f;
			LLVector3 vert[] =
			{
				center + size.scaledVec(LLVector3(1,1,1)),
				center + size.scaledVec(LLVector3(-1,1,1)),
				center + size.scaledVec(LLVector3(1,-1,1)),
				center + size.scaledVec(LLVector3(-1,-1,1)),
				center + size.scaledVec(LLVector3(1,1,-1)),
				center + size.scaledVec(LLVector3(-1,1,-1)),
				center + size.scaledVec(LLVector3(1,-1,-1)),
				center + size.scaledVec(LLVector3(-1,-1,-1)),
			};

			LLVOVolume* vo = (LLVOVolume*) objectp;

			for (U32 i = 0; i < 8; i++)
			{
				vect_face.push_back(vo->volumePositionToAgent(vert[i]));	
			}
		}
		vert_it = vect_face.begin();
		vert_end = vect_face.end();
		
		LLMatrix4a mat;
		if (!is_hud) 
		{
			mat.setMul(glh_get_current_projection(),glh_get_current_modelview());
		}
		else {
			LLMatrix4a proj, modelview;
			if (get_hud_matrices(proj, modelview))
			{
				//mat = proj * modelview;
				mat.setMul(proj,modelview);
			}
		}
		LLVector4a min;
		min.splat(1.f);
		LLVector4a max;
		max.splat(-1.f);
		for(; vert_it != vert_end; ++vert_it)
		{
			// project silhouette vertices into screen space
			LLVector4a screen_vert;
			screen_vert.load3(vert_it->mV,1.f);

			mat.perspectiveTransform(screen_vert,screen_vert);

			// add to screenspace bounding box
			min.setMin(screen_vert,min);
			max.setMax(screen_vert,max);
		}
		
		// convert screenspace bbox to pixels (in screen coords)
		LLRect window_rect = gViewerWindow->getWorldViewRectScaled();
		LLCoordGL screen_min;
		screen_min.mX = ll_round((F32)window_rect.mLeft + (F32)window_rect.getWidth() * (min.getF32ptr()[VX] + 1.f) * 0.5f);
		screen_min.mY = ll_round((F32)window_rect.mBottom + (F32)window_rect.getHeight() * (min.getF32ptr()[VY] + 1.f) * 0.5f);
		
		LLCoordGL screen_max;
		screen_max.mX = ll_round((F32)window_rect.mLeft + (F32)window_rect.getWidth() * (max.getF32ptr()[VX] + 1.f) * 0.5f);
		screen_max.mY = ll_round((F32)window_rect.mBottom + (F32)window_rect.getHeight() * (max.getF32ptr()[VY] + 1.f) * 0.5f);
		
		// grow panel so that screenspace bounding box fits inside "media_region" element of panel
		LLRect media_panel_rect;
		// Get the height of the controls (less the volume slider)
		S32 controls_height = mMediaControlsStack->getRect().getHeight() - mVolumeSliderCtrl->getRect().getHeight();
		getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_panel_rect);
		media_panel_rect.mTop += controls_height;
		
		// keep all parts of panel on-screen
		// Area of the top of the world view to avoid putting the controls
		window_rect.mTop -= mTopWorldViewAvoidZone;
		// Don't include "spacing" bookends on left & right of the media controls
		window_rect.mLeft -= mLeftBookend->getRect().getWidth();
		window_rect.mRight += mRightBookend->getRect().getWidth();
		// Don't include the volume slider
		window_rect.mBottom -= mVolumeSliderCtrl->getRect().getHeight();
		media_panel_rect.intersectWith(window_rect);
		
		// clamp to minimum size, keeping rect inside window
		S32 centerX = media_panel_rect.getCenterX();
		S32 centerY = media_panel_rect.getCenterY();
		// Shrink screen rect by min width and height, to ensure containment
		window_rect.stretch(-mMinWidth/2, -mMinHeight/2);
		window_rect.clampPointToRect(centerX, centerY);
		media_panel_rect.setCenterAndSize(centerX, centerY, 
										  llmax(mMinWidth, media_panel_rect.getWidth()),
										  llmax(mMinHeight, media_panel_rect.getHeight()));
		
		// Finally set the size of the panel
		setShape(media_panel_rect, true);
		
		// Test mouse position to see if the cursor is stationary
		LLCoordWindow cursor_pos_window;
		getWindow()->getCursorPosition(&cursor_pos_window);
		
		// If last pos is not equal to current pos, the mouse has moved
		// We need to reset the timer, and make sure the panel is visible
		if(cursor_pos_window.mX != mLastCursorPos.mX ||
		   cursor_pos_window.mY != mLastCursorPos.mY ||
		   mScrollState != SCROLL_NONE)
		{
			mInactivityTimer.start();
			mLastCursorPos = cursor_pos_window;
		}
		
		if(isMouseOver() || hasFocus())
		{
			// Never fade the controls if the mouse is over them or they have keyboard focus.
			mFadeTimer.stop();
		}
		else if(!mClearFaceOnFade && (mInactivityTimer.getElapsedTimeF32() < mInactiveTimeout))
		{
			// Mouse is over the object, but has not been stationary for long enough to fade the UI
			mFadeTimer.stop();
		}
		else if(! mFadeTimer.getStarted() )
		{
			// we need to start fading the UI (and we have not already started)
			mFadeTimer.reset();
			mFadeTimer.start();
		}
		else
		{
			// I don't think this is correct anymore.  This is done in draw() after the fade has completed.
			//			setVisible(FALSE);
		}
	}
}