3ds_max_game_export_programming_guide.doc

44
3ds max Game Export Interface Programming Guide

Upload: aaaa66

Post on 24-Oct-2014

79 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: 3ds_max_game_export_programming_guide.doc

3ds max Game Export InterfaceProgramming Guide

Page 2: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

3ds max Game Export Interface.............................................................................1Programming Guide................................................................................................1Introduction.............................................................................................................3

3ds max Game Export Interface Overview............................................................3Programming with the 3ds max Game Export Interface......................................4

Initialising the Game Export Interfaces..................................................................5Extracting the Data................................................................................................6

IGameScene......................................................................................................6IGameNode........................................................................................................6IExportEntity.......................................................................................................7IGameObjects....................................................................................................7

IGameMesh....................................................................................................9IGameSpline.................................................................................................10IGameIKChain..............................................................................................11IGameCamera and IGameLight....................................................................12IGameSupportObject....................................................................................12IGameGenObject..........................................................................................13

Modifiers...........................................................................................................13Controllers........................................................................................................14

IGameKey.....................................................................................................15Materials and Textures.....................................................................................16

Supporting Parameter Blocks and User Defined Data.......................................17XML Defined........................................................................................................18Simple Enumeration............................................................................................21

Error Reporting......................................................................................................22Existing Code Integration.....................................................................................22Appendix................................................................................................................24

Pararameter Blocks.............................................................................................24IGameProperty XML format.................................................................................26

File syntax........................................................................................................26Export Entities syntax.......................................................................................27Export User Data syntax..................................................................................28

IGameObject Interfaces.......................................................................................283ds max Mesh Representation............................................................................29IGameKey Definition............................................................................................32Object Properties.................................................................................................34

2

Page 3: 3ds_max_game_export_programming_guide.doc

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 Cameras4. Controllers – including Euler, constraints and Biped5. IK Chains6. Skin deformers7. Materials8. Texture – including Bitmap Texture9. Custom Attributes10.Custom Node Data11. ParamBlocks

3

Page 4: 3ds_max_game_export_programming_guide.doc

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 point3if (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

Page 5: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

Initialising the Game Export InterfacesBefore 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 onlypIgame->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 Handed1, //X axis goes right4, //Y Axis goes in3, //Z Axis goes down.0, //U Tex axis is left1, //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

Page 6: 3ds_max_game_export_programming_guide.doc

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 pointerIGameScene * scene = pIgame->InitialiseIGame(interestingNodes,false);

Extracting the Data

IGameSceneThe 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.

IGameNodeThe 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

Page 7: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

//pIGame is an IGameScene pointervoid 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

Page 8: 3ds_max_game_export_programming_guide.doc

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.

IGameObjectsIGameNodes 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 pointerIGameObject * 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

Page 9: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

IGame Object Type IGame InterfaceIGAME_UNKNOWN IGameGenObjectIGAME_LIGHT IGameLightIGAME_MESH IGameMeshIGAME_SPLINE IGameSplineIGAME_CAMERA IGameCameraIGAME_HELPER IGameHelperObjectIGAME_BONE IGameHelperObjectIGAME_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

Page 10: 3ds_max_game_export_programming_guide.doc

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 IGameMeshif(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

Page 11: 3ds_max_game_export_programming_guide.doc

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.

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

IGameIKChainIGameIKChain 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

IGameSpline

IGameSpline3D

Page 12: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

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

Page 13: 3ds_max_game_export_programming_guide.doc

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.

ModifiersThe 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

Page 14: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

ControllersIGameControl 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 ControllerIGAME_UNKNOWN Procedural Controller / 3rd PartyIGAME_MAXSTD Linear, TCB, BezierIGAME_BIPED Biped ControllerIGAME_ROT_CONSTRAINT Orientation and Look At ConstraintIGAME_POS_CONSTRAINT Path and Position Constraint.IGAME_LINK_CONSTRAINT A Matrix3 TM constraintIGAME_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

Page 15: 3ds_max_game_export_programming_guide.doc

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);//positionif(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);

}

//rotationelse 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);

}

elseDumpSampleKeys(child,prsNode); // usually Biped

}}

IGameKeyEvery 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

Page 16: 3ds_max_game_export_programming_guide.doc

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 TexturesMaterials 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 IGameMaterialTSTR 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

