Пример #1
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;
}
Пример #2
0
void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
{
	LLFastTimer t(FTM_RIGGED_VBO);

	//update rigged vertex buffers
	for (U32 type = 0; type < NUM_RIGGED_PASSES; ++type)
	{
		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)
			{
				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);
		}
	}
}
Пример #3
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)
    {
        BOOL inside = pointInFrustum(volumep->getRenderPosition());

        return (inside > 0);
    }

    LLVOVolume* vo_volume = (LLVOVolume*) volumep;

    vo_volume->updateRelativeXform();
    LLMatrix4 mat = vo_volume->getRelativeXform();

    LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition()));

    num_faces = volume->getNumVolumeFaces();
    for (i = 0; i < num_faces; i++)
    {
        const LLVolumeFace& face = volume->getVolumeFace(i);

        for (U32 v = 0; v < face.mVertices.size(); v++)
        {
            LLVector4 vec = LLVector4(face.mVertices[v].mPosition) * mat;

            if (drawablep->isActive())
            {
                vec = vec * render_mat;
            }

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

            if (( !in_frustum && all_verts) ||
                    (in_frustum && !all_verts))
            {
                return !all_verts;
            }
        }
    }
    return all_verts;
}
void LLLocalBitmapBrowser::performSculptUpdates(LLLocalBitmap* unit)
{

	/* looking for sculptmap using objects only */
	std::vector<LLAffectedObject> object_list = unit->getUsingObjects(false, false, true);
	if (object_list.empty()) { return; }

	for( std::vector<LLAffectedObject>::iterator iter = object_list.begin();
		 iter != object_list.end(); iter++ )
	{
		LLAffectedObject aobj = *iter;
		if ( aobj.object )
		{
			if ( !aobj.local_sculptmap ) { continue; } // should never get here. only in case of misuse.
			
			// update code [begin]   
			if ( unit->mVolumeDirty )
			{
				LLImageRaw* rawimage = gTextureList.findImage( unit->getID() )->getCachedRawImage();

				LLVolumeParams params = aobj.object->getVolume()->getParams();
				LLVolumeLODGroup* lodgroup = aobj.object->mDrawable->getVOVolume()->getVolumeManager()->getGroup(params);
			
				for (S32 i = 0; i < LLVolumeLODGroup::NUM_LODS; i++)
				{
					LLVolume* vol = lodgroup->getVolByLOD(i);

					if (vol)
						{ vol->sculpt(rawimage->getWidth(), rawimage->getHeight(), rawimage->getComponents(), rawimage->getData(), 0); }
				}

				// doing this again to fix the weirdness with selected-for-edit objects not updating otherwise.
				aobj.object->getVolume()->sculpt(rawimage->getWidth(), rawimage->getHeight(), 
												  rawimage->getComponents(), rawimage->getData(), 0);

				unit->mVolumeDirty = false;
			}

			aobj.object->mDrawable->getVOVolume()->setSculptChanged( true ); 
			aobj.object->mDrawable->getVOVolume()->markForUpdate( true );
			// update code [end]
		}
			
	}

}
Пример #5
0
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->setPercent(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);
			
			const LLVector3* ext = vf.mExtents;
			
			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();
		
		glh::matrix4f mat;
		if (!is_hud) 
		{
			mat = glh_get_current_projection() * glh_get_current_modelview();
		}
		else {
			glh::matrix4f proj, modelview;
			if (get_hud_matrices(proj, modelview))
				mat = proj * modelview;
		}
		LLVector3 min = LLVector3(1,1,1);
		LLVector3 max = LLVector3(-1,-1,-1);
		for(; vert_it != vert_end; ++vert_it)
		{
			// project silhouette vertices into screen space
			glh::vec3f screen_vert = glh::vec3f(vert_it->mV); 
			mat.mult_matrix_vec(screen_vert);
			
			// add to screenspace bounding box
			update_min_max(min, max, LLVector3(screen_vert.v));
		}
		
		// convert screenspace bbox to pixels (in screen coords)
		LLRect window_rect = gViewerWindow->getWorldViewRectScaled();
		LLCoordGL screen_min;
		screen_min.mX = llround((F32)window_rect.getWidth() * (min.mV[VX] + 1.f) * 0.5f);
		screen_min.mY = llround((F32)window_rect.getHeight() * (min.mV[VY] + 1.f) * 0.5f);
		
		LLCoordGL screen_max;
		screen_max.mX = llround((F32)window_rect.getWidth() * (max.mV[VX] + 1.f) * 0.5f);
		screen_max.mY = llround((F32)window_rect.getHeight() * (max.mV[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);
		}
	}
}
Пример #6
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, vobj);

		stop_glerror();

		U32 data_mask = LLFace::getRiggedDataMask(type);

		LLVertexBuffer* buff = face->getVertexBuffer();

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

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

				stop_glerror();

				LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette",
																   skin->mJointNames.size(),
																   FALSE,
																   (GLfloat*) mat[0].mMatrix);

				stop_glerror();
			}
			else
			{
				data_mask &= ~LLVertexBuffer::MAP_WEIGHT4;
			}

			buff->setBuffer(data_mask);

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

			if (glow)
			{
				glColor4f(0,0,0,face->getTextureEntry()->getGlow());
			}

			gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture());
			if (normal_channel > -1)
			{
				LLDrawPoolBump::bindBumpMap(face, normal_channel);
			}

			if (face->mTextureMatrix)
			{
				glMatrixMode(GL_TEXTURE);
				glLoadMatrixf((F32*) face->mTextureMatrix->mMatrix);
				buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
				glLoadIdentity();
				glMatrixMode(GL_MODELVIEW);
			}
			else
			{
				buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
			}
		}
	}
}
Пример #7
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);
		}
	}
}
Пример #8
0
bool Setup()
{
	axis = new Axis(Device);
	accessSqlite();
	
	//LLProfileParams profileParams = LLProfileParams(
	//	LL_PCODE_PROFILE_SQUARE, //Curve
	//	0.f, //Begin
	//	1.0f, //End
	//	0.0f); //Hollow
	//LLPathParams pathParams = LLPathParams(
	//	LL_PCODE_PATH_LINE, //curve 
	//	0.f, //begin
	//	1.0f, //end
	//	1.f, //scaleX
	//	1.f, //scaleY
	//	0.f, //shearX
	//	0.f, //shearY
	//	0.f, //twistEnd
	//	0.f, //twistBegin
	//	0.f, //radiusOffset
	//	0.f, //taperX
	//	0.f, //taperY
	//	1.f, //revolutions
	//	0.f);  //skew
	for(int i=0; i<profileParams.size(); i++)
	{
		LLVolumeParams volumeParams = LLVolumeParams(
			profileParams[ i ], 
			pathParams[ i ], 
			0, //LLUUID
			LL_SCULPT_TYPE_NONE);
		LLVolume* volume = new LLVolume(
			volumeParams, 
			4.f, //detail
			false, //generate_single_face
			FALSE); //is_unique

		S32 numFaces = volume->getNumFaces();
		for(S32 j=0; j<numFaces; j++)
		{
			LLVolumeFace volumeFace = volume->getVolumeFace(j); 
			obj.push_back( Object(Device, &volumeFace, positions[i], rotations[i], scales[i]));
		}
	}
	
	//创建纹理
	D3DXCreateTextureFromFile(
	Device,
	"testTex.jpg",
	&Tex);

	//HRESULT D3DXCreateFont(
	//	  Device,		//LPDIRECT3DDEVICE9 pDevice,
	//	  50,	//INT Height,
	//	  20,	 //UINT Width,
	//	  500,		//UINT Weight,
	//	  0,	//UINT MipLevels,
	//	  false,	//BOOL Italic,
	//	  DEFAULT_CHARSET,	 //DWORD CharSet,
	//	  0,	//DWORD OutputPrecision,
	//	  0,	//DWORD Quality,
	//	  0,	//DWORD PitchAndFamily,
	//	  "Arial",	//LPCTSTR pFacename,
	//	  &font	//LPD3DXFONT * ppFont
	//);
	//RECT rect = {-1, 0, Width, Height};

	/*
	Set projection matrix
	*/
	D3DXMATRIX proj;
	//正射投影
	//D3DXMatrixOrthoLH(&proj, 
	//	5, //width of the view volume
	//	5, //height of the view volume
	//	1.0f, //z-near
	//	1000.f); //z-far

	//透视投影
	D3DXMatrixPerspectiveFovLH(
		&proj,
		D3DX_PI * 0.25,
		(float)Width/(float)Height,
		1.0f,
		1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;
}
Пример #9
0
void LLSceneView::draw()
{
	S32 margin = 10;
	S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
	S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f);
	
	LLRect new_rect;
	new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height);
	setRect(new_rect);

	// Draw the window background
	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
	gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
	

	//aggregate some statistics

	//object sizes
	std::vector<F32> size[2];

	//triangle counts
	std::vector<S32> triangles[2]; 
	std::vector<S32> visible_triangles[2];
	S32 total_visible_triangles[] = {0, 0};
	S32 total_triangles[] = {0, 0};
	
	//streaming cost
	std::vector<F32> streaming_cost[2];
	F32 total_streaming[] = { 0.f, 0.f };

	//physics cost
	std::vector<F32> physics_cost[2];
	F32 total_physics[] = { 0.f, 0.f };
	

	U32 object_count = 0;

	LLViewerRegion* region = gAgent.getRegion();
	if (region)
	{
		for (U32 i = 0; i < gObjectList.getNumObjects(); ++i)
		{
			LLViewerObject* object = gObjectList.getObject(i);
			
			if (object && 
				object->getVolume()&&
				object->getRegion() == region)
			{
				U32 idx = object->isAttachment() ? 1 : 0;

				LLVolume* volume = object->getVolume();
				object_count++;
				
				F32 radius = object->getScale().magVec();
				size[idx].push_back(radius);

				S32 visible = volume->getNumTriangles();
				S32 high_triangles = object->getHighLODTriangleCount();

				total_visible_triangles[idx] += visible;
				total_triangles[idx] += high_triangles;

				visible_triangles[idx].push_back(visible);
				triangles[idx].push_back(high_triangles);

				F32 streaming = object->getStreamingCost();
				total_streaming[idx] += streaming;
				streaming_cost[idx].push_back(streaming);

				F32 physics = object->getPhysicsCost();
				total_physics[idx] += physics;
				physics_cost[idx].push_back(physics);
			}
		}
	}

	const char* category[] =
	{
		"Region",
		"Attachment"
	};

	S32 graph_pos[4];

	for (U32 i = 0; i < 4; ++i)
	{
		graph_pos[i] = new_rect.getHeight()/4*(i+1);
	}

	for (U32 idx = 0; idx < 2; idx++)
	{
		if (!size[idx].empty())
		{ //display graph of object sizes
			std::sort(size[idx].begin(), size[idx].end());

			ll_remove_outliers(size[idx], 1.f);

			LLRect size_rect;
			
			if (idx == 0)
			{
				size_rect = LLRect(margin, graph_pos[0]-margin, new_rect.getWidth()/2-margin, margin*2);
			}
			else
			{
				size_rect = LLRect(margin+new_rect.getWidth()/2, graph_pos[0]-margin, new_rect.getWidth()-margin, margin*2);
			}

			gl_rect_2d(size_rect, LLColor4::white, false);

			F32 size_domain[] = { 128.f, 0.f };
			
			//get domain of sizes
			for (U32 i = 0; i < size[idx].size(); ++i)
			{
				size_domain[0] = llmin(size_domain[0], size[idx][i]);
				size_domain[1] = llmax(size_domain[1], size[idx][i]);
			}

			F32 size_range = size_domain[1]-size_domain[0];
			
			U32 count = size[idx].size();

			F32 total = 0.f;

			gGL.begin(LLRender::LINE_STRIP);

			for (U32 i = 0; i < count; ++i)
			{
				F32 rad = size[idx][i];
				total += rad;	
				F32 y = (rad-size_domain[0])/size_range*size_rect.getHeight()+size_rect.mBottom;
				F32 x = (F32) i / count * size_rect.getWidth() + size_rect.mLeft;

				gGL.vertex2f(x,y);

				if (i%4096 == 0)
				{
					gGL.end();
					gGL.flush();
					gGL.begin(LLRender::LINE_STRIP);
				}
			}

			gGL.end();
			gGL.flush();

			std::string label = llformat("%s Object Sizes (m) -- [%.1f, %.1f] Mean: %.1f  Median: %.1f -- %d samples",
											category[idx], size_domain[0], size_domain[1], total/count, size[idx][count/2], count);

			LLFontGL::getFontMonospace()->renderUTF8(label,
											0 , size_rect.mLeft, size_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);

		}
	}

	for (U32 idx = 0; idx < 2; ++idx)
	{
		if (!triangles[idx].empty())
		{ //plot graph of visible/total triangles
			std::sort(triangles[idx].begin(), triangles[idx].end());
			
			ll_remove_outliers(triangles[idx], 1.f);
			
			LLRect tri_rect;
			if (idx == 0)
			{
				tri_rect = LLRect(margin, graph_pos[1]-margin, new_rect.getWidth()/2-margin, graph_pos[0]+margin);
			}
			else
			{
				tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[1]-margin, new_rect.getWidth()-margin, graph_pos[0]+margin);
			}

			gl_rect_2d(tri_rect, LLColor4::white, false);

			S32 tri_domain[] = { 65536, 0 };
						
			//get domain of triangle counts
			for (U32 i = 0; i < triangles[idx].size(); ++i)
			{
				tri_domain[0] = llmin(tri_domain[0], triangles[idx][i]);
				tri_domain[1] = llmax(tri_domain[1], triangles[idx][i]);		
			}

			U32 triangle_range = tri_domain[1]-tri_domain[0];

			U32 count = triangles[idx].size();

			U32 total = 0;

			gGL.begin(LLRender::LINE_STRIP);
			//plot triangles
			for (U32 i = 0; i < count; ++i)
			{
				U32 tri_count = triangles[idx][i];
				total += tri_count;	
				F32 y = (F32) (tri_count-tri_domain[0])/triangle_range*tri_rect.getHeight()+tri_rect.mBottom;
				F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;

				gGL.vertex2f(x,y);

				if (i%4096 == 0)
				{
					gGL.end();
					gGL.flush();
					gGL.begin(LLRender::LINE_STRIP);
				}
			}

			gGL.end();
			gGL.flush();

			U32 total_visible = 0;
			count = visible_triangles[idx].size();

			for (U32 i = 0; i < count; ++i)
			{
				U32 tri_count = visible_triangles[idx][i];
				total_visible += tri_count;	
			}

			std::string label = llformat("%s Object Triangle Counts (Ktris) -- [%.2f, %.2f] Mean: %.2f  Median: %.2f  Visible: %.2f/%.2f",
											category[idx], tri_domain[0]/1024.f, tri_domain[1]/1024.f, (total/count)/1024.f, triangles[idx][count/2]/1024.f, total_visible_triangles[idx]/1024.f, total_triangles[idx]/1024.f);

			LLFontGL::getFontMonospace()->renderUTF8(label,
											0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);

		}
	}

	for (U32 idx = 0; idx < 2; ++idx)
	{
		if (!streaming_cost[idx].empty())
		{ //plot graph of streaming cost
			std::sort(streaming_cost[idx].begin(), streaming_cost[idx].end());
			
			ll_remove_outliers(streaming_cost[idx], 1.f);
			
			LLRect tri_rect;
			if (idx == 0)
			{
				tri_rect = LLRect(margin, graph_pos[2]-margin, new_rect.getWidth()/2-margin, graph_pos[1]+margin);
			}
			else
			{
				tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[2]-margin, new_rect.getWidth()-margin, graph_pos[1]+margin);
			}

			gl_rect_2d(tri_rect, LLColor4::white, false);

			F32 streaming_domain[] = { 65536, 0 };
						
			//get domain of triangle counts
			for (U32 i = 0; i < streaming_cost[idx].size(); ++i)
			{
				streaming_domain[0] = llmin(streaming_domain[0], streaming_cost[idx][i]);
				streaming_domain[1] = llmax(streaming_domain[1], streaming_cost[idx][i]);		
			}

			F32 cost_range = streaming_domain[1]-streaming_domain[0];

			U32 count = streaming_cost[idx].size();

			F32 total = 0;

			gGL.begin(LLRender::LINE_STRIP);
			//plot triangles
			for (U32 i = 0; i < count; ++i)
			{
				F32 sc = streaming_cost[idx][i];
				total += sc;	
				F32 y = (F32) (sc-streaming_domain[0])/cost_range*tri_rect.getHeight()+tri_rect.mBottom;
				F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;

				gGL.vertex2f(x,y);

				if (i%4096 == 0)
				{
					gGL.end();
					gGL.flush();
					gGL.begin(LLRender::LINE_STRIP);
				}
			}

			gGL.end();
			gGL.flush();

			std::string label = llformat("%s Object Streaming Cost -- [%.2f, %.2f] Mean: %.2f  Total: %.2f",
											category[idx], streaming_domain[0], streaming_domain[1], total/count, total_streaming[idx]);

			LLFontGL::getFontMonospace()->renderUTF8(label,
											0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);

		}
	}

	for (U32 idx = 0; idx < 2; ++idx)
	{
		if (!physics_cost[idx].empty())
		{ //plot graph of physics cost
			std::sort(physics_cost[idx].begin(), physics_cost[idx].end());
			
			ll_remove_outliers(physics_cost[idx], 1.f);
			
			LLRect tri_rect;
			if (idx == 0)
			{
				tri_rect = LLRect(margin, graph_pos[3]-margin, new_rect.getWidth()/2-margin, graph_pos[2]+margin);
			}
			else
			{
				tri_rect = LLRect(new_rect.getWidth()/2+margin, graph_pos[3]-margin, new_rect.getWidth()-margin, graph_pos[2]+margin);
			}

			gl_rect_2d(tri_rect, LLColor4::white, false);

			F32 physics_domain[] = { 65536, 0 };
						
			//get domain of triangle counts
			for (U32 i = 0; i < physics_cost[idx].size(); ++i)
			{
				physics_domain[0] = llmin(physics_domain[0], physics_cost[idx][i]);
				physics_domain[1] = llmax(physics_domain[1], physics_cost[idx][i]);		
			}

			F32 cost_range = physics_domain[1]-physics_domain[0];

			U32 count = physics_cost[idx].size();

			F32 total = 0;

			gGL.begin(LLRender::LINE_STRIP);
			//plot triangles
			for (U32 i = 0; i < count; ++i)
			{
				F32 pc = physics_cost[idx][i];
				total += pc;	
				F32 y = (F32) (pc-physics_domain[0])/cost_range*tri_rect.getHeight()+tri_rect.mBottom;
				F32 x = (F32) i / count * tri_rect.getWidth() + tri_rect.mLeft;

				gGL.vertex2f(x,y);

				if (i%4096 == 0)
				{
					gGL.end();
					gGL.flush();
					gGL.begin(LLRender::LINE_STRIP);
				}
			}

			gGL.end();
			gGL.flush();

			std::string label = llformat("%s Object Physics Cost -- [%.2f, %.2f] Mean: %.2f  Total: %.2f",
											category[idx], physics_domain[0], physics_domain[1], total/count, total_physics[idx]);

			LLFontGL::getFontMonospace()->renderUTF8(label,
											0 , tri_rect.mLeft, tri_rect.mTop+margin, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);

		}
	}

	
	

	LLView::draw();
}
Пример #10
0
BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
								const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume)
{
	LLMemType mt1(LLMemType::MTYPE_DRAWABLE);

	//get bounding box
	if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION
#if MESH_ENABLED
		| LLDrawable::REBUILD_RIGGED
#endif //MESH_ENABLED
		))
	{
		//VECTORIZE THIS
		LLMatrix4a mat_vert;
		mat_vert.loadu(mat_vert_in);

		LLMatrix4a mat_normal;
		mat_normal.loadu(mat_normal_in);

		//if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
		//{ //vertex buffer no longer valid
		//	mVertexBuffer = NULL;
		//	mLastVertexBuffer = NULL;
		//}

		//VECTORIZE THIS
		LLVector4a min,max;
	
		if (f >= volume.getNumVolumeFaces())
		{
			llwarns << "Generating bounding box for invalid face index!" << llendl;
			f = 0;
		}

		const LLVolumeFace &face = volume.getVolumeFace(f);
		min = face.mExtents[0];
		max = face.mExtents[1];
		
		llassert(less_than_max_mag(min));
		llassert(less_than_max_mag(max));

		//min, max are in volume space, convert to drawable render space
		LLVector4a center;
		LLVector4a t;
		t.setAdd(min, max);
		t.mul(0.5f);
		mat_vert.affineTransform(t, center);
		LLVector4a size;
		size.setSub(max, min);
		size.mul(0.5f);

		llassert(less_than_max_mag(min));
		llassert(less_than_max_mag(max));

		if (!global_volume)
		{
			//VECTORIZE THIS
			LLVector4a scale;
			scale.load3(mDrawablep->getVObj()->getScale().mV);
			size.mul(scale);
		}

		mat_normal.mMatrix[0].normalize3fast();
		mat_normal.mMatrix[1].normalize3fast();
		mat_normal.mMatrix[2].normalize3fast();
		
		LLVector4a v[4];

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

		//VECTORIZE THIS
		LLVector4a scale;
		
		scale.set(-1.f, -1.f, 1.f);
		scale.mul(size);
		mat_normal.rotate(scale, v[1]);
		
		scale.set(1.f, -1.f, -1.f);
		scale.mul(size);
		mat_normal.rotate(scale, v[2]);
		
		scale.set(-1.f, 1.f, -1.f);
		scale.mul(size);
		mat_normal.rotate(scale, v[3]);

		LLVector4a& newMin = mExtents[0];
		LLVector4a& newMax = mExtents[1];
		
		newMin = newMax = center;
		
		llassert(less_than_max_mag(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);

			llassert(less_than_max_mag(newMin));
			llassert(less_than_max_mag(newMax));
		}

		if (!mDrawablep->isActive())
		{
			LLVector4a offset;
			offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
			newMin.add(offset);
			newMax.add(offset);
			
			llassert(less_than_max_mag(newMin));
			llassert(less_than_max_mag(newMax));
		}

		t.setAdd(newMin, newMax);
		t.mul(0.5f);

		llassert(less_than_max_mag(t));
		
		//VECTORIZE THIS
		mCenterLocal.set(t.getF32ptr());
		
		llassert(less_than_max_mag(newMin));
		llassert(less_than_max_mag(newMax));

		t.setSub(newMax,newMin);
		mBoundingSphereRadius = t.getLength3().getF32()*0.5f;

		updateCenterAgent();
	}

	return TRUE;
}
Пример #11
0
BOOL LLFace::getGeometryVolume(const LLVolume& volume,
							   const S32 &f,
								const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in,
								const U16 &index_offset,
								bool force_rebuild)
{
	llassert(verify());
	const LLVolumeFace &vf = volume.getVolumeFace(f);
	S32 num_vertices = (S32)vf.mNumVertices;
	S32 num_indices = (S32) vf.mNumIndices;
	
	if (mVertexBuffer.notNull())
	{
		if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices())
		{
			llwarns	<< "Index buffer overflow!" << llendl;
			llwarns << "Indices Count: " << mIndicesCount
					<< " VF Num Indices: " << num_indices
					<< " Indices Index: " << mIndicesIndex
					<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl;
			llwarns	<< "Last Indices Count: " << mLastIndicesCount
					<< " Last Indices Index: " << mLastIndicesIndex
					<< " Face Index: " << f
					<< " Pool Type: " << mPoolType << llendl;
			return FALSE;
		}

		if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts())
		{
			llwarns << "Vertex buffer overflow!" << llendl;
			return FALSE;
		}
	}

	LLStrider<LLVector3> vertices;
	LLStrider<LLVector2> tex_coords;
	LLStrider<LLVector2> tex_coords2;
	LLStrider<LLVector3> normals;
	LLStrider<LLColor4U> colors;
	LLStrider<LLVector3> binormals;
	LLStrider<U16> indicesp;
