Max对外部的接口
有时候,我们希望可以从外部去操纵max,比如我前几天做的将kinect的动作信息发送至Max .Max本身提供了一个方式,它可以将自己注册成一个Ole自动化对象,默认是没有开启的。在Maxscript的自带文档 OLE Automation 章节有相关描叙。
开启这个接口只需要导入一个注册表,文档中的注册表文件见 "OLE Automation --> MAXScript.reg - Registery file"章节,需要自行更改max的版本以及安装路径。
或者可以将这段Max脚本放到max安装路径下的Scripts\StartUp
local version,outstr,executablePath,regPath
version = (maxversion())[1] /1000
outstr = createFile "$scripts/register_mxscom.reg"
format "Windows Registry Editor Version 5.00\n\n" to: outstr
format "[HKEY_CLASSES_ROOT\\MAX.Application]\n" to: outstr
format "@=\"OLE Automation MAX Application\"\n\n" to: outstr
format "[HKEY_CLASSES_ROOT\\MAX.Application\\Clsid]\n" to: outstr
format "@=\"{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}\"\n\n" to: outstr
format "[HKEY_CLASSES_ROOT\\MAX.Application\\CurVer]\n" version to: outstr
format "@=\"MAX.Application.%\"\n\n" version to: outstr
format "HKEY_CLASSES_ROOT\\CLSID\\{7FA22CB1-D26F-11d0-B260-00A0240CEEA3} = OLE Automation MAX %.0 Application\n" version to: outstr
format "HKEY_CLASSES_ROOT\\CLSID\{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}\\ProgID = MAX.Application.%\n" version to: outstr
format "HKEY_CLASSES_ROOT\\CLSID\\{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}\\VersionIndependentProgID = MAX.Application\n" to: outstr
executablePath =(getdir #maxroot) +"3dsmax.exe"
format "HKEY_CLASSES_ROOT\CLSID\{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}\\LocalServer32 = %\n" executablePath to: outstr
flush outstr
close outstr
regPath ="/S \""+ (getdir #maxroot) +"scripts\\register_mxscom.reg\""
shellLaunch "Regedit" regPath
registerOLEInterface #(Filein, Execute)
)
/*
这几行用于测试是否注册成功
MaxApp = createOLEObject "MAX.Application"
MaxApp.execute "box()"
MaxApp.FileIn "e:\\t.ms"
*/
这段脚本会在Max安装目录下的Scripts目录创建一个register_mxscom.reg文件,如果是Win7有可能因为权限禁止写入注册表,需要手动导入。
如果手动导入后还是无效,可以重启一下计算机,一般就启用了。
随后可以用VbScript或者Jscript去操作Max.这两种脚本需要Windows Script Host(一般系统中已经安装)
JScript的内容保存成.js文件,VbScript的内容保存为.vbs文件,如果一切操作正确,直接双击这两个文件中的任意一个,会在Max中创建一个立方体。
MaxApp.Execute("Box()");
Max.Execute("Box()")
可能我们并不满足于在VbScript或JScript中去操作Max,比如我前面说的Kinect相关的部分。我们还可以使用C++或C#来做。C#的方式会抛出异常,微软网站上对此的解释为 http://support.microsoft.com/kb/317276/zh-cn.话说我觉得没啥用,所以就直接放在try里面了.
补充一下,如果使用Python可以借助pywin32里的win32com.client来操作Max,相关的内容可以参考Cgtalk的MaxScript板块置顶贴,这里就不赘述了
因为不少人在学Python,所以加上Python的方法,需要下载相应Python版本的pywin32,搜索一下即可
#include "afxdisp.h "
#include <iostream>
using namespace std;
int main(int argc, TCHAR * argv[])
{
::CoInitialize(NULL);
COleDispatchDriver Dsp;
if(!Dsp.CreateDispatch("Max.Application"))
{
cout<<L"Max.Application创建失败"<<endl;
return -1;
}
DISPID PropID;
BSTR PropName[1];
PropName[0]=SysAllocString(L"execute");
Dsp.m_lpDispatch->GetIDsOfNames(IID_NULL,PropName,1,LOCALE_SYSTEM_DEFAULT,&PropID);
static BYTE parms[] = VTS_BSTR;
LPCTSTR lpszArgValue;
if (argc > 1)
{
lpszArgValue = argv[1];
}
else
{
lpszArgValue = "box()";
}
Dsp.InvokeHelper(PropID,DISPATCH_METHOD,VT_EMPTY,NULL,parms,lpszArgValue);
Dsp.ReleaseDispatch();
::CoUninitialize();
return 0;
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace SharpMaxCom
{
class Program
{
static void Main(string[] args)
{
Type AutodeskMax = Type.GetTypeFromProgID("Max.Application");
Object MaxApplication = Activator.CreateInstance(AutodeskMax);
object[] parameter = new object[1];
parameter[0] = "box()";
try
{
AutodeskMax.InvokeMember("execute", BindingFlags.InvokeMethod | BindingFlags.Instance, System.Type.DefaultBinder, MaxApplication, parameter);
}
catch (Exception EM)
{
Console.WriteLine(EM.ToString());
}
Console.ReadKey();
}
}
}
import win32com.client
MaxApplication = win32com.client.Dispatch("Max.Application")
MaxApplication._FlagAsMethod("Execute")
MaxApplication.Execute("Box()")