예제 #1
0
BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
{
	//VECTORIZE THIS
	//get area of circle around face
	LLVector4a center;
	center.load3(getPositionAgent().mV);
	LLVector4a size;
	size.setSub(mExtents[1], mExtents[0]);
	size.mul(0.5f);

	LLViewerCamera* camera = LLViewerCamera::getInstance();

	F32 size_squared = size.dot3(size).getF32();
	LLVector4a lookAt;
	LLVector4a t;
	t.load3(camera->getOrigin().mV);
	lookAt.setSub(center, t);
	F32 dist = lookAt.getLength3().getF32();
	dist = llmax(dist-size.getLength3().getF32(), 0.f);
	lookAt.normalize3fast() ;	

	//get area of circle around node
	F32 app_angle = atanf((F32) sqrt(size_squared) / dist);
	radius = app_angle*LLDrawable::sCurPixelAngle;
	mPixelArea = radius*radius * 3.14159f;
	LLVector4a x_axis;
	x_axis.load3(camera->getXAxis().mV);
	cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32();

	if(dist < mBoundingSphereRadius) //camera is very close
	{
		cos_angle_to_view_dir = 1.0f;
		mImportanceToCamera = 1.0f;
	}
	else
	{
		mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist);
	}

	return true;
}
예제 #2
0
//-----------------------------------------------------------------------------
// postRender()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::postRender(BOOL success)
{
	{
		if (success)
		{
			if(mGLTexturep.isNull())
			{
				generateGLTexture() ;
			}
			else if(!mGLTexturep->getHasGLTexture())
			{
				generateGLTexture() ;
			}			
			else if(mGLTexturep->getDiscardLevel() != 0)//do not know how it happens, but regenerate one if it does.
			{
				generateGLTexture() ;
			}

			success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
		}
	}

	// restore viewport
	gViewerWindow->setup2DViewport();

	// restore camera
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	camera->setOrigin(mCamera);
	camera->setAxes(mCamera);
	camera->setAspect(mCamera.getAspect());
	camera->setView(mCamera.getView());
	camera->setNear(mCamera.getNear());
}
예제 #3
0
//-----------------------------------------------------------------------------
// postRender()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::postRender(BOOL success)
{
	{
		if (success)
		{
			if(mGLTexturep.isNull())
			{
				generateGLTexture() ;
			}
			if(!mGLTexturep->getHasGLTexture())
			{
				generateGLTexture() ;
			}
			llcallstacks << "class type: " << (S32)getType() << llcallstacksendl ;

			success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
		}
	}

	// restore viewport
	gViewerWindow->setup2DViewport();

	// restore camera
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	camera->setOrigin(mCamera);
	camera->setAxes(mCamera);
	camera->setAspect(mCamera.getAspect());
	camera->setView(mCamera.getView());
	camera->setNear(mCamera.getNear());
}
예제 #4
0
void LLAgentPilot::addAction(enum EActionType action_type)
{
	llinfos << "Adding waypoint: " << gAgent.getPositionGlobal() << llendl;
	Action action;
	action.mType = action_type;
	action.mTarget = gAgent.getPositionGlobal();
	action.mTime = mTimer.getElapsedTimeF32();
	LLViewerCamera *cam = LLViewerCamera::getInstance();
	action.mCameraView = cam->getView();
	action.mCameraOrigin = cam->getOrigin();
	action.mCameraXAxis = cam->getXAxis();
	action.mCameraYAxis = cam->getYAxis();
	action.mCameraZAxis = cam->getZAxis();
	mLastRecordTime = (F32)action.mTime;
	mActions.put(action);
}
예제 #5
0
void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
					const LLFontGL &font,
					const U8 style,
					const LLFontGL::ShadowType shadow,
					const F32 x_offset, const F32 y_offset,
					const LLColor4& color,
					const BOOL orthographic)
{
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	// Do cheap plane culling
	LLVector3 dir_vec = pos_agent - camera->getOrigin();
	dir_vec /= dir_vec.magVec();

	if (wstr.empty() || (!orthographic && dir_vec * camera->getAtAxis() <= 0.f))
	{
		return;
	}

	LLVector3 right_axis;
	LLVector3 up_axis;
	if (orthographic)
	{
		right_axis.setVec(0.f, -1.f / gViewerWindow->getWorldViewHeightScaled(), 0.f);
		up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWorldViewHeightScaled());
	}
	else
	{
		camera->getPixelVectors(pos_agent, up_axis, right_axis);
	}
	LLCoordFrame render_frame = *camera;
	LLQuaternion rot;
	if (!orthographic)
	{
		rot = render_frame.getQuaternion();
		rot = rot * LLQuaternion(-F_PI_BY_TWO, camera->getYAxis());
		rot = rot * LLQuaternion(F_PI_BY_TWO, camera->getXAxis());
	}
	else
	{
		rot = LLQuaternion(-F_PI_BY_TWO, LLVector3(0.f, 0.f, 1.f));
		rot = rot * LLQuaternion(-F_PI_BY_TWO, LLVector3(0.f, 1.f, 0.f));
	}
	F32 angle;
	LLVector3 axis;
	rot.getAngleAxis(&angle, axis);

	LLVector3 render_pos = pos_agent + (floorf(x_offset) * right_axis) + (floorf(y_offset) * up_axis);

	//get the render_pos in screen space
	
	LLVector3 window_coordinates;
	F32& winX = window_coordinates.mV[VX];
	F32& winY = window_coordinates.mV[VY];
	F32& winZ = window_coordinates.mV[VZ];

	const LLRect& world_view_rect = gViewerWindow->getWorldViewRectRaw();
	
	glProjectf(render_pos, gGLModelView, gGLProjection, world_view_rect, window_coordinates);

	//fonts all render orthographically, set up projection``
	gGL.matrixMode(LLRender::MM_PROJECTION);
	gGL.pushMatrix();
	gGL.matrixMode(LLRender::MM_MODELVIEW);
	gGL.pushMatrix();
	LLUI::pushMatrix();
		
	gl_state_for_2d(world_view_rect.getWidth(), world_view_rect.getHeight());
	gViewerWindow->setup3DViewport();
	
	winX -= world_view_rect.mLeft;
	winY -= world_view_rect.mBottom;
	LLUI::loadIdentity();
	gGL.loadIdentity();
	LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
	F32 right_x;
	
	font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x);
	LLUI::popMatrix();
	gGL.popMatrix();
	
	gGL.matrixMode(LLRender::MM_PROJECTION);
	gGL.popMatrix();
	gGL.matrixMode(LLRender::MM_MODELVIEW);
}
예제 #6
0
파일: llhudrender.cpp 프로젝트: Kiera/Crow
void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
					const LLFontGL &font,
					const U8 style,
					const F32 x_offset, const F32 y_offset,
					const LLColor4& color,
					const BOOL orthographic)
{
	LLViewerCamera* camera = LLViewerCamera::getInstance();
	// Do cheap plane culling
	LLVector3 dir_vec = pos_agent - camera->getOrigin();
	dir_vec /= dir_vec.magVec();

	if (wstr.empty() || (!orthographic && dir_vec * camera->getAtAxis() <= 0.f))
	{
		return;
	}

	LLVector3 right_axis;
	LLVector3 up_axis;
	if (orthographic)
	{
		right_axis.setVec(0.f, -1.f / gViewerWindow->getWindowHeight(), 0.f);
		up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWindowHeight());
	}
	else
	{
		camera->getPixelVectors(pos_agent, up_axis, right_axis);
	}
	LLCoordFrame render_frame = *camera;
	LLQuaternion rot;
	if (!orthographic)
	{
		rot = render_frame.getQuaternion();
		rot = rot * LLQuaternion(-F_PI_BY_TWO, camera->getYAxis());
		rot = rot * LLQuaternion(F_PI_BY_TWO, camera->getXAxis());
	}
	else
	{
		rot = LLQuaternion(-F_PI_BY_TWO, LLVector3(0.f, 0.f, 1.f));
		rot = rot * LLQuaternion(-F_PI_BY_TWO, LLVector3(0.f, 1.f, 0.f));
	}
	F32 angle;
	LLVector3 axis;
	rot.getAngleAxis(&angle, axis);

	LLVector3 render_pos = pos_agent + (floorf(x_offset) * right_axis) + (floorf(y_offset) * up_axis);

	//get the render_pos in screen space
	
	F64 winX, winY, winZ;
	gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2],
				gGLModelView, gGLProjection, (GLint*) gGLViewport,
				&winX, &winY, &winZ);
		
	//fonts all render orthographically, set up projection
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glMatrixMode(GL_MODELVIEW);
	
	LLUI::pushMatrix();
		
	gViewerWindow->setup2DRender();

	LLUI::loadIdentity();
	LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
	//glRotatef(angle * RAD_TO_DEG, axis.mV[VX], axis.mV[VY], axis.mV[VZ]);
	//glScalef(right_scale, up_scale, 1.f);
	F32 right_x;
	
	font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, wstr.length(), 1000, &right_x);
	LLUI::popMatrix();
	
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
}
//---------------------------------------------------
// this method is inherited from HUD Effect
//---------------------------------------------------
void LLVoiceVisualizer::render()
{
	if ( ! mVoiceEnabled )
	{
		return;
	}
	
	if ( mSoundSymbol.mActive ) 
	{				
		mPreviousTime = mCurrentTime;
		mCurrentTime = mTimer.getTotalSeconds();
	
		//---------------------------------------------------------------
		// set the sound symbol position over the source (avatar's head)
		//---------------------------------------------------------------
		mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD;
	
		//---------------------------------------------------------------
		// some gl state
		//---------------------------------------------------------------
		LLGLSPipelineAlpha alpha_blend;
		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
		
		//-------------------------------------------------------------
		// create coordinates of the geometry for the dot
		//-------------------------------------------------------------
		LLViewerCamera* camera = LLViewerCamera::getInstance();
		LLVector3 l	= camera->getLeftAxis() * DOT_SIZE;
		LLVector3 u	= camera->getUpAxis()   * DOT_SIZE;

		LLVector3 bottomLeft	= mSoundSymbol.mPosition + l - u;
		LLVector3 bottomRight	= mSoundSymbol.mPosition - l - u;
		LLVector3 topLeft		= mSoundSymbol.mPosition + l + u;
		LLVector3 topRight		= mSoundSymbol.mPosition - l + u;
		
		//-----------------------------
		// bind texture 0 (the dot)
		//-----------------------------
		gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]);
		
		//-------------------------------------------------------------
		// now render the dot
		//-------------------------------------------------------------
		gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV );	
		
		gGL.begin( LLRender::TRIANGLE_STRIP );
			gGL.texCoord2i( 0,	0	); gGL.vertex3fv( bottomLeft.mV );
			gGL.texCoord2i( 1,	0	); gGL.vertex3fv( bottomRight.mV );
			gGL.texCoord2i( 0,	1	); gGL.vertex3fv( topLeft.mV );
		gGL.end();

		gGL.begin( LLRender::TRIANGLE_STRIP );
			gGL.texCoord2i( 1,	0	); gGL.vertex3fv( bottomRight.mV );
			gGL.texCoord2i( 1,	1	); gGL.vertex3fv( topRight.mV );
			gGL.texCoord2i( 0,	1	); gGL.vertex3fv( topLeft.mV );
		gGL.end();
		
		
		
		//--------------------------------------------------------------------------------------
		// if currently speaking, trigger waves (1 through 6) based on speaking amplitude
		//--------------------------------------------------------------------------------------
		if ( mCurrentlySpeaking )
		{
			F32 min = 0.2f;
			F32 max = 0.7f;
			F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min );
		
			// in case mSpeakingAmplitude > max....
			if ( fraction > 1.0f )
			{
				fraction = 1.0f;
			}
														
			S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) );
																										
			for (int i=0; i<level+1; i++)
			{
				mSoundSymbol.mWaveActive			[i] = true;
				mSoundSymbol.mWaveOpacity			[i] = 1.0f;
				mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime;
			}			
			
		} // if currently speaking
								
		//---------------------------------------------------
		// determine color
		//---------------------------------------------------
		F32 red		= 0.0f;
		F32 green	= 0.0f;
		F32 blue	= 0.0f;
        if ( mSpeakingAmplitude < RED_THRESHOLD )
        {
			if ( mSpeakingAmplitude < GREEN_THRESHOLD )
			{
				red		= BASE_BRIGHTNESS;
				green	= BASE_BRIGHTNESS;
				blue	= BASE_BRIGHTNESS;
			}
			else
			{
				//---------------------------------------------------
				// fade from gray to bright green
				//---------------------------------------------------
				F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD );
				red		= BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
				green	= BASE_BRIGHTNESS +   fraction * ( 1.0f - BASE_BRIGHTNESS );
				blue	= BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
			}
        }
        else
        {
			//---------------------------------------------------
			// redish
			//---------------------------------------------------
			red		= 1.0f;
			green	= 0.2f;
			blue	= 0.2f;
        }
														
		for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
		{
			if ( mSoundSymbol.mWaveActive[i] ) 
			{
				F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION;

				mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction;
				
				if ( mSoundSymbol.mWaveOpacity[i] < 0.0f )
				{
					mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime;
					mSoundSymbol.mWaveOpacity			[i] = 0.0f;
					mSoundSymbol.mWaveActive			[i] = false;
				}
				
				//----------------------------------------------------------------------------------
				// This is where we calculate the expansion of the waves - that is, the
				// rate at which they are scaled greater than 1.0 so that they grow over time.
				//----------------------------------------------------------------------------------
				F32 timeSlice = (F32)( mCurrentTime - mPreviousTime );
				F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE;
				mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed );
				
				if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX )
				{
					mSoundSymbol.mWaveExpansion[i] = 1.0f;
				}			
								
				//----------------------------------------------------------------------------------
				// create geometry for the wave billboard textures
				//----------------------------------------------------------------------------------
				F32 width	= i * WAVE_WIDTH_SCALE  * mSoundSymbol.mWaveExpansion[i];
				F32 height	= i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i];

				LLVector3 l	= camera->getLeftAxis() * width;
				LLVector3 u	= camera->getUpAxis()   * height;

				LLVector3 bottomLeft	= mSoundSymbol.mPosition + l - u;
				LLVector3 bottomRight	= mSoundSymbol.mPosition - l - u;
				LLVector3 topLeft		= mSoundSymbol.mPosition + l + u;
				LLVector3 topRight		= mSoundSymbol.mPosition - l + u;
							
				gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV );		
				gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]);

				
				//---------------------------------------------------
				// now, render the mofo
				//---------------------------------------------------
				gGL.begin( LLRender::TRIANGLE_STRIP );
					gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV );
					gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
					gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
				gGL.end();

				gGL.begin( LLRender::TRIANGLE_STRIP );
					gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
					gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV );
					gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
				gGL.end();
				
			} //if ( mSoundSymbol.mWaveActive[i] ) 
			
		}// for loop
											
	}//if ( mSoundSymbol.mActive ) 

}//---------------------------------------------------
예제 #8
0
void LLNetMap::draw()
{
 	static LLFrameTimer map_timer;

	if (mObjectImagep.isNull())
	{
		createObjectImage();
	}

	LLCachedControl<S32> minimap_center(gSavedSettings, "MiniMapCenter");
	if (minimap_center != MAP_CENTER_NONE)
	{
		mCurPanX = lerp(mCurPanX, mTargetPanX, LLCriticalDamp::getInterpolant(0.1f));
		mCurPanY = lerp(mCurPanY, mTargetPanY, LLCriticalDamp::getInterpolant(0.1f));
	}

	LLViewerCamera* camera = LLViewerCamera::getInstance();

	F32 rotation = 0;

	// Prepare a scissor region
	{
		LLGLEnable scissor(GL_SCISSOR_TEST);

		{
			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
			LLLocalClipRect clip(getLocalRect());

			glMatrixMode(GL_MODELVIEW);

			// Draw background rectangle
			if(isBackgroundVisible())
			{
				gGL.color4fv(isBackgroundOpaque() ? getBackgroundColor().mV : getTransparentColor().mV);
				gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0);
			}
		}

		// region 0,0 is in the middle
		S32 center_sw_left = getRect().getWidth() / 2 + llfloor(mCurPanX);
		S32 center_sw_bottom = getRect().getHeight() / 2 + llfloor(mCurPanY);

		gGL.pushMatrix();

		gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f);

		BOOL rotate_map = gSavedSettings.getBOOL( "MiniMapRotate" );
		if( rotate_map )
		{
			// rotate subsequent draws to agent rotation
			rotation = atan2( camera->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] );
			glRotatef( rotation * RAD_TO_DEG, 0.f, 0.f, 1.f);
		}

		// figure out where agent is
		S32 region_width = llround(LLWorld::getInstance()->getRegionWidthInMeters());
		LLColor4 this_region_color = gColors.getColor( "NetMapThisRegion" );
		LLColor4 live_region_color = gColors.getColor( "NetMapLiveRegion" );
		LLColor4 dead_region_color = gColors.getColor( "NetMapDeadRegion" );

		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
			 iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
		{
			LLViewerRegion* regionp = *iter;
			// Find x and y position relative to camera's center.
			LLVector3 origin_agent = regionp->getOriginAgent();
			LLVector3 rel_region_pos = origin_agent - gAgent.getCameraPositionAgent();
			F32 relative_x = (rel_region_pos.mV[0] / region_width) * mScale;
			F32 relative_y = (rel_region_pos.mV[1] / region_width) * mScale;

			// background region rectangle
			F32 bottom =	relative_y;
			F32 left =		relative_x;
			F32 top =		bottom + mScale ;
			F32 right =		left + mScale ;

			gGL.color4fv(regionp == gAgent.getRegion() ? this_region_color.mV : live_region_color.mV);
			if (!regionp->isAlive())
			{
				gGL.color4fv(dead_region_color.mV);
			}


			// Draw using texture.
			gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture());
			gGL.begin(LLRender::QUADS);
				gGL.texCoord2f(0.f, 1.f);
				gGL.vertex2f(left, top);
				gGL.texCoord2f(0.f, 0.f);
				gGL.vertex2f(left, bottom);
				gGL.texCoord2f(1.f, 0.f);
				gGL.vertex2f(right, bottom);
				gGL.texCoord2f(1.f, 1.f);
				gGL.vertex2f(right, top);
			gGL.end();

			// Draw water
			gGL.setAlphaRejectSettings(LLRender::CF_GREATER, ABOVE_WATERLINE_ALPHA / 255.f);
			{
				if (regionp->getLand().getWaterTexture())
				{
					gGL.getTexUnit(0)->bind(regionp->getLand().getWaterTexture());
					gGL.begin(LLRender::QUADS);
						gGL.texCoord2f(0.f, 1.f);
						gGL.vertex2f(left, top);
						gGL.texCoord2f(0.f, 0.f);
						gGL.vertex2f(left, bottom);
						gGL.texCoord2f(1.f, 0.f);
						gGL.vertex2f(right, bottom);
						gGL.texCoord2f(1.f, 1.f);
						gGL.vertex2f(right, top);
					gGL.end();
				}
			}
			gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
		}

		// Redraw object layer periodically
		if (mUpdateNow || (map_timer.getElapsedTimeF32() > 0.5f))
		{
			mUpdateNow = FALSE;

			// Locate the centre of the object layer, accounting for panning
			LLVector3 new_center = globalPosToView(gAgent.getCameraPositionGlobal(), rotate_map);	
			new_center.mV[0] -= mCurPanX;
			new_center.mV[1] -= mCurPanY;
			new_center.mV[2] = 0.f;
			mObjectImageCenterGlobal = viewPosToGlobal(llround(new_center.mV[0]), llround(new_center.mV[1]), rotate_map);

			// Create the base texture.
			U8 *default_texture = mObjectRawImagep->getData();
			memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() );

			// Draw buildings
			//gObjectList.renderObjectsForMap(*this);
			LLCachedControl<bool> mm_fastminimap(gSavedSettings, "mm_fastminimap");
			if (!mm_fastminimap)
			{
				gObjectList.renderObjectsForMap(*this);
				mObjectImagep->setSubImage(mObjectRawImagep, 0, 0, mObjectImagep->getWidth(), mObjectImagep->getHeight());
			}

			mObjectImagep->setSubImage(mObjectRawImagep, 0, 0, mObjectImagep->getWidth(), mObjectImagep->getHeight());
			
			map_timer.reset();
		}

		LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal);
		map_center_agent -= gAgent.getCameraPositionAgent();
		map_center_agent.mV[VX] *= mScale/region_width;
		map_center_agent.mV[VY] *= mScale/region_width;

		gGL.getTexUnit(0)->bind(mObjectImagep);
		F32 image_half_width = 0.5f*mObjectMapPixels;
		F32 image_half_height = 0.5f*mObjectMapPixels;

		gGL.begin(LLRender::QUADS);
			gGL.texCoord2f(0.f, 1.f);
			gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, image_half_height + map_center_agent.mV[VY]);
			gGL.texCoord2f(0.f, 0.f);
			gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, map_center_agent.mV[VY] - image_half_height);
			gGL.texCoord2f(1.f, 0.f);
			gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height);
			gGL.texCoord2f(1.f, 1.f);
			gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]);
		gGL.end();

		gGL.popMatrix();

		LLVector3d pos_global;
		LLVector3 pos_map;

		// Mouse pointer in local coordinates
		S32 local_mouse_x;
		S32 local_mouse_y;
		LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
		mClosestAgentToCursor.setNull();
		F32 closest_dist = F32_MAX;
		F32 min_pick_dist = mDotRadius * MIN_PICK_SCALE; 

		// Draw avatars
