Archive

Archive for July, 2009

Spore Creatures

The latest spore patch added a “Cheat” to export creatures to Collada. I started playing around with it.

Export a Creature

To export a creature to collada, you have go into the creature editor and bring up the cheat console. (Strg-Shift-C) and type in colladaexport.  The first time you have to accept the EULA. The path for the exported creature is shown in the console.

Importing a static mesh

I started with a creature I had made before. I just exported it and got a 5.3mb colllada file plus a diffuse, normal and specular texture. I now started to import it into the various 3d packages I have access to, but I couldn’t get it into Blender at all. In the Softimage Mod Tool it looked better but just the mesh was imported. It has lost the uv mapping and rigging information, yes the creatures are also rigged, when exported. Which makes it especially interesting.

So now it just tried to export it as .fbx using the 2010.0 FBX Converter. The conversion was successful without any warnings or errors.
So just added it to a xna project and the pipeline imported it. When rendering the model I got this result.

clip_image001

The model is imported correctly, just the texture is missing. SO I had to manually set the diffuse texture and everything looks like it should look.

clip_image001[5]

I tried it with all kind of creatures and everything worked great.

Importing as skinned mesh

As I said before all exported creatures are completely rigged, so I now tried to import and render the meshes as skinned meshes. But as I opened the collada file to see how many bones a creature has, I was a little bit shocked. This mesh had 192 bones.

So I created a new mesh, a lot simpler with just 52 bones. This is ok. My existing skinning solution supported up 80 bones.

I just imported it and everything worked, without any problems.  You can see the skinned model below on the left in the bind pose and on the right with a big toes, just one bone scaled up.

clip_image001[7]

clip_image001[9]

More complex creatures

But now back to my previous test creature,  which has 192 bones. But this creature isn’t the most complex you can build in spore. After some more testing I had to see that creature can get a lot more than 200 bones. The Question, how should I handle those large number of bones? Implement a mesh splitting algorithm or do the skinning on the CPU?
I decided to choose the CPU way, after I couldn’t find any resources about a mesh splitting algorithm on the web.
I just want to play with the creatures for now,  if the performance would be to bad I always could go back and implement skinning on the GPU at a later time.

Current State

I have now implemented skinning on the CPU and I’m able to import and use every creature from the spore universe.

What’s next?

Next step is to implement the creation of animations directly into xna, as I’m not able to get the creatures into any other 3d package I own.

This will be an interesting experiment to get this working.

Categories: all

Using Windows Management Instrumentation(WMI) to get Hardware Information in .Net

I’m currently working on some new projects in .Net which use the new addition for Parallel Programming in the .NET Framework. While developing I noticed that my simple-log really isn’t that great in a Multithreaded Project. I was using a simple text file. I’m now switching to an new log-system, I’m currently working on, but this is a different post.

As I was designing the new log-system I saw that I don’t had any information about the system the application was running on. I was dependent that everybody who send me a log for a bug report also tells me their system information. This wasn’t that clever. So I started to look for a way to get all those data in .Net and I found out that WMI also can be easily be accessed from .Net.

The code to access WMI is in the System.Management namespace. This is in the Assembly with the same name. Which is referenced by default, so don’t forget to add the reference.

When you have found all the different pieces needed to query all the different data you have done the task which takes most of the time. Sadly I haven’t found any resource which had all the links in one place. I will post the links to the documentations you need at the end of the post.

When we have all the documentation open it’s really easy to get a lot of information from the hardware. So lets start.

The first step is to create a ManagementObjectSearcher. A ManagementObjectSearcher returns a collection of ManagementObject based on the query defined when creating the Searcher. The ManagementObjectSearcher overload I will be using here takes two strings. The first argument contains the scope in which the query should be executed and the second argument is the actual query. But lets look at the code:

ManagementObjectSearcher searcher = new ManagementObjectSearcher(“root\\CIMV2″, “SELECT * FROM Win32_Processor”);

This ManagementObjectSearcher queries all the Processors in the “root\\CIMV2” scope, this is the default scope, it contains all the hardware.

Now we have to get the actual processors from the searcher.
foreach (ManagementObject wmiObject in searcher.Get())
{
// [Add Code here]
}
The searcher.Get() methods returns a ManagementObjectCollection so we use a foreach to get the data. Maybe the PC has multiple elements of this kind as well so keep in mind to handle those cases as well.

Now it’s time again to look in the documentation, in this case we have to look at the WIN_32_Processor documentation. At this page you get a look at all the different properties you have access to.

If you have found the name of the property you want to get the data from you just have to call the following code. You just have to replace the string with the name the property you want to get the value from.
object clockSpeedObject = wmiObject.GetPropertyValue(“CurrentClockSpeed”);
uint clockSpeed = (uint) clockSpeedObject;
GetPropertyValue(..) will always return a object so you have to cast it your self, always check the types the Property values is in.

This is everything needed you need to know. Below are some samples showing how to retrieve data from GPU, CPU and RAM.

Hope you find this useful. This article just scratches the surface of what WMI is able to do.

GPU

ManagementObjectSearcher searcher = newManagementObjectSearcher(“root\\CIMV2″, “SELECT * FROM Win32_VideoController”);

foreach (ManagementObject wmiObject in searcher.Get())
{
object memoryInBytes = wmiObject.GetPropertyValue(“AdapterRAM”);

// some video controllers are listed without RAM
// those aren’t real cards, so can we ignore them
if (memoryInBytes != null)
{
// calculate Memory in MB
uint memoryInMB = (uint)memoryInBytes / 1024 / 1024;

string cardName = (string)wmiObject.GetPropertyValue(“Description”);
string driverVersion = (string)wmiObject.GetPropertyValue(“DriverVersion”);
string manufacturer = (string)wmiObject.GetPropertyValue(“AdapterCompatibility”);
}
}

CPU

ManagementObjectSearcher searcher = new ManagementObjectSearcher(
 "root\\CIMV2", "SELECT * FROM Win32_Processor");

foreach (ManagementObject wmiObject in searcher.Get())
{
      object clockSpeedObject = wmiObject.GetPropertyValue("CurrentClockSpeed");

      // get all the informations about the processor
      uint clockSpeed = (uint)wmiObject.GetPropertyValue("CurrentClockSpeed");
      uint physicalCoreCount = (uint)wmiObject.GetPropertyValue("NumberOfCores";
      uint logicalCoreCount = (uint)wmiObject.GetPropertyValue("NumberOfLogicalProcessors");
      string manufacturer = (string)wmiObject.GetPropertyValue("Manufacturer");
      string name = (string)wmiObject.GetPropertyValue("Name");
}

RAM

ManagementObjectSearcher searcher = new ManagementObjectSearcher(
                     "root\\CIMV2", "SELECT * FROM Win32_PhysicalMemory");

int totalMemory = 0;

// calculate the RAM capacity we have
//  we have to add every RAM-Stick Capacity to get the fincal value
foreach (ManagementObject wmiObject in searcher.Get())
{
     ulong capacityInBytes = (ulong)wmiObject.GetPropertyValue("Capacity");
     // calculate in MB
     ulong capacityInMB = capacityInBytes / 1024 / 1024;
     totalMemory += (int)capacityInMB;
}

Links

Categories: all