Page 17: 3ds_max_game_export_programming_guide.doc

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.

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

Parameters hosted in a Paramblock

Page 18: 3ds_max_game_export_programming_guide.doc

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 DefinedTo 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

Page 19: 3ds_max_game_export_programming_guide.doc

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,

// paramsan_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 1IGameProperty * prop = pc->QueryProperties(AMBIENT);

19

Page 20: 3ds_max_game_export_programming_guide.doc

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

Page 21: 3ds_max_game_export_programming_guide.doc

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

Page 22: 3ds_max_game_export_programming_guide.doc

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

Page 23: 3ds_max_game_export_programming_guide.doc

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

Page 24: 3ds_max_game_export_programming_guide.doc

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.

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

Parameters hosted in a Paramblock

Page 25: 3ds_max_game_export_programming_guide.doc

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

Page 26: 3ds_max_game_export_programming_guide.doc

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 theproperties defined below. They are used to query the Property Containerand 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>

- <!-- Access to the Node User Data

26

Page 27: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

 - <!-- 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 syntaxEach 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

Page 28: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

Export User Data syntaxEvery 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 InterfacesIGameObject Types with their associated interfaces.

IGame Object Type IGame InterfaceIGAME_UNKNOWN IGameGenObjectIGAME_LIGHT IGameLightIGAME_MESH IGameMeshIGAME_SPLINE IGameSplineIGAME_CAMERA IGameCameraIGAME_HELPER IGameHelperObjectIGAME_BONE IGameHelperObjectIGAME_IKCHAIN IGameIKChain

28

Page 29: 3ds_max_game_export_programming_guide.doc

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

Page 30: 3ds_max_game_export_programming_guide.doc

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

Page 31: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

Figure 4 A multi Textured Box

31

Page 32: 3ds_max_game_export_programming_guide.doc

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 datafloat tens, cont, bias, easeIn, easeOut;//! float based value, used with IGAME_FLOATfloat fval;//! Point3 based value, used iwth IGAME_POINT3 | IGAME_POSPoint3 pval;//! Angle Axis based value where quarternions can be

extracted, used with IGAME_ROTAngAxis aval;//! ScaleValue based value, used with IGAME_SCALEScaleValue sval;

};

//! class IGameBezierKey/*! A generic Bezier Key class for IGame*/class IGameBezierKey {

public://! float based In and out tangents, used with IGAME_FLOATfloat fintan, fouttan;

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

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

Point3 pintan, pouttan;

//! Point3 value, used with IGAME_POINT3 | IGAME_POSPoint3 pval;//! Point3 based tangent lengths used with IGAME_POINT3 |

IGAME_POSPoint3 pinLength, poutLength;//! Quaternion based value, used with IGAME_ROTQuat qval;//! ScaleValue , used with IGAME_SCALEScaleValue sval;

};

//! class IGameLinearKey/*! A generic Linear Key class for IGame*/class IGameLinearKey {

public://! float based value, using IGAME_FLOATfloat fval;//! Point3 based value, using IGAME_POS |IGAME_POINT3Point3 pval;//! Quaternion based value, using IGAME_ROT

32

Page 33: 3ds_max_game_export_programming_guide.doc

3ds max Game Export Interface Programming Guide

Quat qval;//!Scale value, using IGAME_SCALEScaleValue sval;

};

//! class IGameSampleKey/*! A generic Sample Key class for IGame. This is used for unkown controllers or controllers thatsimply need to be sampled, this can includes Biped*/class IGameSampleKey{

public://! Point3 value, used with IGAME_POINT3 and IGAME_POSPoint3 pval;//! float value, used with IGAME_FLOARfloat fval;//! Quaternion value, used with IGAME_ROTQuat qval;//! Scale value, used with IGAME_SCALEScaleValue sval;//! GMatrix, used with IGAME_TMGMatrix 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 setTimeValue t;//! Flags various selection states for the key.DWORD flags;//!The TCB KeysIGameTCBKey tcbKey;//!The Bezier keysIGameBezierKey bezierKey;//!The linear keysIGameLinearKey linearKey;//!The sampled keysIGameSampleKey sampleKey;

};

33

Page 34: 3ds_max_game_export_programming_guide.doc

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

Page 35: 3ds_max_game_export_programming_guide.doc

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