use modified ver from french website, + my own mods

This commit is contained in:
cxgeorge 2002-03-30 02:45:09 +00:00
parent af8991b2a1
commit 1cbdcc2582
2 changed files with 536 additions and 220 deletions

View File

@ -2,9 +2,9 @@
// File: D3DFont.cpp // File: D3DFont.cpp
// //
// Desc: Texture-based font class // Desc: Texture-based font class
// // modified from a modified version of DXSDK CD3DFont from http://www.lafaqmfc.com/directx.htm
// Note that this is faster than ID3DXFont, which calls GDI in Draw()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef STRICT #ifndef STRICT
#define STRICT #define STRICT
#endif #endif
@ -18,7 +18,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Custom vertex types for rendering text // Custom vertex types for rendering text
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#define MAX_NUM_VERTICES 50*6
struct FONT2DVERTEX { struct FONT2DVERTEX {
D3DXVECTOR4 p; DWORD color; FLOAT tu, tv; D3DXVECTOR4 p; DWORD color; FLOAT tu, tv;
@ -27,9 +26,6 @@ struct FONT3DVERTEX {
D3DXVECTOR3 p; D3DXVECTOR3 n; FLOAT tu, tv; D3DXVECTOR3 p; D3DXVECTOR3 n; FLOAT tu, tv;
}; };
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color, inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color,
FLOAT tu, FLOAT tv ) { FLOAT tu, FLOAT tv ) {
FONT2DVERTEX v; v.p = p; v.color = color; v.tu = tu; v.tv = tv; FONT2DVERTEX v; v.p = p; v.color = color; v.tu = tu; v.tv = tv;
@ -55,8 +51,11 @@ CD3DFont::CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags ) {
m_pTexture = NULL; m_pTexture = NULL;
m_pVB = NULL; m_pVB = NULL;
m_dwSavedStateBlock = 0L; m_dwSavedStateBlock = NULL;
m_dwDrawTextStateBlock = 0L; m_dwDrawTextStateBlock = NULL;
ClearBeginEndData ( ) ;
m_bBeginText = false ;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -83,32 +82,16 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
m_fTextScale = 1.0f; // Draw fonts into texture without scaling m_fTextScale = 1.0f; // Draw fonts into texture without scaling
// Large fonts need larger textures // Large fonts need larger textures
// We can be generous at this step, this is an estimate
if(m_dwFontHeight > 40) if(m_dwFontHeight > 40)
m_dwTexWidth = m_dwTexHeight = 2048;
else if(m_dwFontHeight > 32)
m_dwTexWidth = m_dwTexHeight = 1024; m_dwTexWidth = m_dwTexHeight = 1024;
else if(m_dwFontHeight > 20) else if(m_dwFontHeight > 16)
m_dwTexWidth = m_dwTexHeight = 512; m_dwTexWidth = m_dwTexHeight = 512;
else else
m_dwTexWidth = m_dwTexHeight = 256; m_dwTexWidth = m_dwTexHeight = 256;
// If requested texture is too big, use a smaller texture and smaller font,
// and scale up when rendering.
D3DCAPS8 d3dCaps;
m_pd3dDevice->GetDeviceCaps( &d3dCaps );
if(m_dwTexWidth > d3dCaps.MaxTextureWidth) {
m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth;
m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth;
}
// Create a new texture for the font
hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1,
0, D3DFMT_A4R4G4B4,
D3DPOOL_MANAGED, &m_pTexture );
if(FAILED(hr)) {
cout << "CD3DFONT CreateTexture failed!" << D3DERRORSTRING(hr);
return hr;
}
// Prepare to create a bitmap // Prepare to create a bitmap
DWORD* pBitmapBits; DWORD* pBitmapBits;
BITMAPINFO bmi; BITMAPINFO bmi;
@ -132,47 +115,183 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
(INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 ); (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
DWORD dwBold = (m_dwFontFlags&D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL; DWORD dwBold = (m_dwFontFlags&D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL;
DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE : FALSE; DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE : FALSE;
HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic, HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold,
FALSE , // dwItalic, // NO! We should not do that...
// See below comment about GetTextExtentPoint32
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, m_strFontName ); VARIABLE_PITCH, m_strFontName );
if(NULL==hFont) { if(NULL==hFont) {
cout << "CD3DFONT CreateFont failed!\n"; cout << "CD3DFont InitDeviceObjects(): initial CreateFont failed! GetLastError=" << GetLastError() << endl;
return E_FAIL; return E_FAIL;
} }
SelectObject( hDC, hbmBitmap ); HBITMAP hbmOld = ( HBITMAP ) SelectObject ( hDC, hbmBitmap );
SelectObject( hDC, hFont ); HFONT hfOld = ( HFONT ) SelectObject ( hDC, hFont );
// Set text properties // Set text properties
SetTextColor( hDC, RGB(255,255,255) ); SetTextColor( hDC, RGB(255,255,255) );
SetBkColor( hDC, 0x00000000 ); SetBkColor( hDC, 0x00000000 );
SetTextAlign( hDC, TA_TOP ); SetTextAlign( hDC, TA_TOP );
// Loop through all printable character and output them to the bitmap.. // First Loop through all printable characters
// Meanwhile, keep track of the corresponding tex coords for each character. // in order to determine the smallest necessary texture
DWORD x = 0; DWORD x = 0;
DWORD y = 0; DWORD y = 0;
TCHAR str[2] = _T("x"); TCHAR str[2] = _T("x");
SIZE size; SIZE size;
SIZE sizes [ 127 - 32 ] ;
for(TCHAR c=32; c<127; c++) {
str[0] = c;
// GetTextExtentPoint32 does not care that the font is Italic or not, it will
// return the same value. However, if we specify an Italic font, the output
// on the bitmap will use more pixels.
// If the font is Italic we have to output the standard character
// and bend our vertices.
GetTextExtentPoint32 ( hDC, str, 1, & sizes [ c - 32 ] );
} ;
static DWORD TexturesSizes [ 5 ] = { 128 , 256 , 512 , 1024 , 2048} ;
DWORD dwTexSize = 0 ;
for(DWORD iTex = 0 ; iTex < 5 ; ++ iTex) {
// fake the tex coord loop calculation
x = 0 ;
y = 0 ;
for(TCHAR c=32; c<127; c++) {
if((DWORD)( x + sizes[ c - 32 ].cx+1) > TexturesSizes [ iTex ]) {
x = 0;
y += sizes[ c - 32 ].cy+1;
// new y size
if((DWORD) ( y + sizes[ 0 ].cy + 1 ) >= TexturesSizes [ iTex ]) {
// does not fit, let's try a larger one
break ;
};
};
x += sizes[ c - 32 ].cx + 2 ;
} ;
if((DWORD) ( y + sizes[ 0 ].cy + 1 ) < TexturesSizes [ iTex ]) {
// Yahoo! it fits!
dwTexSize = TexturesSizes [ iTex ] ;
break ;
};
} ;
m_dwTexWidth = m_dwTexHeight = dwTexSize ;
// Select old objects ( added )
// Is this needed for compatible DCs?
// The old handles are not not NULL, so it is done "by the book"
SelectObject ( hDC, hbmOld );
SelectObject ( hDC, hfOld );
// delete our gdi objects
DeleteObject( hbmBitmap );
DeleteObject( hFont );
DeleteDC( hDC );
// moved here to allow deletion of GDI objects
if(dwTexSize == 0) {
cout << "CD3DFont InitDeviceObjects() error: Texture didnt fit, creation failed!\n";
return E_FAIL;
}
// Re-Create new GDI stuff with the optimal size
//
// Prepare to create a bitmap
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;
// Create a DC and a bitmap for the font
hDC = CreateCompatibleDC( NULL );
hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
(VOID**)&pBitmapBits, NULL, 0 );
SetMapMode( hDC, MM_TEXT );
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
// antialiased font, but this is not guaranteed.
nHeight = -MulDiv( m_dwFontHeight,
(INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
dwBold = (m_dwFontFlags&D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL;
dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE : FALSE;
hFont = CreateFont( nHeight, 0, 0, 0, dwBold,
FALSE , // was dwItalic, // see above
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
VARIABLE_PITCH, m_strFontName );
if(NULL==hFont) {
cout << "CD3DFont InitDeviceObjects(): optimal CreateFont failed! GetLastError=" << GetLastError() << endl;
return E_FAIL;
}
hbmOld = ( HBITMAP ) SelectObject ( hDC, hbmBitmap );
hfOld = ( HFONT ) SelectObject ( hDC, hFont );
// Set text properties
SetTextColor( hDC, RGB(255,255,255) );
SetBkColor( hDC, 0x00000000 );
SetTextAlign( hDC, TA_TOP );
// If requested texture is too big, use a smaller texture and smaller font,
// and scale up when rendering.
D3DCAPS8 d3dCaps;
m_pd3dDevice->GetDeviceCaps( &d3dCaps );
if(m_dwTexWidth > d3dCaps.MaxTextureWidth) {
m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth;
m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth;
};
// Create a new texture for the font
hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1,
0, D3DFMT_A4R4G4B4,
D3DPOOL_MANAGED, &m_pTexture );
if(FAILED(hr)) {
SelectObject ( hDC, hbmOld );
SelectObject ( hDC, hfOld );
DeleteObject( hbmBitmap );
DeleteObject( hFont );
DeleteDC( hDC );
cout << "CD3DFont InitDeviceObjs CreateTexture failed!" << D3DERRORSTRING(hr);
return hr;
};
// Loop through all printable character and output them to the bitmap..
// Meanwhile, keep track of the corresponding tex coords for each character.
x = 0 ;
y = 0 ;
for(TCHAR c=32; c<127; c++) { for(TCHAR c=32; c<127; c++) {
str[0] = c; str[0] = c;
GetTextExtentPoint32( hDC, str, 1, &size ); GetTextExtentPoint32( hDC, str, 1, &size );
if((DWORD)(x+size.cx+1) > m_dwTexWidth) { if((DWORD)(x+size.cx+1) > m_dwTexWidth) {
x = 0; x = 0;
y += size.cy+1; y += size.cy+1;
} }
ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL ); // We need one pixel on both sides
m_fTexCoords[c-32][0] = ((FLOAT)(x+0))/m_dwTexWidth; // plus one here for one pixel on the left
m_fTexCoords[c-32][1] = ((FLOAT)(y+0))/m_dwTexHeight; ExtTextOut( hDC, x + 1, y, ETO_OPAQUE, NULL, str, 1, NULL );
m_fTexCoords[c-32][2] = ((FLOAT)(x+0+size.cx))/m_dwTexWidth;
m_fTexCoords[c-32][3] = ((FLOAT)(y+0+size.cy))/m_dwTexHeight;
x += size.cx+1; m_fTexCoords[c-32][0] = ( (FLOAT) x + 0.5f ) / m_dwTexWidth ;
m_fTexCoords[c-32][1] = ( (FLOAT) y + 0.5f ) / m_dwTexHeight ;
m_fTexCoords[c-32][2] = ( (FLOAT) x + 0.5f + size.cx ) / m_dwTexWidth;
m_fTexCoords[c-32][3] = ( (FLOAT) y + 0.5f + size.cy ) / m_dwTexHeight;
// plus two here because we also need one more pixel on the right side
x += size.cx + 2 ;
} }
// Lock the surface and write the alpha values for the set pixels // Lock the surface and write the alpha values for the set pixels
@ -197,9 +316,13 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
// Done updating texture, so clean up used objects // Done updating texture, so clean up used objects
m_pTexture->UnlockRect(0); m_pTexture->UnlockRect(0);
SelectObject ( hDC, hbmOld );
SelectObject ( hDC, hfOld );
DeleteObject( hbmBitmap ); DeleteObject( hbmBitmap );
DeleteDC( hDC );
DeleteObject( hFont ); DeleteObject( hFont );
DeleteDC( hDC );
return RestoreDeviceObjects(); return RestoreDeviceObjects();
} }
@ -208,14 +331,17 @@ HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ) {
// Name: RestoreDeviceObjects() // Name: RestoreDeviceObjects()
// Desc: // Desc:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
HRESULT CD3DFont::RestoreDeviceObjects(void) { HRESULT CD3DFont::RestoreDeviceObjects() {
HRESULT hr; HRESULT hr;
// Create vertex buffer for the letters // Create vertex buffer for the letters
if(FAILED( hr = m_pd3dDevice->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX), if(FAILED( hr = m_pd3dDevice->CreateVertexBuffer(
// can be rendered 3d
MAX_NUM_VERTICES*sizeof(FONT3DVERTEX /*FONT2DVERTEX */ ),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
D3DPOOL_DEFAULT, &m_pVB ) )) { D3DPOOL_DEFAULT, // D3DUSAGE_DYNAMIC makes D3DPOOL_MANAGED impossible
cout << "CD3DFONT::RestoreDevObjs() CreateVB failed!" << D3DERRORSTRING(hr); &m_pVB ) )) {
cout << "CD3DFont CreateVB failed!" << D3DERRORSTRING(hr);
return hr; return hr;
} }
@ -268,17 +394,22 @@ HRESULT CD3DFont::RestoreDeviceObjects(void) {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects() // Name: InvalidateDeviceObjects()
// Desc: Destroys all device-dependent objects // Desc: Destroys all device-dependent objects
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
HRESULT CD3DFont::InvalidateDeviceObjects() { HRESULT CD3DFont::InvalidateDeviceObjects() {
#ifdef _DEBUG
if(m_pVB) {
cout << "XXXX Releasing Font VertexBuffer\n";
}
#endif
SAFE_RELEASE( m_pVB ); SAFE_RELEASE( m_pVB );
// Delete the state blocks // Delete the state blocks
if(IS_VALID_PTR(m_pd3dDevice)) { if(m_pd3dDevice) {
assert(IS_VALID_PTR(m_pd3dDevice));
if(m_dwSavedStateBlock) if(m_dwSavedStateBlock)
m_pd3dDevice->DeleteStateBlock( m_dwSavedStateBlock ); m_pd3dDevice->DeleteStateBlock( m_dwSavedStateBlock );
if(m_dwDrawTextStateBlock) if(m_dwDrawTextStateBlock)
@ -292,13 +423,12 @@ HRESULT CD3DFont::InvalidateDeviceObjects() {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Name: DeleteDeviceObjects() // Name: DeleteDeviceObjects()
// Desc: Destroys all device-dependent objects // Desc: Destroys all device-dependent objects
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
HRESULT CD3DFont::DeleteDeviceObjects() { HRESULT CD3DFont::DeleteDeviceObjects() {
InvalidateDeviceObjects();
SAFE_RELEASE( m_pTexture ); SAFE_RELEASE( m_pTexture );
m_pd3dDevice = NULL; m_pd3dDevice = NULL;
@ -306,8 +436,6 @@ HRESULT CD3DFont::DeleteDeviceObjects() {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Name: GetTextExtent() // Name: GetTextExtent()
// Desc: Get the dimensions of a text string // Desc: Get the dimensions of a text string
@ -346,9 +474,6 @@ HRESULT CD3DFont::GetTextExtent( TCHAR* strText, SIZE* pSize ) {
return S_OK; return S_OK;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Name: DrawTextScaled() // Name: DrawTextScaled()
// Desc: Draws scaled 2D text. Note that x and y are in viewport coordinates // Desc: Draws scaled 2D text. Note that x and y are in viewport coordinates
@ -363,27 +488,169 @@ HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
if(m_pd3dDevice == NULL) if(m_pd3dDevice == NULL)
return E_FAIL; return E_FAIL;
// Set up renderstate HRESULT hr ;
m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock ); if(m_bBeginText) {
m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock ); hr = DeferedDrawTextScaled ( x, y, z, fXScale, fYScale, dwColor, strText, dwFlags ) ;
m_pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX ); } else {
m_pd3dDevice->SetPixelShader( NULL ); BeginText ( ) ;
m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT2DVERTEX) ); hr = DeferedDrawTextScaled ( x, y, z, fXScale, fYScale, dwColor, strText, dwFlags ) ;
if(! FAILED ( hr ))
EndText ( ) ;
} ;
// Set filter states return hr ;
if(dwFlags & D3DFONT_FILTERED) { }
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); //-----------------------------------------------------------------------------
// Name: DrawText()
// Desc: Draws 2D text
//-----------------------------------------------------------------------------
HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
TCHAR* strText, DWORD dwFlags ) {
if(m_pd3dDevice == NULL)
return E_FAIL;
HRESULT hr ;
if(m_bBeginText) {
hr = DeferedDrawText ( sx, sy, dwColor, strText, dwFlags ) ;
} else {
BeginText();
hr = DeferedDrawText ( sx, sy, dwColor, strText, dwFlags ) ;
if(! FAILED ( hr ))
EndText ( ) ;
} ;
return hr ;
}
void CD3DFont::ClearBeginEndData ( void ) {
m_nDeferedCalls = 0 ;
m_TextBuffer [ 0 ] = 0 ;
m_pTextBuffer = & m_TextBuffer [ 0 ] ;
}
HRESULT CD3DFont::BeginText ( void ) {
m_bBeginText = true ;
ClearBeginEndData() ;
return S_OK ;
}
HRESULT CD3DFont::DeferedDrawTextScaled
( FLOAT x, FLOAT y, FLOAT z,
FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
TCHAR* strText, DWORD dwFlags ) {
return
DeferedDraw ( true , x, y, z, fXScale, fYScale, dwColor, strText, dwFlags ) ;
}
HRESULT CD3DFont::DeferedDrawText
( FLOAT x, FLOAT y, DWORD dwColor,
TCHAR* strText, DWORD dwFlags ) {
return
DeferedDraw ( false , x, y, 0.0f , 0.0f , 0.0f , dwColor, strText, dwFlags ) ;
}
HRESULT CD3DFont::DeferedDraw
( bool bScaled ,
FLOAT x, FLOAT y, FLOAT z,
FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
TCHAR* strText, DWORD dwFlags ) {
if(m_nDeferedCalls >= MaxCalls) {
cout << "CD3DFont DeferedDraw() error, MaxCalls exceeded!\n";
return E_FAIL ;
} }
// we need to make a deep copy of the string
// the user object might have fallen out of scope
// when it will be time to render
int nStrLen = strlen ( strText ) + 1 ;
int nUsed = m_pTextBuffer - & m_pTextBuffer [ 0 ] ;
if(nUsed + nStrLen > TextBufferLength) {
cout << "CD3DFont DeferedDraw() error, TextBufferLength exceeded!\n";
return E_FAIL ;
}
strcpy ( m_pTextBuffer , strText ) ;
m_DTArgs [ m_nDeferedCalls ].m_strText = m_pTextBuffer ;
m_pTextBuffer += nStrLen ;
m_DTArgs [ m_nDeferedCalls ].m_bScaled = bScaled ;
m_DTArgs [ m_nDeferedCalls ].m_x = x ;
m_DTArgs [ m_nDeferedCalls ].m_y = y ;
m_DTArgs [ m_nDeferedCalls ].m_z = z ;
m_DTArgs [ m_nDeferedCalls ].m_fXScale = fXScale ;
m_DTArgs [ m_nDeferedCalls ].m_fYScale = fYScale ;
m_DTArgs [ m_nDeferedCalls ].m_dwColor = dwColor ;
m_DTArgs [ m_nDeferedCalls ].m_dwFlags = dwFlags ;
m_nDeferedCalls ++ ;
return S_OK ;
}
HRESULT CD3DFont::EndText ( void ) {
if(m_pd3dDevice == NULL)
return E_FAIL;
HRESULT hr;
assert(IS_VALID_PTR(m_pVB));
DWORD hSavedVertexShader,hSavedPixelShader;
UINT SavedStreamStride;
IDirect3DVertexBuffer8 *pSavedStreamData=NULL;
hr = m_pd3dDevice->GetVertexShader(&hSavedVertexShader);
hr = m_pd3dDevice->GetPixelShader(&hSavedPixelShader);
// Set up renderstate
hr = m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock );
hr = m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
if(hSavedVertexShader!=D3DFVF_FONT2DVERTEX)
hr = m_pd3dDevice->SetVertexShader(D3DFVF_FONT2DVERTEX);
if(hSavedPixelShader!=NULL)
hr = m_pd3dDevice->SetPixelShader(NULL);
hr = m_pd3dDevice->GetStreamSource(0,&pSavedStreamData,&SavedStreamStride);
if(FAILED(hr)) {
cout << "CD3DFont EndText GetStreamSource() failed!" << D3DERRORSTRING(hr);
return E_FAIL;
}
if((pSavedStreamData!=m_pVB)||(SavedStreamStride!=sizeof(FONT2DVERTEX))) {
hr = m_pd3dDevice->SetStreamSource(0,m_pVB,sizeof(FONT2DVERTEX));
if(FAILED(hr)) {
cout << "CD3DFont EndText initial SetStreamSource() failed!" << D3DERRORSTRING(hr);
return E_FAIL;
}
}
// Set filter states
//
// filter if any in our list is specified filtered
//
// This functionality is different from the original D3DFont
// but is a significant speed increase
//
// User will make another batch if necessary
//
bool bFiltered = false ;
for(UINT i = 0 ; i < m_nDeferedCalls ; ++ i) {
DWORD dwFlags = m_DTArgs [ i ].m_dwFlags ;
if(dwFlags & D3DFONT_FILTERED) {
bFiltered = true ;
break ;
}
} ;
if(bFiltered) {
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
};
// useless if nothing is scaled but should be fast enough
D3DVIEWPORT8 vp; D3DVIEWPORT8 vp;
m_pd3dDevice->GetViewport( &vp ); m_pd3dDevice->GetViewport( &vp );
FLOAT sx = (x+1.0f)*vp.Width/2;
FLOAT sy = (y+1.0f)*vp.Height/2;
FLOAT sz = z;
FLOAT rhw = 1.0f;
FLOAT fStartX = sx;
FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight; FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight;
// Fill vertex buffer // Fill vertex buffer
@ -391,6 +658,30 @@ HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
DWORD dwNumTriangles = 0L; DWORD dwNumTriangles = 0L;
m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
bool bItalic = 0 != ( m_dwFontFlags & D3DFONT_ITALIC ) ;
// loop on our batched sets of arguments
for(UINT i = 0 ; i < m_nDeferedCalls ; ++ i) {
bool bScaled = m_DTArgs [ i ].m_bScaled ;
FLOAT x = m_DTArgs [ i ].m_x ;
FLOAT y = m_DTArgs [ i ].m_y ;
FLOAT z = m_DTArgs [ i ].m_z ;
FLOAT fXScale = m_DTArgs [ i ].m_fXScale ;
FLOAT fYScale = m_DTArgs [ i ].m_fYScale ;
DWORD dwColor = m_DTArgs [ i ].m_dwColor ;
TCHAR * strText = m_DTArgs [ i ].m_strText ;
if(bScaled) {
FLOAT sx = (x+1.0f)*vp.Width/2;
FLOAT sy = (y-1.0f)*vp.Height/2;
FLOAT sz = z;
FLOAT rhw = 1.0f;
FLOAT fStartX = sx;
FLOAT fBend = 0.0f ;
if(bItalic)
fBend = fYScale*vp.Height / 4.0f ;
while(*strText) { while(*strText) {
TCHAR c = *strText++; TCHAR c = *strText++;
@ -409,16 +700,16 @@ HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
FLOAT w = (tx2-tx1)*m_dwTexWidth; FLOAT w = (tx2-tx1)*m_dwTexWidth;
FLOAT h = (ty2-ty1)*m_dwTexHeight; FLOAT h = (ty2-ty1)*m_dwTexHeight;
w *= (fXScale*vp.Width)/fLineHeight; w *= (fXScale*vp.Height)/fLineHeight;
h *= (fYScale*vp.Height)/fLineHeight; h *= (fYScale*vp.Height)/fLineHeight;
if(c != _T(' ')) { if(c != _T(' ')) {
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx1, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx1, ty2 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f + fBend,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx2, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f + fBend,sy+0-0.5f,sz,rhw), dwColor, tx2, ty1 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f + fBend,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 );
dwNumTriangles += 2; dwNumTriangles += 2;
if(dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) { if(dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) {
@ -431,57 +722,23 @@ HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
} }
sx += w; sx += w;
} } ;
} else { // not scaled
FLOAT fBend = 0.0f ;
if(bItalic)
fBend = fLineHeight / 4.0f ;
// Unlock and render the vertex buffer // Lazy guy...
m_pVB->Unlock(); FLOAT sx = x ;
if(dwNumTriangles > 0) FLOAT sy = y ;
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
// Restore the modified renderstates
m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DrawText()
// Desc: Draws 2D text
//-----------------------------------------------------------------------------
HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
TCHAR* strText, DWORD dwFlags ) {
if(m_pd3dDevice == NULL)
return E_FAIL;
// Setup renderstate
m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock );
m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock );
m_pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX );
m_pd3dDevice->SetPixelShader( NULL );
m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT2DVERTEX) );
// Set filter states
if(dwFlags & D3DFONT_FILTERED) {
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
}
FLOAT fStartX = sx; FLOAT fStartX = sx;
// Fill vertex buffer
FONT2DVERTEX* pVertices = NULL;
DWORD dwNumTriangles = 0;
m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
while(*strText) { while(*strText) {
TCHAR c = *strText++; TCHAR c = *strText++;
if(c == _T('\n')) { if(c == _T('\n')) {
sx = fStartX; sx = fStartX ;
sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight; sy += fLineHeight ;
} }
if(c < _T(' ')) if(c < _T(' '))
continue; continue;
@ -496,11 +753,11 @@ HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
if(c != _T(' ')) { if(c != _T(' ')) {
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f + fBend,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f + fBend,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
*pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f + fBend,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
dwNumTriangles += 2; dwNumTriangles += 2;
if(dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) { if(dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) {
@ -511,10 +768,17 @@ HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
dwNumTriangles = 0L; dwNumTriangles = 0L;
} }
} }; // endif not blank
sx += w; sx += w;
} } ; // end while
} ; // end if else scaled
} ; // end for
m_bBeginText = false ;
ClearBeginEndData ( ) ;
// Unlock and render the vertex buffer // Unlock and render the vertex buffer
m_pVB->Unlock(); m_pVB->Unlock();
@ -523,20 +787,31 @@ HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
// Restore the modified renderstates // Restore the modified renderstates
m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock ); m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock );
if((hSavedVertexShader!=NULL) && (hSavedVertexShader!=D3DFVF_FONT2DVERTEX))
m_pd3dDevice->SetVertexShader(hSavedVertexShader);
if(hSavedPixelShader!=NULL)
m_pd3dDevice->SetPixelShader(hSavedPixelShader);
if(IS_VALID_PTR(pSavedStreamData) && ((pSavedStreamData!=m_pVB)||(SavedStreamStride!=sizeof(FONT2DVERTEX)))) {
hr = m_pd3dDevice->SetStreamSource(0,pSavedStreamData,SavedStreamStride);
if(FAILED(hr)) {
cout << "CD3DFont EndText restore SetStreamSource() failed!" << D3DERRORSTRING(hr);
return E_FAIL;
}
pSavedStreamData->Release();
}
return S_OK; return S_OK;
} }
#if 0
/* // dont need this now
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Name: Render3DText() // Name: Render3DText()
// Desc: Renders 3D text // Desc: Renders 3D text
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags ) HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags ) {
{ if(m_pd3dDevice == NULL)
if( m_pd3dDevice == NULL )
return E_FAIL; return E_FAIL;
// Setup renderstate // Setup renderstate
@ -547,8 +822,7 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT3DVERTEX) ); m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT3DVERTEX) );
// Set filter states // Set filter states
if( dwFlags & D3DFONT_FILTERED ) if(dwFlags & D3DFONT_FILTERED) {
{
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
} }
@ -558,8 +832,7 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
FLOAT y = 0.0f; FLOAT y = 0.0f;
// Center the text block at the origin // Center the text block at the origin
if( dwFlags & D3DFONT_CENTERED ) if(dwFlags & D3DFONT_CENTERED) {
{
SIZE sz; SIZE sz;
GetTextExtent( strText, &sz ); GetTextExtent( strText, &sz );
x = -(((FLOAT)sz.cx)/10.0f)/2.0f; x = -(((FLOAT)sz.cx)/10.0f)/2.0f;
@ -567,7 +840,7 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
} }
// Turn off culling for two-sided text // Turn off culling for two-sided text
if( dwFlags & D3DFONT_TWOSIDED ) if(dwFlags & D3DFONT_TWOSIDED)
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
FLOAT fStartX = x; FLOAT fStartX = x;
@ -575,18 +848,21 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
// Fill vertex buffer // Fill vertex buffer
FONT3DVERTEX* pVertices; FONT3DVERTEX* pVertices;
DWORD dwVertex = 0L; // DWORD dwVertex = 0L; // not ref'ed
DWORD dwNumTriangles = 0L; DWORD dwNumTriangles = 0L;
m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD );
while( c = *strText++ ) bool bItalic = 0 != ( m_dwFontFlags & D3DFONT_ITALIC ) ;
{ FLOAT fBend = 0.0f ;
if( c == '\n' ) if(bItalic)
{ fBend = ( ( m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f ) / 4.0f ;
while(c = *strText++) {
if(c == '\n') {
x = fStartX; x = fStartX;
y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f; y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f;
} }
if( c < 32 ) if(c < 32)
continue; continue;
FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT tx1 = m_fTexCoords[c-32][0];
@ -597,18 +873,16 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
FLOAT w = (tx2-tx1) * m_dwTexWidth / ( 10.0f * m_fTextScale ); FLOAT w = (tx2-tx1) * m_dwTexWidth / ( 10.0f * m_fTextScale );
FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale ); FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale );
if( c != _T(' ') ) if(c != _T(' ')) {
{
*pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+0,0), D3DXVECTOR3(0,0,-1), tx1, ty2 ); *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+0,0), D3DXVECTOR3(0,0,-1), tx1, ty2 );
*pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 ); *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0 + fBend ,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
*pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 ); *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 );
*pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+h,0), D3DXVECTOR3(0,0,-1), tx2, ty1 ); *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w + fBend ,y+h,0), D3DXVECTOR3(0,0,-1), tx2, ty1 );
*pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 ); *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 );
*pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 ); *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0 + fBend ,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
dwNumTriangles += 2; dwNumTriangles += 2;
if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) if(dwNumTriangles*3 > (MAX_NUM_VERTICES-6)) {
{
// Unlock, render, and relock the vertex buffer // Unlock, render, and relock the vertex buffer
m_pVB->Unlock(); m_pVB->Unlock();
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
@ -622,7 +896,7 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
// Unlock and render the vertex buffer // Unlock and render the vertex buffer
m_pVB->Unlock(); m_pVB->Unlock();
if( dwNumTriangles > 0 ) if(dwNumTriangles > 0)
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
// Restore the modified renderstates // Restore the modified renderstates
@ -630,4 +904,4 @@ HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
return S_OK; return S_OK;
} }
*/ #endif