#if MESH_ENABLED
	LLStrider<LLVector4> weights;
#endif //MESH_ENABLED

	BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
	
	BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();
	LLVector3 scale;
	if (global_volume)
	{
		scale.setVec(1,1,1);
	}
	else
	{
		scale = mVObjp->getScale();
	}
	
	bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION);
	bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR);
	bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);
	bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
	bool rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL);
#if MESH_ENABLED
	bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4);
#endif //MESH_ENABLED

	const LLTextureEntry *tep = mVObjp->getTE(f);
	if (!tep) rebuild_color = FALSE;	// can't get color when tep is NULL
	U8  bump_code = tep ? tep->getBumpmap() : 0;


	
	BOOL is_static = mDrawablep->isStatic();
	BOOL is_global = is_static;

	LLVector3 center_sum(0.f, 0.f, 0.f);
	
	if (is_global)
	{
		setState(GLOBAL);
	}
	else
	{
		clearState(GLOBAL);
	}

	LLColor4U color = (tep ? LLColor4U(tep->getColor()) : LLColor4U::white);

	if (rebuild_color)	// FALSE if tep == NULL
	{
		if (tep)
		{
			GLfloat alpha[4] =
			{
				0.00f,
				0.25f,
				0.5f,
				0.75f
			};
			
			if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny())))
			{
				color.mV[3] = U8 (alpha[tep->getShiny()] * 255);
			}
		}
	}

    // INDICES
	if (full_rebuild)
	{
		mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
		for (U32 i = 0; i < (U32) num_indices; i++)
		{
			indicesp[i] = vf.mIndices[i] + index_offset;
		}

		//mVertexBuffer->setBuffer(0);
	}
	
	LLMatrix4a mat_normal;
	mat_normal.loadu(mat_norm_in);
	
	//if it's not fullbright and has no normals, bake sunlight based on face normal
	//bool bake_sunlight = !getTextureEntry()->getFullbright() &&
	//  !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);

	F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0;

	if (rebuild_tcoord)
	{
		bool do_xform;
			
		if (tep)
		{
			r  = tep->getRotation();
			os = tep->mOffsetS;
			ot = tep->mOffsetT;
			ms = tep->mScaleS;
			mt = tep->mScaleT;
			cos_ang = cos(r);
			sin_ang = sin(r);

			if (cos_ang != 1.f || 
				sin_ang != 0.f ||
				os != 0.f ||
				ot != 0.f ||
				ms != 1.f ||
				mt != 1.f)
			{
				do_xform = true;
			}
			else
			{
				do_xform = false;
			}	
		}
		else
		{
			do_xform = false;
		}
						
		//bump setup
		LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f );
		LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f);
		LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f);

		LLQuaternion bump_quat;
		if (mDrawablep->isActive())
		{
			bump_quat = LLQuaternion(mDrawablep->getRenderMatrix());
		}
		
		if (bump_code)
		{
			mVObjp->getVolume()->genBinormals(f);
			F32 offset_multiple; 
			switch( bump_code )
			{
				case BE_NO_BUMP:
				offset_multiple = 0.f;
				break;
				case BE_BRIGHTNESS:
				case BE_DARKNESS:
				if( mTexture.notNull() && mTexture->hasGLTexture())
				{
					// Offset by approximately one texel
					S32 cur_discard = mTexture->getDiscardLevel();
					S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() );
					max_size <<= cur_discard;
					const F32 ARTIFICIAL_OFFSET = 2.f;
					offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size;
				}
				else
				{
					offset_multiple = 1.f/256;
				}
				break;

				default:  // Standard bumpmap textures.  Assumed to be 256x256
				offset_multiple = 1.f / 256;
				break;
			}

			F32 s_scale = 1.f;
			F32 t_scale = 1.f;
			if( tep )
			{
				tep->getScale( &s_scale, &t_scale );
			}
			// Use the nudged south when coming from above sun angle, such
			// that emboss mapping always shows up on the upward faces of cubes when 
			// it's noon (since a lot of builders build with the sun forced to noon).
			LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir;
			LLVector3   moon_ray = gSky.getMoonDirection();
			LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray;

			bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV);
			bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV);
		}

		U8 texgen = getTextureEntry()->getTexGen();
		if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT)
		{ //planar texgen needs binormals
			mVObjp->getVolume()->genBinormals(f);
		}

		U8 tex_mode = 0;
	
		if (isState(TEXTURE_ANIM))
		{
			LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;	
			tex_mode = vobj->mTexAnimMode;

			if (!tex_mode)
			{
				clearState(TEXTURE_ANIM);
			}
			else
			{
				os = ot = 0.f;
				r = 0.f;
				cos_ang = 1.f;
				sin_ang = 0.f;
				ms = mt = 1.f;

				do_xform = false;
			}

			if (getVirtualSize() >= MIN_TEX_ANIM_SIZE)
			{ //don't override texture transform during tc bake
				tex_mode = 0;
			}
		}
	
		LLVector4a scalea;
		scalea.load3(scale.mV);

		bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
		bool do_tex_mat = tex_mode && mTextureMatrix;

		if (!do_bump)
		{ //not in atlas or not bump mapped, might be able to do a cheap update
			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);

			if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
			{
				if (!do_tex_mat)
				{
					if (!do_xform)
					{
						tex_coords.assignArray((U8*) vf.mTexCoords, sizeof(vf.mTexCoords[0]), num_vertices);
					}
					else
					{
						for (S32 i = 0; i < num_vertices; i++)
						{	
							LLVector2 tc(vf.mTexCoords[i]);
							xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
							*tex_coords++ = tc;	
						}
					}
				}
				else
				{ //do tex mat, no texgen, no atlas, no bump
					for (S32 i = 0; i < num_vertices; i++)
					{	
						LLVector2 tc(vf.mTexCoords[i]);
						//LLVector4a& norm = vf.mNormals[i];
						//LLVector4a& center = *(vf.mCenter);

						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
						tmp = tmp * *mTextureMatrix;
						tc.mV[0] = tmp.mV[0];
						tc.mV[1] = tmp.mV[1];
						*tex_coords++ = tc;	
					}
				}
			}
			else
			{ //no bump, no atlas, tex gen planar
				if (do_tex_mat)
				{
					for (S32 i = 0; i < num_vertices; i++)
					{	
						LLVector2 tc(vf.mTexCoords[i]);
						LLVector4a& norm = vf.mNormals[i];
						LLVector4a& center = *(vf.mCenter);
						LLVector4a vec = vf.mPositions[i];	
						vec.mul(scalea);
						planarProjection(tc, norm, center, vec);
						
						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
						tmp = tmp * *mTextureMatrix;
						tc.mV[0] = tmp.mV[0];
						tc.mV[1] = tmp.mV[1];
				
						*tex_coords++ = tc;	
					}
				}
				else
				{
					for (S32 i = 0; i < num_vertices; i++)
					{	
						LLVector2 tc(vf.mTexCoords[i]);
						LLVector4a& norm = vf.mNormals[i];
						LLVector4a& center = *(vf.mCenter);
						LLVector4a vec = vf.mPositions[i];	
						vec.mul(scalea);
						planarProjection(tc, norm, center, vec);
						
						xform(tc, cos_ang, sin_ang, os, ot, ms, mt);

						*tex_coords++ = tc;	
					}
				}
			}

			//mVertexBuffer->setBuffer(0);
		}
		else
		{ //either bump mapped or in atlas, just do the whole expensive loop
			mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);

			std::vector<LLVector2> bump_tc;
		
			for (S32 i = 0; i < num_vertices; i++)
			{	
				LLVector2 tc(vf.mTexCoords[i]);
			
				LLVector4a& norm = vf.mNormals[i];
				
				LLVector4a& center = *(vf.mCenter);
		   
				if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
				{
					LLVector4a vec = vf.mPositions[i];
				
					vec.mul(scalea);

					switch (texgen)
					{
						case LLTextureEntry::TEX_GEN_PLANAR:
							planarProjection(tc, norm, center, vec);
							break;
						case LLTextureEntry::TEX_GEN_SPHERICAL:
							sphericalProjection(tc, norm, center, vec);
							break;
						case LLTextureEntry::TEX_GEN_CYLINDRICAL:
							cylindricalProjection(tc, norm, center, vec);
							break;
						default:
							break;
					}		
				}

				if (tex_mode && mTextureMatrix)
				{
					LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
					tmp = tmp * *mTextureMatrix;
					tc.mV[0] = tmp.mV[0];
					tc.mV[1] = tmp.mV[1];
				}
				else
				{
					xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
				}


				*tex_coords++ = tc;
				if (do_bump)
				{
					bump_tc.push_back(tc);
				}
			}

			//mVertexBuffer->setBuffer(0);


			if (do_bump)
			{
				mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex);
		
				for (S32 i = 0; i < num_vertices; i++)
				{
					LLVector4a tangent;
					tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]);

					LLMatrix4a tangent_to_object;
					tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]);
					LLVector4a t;
					tangent_to_object.rotate(binormal_dir, t);
					LLVector4a binormal;
					mat_normal.rotate(t, binormal);
						
					//VECTORIZE THIS
					if (mDrawablep->isActive())
					{
						LLVector3 t;
						t.set(binormal.getF32ptr());
						t *= bump_quat;
						binormal.load3(t.mV);
					}

					binormal.normalize3fast();
					LLVector2 tc = bump_tc[i];
					tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
					
					*tex_coords2++ = tc;
				}

				//mVertexBuffer->setBuffer(0);
			}
		}
	}

	if (rebuild_pos)
	{
		llassert(num_vertices > 0);
		mVertexBuffer->getVertexStrider(vertices, mGeomIndex);
		LLMatrix4a mat_vert;
		mat_vert.loadu(mat_vert_in);
		
		LLVector4a* src = vf.mPositions;
		LLVector4a position;
		for (S32 i = 0; i < num_vertices; i++)
		{
			mat_vert.affineTransform(src[i], position);
			vertices[i].set(position.getF32ptr());
		}
			
			
		//mVertexBuffer->setBuffer(0);
	}
		
	if (rebuild_normal)
	{
		mVertexBuffer->getNormalStrider(normals, mGeomIndex);
		for (S32 i = 0; i < num_vertices; i++)
		{	
			LLVector4a normal;
			mat_normal.rotate(vf.mNormals[i], normal);
			normal.normalize3fast();
			normals[i].set(normal.getF32ptr());
		}

		//mVertexBuffer->setBuffer(0);
	}
		
	if (rebuild_binormal)
	{
		mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);
		for (S32 i = 0; i < num_vertices; i++)
		{	
			LLVector4a binormal;
			mat_normal.rotate(vf.mBinormals[i], binormal);
			binormal.normalize3fast();
			binormals[i].set(binormal.getF32ptr());
		}

		//mVertexBuffer->setBuffer(0);
	}
	
