3ds Max Data Exchange
Interface (3DXI)
and COLLADA
Bernard Lefebvre
AUTODESK - Media and Entertainment
Dev. Tech. Support
 3DXI
– High Level API for 3ds Max SDK
Overview
Goals and Targets

Interface Scope Overview
 Flexibility and Customization

 COLLADA
- Digital Asset Exchange
Schema
Goals and Guidelines
 Library types

 3DXI
in COLLADA Export plug-in
How things work together
 Data round-trip demonstration

3DXI - High Level API
for 3ds Max SDK
3DXI: Goals and Targets

3DXI (formerly known as IGame) was
introduced as a set of interfaces for
rapid data extraction

Dual target


Allow novice 3ds Max developers to extract data with
minimal effort
Allow for the gradual adoption of 3DXI within existing
pipelines
3DXI: Goals and Targets

M&E is devoting R&D resources to
maintain and expand 3DXI

Short term goal:


Mid term goal:


Complete the set of entities exposed when parsing
the scene graph
Incorporate import capabilities to the API
Long term goal:

Become a standard API for data exchange in and
out of 3ds Max
3DXI: Interface Scope Overview
 Provides
unified Scene traversal and
Object enumeration
 Well
defined data containers for top level
Nodes and Materials interfaces with list of
their children
class IGameScene{
virtual bool InitialiseIGame(bool selected = false)=0;
};
3DXI: Interface Scope Overview
 Built-in
Conversion System
 Coordinate
System Conversions (3ds
Max, OpenGL, DirectX, custom)
IGameConversionManager * cm = GetConversionManager();
cm->SetCoordSystem(IGameConversionManager::IGAME_D3D);
3DXI: Interface Scope Overview
 Access
to 3ds Max elements
 Geometry,
Spline, Lights and Cameras,
Helper Objects
 Modifiers,
Skin Deformers, Materials,
Textures (including Bitmap)
 Controllers,
 Object

Constraints, IK Chain, Bipeds
Parameter Containers
Paramblocks, Custom Attributes, MXS plugins,
Custom Node Data
3DXI: Interface Scope Overview
 Mesh Access
 All
Vertex Colors, Alpha, Illumination, Normals,
Texture Coordinates, Binormals, and Tangents
are accessed directly
 Vertex normals calculated based on the
smoothing group of the face
 Support for Mesh and MNMesh (N-sided
polygons)
3DXI: Interface Scope Overview
 Animation
 Access
to TCB, Euler Controllers, Constraints
and Biped systems
 Option for key sampling for parametric
controllers
3DXI: Interface Scope Overview
 DirectX
Effects
DirectX
9 Shader Material
supported directly via
IGameMaterial
3DXI: Interface Scope Overview
– main interface to D3D effect,
compliant with HLSL COLLADA FX (1.4.0)
IGameFX
– interface for individual
parameter (property), can be extracted to
general IGameProperty
 IGameFXTechnique – interface for technique
information
 IGameFXPass – interface for pass information
 IGameFXFunction – access to function’s data
 IGameFXProperty
3DXI: Interface Scope Overview
Graphical Class Hierarchy
IGameScene
IGameConstraint
IGameNode
IGameGenMod
IGameGenObject
IGameMorpher
IGameLight
IGameSkin
IGameCamera
IGameModifier
IGameControl
IGameKey
IGameObject
IGameIKChain
IExportEntity
IGameMaterial
IGameSpline
IGameTexture Map
IGameXRefObject
IGameUVGen
IGameSupportObject
IGameFX
IGameConversionManager
IPropertyContainer
IGameProperty
FaceEx
IGameMesh
3DXI: Interface Scope Overview
Code Example: Simplification
 Extracting
key frame data from controller (3ds
Max SDK):
Control * cont = node->GetTMController()->GetPositionController()
if (!cont)
return;
IKeyControl * ikc = GetKeyControlInterface(cont);
// TCB point3
if (ikc && (cont->ClassID()== Class_ID(TCBINTERP_POINT3_CLASS_ID, 0)))
{
for (int i=0; i<ikc->GetNumKeys(); i++) {
ITCBPoint3Key key;
ikc->GetKey(i, &key);
// process data
}
}
3DXI: Interface Scope Overview
Code Example: Simplification

The same data in 3DXI can be extracted as:
IGameKeyTab poskeys;
IGameControl * gameControl = gameNode->GetIGameControl();
if (!gameControl) return;
gameControl->GetTCBKeys(poskeys,IGAME_POS));
// process data
3DXI: Flexibility and Customization
 Ability
to fit into existing plugins
 All
the major 3DXI classes provide access to the
underlying 3ds Max object:
INode * node = gameNode->GetMaxNode();
Object * obj = gameObject->GetMaxObject();
Mesh * mesh = gameMesh->GetMaxMesh();
Mtl* mat = gameMaterial->GetMaxMaterial();
 Conversion
