Axiom, XNA and RenderToTexture

So I learned something interesting about XNA. In Axiom, you can setup your entire scene before entering the renderloop. This way there isn’t any hiccups while rendering due to loading textures, models etc. In addition to Models and textures you can also setup additional render targets. These can be used for reflection planes, shadows, dynamic textures and what have you.

Well this all works really well in DirectX and OpenGL. I can setup a (DX) Surface and hold that until I’m ready to render to it. In XNA however, there is a distinction between a Texture and a RenderTarget. You can only set RenderTargets on the device, and once your done rendering, you can take it off the device and get the result using GetTexture().

This is how the original RenderToTexture (RTT) was implemented in XNA. However, GetTexture() is slow and calling it each frame caused a significant reduction in the number of frames per second. I threw in a quick optimization that only grabbed the Texture2D using GetTexture() once, to see if the reference was still valid between frames. My intuition was correct, the Texture2D that gets returned by GetTexture() isn’t recreated for each frame and I was able to get a 10% increase in my framerate.

To make the code even nicer, I decided that I should grab the Texture2D as early as possible, right after I new up the RenderTarget.

XFG.RenderTarget2D _renderTarget = new XFG.RenderTarget2D(_device, SrcWidth, SrcHeight, numMips, xnaPixelFormat);
XFG.Texture2D _normTexture = _renderTarget.GetTexture();

Bad Idea.

Now when calling GetTexture() I am getting a error that states I can’t call GetTexture() while the RenderTarget is still set on the device. ”But I haven’t set you on the device yet”, I screamed in frustration. After a little fiddling and discussion on the #xna IRC channel, which was more on why I needed what I needed than actually solving the problem, I found my solution.

XFG.RenderTarget2D _renderTarget = new XFG.RenderTarget2D(_device, SrcWidth, SrcHeight, numMips, xnaPixelFormat);

XFG.RenderTarget2D _oldTarget = _device.GetRenderTarget( 0 );
_device.SetRenderTarget( 0, _renderTarget );
_device.SetRenderTarget( 0, _oldTarget );
Texture2D _normTexture = _renderTarget.GetTexture();

The error I was getting was a very good description of what was happening. XNA it seams does not create the Texture2D returned by GetTexture() until after it has been set on the device at least once. After that GetTexture() will return a valid Texture2D as long as it is no longer set on the device.

There are two things to remember from this, one, GetTexture() is slow, keep a reference to the Texture instead, and GetTexture() isn’t valid until the RenderTarget has been on the device at least once.

Creating .Net Configuration Sections

A while ago, I removed the configuration handling that was embedded in the Axiom core. I firmly believe that how the configuration information is stored should be the decision of the Application Developer not the library. I kept the format and just moved the relevant classes into the Demos. That particular implementation relied on a custom Typed DataSet and really didn’t fit with the whole .Net configuration patterns. So I decided it was time to look into creating a custom configuration section for the App.config as an example of a good practice for storing engine configuration.

It’s been a long time since I last had to create a custom configuration section for a .Net application. The last time I looked at it was pre .Net 2.0. At that time you would create a class that implemented IConfigurationSectionHandler. Since .Net 2.0 there has been a change to now use ConfigurationSection or ConfigurationSectionGroup to derive from to create your configuration sections.

After spending roughly 6 hours implementing a simple custom configuration section handler, I had a working class. All it did was specify the log file so I could configure the Root object in Axiom, but it was working. The next step was to figure out how to build a set of elements to store ResourceLocations, RenderSystem Options and Plugins. And this is where I found out that build custom Configuration Sections was hard.

While researching the net for something, I came across a StackOverflow post that was fairly relevant ( I’m finding more of these are showing up higher in Google’s page ranks ). One of the followups to the post, was someone asking ‘why would you bother trying to code custom configuration sections by hand anymore, check out the Configuration Section Designer’. I cocked my head a little to the left and clicked the link to see if it was worth it.

  • Read the home page – 2 minutes
  • Download and Install – 5 minutes
  • Use the Designer to create section – 30 minutes

image

  • Not having to code that by hand – Priceless

I am not going to go into any detail on how to create these sections using the CSD, it really was very easy and intuitive to use. I only had about 5 minutes worth of pain as I figured out which properties are required, for the various elements. So the next time you want to create a custom configuration section, head on over to http://csd.codeplex.com and download the Configuration Section Designer and save yourself countless hours of coding and debugging.

Enumerations, structs and Extension Methods

