Max SDK是用于c++项目,开发生成max插件的SDK。编译生成的文件实质上是dll文件,根据插件类型的不同,其后缀有所差别,但形式都是.dl*
官方文档:https://help.autodesk.com/view/3DSMAX/2020/ENU/?guid=__developer_about_the_3ds_max_sdk_html
环境配置
安装max sdk
正常安装Max后,再次打开Max安装文件,选择安装工具和实用程序,之后选择安装SDK

安装visual studio及必要组件
不同版本的max sdk需要的visual studio(下简称vs)版本、windows sdk 开发工具等组件可能会不同,需要根据max sdk版本进行配置安装。
这个网页列举了不同sdk版本的需求环境。
https://help.autodesk.com/view/3DSMAX/2020/ENU/?guid=__developer_about_the_3ds_max_sdk_sdk_requirements_html
以max 2020 sdk为例,安装以下软件和组件即可(vs和platform toolset版本可以高一些,不过还是按照要求配置,遇到的问题会少一些,sdk必须是图中的版本)

配置3ds Max Plugin Wizard项目模板到visual studio
3ds Max Plugin Wizard允许通过vs为3ds Max创建插件项目。
找到你的max skd安装目录,打开maxsdk\howto\3dsmaxPluginWizard\readme.txt文件,按照其中的步骤,进行安装,这里不再赘述。
成功后,可以在vs新建项目的模板中,搜索到max插件模板。

如果创建新项目失败,以下几点可以注意检查一下:
- 如果你用的vs是2019的,可以在vc目录下自己创建个vcprojects文件夹,并把Wizard=VsWizard.VsWizardEngine.15.0最后的.15.0改为.16.0(这点官网没说)。
- 再检查一下3dsmaxPluginWizard文件夹的读写状态,可能因为windows的一些问题,之前设置可读写没有成功。可以使用命令提示符的方式修改文件夹的可读写状态。
创建新项目
如果上一步环境配置没有问题,则会弹出一个创建引导窗口,随便选择一个然后下一步。

设置类名称、插件类型和描述,可以直接下一步。

输入max sdk目录、输出目录和3ds max目录。
输出目录可以设置为3ds Max 20**/Plugins下,即max的插件目录,这样生成插件后,可以直接安装到3dsmax。当然也可以是任意目录,然后手动把生成的插件复制到插件目录也行
3ds max目录可以让你本地调试时直接打开3ds max软件。
如果安装了QT(一个跨平台UI工具库),可以勾选Use QT UI

创建完成后可以生成一下,查看是否有错误:
-
无法打开文件”bmm.lib”

这个目录下没有该文件,把配置Debug改为release

-
无法打开文件“***.h”可能是max sdk环境没有配置好,需要手动添加下面路径到包含目录
D:\autodesk\3ds Max 2020 SDK\maxsdk\include
目录结构

这其中的绝大多数文件是自动生成的,不需要更改,基本只需要修改MyFirstMaxProject.cpp来完成插件功能,不过还是稍稍介绍下各个文件:
DllEntry.cpp
包含了Dll各解释函数的实现,还有最重要的DllMain入口函数,只需要知道是这么个样子且Dll必不可少即可,它是自动生成的。
1 | |
MyFirstMaxProject.def
描述DLL文件的各种属性,对于DLL的功能使用是必要的。
MyFirstMaxProject.rc
包含插件所需的窗口资源,插件名称、类型和描述数据都存在这里,定义了插件默认的用户界面面板(如果没使用QT)
3dsmaxsdk_preinclude.h
这个文件定义了生成编译时待办事项信息所需的宏。如果你是手动创建你的项目,你将不需要这个文件。
resoure.h
与.rc文件类似,该文件是自动生成的,存储资源文件中使用的常量值。如果你是手动创建你的插件,你将不需要这个文件。
plugin_form.ui, QtPluginRollup.cpp, QtPluginRollup.h
如果你勾选了Use QT,则会有这些文件,他们定义了插件的用户界面。
MyFirstMaxProject.h
包含了引用的文件,其中utilapi.h包括了UtilityObj类的定义,其他的头文件在各种类型的插件项目中大差不差。
hInstance是操作系统内存空间中DLL模块的一个句柄(Handle)
GetString()用于从一个字符串表中返回一个字符串。字符串表为储存在.rc文件中的名称、类型、描述数据。
MyFirstMaxProject.cpp
继承自UtilityObj类,其中的成员函数都是纯虚拟的,需要实现所有的函数。
该文件中包括MyFirstMaxProject插件类、MyFirstMaxProjectClassDesc描述类和一个全局函数ClassDesc2* GetMyFirstMaxProjectDesc(),该函数被Dll中的LibClassDesc函数调用,返回MyFirstMaxProjectClassDesc类的静态对象地址。
在3ds max中,同时只能存在一个Utility类型的插件实例(不同于几何对象插件),所以创建插件实例使用的是单例模式。
描述类负责联系3ds Max。插件向导将其命名为<yourpluginname>ClassDesc,但如果你是手动创建你的插件,你可以使用任何名字来命名它。它必须继承自ClassDesc2。它描述了我们正在实现的插件类的类型,它的名字,它的类ID等。它还实现了一个函数,以便在请求时提供这个插件类的实例。插件向导并没有实现这个类中的任何功能的代码–实现这些功能是插件开发者的责任。
Max SDK开发的第一小步
开始和结束函数
首先看void MyFirstMaxProject::BeginEditParams(Interface* ip,IUtil* iu) 这个函数,在插件激活时会被调用,尝试在里面加入
ip->PushPrompt(_M("Hello World form BeignEditParams()"));
这可以让你在打开插件时,在下面输出一条信息:

补充一下,Utility插件都是在这里的工具,在生成的文件放置到max/plugins目录后,可以这样设置插件到面板上
同样,在void MyFirstMaxProject::EndEditParams(Interface* ip,IUtil*) 中加入:
ip->PushPrompt(_M("Bye form EndEditParams()"));
在结束插件时,输出“Bye form EndEditParams()”,说是结束,只要窗口不再显示该插件(切换到别的Utility插件,或者切换别的编辑模式)都会调用End函数,这点很类似Unity的Enable()和Disable()函数。
实际上在结束函数中应该写ip->PopPrompt(); ,因为切换到别的窗口后,之前的输出信息不会消失,这条会消除“Hello World form BeginEditParams()”信息。
场景图、场景节点和场景对象
场景图(Scene Graph)存储了场景对象的信息和他们之间的关系(父子关系),场景图由场景节点(INode)组成
每一个场景节点对应一个场景对象的信息,有指向场景对象的指针,子节点的数量,父节点和子节点的地址,该对象的位置旋转缩放,以及应用的材质。场景节点指向的场景对象不拥有这些信息。
场景图是树形结构,树的根是一个虚拟节点,不与任何节点连接;没有父物体的节点,则是这个树中的第一级节点。
场景对象实例化后,如果没有相应的场景节点,则不会在视口中显示。
下面是一部分INode的成员函数
1 | |
如何学习
maxsdk/howto文件夹中包含了一些简单的插件项目。
maxsdk/samples文件夹中包含了max中标准的插件的vs项目。
可以通过这些项目学习一些开发方法。
