Autodesk 3DSMax 2009. Bug in 3DS Exporter

In the past weeks, we have been working with some 3D models done by another company with 3DSMax 2009, and exported to the 3DS file format, so we can read it. We realized that each model which included Bump Maps, had a wrong map percentage amount in the file.

A note: In the case of Bump Maps, the real map percentage is not stored in the usual Map Percentage (as INT_PERCENTAGE OR FLOAT_PERCENTAGE, chunks 0x0030 or 0x0031), but in the MAT_BUMP_PERCENT (chunk 0xA252) that comes with the material (if you read chunks sequentially instead of by hierarchy, you will normally find it after the MAP_BUMP chunk).

A material with a bump percentage of 999 in 3dsMax will report a percentage of 9 in the file. Of course, materials with more usual bump percentages (below 100), will report no bump at all (zero) in the file. In fact, if you export a model with a 90% of bump, and import back to 3DSMax, you will see that the bump texture is assigned correctly, but the bump percentage is 0.

I installed today the trial version of 3DSMax 2010, with it´s hotfix, just to see if they fixed it. And no, the bug is still there. Will try to report to Autodesk.

For those who still don´t know what is 3DSMax and what you can do with such a powerful program, some mind-blowing pics I´ve found at CGArena. They show the process of creating a human-like 3D model, a replica of the Korean actress 'Song Hye Kyo'.

songtexture1 songhair2

scene1scene2

final

AMAZING!!!!

Direct Input Custom Action Mapping (refresh)

ManagedDirectx is quite a bit outdated, and no longer supported by Microsoft, but it will make it for this example on custom action mapping. I´d suggest you to go XNA or SlimDX if you want to do some serious .Net graphics or game development.
What´s this post about? It´s about having a decent controller configuration system. The first choice, of course, is to start looking at DirectInput´s Action Mapping. If you prefer to do that on your own (to get rid of the standard and no too customizable DX config dialog, for example), keep reading.
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 an InputDevice and an Object of that device to a GameAction defined by us.

PART 1: Define game actions

We will put all of our actions in an enumeration.
        enum eGameActions
        {
            MoveForward,
            MoveBackward,
            TurnLeft,
            TurnRight,
            Shoot,
            . . .
            NumberOfActions    // Not an action, just to know the total count of actions
        }

A quick note for beginners: 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 doesn't have that member.
  • Enum.Parse(typeof(eGameActions), string): Will try to convert any string representation of an enumeration, to the enumeration itself.

PART 2: Inmediate or Buffered mode?

The next step is to make an important choice: Inmediate or Buffered mode? Pasting here the DX SDK description of both modes:
“DirectInput supplies two types of data: buffered and immediate. Buffered data is a record of events that are stored until an application retrieves them. Immediate data is a snapshot of the current state of a device. You might use immediate data in an application that is concerned only with the current state of a device - for example, a flight combat simulation that responds to the current position of the joystick and the state of one or more buttons. Buffered data might be the better choice where events are more important than states - for example, in an application that responds to movement of the mouse and button clicks. You can also use both types of data, as you might, for example, if you wanted to get immediate data for joystick axes but buffered data for the buttons.”
DX standard Action Mapping works in Buffered Mode only, but we will want to provide a way of using both. Why? Because we want an Input library for all of our projects, regardless they fit best with a buffered or immediate mode.
Immediate 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 accessing to. It´s the 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? 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
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

PART 3: Making the relationship

We need a way to save and recover from a file something like this: Action="Steering Action" PhysicalDevice="Logitech G25" PhysicalObject="Wheel Axis". We will use XML based files to store the info. How?
  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(attributeGuid.InnerText );
  3. The third attribute.... aaaahhh. This is a little bit more tricky.
We need a way to identify the device´s object we want to map the action to.
Bind up the physical object
What do we put in the XML file to identify the device´s 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.
In Buffered Mode, physical objects are identified through an Offset provided by the GetBufferedData method (inside the BufferedData class). If you look into it, you will realize that this offset is, in fact, the offset inside the JoystickState structure provided by the Immediate Mode. So, it seems we have found a unique identifier for our physical objects, that works in both immediate and buffered mode: THE OBJECT´S OFFSET.
So, our XML configuration file will handle information like the following:
Map Action="Steering Action" PhysicalDeviceGuid="1820-12820-2147-94579-3426-4575" PhysicalObjectOffset="138452"

