3DMax Plugin - 导出插件

第一次编写max场景导出插件的经验分享(仅限第一次写max插件的兄弟姐妹)

这几天第一次开始写max插件比较兴奋,作为这方面的新手有些经验和同样是新手的兄弟姐妹们分享一下
1。插件就是一个dll虽然他的名字未必输出是dll也可能是dlo,dle..

2。既然是dll就一定有一个DllMain函数
如果你和我一样什么都不懂不用害怕,打开max6sdkmaxsdksamplesimpexp中的3dsexp.vcproj这个是3ds文件的导出插件,我们就可以从他开始学起。
这个插件的函数基本都在一个文件里就是3dsexp.cpp中,我们先从入口函数DllMain看起

int controlsInit = FALSE;
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONGfdwReason,LPVOID lpvReserved) 

{

   hInstance = hinstDLL;
   if ( !controlsInit ) 

   {
        controlsInit = TRUE;
        InitCustomControls(hInstance);
        InitCommonControls();
    }
    switch(fdwReason) 

    {
       case DLL_PROCESS_ATTACH:
          break;
       case DLL_THREAD_ATTACH:
          break;
       case DLL_THREAD_DETACH:
          break;
       case DLL_PROCESS_DETACH:
          break;
    }
   return(TRUE);
}
基本上在你写自己的export时这个函数照抄就可以了。。。。

 

2。类
class _3DSClassDesc:public ClassDesc 

{
public:
   int                      IsPublic() { return 1; }
   void *                 Create(BOOL loading = FALSE) { return new _3DSExport; }
   const TCHAR * ClassName() { return GetString(IDS_TH_3DSTUDIO); }
   SClass_ID        SuperClassID() { return SCENE_EXPORT_CLASS_ID; }
   Class_ID           ClassID() { return Class_ID(0xd1d,0); }
   const TCHAR*  Category() { return GetString(IDS_TH_SCENEEXPORT);  }
};


这个是插件类的描述符其中

IsPublic表示插件是否被用户显式调用的
Create方法创建你用来做export的类这里是3DSExport;
classname随便定
SuperClassID是父类的ID对于场景导出来说一定是SCENE_EXPORT_CLASS_ID;
ClassId是本类的ID所有插件的ID都必须唯一你可以从max6sdkmaxsdkhelpgencid.exe获取
Category可以使用GetString(IDS_TH_SCENEEXPORT);
还有DLL的4个export方法必须我们自己实现


__declspec( dllexport ) const TCHAR * LibDescription() { return GetString(IDS_TH_3DSEXPORTDLL); }

 

__declspec( dllexport ) int LibNumberClasses() { return 1; }

 

__declspec( dllexport ) ClassDesc *LibClassDesc(int i)

{
      switch(i) 

      {
        case 0: return &_3DSDesc; break;
        default: return 0; break;
       }
}

 

// Return version so can detect obsolete DLLs
__declspec( dllexport ) ULONG LibVersion() { return VERSION_3DSMAX; }

// Let the plug-in register itself for deferred loading
__declspec( dllexport ) ULONG CanAutoDefer()
{
    return 1;
}

Li
bDescription()是描述这个插件的一个字符串可以随便定
LibNumberClasses()用来说明该插件有几个类这里是1个
LibClassDesc()返回前面定义的类描述符

以上的DLLmain和ClassDesc的派生类以及4个export函数是必须的写完这2个以后我们可以进入正题


class _3DSExport : public SceneExport
从系统类SceneExport派生出的3DSExport类是我们用来导处场景到我们自己的文件格式的


class SceneEnumProc : public ITreeEnumProc
所有对节点的访问都是通过ITreeEnumProc的派生类(这里是SceneEnumProc )来完成的
ITreeEnumProc中有个重要函数就是callback( INode *node );
这个是MAX系统回调你的函数其中max会传给给你node参数这个就是max场景中的节点
使用IScene的int EnumTree( ITreeEnumProc *proc )函数带入我们自己的Enumproc类
例如IScene->EnumTree(SceneEnumProc )l就可以使max完成回调函数。
那么IScene从哪里传来的呢?
SceneExport类有个函数int DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options); // Export file
其中的ExpInterface有个成员theScene就是这个IScene了
这样我们只要在我们自己的SceneExport类(这里是_3DSExport )的DoExport中调用
ei->theScene->EnumTree(SceneEnumProc)

那么我们必须要访问max场景文件的所有节点以及他们包含的几何数据,怎么访问呢

 

很简单吧 接下来要做的就是在你自己的SceneEnumProc派生类中具体实现callback函数了比如对输入的节点进行转换成你的格式等等
    有关调试 如果直接调试会使得3dmax崩溃貌似3dmax6有反调试。你只要先启动max然后在vc中用调试->附加到进程3dsmax就可以顺利设置断点调试了,如果你还不明白就把3ds的export调试一边就全懂了

你可能感兴趣的:(thread,Class,dll,callback,interface)