Archives

All posts for the month November, 2014

Xamarin recently published a interview with George Banfill from LinkNode on their Augmented Reality product, you can see the full interview here. Since then I’ve had a number of requests from people wanting to know how to do this using MonoGame and Xamarin.Android. Believe it or not its simpler than you think to get started.

First thing you need is a class to handle the Camera. Google has done a nice job at giving you a very basic sample of a ‘CameraVew’ here. For those of you not wishing to port that over to C# from Java (yuk) here is the code


public class CameraView : SurfaceView, ISurfaceHolderCallback {
        Camera camera;

        public CameraView (Context context, Camera camera) : base(context)
        {
                this.camera = camera;
		Holder.AddCallback(this);
		// deprecated setting, but required on 
                // Android versions prior to 3.0
		Holder.SetType(SurfaceType.PushBuffers);
	}

	public void SurfaceChanged (ISurfaceHolder holder, Android.Graphics.Format format, int width, int height)
	{
		if (Holder.Surface == null){
			// preview surface does not exist
			return;
		}

		try {
			camera.StopPreview();
		} catch (Exception e){
		}
		try {
			camera.SetPreviewDisplay(Holder);
			camera.StartPreview();
		} catch (Exception e){
			Android.Util.Log.Debug ("CameraView", e.ToString ());
		}
	}

	public void SurfaceCreated (ISurfaceHolder holder)
	{
		try {
			camera.SetPreviewDisplay(holder);
			camera.StartPreview();
		} catch (Exception e) {
			Android.Util.Log.Debug ("CameraView", e.ToString ());
		}
	}

	public void SurfaceDestroyed (ISurfaceHolder holder)
	{
	}
}

It might not be pretty but it does the job, also it doesn’t handle a flipped view so that will need to be added.

The next step is to figure out how to show MonoGame’s GameWindow and the Camera View at the same time. Again, that is quite easy we can use a FrameLayout like so.


protected override void OnCreate (Bundle bundle)
{
	base.OnCreate (bundle);
	Game1.Activity = this;
	var g = new Game1 ();
	FrameLayout frameLayout = new FrameLayout(this);
	frameLayout.AddView (g.Window);  
	try {
		camera = Camera.Open ();
		cameraView = new CameraView (this, camera);
		frameLayout.AddView (cameraView);
	} catch (Exception e) {
		// oops no camera
		Android.Util.Log.Debug ("CameraView", e.ToString ());
	}
	SetContentView (frameLayout);
	g.Run ();
}

This is almost the same as the normal MonoGame android code you get, but instead of just setting the ContentView to the game Window directly we just add that and the CameraView to a frame layout and add that. Note that the order is important, the last item will be on the bottom so we want to add the game view first so it is over the top of the camera.

Now this won’t work out of the box because there are a couple of other small changes we need. First we need to set the SurfaceFormat of the game Window to Rgba8888, this is because it defaults to a format which does not contain an alpha channel. So if we leave it as is we will not see the camera view underneath the game windows since its opaque. We can change the surface format using

g.Window.SurfaceFormat = Android.Graphics.Format.Rgba8888;

We need to do that BEFORE we add that to the frameLayout though. Another thing to note not all devices support Rgba8888, not sure what you do in that case…

The next thing is we need to change our normal Clear colour in Game1 from the standard Color.CornflowerBlue to Color.Transparent

graphics.GraphicsDevice.Clear (Color.Transparent);

With those changes you should be done. Here is a screenshot, note the Xamarin logo in the top left this is drawn using a standard SpriteBatch call 🙂 All the code for this project is available here. I’ve not implemented the iOS version yet as I’m not an “iOS Guy” really, but I will accept pull requests 🙂
Screenshot_2014-11-19-05-40-53

Some of you might have heard that MonoGame now has its own content pipeline tooling, and it works! As a result the need to install the XNA 4.0 SDK is no longer required, unless you want to target Xbox 360 of course.  For those of you looking for documentation on the new tooling you can head over to here for information on the Pipeline GUI and here for information on the MGCB tool. But I’ll give you a basic overview on how this all hangs together.

MGCB.exe

This is a command line tool used to create .xnb files. It works on Windows and Mac (and Linux for some content AFAIK). On windows at the time of writing you will need to download the latest unstable release from here to install the tooling. It installs the tools to

c:\Program Files (x86)\MSBuild\MonoGame\Tools

On a Mac  you will need to get the source and compile this tool yourself. I am working on an add-in for Xamarin Studio which will install this tool for you, if I can figure out how to do it I’ll also knock up a .pkg file to install the tooling in the Applications folder too.