PART 4: Designing the ActionMap class

It´s a good Idea to define a ActionMap class, to handle the mapping between a GameAction and a Physical Object, and store information about the read data. The first part, to manage the mapping with the physica object, could be something like:
    public class ActionMap
    {        
        public eGameActions mActionType;
        public string mActionName = "";
        public eGameActionCategories mCategory = eGameActionCategories.None;
        public DeviceState mDeviceState = null;
        public int mObjectOffset = -1;
       
   
And the second part, to store information about the read data, could have this shape:
        public int mCurrentValue = 0;
        public bool mIsFFAxis = false;
        private bool mReadAsImmediateData = false;
 
        public float mFormattedValue = 0;
        public float mCurrentValue01 = 0;
        public bool mCurrentValueBool = false;
 
        private int mRangeMin = 0;
        private int mRangeMax = 0;
        private bool mInvertReading = false;
        private eBoolBase mBoolBasedOn = eBoolBase.RangeMax;
 
What is all that information? First variable is, of course, the current or last read value. It is an int as every DInput value is read as integer. Second value tells us if this action is mapped to an analog object with Force Feedback enabled. Third value will allow us to configure this specific action to be read as Immediate (instead of buffered, the default behaviour).
Starting from there, I´d recommend you to store another versions of the data. FormattedValue, for example. It is useful to provide this container to your application, so it can transform the read data as you want it, storing the result there for your comfort. It is very common to have other typical formatting of your data too, like the value expressed in the range 0..1, or expressed as a boolean (useful for buttons).
In order to make this conversions, you will need another step.

PART 5: Action calibration

Why every Controller Configuration has a Calibration step? Because you cannot know the range of the object the user selected for an Action. Analog objects, for instance, like pedals, joysticks or steering wheels, usually report an integer value between 0 .. 65535. But some of them will use other ranges. Buttons are retrieved as int too, with the values 0 or 128 only. To make things even worse, objects are sometimes read as inverted, what means that a button can be reported as 0 when un-pressed and 128 when pressed, or just the opposite. The same for analogs.
So, it´s clear that you need calibration, a way to know the valid range for objects and if they have to be read as inverted or not. I´d suggest you to store those values in mRangeMin, mRangeMax, mInvertReading. With that information, you have all you need to transform the int value read to the range 0..1.
The last thing we need is a way to convert it to boolean, so we can quickly check from our application if a button is pressed or not, for example, without having to worry about it´s range, inverted property, or anything. What I usually do here is to define what to compare the int value to, to decide if its pressed (boolean = true) or not (bool = false). You can do this in many ways, but I like to use an enum for such purpose:
public enum eBoolBase
{
    RangeMax,
    RangeMin,
    Zero,
    NotZero,
}
Using this, you can make an Action to be true when it reached it´s max range value, or when it´s non-zero, or whatever you want.

PART 6: The whole ActionMap

The whole Action Map for our application could be handled by a structure like the following (make your own for your purposes):
Dictionary<DeviceState, Dictionary<int, List<ActionMap>>>
Or you can have the reverse, indexing first by the ActionMap, and taking the Device and Object´s Offset later. Choose your favorite option.
Then, just define the ToXml() and FromXml() methods to store and recover all your configuration. The best place to store this configuration is the ApplicationData special folder. This way, the config will be made for every machine the application is installed, keeping a different configuration for each Windows user.To save the settings, just loop for every device in your structre 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.

PART 7: Updating your data at runtime

Once per frame, a DoSteps / OnFrameMove / Update / whatever you like method should be called to update all the data. It should do something similar to this:
                // Read Buffered Data
                foreach (Device dev in this.mActionMap.Keys)
                {
                    dev.Poll();
                    BufferedDataCollection coll = dev.GetBufferedDate();
                    if (coll == null)
                        continue;
                    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 or 128)
                           
                            bdata.Data is what you need
                        }
                    }
                }
                // Read Immediate Data
                foreach (DeviceState st in this.mDeviceStates)
                {
                    foreach (List<ActionMap> lista in dic.Values)
                    {
                        foreach (ActionMap action in lista)
                        {
                            if (!action.ReadAsImmediateData)
                                continue;
 
                            // Use action.Offset to access the JoystickState structure
                        }
                    }
                }

