//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// //=================================================================== // Useful macros // #define CONSTRUCTOR #define DESTRUCTOR #define EXPORT_THIS __declspec(dllexport) #define DEFAULT_EXT _T("smd") #define FStrEq(sz1, sz2) (strcmp((sz1), (sz2)) == 0) //=================================================================== // Class that implements the scene-export. // class SmdExportClass : public SceneExport { friend BOOL CALLBACK ExportOptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); friend class DumpModelTEP; friend class DumpDeformsTEP; public: CONSTRUCTOR SmdExportClass(void); DESTRUCTOR ~SmdExportClass(void); // Required by classes derived from SceneExport virtual int ExtCount(void) { return 1; } virtual const TCHAR *Ext(int i) { return DEFAULT_EXT; } virtual const TCHAR *LongDesc(void) { return _T("Valve Skeletal Model Exporter for 3D Studio Max"); } virtual const TCHAR *ShortDesc(void) { return _T("Valve SMD"); } virtual const TCHAR *AuthorName(void) { return _T("Valve, LLC"); } virtual const TCHAR *CopyrightMessage(void) { return _T("Copyright (c) 1998, Valve LLC"); } virtual const TCHAR *OtherMessage1(void) { return _T(""); } virtual const TCHAR *OtherMessage2(void) { return _T(""); } virtual unsigned int Version(void) { return 201; } virtual void ShowAbout(HWND hWnd) { return; } // virtual int DoExport (const TCHAR *name, ExpInterface *ei, Interface // *i); virtual int DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL suppressPrompts = FALSE, DWORD options = 0); // Export file // Integer constants for this class enum { MAX_NAME_CHARS = 70, UNDESIRABLE_NODE_MARKER = -7777 }; // For keeping info about each (non-ignored) 3dsMax node in the tree typedef struct { char szNodeName[MAX_NAME_CHARS]; // usefull for lookups Matrix3 mat3NodeTM; // node's transformation matrix (at time zero) Matrix3 mat3ObjectTM; // object-offset transformation matrix (at time zero) int imaxnodeParent; // cached index of parent node float xRotFirstFrame; // 1st frame's X rotation float yRotFirstFrame; // 1st frame's Y rotation float zRotFirstFrame; // 1st frame's Z rotation bool isMirrored; } MaxNode; MaxNode *m_rgmaxnode; // array of nodes long m_imaxnodeMac; // # of nodes // Animation metrics (gleaned from 3dsMax and cached for convenience) Interval m_intervalOfAnimation; TimeValue m_tvStart; TimeValue m_tvEnd; int m_tpf; // ticks-per-frame private: BOOL CollectNodes(ExpInterface *expiface); BOOL DumpBones(FILE *pFile, ExpInterface *pexpiface); BOOL DumpRotations(FILE *pFile, ExpInterface *pexpiface); BOOL DumpModel(FILE *pFile, ExpInterface *pexpiface); BOOL DumpDeforms(FILE *pFile, ExpInterface *pexpiface); // Is this MAX file just the reference frame, or an animation? // If TRUE, the "bones" and "mesh" files will be created. // If FALSE, the "rots" file will be created. BOOL m_fReferenceFrame; }; //=================================================================== // Basically just a ClassFactory for communicating with 3DSMAX. // class SmdExportClassDesc : public ClassDesc { public: int IsPublic(void) { return TRUE; } void *Create(BOOL loading = FALSE) { return new SmdExportClass; } const TCHAR *ClassName(void) { return _T("SmdExport"); } SClass_ID SuperClassID(void) { return SCENE_EXPORT_CLASS_ID; } Class_ID ClassID(void) { return Class_ID(0x774a43fd, 0x794d2210); } const TCHAR *Category(void) { return _T(""); } }; //=================================================================== // Tree Enumeration Callback // Just counts the nodes in the node tree // class CountNodesTEP : public ITreeEnumProc { public: virtual int callback(INode *node); int m_cNodes; // running count of nodes }; //=================================================================== // Tree Enumeration Callback // Collects the nodes in the tree into the global array // class CollectNodesTEP : public ITreeEnumProc { public: virtual int callback(INode *node); SmdExportClass *m_phec; }; //=================================================================== // Tree Enumeration Callback // Dumps the bone offsets to a file. // class DumpNodesTEP : public ITreeEnumProc { public: virtual int callback(INode *node); FILE *m_pfile; // write to this file SmdExportClass *m_phec; }; //=================================================================== // Tree Enumeration Callback // Dumps the per-frame bone rotations to a file. // class DumpFrameRotationsTEP : public ITreeEnumProc { public: virtual int callback(INode *node); void cleanup(void); FILE *m_pfile; // write to this file TimeValue m_tvToDump; // dump snapshot at this frame time SmdExportClass *m_phec; }; //=================================================================== // Tree Enumeration Callback // Dumps the triangle meshes to a file. // class DumpModelTEP : public ITreeEnumProc { public: virtual int callback(INode *node); void cleanup(void); FILE *m_pfile; // write to this file TimeValue m_tvToDump; // dump snapshot at this frame time SmdExportClass *m_phec; IPhyContextExport *m_mcExport; IPhysiqueExport *m_phyExport; Modifier *m_phyMod; Modifier *m_bonesProMod; BonesPro_WeightArray *m_wa; private: Point3 Pt3GetRVertexNormal(RVertex *prvertex, DWORD smGroupFace); void DumpWeights(int iVertex); };