Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
2K views35 pages

3ds Max Game Export Programming

The document provides an overview and introduction to programming with the 3ds max Game Export Interface. It describes initializing the interface to extract mesh, spline, lighting, controller and other game asset data from 3ds max in a simplified manner compared to the standard API. The interface supports common 3D objects, custom attributes, and parameter blocks. It handles coordinate system conversions and provides wrapper interfaces to access key data without extensive 3ds max API knowledge.

Uploaded by

bobie70
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2K views35 pages

3ds Max Game Export Programming

The document provides an overview and introduction to programming with the 3ds max Game Export Interface. It describes initializing the interface to extract mesh, spline, lighting, controller and other game asset data from 3ds max in a simplified manner compared to the standard API. The interface supports common 3D objects, custom attributes, and parameter blocks. It handles coordinate system conversions and provides wrapper interfaces to access key data without extensive 3ds max API knowledge.

Uploaded by

bobie70
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 35

3ds max Game Export

Interface
Programming Guide
3ds max Game Export Interface Programming Guide

3ds max Game Export Interface..............................................................................1


Programming Guide.................................................................................................1
...................................................................................................................................2
Introduction...............................................................................................................3
3ds max Game Export Interface Overview.............................................................3
Programming with the 3ds max Game Export Interface
....................................................................................................................................4
Initialising the Game Export Interfaces...................................................................5
Extracting the Data..................................................................................................6

IGameScene........................................................................................................6
IGameObjects......................................................................................................8

IGameMesh .....................................................................................................9
IGameSpline .................................................................................................10
IGameIKChain................................................................................................11
IGameCamera and IGameLight ....................................................................12
IGameSupportObject ....................................................................................12
IGameGenObject ..........................................................................................13
Modifiers............................................................................................................13
Controllers..........................................................................................................14
IGameKey......................................................................................................15
Materials and Textures......................................................................................16
Supporting Parameter Blocks and User Defined Data.......................................17
XML Defined..........................................................................................................18
Simple Enumeration..............................................................................................21

Error Reporting.......................................................................................................22
Existing Code Integration......................................................................................22
Appendix..................................................................................................................24
Pararameter Blocks...............................................................................................24
IGameProperty XML format.................................................................................26

File syntax..........................................................................................................26
Export Entities syntax........................................................................................27
Export User Data syntax....................................................................................28
IGameObject Interfaces........................................................................................28
3ds max Mesh Representation.............................................................................29
IGameKey Definition.............................................................................................32
Object Properties...................................................................................................34

2
3ds max Game Export Interface Programming Guide

Introduction
Since its inception, 3ds max has provided a rich API to control nearly every aspect
of the application. Stunning plugins, such as advanced renderers and cloth
simulations, could be written using this powerful and extensive API.

As the 3d development community matured, a new breed of developer began


writing plugins for 3ds max, simply interested in extracting data from the application.
The dawn of the export developer had arrived.

This developer was now faced with the steep learning curve inherent in the 3ds
max API. For commercial plug-in developers, this challenge could be tempered by
integrating a good learning period into the development cycle, but for game
developers, many with tight-schedules, this challenge often created programmers
with specialized knowledge scattered around the 3ds max API.

Game developers needed a simple and comprehensive API for quickly extracting
3ds max game asset data so they could move into other, more pressing, areas of
the game pipeline. They also needed to be sure that their export code remained
approachable and maintainable for novice users.

Enter 3ds max Game Export Interface, a High Level C++ API for 3ds max from the
Sparks developer support team at Discreet.

3ds max Game Export Interface Overview

The 3ds max Game Export Interface is built on top of the existing 3ds max API,
providing wrapper interfaces for the most common aspects of data export from 3ds
max.

The export Interface supports the following 3ds max objects

1. Mesh
2. Spline
3. Lights and Cameras
4. Controllers – including Euler, constraints and Biped
5. IK Chains
6. Skin deformers
7. Materials
8. Texture – including Bitmap Texture
9. Custom Attributes
10. Custom Node Data
11. ParamBlocks

3
3ds max Game Export Interface Programming Guide

The interface has been designed so that developers with very little experience with
programming with 3ds max can write an exporter with very little effort. Using the
custom interfaces a developer has access to the key max elements with out
needing to know how they work. This is key to being able to get to data and use it
Most developers know what data they want, but find it hard to work out where to
begin to find it.

Programming with the 3ds max Game Export Interface

The 3d max game export interface is supplied as a DLL with Library and Header
files to be used with your project. The DLL should be placed in the root 3ds max
directory. The interface does use MS XML implementation so IE 5+ should be on
the system. IE 5 is available on the 3ds max installation CD. To support the
properties, the provided IGameProp.xml should be placed in the plugcfg directory.

A simple comparison between the Game Export Interface and the standard
3ds max API:

Extracting Controller Data via the original 3ds max API:

Control * cont = node->GetTMController()->GetPositionController()

if (!cont) // Bug out if no controller.


return;

int i;
IKeyControl *ikc = NULL;

ikc = GetKeyControlInterface(cont);

