bool CD3DMGEng::DrawText3D ( float x, float y, float z, D3DMATRIX * pMatView, DWORD dwColor, const TCHAR *wszText, float fTextSize, FONTFLAGS ffFlags, FONTSET fsSet ) { D3DSPRITEVERTEX3D * pVertices = NULL; D3DXMATRIX MatWorld, MatView, MatTranslation, MatTransposed; DWORD dwTriangleCount = 0; float fStartX = 0; //////////////////////////////////////////////////// // Make sure we have a valid vertex buffer. if ( m_pVB == NULL ) { return false; } //////////////////////////////////////////////////// // Make sure our texture and coords are loaded. if ( m_pFontTexture == NULL || m_bFontInfoLoaded == false ) { return false; } /////////////////////////////////////////////////// // Setup the rendering. // Convert our view matrix from D3DMATRIX to D3DXMATRIX MatView = *pMatView; D3DXMatrixTranspose ( &MatTransposed, &MatView ); // Create an Inverse matrix out of the view matrix (go from view to world space). MatTransposed._41 = MatTransposed._42 = MatTransposed._43 = MatTransposed._14 = MatTransposed._24 = MatTransposed._34 = 0.0f; // Create an empty identity matrix. D3DXMatrixIdentity ( &MatWorld ); // Add in our scaling here. float fSize = fTextSize / 100.0f; D3DXMatrixScaling ( &MatWorld, fSize, fSize, fSize ); // Set position of text in world. D3DXMatrixTranslation ( &MatTranslation, x, y, z ); // Apply settings to new world matrix. D3DXMatrixMultiply ( &MatWorld, &MatWorld, &MatTransposed ); D3DXMatrixMultiply ( &MatWorld, &MatWorld, &MatTranslation ); m_pDevice->SetFVF ( D3DFVF_SPRITEVERTEX3DTEX ); m_pDevice->SetStreamSource ( 0, m_pVB, 0, sizeof(D3DSPRITEVERTEX3D) ); m_pDevice->SetTexture ( 0, m_pFontTexture ); m_pDevice->SetTransform ( D3DTS_WORLD, &MatWorld ); x = 0; y = 0; /////////////////////////////////////////////////// // Do flag processing before we go any further. if ( ffFlags ) { SIZE sz; // First, get extent of drawn text. UTIL_GetTextExtent(wszText, &sz, fTextSize); // Do math on x coordinate accordingly. switch ( ffFlags ) { case D3DFF_CENTERED: x -= sz.cx/2; break; case D3DFF_RIGHT: x += sz.cx; break; case D3DFF_LEFT: //x += sz.cx/2; break; default: break; } } fStartX = x; m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); while ( *wszText ) { TCHAR c = *wszText++; if ( c == _T('\n') ) { x = fStartX; y += m_aFontCoords[fsSet].fHeight; continue; } if ( c < _T(' ') || c > _T(128) ) { continue; } float tx1 = m_aFontCoords[fsSet+c-32].tx1; float tx2 = m_aFontCoords[fsSet+c-32].tx2; float ty1 = m_aFontCoords[fsSet+c-32].ty1; float ty2 = m_aFontCoords[fsSet+c-32].ty2; float w = m_aFontCoords[fsSet+c-32].fWidth; float h = m_aFontCoords[fsSet+c-32].fHeight; if ( c == _T(' ') ) { x += w; continue; } // First triangle (bottom right) *pVertices++ = InitFont3DVertex ( x+w, y+h, 0.0f, dwColor, tx2, ty1 ); //bottom right. *pVertices++ = InitFont3DVertex ( x+w, y, 0.0f, dwColor, tx2, ty2 ); //top right. *pVertices++ = InitFont3DVertex ( x, y+h, 0.0f, dwColor, tx1, ty1 ); //bottom left. // Second triangle (upper left) *pVertices++ = InitFont3DVertex ( x, y, 0.0f, dwColor, tx1, ty2 ); //top left. *pVertices++ = InitFont3DVertex ( x+w, y, 0.0f, dwColor, tx2, ty2 ); //top right. *pVertices++ = InitFont3DVertex ( x, y+h, 0.0f, dwColor, tx1, ty1 ); //bottom right. x += w; dwTriangleCount += 2; //////////////////////////////////////////////////// // If we've gone over our limit, draw what we have. if ( dwTriangleCount*3 >= D3DSPRITE_NUMVERTS-6 ) { m_pVB->Unlock(); m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwTriangleCount ); m_pVB->Lock( 0, 0, (void**)&(pVertices=NULL), D3DLOCK_DISCARD ); dwTriangleCount = 0L; } } m_pVB->Unlock(); //////////////////////////////////////////////////// // Draw if we have anything. if ( dwTriangleCount > 0 ) { m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwTriangleCount ); } return true; }
//----------------------------------------------------------------------------- // Name: Render3DText() // Desc: Renders 3D text //----------------------------------------------------------------------------- HRESULT CD3DFont::Render3DText( const TCHAR* strText, DWORD dwFlags ) { if( m_pd3dDevice == NULL ) return E_FAIL; // Setup renderstate m_pStateBlockSaved->Capture(); m_pStateBlockDrawText->Apply(); m_pd3dDevice->SetFVF( D3DFVF_FONT3DVERTEX ); m_pd3dDevice->SetPixelShader( NULL ); m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT3DVERTEX) ); // Set filter states if( dwFlags & D3DFONT_FILTERED ) { m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); } // Position for each text element FLOAT x = 0.0f; FLOAT y = 0.0f; // Center the text block at the origin (not the viewport) if( dwFlags & D3DFONT_CENTERED_X ) { SIZE sz; GetTextExtent( strText, &sz ); x = -(((FLOAT)sz.cx)/10.0f)/2.0f; } if( dwFlags & D3DFONT_CENTERED_Y ) { SIZE sz; GetTextExtent( strText, &sz ); y = -(((FLOAT)sz.cy)/10.0f)/2.0f; } // Turn off culling for two-sided text if( dwFlags & D3DFONT_TWOSIDED ) m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); // Adjust for character spacing x -= m_dwSpacing / 10.0f; FLOAT fStartX = x; TCHAR c; // Fill vertex buffer FONT3DVERTEX* pVertices; DWORD dwNumTriangles = 0L; m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); while( (c = *strText++) != 0 ) { if( c == '\n' ) { x = fStartX; y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f; } if( (c-32) < 0 || (c-32) >= 128-32 ) continue; FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT ty1 = m_fTexCoords[c-32][1]; FLOAT tx2 = m_fTexCoords[c-32][2]; FLOAT ty2 = m_fTexCoords[c-32][3]; FLOAT w = (tx2-tx1) * m_dwTexWidth / ( 10.0f * m_fTextScale ); FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale ); if( c != _T(' ') ) { *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+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,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 ); *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 ); dwNumTriangles += 2; if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) { // Unlock, render, and relock the vertex buffer m_pVB->Unlock(); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); dwNumTriangles = 0L; } } x += w - (2 * m_dwSpacing) / 10.0f; } // Unlock and render the vertex buffer m_pVB->Unlock(); if( dwNumTriangles > 0 ) m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); // Restore the modified renderstates m_pStateBlockSaved->Apply(); return S_OK; }
//----------------------------------------------------------------------------- // Name: Render3DText() // Desc: Renders 3D text //----------------------------------------------------------------------------- HRESULT CD3DFont::Render3DText( TCHAR* strText, DWORD dwFlags, float r, float g, float b, float a ) { D3DMATERIAL8 mtrl; if( m_pd3dDevice == NULL ) return E_FAIL; // Setup renderstate m_pd3dDevice->CaptureStateBlock( m_dwSavedStateBlock ); m_pd3dDevice->ApplyStateBlock( m_dwDrawTextStateBlock ); m_pd3dDevice->SetVertexShader( D3DFVF_FONT3DVERTEX ); m_pd3dDevice->SetPixelShader( NULL ); m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(FONT3DVERTEX) ); m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); D3DUtil_InitMaterial( mtrl, r, g, b, a ); m_pd3dDevice->SetMaterial(&mtrl); // Set filter states if( dwFlags & D3DFONT_FILTERED ) { m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); } // Position for each text element FLOAT x = 0.0f; FLOAT y = 0.0f; // Center the text block at the origin if( dwFlags & D3DFONT_CENTERED ) { SIZE sz; GetTextExtent( strText, &sz ); x = -(((FLOAT)sz.cx)/10.0f)/2.0f; y = -(((FLOAT)sz.cy)/10.0f)/2.0f; } // Turn off culling for two-sided text if( dwFlags & D3DFONT_TWOSIDED ) m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); FLOAT fStartX = x; TCHAR c; // Fill vertex buffer FONT3DVERTEX* pVertices; DWORD dwVertex = 0L; DWORD dwNumTriangles = 0L; m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); while( c = *strText++ ) { if( c == '\n' ) { x = fStartX; y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f; } if( c == _T('\01')) { // Unlock, render, and relock the vertex buffer m_pVB->Unlock(); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); dwNumTriangles = 0L; float g1 = (float)((int)(0xFF&*strText++) / 255.f); float b1 = (float)((int)(0xFF&*strText++) / 255.f); float r1 = (float)((int)(0xFF&*strText++) / 255.f); float a1 = (float)((int)(0xFF&*strText++) / 255.f); D3DUtil_InitMaterial( mtrl, r1,b1,g1,a1 );/*((float)(*strText++))/255.0f, ((float)(*strText++))/255.0f, // ((float)(*strText++))/255.0f, ((float)(*strText++))/255.0f );*/ m_pd3dDevice->SetMaterial(&mtrl); continue; } if( c < 32 ) continue; FLOAT tx1 = m_fTexCoords[c-32][0]; FLOAT ty1 = m_fTexCoords[c-32][1]; FLOAT tx2 = m_fTexCoords[c-32][2]; FLOAT ty2 = m_fTexCoords[c-32][3]; FLOAT w = (tx2-tx1) * m_dwTexWidth / ( 10.0f * m_fTextScale ); FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale ); if( c != _T(' ') ) { *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+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,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 ); *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 ); dwNumTriangles += 2; if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) { // Unlock, render, and relock the vertex buffer m_pVB->Unlock(); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); m_pVB->Lock( 0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD ); dwNumTriangles = 0L; } } x += w; } // Unlock and render the vertex buffer m_pVB->Unlock(); if( dwNumTriangles > 0 ) m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); // Restore the modified renderstates m_pd3dDevice->ApplyStateBlock( m_dwSavedStateBlock ); return S_OK; }