applying text to a mesh/texture

Started by
5 comments, last by Chett2001 17 years ago
Basically what im trying to do is create a book, i have created a simple page which ive animated to flip over when a key is pressed. Because each page will have different text on it i need a way to apply the text onto the page so when the book turns the text turns with it, the only way i have done text before is using RECT's as place holders so im pretty stumped how i can achieve this without creating a texture with the text on it. I dont want to do that because its not inline with the spec of the application i have to make (unless its done exclusively in DirectX at run time). Anyone got any suggestions for better ways of achieving this effect? The page (a flat rectangle) was created in 3dsmax and the page flip 'animation' is simply a rotation on the Y axis of 180 degrees.
Chett - "I look forward to helping all of you one day, but right now im just a noob learning his way through the perils of game Development."
Advertisement
Hey Chett2001,

I am not sure I understand : Why do you want not to use a Direct3D texture for that ? Could you please elaborate ?
Do you know that you can create a Direct3D texture in memory and write whatever you want on it, at runtime ? If you did not, the following code shows how to do that.
void my_function_that_writes_text_on_a_texture_in_memory(){	D3DSURFACE_DESC ddsd;	if (FAILED(D3DXCreateTexture(m_pD3DDevice, iTextureWidth, iTextureHeight, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pMyTexture)) )	{		return FALSE;	}	if (FAILED(m_pTitleTexture->GetLevelDesc( 0, &ddsd ) ) )	{		return FALSE;	}	D3DFORMAT g_TextureFormat = ddsd.Format;	if (g_TextureFormat != D3DFMT_A8R8G8B8 && g_TextureFormat != D3DFMT_A1R5G5B5) {		return FALSE;	}	BYTE* ptPixels;		HDC memDC = CreateCompatibleDC(NULL);	HBITMAP hSomeBitmap = InitGenericBitmap(m_iMaxTitleWidth, m_iMaxTitleHeight, memDC, &ptPixels);	HBITMAP OldResBitmap = (HBITMAP)SelectObject(memDC, hSomeBitmap);	// prepare the bitmap for transparency...	HBRUSH myTransparentColorBrush = CreateSolidBrush(D3DCOLOR_RGBA(129, 87, 112, 30));  // for test purpose	HBRUSH theOldBrush = (HBRUSH)SelectObject(memDC, myTransparentColorBrush);	PatBlt(memDC, 0, 0, m_iMaxTitleWidth, m_iMaxTitleHeight, PATCOPY);	SelectObject(memDC, theOldBrush);	DeleteObject(myTransparentColorBrush);	int oldbkmode = SetBkMode(memDC, TRANSPARENT);	COLORREF textcolor = RGB(255, 255, 255);	COLORREF oldtextcolor = SetTextColor(memDC, textcolor);	LOGFONT lfFont;	SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lfFont, 0);    HFONT hFontNew = CreateFontIndirect(&lfFont);    HFONT hFontOld = (HFONT) SelectObject(memDC, hFontNew);	RECT myRect;	myRect.right = m_iMaxTitleWidth-1; // Mmm... I have an example on my desktop of an icon that can be displayed	// on one single line, and however, it appears on two lines...  that's why I am reducing the rectangle here.	myRect.left = 0;	myRect.bottom = m_iMaxTitleHeight-1; // same for the height, even though I have not experienced it	myRect.top = 0;	char Msg[255];	strcpy(Msg, "Hello brave new world...");	DrawText(memDC, Msg, strlen(Msg), &myRect, DT_WORDBREAK | DT_CENTER | DT_NOPREFIX | DT_END_ELLIPSIS);	// Clean up.	SetTextColor(memDC, oldtextcolor);	SetBkMode(memDC, oldbkmode);    SelectObject(memDC, hFontOld);    DeleteObject(hFontNew);	SelectObject(memDC, OldResBitmap);    DeleteDC(memDC);	addBitmapToTitleTexture(hSomeBitmap); // see next function below	DeleteObject(hSomeBitmap);}void addBitmapToTitleTexture(HBITMAP theBitmap){	BYTE* ptPixels;		BITMAP bm;	GetObject(theBitmap, sizeof(bm), &bm);		HDC DirectDC = CreateCompatibleDC(NULL); // DC for working	HBITMAP DirectBitmap = InitGenericBitmap(bm.bmWidth, bm.bmHeight, DirectDC, &ptPixels);	if (DirectBitmap)	{		HDC BufferDC = CreateCompatibleDC(NULL);		SelectObject(BufferDC, theBitmap);		HGDIOBJ PreviousObject=SelectObject(DirectDC, DirectBitmap);		// we use StretchBlt as a trick to mirror the bitmap.  As a matter of fact, copying to the DirectX texture mirrors the result		BOOL bRes = StretchBlt(DirectDC, 0, bm.bmHeight-1, bm.bmWidth, -bm.bmHeight, BufferDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);				SelectObject(DirectDC, PreviousObject);		BYTE* clrPixels = ptPixels;		D3DLOCKED_RECT d3dlr;		m_pTitleTexture->LockRect( 0, &d3dlr, 0, 0 );		LONG lTexturePitch = d3dlr.Pitch;		LONG lSamplePitch = 4*bm.bmWidth;		// Get the texture buffer & pitch		BYTE *pTextureBuffer = static_cast<byte *>(d3dlr.pBits) + lSamplePitch+bm.bmHeight;		for(LONG row = 0; row < bm.bmHeight; row++ ) 		{			BYTE *pBmpBufferOld = clrPixels;			BYTE *pTxtBufferOld = pTextureBuffer;			for (LONG col = 0; col < bm.bmWidth; col++) 			{				pTextureBuffer[0] = clrPixels[0];				pTextureBuffer[1] = clrPixels[1];				pTextureBuffer[2] = clrPixels[2];				{					// condition for alpha blending/testing					if (clrPixels[0] == my_r && clrPixels[1] == my_g && clrPixels[2] == my_b)						pTextureBuffer[3] = 0x00;					else						pTextureBuffer[3] = 0xFF;				}				pTextureBuffer += 4;				clrPixels  += 4;			}			clrPixels  = pBmpBufferOld + lSamplePitch;			pTextureBuffer = pTxtBufferOld + lTexturePitch;		}		m_pTitleTexture->UnlockRect(0);		DeleteDC(BufferDC);	}	DeleteDC(DirectDC);	DeleteObject(DirectBitmap);}

Cheers
StratBoy61
I think the easiest way to do this would be to use a render-to-texture pass to generate the page texture at runtime. This way you can still use the text rendering like you're used to and because you only need to generate the texture once, this approach should get the job done with a minimum of overhead.

Edit - Bah, too late [smile] StratBoy61's solution should also work just fine.
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
MMm im finding that code kinda confusing im pretty new to DirectX and C++, do you have a full example? I replaced m_pMyTexture with the name of my bitmaps texture but ive got errors such as InitGenericBitmap': identifier not found, do i need to define it somewhere? I defined some UINT's for the sizes of the texture look right?:

UINT iTextureWidth = 1024;
UINT iTextureHeight = 1024;
UINT m_iMaxTitleWidth = 1000;
UINT m_iMaxTitleHeight = 40;

And to make it work i would have to call:

my_function_that_writes_text_on_a_texture_in_memory()

then

addBitmapToTitleTexture(?????) (I see the first function uses this one so i dont have too !!)

(-_-)
Chett - "I look forward to helping all of you one day, but right now im just a noob learning his way through the perils of game Development."
Hey Chet2001,

Here is the implementation of the missing funtion.
HBITMAP InitGenericBitmap(int iIconWidth, int iIconHeight, HDC theDC, BYTE **BitmapPtr){	BITMAPINFO RGB32BitsBITMAPINFO; 	ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));	RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);	RGB32BitsBITMAPINFO.bmiHeader.biWidth=iIconWidth;	RGB32BitsBITMAPINFO.bmiHeader.biHeight=iIconHeight;	RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;	RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32;	return CreateDIBSection(theDC, 						   (BITMAPINFO *)&RGB32BitsBITMAPINFO, 						   DIB_RGB_COLORS,						   (void **)BitmapPtr, 						   NULL, 0);}

