Wednesday, May 15, 2013

Broken FBX animations with XNA importer (FIX)

We successfully replaced XNA in our engine and we are excited by performance speedup and count of bugs we finally fixed with this step. SharpDX is really great library.

The last piece of code where we still use XNA is our content processor pipeline. There is no satisfying replacement for FBX import, although some appears to be already on the way (https://github.com/assimp/assimp)

As it is a good tradition in XNA, there is a couple of bugs. And as it is a good tradition in Microsoft, nobody cares. This time we bumped into annoying bug with importing animations from FBX file. This is done through XNA FBXImporter class, which is built over FBX SDK from 2009. Hard to say if bug is caused by Autodesk's SDK, or Microsoft importer implementation, but importer always fails to import animation from first node in hiearchy. Really shame that Microsoft haven't published XNA source code, rebuild of FBX importer with latest FBX SDK and fix of this issue would be a few minutes task.

My idea is that Autodesk made a little mess with his "imaginary" FBX root node in its SDK, which is created on the fly and has nothing similar with FBX file content, only keeps root nodes from the file as children. FBX importer decided to not import "first" node, because that is anyway just fake, and always skips it. But unfortunatelly, there is a bug somewhere and importer skips valid node.

We had a hard times to even find out what's going on, and also finding a solution to this problem. Luckily, there is a workaround which works, at least for us, and you have to pray to be working also for you. Or you will be more lucky and in the time you are reading this article, there will be complete implementation of Assimp .NET importer for FBX.

So what to do with your animation to be correctly imported with XNA FBX importer? You always have to add fake root node to this animation. It can be achieved by Dummy object in 3DS Max.


Put Dummy into scene with your animation. Next step is to set Dummy transformation exactly same, as it is at first bone/node at first key. You can do this by using Select by name and Transform Type-In dialogs (they appears after right clicking on Select and Move or Rotate and Move tool buttons.


Note that dummy can be inserted as "Freezed", so you have to unfreeze it in the first time.

After the Dummy has correct transformation, you have to set it up as a parent of your animation. Do this in schematic view.


Correct hierarchy should appear like this:


With dummy parent, FBX importer skips our "dummy" and correctly process all underlying animations. Voila!

Saturday, January 5, 2013

Is .NET and XNA mature enough for AAA game?

On 28th November we finally released our main title MinerWars 2081, the most technically and visually precised game written entirelly in .NET and XNA. What is our experience with these technologies and how they helped us? I will conclude everything in this post mortem article.



Why .NET + XNA?


First versions of the game were written by Marek Rosa as technological demos of destructible environments, and were written in C++ and OpenGL. After great public reception Marek decided to use this technology to create commercial game, and that's how MinerWars idea was created. In that time, three years ago, there was no suitable engines available, like CryEngine or UDK today (regarding to our requirements, price, development effectivity and dynamic environment support). It was time when Unity was in beginning and its quality was just not enough for MinerWars. To choose between quality and development effectivity, Marek finally picked XNA and .NET as his main technology. It was the best possible solution in the time, and was heavily supported by Microsoft marketing, where XNA was presented as future game platform.



My participation


The game development with .NET and XNA lasted for two years, there were involved 1-7 tech programmers, and up to 6 scripters using C# for scripting too. Most time I worked as Lead programmer (render, lighting, object management, game logic), also I was responsible for application architecture and design, writing and authorizing prototypes, but also hiring new programmers, managing their work and checking the code quality after them. With all these experience I will try to conlude my thoughts about .NET and XNA, even Microsoft and other related products. All these are my personal opinions made during the time, and I am willing to change them if anyone is willing to persuade me :)


Pros of commercial game development in XNA and .NET


Let's begin with better things. .NET and even XNA surely have their pros in game development. It should be mentoied that in beginning, our idea was to create game for both PC and XBOX360 platforms, later appeared, that XBOX will be harder nut that Microsoft presents. Because of this, only PC related issues are listed here.

- Effectivity

With managed environment, C# language and XNA, development of the game is going really fast. Development of small game (2D arcade, 3D chess..) can be finished in weeks. Many solutions in XNA are already premade and ready for use. Just find it, know it, and use it.

- Managed code debugging

Debugging variables, code flow or crashes is usually very straightforward and user-friendly. Together with some other anti-bug solution (unit tests, buddy checking, auto-builds/runs) it is possible to generate very low bugged code.

- Memory safety

No more access violation or reading corrupted memory. Only (big) problem which remains are memory leaks.

- Tutorials and samples

There is many tutorials and samples for XNA (2-4.0) and for .NET. You can find basic and advanced solutions on servers like http://stackoverflow.com/, http://xboxforums.create.msdn.com/forums/, or just reading articles from Shawn Hargreaves.


Cons of commercial game development in XNA and .NET


- Microsoft support

It's dead. Microsoft stopped development of XNA for PC platform and day from day they stopped all official support. They are not fixing bugs, they are not releasing new versions. Very "fair" to many people stuck on this technology (and sad for companies which built their engines on XNA).


- Performance

In the past, Microsoft presented .NET great performance on running Quake 2 in managed code. It was year 2003 and nowadays, this kind of games is able to run even on mobile platforms. .NET performance is highly inadequate to run engines with same quality and features similar to CryEngine etc. The sad truth is that if Microsoft continues .NET and XNA development, it could be different. Why is it not possible to compare managed XNA engine to C++ native engines?

  1. Compiler - C# compiler optimizations are very naive comparing to C++ optimizations. Compiler is using slow virtual calls in all non static cases. The difference between Debug and Release performance is minimal.
  2. Inlines - It is not possible tell the compiler which method to inline and which not. It depends on internal logic which chooses inlining rarely.
  3. Garbage collector - there is no possibility how to alter its behavior, how to access/profile allocations in realtime, how to disable/change allocator or write custom one (plus it is not recommended at all).  
  4. Allocations all around - altough best practice to write performance applications (game) is to avoid any allocation, many C# or XNA methods do allocations and there is no way how to avoid them. You just must not use them. For example - XACT in XNA is full of allocations, lambda functions do allocations, adding/removing event handler, all string (even some preallocated Stringbuilder) operations, accessing dictionary with struct as a key and many more.
  5. SIMD - C# compiler does not use even single one SIMD instruction. That's deadly for vector+matrices calculations, which are used most in games development
  6. XNA is not wrapper - XNA is framework with additional logic, which on many places costs performance. You can see XNA performance here (10x slower against native implementation) http://code4k.blogspot.cz/2011/03/benchmarking-cnet-direct3d-11-apis-vs.html

- XNA Bugs and flaws

  1.  XNA is stucked on DirectX 9 - You can use nothing from nowadays high-end graphics cards. It is not supported on Windows 8.
  2. Device lost - this situation is solved strangely in XNA 4.0 (even when it worked fine in XNA 3.0) and resources are needed to be always reloaded, even when XNA should manage it.
  3. Multi monitor support - some multi monitor configurations are unstable and can cause XNA crash (or end in neverending DeviceLost loop)
  4. Reduced DX9 features - because of compatibility with XBOX 360, XNA developers decided to disable some features in XNA (ie. reading depth buffer, hw. occlusion queries for float buffers, separate depth buffer, optional parameters when creating resources and many more). All these features are fundamental if you want to create high-end rendering engine.
  5. Audio problems - XNA crashes when some disabled audio output is set.

- Out of memory

The problem with memory when developing .NET game is always one - it is always low. If you are out of memory, it is difficult to use any profiler, because it crashes on out of memory too. The only way to debug it is to use SOS commandline tool or use profiler, which is able to access crashed process (http://memprofiler.com/ Proffesional). It is difficult to track all references and keep them clean during the development. Moreover, there can be problems with Large memory heap fragmentation or you can even get out of native process memory.


General conclusion

Altough the game can be developed very fast in .NET and with XNA, there is a big price in performance penalty and memory problems. Fortunatelly, there are some projects now which can reduce this penalty, because they are just wrappers above DirectX. See http://sharpdx.org/ or http://slimdx.org/. Some projects also target to replace XNA, and make its better and faster alternative (http://anxframework.codeplex.com/http://monogame.codeplex.com/)

Because of .NET design and compiler problems, the managed game will be never as fast as native C++ game. But thanks to projects like SharpDX and SlimDX, more effective and more advanced game/engines can be created, still with great development effectivity. And I am looking forward to them.




Friday, November 30, 2012

Castle in VRage 2


Some time ago I posted a blog presenting very simple castle in our voxel engine. And because I like editing and visualisations, I wanted to make something more.. challenging. Today, having a short time after our MinerWars 2081 release, I finished more advanced version of the castle, inspired by famous Germany Neuschwanstein castle.







This video is only presenting features of our in-game voxel editor and VRage engine, castle is not used in the game. But I can imagine more action in this area ;)







How would you like to build your own structures? How would you like to destroy it then? Can you image the game in this environment? ;)

Sunday, September 30, 2012

Castle in VRage

Not only space shooters can be made in our powerful voxel engine VRage. This castle was made in 30mins using our voxel hand tool.




Friday, June 22, 2012

Minecraft as a side-effect

Thanks to our powerful voxel engine we can get sometimes quite unexpected results. While we were testing a new feature, we accidentally developed new Minecraft clone. And it was fun to play :)


Would you like MinerWars craft mode? :)




Friday, June 15, 2012

NextAfter in C# without allocations or unsafe code

In C99, there is a standard way to get the next larger or smaller float32: the function nextafterf. In C#, there’s no such function and I had to roll my own version.
There are three ugly possibilities.
  1. use pointer aliasing,
  2. BitConverter.GetBytes,
  3. simulate an union.
The main update loop may not make any allocations, so BitConverter is out. Pointer aliasing is unsafe, so I couldn’t use it either. So the version I ended up with looks like this:
[StructLayout(LayoutKind.Explicit)]
struct FloatIntUnion
{
    [FieldOffset(0)]
    public int i;
    [FieldOffset(0)]
    public float f;
}

//  Returns the next float after x in the direction of y.
float NextAfter(float x, float y)
{
    if (float.IsNaN(x) || float.IsNaN(y)) return x + y;
    if (x == y) return y;  // nextafter(0, -0) = -0

    FloatIntUnion u;
    u.i = 0; u.f = x;  // shut up the compiler

    if (x == 0)
    {
        u.i = 1;
        return y > 0 ? u.f : -u.f;
    }

    if ((x > 0) == (y > x))
        u.i++;
    else
        u.i--;
    return u.f;
}