PART 8: 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, uncustomizable, 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. Set the timer to fire up every 100 ms or so. In the Timer_tick event, do the actual "listening" process:
    1. Increment a Time Counter. If it reaches the amount of time for listening, get out.
    2. Loop through every device
    3. Make device.GetBufferedData ()
    4. Assign first retrieved data to selected GameAction
In this algorithm you should also apply a Thresold, 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.
Take Care!

Bring old MSDOS applications to life in Windows Vista

Some days ago, a friend asked for my help with a problem. He bought a brand new Dell laptop with Vista installed on it. He is retired now, but he has been a consultant and manager for many years. During his life, he worked a lot with Open Access 4, and he currently has lots of files and data bases he wants to keep.

The problem is that MSDOS applications compatibility in Vista has been remarkably degraded, compared to XP. Open Access worked, but tooooooo slow and with no support for full-screen mode… No matter what the application settings were (compatibility mode, admin. privileges, etc). After some days investigating, I´ve found a very interesting project that solved all my problems: DOS Box.

DOS-Box is an X86 emulator with a built-in MSDOS version. It has been designed to allow playing old games again, with sound, decent fps, and in full-screen. There are even GLIDE and OpenGL enabled versions out there. You can download it and make a donation if you want here. How to use it? Easy, install and run, or plug and play if you prefer.

The only thing you have to do to make it work is to mount virtual units to access your disks. Just like this:

“mount VirtualUnit RealDirectoryToMap”

Example: “mount H: C:\EyeOfTheBeholder”

Automatic application launching using a FrontEnd

If you don´t wont to deal with mounting drives, and all that stuff, you can use a FrontEnd application for DosBox, many of them also available from the download link. I have tried DosShell and works pretty well.

Main window

 

Just install it and configure the DosBox path: Edit –> Preferences –> DosBox Folder. Then click on the “plus” icon to add shortcuts to your applications.

A quick note: After adding my first application, I got an error when trying to launch it, something like: “DosBox configuration file not found”. To fix it, just enter DosBox (double clicking its icon), and type the following command:

CONFIG -WRITECONF dosbox.conf

Hit return, and now it should work.

Enjoy!

nVidia Control Panel Stopped working bug fixed

For the last 3 or 4 months, I have been experiencing a very frustrating bug in the nVidia control panel, which made it to fail at opening. I tried many things to fix it: installing latest versions, uninstalling and re-installing in safe mode, etc, but nothing worked. Until today.

Today I installed the latest GeForce drivers, version 185.85, and they seem to fix the thing. THANK GOD!!!!

My specs where:

  • Dell XPS 630 i
  • Windows Vista Ultimate 32 bits Spanish
  • GeForce GTX 280 with nForce motherboard

Cheers!

Error en el instalador de SQL Server 2005 Management Studio Express

Si te bajas el SQL Server 2005 Management Studio Express, muy probablemente recibirás un mensaje de error 29506 al final del proceso de instalación, diciendo algo como:

“El instalador encontró un error inesperado al instalar este paquete. Esto puede indicar un problema con este paquete. El código de error es 29506”

He probado a bajarme el paquete dos veces, desde ordenadores distintos, y a instalarlo en máquinas diferentes también con la siguiente config aproximada:

  • Máquina 1: Dell XPS 630i, Windows Vista Ultimate en castellano
  • Máquina 2: Dell XPS M1530, Windows Vista Home en castellano

Ambas con el SQL Server 2005 ya instalado (pero sin el Management Studio, obviamente). En ambas falla.

Solución: Bájate la versión en inglés del Management Studio. En la parte superior de la pantalla, cambia el idioma y vuelve a bajarte el paquete. Esa te funcionará.

Salu2!

Entrevista en Diario Las Provincias y en Punto Radio Valencia

Hoy se ha publicado una entrevista que nos han hecho como ganadores de uno de los galardones a la mejor empresa de Base Tecnológica del año 2008, en los premios Bancaja. El link a la publicación en el diario las noticias aqui:

http://actual.lasprovincias.es/jovenesemprendedores/la-tecnologia-puede-ser-economica/

Take Care!

Simax en el Salón del Automóvil de Barcelona

Entre el 9 y el 17 de Mayo, Simax estará presente en el stand de Toyota en el Salón Internacional del Automóvil de Barcelona. No olvides probar nuestro simulador de Conducción Ecológica.