Using the tool is very simple you can either pass all your parameters on the command line  like so

MGCB.exe /outputDir:bin/foo/$(Platform) /intermediateDir:obj/foo/($Platform) /rebuild /platform:iOS /build:Textures\wood.png

Note for Mac users you will need to prefix your command with  ‘mono’.

The other option is to create a .mgcb response file which contains all the required commands.

Now a .mgcb file has some distinct advantages. Firstly its compatible with the Pipeline GUI tooling, secondly it allows you do process a bunch of files at once and still have a nice readable file rather than a HUGE command line. Here is a sample .mgcb file

# Directories
/outputDir:bin/foo/$(Platform) 
/intermediateDir:obj/foo/$(Platform) 

/rebuild

# Build a texture
/importer:TextureImporter
/processor:TextureProcessor
/processorParam:ColorKeyEnabled=false
/build:Textures\wood.png
/build:Textures\metal.png
/build:Textures\plastic.png

You can pass this to MGCB using

MGCB /platform:Android /@:MyFile.mgcb

This will process the file and build your content, again on a Mac prefix the command with ‘mono’

Note that in in both cases I passed the /platform parameter and used the $(Platform) macro’s in the command line and the response file. This allows me to produce different content per platform. A good example of this is with textures, to get the most out of the iOS platform its best to produce PVRTC compressed textures. MGCB knows which texture compression works best on each platform and will optimise your content accordingly, as a result an .xnb build for iOS won’t work on Android. Well it might but only if the GPU on the device supports that texture compression. In reality its best to compile your content for each platform, that said for desktop platforms (Windows, Linux, Mac) you can get away with using the same content as most GPU’s on desktop PC’s/Mac support DXT texture compression.

Those of you familiar with XNA will have noticed familiar ‘processorParam’ values in the sample response file above. The great news is that all the various processor parameters on the various processors you had in XNA are also available in MonoGame.

Pipeline.exe

This tool is just a GUI over the top of MGCB.exe, currently its only available on windows, but it is being ported to Mac and Linux. When you create a new project file it creates an .mgcb file which to totally compatible with the response file mentioned earlier. So you can hand edit it, or use the tooling its up to you. The Pipeline tool is in the early stages of development but its already useful enough to allow you to replace the existing XNA content projects.

I’m not going to go into the details of how to use the Pipeline tool as it’s covered pretty well in the documentation. Like the MGCB tool it is included in the latest unstable installers and can be found in

c:\Program Files (x86)\MSBuild\MonoGame\Tools

It was a conscious decision on the team’s part NOT to go down a tightly integrated MSBuild style solution for content processing. At the end of the day a stand alone console app gives the developer allot of flexibility on how they want to integrate content processing into there own build processes (some of you might just want to use Nant, ruby, make or some other build scripting tooling). That said there are some .targets files available for those of you who wish to make use of msbuild.

That said, the other nice thing is the Pipeline GUI tool has an import function (on windows) to import and existing XNA .contentproj file into a .mgcb file. So if you want to upgrade your existing projects to use the new tooling there is an easy route.

Custom Content Processors

Now one of the fantastic things about the XNA content pipeline was the ability to extend it. The great news is that MonoGame supports that too, in fact the changes are if you have an existing XNA custom content processor (or importer) if you rebuild it against the MonoGame content pipeline assembles which are installed as part of the installer it should “just work”. At some point I’m sure templates for both Visual Studio and Xamarin Studio will be available for those of you wanting to create your own processors.

Things to remember

It is worth remembering that all of the work done on MonoGame is done in spare time and for free! So if there is a feature that doesn’t work or hasn’t been completed yet please remember that people work on this project because they love doing it they also have day jobs , families and other commitments.

One good example of this is the content processing on a Mac (and Linux), for the most part it will work for Textures, Models, Fonts and Audio (mostly) it will work fine, but there is no installer. Also shaders will NOT work, this is mainly because HLSL is just not supported on a Mac (On a side note the team are abut to embark on a project to support GLSL in the .fx file format which will allow users on a Mac to write their shaders using GLSL but at the time of writing if you use custom shaders you will need to compile those on a windows box).

People might be tempted to start complaining about how ‘it doesn’t work on a Mac or Linux’ and yes the support for those platforms is lagging behind the windows support (mostly due to a lack of contributors on those platforms). But we are working on it so please be patient and if its a feature you really really really want and no one seems to be working on it please feel free to ‘go fork and contribute’, just let the team know what you are up to so two people don’t end up working on the same thing.