// TCB point3
if (ikc && cont->ClassID() == Class_ID(TCBINTERP_POINT3_CLASS_ID, 0)) {
for (i=0; i<ikc->GetNumKeys(); i++) {
ITCBPoint3Key key;
ikc->GetKey(i, &key);
// do as you wish with the data

Extracting Controller Data via the export interfaces:

IGameKeyTab poskeys;
IGameControl * pGameControl = gameNode->GetIGameControl();
pGameControl->GetBezierKeys(poskeys,IGAME_POS));

As can be seen, accessing data via the new interfaces is much simpler and
requires little to no knowledge of the internal structures used by 3ds max.

4
3ds max Game Export Interface Programming Guide

Initialising the Game Export Interfaces


Before you can begin using the export interfaces, it must be initialised by obtaining
a pointer to the main IGameScene. This is accomplished through the code below.

IGameScene * pIgame = GetIGameInterface();

You may specify the coordinate space during initialisation.


The export interfaces uses a system where the developer can define such
coordinate system standards such as Max, OpenGL or DirectX. By default, the
conversion manager will default to the 3ds max system which is a Right-Handed
system with Z-up and Y into the screen.

The developer can also define a custom system with the ability to set the
handedness and principle axis orientation. The conversion manager will ensure
that all Matrix and Coordinate data is returned in the correct format without the need
for further processing.

//pIGame is an IGameScene pointer

IGameConversionManager * cm = GetConversionManager();
cm->SetCoordSystem(IGAME_D3D);
pIgame->InitialiseIGame(true); // true- we want selected only
pIgame->SetStaticFrame(0);

The above code snippet sets the conversion manager up with the internal database
ready to be used with data being converted to a DirectX format. It is now a simple
case of enumerating the IGameNodes and extracting the data you need.

The following code snippet show how to setup a user defined coordinate system

UserCoord WhackySystem = {
1, //Right Handed
1, //X axis goes right
4, //Y Axis goes in
3, //Z Axis goes down.
0, //U Tex axis is left
1, //V Tex axis is Down
};

IGameConversionManager * cm = GetConversionManager();
cm->SetUserCoordSystem(WhackySystem);

You may also initialise the Export Interface based on a set of INodes:
If you do not wish to gather data from every node in the 3ds max scene, you can
initialise IGame based on a single node or list of nodes by supplying the INode(s)
that you are interested in. This will provide you with an IGameScene maintaining

5
3ds max Game Export Interface Programming Guide

pointers only to the specified nodes.

Tab < INode *> interestingNodes;


Interface * ip = GetCOREInterface();

//use the regular max sdk to provide access to the selected nodes.

for(int i=0;i<ip->GetSelNodeCount();i++)
{
interestingNodes.Append(1,&ip->GetSelNode(i);
}

//pIGame is an IGameScene pointer


IGameScene * scene = pIgame->InitialiseIGame(interestingNodes,false);

Extracting the Data

IGameScene
The IGameScene object maintains a list, and count, of the all the top-level Nodes
and Materials. Each top-level interface, be it Node or Material, maintains that
node’s list of children.

As well as providing a count of the top-level Nodes, IGameScene also maintains a


count of all Nodes in the scene. This is something that you would have had to
perform as a pre-process with the existing 3ds max API.

IGameNode
The IGameNode is a container which maintains an actual Object, any Controller
associated with that Object, or a Material in the scene.

The following code demonstrates how Materials are accessed at the root level via
IGameScene. One call to IGameScene::GetRootMaterialCount() ,gets the
number of Materials in the scene, and a simple enumeration of the count allows a
direct index into the Material List via GetRootMaterial() .

6
3ds max Game Export Interface Programming Guide

//pIGame is an IGameScene pointer


void IGameExporter::ExportMaterials()
{
TSTR buf;
if(exportMaterials)
{
int matCount = pIgame->GetRootMaterialCount();
buf.printf("%d",matCount);
for(int j =0;j<matCount;j++)
{
IGameMaterial * mat = pIgame->GetRootMaterial(j);
if(mat)
DumpMaterial(matNode,mat,j);
}
}
}

Nodes are accessed in a similar way. In this example, the parent (top-level) Nodes
are accessed and exported. Note that ExportNodeInfo() is not apart of the
game interfaces.

for(int loop = 0; loop <pIgame->GetTopLevelNodeCount();loop++)


{
IGameNode * pGameNode = pIgame->GetTopLevelNode(loop);

if(pGameNode->IsTarget())
continue;
ExportNodeInfo(pGameNode);
pIgame->ReleaseIGameNode(&pGameNode); // free the memory

As the IGameNode is simply the object container, GetIGameObject()must be


called to access the actual object. Similarly, access to the Node’s Material and/or
Controller is accomplished through GetNodeMaterial() and
GetIGameControl() respectively. The developer can then call
ReleaseIGameObject() when they are finished with it, which will free all of the
memory associated with that object. Note that freeing the memory of the
IGameObject will not affect the Controller or Material data.

IExportEntity

All 3ds max objects that can be exported via Game Interfaces are derived
from IExportEntity.

This interface provides unified parameter access as well as a way of querying


whether a particular ExportEntity is supported with a dedicated API. The method
IsEntitySupported() is used for this - any supported Entity will return true.
IExportEntity will use this method to define whether the Entity is directly supported
from within the game interfaces, such as a Bitmap Texture, and will provide direct

7
3ds max Game Export Interface Programming Guide

access via the API for this Entity.

In another example, the IGameMesh object provides direct support for Tri Objects.
In this case, IGameMesh is a wrapper for any geometry-based object, so calling
IsEntitySupported() would yield true for any object it can convert to a Tri
Object, false for the others. If this method returns false, it simply means that there
is not a dedicated API for use with this object. A developer can still use the
IPropertyContainer interface to iterate through properties and access data that way.

IGameObjects
IGameNodes act as the containers of the IGameObjects – you can think of the
Objects as being the actual physical entity with relevant properties.

IGameObjects define the type of object they are, be it Cameras, Lights etc. The
developer must then cast the object to its correct interface, as demonstrated below.

The following is code from the IGameExporter sample (edited for clarity).

//child is an IGameNode pointer


IGameObject * obj = child->GetIGameObject();
switch(obj->GetIGameType())
{
case IGameObject::IGAME_MESH:
if(exportGeom )
{
IGameMesh * gM = (IGameMesh*)obj;
if(gM->InitializeData())
{
DumpMesh(gM,geomData);
}
else
{
DebugPrint(“Bad Object\n”)
}
}
break;
case IGameObject::IGAME_SPLINE:
if(exportSplines)
{
IGameSpline * sp = (IGameSpline*)obj;
sp->InitializeData();
DumpSpline(sp,splineData);
}
break;
}
child->ReleaseIGameObject();

In this example, we call GetIGameType()on the IGameObject and cast the


IGameObject to its associated interface. Please see the table below for a list of
IGameObject Types and their associated interfaces. This table is also viewable in
the Appendix.

8
3ds max Game Export Interface Programming Guide

IGame Object Type IGame Interface


IGAME_UNKNOWN IGameGenObject
IGAME_LIGHT IGameLight
IGAME_MESH IGameMesh
IGAME_SPLINE IGameSpline
IGAME_CAMERA IGameCamera
IGAME_HELPER IGameHelperObject
IGAME_BONE IGameHelperObject
IGAME_IKCHAIN IGameIKChain

To preserve memory, IGameObject has an InitializeData member. This tells IGame


to start the actual Object conversion. Objects like Editable Meshes can take up a
fair amount of memory, so this conversion happens at the request of the developer.
For example, in the case that only the simple node transformation data is required,
InitializeData wouldn’t need to get called.

IGameMesh

The IGameMesh object provides complete access to all the mesh relevant
data including normals, mapping channel, vertex information, and texture
coordinates.

It will also take care of such things as mirroring, which is again something that can
cause unexpected results when exporting as the normals will appear to be flipped.

Once you have an IGameMesh pointer you can use the various methods therein to
extract the data. Most face data (except mapping channel data) is provided in an
extended face class called FaceEx. This is an extension to the 3ds max class
Face and includes additional indexing for Vertex color, Alpha, Illumination and
normals. Mapping channels are dealt with separately.

The following example shows how to extract the vertices and face data of the given
mesh. The other data types are extracted in a similar way.

int numVerts = gm->GetNumberOfVerts();


for(int i = 0;i<numVerts;i++)
{
TSTR data;
Point3 v;
if(gm->GetVertex(i,v))
{
//use the data here
}

}
int numFaces = gm->GetNumberOfFaces();
for(int f=0;f<numFaces;f++)
{
FaceEx * face = gm->GetFace(f);
// use data here
}

9
3ds max Game Export Interface Programming Guide

IGameMesh also provides access to Face data based on smoothing groups. For
any particular smoothing group a list of faces can be returned. This also goes for
faces on a per Material ID basis, with material lookup into the global material list
based on the Material ID from the face. This type of access is important for
realtime display of the data as hardware has no concept of a multi-material, so the
mesh needs to be split up into smaller chunks based on the material at the face.
This is described further in the Appendix.

Any mapping data found on the object is collected and stored. The user simply
queries which channels have data, and then accesss them in a similar way to other
data channels. Typically the user would call GetMapFace() and
GetMapFaceIndex() to access all the data.

//gm is a pointer to IGameMesh


if(exportMappingChannel)
{
Tab<int> mapNums = gm->GetActiveMapChannelNum();
int mapCount = mapNums.Count();

for(int i=0;i < mapCount;i++)


{

int vCount = gm->GetNumberOfMapVerts(mapNums[i]);


buf.printf("%d",vCount);
for(int j=0;j<vCount;j++)
{
vert = NULL;
Point3 v;
if(gm->GetMapVertex(mapNums[i],j,v))
{
//use data here
}

}
int fCount = gm->GetNumberOfFaces();

for(int k=0;k<fCount;k++)
{
DWORD v[3];
gm->GetMapFaceIndex(mapNums[i],k,v);
//use data here
}

IGameSpline
Any spline-based IGameObject can be converted to an IGameSpline object. This
Object acts as a container for the actual spline data, which is represented as one or

10
3ds max Game Export Interface Programming Guide

multiple IGameSpline3D objects, depending on how many splines the original 3ds
max spline was made up of.

The knot and tangent data is stored within the IGameSpline3d Object. Along with
basic knot data, IGameSpline3D will also store the animation of any knot or tangent
handle.

The diagram below examines the relationship of the IGameSpline container Object
to the IGameSpline3D Objects it contains.

IGameSpline

IGameSpline3D

Splines are also used in conjunction with Constraints for path based animation, so
they could commonly be exported as part of the Constraint data.

IGameIKChain
IGameIKChain provides direct access to an Inverse kinematic (IK) chain. This
means that character could be exported based on its IK setup. Each IK chain is
made up of a set of linked nodes. These nodes are then under the control of the
end effector running in either IK or Forward Kinematic (FK) mode. This mode is
determined by an On/Off controller which can be accessed through IGameIKChain
interface.

11
3ds max Game Export Interface Programming Guide

Nodes in
Chain

IK Chain

End Effector

When the IK is enabled the IGameControl retrieved from the IGameNode will be the
controller for the end effector. When IK is disabled, the Forward kinematics can be
calculated by the IGameController’s from the nodes making up the IK chain. Along
with the IK Enabled controller, direct access to the Swivel angle data is provided as
an IGameProperty.

IGameCamera and IGameLight


All Light and Camera properties are exported as an IGameProperty. This includes
any animated light objects and multiplier data as well as any include/exclude data
for lights. All 3ds max lights and cameras are exported via this interface, they
“share” the common data. The light and camera types along with the nodes for the
targets are also supported.

IGameSupportObject
Any Helper objects, including Bones, are wrapped as IGameSupportObjects. This
is a very simple interface that mostly provides access to the main
IPropertyContainer interface. However, additional access to the Helper’s geometry
is provided through an IGameMesh pointer maintained by the IGameSupportObject.

12
3ds max Game Export Interface Programming Guide

IGameGenObject
Any object unknown to the game inerface is wrapped as an IGameGenObject. The
only available access is to the basic properties of the Object. Access to Object
properties is explained in the following Chapter.

Modifiers
The modifier stack in 3ds max can be very daunting, and can become especially
confusing from within the API. The danger is that the developer can access the
data without really understanding it, with the potential of leaving the stack unstable.
This not only means that it is harder for a developer to fix bugs, but even harder to
extend functionality beyond that of sample code because of the lack of
understanding.

3ds max Game Export Interface provides direct access to modifiers via the
IGameObject interface with no knowledge of Derived Objects or internal workings
needed. IGameObject maintains a list of all the modifiers applied to the object with
access to both the name used in the stack and the internal name, so the developer
can simply determine if the modifier is needed.

As an extension to this, IGameModifier directly supports the skin deformation


modifiers of “max skin” and “physique”. Even though both modifiers provide their
own APIs, both are different. IGame provides a unified access to both skin
modifiers, by using the method IGameModifier::IsSkin() the developer can
then cast to IGameSkin for direct access of weights and bone bindings.

IGameModifier still provides access to the original 3ds max modifier as some data
is user defined in such a way that IGame can not extract it. This is usually in the
form of LocalModData or Per Face Data, and hence must be accessed directly by
the developer who wrote it.

int numMod = igameObj->GetNumModifiers();


if(numMod > 0)
{
for(int i=0;i<numMod;i++)
{
IGameModifier * m = igameObj->GetIGameModifier(i);
// access data here........
}
}

The IGameModifier interface also provides a list of all the nodes that are affected by
the modifier, so on export you can choose to export nodes based on modifiers,
such as Physique.

13
3ds max Game Export Interface Programming Guide

Controllers
IGameControl provides direct access to all the standard key frame controllers in
3ds max. This is particularly beneficial to game developers, as they know what
type of controller they are exporting as it is defined by their game engine.

To do this in the standard 3ds max API would require asking for the position
controller, checking to see if it had the required Key interface, and then extracting
the key based on the control type. 3ds max Game Export Interface handles this
automatically, allowing the developer to simply request a list of all Bezier position
keys for export. Again, this level of abstraction means that data can be accessed
quickly without detailed knowledge of the 3ds max internals.

Along with the basic Key frame controllers, IGameControl can also sample a
controller. This is important for certain controllers that do not support the Key
interfaces, such as Biped. Each IGameControl interface maintains a control type
which allows the developer to find out what type of controller IGameControl has
stored it as, based on the transform style. For example, if the Control is an
Unsupported controller or Biped, then the developer can sample it at the required
rate. IGame provides two types of sampling, Full and Quick. Full will sample the
animation over the entire animation range at the specified sampling rate set by the
developer. Quick will only sample the controller where a key exists. This has
limitations in that it will not work for IGAME_TM sampling or controllers that do not
support key setting.

To ease programming logic, all IGameControl Get[…]Keys() methods return a


success flag as a boolean.

This allows for a simple iteration through all the key methods. Thus if all return
false, no keys were found, and then sampling can be requested.

Please see the table below for a list of IGameController Types and their associated
meanings. This table is also viewable in the Appendix.

IGame Controller Type Max Controller


IGAME_UNKNOWN Procedural Controller / 3rd Party
IGAME_MAXSTD Linear, TCB, Bezier
IGAME_BIPED Biped Controller
IGAME_ROT_CONSTRAINT Orientation and Look At Constraint
IGAME_POS_CONSTRAINT Path and Position Constraint.
IGAME_LINK_CONSTRAINT A Matrix3 TM constraint
IGAME_LIST A List Controller

Constraints are also supported directly by IGameControl. Like the skin access, all
Constraints are supported through a unified interface. The Constraint is identified
as a Controller type; if found, the developer simply needs to get the Constraint

14
3ds max Game Export Interface Programming Guide

interface for that particular controller type. The following code sample shows this in
action.

if(exportControllers)
{
IGameKeyTab posKeys,rotKeys,
IGameControl * pGC = node->GetIGameControl();
DWORD T = pGC->GetControlType(IGAME_POS);
//position
if(T==IGAME_MAXSTD && pGC->GetBezierKeys(poskeys,IGAME_POS))
DumpBezierKeys(IGAME_POS,poskeys,prsNode);

else if(T==IGAME_POS_CONSTRAINT && !forceSample)


{
IGameConstraint * cnst = pGC->GetConstraint(IGAME_POS);
DumpConstraints(prsNode,cnst);
}

//rotation
else if(T==IGAME_MAXSTD && pGC->GetTCBKeys(rotkeys,IGAME_ROT)
{
DumpTCBKeys(IGAME_ROT,rotkeys,prsNode);
}

else if(T==IGAME_ROT_CONSTRAINT && !forceSample)


{
IGameConstraint * cnst = pGC->GetConstraint(IGAME_ROT);
DumpConstraints(prsNode,cnst);
}

else
DumpSampleKeys(child,prsNode); // usually Biped
}
}

IGameKey
Every key extracted is stored in a simple storage class that maintains a list for all
the Key types: Bezier, TCB, Linear and Sampled. See the Appendix for Class
information on IGameKey.

The data is accessed depending on the controller type. The code sample below
retrieves all the Bezier Keys for Position:

IGameKeyTab BezKeys;
If(pGC->GetBezierKeys(BezKeys,IGAME_POS))
{
for(int i = 0;i<BezKeys.Count();i++)
{
if(Type==IGAME_POS || Type==IGAME_POINT3)
{
Point3 k = BezKeys[i].bezierKey.pval;
//use data here
}

15
3ds max Game Export Interface Programming Guide

}
}

As this sample is interested in Bezier Position data, the GetBezierKeys()


method is used with the IGAME_POS flag. If successful, BezKeys will contain a list
of keys from which access the bezierKey member is available. This list is
maintained by IGameKey.

Materials and Textures


Materials are stored globally as IGameMaterial, with each node providing an index
into this global array. The Standard Max material (StdMtl2) is directly supported
with methods for getting the basic material data such as Ambient and Diffuse
colour, Glossiness and Opacity. Any other material found will provide access to the
IPropertyContainer so that Parameter extraction is possible. In these cases it is
best to use the xml property file, described in the following chapter, to define a
custom set of access APIs.

The Multi Material is supported, with access to the sub materials and the Material
ID being used on the SubObject level. Materials also provide access to any texture
that is used, with direct support for Bitmap Textures. All of the properties of Bitmap
Textures, including clipping data, are supported.

// mat is a pointer to an IGameMaterial


TSTR buf;
int texCount = mat->GetNumberOfTextureMaps();

for(int i=0;i<texCount;i++)
{
IGameTextureMap * tex = mat->GetIGameTextureMap(i);
TCHAR * name = tex->GetTextureName();
if(tex->IsEntitySupported()) //its a bitmap texture
{
IGameProperty * prop = tex->GetClipHData();
DumpProperties(bitmapTexture,prop);

prop = tex->GetClipUData();
DumpProperties(bitmapTexture,prop);

prop = tex->GetClipVData();
DumpProperties(bitmapTexture,prop);

prop = tex->GetClipWData();
DumpProperties(bitmapTexture,prop);

16
3ds max Game Export Interface Programming Guide

Textures also provide access to the Coordinate rollout data used by textures to
handle transformations. Either the complete transform or the individual elements
that make up the transform can be accessed.

Supporting Parameter Blocks and User Defined Data


Parameter blocks, or ParamBlocks, are a central part of programming in 3ds
max:

In 3ds max, almost all parameters are registered as ParamBlocks. This enables
developers to leave the UI and data handling to the core application. For example,
much of the editable data in TrackView is driven by the ParamBlock system.

The example below demonstrates the power of accessing the same paramblock
from different locations. In this case, even though the data was intended to be
displayed in the modifier dialog, TrackView has direct access to that modifier’s
parameters by accessing its ParamBlock.

Parameters
hosted in a
Paramblock

When programming for IGame, ParamBlock properties are retrieved via the
IPropertyContainer interface:

Each IExportEntity stored in the game export interface database supports


IPropertyContainer. This interface is responsible for actually finding the properties
on the Entity - it will loop through all the various places where ParamBlocks can be
stored, gathering Custom Object Data and Custom Attributes, if applicable.
Developers should request this interface if they want to export any plug-in specific
parameters.

17
3ds max Game Export Interface Programming Guide

IGameGenObjects also support IPropertyContainer, permitting access to properties


of 3ds max objects unknown to the game interfaces.

IGameScene does provide two slightly different ways to extract parameters


from ParamBlocks maintained by plugins, or IGameObjects:

1. XML Defined
This method allows the developer to extract Custom Attributes, Custom
Object Data, and developer-defined plug-in data directly and without
enumeration.

2. Simple Enumeration
This method allows direct handling of the ParamBlock, including read/write,
and is also the quickest way to enumerate through all of the properties of the
various entities.

Both of these methods will supply the desired parameter data wrapped as an
IGameProperty. Which method to follow depends on the level of control and the
amount of data to extract.

For example, the XML Defined route will supply all paramblock parameters, as well
as Custom Attributes and Custom Object Data that is assigned in the Object
Properties dialog of a 3ds max object. Custom Attributes are also supported via
this route. Developers can specify the name of the file to be used when initialising
the game export interfaces, thus allowing game-specific data to be maintained.

XML Defined
To allow for customisation and support for unknown properties the export interface
uses a Properties file. This is an XML file in which the developer describes the
parameters that need to be extracted. The benefit of using this system is that new
properties can be added without IGame having to be updated to explicitly support
them. A full description of the IGameProp.xml file can be found in the Appendix.

The format of the XML is very simple and can be hand edited. However, an IGame
Property Editor utility is available to add new Properties and Custom data in a
failsafe way. The data stored provides enough information about the property so
that IGame can extract it from the original ParamBlock. The XML file also stores a
unique identifier for the parameter which can be used in the querying of the
parameter from the IPropertyContainer interface. This also means that the
developer can create his own API to extract properties that perhaps performs some
extra validation. An example of the XML Property Definition file can be seen in the
following below.

18
3ds max Game Export Interface Programming Guide

- <ExportEntity>
- <!--
StdMat2 Properties
-->
<simplename>StdMat2</simplename>
<classid>0x0000002,0</classid>
<shared>false</shared>
- <Property>
<id>1</id>
<simplename>Ambient</simplename>
<name>ambient</name>
<type>point3</type>
<paramblock2>true</paramblock2>
</Property>
- <Property>
<id>2</id>
<simplename>Diffuse</simplename>
<name>diffuse</name>
<type>point3</type>
<paramblock2>true</paramblock2>
</Property>
- </ExportEntity>

Upon initialisation, IGameScene will load this file and parse matching entities
against it during scene traversal. It makes a match based on the ClassID of the
node and the SubAnimName for IParamBlock or the internal name stored in the
ParamBlockDesc2 for IParamBlock2 (shown red in the source below).

static ParamBlockDesc2 aniso_param_blk ( aniso_params,


_T("shaderParameters"), 0, &anisoCD, P_AUTO_CONSTRUCT, 0,
// params
an_ambient, _T("ambient"), TYPE_RGBA, P_ANIMATABLE, IDS_AMBIENT,
p_default, Color(0, 0, 0),
end,
an_diffuse, _T("diffuse"), TYPE_RGBA, P_ANIMATABLE, IDS_DIFFUSE,
p_default, Color(0.5f, 0.5f, 0.5f),
end,

The developer can then either Query the property by name or ID.

Given a pointer to an IPropertyContainer interface a developer could write a


wrapper function as follows.

IPropertyContainer * pc = entity-> GetIPropertyContainer ();


IGameProperty * prop = pc->QueryProperties(_T(“Ambient”));

Or

#define AMBIENT 1
IGameProperty * prop = pc->QueryProperties(AMBIENT);

19
3ds max Game Export Interface Programming Guide

Using the IGame Property Editor tool will allow you to save out an include file with
all the IDs represented as #defines. Many of the methods in game export interface
are simply wrappers around parameters, and are implemented in the exact same
way. The actual IDs are created by the editor and some defines are not
changeable as the internal code will uses them for their own lookup. This includes
Materials, BitmapTextures and both lights and cameras.

Another important aspect of the XML based extraction is that Custom Object data
can be exported and represented as an IGameProperty. Once the data is defined,
it can be accessed in the exact same way as any other property.

Custom Object data is defined a little differently than ParamBlock properties as can
be seen in the following listing

- <ExportUserData>
- <!--
Access to the Node User Data
- <!--
The id must be unique to the file

- <UserProperty>
<id>101</id>
<simplename>IGameTestString</simplename>
<keyName>IGameTestString</keyName>
<type>string</type>
</UserProperty>
</ExportUserData>

Note that the only difference between an IGameProperty object returning a User
Property is that the controller interface will be NULL.

20
3ds max Game Export Interface Programming Guide

Simple Enumeration

Any ExportEntity can have its parameters enumerated. The developer simply
registers a callback for the IPropertyContainer to use, and then every ParamBlock-
based parameter found will be returned to the developer via the callback.

The DumpProperty sample uses this technique to export the names of every
property found on an object. This includes modifiers, materials or anything that
supports the IPropertyContainer interface. The following code sample shows how
to setup the callback.

class MyProc : public PropertyEnum


{
DumpProperties * dp;

public:

MyProc(DumpProperties * d) {dp = d;}

bool Proc(IGameProperty * prop)


{
TCHAR Buf[256];
_tcscpy(Buf,prop->GetName());

// if it is null, this is usually because its a IParamBlock and it is //


not animated, thus No name
if(_tcscmp(Buf, _T(""))!=0){
//use the Property here
}
return false; //lets keep going
}
};

The callback is set using the following code where material is a pointer to an
IGameMaterial object.

IPropertyContainer *pCont = material->GetIPropertyContainer();


MyProc * proccy = new MyProc(this);
pCont->EnumerateProperties(proccy);

This method will provide access to every parameter that was found during the
initialisation process. The technique is useful if you want to get access to the
underlying ParamBlock for any parameter and thus provide read and write access
to the data. This is also the quickest way to get all the parameters from the various
entities. The developer is responsible for accessing the ParamBlock in the correct
manner using the original 3ds max API if they decide to use the kind of low level
access.

21
3ds max Game Export Interface Programming Guide

Error Reporting
The game export interface uses a standard “GetLastError” technique, similar to the
windows API to provide diagnostic feedback. Most IGame functions will set a
global error which can be checked for from the calling code. Detailed error text is
also available to describe what might have happened. This approach allows the
developer to decide how much error checking is performed in their own code. For
example using GetLastIGameError could result in IG_NODE_NOT_FOUND being
returned, using GetLastIGameErrorText would yield “No Target Node found”
thus suggesting that the developer requested the target node for a non target-
based light or camera.

There is also a Callback that can be registered, so that you are notified of any Error
that may occur. This event is fired when the global error is set so it could be
trapped before the calling method at fault has actually returned. This method is a
convenient way to provide a full diagnostic dump for the user after an export has
been completed.

class MyErrorProc : public IGameErrorCallBack


{
public:
void ErrorProc(IGameError error)
{
TCHAR * buf = GetLastIGameErrorText();
DebugPrint("ErrorCode = %d ErrorText = %s\n", error,buf);
}
};

MyErrorProc pErrorProc;
SetErrorCallBack(&pErrorProc);

Existing Code Integration


In order to provide good flexibility, the game export interfaces needed to be able to
fit into existing pipelines and code. This has been achieved by providing access to
the original 3ds max container from all IGame interfaces.

IGame provides various initialisation options to make integration easier. The


IGameScene can be initialised by a single Node or a table of Nodes, depending on
the situation. In this way, a plug-in’s main node enumeration can be replaced with
an game interface equivalent, knowing that access to the original 3ds max object is
available.

22
3ds max Game Export Interface Programming Guide

for(int loop = 0; loop <pIgame->GetTopLevelNodeCount();loop++)


{
INode * pNode = pIgame->GetTopLevelNode(loop)->GetMaxNode();

//.. Carry on as before

Another possible route is to use the IGameObject directly. It has a public


constructor, so access to IGameObject interfaces plus modifiers can be
implemented this way. This is a simple route if access to skin modifiers or just
parameters is required.

Furthermore, the IGameSkin interface provides data access based on either


IGameNodes or the original 3ds max INode, which leaves open further integration.

23
3ds max Game Export Interface Programming Guide

Appendix

Pararameter Blocks

Parameter blocks, or ParamBlocks, are a central part of programming in 3ds


max:

In 3ds max, almost all parameters are registered as ParamBlocks. This enables
developers to leave the UI and data handling to the core application. For example,
much of the editable data in TrackView is driven by the ParamBlock system.

The example below demonstrates the power of accessing the same paramblock
from different locations. In this case, even though the data was intended to be
displayed in the modifier dialog, TrackView has direct access to that modifier’s
parameters by accessing its ParamBlock.

Parameters
hosted in a
Paramblock

One problem with this parameter storage mechanism is that the developer does not
know where to look for a particular item in the ParamBlock. This is not so much of
a problem with built-in plugins as the SDK does provide source code for a good
majority of plugins, but this can cause a problem for undocumented 3rd party
plugins. This problem is the cause for much confusion from developers and is
responsible for the number one 3ds max SDK web board question – “How do I get
XXX parameter from YYY object”. The game export interface provides access to all
this data along with a simple, property-based approach to handling 3rd party plugins.

It is not always clear how to get hold of a ParamBlock. Although there are max sdk
methods for paramblock retrieval, not all plugins decide to expose their plugins this

24
3ds max Game Export Interface Programming Guide

way. However, most paramblock are stored in the reference system. This again
brings the developer into contact of another complicated and often misunderstood
area of the max sdk. IGame however deals with this for the developer by checking
all places that could house a paramblock that is accessible from the out side. In
order to do this IGame loops all the references maintained by the plugin and looks
for the various SuperClassIDs for the IParamBlock and IParamBlock2. It will also
check nested Reference Targets to see if they contain any new paramblocks.

25
3ds max Game Export Interface Programming Guide

IGameProperty XML format.

To allow IGame to be as extendable as possible, new properties needed to be


supported. This would allow custom material or objects to be supported through a
standard interface. All the property access in IGame is defined through the
IGameProp.xml file. A method that returns an IGameProperty will have an entry in
this file. The only difference is that IGame “knows” about some of these and has
provided a simple wrapper around the retrieval of the property. For any other
properties a developer can use the unique ID to perform a lookup into the
properties maintained by the Export Entity.

File syntax

<?xml version="1.0" encoding="utf-8" ?>


- <!--
Property file for use with the IGame exporter
-->
- <!--
To use the IGame exposed APIs please do not change the IDs of the
properties defined below. They are used to query the Property
Container
and some methods use this to provide a wrapper around this.

The ID in each Property is not an index into the ParamBlock but


is
a unique identifier used in various lookups
-->
- <IGameProperties>
- <ExportEntity>
- <!--
StdMat2 Properties
-->
<simplename>StdMat2</simplename>
<classid>0x0000002,0</classid>
<shared>false</shared>
- <Property>
<id>1</id>
<simplename>Ambient</simplename>
<name>ambient</name>
<type>point3</type>
<paramblock2>true</paramblock2>
</Property>
- <Property>
<id>2</id>
<simplename>Diffuse</simplename>
<name>diffuse</name>
<type>point3</type>
<paramblock2>true</paramblock2>
</Property>
- </ExportEntity>
- <ExportUserData>
- <!--

26
3ds max Game Export Interface Programming Guide

Access to the Node User Data


- <!--
The id must be unique to the file

- <UserProperty>
<id>101</id>
<simplename>IGameTestString</simplename>
<keyName>IGameTestString</keyName>
<type>string</type>
</UserProperty>
</ExportUserData>
</IGameProperties>

Export Entities syntax


Each Export Entity to be supported in IGame must have an - <ExportEntity>
section. This defines the parent and whether the property is shared.

<simplename> A field that can be used for a more detailed description of the
ExportEntity. This field has no relevance to IGame and is used
only to more easily identify an ExportEntity while editing/examining
the IGameProp.xml file.

<classid> This is the ClassID of the owner of the ParamBlock

<shared> This tells IGame whether the Property is Shared or not. An


example of a Shared property is Lights. There are many different
lights but the all share common properties. In this case the classid
is the “SuperClassID” of the group.

Each Property is contained in a <Property> block. This is the data that is used to
lookup into the Paramblock

<id> The unique ID for the Parameter. This is only needs to be unique
for the properties in an <ExportEntity> block

<simplename> A field that can be used for a more detailed description of the
Property. This field has no relevance to IGame and is used only to
more easily identify a Property while editing/examining the
IGameProp.xml file.

<name> The name of the parameter. For IParamBlock, this is the


SubAnimName, for IParamBlock2, this is the internal name

<type> The ParamBlock type – currently float, point3, int and string
are supported

<paramblock2> Whether this property is a ParamBock2 or not.

27
3ds max Game Export Interface Programming Guide

Export User Data syntax


Every node in max can have user data added to it via the object properties dialog
box. IGame can extract this data as an IGameProperty. It uses the data found in
the <ExportUserData> field to correctly extract the data found. Each piece of user
data is contained in a <UserProperty>

<id> The unique ID for the Parameter. This is has to be unique to the file

<simplename> A field that can be used for a more detailed description of the
UserProperty. This field has no relevance to IGame and is used only
to more easily identify a UserProperty while editing/examining the
IGameProp.xml file.

<keyName> The name of data chunk. This can not contain spaces

<type> The data type, User data supports int, float, bool and string

IGameObject Interfaces
IGameObject Types with their associated interfaces.

IGame Object Type IGame Interface


IGAME_UNKNOWN IGameGenObject
IGAME_LIGHT IGameLight
IGAME_MESH IGameMesh
IGAME_SPLINE IGameSpline
IGAME_CAMERA IGameCamera
IGAME_HELPER IGameHelperObject
IGAME_BONE IGameHelperObject
IGAME_IKCHAIN IGameIKChain

28
3ds max Game Export Interface Programming Guide

3ds max Mesh Representation

The following set of diagrams aims to show the basic 3ds max mesh at a very high
level. This information will help when exporting data from IGame.

Figure 1 Box with face and Vertex visible

Figure 1 shows a very basic box, but this is actually a complex object. You can
clearly see the faces and the vertices but what you do not see are the normals. As
a box has hard edges it is important that the faces on either side of the edge have
normals that are 90 degrees apart. This allows the lighting to be calculated
correctly. Thus a Box will actually have 3 Normals, one for each face connected to
it. This data and the normal lookup are handled with smoothing groups inside 3ds
max. It is important that this is handled correctly and the correct normal for the face
based on the smoothing group is calculated. Figures 2 and 3 show this working in
the viewport.

Figure 2 Unique normals per face

29
3ds max Game Export Interface Programming Guide

The three normals in blue can clearly be seen at each vertex, providing hard edges
visible in the box on the right. If the faces around one of the vertices were allowed
to share a normal, this is in the same smoothing group and very different rendering
would be produced

Figure 3 Shared Vertex Normal

You can see the shared normal in red (top right front) and obviously you lose the
sharp edges around this vertex which is apparent from the image on the right.

Each face is also capable of having multiple Material IDs. This allows a face to
have different textures than that of a connecting face. In 3ds max this is achieved
by applying a Multi\SubObject material, where the materials are applied to the
matching Material ID on the face. A multi\Subobject material is created
automatically if the user “drag n drops” a material onto a selected face. Each face
that receives a material will have its Material ID updated and the new multi material
will be updated to reflect that. This again is important to understand, as this kind of
setup requires that each face with unique Material ID is rendered (interactively)
separately to the others. The mesh is quite simply broken up and drawn as
separate meshes each with its own material. IGame does provide ability to export
faces based on either smoothing groups or Material IDs.

30
3ds max Game Export Interface Programming Guide

Figure 4 A multi Textured Box

31
3ds max Game Export Interface Programming Guide

IGameKey Definition

//! class IGameTCBKey


/*! A generic TCB key class for IGame
*/
class IGameTCBKey {
public:
//! access to basic TCB data
float tens, cont, bias, easeIn, easeOut;
//! float based value, used with IGAME_FLOAT
float fval;
//! Point3 based value, used iwth IGAME_POINT3 | IGAME_POS
Point3 pval;
//! Angle Axis based value where quarternions can be
extracted, used with IGAME_ROT
AngAxis aval;
//! ScaleValue based value, used with IGAME_SCALE
ScaleValue sval;
};

//! class IGameBezierKey


/*! A generic Bezier Key class for IGame
*/
class IGameBezierKey {
public:
//! float based In and out tangents, used with IGAME_FLOAT
float fintan, fouttan;

//! float value, used with IGAME_FLOAT


float fval;
//! float based tangent lengths used with IGAME_FLOAT
float finLength, foutLength;

//! Point3 based In and out tangents, used with IGAME_POINT3 |


IGAME_POS
Point3 pintan, pouttan;

//! Point3 value, used with IGAME_POINT3 | IGAME_POS


Point3 pval;
//! Point3 based tangent lengths used with IGAME_POINT3 |
IGAME_POS
Point3 pinLength, poutLength;
//! Quaternion based value, used with IGAME_ROT
Quat qval;
//! ScaleValue , used with IGAME_SCALE
ScaleValue sval;

};

//! class IGameLinearKey


/*! A generic Linear Key class for IGame
*/
class IGameLinearKey {
public:
//! float based value, using IGAME_FLOAT
float fval;
//! Point3 based value, using IGAME_POS |IGAME_POINT3
Point3 pval;
//! Quaternion based value, using IGAME_ROT

32
3ds max Game Export Interface Programming Guide

Quat qval;
//!Scale value, using IGAME_SCALE
ScaleValue sval;
};

//! class IGameSampleKey


/*! A generic Sample Key class for IGame. This is used for unkown
controllers or controllers that
simply need to be sampled, this can includes Biped
*/
class IGameSampleKey{
public:
//! Point3 value, used with IGAME_POINT3 and IGAME_POS
Point3 pval;
//! float value, used with IGAME_FLOAR
float fval;
//! Quaternion value, used with IGAME_ROT
Quat qval;
//! Scale value, used with IGAME_SCALE
ScaleValue sval;
//! GMatrix, used with IGAME_TM
GMatrix gval;

};

//!class IGameKey
/*! A simple container class for direct Key access of all the available
Key types

*/
class IGameKey
{
public:
//! The time the key was set
TimeValue t;
//! Flags various selection states for the key.
DWORD flags;
//!The TCB Keys
IGameTCBKey tcbKey;
//!The Bezier keys
IGameBezierKey bezierKey;
//!The linear keys
IGameLinearKey linearKey;
//!The sampled keys
IGameSampleKey sampleKey;
};

33
3ds max Game Export Interface Programming Guide

Object Properties

The property manager allows the extraction of Object Properties (referenced as


node properties in the max sdk). It supports this through the XML properties file
allowing the developer to provide a definition of the data stored on the object. Data
types supported are INT, BOOL, FLOAT, and STRING.

The user can add this data from within max, by right clicking on an object and
selecting Properties from the Quad Menu. The following windows dialog window
will be displayed.

The user would then simply type in a key, followed by “=” then the data. The key
must not contain a space character.

34
3ds max Game Export Interface Programming Guide

In the xml file the developer would add the following entry, so that the Property
Manager could parse the data and provide access to it via the IGameProperty
interface.
- <ExportUserData>
- <!--
Access to the Node User Data
- <!--
The id must be unique to the file

- <UserProperty>
<id>101</id>
<simplename>IGameTestString</simplename>
<keyName>string</keyName>
<type>string</type>
</UserProperty>
- <UserProperty>
<id>102</id>
<simplename>IGameTestInt</simplename>
<keyName>int</keyName>
<type>int</type>
</UserProperty>
- <UserProperty>
<id>103</id>
<simplename>IGameTestFLoat</simplename>
<keyName>float</keyName>
<type>float</type>
</UserProperty>
- <UserProperty>
<id>104</id>
<simplename>IGameTestBool</simplename>
<keyName>bool</keyName>
<type>bool</type>
</UserProperty>
</ExportUserData>

35

You might also like