예제 #1
0
////////////////////////////////////////////////////////////////////////////////
// render
//virtual
void GaMainGameState::render()
{
	// NEILO HACK: REMOVE.
	OsClient* pClient = OsCore::pImpl()->getClient( 0 );
	RsViewport Viewport( 0, 0, pClient->getWidth(), pClient->getHeight() );
	
	// Render background.
	Projection_.perspProjectionHorizontal( BcPIDIV4, (BcReal)pClient->getWidth() / (BcReal)pClient->getHeight(), 1.0f, 1024.0f );
	WorldView_.lookAt( BcVec3d( 0.0f, 350.0f, 270.0f ), BcVec3d( 0.0f, 0.0f, 0.0f ), BcVec3d( 0.0f, 0.0f, 1.0f ) );

	if( SsCore::pImpl() != NULL )
	{
		SsCore::pImpl()->setListener( BcVec3d( 0.0f, 350.0f, 270.0f ), BcVec3d( 0.0f, -4.0f, -2.0f ).normal(), BcVec3d( 0.0f, 0.0f, 1.0f  ) );
	}

	setMaterialComponentParams( BackgroundMaterialComponent_, BcMat4d() );
	Canvas_->setMaterialComponent( BackgroundMaterialComponent_ );
	Canvas_->drawSpriteCentered3D( BcVec3d( 0.0f, 0.0f, 0.0f ), WorldHalfSize_ * 4.0f, 0, RsColour::WHITE, 0 );

	// Render entities.
	for( BcU32 Idx = 0; Idx < Entities_.size(); ++Idx )
	{
		GaGameComponent* pEntity = Entities_[ Idx ];
		pEntity->render( Canvas_ );
	}

	// Draw foreground.
	BcMat4d Ortho;
	Ortho.orthoProjection( -WorldHalfSize_.x(), WorldHalfSize_.x(), -WorldHalfSize_.y(), WorldHalfSize_.y(), -1.0f, 0.0f );

	Canvas_->pushMatrix( Ortho );
	Canvas_->setMaterialComponent( ForegroundMaterialComponent_ );
	Canvas_->drawSpriteCentered( BcVec2d( 0.0f, 0.0f ), BcVec2d( WorldHalfSize_.x() * 2.2f, WorldHalfSize_.y() * -2.0f ), 0, RsColour::WHITE, 20 );

	BcReal Width = BcMax( 0.0f, FoodHealth_ - 0.5f ) * 2.0f;

	RsColour Colour;
	Colour.lerp( RsColour::RED, RsColour::GREEN, Width );

	Canvas_->setMaterialComponent( BarMaterialComponent_ );
	Canvas_->drawSpriteCentered( 
		BcVec2d( 0.0f, WorldHalfSize_.y() - ( WorldHalfSize_.y() * 0.05f ) ), 
		BcVec2d( WorldHalfSize_.x() * 1.5f * Width, WorldHalfSize_.y() * 0.05f ), 
		0, Colour, 20 );

	Canvas_->popMatrix();

	// Base render.
	GaBaseGameState::render();
}
예제 #2
0
//////////////////////////////////////////////////////////////////////////
// drawLines
void ScnCanvasComponent::drawLines( const MaVec2d* pPoints, BcU32 NoofLines, const RsColour& Colour, BcU32 Layer )
{
	BcU32 NoofVertices = 2 * NoofLines;
	ScnCanvasComponentVertex* pVertices = allocVertices( NoofVertices );
	ScnCanvasComponentVertex* pFirstVertex = pVertices;

	// Only draw if we can allocate vertices.
	if( pVertices != NULL )
	{	
		// Now copy in data.
		BcU32 ABGR = Colour.asABGR();

		for( BcU32 Idx = 0; Idx < NoofVertices; ++Idx )
		{
			pVertices->X_ = pPoints[ Idx ].x();
			pVertices->Y_ = pPoints[ Idx ].y();
			pVertices->Z_ = 0.0f;
			pVertices->W_ = 1.0f;
			pVertices->ABGR_ = ABGR;
			++pVertices;
		}
		
		// Add primitive.		
		addPrimitive( RsTopologyType::LINE_LIST, pFirstVertex, NoofVertices, Layer, BcTrue );
	}
}
예제 #3
0
//////////////////////////////////////////////////////////////////////////
// drawLines
void ScnDebugRenderComponent::drawLines( const MaVec3d* pPoints, BcU32 NoofLines, const RsColour& Colour, BcU32 Layer )
{
	BcU32 NoofVertices = 2 * NoofLines;
	ScnDebugRenderComponentVertex* pVertices = allocVertices( NoofVertices );
	ScnDebugRenderComponentVertex* pFirstVertex = pVertices;

	// Only draw if we can allocate vertices.
	if( pVertices != NULL )
	{	
		// Now copy in data.
		BcU32 ABGR = Colour.asABGR();

		for( BcU32 Idx = 0; Idx < NoofVertices; ++Idx )
		{
			pVertices->X_ = pPoints[ Idx ].x();
			pVertices->Y_ = pPoints[ Idx ].y();
			pVertices->Z_ = pPoints[ Idx ].z();
			pVertices->ABGR_ = ABGR;
			++pVertices;
		}
		
		// Add primitive.		
		addPrimitive( rsPT_LINESTRIP, pFirstVertex, NoofVertices, Layer, BcTrue );
	}
}
예제 #4
0
//////////////////////////////////////////////////////////////////////////
// drawLine3d
void ScnCanvasComponent::drawLine3d( const MaVec3d& PointA, const MaVec3d& PointB, const RsColour& Colour, BcU32 Layer )
{
	ScnCanvasComponentVertex* pVertices = allocVertices( 2 );
	ScnCanvasComponentVertex* pFirstVertex = pVertices;
	
	// Only draw if we can allocate vertices.
	if( pVertices != NULL )
	{
		// Now copy in data.
		BcU32 ABGR = Colour.asABGR();
		
		pVertices->X_ = PointA.x();
		pVertices->Y_ = PointA.y();
		pVertices->Z_ = PointA.z();
		pVertices->ABGR_ = ABGR;
		++pVertices;
		pVertices->X_ = PointB.x();
		pVertices->Y_ = PointB.y();
		pVertices->Z_ = PointB.z();
		pVertices->ABGR_ = ABGR;

		// Add primitive.	
		addPrimitive( rsPT_LINELIST, pFirstVertex, 2, Layer, BcTrue );
	}
}
예제 #5
0
//////////////////////////////////////////////////////////////////////////
// drawBox
void ScnCanvasComponent::drawBox( const MaVec2d& CornerA, const MaVec2d& CornerB, const RsColour& Colour, BcU32 Layer )
{
	ScnCanvasComponentVertex* pVertices = allocVertices( 4 );
	ScnCanvasComponentVertex* pFirstVertex = pVertices;
	
	// Only draw if we can allocate vertices.
	if( pVertices != NULL )
	{
		// Now copy in data.
		BcU32 ABGR = Colour.asABGR();
		
		pVertices->X_ = CornerA.x();
		pVertices->Y_ = CornerA.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = 0.0f;
		pVertices->V_ = 0.0f;
		pVertices->ABGR_ = ABGR;
		++pVertices;

		pVertices->X_ = CornerB.x();
		pVertices->Y_ = CornerA.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = 1.0f;
		pVertices->V_ = 0.0f;
		pVertices->ABGR_ = ABGR;
		++pVertices;

		pVertices->X_ = CornerA.x();
		pVertices->Y_ = CornerB.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = 0.0f;
		pVertices->V_ = 1.0f;
		pVertices->ABGR_ = ABGR;
		++pVertices;

		pVertices->X_ = CornerB.x();
		pVertices->Y_ = CornerB.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = 1.0f;
		pVertices->V_ = 1.0f;
		pVertices->ABGR_ = ABGR;
		
		// Add primitive.	
		addPrimitive( RsTopologyType::TRIANGLE_STRIP, pFirstVertex, 4, Layer, BcTrue );
	}
}
예제 #6
0
//////////////////////////////////////////////////////////////////////////
// drawLine
void ScnDebugRenderComponent::drawLine( const MaVec3d& PointA, const MaVec3d& PointB, const RsColour& Colour, BcU32 Layer )
{
	ScnDebugRenderComponentVertex* pVertices = allocVertices( 2 );
	ScnDebugRenderComponentVertex* pFirstVertex = pVertices;
	
	// Only draw if we can allocate vertices.
	if( pVertices != NULL )
	{
		// Now copy in data.
		BcU32 ABGR = Colour.asABGR();
		
		pVertices->X_ = PointA.x();
		pVertices->Y_ = PointA.y();
		pVertices->Z_ = PointA.z();
		pVertices->ABGR_ = ABGR;
		++pVertices;
		pVertices->X_ = PointB.x();
		pVertices->Y_ = PointB.y();
		pVertices->Z_ = PointB.z();
		pVertices->ABGR_ = ABGR;

		// Quickly check last primitive.
		BcBool AddNewPrimitive = BcTrue;
		if( LastPrimitiveSection_ != BcErrorCode )
		{
			ScnDebugRenderComponentPrimitiveSection& PrimitiveSection = PrimitiveSectionList_[ LastPrimitiveSection_ ];

			// If the last primitive was the same type as ours we can append to it.
			// NOTE: Need more checks here later.
			if( PrimitiveSection.Type_ == rsPT_LINELIST &&
				PrimitiveSection.Layer_ == Layer &&
				PrimitiveSection.MaterialComponent_ == MaterialComponent_ )
			{
				PrimitiveSection.NoofVertices_ += 2;
				
				AddNewPrimitive = BcFalse;
			}
		}
		
		// Add primitive.
		if( AddNewPrimitive == BcTrue )
		{
			addPrimitive( rsPT_LINELIST, pFirstVertex, 2, Layer, BcTrue );
		}
	}
}
예제 #7
0
//////////////////////////////////////////////////////////////////////////
// drawSprite
void ScnCanvasComponent::drawSprite( const MaVec2d& Position, const MaVec2d& Size, BcU32 TextureIdx, const RsColour& Colour, BcU32 Layer )
{
	ScnCanvasComponentVertex* pVertices = allocVertices( 6 );
	ScnCanvasComponentVertex* pFirstVertex = pVertices;
	
	const MaVec2d CornerA = Position;
	const MaVec2d CornerB = Position + Size;

	const ScnRect Rect = DiffuseTexture_.isValid() ? DiffuseTexture_->getRect( TextureIdx ) : ScnRect();
	
	// Only draw if we can allocate vertices.
	if( pVertices != NULL )
	{
		// Now copy in data.
		BcU32 ABGR = Colour.asABGR();
		
		pVertices->X_ = CornerA.x();
		pVertices->Y_ = CornerA.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = Rect.X_;
		pVertices->V_ = Rect.Y_;
		pVertices->ABGR_ = ABGR;
		++pVertices;
		
		pVertices->X_ = CornerB.x();
		pVertices->Y_ = CornerA.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = Rect.X_ + Rect.W_;
		pVertices->V_ = Rect.Y_;
		pVertices->ABGR_ = ABGR;
		++pVertices;
		
		pVertices->X_ = CornerA.x();
		pVertices->Y_ = CornerB.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = Rect.X_;
		pVertices->V_ = Rect.Y_ + Rect.H_;
		pVertices->ABGR_ = ABGR;
		++pVertices;
		
		pVertices->X_ = CornerA.x();
		pVertices->Y_ = CornerB.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = Rect.X_;
		pVertices->V_ = Rect.Y_ + Rect.H_;
		pVertices->ABGR_ = ABGR;
		++pVertices;

		pVertices->X_ = CornerB.x();
		pVertices->Y_ = CornerA.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = Rect.X_ + Rect.W_;
		pVertices->V_ = Rect.Y_;
		pVertices->ABGR_ = ABGR;
		++pVertices;

		pVertices->X_ = CornerB.x();
		pVertices->Y_ = CornerB.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->U_ = Rect.X_ + Rect.W_;
		pVertices->V_ = Rect.Y_ + Rect.H_;
		pVertices->ABGR_ = ABGR;
		
		// Quickly check last primitive.
		BcBool AddNewPrimitive = BcTrue;
		if( LastPrimitiveSection_ != BcErrorCode )
		{
			ScnCanvasComponentPrimitiveSection& PrimitiveSection = PrimitiveSectionList_[ LastPrimitiveSection_ ];

			// If the last primitive was the same type as ours we can append to it.
			// NOTE: Need more checks here later.
			if( PrimitiveSection.Type_ == RsTopologyType::TRIANGLE_LIST &&
				PrimitiveSection.Layer_ == Layer &&
				PrimitiveSection.MaterialComponent_ == MaterialComponent_ )
			{
				PrimitiveSection.NoofVertices_ += 6;

				// Matrix stack.
				// TODO: Factor into a seperate function.
				if( IsIdentity_ == BcFalse )
				{
					MaMat4d Matrix = getMatrix();

					for( BcU32 Idx = 0; Idx < 6; ++Idx )
					{
						ScnCanvasComponentVertex* pVertex = &pFirstVertex[ Idx ];
						MaVec3d Vertex = MaVec3d( pVertex->X_, pVertex->Y_, pVertex->Z_ ) * Matrix;
						pVertex->X_ = Vertex.x();
						pVertex->Y_ = Vertex.y();
						pVertex->Z_ = Vertex.z();
						pVertex->W_ = 1.0f;
					}
				}
				
				AddNewPrimitive = BcFalse;
			}
		}
		
		// Add primitive.
		if( AddNewPrimitive == BcTrue )
		{
			addPrimitive( RsTopologyType::TRIANGLE_LIST, pFirstVertex, 6, Layer, BcTrue );
		}
	}
}
예제 #8
0
//////////////////////////////////////////////////////////////////////////
// drawLine
void ScnCanvasComponent::drawLine( const MaVec2d& PointA, const MaVec2d& PointB, const RsColour& Colour, BcU32 Layer )
{
	ScnCanvasComponentVertex* pVertices = allocVertices( 2 );
	ScnCanvasComponentVertex* pFirstVertex = pVertices;
	
	// Only draw if we can allocate vertices.
	if( pVertices != NULL )
	{
		// Now copy in data.
		BcU32 ABGR = Colour.asABGR();
		
		pVertices->X_ = PointA.x();
		pVertices->Y_ = PointA.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->ABGR_ = ABGR;
		++pVertices;
		pVertices->X_ = PointB.x();
		pVertices->Y_ = PointB.y();
		pVertices->Z_ = 0.0f;
		pVertices->W_ = 1.0f;
		pVertices->ABGR_ = ABGR;

		// Quickly check last primitive.
		BcBool AddNewPrimitive = BcTrue;
		if( LastPrimitiveSection_ != BcErrorCode )
		{
			ScnCanvasComponentPrimitiveSection& PrimitiveSection = PrimitiveSectionList_[ LastPrimitiveSection_ ];

			// If the last primitive was the same type as ours we can append to it.
			// NOTE: Need more checks here later.
			if( PrimitiveSection.Type_ == RsTopologyType::LINE_LIST &&
				PrimitiveSection.Layer_ == Layer &&
				PrimitiveSection.MaterialComponent_ == MaterialComponent_ )
			{
				PrimitiveSection.NoofVertices_ += 2;

				// Matrix stack.
				// TODO: Factor into a seperate function.
				if( IsIdentity_ == BcFalse )
				{
					MaMat4d Matrix = getMatrix();

					for( BcU32 Idx = 0; Idx < 2; ++Idx )
					{
						ScnCanvasComponentVertex* pVertex = &pFirstVertex[ Idx ];
						MaVec3d Vertex = MaVec3d( pVertex->X_, pVertex->Y_, pVertex->Z_ ) * Matrix;
						pVertex->X_ = Vertex.x();
						pVertex->Y_ = Vertex.y();
						pVertex->Z_ = Vertex.z();
						pVertices->W_ = 1.0f;
					}
				}
				
				AddNewPrimitive = BcFalse;
			}
		}
		
		// Add primitive.
		if( AddNewPrimitive == BcTrue )
		{
			addPrimitive( RsTopologyType::LINE_LIST, pFirstVertex, 2, Layer, BcTrue );
		}
	}
}
void RsTextureWinGL::Render( const MtVector2& v2Position,
							 const MtVector2& v2Dimension,
							 RsColour colour,
							 BtU32 sortOrder )
{
	// Cache the impl
	RsImplWinGL *pImpl = (RsImplWinGL*)RsImpl::pInstance();

	// Cache the render target
	RsRenderTarget *pRenderTarget = RsRenderTarget::GetCurrent();

	// Cache the camera
	RsCamera camera = pRenderTarget->GetCamera();

	// Cache the display width and height
	BtFloat Width  = (BtFloat)camera.GetViewport().m_width;
	BtFloat Height = (BtFloat)camera.GetViewport().m_height;

	// Cache the display width and height
	BtFloat fScaleWidth  = 1.0f / Width;
	BtFloat fScaleHeight = 1.0f / Height;

	// Allocate vertex
	RsVertex3 *pStartVertex = pImpl->StartVertex();

	// Set the start vertex
	RsVertex3 *pVertex = pStartVertex;

	// Cache the texture width and height
	BtFloat fTextureWidth  = m_pMipmaps[0].m_nWidth;
	BtFloat fTextureHeight = m_pMipmaps[0].m_nHeight;

	// Calculate the texture scalars
	BtFloat fScalarX = 1.0f / fTextureWidth;
	BtFloat fScalarY = 1.0f / fTextureHeight;

	BtFloat minU = fScalarX / 2;
	BtFloat minV = fScalarY / 2;

	BtFloat maxU = ( m_pMipmaps[0].m_originalWidth * fScalarX )  - minU;
	BtFloat maxV = ( m_pMipmaps[0].m_originalHeight * fScalarY ) - minV;

	// Calculate the positions
	BtFloat xmin = v2Position.x;
	BtFloat xmax = v2Position.x + v2Dimension.x;
	BtFloat ymin = v2Position.y;
	BtFloat ymax = v2Position.y + v2Dimension.y;

	RsVertex3 *pQuad = pVertex;

	// Copy these into vertex
	pVertex->m_v3Position = MtVector3(xmin, ymin, 0.1f );
	pVertex->m_v2UV = MtVector2( minU, minV );
	++pVertex;

	pVertex->m_v3Position = MtVector3(xmin, ymax, 0.1f );
	pVertex->m_v2UV = MtVector2( minU, maxV );
	++pVertex;

	pVertex->m_v3Position = MtVector3(xmax, ymin, 0.1f );
	pVertex->m_v2UV = MtVector2( maxU, minV );
	++pVertex;

	pVertex->m_v3Position = MtVector3(xmax, ymax, 0.1f );
	pVertex->m_v2UV = MtVector2( maxU, maxV );
	++pVertex;

	// Scale the position to local screen space -1 to 1
	for( BtU32 i=0; i<4; i++ )
	{
		// Set the colour
		pQuad[ i ].m_colour = colour.asARGB();

		// Flip the y
		pQuad[ i ].m_v3Position.y = Height - pQuad[ i ].m_v3Position.y;

		// Scale from 0..width to 0..1
		pQuad[ i ].m_v3Position.x *= fScaleWidth;
		pQuad[ i ].m_v3Position.y *= fScaleHeight;

		// Scale from 0..1 to 0..2
		pQuad[ i ].m_v3Position.x *= 2.0f;
		pQuad[ i ].m_v3Position.y *= 2.0f;

		// Translate from 0..2 to -1..1
		pQuad[ i ].m_v3Position.x -= 1.0f;
		pQuad[ i ].m_v3Position.y -= 1.0f;
	}

	// Setup the primitive
	RsPrimitiveWinGL *pPrimitive = pImpl->AddPrimitive();
	pPrimitive->m_primitiveType = GL_TRIANGLE_STRIP;
	pPrimitive->m_numVertex	    = 4;
	pPrimitive->m_nStartVertex  = pImpl->GetCurrentVertex();

	// End the current vertex
	pImpl->EndVertex( 4 );

	// Make a new font renderable
	RsTextureRenderable *pTextureRenderable = pImpl->AddTexture();
	pTextureRenderable->m_pTexture  = this;
	pTextureRenderable->m_pVertex   = pStartVertex;
	pTextureRenderable->m_primitive = pPrimitive;

	// Validate the shader
	BtAssert( pTextureRenderable->m_pShader != BtNull );

	// Add the font to the renderable list
	RsRenderTargetWinGL *pCurrentRenderTarget = (RsRenderTargetWinGL*)RsRenderTarget::GetCurrent();
	pCurrentRenderTarget->Add( sortOrder, pTextureRenderable );
}
예제 #10
0
// virtual
MtVector2 RsFontWin32GL::Render( const MtVector2& v2StartPosition,
							     const MtVector2& v2Scale,
							     const RsColour &colour,
							     const BtChar* szText,
							     BtU32 sortOrder )
{
	const BtU32 MaxFontLength = 256;

	MtVector2 v2LastPosition = MtVector2( 0, 0 );

	// Cache the impl
	RsImplWinGL *pImpl = (RsImplWinGL*)RsImpl::pInstance();

	// Cache the render target
	RsRenderTarget *pRenderTarget = RsRenderTarget::GetCurrent();

	// Cache the camera
	RsCamera camera = pRenderTarget->GetCamera();

	// Cache the display width and height
	BtFloat Width  = (BtFloat)camera.GetViewport().m_width;
	BtFloat Height = (BtFloat)camera.GetViewport().m_height;

	// Cache the display width and height
	BtFloat fScaleWidth  = 1.0f / Width;
	BtFloat fScaleHeight = 1.0f / Height;

	// Allocate vertex
	RsVertex3 *pStartVertex = pImpl->StartVertex();

	// Set the start vertex
	RsVertex3 *pVertex = pStartVertex;

	// Cache the texture
	RsTextureWinGL* pTexture = (RsTextureWinGL*) m_pTextures[ 0 ];

	// Set the start position
	MtVector2 v2Position = v2StartPosition;

	// Cache the string length
	BtU32 length = strlen(szText);

	// Cache the texture width and height
	BtFloat TextureWidth  = 1.0f / (BtFloat) pTexture->GetWidth();
	BtFloat TextureHeight = 1.0f / (BtFloat) pTexture->GetHeight();

	BtU32 currentVertex = 0;

	// Loop through the string
	for( BtU32 nCharacterIndex=0; nCharacterIndex<length; nCharacterIndex++ )
	{
		// Cache each character
		BtUChar Character = szText[nCharacterIndex];

		if( Character == '\n' )
		{
			// Cache the font character
			LBaFontChar& fontChar = m_pFileData->m_characters['A'];	
			v2Position.x = v2StartPosition.x;
			v2Position.y += fontChar.m_fHeight * 1.50f * v2Scale.y;
			continue;
		}

		// Cache the font character
		LBaFontChar& fontChar = m_pFileData->m_characters[Character];

		// Set the dimension from the width and height of the texture
		MtVector2 v2Dimension = MtVector2( fontChar.m_fWidth, fontChar.m_fHeight );

		// Calculate the positions
		BtFloat fX0 = v2Position.x;
		BtFloat fX1 = fX0 + ( v2Dimension.x * v2Scale.x );
		BtFloat fY0 = v2Position.y + ( fontChar.m_nYOffset * v2Scale.y );
		BtFloat fY1 = fY0 + ( v2Dimension.y * v2Scale.y );

		RsVertex3 *pQuad = pVertex;

		// Copy these into vertex
		pVertex->m_v3Position = MtVector3(fX0, fY0, 0.1f );
		pVertex->m_v2UV = MtVector2( fontChar.m_U0 , fontChar.m_V0 );
		++pVertex;

		pVertex->m_v3Position = MtVector3(fX0, fY1, 0.1f );
		pVertex->m_v2UV = MtVector2( fontChar.m_U0, fontChar.m_V1 + 1 );
		++pVertex;

		pVertex->m_v3Position = MtVector3(fX1, fY0, 0.1f );
		pVertex->m_v2UV = MtVector2( fontChar.m_U1 + 1, fontChar.m_V0  );
		++pVertex;

		pVertex->m_v3Position = MtVector3(fX0, fY1, 0.1f );
		pVertex->m_v2UV = MtVector2( fontChar.m_U0 , fontChar.m_V1 + 1 );
		++pVertex;

		pVertex->m_v3Position = MtVector3(fX1, fY1, 0.1f );
		pVertex->m_v2UV = MtVector2( fontChar.m_U1 + 1, fontChar.m_V1 + 1 );
		++pVertex;

		pVertex->m_v3Position = MtVector3(fX1, fY0, 0.1f );
		pVertex->m_v2UV = MtVector2( fontChar.m_U1 + 1, fontChar.m_V0 );
		++pVertex;

		// Scale the position to local screen space -1 to 1
		for( BtU32 i=0; i<6; i++ )
		{
			// Set the colour
			pQuad[ i ].m_colour = colour.asWord();

			// Scale the uvs
			pQuad[ i ].m_v2UV.x *= TextureWidth;
			pQuad[ i ].m_v2UV.y *= TextureHeight;

			// Flip the y
			pQuad[ i ].m_v3Position.y = Height - pQuad[ i ].m_v3Position.y;

			pQuad[ i ].m_v3Position.x -= 0.5f;
			pQuad[ i ].m_v3Position.y -= 0.5f;

			// Scale from 0..width to 0..1
			pQuad[ i ].m_v3Position.x *= fScaleWidth;
			pQuad[ i ].m_v3Position.y *= fScaleHeight;

			// Scale from 0..1 to 0..2
			pQuad[ i ].m_v3Position.x *= 2.0f;
			pQuad[ i ].m_v3Position.y *= 2.0f;

			// Translate from 0..2 to -1..1
			pQuad[ i ].m_v3Position.x -= 1.0f;
			pQuad[ i ].m_v3Position.y -= 1.0f;
		}

		// Render the 6 new vertex

		// Increment the last position
		v2LastPosition.x = MtMax( v2LastPosition.x, v2Position.x + v2Dimension.x );
		v2LastPosition.y = MtMax( v2LastPosition.y, v2Position.y + v2Dimension.y );

		// Increment the position
		v2Position.x += ( fontChar.m_nXAdvance * v2Scale.x );

		currentVertex += 6;
	}

	// Setup the primitive
	RsPrimitiveWinGL *pPrimitive = pImpl->AddPrimitive();
	pPrimitive->m_primitiveType = GL_TRIANGLES;
	pPrimitive->m_numVertex	    = currentVertex;
	pPrimitive->m_nStartVertex  = pImpl->GetCurrentVertex();

	// End the current vertex
	pImpl->EndVertex( currentVertex );

	// Make a new font renderable
	RsFontRenderable *pFontRenderable = pImpl->AddFont();
	pFontRenderable->m_pFont = this;
	pFontRenderable->m_pVertex = pStartVertex;
	pFontRenderable->m_primitive = pPrimitive;

	// Validate the shader
	BtAssert( pFontRenderable->m_pShader != BtNull );

	// Add the font to the renderable list
	RsRenderTargetWinGL *pCurrentRenderTarget = (RsRenderTargetWinGL*)RsRenderTarget::GetCurrent();
	pCurrentRenderTarget->Add( sortOrder, pFontRenderable );

	// Calculate the dimension
	MtVector2 v2Dimension = v2LastPosition - v2StartPosition;

	// Return the dimension
	return v2Dimension;
}