from INode* to IGameNode*:
IGameNode * gameNode = GetIGameInterface()->GetIGameNode(node);
3DXI: Flexibility and Customization
 Object
properties are stored in
different containers

IParamBlock, IParamBlock2, Custom Attributes,
MXS plugins
 3DXI
collects all properties from
different 3ds Max containers
automatically
3DXI: Flexibility and Customization
 And
provides an interface to extract them
by index or by name (as the name known
to MAXScript)
IGameObject * obj = gameNode->GetIGameObject();
switch(obj->GetIGameType()){
case IGameObject::IGAME_LIGHT:
{
IGameLight * light = (IGameLight*)obj;
IGameProperty * prop =
GetIPropertyContainer()->QueryProperty(_T("color"));
Point3 pvalue;
if (prop) // property can be NULL, if name not found
prop->GetPropertyValue(pvalue);
}
}
3DXI: Flexibility and Customization
If you use User Defined Properties:

XML defined in IGameProp.xml
<ExportUserData>
<UserProperty>
<id>101</id>
<simplename>MyString</simplename>
<keyName>IGameTestString</keyName>
<type>string</type>
</UserProperty></ExportUserData>

Extract Custom Property
IGameObject * obj = gameNode->GetIGameObject();
IGameSupportObject * hO = (IGameSupportObject*)obj;
IPropertyContainer * cc = hO->GetIPropertyContainer();
IGameProperty * prop = cc->QueryProperty(101);
TCHAR * buf;
if(prop)
prop->GetPropertyValue(buf);
3DXI: Flexibility and Customization

Example of IGameProperty advantage for
lights:
Omni - is paramblock based
 Skylight – is paramblock2 based
 Mr_Area_Omni – is scripted plugin