I happened to come across a situation where I needed an Enumeration but the enumeration needed to provide more than just a int value. In my situation, I not only had a integer value that was tied to the database, but I also needed to display an image for each individual value. I wanted to maintain a .Net-ish look and feel to the code, so I started by writing a few tests based on an existing enumeration. First the enum :

public enum StatusIndicator : int
{
    Ready = 1,
    Paused = 2,
    Offline = 3
}

And the tests :

[TestMethod]
public void GetPausedId()
{
    int expected = 2;
    int actual = (int)StatusIndicator.Paused;

    Assert.AreEqual( expected, actual );
}


[TestMethod]
public void GetPausedUrl()
{
    string expected = "status.paused.jpg";
    string actual = StatusIndicator.Paused.Image;

    Assert.AreEqual( expected, actual );
}

So obviously at this point the GetPausedImage() test fails because the enumeration doesn’t have a member named Image. The easiest way to do this on an existing enumeration without breaking any existing code is to use a static class and Extension Methods.

static class StatusIndicatorHelper
{
    private static readonly Dictionary<StatusIndicator, string> _image;

    static StatusIndicatorHelper()
    {
        _image = new Dictionary<StatusIndicator, string>();
        _image.Add( StatusIndicator.Ready, "status.ready.jpg" );
        _image.Add( StatusIndicator.Paused, "status.paused.jpg" );
        _image.Add( StatusIndicator.Offline, "status.offline.jpg" );
    }

    public static string Image( this StatusIndicator value)
    {
        return _image[ value ];
    }
}

However, even with this code, that test fails. It’s expecting Image as a Property, not a Method. Unfortunately, we can only create Extension Methods, not Extension Properties, so I ended up having to modify the test to use a method. This works, but maintenance looks like it could be disastrous.  If I add a new enumeration value, I have to add a line of initialization code to create a mapping between the value and it’s image. If I add a new attribute tot he enumeration, I have to add the container, it’s initialization code, and an extension method to get the attribute value for the enumeration.

Can this be made any better with Attributes? Let’s take a look at how I implemented it.

enum StatusIndicator
{
    [StatusIndicatorAttribute( "status.ready.jpg" )]
    Ready = 1,
    [StatusIndicatorAttribute( "status.paused.jpg" )]
    Paused = 2,
    [StatusIndicatorAttribute( "status.offline.jpg" )]
    Offline = 3
}

[AttributeUsage( AttributeTargets.Field, AllowMultiple = true )]
class StatusIndicatorAttribute : Attribute
{
    public StatusIndicatorAttribute( string image ) { this.Image = image; }
    public string Image { get; set; }

    public static StatusIndicatorAttribute Values( StatusIndicator value )
    {
        // get the list of fields in the enum
        FieldInfo field = typeof( StatusIndicator ).GetField( value.ToString() );
        object[] atts = field.GetCustomAttributes( typeof( StatusIndicatorAttribute ), false );

         // if we found 1, take a look at it
        if ( atts.Length > 0 )
        {
            // convert the first element to the right type (assume there is only 1 attribute)
            return (StatusIndicatorAttribute)atts[ 0 ];
        }

        return null;
    }
}

static class StatusIndicatorHelper
{
    public static string Image( this StatusIndicator value )
    {
        return StatusIndicatorAttribute.Values( value ).Image;
    }
}

This required modifying the enumeration, but in a non-breaking way. I also had to add two new classes, one for the attribute and another for the Extension Method helpers. The test code from the first implementation didn’t have to change at all, which is good. So how does this compare for maintenance? If I need to add a new enumeration value, I can just add the value into the enumeration and it’s associated attribute, usually a quick Copy+Paste+Modify operation. To add a new attribute, I would have to add a new Property to the StatusIndicatorAttribute class, and modify the constructor to accept the new attribute. Then I would have to add a new Extension Method to the StatusIndicatorHelper class to return the new attribute. Lastly, add the new attribute values onto existing enumeration values. A second way to add an attribute is a little more bloated, and that is implemented using a new Attribute class. I don’t recommend it as it causes code bloat in the Values() static method being in every new Attribute class.

This method caused me some concern due to the Reflection involved in getting the attribute value. This could be mitigated by caching the value in the Values() static method after retrieving it the first time, thereby reducing the Reflection calls to one per enumeration value. You could also control the timing of the reflection by using a static constructor to iterate over all the fields in the enumeration and cache the Attributes at that time.

The last implementation I came up with had the least .Net feel to it, in the implementation, but fit the requirements perfectly.