View File

@ -1,13 +1,14 @@
//----------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
// File: D3DFont.h // File: D3DFont.h
// //
// Desc: Texture-based font class // Desc: Texture-based font class
//----------------------------------------------------------------------------- // based on a modified version of DXSDK CD3DFont from http://www.lafaqmfc.com/directx.htm
// Note that this is faster than ID3DXFont, which calls GDI in Draw()
//---------------------------------------------------------------------------------------------
#ifndef D3DFONT_H #ifndef D3DFONT_H
#define D3DFONT_H #define D3DFONT_H
#include <tchar.h> #include <tchar.h>
#include <D3D8.h> #include <d3d8.h>
// Font creation flags // Font creation flags
#define D3DFONT_BOLD 0x0001 #define D3DFONT_BOLD 0x0001
@ -19,13 +20,21 @@
#define D3DFONT_TWOSIDED 0x0002 #define D3DFONT_TWOSIDED 0x0002
#define D3DFONT_FILTERED 0x0004 #define D3DFONT_FILTERED 0x0004
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Name: class CD3DFont // Name: class CD3DFont
// Desc: Texture-based font class for doing text in a 3D scene. // Desc: Texture-based font class for doing text in a 3D scene.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class CD3DFont class CD3DFont
{ {
enum
{
D3DFVF_FONT2DVERTEX = (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) ,
D3DFVF_FONT3DVERTEX = (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1) ,
TextBufferLength = 1024 ,
MAX_NUM_VERTICES = TextBufferLength * 6 ,
MaxCalls = 30
} ;
TCHAR m_strFontName[80]; // Font properties TCHAR m_strFontName[80]; // Font properties
DWORD m_dwFontHeight; DWORD m_dwFontHeight;
DWORD m_dwFontFlags; DWORD m_dwFontFlags;
@ -42,20 +51,53 @@ class CD3DFont
DWORD m_dwSavedStateBlock; DWORD m_dwSavedStateBlock;
DWORD m_dwDrawTextStateBlock; DWORD m_dwDrawTextStateBlock;
struct DrawTextArgs
{
bool m_bScaled ;
FLOAT m_x ; FLOAT m_y ; FLOAT m_z ;
FLOAT m_fXScale ; FLOAT m_fYScale ;
DWORD m_dwColor ;
TCHAR *m_strText ;
DWORD m_dwFlags ;
} ;
DrawTextArgs m_DTArgs [ MaxCalls ] ;
char m_TextBuffer [ TextBufferLength ] ;
char *m_pTextBuffer ;
UINT m_nDeferedCalls ;
bool m_bBeginText ;
inline HRESULT DeferedDrawText( FLOAT x, FLOAT y, DWORD dwColor,
TCHAR* strText, DWORD dwFlags=0L );
inline HRESULT DeferedDrawTextScaled ( FLOAT x, FLOAT y, FLOAT z,
FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
TCHAR* strText, DWORD dwFlags=0L ) ;
inline HRESULT DeferedDraw
( bool bScaled ,
FLOAT x, FLOAT y, FLOAT z,
FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
TCHAR* strText, DWORD dwFlags ) ;
inline void ClearBeginEndData (void ) ;
public: public:
// 2D and 3D text drawing functions // 2D and 3D text drawing functions
HRESULT BeginText ( void ) ;
HRESULT EndText ( void ) ;
HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor, HRESULT DrawText( FLOAT x, FLOAT y, DWORD dwColor,
TCHAR* strText, DWORD dwFlags=0L ); TCHAR* strText, DWORD dwFlags=0L );
HRESULT DrawTextScaled( FLOAT x, FLOAT y, FLOAT z, HRESULT DrawTextScaled ( FLOAT x, FLOAT y, FLOAT z,
FLOAT fXScale, FLOAT fYScale, DWORD dwColor, FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
TCHAR* strText, DWORD dwFlags=0L ); TCHAR* strText, DWORD dwFlags=0L ) ;
// HRESULT Render3DText( TCHAR* strText, DWORD dwFlags=0L );
// HRESULT Render3DText( TCHAR* strText, DWORD dwFlags=0L );
// Function to get extent of text // Function to get extent of text
HRESULT GetTextExtent( TCHAR* strText, SIZE* pSize ); HRESULT GetTextExtent( TCHAR* strText, SIZE* pSize );
// Initializing and destroying device-dependent objects // Initializing and destroying device-dependent objects
HRESULT InitDeviceObjects( LPDIRECT3DDEVICE8 pd3dDevice ); HRESULT InitDeviceObjects(LPDIRECT3DDEVICE8 pd3dDevice);
HRESULT RestoreDeviceObjects(void); HRESULT RestoreDeviceObjects(void);
HRESULT InvalidateDeviceObjects(void); HRESULT InvalidateDeviceObjects(void);
HRESULT DeleteDeviceObjects(void); HRESULT DeleteDeviceObjects(void);