Text *= (1/2)

Started by
7 comments, last by Hippokrates 21 years, 8 months ago
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 - 32 + (128 * iCharacterSet));

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

		//Links Unten
		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;
		//Links Oben
		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);
}
 </pre> 
The LetterWidth variables are always (1 / 16).
So why do I get "Hi" when I tell the function to write "Hiho" ?  </i>   
Im Anfang war die Tat...Faust
Advertisement
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
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?
Im Anfang war die Tat...Faust
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.
Why are my vertices set up for a triangle list??
And using dynamic buffers won`t have my text appear completely, will it ?
Im Anfang war die Tat...Faust
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 won`t have my text appear completely, will it ?

not if you keep asking instead of fixing your code in devstudio.
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...
Im Anfang war die Tat...Faust
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.
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
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.
Im Anfang war die Tat...Faust

This topic is closed to new replies.

Advertisement