Marmalade SDK: Export character from 3DS MAX to GEO

Rendering an Animated Character Using Marmalade Studio

This tutorial walks you through a simple example of how to render an animated character using Marmalade Studio. You will learn how to export a model from your 3D art package and how to render the animated character from a Marmalade code project.

Building and exporting the assets

The art files for this tutorial are found in the sdk installexamplesgamesArtAssetscombateva, files for each 3D modelling package are within appropriately named folders.
Exporting the Model
The character is exported in two sections. First the rig is exported. This includes the skin and skeleton and all the controllers. Within the game, the base file is used for all animations for the character, so the animations should all use an exact copy of the rig, else errors will occur.
The Rigged Character
  • Open the file combatEva_rig in your preferred 3D Modelling Package
  • Open the Exporter Dialog
  • Choose an appropriate project (if required create a new project for this tutorial and add a data directory)
  • The Exporter Dialog
  • Choose a Model Export if not already selected
  • Change the ‘Save to Location’ option to ‘data’
  • The Exporter Dialog
  • Leave all the other options as they are already set
  • Click Export
Exporting the Animations
The animations for a character are usually exported from separate source files. The animation is the only thing that is saved within an ‘anim’ Export; all the information about the character is stored when the initial rig is exported, as completed above.
The Animated Character
  • Open the file combatEva_anim in your preferred 3D Modelling Package
  • Open the Exporter Dialog
  • Select the same project as before
  • Choose a anim Export
  • Change the ‘Save to Location’ option to ‘data’
  • The Exporter Dialog
  • Leave all the other options as set
  • Click Export

Rendering the animated character

Now we must write the code to render the character in the application.

We include the headers of the modules we will be using.
  • IwGx provides low-level rendering API, abstracting software and hardware rendering.
  • IwGraphics provides a higher-level API that renders models.
  • IwAnim extends IwGraphics, providing skinned animation.
  • IwResManager provides resource management – the loading and binarising of assets.
#include "IwAnim.h"
#include "IwGraphics.h"
#include "IwGx.h"
#include "IwResManager.h"
The entry point (where the code starts executing) is the standard c main function.
int main()
Marmalade Studio modules must be explicitly initialised before use. Modules may implicitly initialise other modules they depend on. In this example IwGx will initialise IwResManager.
Now we load our animated character. Marmalade Studio resources are held in atomic units called resource groups (.group files). A resource group contains one or more resources.
A .group file is a human readable text file specifying which resource are contained in the group.
The group for this example looks like:
// Source file: C:/Dev/sdk/main/sdk_examples/ArtAssets/combatEva/Maya7/combatEva_rig.mb
// Exported By: on 04/03/08 17:04:26

 name "combatEva"
As you can see, her model (.geo), skeleton (.skel), skin (.skin) and animations (.anim) are all resources included in the group file.
To load a group we simply call the LoadGroup method of the resource manager singleton.
Once the group file has been loaded, the resource manager singleton can retrieve resources by name and type.
Let’s retrieve the resources from the group. Notice that the resource’s name is the filename without the extension. Each resource is asked for by its name and its c++ type.
 CIwModel* pModel = (CIwModel*)IwGetResManager()->GetResNamed("combatEva", "CIwModel");
CIwAnimSkin* pSkin = (CIwAnimSkin*)IwGetResManager()->GetResNamed("combatEva", "CIwAnimSkin");
CIwAnimSkel* pSkel = (CIwAnimSkel*)IwGetResManager()->GetResNamed("combatEva_rig", "CIwAnimSkel");
CIwAnim* pAnim = (CIwAnim*)IwGetResManager()->GetResNamed("LfFwShuffle", "CIwAnim");
To play an animation on a model we create a CIwAnimPlayer object, set the skeleton and play the animation. The animation player contains its own copy of the skeleton which it will pose according to the current interpolated frame of the animation.
 CIwAnimPlayer* pPlayer = new CIwAnimPlayer;
pPlayer->PlayAnim(pAnim, IW_GEOM_ONE, CIwAnimBlendSource::LOOPING_F);
We keep track of how many milliseconds elapse every frame to play the animation at a constant speed independent of the framerate.
 uint64 lastFrame = s3eTimerGetMs();
Now we enter the main loop. The exit condition is s3eDeviceCheckQuitRequest. This will return true if the OS requires us to exit. In the Marmalade Simulator this will be when the close icon is clicked.
First of all, update the player according to how long the last frame took.
The return value of s3eTimerGetMs() is in milliseconds, while update takes a value based on fixed-point seconds. In Marmalade Studio fixed-point numbers are in 1.19.12 bit format – IW_GEOM_ONE is defined to be (1 << 12).
  uint64 now = s3eTimerGetMs();
pPlayer->Update((uint32)(now - lastFrame) * IW_GEOM_ONE / 1000);
lastFrame = now;
Now we begin rendering.
First of all we clear the screen.
Set a simple camera matrix.
Starting from identity (which means looking along the positive Z axis from the origin) we move backwards along the Z axis, upwards along the Y axis, and finally rotate 180 degrees around the Z axis. Rotations are specified in fractions of an entire revolution i.e. IW_GEOM_ONE is 360 degrees. This final rotation is required because positive Y is downwards in screenspace – (0,0) is the top left hand corner of the screen.
  CIwMat view = CIwMat::g_Identity;
view.t.z -= 200;
view.t.y += 100;
Set the model matrix.
In this example we just rotate Eva 120 degrees around the Y axis so she’s facing us, but slightly askew (she is looking down the Z axis in maya).
  CIwMat model = CIwMat::g_Identity;
We must set the animation context so the model gets the skeleton from the player when it renders.
Now we actually render the model. This will submit draw commands to iwgx. Nothing will actually be rendered until IwGxFlush is called.
Although not strictly necessary in this example it’s good practice to return the anim context to its default state, so errors when rendering future characters without setting up the context correctly are easier to understand.
IwGxFlush commits all the drawing commands to the renderer.
Finally we call IwGxSwapBuffers to present the rendered output to the screen.
Marmalade applications are co-operatively threaded. This means they must yield frequently to the system so background processes can continue to run. This is done using s3eDeviceYield. In this example we want to run as fast as possible, so we pass 0 to s3eDeviceYield. This will return control to our application as soon as possible.
Once the main loop has ended, we must free up any resources we created. Note that the resource allocations in the resource manager are owned by that module. Resource manager resources are destroyed using DestroyGroup. However, any groups still loaded when resource manager terminates will be freed automatically, so we will not explicitly free them here.
 delete pPlayer;
Finally, we terminate the modules we created for a clean exit. Marmalade Studio will assert if any allocations are leaked. There are various useful debugging options for identifying leaks.
main() should return 0 to indicate no errors occurred.
 return 0;

Leave a Comment