From May 9th to 17th, Simax will be present at the Barcelona International MotorShow. Be sure to try our ECO-Driving simulator at Toyota stand.

¡ Por fin sabemos de donde saca MediaMarkt esos precios !

Bueno, es un decir, porque algunas cosas en MediaMarkt son caras de la ostia… Pero bueno, era una buena entradilla para el post. Y es que parece que han puesto a tres orangutanes redactando la publicidad. Atentos:

Hoy me llega a casa el folleto de publi más jodidamente grande que he visto en mi vida. Si los normales de MediaMarkt ya son enormes, imaginaos uno con EL DOBLE de tamaño. Supongo que es para festejar que tienen una LG FullHD de 47” a 799 lereles. El caso es que, cuando más han querido llamar la atención con un folleto donde todo España pondrá sus miradas a la caza de una ganga, va y te encuentras esto:

mmrkt

Vaya pedazo de patada el diccionario de la Royal Academy. Ya me veo la escena…

- Pacoooo!, ¿como se escribe eso de “mobail”?

- A ver, ignorante de la vida… ¿Cómo quieres que se escriba? ¡PUES COMO SUENA!

¡Qué grande! En mayores letras no lo podían haber puesto. A ver si después de tantos años, lo de la “E” de MediaMarkt va a ser otra de estas… Juas!

Actualizar el Firmware de un LGRH177

En muchos sitios se dice cómo hacer esto, pero casi todos se dejan un punto fundamental (el 3B) que hace que el dvd no reconozca el disco como de actualización. Pongo las instros en inglés, porque son casi las 2 de la mañana y me da pereza traducirlas:

1) Go to link: http://pl.lgservice.com/
2) press Floppy disc icon
3) select DVD/Video in Produkt
4) press Szukaj
5) select the file from the list

--[Creating the CD by using NERO]
1) use a CD-R or CD-RW;
2) create an ISO CD-ROM with only one session;
3) use ISO-9660 mode;
3b) select 31characters file name length;
4) label CD as "RH1000_UP";
5) burn just the file LG_HDR_UPDATE.004;
6) burn with DAO (disc-at-once) mode and finalize;
7) insert the CD in the DVD-Recoder;
8 ) press "Home" button and go on "Music > Disc"
9) follow the instruction the recorder shows (... you
have to press some times REC and so on..)
10) after the upgrade has been completed (be sure of this!), turn off the recorder.

A disfrutar!

Arreglar un DVD LGRH177 con lector/grabador defectuoso

Si eres uno de los afortunados (o desafortunados, según se mire) poseedores de un dvd grabador LGRH177 sigue leyendo, esto te interesa.

Eres afortunado porque el cacharrillo está bastante bien, pero la fortuna se te acabará, tarde o temprano. Estos bichos cascan más que una escopeta de feria, sobre todo la unidad lectora/grabadora de discos.

Lo primero de todo, algunos trucos para este dvd y los de series parecidas: como saber qué firmware tienes, como actualizarlo, etc etc.

Lo segundo de todo, comentarte que muy probablemente, alguna vez este dvd te de un error al leer o escribir un DVD. Siento decirte que la frecuencia con la que falla va a aumentar, hasta que deje de funcionar del todo. Y sin un DVD donde grabar las cosas, o desde donde meter pelis al disco duro, de poco nos sirve el invento. ¿La solución?

Cambiar la unidad de DVD

[Note: If you don´t undestand Spanish, here you will find a good english explanation about this procedure]

Sí, has oído bien. Es tan fácil que no entiendo como hay tanta gente por cientos de foros de todo el mundo pidiendo ayuda para reparar su bichito. Si abrís la carcasa, os encontraréis que dentro es muy muy parecido a un PC. El disco duro es, obviamente, un disco IDE normal y corriente. Y el lector de DVD, pues más de lo mismo: un lector normal y corriente de ordenador. Esto es lo que os vais a encontrar al abrirlo (perdón por la calidad de las fotos, son de móvil):

SNC00153

Como véis (aunque en la foto no se vea bien), ambos dispositivos van conectados con cable IDE. Desmontad con mucho cuidado el lector de DVD (el cable que trae el reproductor es muy muy fino y se rompe con facilidad).

