65.9K
CodeProject is changing. Read more.
Home

Write Text Inside an Image: Add a Poster to Add it in your Mogre Scene

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1 vote)

Feb 19, 2010

CPOL
viewsIcon

10076

To display information in your scene, you can use a billboard represented by the MovableText into (M)ogre but sometimes you just want to put some static text somewhere because it's more readable.

Introduction

To display information in your scene, you can use a billboard represented by the MovableText into (M)ogre but sometimes you just want to put some static text somewhere because it's more readable.

For example:

Create a poster to add it in your Mogre Scene

The Code

Here is the code which uses a lot of my last article.

The steps are as given below:

  1. Create a bitmap with the text in it
  2. Create a texture with this image, then a material
  3. Create a poster (rectangle) and put the texture on it
  4. Return the manualObject created

The part which may interest you is how to get the right size for the created bitmap based on the text...

Also the creation of the manualObject is not necessary but I think it may interest some people to see how to use it.

/// <summary>
/// Creates a 'poster' based on a text.
/// </summary>
/// <param name="Smgr">The scenemanager (necessary to create the manual object).</param>
/// <param name="text">The text to put on the poster.</param>
/// <author>Jonathan ANTOINE</author>
private static ManualObject createALabel(SceneManager Smgr, String text)
{
String textureName = Guid.NewGuid().ToString();
System.Drawing.Font font = new System.Drawing.Font("Calibri", 12, FontStyle.Bold);
Bitmap bitmap = new Bitmap(1, 1);
Graphics g = Graphics.FromImage(bitmap);
 
SizeF measureString = g.MeasureString(text, font);
bitmap = new Bitmap((int)measureString.Width, (int)measureString.Height);
g = Graphics.FromImage(bitmap);
g.FillRectangle(Brushes.Black, 
	new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height));
g.DrawString(text, font, new System.Drawing.SolidBrush(Color.White), new Point(3, 3));
 
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
 
Stream oStream = new MemoryStream();
g.Save();
bitmap.Save(oStream, ImageFormat.Png);
oStream.Flush();
 
//bitmap.Dispose();
//Back to the start of the stream
oStream.Position = 0;
 
//read all the stream
BinaryReader oBinaryReader = new BinaryReader(oStream);
byte[] pBuffer = oBinaryReader.ReadBytes((int)oBinaryReader.BaseStream.Length);
oStream.Close(); //No more needed
TextureManager.Singleton.Remove(textureName); //Remove eventually texture with the same name
unsafe
{
GCHandle handle = GCHandle.Alloc(pBuffer, GCHandleType.Pinned);
byte* pUnsafeByte = (byte*)handle.AddrOfPinnedObject();
void* pUnsafeBuffer = (void*)handle.AddrOfPinnedObject();
 
MemoryDataStream oMemoryStream = new MemoryDataStream(pUnsafeBuffer, (uint)pBuffer.Length);
DataStreamPtr oPtrDataStream = new DataStreamPtr(oMemoryStream);
 
Mogre.Image oMogreImage = new Mogre.Image().Load(oPtrDataStream, "png");
 
TextureManager.Singleton.LoadImageW(textureName, 
	ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME, oMogreImage);
 
//handle.Free();
}
String matNam = Guid.NewGuid().ToString();
MaterialPtr _dynamicMaterial = 
MaterialManager.Singleton.Create(matNam, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME);
Pass pass = _dynamicMaterial.GetTechnique(0).GetPass(0);
 
pass.ShadingMode = ShadeOptions.SO_PHONG;
 
TextureUnitState tus = pass.CreateTextureUnitState(textureName);
tus.SetTextureAddressingMode(TextureUnitState.TextureAddressingMode.TAM_CLAMP);
pass.AddTextureUnitState(tus);
 
_dynamicMaterial.Dispose(); //Dispose the pointer, not the material !
 
ManualObject manualObject = Smgr.CreateManualObject(Guid.NewGuid().ToString());
 
manualObject.EstimateIndexCount(6);
manualObject.EstimateVertexCount(6);
 
manualObject.Begin(matNam, RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
 
//DESSUS
int yWidthVariable = bitmap.Width;
int xWidth = bitmap.Height;
 
manualObject.Position(new Vector3(0, 0, 0));
manualObject.TextureCoord(1, 0);
manualObject.Normal(Vector3.UNIT_Z);
 
manualObject.Position(new Vector3(0, -yWidthVariable, 0));
manualObject.TextureCoord(0, 0f);
manualObject.Normal(Vector3.UNIT_Z);
manualObject.Position(new Vector3(xWidth, 0, 0));
manualObject.TextureCoord(1f, 1);
manualObject.Normal(Vector3.UNIT_Z);
 
manualObject.Position(new Vector3(0, -yWidthVariable, 0));
manualObject.TextureCoord(0f, 0f);
manualObject.Normal(Vector3.UNIT_Z);
manualObject.Position(new Vector3(xWidth, -yWidthVariable, 0));
manualObject.TextureCoord(0f, 1.0f);
manualObject.Normal(Vector3.UNIT_Z);
manualObject.Position(new Vector3(xWidth, 0, 0));
manualObject.TextureCoord(1f, 1.0f);
manualObject.Normal(Vector3.UNIT_Z);
 
manualObject.End();
 
manualObject.CastShadows = false;
 
return manualObject;
}

Also you can get the size of the "poster" by using the boundingbox. An example of use:

manualObject.BoundingBox.Size.x * 0.5f * Vector3.UNIT_Y;

The code can be found as an attached file.

kick it on DotNetKicks.com