#if MESH_ENABLED
	if (rebuild_weights && vf.mWeights)
	{
		mVertexBuffer->getWeight4Strider(weights, mGeomIndex);
		weights.assignArray((U8*) vf.mWeights, sizeof(vf.mWeights[0]), num_vertices);
		//mVertexBuffer->setBuffer(0);
	}
#endif //MESH_ENABLED

	if (rebuild_color)
	{
		mVertexBuffer->getColorStrider(colors, mGeomIndex);
		for (S32 i = 0; i < num_vertices; i++)
		{
			colors[i] = color;	
		}

		//mVertexBuffer->setBuffer(0);
	}

	if (rebuild_tcoord)
	{
		mTexExtents[0].setVec(0,0);
		mTexExtents[1].setVec(1,1);
		xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt);
		xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt);
		
		F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ;
		F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ;
		mTexExtents[0][0] *= es ;
		mTexExtents[1][0] *= es ;
		mTexExtents[0][1] *= et ;
		mTexExtents[1][1] *= et ;
	}

	mLastVertexBuffer = mVertexBuffer;
	mLastGeomCount = mGeomCount;
	mLastGeomIndex = mGeomIndex;
	mLastIndicesCount = mIndicesCount;
	mLastIndicesIndex = mIndicesIndex;

	return TRUE;
}
void LLPanelMediaHUD::updateShape()
{
	const S32 MIN_HUD_WIDTH=200;
	const S32 MIN_HUD_HEIGHT=120;

	LLPluginClassMedia* media_plugin = NULL;
	if(mMediaImpl.notNull() && mMediaImpl->hasMedia())
	{
		media_plugin = mMediaImpl->getMediaPlugin();
	}

	// Early out for no media plugin
	if(media_plugin == NULL)
	{
		setVisible(FALSE);
		return;
	}

	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();

	bool can_navigate = parcel->getMediaAllowNavigate();

	// LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection();

	LLSelectNode* nodep = mMediaFocus ? LLSelectMgr::getInstance()->getSelection()->getFirstNode() : LLSelectMgr::getInstance()->getHoverNode();
	if(! nodep)
	{
		return;
	}
	setVisible(FALSE);
	LLViewerObject* objectp = nodep->getObject();

	if (objectp)
	{

		// Set the state of the buttons
		LLButton* back_btn = getChild<LLButton>("back");
		LLButton* fwd_btn = getChild<LLButton>("fwd");
		LLButton* reload_btn = getChild<LLButton>("reload");
		LLButton* play_btn = getChild<LLButton>("play");
		LLButton* pause_btn = getChild<LLButton>("pause");
		LLButton* stop_btn = getChild<LLButton>("stop");
		LLButton* media_stop_btn = getChild<LLButton>("media_stop");
		LLButton* home_btn = getChild<LLButton>("home");
		LLButton* close_btn = getChild<LLButton>("close");
		LLButton* open_btn = getChild<LLButton>("new_window");
		LLPanel* media_focused_panel = getChild<LLPanel>("media_focused_controls");
		LLPanel* media_hover_panel = getChild<LLPanel>("media_hover_controls");
		back_btn->setVisible(true);
		fwd_btn->setVisible(true);
		reload_btn->setVisible(true);
		stop_btn->setVisible(false);
		home_btn->setVisible(true);
		close_btn->setVisible(true);
		open_btn->setVisible(true);


		if(mMediaFocus)
		{
			back_btn->setEnabled(mMediaImpl->canNavigateBack() && can_navigate);
			fwd_btn->setEnabled(mMediaImpl->canNavigateForward() && can_navigate);
			stop_btn->setEnabled(can_navigate);
			home_btn->setEnabled(can_navigate);
			LLPluginClassMediaOwner::EMediaStatus result = media_plugin->getStatus();

			if(media_plugin->pluginSupportsMediaTime())
			{
				reload_btn->setEnabled(FALSE);
				reload_btn->setVisible(FALSE);
				media_stop_btn->setVisible(TRUE);
				home_btn->setVisible(FALSE);
				back_btn->setEnabled(TRUE);
				fwd_btn->setEnabled(TRUE);
				switch(result)
				{
				case LLPluginClassMediaOwner::MEDIA_PLAYING:
					play_btn->setEnabled(FALSE);
					play_btn->setVisible(FALSE);
					pause_btn->setEnabled(TRUE);
					pause_btn->setVisible(TRUE);
					media_stop_btn->setEnabled(TRUE);
					break;
				case LLPluginClassMediaOwner::MEDIA_PAUSED:
				default:
					pause_btn->setEnabled(FALSE);
					pause_btn->setVisible(FALSE);
					play_btn->setEnabled(TRUE);
					play_btn->setVisible(TRUE);
					media_stop_btn->setEnabled(FALSE);
					break;
				}
			}
			else
			{
				play_btn->setVisible(FALSE);
				pause_btn->setVisible(FALSE);
				media_stop_btn->setVisible(FALSE);
				if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
				{
					reload_btn->setEnabled(FALSE);
					reload_btn->setVisible(FALSE);
					stop_btn->setEnabled(TRUE);
					stop_btn->setVisible(TRUE);
				}
				else
				{
					reload_btn->setEnabled(TRUE);
					reload_btn->setVisible(TRUE);
					stop_btn->setEnabled(FALSE);
					stop_btn->setVisible(FALSE);
				}
			}
		}
		media_focused_panel->setVisible(mMediaFocus);
		media_hover_panel->setVisible(!mMediaFocus);

		if(media_plugin == NULL)
		// Handle Scrolling
		switch (mScrollState) 
		{
		case SCROLL_UP:
			media_plugin->scrollEvent(0, -1, MASK_NONE);
			break;
		case SCROLL_DOWN:
			media_plugin->scrollEvent(0, 1, MASK_NONE);
			break;
		case SCROLL_LEFT:
			mMediaImpl->handleKeyHere(KEY_LEFT, MASK_NONE);
			break;
		case SCROLL_RIGHT:
			mMediaImpl->handleKeyHere(KEY_RIGHT, MASK_NONE);
			break;
		case SCROLL_NONE:
		default:
			break;
		}
		LLBBox screen_bbox;
		setVisible(TRUE);
		glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview();
		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(nodep->getLastSelectedTE());

			const LLVector3* ext = vf.mExtents;

			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();

		LLVector3 min = LLVector3(1,1,1);
		LLVector3 max = LLVector3(-1,-1,-1);
		for(; vert_it != vert_end; ++vert_it)
		{
			// project silhouette vertices into screen space
			glh::vec3f screen_vert = glh::vec3f(vert_it->mV); 
			mat.mult_matrix_vec(screen_vert);

			// add to screenspace bounding box
			update_min_max(min, max, LLVector3(screen_vert.v));
		}

		LLCoordGL screen_min;
		screen_min.mX = llround((F32)gViewerWindow->getWindowWidth() * (min.mV[VX] + 1.f) * 0.5f);
		screen_min.mY = llround((F32)gViewerWindow->getWindowHeight() * (min.mV[VY] + 1.f) * 0.5f);

		LLCoordGL screen_max;
		screen_max.mX = llround((F32)gViewerWindow->getWindowWidth() * (max.mV[VX] + 1.f) * 0.5f);
		screen_max.mY = llround((F32)gViewerWindow->getWindowHeight() * (max.mV[VY] + 1.f) * 0.5f);

		// grow panel so that screenspace bounding box fits inside "media_region" element of HUD
		LLRect media_hud_rect;
		getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_hud_rect);
		LLView* media_region = getChild<LLView>("media_region");
		media_hud_rect.mLeft -= media_region->getRect().mLeft;
		media_hud_rect.mBottom -= media_region->getRect().mBottom;
		media_hud_rect.mTop += getRect().getHeight() - media_region->getRect().mTop;
		media_hud_rect.mRight += getRect().getWidth() - media_region->getRect().mRight;


		LLRect old_hud_rect = media_hud_rect;
		// keep all parts of HUD on-screen
		media_hud_rect.intersectWith(getParent()->getLocalRect());

		// If we had to clip the rect, don't display the border
		childSetVisible("bg_image", false);

		// clamp to minimum size, keeping centered
		media_hud_rect.setCenterAndSize(media_hud_rect.getCenterX(), media_hud_rect.getCenterY(),
			llmax(MIN_HUD_WIDTH, media_hud_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_hud_rect.getHeight()));

		userSetShape(media_hud_rect);

		// 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)
		{
			mMouseMoveTimer.start();
			mLastCursorPos = cursor_pos_window;
		}
		
		// Mouse has been stationary, but not for long enough to fade the UI
		if(mMouseMoveTimer.getElapsedTimeF32() < mMouseInactiveTime)
		{
			// If we have started fading, reset the alpha values
			if(mFadeTimer.getStarted())
			{
				F32 alpha = 1.0f;
				setAlpha(alpha);
				mFadeTimer.stop();
			}
		}
		// If we need to start fading the UI (and we have not already started)
		else if(! mFadeTimer.getStarted())
		{
			mFadeTimer.reset();
			mFadeTimer.start();
		}
	}
}