Una vez hayáis extraído el lector, desmontadle la carcasa metálica que trae, e id a la tienda a por un sustituto. Yo he usado una grabadora de DVDs que tenía por ahí, por casualidad también marca LG, aunque esto no creo que importe nada. Obviamente, la grabadora que escojáis ha de ser IDE. No seáis muñones y vayáis a comprar una SATA. En concreto, el modelo que yo he probado y que os puedo asegurar funciona es este:

SNC00161

Aseguraos de poner el Jumper de la grabadora en modo “Master” y desmontad la carcasa de ésta también, quitándole también todo el frontal y el embellecedor de la bandeja, ya que en el LG molestarían. Una vez tenemos las dos unidades “en pelotas” veremos que son casi idénticas (ambas fabricadas por Panasonic):

SNC00158

Solo vais a encontrar una complicación. La unidad que viene en el RH177 es 4mm más delgada que las unidades estándar. Por culpa de esto, tendremos que hacer un par de ñapas para encajar la nueva, poniéndole a la nueva unidad parte de la carcasa metálica antigua, y parte de la nueva.

 

Como el lector tiene que ir un pelín más alto que la base del reproductor, es conveniente utilizar la parte inferior de la carcasa metálica original del RH177, mientras que para la parte superior, es mejor usar la de la carcasa de la unidad nueva (ya que la original del RH no te va a encajar).

SNC00162

Mitad inferior de la carcasa RH177

SNC00159

Mitad superior de la carcasa del lector sustituto

Así, hacemos un pequeño Frankenstein con las carcasas, pero queda fetén. Para que encaje la parte inferior en la nueva unidad, es posible que tengas que empujar un poco hacia adentro el LED de actividad. En mi caso molestaba un poco.

Un par de últimos detalles: una vez tenemos la nueva unidad con ambas partes de las carcasas encajadas, vamos a tener que doblar algunas cosas para que todo encaje. Si si… doblar.

1.- En la carcasa del nuevo lector, la parte inferior tendrá unas pestañas que nos van a molestar. Doblarlas hacia arriba hasta que los agujeritos de las patas se alineen bien con los de la base.

2.- Veremos que, dado que la nueva unidad es más ancha, no cabe en la carcasa principal del DVD. Para lograr que entre bien, tenemos que doblar una pestaña del frontal de dicha carcasa. Parece una burrada pero no nos va a molestar en absoluto después. Os muestro en la siguiente foto qué teneis que doblar y como (en rojo):

SNC00154_2

3.- Por último, es muy fácil que la nueva unidad no os quede perfectamente alineada con la posición original, y que eso haga que la bandeja no salga bien (pegará con los embellecedores del DVD una vez montado todo). Para solucionarlo, en mi caso bastón con quitarle la puertecilla embellecedora al frontal del DVD, que le restaba mucho espacio. Sin ella, queda muy jujano, pero qué quieres que te diga. De tener que tirar el cacharro a la basura a que funcione de nuevo al 100%…

¿Y qué pasa con el disco duro?

Pues más de lo mismo.

Si se te ha estropeado o si simplemente quieres uno de más capacidad, es muy fácil cambiarlo. Yo no lo he hecho, pero hay instrucciones por la red acerca del procedimiento.

Os dejo un recurso muy valioso acerca del RH177. Tiene mil tutoriales de todo tipo, incluso sobre algo que realmente eché de menos en este DVD: cómo instalarle una toma USB para acceder al disco: http://ifndef.altervista.org/

Increíble!!!!

Final de Microsoft Imagine Cup España 2009

El próximo 7 de Mayo, seré uno de los ponentes en la final del concurso Imagine Cup 09 en su edición Española, que tendrá lugar si no me equivoco en la Universidad Complutense de Madrid.

Se trata de un concurso internacional que promueve Microsoft para apoyar a los nuevos talentos desde la Universidad. Los premios van desde un smartphone o una XBox360 hasta un viaje a El Cairo con todos los gastos pagados para participar en la final mundial de Imagine Cup. Según la propia web:

“En la edición de Imagine Cup en España participan estudiantes universitarios españoles con inquietud por la tecnología y en particular por el desarrollo de aplicaciones innovadoras y creativas. La séptima edición internacional de Imagine Cup tiene como objetivo encontrar soluciones a los problemas reales de nuestros días.”

Más información haciendo click en la foto.