[Edit: 06/17/2009 - As Steve points out in the comments, this is the java type safe enumeration pattern. I didn't really 'come up' with this as much as I stumbled upon it. I also added the private constructor as I had missed that. ]

struct StatusIndicator
{
    public static readonly StatusIndicator Ready    = new StatusIndicator { Id = 1, Image = "status.ready.jpg" };
    public static readonly StatusIndicator Paused   = new StatusIndicator { Id = 2, Image = "status.paused.jpg" };
    public static readonly StatusIndicator Offline  = new StatusIndicator { Id = 3, Image = "status.offline.jpg" };

    #region Enumeration Implementation

    private StatusIndicator() { }

    public int Id { get; set; }
    public string Image { get; set; }

    public static explicit operator int( StatusIndicator value )
    {
        return value.Id;
    }

    #endregion Enumeration Implementation
}

In this implementation I am not using an enum at all. It has been replaced with a struct. In order to get the struct to act like an enum, I added an explicit conversion operator which return the Id property of the struct. This allows the GetPausedId() test to pass. In fact, the explicit type conversion in the test isn’t needed, the operator int() can be made implicit, but I felt that it was better to maintain compatibility rather than change behavior at this point.

Since this is a struct, I can add as many properties as I need. And it’s a simple process to add a new value to the enumeration.

After putting this all together, I am torn between the last two implementations. I like the .Net feel to the Attribute based implementation, but for high performance applications the reflection bothers me. However, for the struct based implementation, I like the improved maintenance story and lack of reflection, however the fact that is no longer a true enum is a little un-.Net like.

Microsoft DreamSpark now available for High Schools!

Are you a high school student? Do you like to play games on your XBox 360? How would you like to be able to create games for your XBox 360? Now you can.

At the Government Leaders Summit today, Microsoft announced that they are extending the Microsoft DreamSpark program to high school students and teachers. This program was previously available to college students and instructors.

As part of the program, students get access to Microsoft software that they may not have been able to. In the case of gaming, XNA Game Studio is an extension of Visual Studio 2008 Express ( and other editions ) and these have always been freely downloadable. But in order to deploy your games to the XBox 360 you need a Creators Club membership. As part of the program you’ll get a 12-month standard Creators Club membership so you can play your creations on your XBox. Below is an excerpt from the DreamSpark website:

XNA Creators Club 12-Month Student Trial Membership coupled with XNA Game Studio 3.0, opens up video game development to untapped creative minds, enabling students to build and play their amazing games on Xbox 360 systems. The access key below grants access to a 12-month trial membership that provides aspiring game developers the ability to develop games for their Xbox 360 without having to pay the $100 yearly membership (minimum Xbox LIVE silver membership required to deploy your games on your Xbox 360). However, this membership will not give you access to premium content or the ability to submit your games to Xbox LIVE Community Games.

Check out the FAQ (https://www.dreamspark.com/FAQ/HighSchoolAdministratorFaq.aspx) for more information and pass this information along to any high school administrators you know.

MOSS Solutions and Features in Deployments ( Part 3 )

In Parts 1 and 2 of this series we covered some of the pitfalls and precautions the need to be taken when deploying SharePoint artifacts such as Site Columns, and Content Types. Wrapping up these posts we will discuss how to deploy Page Layouts successfully. And just so that we are still on the same page, these posts are focused on deploying using the SharePoint Solution deployments not creating these artifacts using SharePoint Designer or the Web Interface.

Page Layouts

Page Layouts are a great way of reusing structure within your sites. My typical development pattern is to create a layout in a development environment using the web interface, the open it up in SharePoint Designer to polish it up.

The main reason I go about it this way is that using SPD to design a layout is just so easy. Think of it in the same vein as what Visual Studio does for regular ASP.NET applications. The astute reader may have noticed that in previous posts I have cautioned against the use of SPD. This is true, but that is always tempered with 'with caution'. Knowing what using SharePoint designer means can make all the difference. Additionally, I only use it against my development farm, no where else.

image Once I have gotten the layout to a state that I am happy with, I copy the contents using the code view of SPD, paste it into a file in Visual Studio. From there I can add it to my Feature and have it deployed properly. I then reghost the file. Remember that SPD is going to unghost (customize) the file and any attempt to update it using a feature will fail miserably.

Here's your first tip: It appears that some engineer, and I use this term loosely, decided that when you deploy a file to SharePoint, the determination of it being a Page Layout is the presence of a tag with the name 'Content'. Not 'content', or 'conTent', just 'Content'. Would you care to guess what capitalization SPD uses by default for content section in page layouts? Yep, you guessed it 'content' I'm shipping a case of wet trout to the MS campus as you read this, let the slapping begin. And it gets even worse, you have to have all the <asp:Content /> controls use the proper case.

The fallout of this is that if you deploy a file without a 'Content' tag SharePoint determines that this is just a plain old HTML file, however it does some additional inspection and doesn't find an HTML tag, so it kindly inserts one for you. Isn't that sweet? I'm not smiling. This causes your layout file to be customized and and future upgrades will appear to not work even though the file in the 12 Hive is correct. Here is the offending code that you will find at the end of you page layout if you view it in SPD.

<html xmlns:mso="urn:schemas-microsoft-com:office:office"xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"><head>
<META name="WebPartPageExpansion" content="full">
<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:PublishingPreviewImage msdt:dt="string"></mso:PublishingPreviewImage>
<mso:ContentType msdt:dt="string">Page Layout</mso:ContentType>
<mso:MasterPageDescription msdt:dt="string"></mso:MasterPageDescription>
<mso:PublishingAssociatedVariations msdt:dt="string"></mso:PublishingAssociatedVariations>
<mso:PublishingHidden msdt:dt="string">0</mso:PublishingHidden>
<mso:PublishingAssociatedContentType msdt:dt="string">;#Agenda item;#0x010100C568DB52D...;#</mso:PublishingAssociatedContentType>
</mso:CustomDocumentProperties>
</xml><![endif]-->
<title>Dummy Content Type</title></head>

Fortunately this can be easily corrected, if you've already been bit by it. You’ll know this is the problem, because when you go to load a page based on that layout, you’ll receive this error:

Only Content controls are allowed directly in a content page that contains Content controls.

First do a Find/Replace on your Page Layouts and make all of the asp:content tag asp:Content. Next using the STSADM Extensions from Gary Lapointe, uncustomize the file with the gl-reghostfile operation.

image
This operation uses the RevertContentStream() method of the SPFile class. Now when you upgrade your solution the updated layouts will be used.

Axiom 0.7.5.0 Beta 1

Today I released the first Beta of the next version of Axiom. Axiom is a C# 3D rendering engine. This year marks the 6th year of it’s existence. I have been maintaining it for the past 3 years. I am particularly excited about this release because for the first time we are shipping some brand new features.

XNA Renderer

The largest feature that was added for 0.7.5.0 was the XNA Renderer. It has been in development for the past year. A large hurdle for the XNA renderer was the absence of any fixed function pipeline support. Only vertex and pixel shaders can be used. Since Axiom is old enough to still support the fixed function pipeline, it needed a way to provide that functionality using a shader. The result of this is the FixedFunctionEmulation layer. It will take the fixed function state of the engine aand generate a set of shaders on the fly. This will unfortunately only work with XNA on the windows platform as the XBox does not allow compilation of shaders at runtime. In this release the only Axiom functionality not supported is shadows. The plan is to have shader based shadows by the time this version is final.

The windows support of XNA in this release is much richer than the XBox. Axiom includes a custom pipeline component to load textures instead of using the native library DevIL. DevIL works wonderfully on the Windows platform, however native code cannot be used in XNA projects on the XBox. Rather than port the library over, I leveraged the XNA Content Pipeline to load the textures into the standard resource system. Additionally, the XNA Content Pipeline was used to precompile HLSL files into VertexShaders and PixelShaders for the XBox. Version 3 of XNA only supports FX files by default. Since Axiom has it’s own Material System, I don’t need FX files. I plan to add FX file support in a future release.

Once the final is released I am really hoping to see someone create a game using Axiom and publish it on the Community Games for XBox Live. That would be just awesome.

Project Files

Another big change for this release is in the build system. Previously I did not keep the project files in source control or ship them. Instead Prebuild was used to generate them specifically for your environment. This worked generally, and was necessary because SharpDevelop, Monodevelop and Visual Studio all supported different project file formats. As of MonoDevelop 1.0, SharpDevelop 2.2 and Visual Studio 2008, they now all support the 2008 version of the project file format. This means that now all project files are in the source control repository and shipped as part of the distribution. This should make it easier for newer users to get started with Axiom.

Additionally this will mean adoption of metabuild as the project build system, replacing the custom nAnt build scripts currently in use. The only roadblock for metabuild is Mono’s support for MSBuild scripts. Mono’s implementation of MSBuild, called xbuild, is still fairly immature, however I am testing it out with the Axiom projects to see how well it works.

The obligatory screenshots

Below you will find a few of my favorite demo screenshots. These are all running on windows using the XNA Renderer. Not bad for a managed engine.

RenderToTesture EnvironmentMapping ParticleFX SkeletalAnimation

What’s next?

After this version is complete and final, I already have another set of features hot on it’s tail. There is a post processing framework ( Blur, HDR ), better material handling, better window management, background loading of resources, an overhaul of the OpenGL Renderer and much much more.

call to action

Please, in order for Axiom to be the best it can be, I need some assistance in making sure the new features do what they are supposed to. More importantly, do what you need them to do. So go download Axiom today and kick it’s tires, file bug reports, and send me feedback.

Cross platform assembly merging

A common problem I have with users of Axiom is that they will mismatch the assemblies need to get the engine up and running. Axiom uses a plugin system that allows for interchanging the platform in use (Win32, SDL, etc ) and which graphics system to use ( XNA, OpenGL, DirectX ). Unfortunately, there isn’t as loose coupling as I’d like, in particular the OpenGL rendering system has to be recompiled to use S.W.F forms or SDL forms. SLD is the particularly nasty one because it has to be paired with the SDL platform manager.

A few months ago I ran across the ILMerge utility and thought that it would solve some problems. I could combine the main engine with the proper combinations of a platform manger and render system there by eliminating the mismatch. I didn’t investigate it much because a quick try just created errors. More recently a request came up on the forums to be able to do this exact thing. I took a few hours and made it so that users could use ILMerge on the assemblies and have the system behave properly. However I didn’t make the assemblies myself, as I wasn’t preparing for a release.

Fast forward to this week. I should have released a beta of Axiom 0.7.5 back in January, but because things were a bit crazy I didn’t get to it until this week. With this release I wanted to be able to ship these combined assemblies. I like to automate things so I found an implementation of some MSBuild tasks that use ILMerge to produce a single assembly.

Now this week I had also been testing Mono’s xbuild, which is an implementation of MSBuild but on mono. Knowing that I have a large percentage of my users are linux based I investigated the ability of ILMerge to run on Mono. It doesn’t.

Ok, back to the drawing board. After a quick search I found MonoMerge. I tested it out a little to see if it worked, as it didn’t have as many options as ILMerge. It seemed to do the rick.

Now I needed a MSBuild task to execute MonoMerge. Using the ILMerge task as a guide I quickly put together a new MSBuild task that can now merge assemblies on Mono and .Net.

Enjoy!

UPDATE : Added hyperlinks to various resources.

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Mono.Cecil;
using Mono.Merge;

namespace Mathoms.MSBuild.Tasks
{
    public class MonoMerge : Task 
    {
        private string _outputFile;
        private ITaskItem[] _assemblies = new ITaskItem[0];

        [Required]
        public virtual string OutputFile
        {
            get { return _outputFile; }
            set { _outputFile = System.IO.Path.Combine(BuildEngine.ProjectFileOfTaskNode,value); }
        }

        [Required]
        public virtual ITaskItem[] InputAssemblies
        {
            get { return _assemblies; }
            set { _assemblies = value; }
        }


        public override bool Execute()
        {
            var context = new MergeContext {OutputPath = _outputFile};

            var assemblies = new string[ _assemblies.Length];
            for( var i = 0; i < assemblies.Length; i++ )
            {
                assemblies[ i ] = _assemblies[ i ].ToString();
            }

            context.Assemblies.AddRange( assemblies );

            try
            {
                var primary = AssemblyFactory.GetAssembly( context.Assemblies[ 0 ] );

                for ( int i = 1; i < context.Assemblies.Count; i++ )
                {
                    var asm = AssemblyFactory.GetAssembly( context.Assemblies[ i ] );
                    asm.Accept( new StructureMerger( context, primary, asm ) );
                }

                var fix = new FixReflectionAfterMerge( context, primary, primary );
                fix.Process();

                AssemblyFactory.SaveAssembly( primary, context.OutputPath );

            }
            catch (Exception e)
            {
                Log.LogErrorFromException(e);
                return false;
            }

            return true;
        }
    }
}

Oslo : First Impressions

Oslo is a platform of technologies designed to help us create model driven applications. Currently Oslo is composed of 3 components; A language , a tool, and a database.

Red Dog : Windows Azure and the Azure Services Platform

Microsoft announced at PDC 2008 yesterday that the project they have been working on for cloud computing called Red Dog has a final name as Azure (ăzh'ər). At a dinner function last night there was some debate on the proper pronunciation of the word, but it's origins are pretty clear. It comes from the Persian, for the location of the Lapis Lazuli.

Together @ PDC2008

So I am at the PDC this year with the Together @ PDC2008 program from Microsoft. This allows various people to go to the PDC with Microsoft Employees. This year I am buddied up with Chris Bowen, my Regional Developer Evangelist.