//		LLColor4 mapcolor = gAvatarMapColor;
		static LLCachedControl<LLColor4U> sMapAvatar(gColors, "MapAvatar");
		LLColor4 avatar_color = (LLColor4)sMapAvatar;

		LLColor4 standard_color = avatar_color;
		//LLColor4 friend_color = gColors.getColor( "MapFriend" );
// [RLVa:KB] - Version: 1.23.4 | Alternate: Snowglobe-1.2.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b
		LLColor4 friend_color = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? gColors.getColor("MapFriend") : avatar_color;
// [/RLVa:KB]
		LLColor4 linden_color = gColors.getColor( "MapLinden" );
		LLColor4 muted_color = gColors.getColor( "MapMuted" );

		std::vector<LLUUID> avatar_ids;
		std::vector<LLVector3d> positions;
		LLWorld::getInstance()->getAvatars(&avatar_ids, &positions);
		U32 a;
		static LLCachedControl<bool> friendsGroupsOnMinimap(gSavedSettings, "PhoenixContactSetsColorizeMiniMap");
		for(U32 i=0; i<avatar_ids.size(); i++)
		{
			avatar_color = standard_color;
			// TODO: it'd be very cool to draw these in sorted order from lowest Z to highest.
			// just be careful to sort the avatar IDs along with the positions. -MG
			
			LLVector3d currentPos(positions[i]);
			bool isHeightUnknown = (currentPos.mdV[VZ] == 0.f);
			if (avatar_ids[i].notNull() && isHeightUnknown)
			{
				LLViewerObject* viewerObject = gObjectList.findObject(avatar_ids[i]);
				if (viewerObject)
				{
					currentPos.mdV[VZ] = viewerObject->getPositionGlobal().mdV[VZ];
					isHeightUnknown = false;
				}
			}
			pos_map = globalPosToView(currentPos, rotate_map);

			std::string first, last;
			gCacheName->getName(avatar_ids[i], first, last);

			if (LLMuteList::getInstance()->isMuted(avatar_ids[i])) avatar_color = muted_color;
			if (is_agent_friend(avatar_ids[i]) || LGGContactSets::getInstance()->isNonFriend(avatar_ids[i]))
			{
				if(friendsGroupsOnMinimap)
				{
					LLColor4 fgColor = LGGContactSets::getInstance()->getFriendColor(avatar_ids[i]);
					if(fgColor!=LGGContactSets::getInstance()->getDefaultColor())
						avatar_color=fgColor;
				}else
				avatar_color = friend_color;

			}
			if((last == "Linden") || (last == "Tester")) avatar_color = linden_color;
			
			// MOYMOD Minimap custom av colors.
			for(a=0;a<mm_netmapnum;a+=1)if(avatar_ids[i]==mm_mapkeys[a])avatar_color=mm_mapcols[a];

// [RLVa:KB] - Alternate: Phoenix-370 | Checked: 2009-07-21 (RLVa-1.0.0) | Added: RLVa-1.0.0
			// Phoenix-specific: shouldn't be able to tell anything "personal" about anyone from the minimap under @shownames=n
			LLWorldMapView::drawAvatar(
				pos_map.mV[VX], pos_map.mV[VY], 
				(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? avatar_color : standard_color, 
				pos_map.mV[VZ],mDotRadius, isHeightUnknown);
// [/RLVa:KB]
//			LLWorldMapView::drawAvatar(
//				pos_map.mV[VX], pos_map.mV[VY], avatar_color, pos_map.mV[VZ],mDotRadius);

			F32	dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y));
			if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist)
			{
				closest_dist = dist_to_cursor;
				mClosestAgentToCursor = avatar_ids[i];
				mClosestAgentPosition = currentPos;
			}
		}

		// Draw dot for autopilot target
		if (gAgent.getAutoPilot())
		{
			drawTracking( gAgent.getAutoPilotTargetGlobal(), rotate_map, gTrackColor );
		}
		else
		{
			LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
			if (  LLTracker::TRACKING_AVATAR == tracking_status )
			{
				drawTracking( LLAvatarTracker::instance().getGlobalPos(), rotate_map, gTrackColor );
			} 
			else if ( LLTracker::TRACKING_LANDMARK == tracking_status 
					|| LLTracker::TRACKING_LOCATION == tracking_status )
			{
				drawTracking( LLTracker::getTrackedPositionGlobal(), rotate_map, gTrackColor );
			}
		}

		// Draw dot for self avatar position
		pos_global = gAgent.getPositionGlobal();
		pos_map = globalPosToView(pos_global, rotate_map);
		LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage;
		S32 dot_width = llround(mDotRadius * 2.f);
		you->draw(
			llround(pos_map.mV[VX] - mDotRadius),
			llround(pos_map.mV[VY] - mDotRadius),
			dot_width,
			dot_width);

		// Draw frustum
		F32 meters_to_pixels = mScale/ LLWorld::getInstance()->getRegionWidthInMeters();

		F32 horiz_fov = camera->getView() * LLViewerCamera::getInstance()->getAspect();
		F32 far_clip_meters = camera->getFar();
		F32 far_clip_pixels = far_clip_meters * meters_to_pixels;

		F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 );
		F32 half_width_pixels = half_width_meters * meters_to_pixels;
		
		F32 ctr_x = (F32)center_sw_left;
		F32 ctr_y = (F32)center_sw_bottom;


		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);

		if( rotate_map )
		{
			gGL.color4fv(gColors.getColor("NetMapFrustum").mV);

			gGL.begin( LLRender::TRIANGLES  );
				gGL.vertex2f( ctr_x, ctr_y );
				gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels );
				gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels );
			gGL.end();
		}
		else
		{
			gGL.color4fv(gColors.getColor("NetMapFrustumRotating").mV);
			
			// If we don't rotate the map, we have to rotate the frustum.
			gGL.pushMatrix();
				gGL.translatef( ctr_x, ctr_y, 0 );
				glRotatef( atan2( camera->getAtAxis().mV[VX], camera->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f);
				gGL.begin( LLRender::TRIANGLES  );
					gGL.vertex2f( 0, 0 );
					gGL.vertex2f( -half_width_pixels, far_clip_pixels );
					gGL.vertex2f(  half_width_pixels, far_clip_pixels );
				gGL.end();
			gGL.popMatrix();
		}
	}
	
	// Rotation of 0 means that North is up
	setDirectionPos( getChild<LLTextBox>("e_label"), rotation);
	setDirectionPos( getChild<LLTextBox>("n_label"), rotation + F_PI_BY_TWO);
	setDirectionPos( getChild<LLTextBox>("w_label"), rotation + F_PI);
	setDirectionPos( getChild<LLTextBox>("s_label"), rotation + F_PI + F_PI_BY_TWO);

	setDirectionPos( getChild<LLTextBox>("ne_label"), rotation + F_PI_BY_TWO / 2);
	setDirectionPos( getChild<LLTextBox>("nw_label"), rotation + F_PI_BY_TWO + F_PI_BY_TWO / 2);
	setDirectionPos( getChild<LLTextBox>("sw_label"), rotation + F_PI + F_PI_BY_TWO / 2);
	setDirectionPos( getChild<LLTextBox>("se_label"), rotation + F_PI + F_PI_BY_TWO + F_PI_BY_TWO / 2);

	LLView::draw();
}