#### Archived

This topic is now archived and is closed to further replies.

# Text *= (1/2)

## Recommended Posts

Well, this is not a question about how to split a text in 2 halfs because I can already do that. But actually exactly this is what I want to avoid . I have written a class to handle a texture font but its print method just shows half the text. The class uses a texture which contains 16 * 16 letters which are 16 * 16 in size. They are the same order as in the ASCII code (but starting with 32) and I have 2 character sets per texture which makes it 256 characters and 128 characters per set. So this is the code for printing:
void CTextureFont:rint(int iX, int iY, D3DCOLOR Color, int iCharacterSet, LPSTR strFormat, ...) {
char strText[1024];
int iCurrentPosition = 0;
int iLastX = iX;
float fX = 0.0f;
float fY = 0.0f;
va_list Arguments;
CMaterial Material;
LPVERTEX2D pFontVertices = NULL;
VERTEX2D LetterVertices[4];

if(iCharacterSet > 1) {
iCharacterSet = 1;
}

va_start(Arguments, strFormat);
vsprintf(strText, strFormat, Arguments);
va_end(Arguments);

pFontVertices = new VERTEX2D[strlen(strText) * 4];
ZeroMemory(pFontVertices, sizeof(VERTEX2D) * strlen(strText) * 4);

m_pVertexBuffer->ShutDown();
m_pVertexBuffer->Init(m_pGraphics, strlen(strText) * 4, VERTEX_2D, sizeof(VERTEX2D), D3DUSAGE_WRITEONLY);

for(int i = 0; i < strlen(strText); i++) {
fX = float(strText - 32 + (128 * iCharacterSet));
fY = float(strText[i] - 32 + (128 * iCharacterSet));

fX = (Round(fX) % 16) / 16.0f;
fY = floorf(fY / 16.0f) / 16.0f;

LetterVertices[0].color = Color;
LetterVertices[0].rhw = 1.0f;
LetterVertices[0].tu = fX;
LetterVertices[0].tv = fY + m_fLetterHeight;
LetterVertices[0].x = iX;
LetterVertices[0].y = iY + 16;
LetterVertices[0].z = 0.0f;
LetterVertices[1].color = Color;
LetterVertices[1].rhw = 1.0f;
LetterVertices[1].tu = fX;
LetterVertices[1].tv = fY;
LetterVertices[1].x = iX;
LetterVertices[1].y = iY;
LetterVertices[1].z = 0.0f;
//Rechts Unten
LetterVertices[2].color = Color;
LetterVertices[2].rhw = 1.0f;
LetterVertices[2].tu = fX + m_fLetterWidth;
LetterVertices[2].tv = fY + m_fLetterHeight;
LetterVertices[2].x = iX + 16;
LetterVertices[2].y = iY + 16;
LetterVertices[2].z = 0.0f;
//Rechts Oben
LetterVertices[3].color = Color;
LetterVertices[3].rhw = 1.0f;
LetterVertices[3].tu = fX + m_fLetterWidth;
LetterVertices[3].tv = fY;
LetterVertices[3].x = iX + 16;
LetterVertices[3].y = iY;
LetterVertices[3].z = 0.0f;

memcpy(&pFontVertices[iCurrentPosition], LetterVertices, sizeof(VERTEX2D) * 4);
iCurrentPosition += 4;
iX += 16;
}

m_pVertexBuffer->Set(0, 4 * strlen(strText), pFontVertices);

m_pGraphics->SetTexture(0, m_pTexture);
m_pGraphics->SetMaterial(&Material);
m_pGraphics->SetRenderState(D3DRS_ZENABLE, FALSE);

m_pVertexBuffer->Render(0, 2 * strlen(strText), D3DPT_TRIANGLESTRIP);

m_pGraphics->SetRenderState(D3DRS_ZENABLE, TRUE);
m_pGraphics->GetDevice()->SetTexture(0, NULL);

SAFE_DELETEV(pFontVertices);
}

The LetterWidth variables are always (1 / 16). So why do I get "Hi" when I tell the function to write "Hiho" ?

##### Share on other sites
i think you need TRIANGLELIST primitive type, not the strip.

also, some performance tips:
- call strlen only once for the entire function
- don''t dynamically allocate any memory, write directly to vertex buffer
- use D3DUSAGE_DYNAMIC along with WRITEONLY
- don''t create vertex buffer here, create it on program startup instead
- i may be wrong here, but setting material is useless because you''re drawing lit primitives

##### Share on other sites
Well, the function will have to be able to display any length of text possible (well, almost) so I would have to set up a really large VB (1024 letters possible * 4 or 6 vertices = 4048 or 6144 vertices).

And why will I need a triangle list?

##### Share on other sites
quote:
Original post by Hippokrates
Well, the function will have to be able to display any length of text possible (well, almost) so I would have to set up a really large VB (1024 letters possible * 4 or 6 vertices = 4048 or 6144 vertices).

no. use dynamic vertex buffers as CD3DFont in the samples does.
quote:

And why will I need a triangle list?

because that''s how your vertices are set up.

you''re doing something really unusual in this code. i suggest you look at the CD3DFont class which you can find in dxsdk\samples\multimedia\common. it is a fairly clean and efficient font class, and you should understand it before trying to write your own font class.

##### Share on other sites
Why are my vertices set up for a triangle list??
And using dynamic buffers wont have my text appear completely, will it ?

##### Share on other sites
quote:
Original post by Hippokrates
Why are my vertices set up for a triangle list??

because you''re writing four vertices for every character? did you actually try to change one line in your program and see if that change fixed the problem? if yes, why not say just that? if no, why are you wasting my time with stupid questions?
quote:

And using dynamic buffers wont have my text appear completely, will it ?

##### Share on other sites
Well, I have to admit, using 6 vertices and a triangle list did indeed fix the problem. But I still don`t have a clue why it did...

##### Share on other sites
Perhaps I am reading the code wrong, but it seems like you are doing this in a not-so-good way.

Rendering the text letter by letter is a very slow way to do it.
Create one vertex buffer and fill it with many letters before drawing it. If the number of letters exceeds your VB size, render what you have so far and THEN refill (as opposed to every letter).

Your method is essentially the same as CD3DFont, but CD3DFont is probably much faster. See the code in the SDK to see how they do it.

##### Share on other sites
I am filling in all the letters as a triangle list and render them in one go. This works so far.
But I would like to know how to use dynamic vertex buffers and if this would increase performance.

• ### Forum Statistics

• Total Topics
628329
• Total Posts
2982104

• 22
• 9
• 9
• 13
• 11