After working a bit with the NVIDIA PhysX plugin the first question that came into my mind is how do i get my hands on all the scene data from inside the 3DS Max SDK. NVIDIA throws a hint regarding a interface static Interface_ID PX_INTERFACE_ID(0x4e0b7250, 0x16f70e0a) witch should permit access to the internal data. This seem easy at first so lest get into the code and see what happens :) .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Get our plugin interface
FPInterface* realInterface = GetCOREInterface(PX_INTERFACE_ID);
//Start enumerating all the wonders the plugin interface offers
FPInterfaceDesc* pxDesc = realInterface->GetDesc();
for (int j = 0; j < pxDesc->functions.Count(); ++j)
{
FPFunctionDef* fd = pxDesc->functions[j];
if (fd == NULL)
continue;
//read function info
for (int i = 0; i < fd->params.Count(); ++i)
{
//read function parameters
}
}
After a bit of parsing we get a nice list of functions:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/* ID[5] */int GetPhysXSDKVersion();
/* ID[6] */MCHAR* GetPhysXSDKVersionString();
/* ID[7] */int GetPhysXSDKVersionMajor();
/* ID[8] */int GetPhysXSDKVersionMinor();
/* ID[9] */int GetPhysXSDKVersionBugFix();
/* ID[10] */int GetApexSDKVersion();
/* ID[0] */int InitializePhysX(Value stream);
/* ID[1] */int CreateToolbar();
/* ID[2] */void ShowToolbar(BOOL show);
/* ID[12] */BOOL ShowValidateScene(BOOL automated);
/* ID[13] */BOOL HwAvailable();
/* ID[11] */int GetScreenHeight();
/* ID[14] */float GetSimulationFPS();
/* ID[15] */BOOL PrintSimulationFPS(BOOL onoff);
/* ID[32] */int AddRigidbody(INode* inode);
/* ID[33] */int AddConstraint(INode* node);
/* ID[34] */int AddDistanceJoint(INode* node);
/* ID[35] */BOOL CaptureInitTransform(INode* inode);
/* ID[38] */int SetRigidbodyShapeFlag(INode* inode,TSTR val flagname,BOOL value);
/* ID[36] */int RemoveRigidbody(INode* inode);
/* ID[37] */int RemoveAll();
/* ID[270] */int NotifyBeforeFirstFrame();
/* ID[28] */int ClearInvalidNodes();
/* ID[29] */int Simulate(float deltat);
/* ID[30] */int SetSimulationSubSteps(int numSteps);
/* ID[31] */int SimulationReset();
/* ID[134] */void SetSimulationState(int state);
/* ID[135] */int GetSimulationState();
/* ID[136] */BOOL IsSimulating();
/* ID[23] */int ExportPhysXScene(MCHAR* filename,MCHAR* extension);
/* ID[24] */int ExportPhysXProjectFile(MCHAR* physxProjectPath,MCHAR* physxProjectName);
/* ID[25] */int ExportPhysXProject(MCHAR* physxProjectPath,MCHAR* physxProjectName,MCHAR* fbxFileName);
/* ID[26] */int PrepExportPhysXScene(BOOL isexportphysx,MCHAR* extension);
/* ID[27] */int PrepExportAPEXClothing(BOOL exportAPEXClothing,MCHAR* apExtension,BOOL useModelSpace,float scale,BOOL addHulls,BOOL exportCTW,BOOL exportFBX,BOOL exportSelected,BOOL launchViewer,BOOL reverseWinding,BOOL omitMeshSubpartName);
/* ID[39] */Point3 ref GetLinearVelocity(INode* inode);
/* ID[40] */Point3 ref GetAngularVelocity(INode* inode);
/* ID[41] */int SetLinearVelocity(INode* inode,Point3 ref linearvelocity);
/* ID[42] */int SetAngularVelocity(INode* inode,Point3 ref angularvelocity);
/* ID[43] */Point3 ref GetGlobalPosition(INode* inode);
/* ID[44] */int SetGlobalPosition(INode* inode,Point3 ref position);
/* ID[45] */Matrix3 ref GetGlobalPose(INode* inode);
/* ID[46] */int SetGlobalPose(INode* inode,Matrix3 ref pose);
/* ID[47] */float GetMass(INode* inode);
/* ID[48] */float SetMass(INode* inode,float value);
/* ID[66] */float GetDynamicFriction(INode* inode);
/* ID[67] */float GetStaticFriction(INode* inode);
/* ID[68] */float GetRestitution(INode* inode);
/* ID[69] */int SetDynamicFriction(INode* inode,float value);
/* ID[70] */int SetStaticFriction(INode* inode,float value);
/* ID[71] */int SetRestitution(INode* inode,float value);
/* ID[72] */BOOL SaveMaterial(MCHAR* filename,float staticFriction,float dynamicFriction,float bounciness,int density);
/* ID[73] */float LoadMaterialDynFric(MCHAR* filename);
/* ID[74] */float LoadMaterialStaticFric(MCHAR* filename);
/* ID[75] */float LoadMaterialBounciness(MCHAR* filename);
/* ID[76] */int LoadMaterialDensity(MCHAR* filename);
/* ID[77] */INode* CreateBoundingBox(INode* inode);
/* ID[78] */INode* CreateBoundingSphere(INode* inode);
/* ID[79] */INode* CreateBoundingCapsule(INode* inode);
/* ID[80] */INode* CreateBoundingCapsuleFromPoints(Matrix3 poseTransform,Tab<float ref> points);
/* ID[81] */INode* CreateBoundingShapeConvex(INode* inode,int vertLimit,float inflation,int style);
/* ID[82] */Mesh CreateBoundingConvex(INode* inode,int vertLimit,float inflation);
/* ID[83] */Mesh CreateBoundingConvexFromNodes(Tab<INode* ref> inodes,int vertLimit,float inflation);
/* ID[84] */BOOL SetAsDynamic(INode* inode,BOOL onoff);
/* ID[85] */BOOL SetSleepState(INode* inode,BOOL onoff);
/* ID[86] */BOOL SetRBParam(INode* inode,MCHAR* paramName,MCHAR* paramValue);
/* ID[87] */MCHAR* GetRBParam(INode* inode,MCHAR* paramName);
/* ID[88] */BOOL SetRBShapeParam(INode* inodeRB,INode* inodeShape,MCHAR* paramName,MCHAR* paramValue);
/* ID[89] */BOOL GetRBShapeParam(INode* inodeRB,INode* inodeShape,MCHAR* paramName);
/* ID[90] */BOOL SetConstraintParam(INode* inode,MCHAR* paramName,MCHAR* paramValue);
/* ID[91] */BOOL GetConstraintParam(INode* inode,MCHAR* paramName);
/* ID[3] */int DebugPrint();
/* ID[4] */void DescribeMe();
/* ID[16] */int SetSDKParameter(TSTR val paramName,float value);
/* ID[17] */float GetSDKParameter(TSTR val paramName);
/* ID[18] */int SetSDKDefaultParameter(TSTR val paramName);
/* ID[50] */Mesh CreateConvexHull(Mesh mesh,int vertlimit,float inflation);
/* ID[51] */Mesh CreateConvexFromPoints(Tab<float ref> points,int vertlimit,float inflation);
/* ID[19] */Point3 val GetGravity();
/* ID[20] */int SetGravity(Point3 val gravity);
/* ID[21] */float SetGeometryScale(float scaleRate);
/* ID[22] */float GetGeometryScale();
/* ID[54] */BOOL SetUseContactReport(BOOL OnOff);
/* ID[55] */int GetContactsCount();
/* ID[56] */BOOL SelectFirstContact();
/* ID[57] */BOOL GetNextContact();
/* ID[58] */Point3 val GetContactForce(index_int index);
/* ID[59] */Point3 val GetContactPoint(index_int index);
/* ID[60] */INode* GetContactNode0(index_int index);
/* ID[61] */INode* GetContactNode1(index_int index);
/* ID[62] */float SetContactFilter(float force);
/* ID[63] */float GetContactFilter();
/* ID[64] */int FindSleepingActors();
/* ID[65] */INode* GetSleepingActor(int index);
/* ID[92] */BOOL RBBroken(INode* inode);
/* ID[93] */int PrintTM(INode* inode);
/* ID[94] */int PrintNodeParams(INode* inode);
/* ID[107] */INode* RagdollGetRootBone(INode* inode);
/* ID[106] */BOOL IsRagdollNode(INode* inode);
/* ID[108] */BOOL PhysiqueLoad(INode* inode);
/* ID[109] */int PhysiqueGetNumBones(INode* inode);
/* ID[110] */INode* PhysiqueGetBone(INode* inode,int boneIndex);
/* ID[111] */int PhysiqueGetNumBoneVertices(INode* inode,INode* boneNode);
/* ID[112] */Point3 val PhysiqueGetBoneVertex(INode* inode,INode* boneNode,int verticeIndex);
/* ID[102] */BOOL IsConvex(INode* inode);
/* ID[103] */float CalcVolume(INode* inode);
/* ID[104] */BOOL ConnectPVD(MCHAR* hostName);
/* ID[96] */int SaveClothingTemplate(MCHAR* filePath,MCHAR* fileName);
/* ID[95] */int LoadClothingTemplate(MCHAR* filePath);
/* ID[97] */int RebuildSelectedClothingNode();
/* ID[98] */int SaveAPEXClothing(MCHAR* filePath,BOOL useModelSpace,float scale,BOOL addHulls,BOOL exportCTW,BOOL exportFBX,BOOL exportCTP,BOOL exportSelected,BOOL launchViewer,BOOL reverseWinding,BOOL omitMeshSubpartName);
/* ID[105] */void SetButtonCheck(int id,BOOL value);
/* ID[99] */void DestroyPhysX();
/* ID[113] */BOOL ParseSkinInfo(INode* inode,float weightThreshold);
/* ID[114] */Tab<float val> GetVerticesFromSkinnedBone(INode* inode);
/* ID[115] */int GetVerticesCountFromSkinnedBone(INode* inode);
/* ID[116] */BOOL ReleaseSkinInfo();
/* ID[117] */BOOL HaveBoneFloatLimitControl(INode* inode,MCHAR* block);
/* ID[118] */MCHAR* GetBoneFloatLimitValue(INode* inode,MCHAR* block,MCHAR* param);
/* ID[119] */BOOL IsBone(INode* inode);
/* ID[120] */BOOL IsBiped(INode* inode);
/* ID[121] */BOOL IsBipedRoot(INode* inode);
/* ID[122] */BOOL IsBipedFootsteps(INode* inode);
/* ID[123] */void BipedSetKeys(BOOL setKeys);
/* ID[100] */int GetSolverIterations();
/* ID[101] */int SetSolverIterations(int count);
/* ID[124] */BOOL CreateGround(float position,Point3 ref normal);
/* ID[125] */BOOL RemoveGround();
/* ID[128] */BOOL SetRBDisplayMaterial(Mtl* dynamicMat,Mtl* kinematicMat,Mtl* staticMat);
/* ID[130] */Matrix3 val GetBonePose(INode* inode);
/* ID[131] */BOOL LoadRagdollHelperMesh(Mesh val mesh);
/* ID[132] */BOOL SetNullCM();
/* ID[133] */BOOL RemoveNullCM();
/* ID[137] */BOOL ReadSystemUnit(int type,float scale);
/* ID[138] */BOOL CopyRigidbody(INode* fromNode,INode* toNode);
/* ID[139] */int GetRBMeshCount(INode* inode);
/* ID[140] */Matrix3 ref GetRBMeshTM(INode* inode,int meshIndex);
/* ID[141] */int SetRBMeshTM(INode* inode,int meshIndex,Matrix3 ref pose);
/* ID[142] */int AddRBMesh(INode* inode);
/* ID[143] */BOOL DeleteRBMesh(INode* inode,int meshIndex);
/* ID[144] */BOOL ClipboardCopyRBMesh(INode* inode,int meshIndex);
/* ID[145] */BOOL ClipboardPasteRBMesh(INode* inode);
/* ID[146] */MCHAR* GetRBMeshName(INode* inode,int meshIndex);
/* ID[147] */int SetRBMeshName(INode* inode,int meshIndex,MCHAR* meshName);
/* ID[148] */MCHAR* GetRBMeshType(INode* inode,int meshIndex);
/* ID[149] */int SetRBMeshType(INode* inode,int meshIndex,int meshType);
/* ID[150] */float GetRBMeshRadius(INode* inode,int meshIndex);
/* ID[151] */int SetRBMeshRadius(INode* inode,int meshIndex,float radius);
/* ID[152] */float GetRBMeshLength(INode* inode,int meshIndex);
/* ID[153] */int SetRBMeshLength(INode* inode,int meshIndex,float Length);
/* ID[154] */float GetRBMeshWidth(INode* inode,int meshIndex);
/* ID[155] */int SetRBMeshWidth(INode* inode,int meshIndex,float Width);
/* ID[156] */float GetRBMeshHeight(INode* inode,int meshIndex);
/* ID[157] */int SetRBMeshHeight(INode* inode,int meshIndex,float Height);
/* ID[158] */INode* GetRBMeshCustomNode(INode* inode,int meshIndex);
/* ID[159] */int SetRBMeshCustomNode(INode* inode,int meshIndex,INode* CustomNode);
/* ID[160] */int GetRBMeshVertexLimit(INode* inode,int meshIndex);
/* ID[161] */int SetRBMeshVertexLimit(INode* inode,int meshIndex,int VerticeLimit);
/* ID[162] */float GetRBMeshInflation(INode* inode,int meshIndex);
/* ID[163] */int SetRBMeshInflation(INode* inode,int meshIndex,float Inflation);
/* ID[164] */Mesh GetRBMeshShape(INode* inode,int meshIndex);
/* ID[165] */BOOL SetRBMeshShape(INode* inode,int meshIndex,Mesh newMesh);
/* ID[166] */BOOL GetRBMeshOverrideMasterMat(INode* inode,int meshIndex);
/* ID[167] */BOOL SetRBMeshOverrideMasterMat(INode* inode,int meshIndex,BOOL overrideIt);
/* ID[126] */float SetMeterToSystemUnit(float newValue);
/* ID[127] */float GetMeterToSystemUnit();
/* ID[181] */BOOL StartIndirectDrag(INode* attach);
/* ID[182] */BOOL OnIndirectDrag(Point3 ref mousepos);
/* ID[183] */BOOL EndIndirectDrag();
/* ID[180] */SClass_ID GetObjectClass(INode* node);
/* ID[184] */BOOL IsApexAvailable();
/* ID[190] */int MaterialGetCount();
/* ID[191] */int MaterialGetId(int matIndex);
/* ID[192] */int MaterialGetType(int matId);
/* ID[193] */BOOL MaterialIsLocked(int matId);
/* ID[194] */int MaterialFind(MCHAR* ParamName);
/* ID[195] */int MaterialCreate(int type);
/* ID[196] */BOOL MaterialRemove(int matId);
/* ID[197] */MCHAR* MaterialGetParam(int matId,MCHAR* ParamName);
/* ID[198] */int MaterialSetParam(int matId,MCHAR* ParamName,MCHAR* ParamValue);
/* ID[199] */void RagdollRegenerate(INode* ragdoll,Tab<INode* ref> bones);
/* ID[200] */void RagdollAddBone(INode* ragdoll,INode* boneNode);
/* ID[201] */void RagdollRemoveBone(INode* ragdoll,INode* boneNode);
/* ID[202] */BOOL RagdollGroupBones(INode* ragdoll,Tab<INode* ref> bones);
/* ID[203] */BOOL RagdollSave(INode* ragdoll,MCHAR* filename);
/* ID[204] */BOOL RagdollLoad(INode* ragdoll,MCHAR* filename);
/* ID[205] */BOOL VisualizerGetEnabled();
/* ID[206] */void VisualizerSetEnabled(BOOL flag);
/* ID[207] */float VisualizerGetScale();
/* ID[208] */float VisualizerSetScale(float newScale);
/* ID[209] */int VisualizerGetPhysXParamCount();
/* ID[210] */MCHAR* VisualizerGetPhysXParamName(int index);
/* ID[211] */int VisualizerGetPhysXParam(MCHAR* paramName);
/* ID[212] */BOOL VisualizerSetPhysXParam(MCHAR* paramName,BOOL flag);
/* ID[213] */int VisualizerGetApexParamCount();
/* ID[214] */MCHAR* VisualizerGetApexParamName(int index);
/* ID[215] */int VisualizerGetApexParam(MCHAR* paramName);
/* ID[216] */BOOL VisualizerSetApexParam(MCHAR* paramName,BOOL flag);
/* ID[186] */int GetPMVisibleForRigidBodies();
/* ID[185] */void SetPMVisibleForRigidBodies(int visible);
/* ID[187] */void ProfilerBegin(MCHAR* name);
/* ID[188] */void ProfilerEnd(MCHAR* name);
/* ID[189] */void ProfilerDump();
/* ID[217] */INode* CreateRagdollHelper();
/* ID[218] */BOOL SupportMultiThread();
/* ID[219] */BOOL UseMultiThread(BOOL onOff);
/* ID[220] */BOOL IsMultiThreadOn();
/* ID[221] */BOOL SupportHardwareScene();
/* ID[222] */BOOL UseHardwareScene(BOOL onOff);
/* ID[223] */BOOL IsHardwareSceneOn();
/* ID[224] */void UnitTest_MaterialCreate(int type,MCHAR* name);
/* ID[225] */BOOL UnitTest_MaterialFind(MCHAR* name);
/* ID[226] */void UnitTest_MaterialDelete(MCHAR* type);
/* ID[227] */void UnitTest_MaterialAssign(INode* node,MCHAR* name);
/* ID[228] */MCHAR* UnitTest_MaterialPick(INode* node);
/* ID[229] */void OpenHelpFile();
/* ID[230] */void PhysXPanelTooltip();
/* ID[231] */void SetCCDMotionThreshold(float ccdMotionThreshold);
/* ID[232] */int GetPhysXPluginCount();
/* ID[233] */int GetPhysXPluginVersion(int Index);
/* ID[234] */MCHAR* GetPhysXPluginVersionString(int Index);
/* ID[235] */int GetPhysXPluginVersionMajor(int Index);
/* ID[236] */int GetPhysXPluginVersionMinor(int Index);
/* ID[237] */int GetPhysXPluginVersionBugFix(int Index);
/* ID[238] */BOOL UsePhysXPlugin(int Index);
/* ID[239] */void DetachPhysX();
/* ID[240] */void AttachPhysX();
/* ID[245] */MCHAR* GetScriptPath();
/* ID[246] */bool IsAutodeskVersion();
/* ID[242] */MCHAR* GetPluginCompanyName();
/* ID[243] */void SetAnimationState(BOOL state);
/* ID[244] */BOOL GetAnimationState();
/* ID[247] */void CreateViewer();
/* ID[250] */void PreCreateViewer();
/* ID[251] */void PostCreateViewer();
/* ID[248] */MCHAR* GetPluginBuild();
/* ID[249] */void ShowAboutDialog();
/* ID[252] */int GetBehaviorReason();
/* ID[253] */BOOL SetBehaviorReason(int mode);
/* ID[254] */BOOL GetBakedFlag(INode* inode);
/* ID[255] */BOOL SetBakedFlag(INode* inode,BOOL isBaked);
/* ID[256] */Matrix3 val GetInitialPose(INode* inode);
/* ID[257] */void SetInitialPose(INode* inode,Matrix3 ref initialPose);
/* ID[258] */BOOL CaptureInitTransforms(Tab<INode* ref> nodes);
/* ID[259] */BOOL ShouldViewerSync();
/* ID[260] */int GetViewerCommand();
/* ID[261] */int SetViewerCommand(int command);
/* ID[262] */void CheckViewerState();
/* ID[263] */void UpdateViewerPlayback();
/* ID[264] */int GetVirtualScreenX();
/* ID[265] */int GetVirtualScreenY();
/* ID[266] */void DumpContentCore(MCHAR* file,int Type);
/* ID[269] */void SetShapePerElement(BOOL shapePerElement);
/* ID[271] */INode* CreateDestruction(Tab<INode* ref> nodes);
/* ID[272] */BOOL GetExporterMode(int Parameter);
/* ID[273] */BOOL SetExporterMode(int Parameter,BOOL onOff);
After exposing this wonderful interface we notice we have access to mostly everything physics regarded. Well NVIDIA fails to provide 2 things:
1.
A simulation is required to run before any of the interface returns anything witch can be started manually.
1
2
ExecuteMAXScriptScript(_M("PxResetPhysXScene()"));
ExecuteMAXScriptScript(_M("PxCreatePhysXScene()"));
2. NVIDIA failed to provide a GetRigidBodyType for a Node so that we know if we are dealing with a STATIC/DYNAMIC/KINEMATIC node and the hardcore version is to call MaxScript once again. A call to PxGetNodeType should solve our problem but it involves writhing a bit more uglier code than a simple interface call.
All the pieces are now in place and with a bit more work i will started benefiting the same luxuries that UE3 engine have when exporting this data. I hope this info helps a few more people get a head start in getting a more direct transition from the CAD software to your game engine.