Advertisement
Guest User

Untitled

a guest
Jun 26th, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.95 KB | None | 0 0
  1. #define _CRT_SECURE_NO_DEPRECATE
  2. #include "cStdAfx.h"
  3. #include <d3dx9.h>
  4. #include "cFont.h"
  5. #define SAFE_RELEASE(p) { if(p) {(p)->Release();(p)=NULL;} }
  6.  
  7. //-----------------------------------------------------------------------------
  8. // Custom vertex types for rendering text
  9. //-----------------------------------------------------------------------------
  10. #define MAX_NUM_VERTICES 50*6
  11.  
  12. struct FONT2DVERTEX { D3DXVECTOR4 p; DWORD color; FLOAT tu, tv; };
  13. struct FONT3DVERTEX { D3DXVECTOR3 p; D3DXVECTOR3 n; FLOAT tu, tv; };
  14.  
  15. #define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
  16. #define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
  17.  
  18. inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color,
  19. FLOAT tu, FLOAT tv )
  20. {
  21. FONT2DVERTEX v; v.p = p; v.color = color; v.tu = tu; v.tv = tv;
  22. return v;
  23. }
  24.  
  25. inline FONT3DVERTEX InitFont3DVertex( const D3DXVECTOR3& p, const D3DXVECTOR3& n,
  26. FLOAT tu, FLOAT tv )
  27. {
  28. FONT3DVERTEX v; v.p = p; v.n = n; v.tu = tu; v.tv = tv;
  29. return v;
  30. }
  31.  
  32.  
  33.  
  34.  
  35. //-----------------------------------------------------------------------------
  36. // Name: CD3DFont()
  37. // Desc: Font class constructor
  38. //-----------------------------------------------------------------------------
  39. CD3DFont::CD3DFont( TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags )
  40. {
  41. _tcsncpy( m_strFontName, strFontName, sizeof(m_strFontName) / sizeof(TCHAR) );
  42. m_strFontName[sizeof(m_strFontName) / sizeof(TCHAR) - 1] = _T('\0');
  43. m_dwFontHeight = dwHeight;
  44. m_dwFontFlags = dwFlags;
  45. m_dwSpacing = 0;
  46.  
  47. m_pd3dDevice = NULL;
  48. m_pTexture = NULL;
  49. m_pVB = NULL;
  50.  
  51. m_pStateBlockSaved = NULL;
  52. m_pStateBlockDrawText = NULL;
  53. }
  54.  
  55. //-----------------------------------------------------------------------------
  56. // Name: ~CD3DFont()
  57. // Desc: Font class destructor
  58. //-----------------------------------------------------------------------------
  59. CD3DFont::~CD3DFont()
  60. {
  61. InvalidateDeviceObjects();
  62. DeleteDeviceObjects();
  63. }
  64.  
  65.  
  66.  
  67.  
  68. //-----------------------------------------------------------------------------
  69. // Name: CreateGDIFont
  70. // Desc: Create a font based on the current state of related member variables
  71. // and return the handle (or null on error)
  72. //-----------------------------------------------------------------------------
  73. HRESULT CD3DFont::CreateGDIFont( HDC hDC, HFONT* pFont )
  74. {
  75. // Create a font. By specifying ANTIALIASED_QUALITY, we might get an
  76. // antialiased font, but this is not guaranteed.
  77. INT nHeight = -MulDiv( m_dwFontHeight,
  78. (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale),
  79. 72 );
  80. DWORD dwBold = (m_dwFontFlags & D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL;
  81. DWORD dwItalic = (m_dwFontFlags & D3DFONT_ITALIC) ? TRUE : FALSE;
  82. *pFont = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic,
  83. FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
  84. CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
  85. VARIABLE_PITCH, m_strFontName );
  86.  
  87. if( *pFont == NULL )
  88. return E_FAIL;
  89.  
  90. return S_OK;
  91. }
  92.  
  93.  
  94.  
  95.  
  96. //-----------------------------------------------------------------------------
  97. // Name: PaintAlphabet
  98. // Desc: Paint the printable characters for the given GDI font onto the
  99. // provided device context. If the bMeasureOnly flag is set, no drawing
  100. // will occur.
  101. //-----------------------------------------------------------------------------
  102. HRESULT CD3DFont::PaintAlphabet( HDC hDC, BOOL bMeasureOnly )
  103. {
  104. SIZE size;
  105. TCHAR str[2] = _T("x"); // One-character, null-terminated string
  106.  
  107. // Calculate the spacing between characters based on line height
  108. if( 0 == GetTextExtentPoint32( hDC, str, 1, &size ) )
  109. return E_FAIL;
  110. m_dwSpacing = (DWORD) ceil(size.cy * 0.3f);
  111.  
  112. // Set the starting point for the drawing
  113. DWORD x = m_dwSpacing;
  114. DWORD y = 0;
  115.  
  116. // For each character, draw text on the DC and advance the current position
  117. for( char c = 32; c < 127; c++ )
  118. {
  119. str[0] = c;
  120. if( 0 == GetTextExtentPoint32( hDC, str, 1, &size ) )
  121. return E_FAIL;
  122.  
  123. if( (DWORD)(x + size.cx + m_dwSpacing) > m_dwTexWidth )
  124. {
  125. x = m_dwSpacing;
  126. y += size.cy + 1;
  127. }
  128.  
  129. // Check to see if there's room to write the character here
  130. if( y + size.cy > m_dwTexHeight )
  131. return D3DERR_MOREDATA;
  132.  
  133. if( !bMeasureOnly )
  134. {
  135. // Perform the actual drawing
  136. if( 0 == ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL ) )
  137. return E_FAIL;
  138.  
  139. m_fTexCoords[c-32][0] = ((FLOAT)(x + 0 - m_dwSpacing))/m_dwTexWidth;
  140. m_fTexCoords[c-32][1] = ((FLOAT)(y + 0 + 0 ))/m_dwTexHeight;
  141. m_fTexCoords[c-32][2] = ((FLOAT)(x + size.cx + m_dwSpacing))/m_dwTexWidth;
  142. m_fTexCoords[c-32][3] = ((FLOAT)(y + size.cy + 0 ))/m_dwTexHeight;
  143. }
  144.  
  145. x += size.cx + (2 * m_dwSpacing);
  146. }
  147.  
  148. return S_OK;
  149. }
  150.  
  151.  
  152.  
  153.  
  154.  
  155. //-----------------------------------------------------------------------------
  156. // Name: InitDeviceObjects()
  157. // Desc: Initializes device-dependent objects, including the vertex buffer used
  158. // for rendering text and the texture map which stores the font image.
  159. //-----------------------------------------------------------------------------
  160. HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
  161. {
  162. HRESULT hr = S_OK;
  163. HFONT hFont = NULL;
  164. HFONT hFontOld = NULL;
  165. HDC hDC = NULL;
  166. HBITMAP hbmBitmap = NULL;
  167. HGDIOBJ hbmOld = NULL;
  168.  
  169. // Keep a local copy of the device
  170. m_pd3dDevice = pd3dDevice;
  171.  
  172. // Assume we will draw fonts into texture without scaling unless the
  173. // required texture size is found to be larger than the device max
  174. m_fTextScale = 1.0f;
  175.  
  176. hDC = CreateCompatibleDC( NULL );
  177. SetMapMode( hDC, MM_TEXT );
  178.  
  179. hr = CreateGDIFont( hDC, &hFont );
  180. if( FAILED(hr) )
  181. goto LCleanReturn;
  182.  
  183. hFontOld = (HFONT) SelectObject( hDC, hFont );
  184.  
  185. // Calculate the dimensions for the smallest power-of-two texture which
  186. // can hold all the printable characters
  187. m_dwTexWidth = m_dwTexHeight = 128;
  188. while( D3DERR_MOREDATA == ( hr = PaintAlphabet( hDC, true ) ) )
  189. {
  190. m_dwTexWidth *= 2;
  191. m_dwTexHeight *= 2;
  192. }
  193.  
  194. if( FAILED(hr) )
  195. goto LCleanReturn;
  196.  
  197. // If requested texture is too big, use a smaller texture and smaller font,
  198. // and scale up when rendering.
  199. D3DCAPS9 d3dCaps;
  200. m_pd3dDevice->GetDeviceCaps( &d3dCaps );
  201.  
  202. if( m_dwTexWidth > d3dCaps.MaxTextureWidth )
  203. {
  204. m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth;
  205. m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth;
  206.  
  207. bool bFirstRun = true; // Flag clear after first run
  208.  
  209. do
  210. {
  211. // If we've already tried fitting the new text, the scale is still
  212. // too large. Reduce and try again.
  213. if( !bFirstRun)
  214. m_fTextScale *= 0.9f;
  215.  
  216. // The font has to be scaled to fit on the maximum texture size; our
  217. // current font is too big and needs to be recreated to scale.
  218. DeleteObject( SelectObject( hDC, hFontOld ) );
  219.  
  220. hr = CreateGDIFont( hDC, &hFont );
  221. if( FAILED(hr) )
  222. goto LCleanReturn;
  223.  
  224. hFontOld = (HFONT) SelectObject( hDC, hFont );
  225.  
  226. bFirstRun = false;
  227. }
  228. while( D3DERR_MOREDATA == ( hr = PaintAlphabet( hDC, true ) ) );
  229. }
  230.  
  231.  
  232. // Create a new texture for the font
  233. hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1,
  234. 0, D3DFMT_A4R4G4B4,
  235. D3DPOOL_MANAGED, &m_pTexture, NULL );
  236. if( FAILED(hr) )
  237. goto LCleanReturn;
  238.  
  239. // Prepare to create a bitmap
  240. DWORD* pBitmapBits;
  241. BITMAPINFO bmi;
  242. ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
  243. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  244. bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
  245. bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
  246. bmi.bmiHeader.biPlanes = 1;
  247. bmi.bmiHeader.biCompression = BI_RGB;
  248. bmi.bmiHeader.biBitCount = 32;
  249.  
  250. // Create a bitmap for the font
  251. hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
  252. (void**)&pBitmapBits, NULL, 0 );
  253.  
  254. hbmOld = SelectObject( hDC, hbmBitmap );
  255.  
  256. // Set text properties
  257. SetTextColor( hDC, RGB(255,255,255) );
  258. SetBkColor( hDC, 0x00000000 );
  259. SetTextAlign( hDC, TA_TOP );
  260.  
  261. // Paint the alphabet onto the selected bitmap
  262. hr = PaintAlphabet( hDC, false );
  263. if( FAILED(hr) )
  264. goto LCleanReturn;
  265.  
  266. // Lock the surface and write the alpha values for the set pixels
  267. D3DLOCKED_RECT d3dlr;
  268. m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
  269. BYTE* pDstRow;
  270. pDstRow = (BYTE*)d3dlr.pBits;
  271. WORD* pDst16;
  272. BYTE bAlpha; // 4-bit measure of pixel intensity
  273. DWORD x, y;
  274.  
  275. for( y=0; y < m_dwTexHeight; y++ )
  276. {
  277. pDst16 = (WORD*)pDstRow;
  278. for( x=0; x < m_dwTexWidth; x++ )
  279. {
  280. bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
  281. if (bAlpha > 0)
  282. {
  283. *pDst16++ = (WORD) ((bAlpha << 12) | 0x0fff);
  284. }
  285. else
  286. {
  287. *pDst16++ = 0x0000;
  288. }
  289. }
  290. pDstRow += d3dlr.Pitch;
  291. }
  292.  
  293. hr = S_OK;
  294.  
  295. // Done updating texture, so clean up used objects
  296. LCleanReturn:
  297. if( m_pTexture )
  298. m_pTexture->UnlockRect(0);
  299.  
  300. SelectObject( hDC, hbmOld );
  301. SelectObject( hDC, hFontOld );
  302. DeleteObject( hbmBitmap );
  303. DeleteObject( hFont );
  304. DeleteDC( hDC );
  305.  
  306. return hr;
  307. }
  308.  
  309.  
  310.  
  311.  
  312. //-----------------------------------------------------------------------------
  313. // Name: RestoreDeviceObjects()
  314. // Desc:
  315. //-----------------------------------------------------------------------------
  316. HRESULT CD3DFont::RestoreDeviceObjects()
  317. {
  318. HRESULT hr;
  319.  
  320. // Create vertex buffer for the letters
  321. int vertexSize = max( sizeof(FONT2DVERTEX), sizeof(FONT3DVERTEX ) );
  322. if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( MAX_NUM_VERTICES * vertexSize,
  323. D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
  324. D3DPOOL_DEFAULT, &m_pVB, NULL ) ) )
  325. {
  326. return hr;
  327. }
  328.  
  329. bool bSupportsAlphaBlend = true;
  330. LPDIRECT3D9 pd3d9 = NULL;
  331. if( SUCCEEDED( m_pd3dDevice->GetDirect3D( &pd3d9 ) ) )
  332. {
  333. D3DCAPS9 Caps;
  334. D3DDISPLAYMODE Mode;
  335. LPDIRECT3DSURFACE9 pSurf = NULL;
  336. D3DSURFACE_DESC Desc;
  337. m_pd3dDevice->GetDeviceCaps( &Caps );
  338. m_pd3dDevice->GetDisplayMode( 0, &Mode );
  339. if( SUCCEEDED( m_pd3dDevice->GetRenderTarget( 0, &pSurf ) ) )
  340. {
  341. pSurf->GetDesc( &Desc );
  342. if( FAILED( pd3d9->CheckDeviceFormat( Caps.AdapterOrdinal, Caps.DeviceType, Mode.Format,
  343. D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_SURFACE,
  344. Desc.Format ) ) )
  345. {
  346. bSupportsAlphaBlend = false;
  347. }
  348. SAFE_RELEASE( pSurf );
  349. }
  350. SAFE_RELEASE( pd3d9 );
  351. }
  352.  
  353. // Create the state blocks for rendering text
  354. for( UINT which=0; which<2; which++ )
  355. {
  356. m_pd3dDevice->BeginStateBlock();
  357. m_pd3dDevice->SetTexture( 0, m_pTexture );
  358.  
  359. if ( D3DFONT_ZENABLE & m_dwFontFlags )
  360. m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  361. else
  362. m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
  363.  
  364. if( bSupportsAlphaBlend )
  365. {
  366. m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  367. m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  368. m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  369. }
  370. else
  371. {
  372. m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  373. }
  374. m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
  375. m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 );
  376. m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
  377. m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  378. m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
  379. m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE );
  380. m_pd3dDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
  381. m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, FALSE );
  382. m_pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, D3DVBF_DISABLE );
  383. m_pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
  384. m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
  385. m_pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE,
  386. D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN |
  387. D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA );
  388. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
  389. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  390. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  391. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  392. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  393. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
  394. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
  395. m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
  396. m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
  397. m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
  398. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
  399. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
  400. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE );
  401.  
  402. if( which==0 )
  403. m_pd3dDevice->EndStateBlock( &m_pStateBlockSaved );
  404. else
  405. m_pd3dDevice->EndStateBlock( &m_pStateBlockDrawText );
  406. }
  407.  
  408. return S_OK;
  409. }
  410.  
  411.  
  412.  
  413.  
  414. //-----------------------------------------------------------------------------
  415. // Name: InvalidateDeviceObjects()
  416. // Desc: Destroys all device-dependent objects
  417. //-----------------------------------------------------------------------------
  418. HRESULT CD3DFont::InvalidateDeviceObjects()
  419. {
  420. SAFE_RELEASE( m_pVB );
  421. SAFE_RELEASE( m_pStateBlockSaved );
  422. SAFE_RELEASE( m_pStateBlockDrawText );
  423.  
  424. return S_OK;
  425. }
  426.  
  427.  
  428.  
  429.  
  430. //-----------------------------------------------------------------------------
  431. // Name: DeleteDeviceObjects()
  432. // Desc: Destroys all device-dependent objects
  433. //-----------------------------------------------------------------------------
  434. HRESULT CD3DFont::DeleteDeviceObjects()
  435. {
  436. SAFE_RELEASE( m_pTexture );
  437. m_pd3dDevice = NULL;
  438.  
  439. return S_OK;
  440. }
  441.  
  442.  
  443.  
  444.  
  445. //-----------------------------------------------------------------------------
  446. // Name: GetTextExtent()
  447. // Desc: Get the dimensions of a text string
  448. //-----------------------------------------------------------------------------
  449. HRESULT CD3DFont::GetTextExtent( TCHAR* strText, SIZE* pSize )
  450. {
  451. if( NULL==strText || NULL==pSize )
  452. return E_FAIL;
  453.  
  454. FLOAT fRowWidth = 0.0f;
  455. FLOAT fRowHeight = (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
  456. FLOAT fWidth = 0.0f;
  457. FLOAT fHeight = fRowHeight;
  458.  
  459. while( *strText )
  460. {
  461. TCHAR c = *strText++;
  462.  
  463. if( c == _T('\n') )
  464. {
  465. fRowWidth = 0.0f;
  466. fHeight += fRowHeight;
  467. }
  468.  
  469. if( (c-32) < 0 || (c-32) >= 128-32 )
  470. continue;
  471.  
  472. FLOAT tx1 = m_fTexCoords[c-32][0];
  473. FLOAT tx2 = m_fTexCoords[c-32][2];
  474.  
  475. fRowWidth += (tx2-tx1)*m_dwTexWidth - 2*m_dwSpacing;
  476.  
  477. if( fRowWidth > fWidth )
  478. fWidth = fRowWidth;
  479. }
  480.  
  481. pSize->cx = (int)fWidth;
  482. pSize->cy = (int)fHeight;
  483.  
  484. return S_OK;
  485. }
  486.  
  487.  
  488.  
  489.  
  490. //-----------------------------------------------------------------------------
  491. // Name: DrawTextScaled()
  492. // Desc: Draws scaled 2D text. Note that x and y are in viewport coordinates
  493. // (ranging from -1 to +1). fXScale and fYScale are the size fraction
  494. // relative to the entire viewport. For example, a fXScale of 0.25 is
  495. // 1/8th of the screen width. This allows you to output text at a fixed
  496. // fraction of the viewport, even if the screen or window size changes.
  497. //-----------------------------------------------------------------------------
  498. HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z,
  499. FLOAT fXScale, FLOAT fYScale, DWORD dwColor,
  500. TCHAR* strText, DWORD dwFlags )
  501. {
  502. if( m_pd3dDevice == NULL )
  503. return E_FAIL;
  504.  
  505. // Set up renderstate
  506. m_pStateBlockSaved->Capture();
  507. m_pStateBlockDrawText->Apply();
  508. m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX );
  509. m_pd3dDevice->SetPixelShader( NULL );
  510. m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
  511.  
  512. // Set filter states
  513. if( dwFlags & D3DFONT_FILTERED )
  514. {
  515. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  516. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  517. }
  518.  
  519. D3DVIEWPORT9 vp;
  520. m_pd3dDevice->GetViewport( &vp );
  521. FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight;
  522.  
  523. // Center the text block in the viewport
  524. if( dwFlags & D3DFONT_CENTERED_X )
  525. {
  526. const TCHAR* strTextTmp = strText;
  527. float xFinal = 0.0f;
  528.  
  529. while( *strTextTmp )
  530. {
  531. TCHAR c = *strTextTmp++;
  532.  
  533. if( c == _T('\n') )
  534. break; // Isn't supported.
  535. if( (c-32) < 0 || (c-32) >= 128-32 )
  536. continue;
  537.  
  538. FLOAT tx1 = m_fTexCoords[c-32][0];
  539. FLOAT tx2 = m_fTexCoords[c-32][2];
  540.  
  541. FLOAT w = (tx2-tx1)*m_dwTexWidth;
  542.  
  543. w *= (fXScale*vp.Height)/fLineHeight;
  544.  
  545. xFinal += w - (2 * m_dwSpacing) * (fXScale*vp.Height)/fLineHeight;
  546. }
  547.  
  548. x = -xFinal/vp.Width;
  549. }
  550. if( dwFlags & D3DFONT_CENTERED_Y )
  551. {
  552. y = -fLineHeight/vp.Height;
  553. }
  554.  
  555. FLOAT sx = (x+1.0f)*vp.Width/2;
  556. FLOAT sy = (y+1.0f)*vp.Height/2;
  557. FLOAT sz = z;
  558. FLOAT rhw = 1.0f;
  559.  
  560. // Adjust for character spacing
  561. sx -= m_dwSpacing * (fXScale*vp.Height)/fLineHeight;
  562. FLOAT fStartX = sx;
  563.  
  564. // Fill vertex buffer
  565. FONT2DVERTEX* pVertices;
  566. DWORD dwNumTriangles = 0L;
  567. m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
  568.  
  569. while( *strText )
  570. {
  571. TCHAR c = *strText++;
  572.  
  573. if( c == _T('\n') )
  574. {
  575. sx = fStartX;
  576. sy += fYScale*vp.Height;
  577. }
  578.  
  579. if( (c-32) < 0 || (c-32) >= 128-32 )
  580. continue;
  581.  
  582. FLOAT tx1 = m_fTexCoords[c-32][0];
  583. FLOAT ty1 = m_fTexCoords[c-32][1];
  584. FLOAT tx2 = m_fTexCoords[c-32][2];
  585. FLOAT ty2 = m_fTexCoords[c-32][3];
  586.  
  587. FLOAT w = (tx2-tx1)*m_dwTexWidth;
  588. FLOAT h = (ty2-ty1)*m_dwTexHeight;
  589.  
  590. w *= (fXScale*vp.Height)/fLineHeight;
  591. h *= (fYScale*vp.Height)/fLineHeight;
  592.  
  593. if( c != _T(' ') )
  594. {
  595. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx1, ty2 );
  596. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 );
  597. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 );
  598. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx2, ty1 );
  599. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 );
  600. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 );
  601. dwNumTriangles += 2;
  602.  
  603. if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
  604. {
  605. // Unlock, render, and relock the vertex buffer
  606. m_pVB->Unlock();
  607. m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
  608. m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
  609. dwNumTriangles = 0L;
  610. }
  611. }
  612.  
  613. sx += w - (2 * m_dwSpacing) * (fXScale*vp.Height)/fLineHeight;
  614. }
  615.  
  616. // Unlock and render the vertex buffer
  617. m_pVB->Unlock();
  618. if( dwNumTriangles > 0 )
  619. m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
  620.  
  621. // Restore the modified renderstates
  622. m_pStateBlockSaved->Apply();
  623.  
  624. return S_OK;
  625. }
  626.  
  627.  
  628.  
  629.  
  630. //-----------------------------------------------------------------------------
  631. // Name: DrawText()
  632. // Desc: Draws 2D text. Note that sx and sy are in pixels
  633. //-----------------------------------------------------------------------------
  634. HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor,
  635. TCHAR* strText, DWORD dwFlags )
  636. {
  637. if( m_pd3dDevice == NULL )
  638. return E_FAIL;
  639.  
  640. // Setup renderstate
  641. m_pStateBlockSaved->Capture();
  642. m_pStateBlockDrawText->Apply();
  643. m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX );
  644. m_pd3dDevice->SetPixelShader( NULL );
  645. m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
  646.  
  647. // Set filter states
  648. if( dwFlags & D3DFONT_FILTERED )
  649. {
  650. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  651. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  652. }
  653.  
  654. // Center the text block in the viewport
  655. if( dwFlags & D3DFONT_CENTERED_X )
  656. {
  657. D3DVIEWPORT9 vp;
  658. m_pd3dDevice->GetViewport( &vp );
  659. const TCHAR* strTextTmp = strText;
  660. float xFinal = 0.0f;
  661.  
  662. while( *strTextTmp )
  663. {
  664. TCHAR c = *strTextTmp++;
  665.  
  666. if( c == _T('\n') )
  667. break; // Isn't supported.
  668. if( (c-32) < 0 || (c-32) >= 128-32 )
  669. continue;
  670.  
  671. FLOAT tx1 = m_fTexCoords[c-32][0];
  672. FLOAT tx2 = m_fTexCoords[c-32][2];
  673.  
  674. FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale;
  675.  
  676. xFinal += w - (2 * m_dwSpacing);
  677. }
  678.  
  679. sx = (vp.Width-xFinal)/2.0f;
  680. }
  681. if( dwFlags & D3DFONT_CENTERED_Y )
  682. {
  683. D3DVIEWPORT9 vp;
  684. m_pd3dDevice->GetViewport( &vp );
  685. float fLineHeight = ((m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight);
  686. sy = (vp.Height-fLineHeight)/2;
  687. }
  688.  
  689. // Adjust for character spacing
  690. sx -= m_dwSpacing;
  691. FLOAT fStartX = sx;
  692.  
  693. // Fill vertex buffer
  694. FONT2DVERTEX* pVertices = NULL;
  695. DWORD dwNumTriangles = 0;
  696. m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
  697.  
  698. while( *strText )
  699. {
  700. TCHAR c = *strText++;
  701.  
  702. if( c == _T('\n') )
  703. {
  704. sx = fStartX;
  705. sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight;
  706. }
  707.  
  708. if( (c-32) < 0 || (c-32) >= 128-32 )
  709. continue;
  710.  
  711. FLOAT tx1 = m_fTexCoords[c-32][0];
  712. FLOAT ty1 = m_fTexCoords[c-32][1];
  713. FLOAT tx2 = m_fTexCoords[c-32][2];
  714. FLOAT ty2 = m_fTexCoords[c-32][3];
  715.  
  716. FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale;
  717. FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale;
  718.  
  719. if( c != _T(' ') )
  720. {
  721. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 );
  722. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
  723. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
  724. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 );
  725. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 );
  726. *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 );
  727. dwNumTriangles += 2;
  728.  
  729. if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
  730. {
  731. // Unlock, render, and relock the vertex buffer
  732. m_pVB->Unlock();
  733. m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
  734. pVertices = NULL;
  735. m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
  736. dwNumTriangles = 0L;
  737. }
  738. }
  739.  
  740. sx += w - (2 * m_dwSpacing);
  741. }
  742.  
  743. // Unlock and render the vertex buffer
  744. m_pVB->Unlock();
  745. if( dwNumTriangles > 0 )
  746. m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
  747.  
  748. // Restore the modified renderstates
  749. m_pStateBlockSaved->Apply();
  750.  
  751. return S_OK;
  752. }
  753.  
  754.  
  755.  
  756.  
  757. //-----------------------------------------------------------------------------
  758. // Name: Render3DText()
  759. // Desc: Renders 3D text
  760. //-----------------------------------------------------------------------------
  761. HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags )
  762. {
  763. if( m_pd3dDevice == NULL )
  764. return E_FAIL;
  765.  
  766. // Setup renderstate
  767. m_pStateBlockSaved->Capture();
  768. m_pStateBlockDrawText->Apply();
  769. m_pd3dDevice->SetFVF( D3DFVF_FONT3DVERTEX );
  770. m_pd3dDevice->SetPixelShader( NULL );
  771. m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT3DVERTEX) );
  772.  
  773. // Set filter states
  774. if( dwFlags & D3DFONT_FILTERED )
  775. {
  776. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  777. m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  778. }
  779.  
  780. // Position for each text element
  781. FLOAT x = 0.0f;
  782. FLOAT y = 0.0f;
  783.  
  784. // Center the text block at the origin (not the viewport)
  785. if( dwFlags & D3DFONT_CENTERED_X )
  786. {
  787. SIZE sz;
  788. GetTextExtent( strText, &sz );
  789. x = -(((FLOAT)sz.cx)/10.0f)/2.0f;
  790. }
  791. if( dwFlags & D3DFONT_CENTERED_Y )
  792. {
  793. SIZE sz;
  794. GetTextExtent( strText, &sz );
  795. y = -(((FLOAT)sz.cy)/10.0f)/2.0f;
  796. }
  797.  
  798. // Turn off culling for two-sided text
  799. if( dwFlags & D3DFONT_TWOSIDED )
  800. m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  801.  
  802. // Adjust for character spacing
  803. x -= m_dwSpacing / 10.0f;
  804. FLOAT fStartX = x;
  805. TCHAR c;
  806.  
  807. // Fill vertex buffer
  808. FONT3DVERTEX* pVertices;
  809. DWORD dwNumTriangles = 0L;
  810. m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
  811.  
  812. while( (c = *strText++) != 0 )
  813. {
  814. if( c == '\n' )
  815. {
  816. x = fStartX;
  817. y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f;
  818. }
  819.  
  820. if( (c-32) < 0 || (c-32) >= 128-32 )
  821. continue;
  822.  
  823. FLOAT tx1 = m_fTexCoords[c-32][0];
  824. FLOAT ty1 = m_fTexCoords[c-32][1];
  825. FLOAT tx2 = m_fTexCoords[c-32][2];
  826. FLOAT ty2 = m_fTexCoords[c-32][3];
  827.  
  828. FLOAT w = (tx2-tx1) * m_dwTexWidth / ( 10.0f * m_fTextScale );
  829. FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale );
  830.  
  831. if( c != _T(' ') )
  832. {
  833. *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+0,0), D3DXVECTOR3(0,0,-1), tx1, ty2 );
  834. *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
  835. *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 );
  836. *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+h,0), D3DXVECTOR3(0,0,-1), tx2, ty1 );
  837. *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 );
  838. *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 );
  839. dwNumTriangles += 2;
  840.  
  841. if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) )
  842. {
  843. // Unlock, render, and relock the vertex buffer
  844. m_pVB->Unlock();
  845. m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
  846. m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
  847. dwNumTriangles = 0L;
  848. }
  849. }
  850.  
  851. x += w - (2 * m_dwSpacing) / 10.0f;
  852. }
  853.  
  854. // Unlock and render the vertex buffer
  855. m_pVB->Unlock();
  856. if( dwNumTriangles > 0 )
  857. m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
  858.  
  859. // Restore the modified renderstates
  860. m_pStateBlockSaved->Apply();
  861.  
  862. return S_OK;
  863. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement