马上注册,加入CGJOY,让你轻松玩转CGJOY。
您需要 登录 才可以下载或查看,没有帐号?立即注册
×
这几天第一次开始写max插件比较兴奋,作为这方面的新手有些经验和同样是新手的兄弟姐妹们分享一下
1。插件就是一个dll虽然他的名字未必输出是dll也可能是dlo,dle..
2。既然是dll就一定有一个DllMain函数
如果你和我一样什么都不懂不用害怕,打开max6sdk\maxsdk\samples\impexp中的3dsexp.vcproj这个是3ds文件的导出插件,我们就可以从他开始学起。
这个插件的函数基本都在一个文件里就是3dsexp.cpp中,我们先从入口函数DllMain看起
int controlsInit = FALSE;
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,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都必须唯一你可以从max6sdk\maxsdk\help\gencid.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;
}
LibDescription()是描述这个插件的一个字符串可以随便定
LibNumberClasses()用来说明该插件有几个类这里是1个
LibClassDesc()返回前面定义的类描述符
以上的DLLmain和ClassDesc的派生类以及4个export函数是必须的写完这2个以后我们可以进入正题
class _3DSExport : public SceneExport
从系统类SceneExport派生出的3DSExport类是我们用来导处场景到我们自己的文件格式的
那么我们必须要访问max场景文件的所有节点以及他们包含的几何数据,怎么访问呢
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)
很简单吧 接下来要做的就是在你自己的SceneEnumProc派生类中具体实现callback函数了比如对输入的节点进行转换成你的格式等等
有关调试 如果直接调试会使得3dmax崩溃貌似3dmax6有反调试。你只要先启动max然后在vc中用调试->附加到进程3dsmax就可以顺利设置断点调试了,如果你还不明白就把3ds的export调试一边就全懂了
下面是一个网友的回帖:- 首先对你跟大家分享经验的做法表示肯定.
- 其次提个醒,max的插件经常出现版本不兼容的情况,现在的美工们都用max9或以上的版本了,而max的sdk更新速度赶不上,而且如果max出个新版本就要换个新sdk的话,那简直让人疯掉.还是用maxscript来进行导出导入为好,毕竟max对它的脚本的兼容性很好,我以前max7上写的脚本现在在max2009上用都没问题,试问用max7sdk开发的插件可以做到这样吗?
- 最后就是要建议大家,是时候转向学习xsi的插件开发了.因为现在的xsi越来越受美工们的青睐(我公司的美工现在都用的xsi建模),而且xsi直接导出.x之类的现成格式的文件出问题少(你想想,微软的软件会导出有问题的.x文件吗),再加上xsi的插件开发支持超多.现在我见了max相关的都想吐
复制代码
|