I recommend you to spend some time understanding what the whole code does. If you are a beginner, it is a bit of a problem, because what you want to do is not straightforward, unfortunately...
Maybe you want to start with a simple project that will only create a DIB with your dynamic text inside and display it onto a window panel (using MFC for instance); then, you may move on to applying the same technique to a DirectX texture.
Cheers
StratBoy61
Allright will do, ive got it kinda working.. textures a bit distorted, the section the text is writen to is inverted colour and text? and the text is small.. Nothing a bit more research can fix no doubt :D. Its just nice to have something to play with so i can see exactly what controls what if you know what i mean, its a lot easier learning that way imo. I had no idea how i would achieve this before making this post so i would like to thank you guys a lot for the help leading me on the right lines. If i get completely stuck again though you might see another post further down the line :)
Chett - "I look forward to helping all of you one day, but right now im just a noob learning his way through the perils of game Development."
OK another quick question, i want to replace the regular char Msg[255] variable text with something i can change the size of or the font type the line of code i need to change is:

DrawText(memDC, Msg, strlen(Msg), &myRect, DT_WORDBREAK | DT_CENTER | DT_NOPREFIX | DT_END_ELLIPSIS);

So i created a font with the settings i want and that all works this type of font doesnt accept the memDC and wants a sprite, when i leave it as a NULL value and let DirectX do its thing nothing shows up:

g_pd3dxFont->DrawText( NULL, myString, -1, &myRect, DT_WORDBREAK | DT_CENTER | DT_NOPREFIX | DT_END_ELLIPSIS, D3DXCOLOR(255, 255, 255, 1.0f));

Im sure its because i cant include the memDC, so:

A) whys is there a significant difference between the two types of DrawText.
B) What would be the best method to achieve this.
C) What exactly is memDC (HDC) achieving in this example? All the documentaiton ive read through hasnt really helped explain it.
Chett - "I look forward to helping all of you one day, but right now im just a noob learning his way through the perils of game Development."

This topic is closed to new replies.

Advertisement