A single way to access property:
IGameProperty * prop =
cc->QueryProperty(_T(“Multiplier"));
COLLADA
Digital Asset Exchange Schema
COLLADA: Goals and Guidelines

COLLADA - An open Digital
Asset Exchange (XML)
Schema for the interactive
3D industry




Driven by Sony Computer
Entertainment , Inc.
Current version is 1.4.0
https://collada.org
http://www.khronos.org/collada/
COLLADA: Goals and Guidelines
 COLLADA
is not a game engine format
 Goals:
 To
liberate digital assets from proprietary binary
formats into XML open-source format


No binary data within XML Shema
Flexibility and Scalability
 To
provide a standard common format for digital
content users

XML Schema, Specification, and API
 To
be a basis for common data exchange between
3D applications

User’s quote: “The days of game developers writing custom export plugins for modeling packages are, from what we've seen, over”
COLLADA 1.4
New features.

COLLADA FX


Cross-platform standard shader and effects definition
written in XML.
Targets:



High-end systems running OpenGL Shading Language
(GLSL) and Cg (HLSL coming),
Resource-constrained systems (OpenGL ES 1.x profile).
COLLADA Physics


Rigid Body Dynamics, Rag Dolls, Contraints, Collision
Volumes.
Enables data interchange between Ageia (Novodex),
Havok, Meqon, ODE and other game physics
middleware
COLLADA: Library types
library_animations, library_animation_clips
 library_geometries
 library_controllers
 library_nodes
 library_materials, library_images
 library_cameras, library_lights
 library_visual_scenes


library_effects
library_physics_models
 library_physics_materials, library_force_fields
 library_physics_scenes

COLLADA: Library types
Example of <animation> created by 3ds Max COLLADA exporter
<animation id="ColladaAnim.max_animation">
<animation id="Box01-Translate">
<source id="Box01-Translate-X-time">
<float_array id="Box01-Translate-X-time-array" count="2">0 3.333333</float_array>
<technique_common>
<accessor source="#Box01-Translate-X-time-array" count="2">
<param name="TIME" type="float"></param>
</accessor>
</technique_common>
</source>
<source id="Box01-Translate-X-value">
<float_array id="Box01-Translate-X-value-array" count="2">0 100.000000</float_array>
<technique_common>
<accessor source="#Box01-Translate-X-value-array" count="2">
<param name="TRANS.X" type="float"></param>
</accessor>
</technique_common>
</source>
COLLADA: Library types
Example of <animation> (Continue)
<source id="Box01-Translate-X-interp">
<Name_array id="Box01-Translate-X-interp-array" count="2">BEZIER BEZIER</Name_array>
<technique_common>
<accessor source="#Box01-Translate-X-interp-array" count="2"> <param name="TRANS.X"
type="Name"></param>
</accessor>
</technique_common>
</source>
<source id="Box01-Translate-X-intgt">
<float_array id="Box01-Translate-X-intgt-array" count="2">-0 -0</float_array>
<technique_common>
<accessor source="#Box01-Translate-X-intgt-array" count="2"> <param name="TRANS.X"
type="float"></param>
</accessor>
</technique_common>
</source>
<source id="Box01-Translate-X-outtgt">
<float_array id="Box01-Translate-X-outtgt-array" count="2">0 0</float_array>
<technique_common>
<accessor source="#Box01-Translate-X-outtgt-array" count="2">
<param name="TRANS.X" type="float"></param>
</accessor>
</technique_common>
</source>
COLLADA: Library types
Example of <animation> (Continue)










<sampler id="Box01-Translate-X-sampler">
<input semantic="INPUT" source="#Box01-Translate-X-time"></input>
<input semantic="OUTPUT" source="#Box01-Translate-X-value"></input>
<input semantic="INTERPOLATION" source="#Box01-Translate-X-interp"></input>
<input semantic="IN_TANGENT" source="#Box01-Translate-X-intgt"></input>
<input semantic="OUT_TANGENT" source="#Box01-Translate-X-outtgt"></input>
</sampler>
<channel source="#Box01-Translate-X-sampler" target="Box01/Trans.X"></channel>
</animation>
</animation>
COLLADA: Library types
Example of <mesh> element exported by 3ds Max COLLADA exporter
<geometry id="Box01-obj" name="Box01">
<mesh>
<source id="Box01-obj-position">
<float_array id="Box01-obj-position-array" count="24">-15.000000 -15.000000 0 15.000000 -15.000000 0
-15.000000 15.000000 0 15.000000 15.000000 0 -15.000000 -15.000000 30.000000 15.000000 -15.000000
30.000000 -15.000000 15.000000 30.000000 15.000000 15.000000 30.000000</float_array>
<technique_common>
<accessor source="#Box01-obj-position-array" count="8" stride="3">
<param name="X" type="float"></param> <param name="Y" type="float"></param>
<param name="Z" type="float"></param>
</accessor>
</technique_common>
</source>
<source id="Box01-obj-normal">
<float_array id="Box01-obj-normal-array" count="72">0 0 -1.000000 0 0 -1.000000 0 0 -1.000000 0 0
-1.000000 0 0 1.000000 0 0 1.000000 0 0 1.000000 0 0 1.000000 0 -1.000000 0 0 -1.000000 0 0 -1.000000 0 0
-1.000000 0 1.000000 0 0 1.000000 0 0 1.000000 0 0 1.000000 0 0 0 1.000000 0 0 1.000000 0 0 1.000000 0 0
1.000000 0 -1.000000 0 0 -1.000000 0 0 -1.000000 0 0 -1.000000 0 0</float_array>
<technique_common>
<accessor source="#Box01-obj-normal-array" count="24" stride="3">
<param name="X" type="float"></param> <param name="Y" type="float"></param>
<param name="Z" type="float"></param>
</accessor>
</technique_common>
</source>
COLLADA: Library types
Example of <mesh> (Continue)
<source id="Box01-obj-mapchan-1">
<float_array id="Box01-obj-mapchan-1-array" count="36">0 0 0 1.000000 0 0 0 1.000000 0 1.000000
1.000000 0 0 0 0 1.000000 0 0 0 1.000000 0 1.000000 1.000000 0 0 0 0 1.000000 0 0 0 1.000000 0 1.000000
1.000000 0</float_array>
<technique_common>
<accessor source="#Box01-obj-mapchan-1-array" count="12" stride="3">
<param name="S" type="float"></param> <param name="T" type="float"></param>
<param name="R" type="float"></param>
</accessor>
</technique_common>
</source>
<vertices id="Box01-obj-vertex">
<input semantic="POSITION" source="#Box01-obj-position"></input>
</vertices>
<polylist material="ColorMaterial_14782296" count="6">
<input semantic="VERTEX" source="#Box01-obj-vertex" offset="0"></input>
<input semantic="NORMAL" source="#Box01-obj-normal" offset="1"></input>
<input semantic="TEXCOORD" source="#Box01-obj-mapchan-1" offset="2" set="1"></input>
<vcount>4 4 4 4 4 4 </vcount>
<p>0 0 0 2 1 2 3 2 3 1 3 1 4 4 4 5 5 5 7 6 7 6 7 6 0 8 8 1 9 9 5 10 11 4 11 10 1 12 12 3 13 13 7 14 15 5 15 14 3
16 16 2 17 17 6 18 19 7 19 18 2 20 20 0 21 21 4 22 23 6 23 22 </p>
</polylist>
</mesh>
</geometry>
COLLADA: external references.
<library_visual_scenes>
<visual_scene id="Animation_max" name="Animation_max">
<node id="MyGeometry" sid="MyGeometry" name="MyGeometry">
<translate sid="Trans">3.01744 7.61249 0 </translate>
<rotate sid="RotZ">0 0 1 41.2879</rotate>
<rotate sid="RotY">0 1 0 -32.6151</rotate>
<rotate sid="RotX">1 0 0 -25.3289</rotate>
<instance_geometry url="./SourceGeometry.dae#MyGeometry-obj">
</instance_geometry>
</node>
</visual_scene>
</library_visual_scenes>
3DXI in COLLADA Export plug-in
3DXI for COLLADA

M&E is fully committed
to COLLADA

COLLADA Exporter
and Importer effort by
Feeling Software, Inc.
Personal thanks to
Guillaume Laforte

3ds Max Exchange
plugins for COLLADA
support version 1.4.0

For 3ds Max 7 and
3ds Max 8.

3DXI for COLLADA

3DXI in action

All code snippets are taken from 3ds Max COLLADA
exporter
//starting point
int ColladaExporter::DoExport(const TCHAR* name, ExpInterface* ei,
Interface* i, BOOL suppressPrompts, DWORD options)
{
IGameScene* pIgame = GetIGameInterface();
pIgame->InitialiseIGame(bool(options & SCENE_EXPORT_SELECTED));
}


Entire scene traversal happening here
All root nodes and materials (including their children) are
enumerated
3DXI for COLLADA

3DXI in action

All code snippets are taken from 3ds Max COLLADA exporter
//Create <material::effect> Library
IGameMaterial* mat = pIgame->GetRootMaterial(i); //for all scene mtls
IGameFX* gameFX = mat->GetIGameFX();
if(!gameFX) return;
//not a DX Material
const TCHAR* fxFilename = gameFX->GetEffectFileName();
int np = gameFX->GetNumberOfProperties();
for (int j = 0; j < np; j++){
IGameFXProperty* fxp = gameFX->GetIGameFXProperty(j);
IGameProperty* property = fxp->GetIGameProperty(); // access to IGameProperty
if (fxp->GetPropertyUsage() == IGameFXProperty::IGAMEFX_LIGHT)
IGameNode* lightNode = fxp->GetBindingNode(); // bound light node
}
int nt = gameFX->GetNumberOfTechniques(), i = 0;
do
{
IGameFXTechnique* fxTechnique = gameFX->GetIGameFXTechnique(i);
for (int j = 0; j < fxTechnique->GetNumberOfPasses(); j++)
IGameFXPass* pass = fxTechnique->GetIGameFXPass(j);
}
while (++i < nt);
3DXI for COLLADA
 3DXI
in action
 All
code snippets are taken from 3ds Max
COLLADA exporter
//extract Object data
IGameNode *node = pIgame->GetTopLevelNode(i); //for all scene nodes
IGameObject* object = node->GetIGameObject();
switch (object->GetIGameType())
{
case IGameObject::IGAME_LIGHT: AddLightObject(node, object); break;
case IGameObject::IGAME_CAMERA: AddCameraObject(node, object); break;
case IGameObject::IGAME_MESH: AddMeshObject(node, object); break;
}
 Object
properties are collected into
IGamePropertyContainer at this point.
3DXI for COLLADA

3DXI in action – Access Mesh

All code snippets are taken from 3ds Max COLLADA exporter
//export Mesh
IGameObject* object = node->GetIGameObject();
IGameMesh* mesh = (IGameMesh*) obj;
mesh->InitializeData();
// mesh vertex positions
for (int i = 0; i < mesh->GetNumberOfVerts(); i++){
Point3 vert;
mesh->GetVertex(i, vert, exporterOptions->ExportObjectSpace());
}
// mesh normals
for (int i = 0; i < mesh->GetNumberOfNormals(); i++){
Point3 n;
mesh->GetNormal(i,n, exporterOptions->ExportObjectSpace());
}
// mesh tangents and binormals for a channel
int chan = 1;
for (int i = 0; i < mesh->GetNumberOfTangents() ; i++){
Point3 t,b;
t = mesh->GetTangent(i,chan);
b = mesh->GetBinormal(i,chan);
}
// mesh texture vertices for a channel
for (int i = 0; i < mesh->GetNumberOfMapVerts(chan); i++){
Point3 tv;
mesh->GetMapVertex(chan, i, tv);
}

For mesh all data (vertices, normals, map channels, binrormals, etc)
collected/calculated. FaceEx* structure is stored per face basis
3DXI for COLLADA
Data round-trip demonstration
 Mesh model textured, skinned with animated
biped as a rig
3DXI Resources

http://beta.discreet.com

http://sparks.autodesk.com

https://collada.org/public_forum
 On
the DVD:
 3DXIHelp.chm
 3DXI
(maxsdk\help)
Headers (maxsdk\include\IGame)
 COLLADA
Exporter and Importer
(maxsdk\samples\Collada)
Questions ?
[email protected]
Descargar

GDC 2005