Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

Use a screenshot of a WPF visual as a texture in Mogre

5.00/5 (2 votes)
19 Feb 2010CPOL1 min read 25.8K  
How to use a screenshot of a WPF elements and put it as a texture on your Mogre object

Introduction

Hello, here is my first post about WPF and Mogre, maybe it will help some people... The subject of today is "How to use a screenshot of a WPF elements and put it as an texture on your Mogre object"...

Why? Because WPF enables you to create a very rich interface and a great image to place on your different elements...

By the way, I let you follow the link at the end of the post to learn how to blend Mogre in WPF and how to take a screenShot of a WPF visual.

The steps to follow are listed below:

  1. Create a screenshot of the WPF visual (any visual can be used)
  2. Put the bitmap in a stream and then to a buffer
  3. Use some unsafe code to create a Mogre MemoryStream and a mogre image
  4. Use this image to create a texture
  5. Use this texture in a material
  6. Put it on the mesh of your choice

Create a Screenshot of the WPF Visual

The original code is from thomas lebrun and can be found in any good WPF book:

C#
Visual theVisual = this ; //Put the aimed visual here.
double width = Convert.ToDouble(theVisual.GetValue(FrameworkElement.WidthProperty));
double height = Convert.ToDouble(theVisual.GetValue(FrameworkElement.HeightProperty));
if (double.IsNaN(width) || double.IsNaN(height))
{
throw new FormatException
	("You need to indicate the Width and Height values of the UIElement.");
}
RenderTargetBitmap render = new RenderTargetBitmap(
      Convert.ToInt32(width),
      Convert.ToInt32(this.GetValue(FrameworkElement.HeightProperty)),
      96,
      96,
      PixelFormats.Pbgra32);
// Indicate which control to render in the image
render.Render(this);
Stream oStream = new MemoryStream();
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(render));
encoder.Save(oStream);
oStream.Flush();

Put the Bitmap in a Stream and Then to a Buffer

C#
//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(sName); //Remove eventually texture with the same name

Create the Texture

C#
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);
            oMogreImage = oMogreImage.Load(oPtrDataStream, "png");
 
            TextureManager.Singleton.LoadImageW
		(sName, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME, oMogreImage);
 
            //handle.Free();
         }

Use this Texture in a Material

Here is the code of how you can create a material with this texture:

C#
_dynamicMaterial = MaterialManager.Singleton.Create
	(SCREENSHOT_MATERIAL_NAME, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME);
Pass pass = _dynamicMaterial.GetTechnique(0).GetPass(0);
 
TextureUnitState tus = pass.CreateTextureUnitState(SCREENSHOT_TEXTURE_NAME);
_dynamicMaterial.GetTechnique(0).GetPass(0).AddTextureUnitState(tus);

Then you just have to use it as a normal texture...

An Example

Here is a screenshot of the results. I display a cube with the face using as a texture a screenshot of the window in which it is....

WPF screenshot as a texture in Mogre

Link: How to blend Mogre in WPF

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)