Archived

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

Hippokrates

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;

		//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);
}
 
The LetterWidth variables are always (1 / 16). So why do I get "Hi" when I tell the function to write "Hiho" ?

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 won`t have my text appear completely, will it ?


not if you keep asking instead of fixing your code in devstudio.

Share this post


Link to post
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 this post


Link to post
Share on other sites