Monday, 29 January 2007

AJAX, XNA, WF, WCF, WPF, WTF does that mean?

Hi there!

last thursday took place here the event:

AJAX, XNA, WF, WCF, WPF, WTF does that mean?





Firstly, we had the chance to learn from David Salgado (http://blogs.msdn.com/davidsalgado/) in his charts about ASP.NET AJAX, WCF and WPF. Amazing !!!!



Thanks David!


Later on, I talked about Managed DirectX and XNA, including a demo about Simax project (http://www.simax.es). Hope you enjoyed it.





We also learned about WF from Carlos Segura (Sharepoint MVP, http://www.ideseg.com/). Excellent work too Carlos!



Thanks a lot to navarraDotNet too !













Wednesday, 10 January 2007

Exception is thrown at Device Reset

Hi there,

In order to get no exceptions when resetting the device, due to a resize or to a FullScreen toggle, you must be sure to have freed every single resource of the device, because for each resource, DirectX mantains an internal counter of references. If any of these counters is not 0 at Reset, it throws an exception and the Reset fails.

Well, in order to make sure this counters are all 0:

1.- Every resource must be Disposed in the OnLostDevice() event.
2.- Every resource must be re-created in the OnResetDevice() event.

BUT: there´s a singularity to this procedure regarding the DepthStencilBuffers.

If you handle depth buffers manually (setting the EnableAutoDepthStencil = false), there´s something you have to be careful with.

When an access to the Device.DepthStencilSurface is done, the API actually calls to the native Device->GetStencilSurface() method. If you take a look at the GetStencilSurface() specs in the SDK C++ docs, you will find that this method increments the resource´s internal reference counter. So:

AFTER TO EVERY SINGLE ACCESS TO Device.DepthStencilSurface, YOU MUST DECREMENT THE REFERENCE COUNTER

If you don´t, you will get an exception at Reset. How to decrement the counter? Calling the Dispose() method.

Example:

1.- ACCESS

Surface mySurface = null;try
{
mySurface = device.DepthStencilSurface;
}
catch {}

........... [ DO YOUR STUFF HERE ] ..................

2.- RELEASE

if(mySurface != null)
{
mySurface.Dispose();
}

Tuesday, 9 January 2007

Managed DirectInput weird slowdown

Yesterday, while finishing the last details of my Custom ActionMapping system, I noticed a terrible slowdown in my application. In a demo app I was using, the fps falled from 82 to 9 !!!!

Looking for the problem, I found that it was due to an access to the Device.DeviceInformation property. I decompiled the DirectInput libraries, and I found that each time an access to this struct is done, a New() object of the type DeviceInstance is created (and don´t tell me why, it´s done twice). This seems to be the source of the slowdown.

So, avoid accesing this struct at runtime. Instead, pre-get any values you need for each device, to local structs at creation time.

Cheers !

Friday, 5 January 2007

MDX Custom Action Mapping (Part III)

[Warning: This article is obsolote. I´d suggest you to read the Refreshed version here.]

We continue with the MDX Custom Action Mapping series where we left it. This is, by now, the last part of the tutorial. Hope it helps you...

Bind up the physical object

What do we put in the file to identify the physical object? It´s name? It´s ID? It´s offset?

Any of them would work if we´d only need to recover info about a physical device, as it´s name, properties, etc. You can do that, looping through the collection Device.Objects, and searching by any of that terms. The problem is that we don´t only need that, we need to retrieve data from that object.

Steping back to the previous part, we could think of using Inmediate Mode, and storing in the file the name of the field in JoystickState struct we wanted to map the game action to, regardless of the physical device it´s attached to. That might be a solution, but once we have the JoystickState structure, how do we get the value of a field whose name is stored in a variable? One way to do that is to make an unsafe pointer access to the struct, if you know the address and size of the field you want to retrieve. This is, you know, so C++, that we´ll discard it by now.
There´s a simpler and better way...so don´t use inmediate mode. That´s why ActionMapping does so too, I guess.

Let´s have a look again at buffered mode. Specially to the BufferedData object. The significant difference in this way of retrieving data is the field Offset . This field does really have a meaning! It is the Physical Device Object´s offset, if Im not wrong, and it will serve us as a link between GameActions and the physical devices. So, what we want to store in the file is the PhysicalOffset, like this:

Map Action="Steering Action"
PhysicalDeviceGuid="1820-12820-2147-94579-3426-4575"
PhysicalObjectOffset="138452"

So there´s the link. We choose BufferedMode and go ahead !

Designing the Action class

It´s a good Idea to defina a class like this:

public class Action
{
public eGameAction mGameAction;
public Device mPhysicalDevice;
public int mPhysicalObjectOffset;

public int mLastDataReaded;
}

It will handle the mapping between a GameAction and a Physical Object, and store the last readed value. Then, to handle the whole Action Map, we could define structures like this (optional, make your own for your purposes):

1.- Collections.Generic.Dictionary<> > mActionMap;

This collection has a first dictionary, keyed by the DirectInput Device, and whose value is another dictionary, with all the Actions mapped for that device, keyed by the offset of the object.

2.- Collections.Generic.Dictionary mActions;

This is a plain list of the actions available in the application. Initialized for every eGameAction, regardless it´s mapped to a device or not.

Initializing and Storing the Action Map

The best way to store the action map is an XML file in the user´s ApplicationData special folder. This way, the config will be made for every machine the application is installed.

To save the settings, simplly loop for every device in mActionMap saving it´s Guid, and a list of actions, just as we´ve seen before.

To read the settings, just load the xml file, loop through it´s nodes, and do the following:

1.- Recover a GameAction based on it´s name: Just as we said earlier, use Enum.Parse ( typeof( eGameActions), name);
2.- Recover a device instance by it´s Guid: Just loop throught the Available Devices searching one with the same guid.

The DoSteps method

Once per frame, a DoSteps / OnFrameMove / whatever you like method should be called to update all the data.

foreach( Device dev in this.mActionMap.Keys)
{
dev.Poll()
BufferedDataCollection coll = dev.GetBufferedDate();
if( coll == null )
continue;

Collections.Generic.Dictionary<> deviceActions = this.mActionMap[dev];

foreach ( BufferedData bdata in coll)
{
if( deviceActions.ContainsKey ( bdata.offset) )
{
// Action is mapped. Save it´s value. Axis will report integer (usually 0..65535) and
// buttons will report integer (0 unpressed, 128 pressed)
deviceActions[ bdata.offset ].mLastDataReaded = bdata.data;
}
}
}

User configuration of the Action Map

DirectX Action Mapping has it´s own user interface to configure the mapping. It´s dark, misterious, ugly, unconfortable, strange, a little bit chaotic, and as we are no longer using standard Action Mapping we can no longer use it. So, make your own config dialog, with the appearance you want, and the behaviour you want.

Now, with your custom action mapping, making a new assignment is as easy as changing Action.PhysicalDevice and Action.PhysicalObjectOffset properties.


Listening to a device

Most of the games makes a controller configuration based on "Listen for any device´s object moving". If that happens, object is assigned to game´s action.

In the config dialog, there will be a list of available game actions. When user selects one and press the "Assign" button, the application should stay for a while listening for devices. To do so:

1.- Define a Timer object in your configuration dialog, which is started when the user presses the "Assign" button.
2.- The timer will fire up every 100 ms or so. In the Timer_tick event, do the actual "listening" process:
2.0.- Increment a Time Counter. If it reaches the amount of time for listening, get out.
2.1.- Loop through every device
2.2.- Make device.GetBufferedData ()
2.3.- Assign first retrieved data to selected GameAction

In this algorithm you should also apply a Thresold system, because analog devices are almost always reporting small changes. So keep track of the first values returned in BufferedData for every physical object and when newer values come, calculate the difference between actual and first value. If the difference is bigger than Thresold, make the assignment.

Finally, reading data from the application

Once in your application, you can simple access the mActions collection to get the data. For example:

1.- Reading the Steering game action:

int wheelPosition = this.mInput.mActions[ eGameActions.Steering ].mLastDataReaded;

2.- Reading a button

if ( this.mInput.mActions [ eGameActions.MoveForward ].mLastDataReaded != 0 )
this.WalkForward();


That´s it ! Hope all this stuff helped you !

Feel free to email any questions.

Best regards,

Iñaki Ayucar

MDX Custom Action Mapping (Part II)

[Warning: This article is obsolote. I´d suggest you to read the Refreshed version here.]

Taking the issue where we left it yesterday...

The next step is to make an important choice: Inmediate or Buffered mode? Take into account that DX Action Mapping works in Buffered Mode only. Why? To answer that, let´s describe both modes a little bit:

Inmediate Mode

Take a look at how data is reported under the Inmediate Mode: all you get is a struct of the type JoystickState, MouseState or KeyboardState, which has all the data you need under some default fields, defined by DirectX (like AxisX, AxixY, etc). This fields are always the same, no matter which device you are accesing to. It´s device´s builder (i.e. Logitech) who decides what physical objects are mapped to what DX default fields. An example:

- For a joystick, it´s quite trivial to map it´s objects to fields, because JoystickState was originally designed for that: joysticks (as it´s name states). So, the AxisX field will almost always be mapped to the X-Axis of the joystick.

- What happens for a driving wheel? Ah! that´s different. That´s something DirectInput was not originally designed for, and when this kind of devices came out, instead of adapting DInput for them, DX guys decided to use existing structs to handle new devices. So, there´s no default field in the JoystickState structure for the WheelAxis object. In this way, some device builders will map wheel axis to AxisX, while others will do to the Rx Axis, and so on...

Buffered Mode

Are things different in Buffered Mode? Quite a bit.

In buffered mode, you don´t get access to the whole structure of data. Instead of that, you call the GetBufferedData() method, which retrieves a collection of BufferedData objects, one for each changing object in the device. That means, if the device is absolutely stall, no data will be returned.

One tip: To set the buffered mode, you have to manually change the property:

Device.Properties.BufferSize = 16.


Making the relationship

What we need is a way to save and recover from a file something like this:

Action="Steering Action" PhysicalDevice="Logitech G25" PhysicalObject="Wheel Axis"

What info do we put there? how do we recover it in order to read data fron the device ? Let´s see:

1.- The first attribute is easy, just gameAction.ToString() to save,

and Enum.Parse(typeof(eGameActions), attributeInnerText); to recover from the file.

2.- The second attribute is not hard either. Instead of saving device´s name, we will save device´s Guid:

Write the guid as DeviceGuid.ToString()
and recover it as: DeviceGuid = new Guid( attributeGuidInnerText );

3.- The third attribute.... aaaahhh. This is a little bit more tricky.

more on this later...



Thursday, 4 January 2007

MDX Custom Action Mapping

 

[Warning: This article is obsolote. I´d suggest you to read the Refreshed version here.]

In the last few months I realized that I didn´t have a decent controller configuration system and I started to look at DirectInput´s Action Mapping.

After a couple of weeks working around it, my frustration growed up and I decided to make my own full ActionMapping system (supporting mapping to several devices). Why?

1.- The documentation of Microsoft about AcionMapping sucks (no offense!)

2.- ManagedDirectX version of Action Mapping seems to be incomplete, just like if they wanted to finish asap, regardless what was the final result: undocumented methods, parameters, etc.

3.- Error reports coming out from methods is something just, impossible to understand without good specs. One example: The Acquire() method always throws "Argument Exception". Why? It can be due to a dozen of things.

4.- To push me even forwarder in my willing of comitting suicide, most of the actionMapping samples have been removed from the SDK. As there´s no human able to find old samples in Microsoft´s websites, I had to dive into the pile of old CDs that, thank to the great lord, I haven´t thrown away yet. Hey you gus, why just not putting there a special website with all the DX samples published ever?

5.- Of course, after finding the samples, they are all C++, so you have to bring all your c++ knowledge to life and start studying them.

6.- Even after all this process, I honestly have to say that I couldn´t determine the behaviour of some methods. They seem to be chaotic and I dont understand what happens sometimes. I loose the action map when set the dataFormat and vice-versa.

7.- Another and last (I hope) reason. What´s all that stuff about pre-defined genres, device types and so on... ??? Who decided that? Did you really thought that it was gonna be enough with a bunch of pre-definded genres and types? To be even worse, they are all mixed up in the Managed DirectInput namespaces, with no order. If you don´t know what Im talking about, I´ll say that, in action mapping, you have to assign a Genre (like "driving", "Fighting", "SpaceSimulator", ...) to your ActionMap. Each genre has it´s own Default Actions, and no more. This default actions are what you map your game actions to, and basing on this mapping and on the genre of your Actionmap, methods of DInput may even crash. Goddamn it! And, what happens if you need more actions than the pre-defined? Yes, I know there´s something called "AnyButton", "AnyAxis" and so on... but... I just don´t like it. i.e., now, with the new Logitech G25... it comes with a clutch pedal. There´s no DX Action for the clutch in the Driving Genre. It´s quite clear that DX was designed in U.S ;)

8.- No! it was not the last reason, more coming to my mind. How standard ActionMapping saves and recovers actionMap configurations is something misterious. Actually, it saves a per-application file in ApplicationData\Microsoft\DirectInput special folder with all the settings. DirectInput loads and saves it "behind the scene", and that´s something I don´t like at all. Why not just putting there a "SaveActionMapToFile(), LoadActionMapFromFile()" methods instead ?. I want to be able to decide where the file will be saved and how! In addition to that, while development, it´s behaviour its very unconfortable, because when app´s guid changed, DirectInput generates additional files. You can easily end up with hundreds of config files in that folder if that happens. Microsoft recommends to manually delete the contents of that folder periodically while development. Arrgglll....

9.- More and more reasons... The Acion Mapping configuration dialog. What can I say? It´s almost un-customizable. It´s behaviour is absolutely undocumented. I really think that DirectInput is the ugly brother of DirectX. It does not follow the quality standard present in other parts of the libs.

Anyway... No more time wasted in ActionMapping. I decided to make my own, custom, brighty, magnificent, easy Action Mapping System. This could seem an easy task, but again, just like always I try to make something new with DirectInput, it´s not.

The main task we want to make in our ActionMapping is to be able to save to disk and recover a controller configuration, which assign a InputDevice and an Object of that device to a GameAction defined by us.

As this tutorial is gonna take long, I will divide it into parts.

PART 1: Define game actions

Will put all of our actions in an enumeration.

enum eGameActions
{
MoveForward = 0,
MoveBackward = 1,
TurnLeft = 2,
TurnRight = 3,
Shoot = 4,

NumberOfActions = 5 // Not an action, just to know the number
}

If you don´t know, there´s a very useful class in the .Net Framework called System.Enum. This class has static methods to loop through members of an enumeration and more. Things like:

Enum.GetNames ( typeof (eGameActions) ) : Will return a string[] with: "MoveForward", "MoveBackward" and so on.

Enum.IsDefined( typeof(eGameActions), 6 ): Will return false because eGameActions doesnt have that member.

more coming tomorrow ...

Cheers !

.Net Framework 3.0. DirectX and XNA event.

Hi all,

late this month, a new Microsoft event will take place here in Pamplona. Promoted by navarraDotNet, it will cover .Net Framework 3.0 technologies and more.

"Masters of Techonology" as David Salgado ( http://blogs.msdn.com/davidsalgado/ ) and Carlos Segura (Microsoft MVP, http://www.ideseg.com/ ) will present some parts of the agenda. More people to be confirmed ! (will post here when known). I also will be there talking about DirectX and XNA.

Hope you all come and enjoy it

or not ;) !!

Cheers !


Some info of the event:


Información general del evento

jueves, 25 de enero de 2007 9:30 - jueves, 25 de enero de 2007 15:00 Madrid, París Hora de recepción: 9:00
Universidad Pública de Navarra
Aula Anexo 04. Campus de Arrosadia. Edificio El Sario
Pamplona Navarra 31006

Agenda:
09:30 – 10:30 ASP.NET AJAX Web Development
10:30 – 11:30 Desarrollo de juegos con DirectX / XNA
--------------------------------------
11:45 – 13:15 Desarrollo de la capa de negocio con Windows Communication Foundation y Windows Workflow Foundation
--------------------------------------
13:30 – 14:30 Construcción del cliente rico con Windows Presentation Foundation
14.30 – 15:00 Creando una web pública con Microsoft Office SharePoint Server

Registro en:

http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032322979&culture=es-ES

Managed DirectInput samples bugs. Logitech G25 FF fails to initialize

Recently, I had the chance to test the magnificent Logitech G25 Racing Wheel, a superb product for PC racing enthusiasts. Of course, after investing two or three hours of my life with TOCA 2 and the wheel ( yeeeeaaaaaah !) , I started to play with it using Managed DirectInput, just to see what is able to do.

I had some problems initializing Force Feedback, and I contacted Joe Kreiner from Logitech, who was very kind, I have to say. They helped me to find the solution, and I describe here what we found:

1.- Managed DirectInput samples have a bug present there for a long time, that any developer probably already discovered. They seemed to have tested their applications with joysticks only, as their code works fine with them. However, with racing wheels (even the Microsoft one), the application reports that no Force Feedback device is present. To find it:

Theres a point in the code like this: if (axis.Length - 1 >= 1)

which tests if the device has 2 or more axis (don´t really understand the sense of comparing (AnyThing -1 >= 1) instead of (AnyThing >= 2) ... :o)

Anyway, replace the code with something like this: if (axis.Length >= 1) and it will work.


2.- The second bug appears when trying to create an instance of the type EffectObject, where an exception of the type "Value does not fall in the required range" is thrown with the G25 (not with other wheels, like the Logitech Driving Force Pro). The problem is in the method FillEffStruct(), where eff.SetAxes() is called twice:

eff.SetAxes(new int[axis.Length]);
...
eff.SetAxes(axis);

Even logitech´s engineers are not very sure what this method does, as there´s no explanation in the DX SDK docs. Anyway, removing the second call to SetAxes solves the problem.


As a conclusion, we are all impressed with the work done in the Managed version of DirectX and we also know it´s been developed by a small team of people with limited resources. Anyway, the documentation lacks lots of explanations, examples, and even methods and classes specs. Hope this will be fixed someday.

Cheers !

Wednesday, 3 January 2007

.Net Security event in Pamplona

Just a couple of weeks ago, we had the chance to learn from Chema Alonso in his chart "Los programadores y la seguridad", here in Pamplona.

Excellent work Chema !



The event was promoted by navarraDotNet, a recent .Net group created in Navarra, with the collaboration of Microsoft and the CES (Centros de Excelencia de Software, www.cesnavarra.net).


Thanks a lot to all of them. More coming soon !

Welcome to Graphic DNA

Hi there,

Just wanted to say hello and welcome you all to my blog.

I´ll try to talk about issues of my interest, like graphics, programming, DirectX, Managed DirectX, .Net, XNA, ...

Any opinion is really welcome !

Regards,

I. Ayucar.