游戏开发论坛

 找回密码
 立即注册
搜索
查看: 14803|回复: 15

3DS Max 插件制作学习心得 1

[复制链接]

4

主题

11

帖子

26

积分

注册会员

Rank: 2

积分
26
发表于 2007-10-25 09:43:00 | 显示全部楼层 |阅读模式
要从3ds Max中导出场景信息,大概有两种方式:1.利用3ds Max的sdk制作插件。2.利用3ds Max的Max Script编写场景输出脚本。两种方式各有优劣,这里仅叙述我用了数天研究3ds Max SDK并制作插件的学习心得。
        1.前期环境配置工作。

       首先肯定要安装带SDK的3ds Max,我安装的是3ds Max7。安装后在maxsdk\help下有个sdkapwz.zip,把这个文件解压到VS 6.0或VS 2003的application wizard路径下,启动VS就会有3ds Max plug-in的应用程序向导来生成插件程序的框架。
       2.制作插件需要了解的几个基本概念。

       2.1 我所了解的插件原理是:3ds Max会公布一些接口,插件制作者需要做的是实现这些接口。例如利用向导生成一个用于场景导出的插件。就会发现在生成的程序中有一个类继承于class SceneExport,而 SDK 中关于这个接口的描述是:

       This is a base class for creating file export plug-ins. The plug-in implements methods of this class  to describe the properties of the export plug-in and a method that handles the actual export  process.

       再看下面的函数说明,可以看到函数是虚函数的方式声明的,所以必须要将其所有的函数进行实现。

       2.2 3ds Max是怎样识别插件的接口?还是以上面的场景到处插件为例,程序中还会生成一个继承于 ClassDesc2的类,这个类会实现一些关于类的ID,层次信息处理的函数。估计系统就是根据这个识别处我的插件的接口,没有具体去研究,只了解个大概。

       2.3 如何调试所编写的插件,SDK中有说明,我这里简单说一下,将工程属性设置为Hybrid(默认是Debug),并且把输出dle文件的路径设为3ds Max的plug-in的路径,再把调试的可执行程序设为3ds Max.exe,这样 调试的时候就会启动3ds Max主程序,其他诸如设置断点,单步等调试手段和普通程序的调试方法一样。
       3.通过一个例子学习插件编程。

    这部分还真不好写,涉及到一些代码,代码中又有很多API需要讲解,API中又有很多基本知识需要说明,唉,硬着头皮来吧。

       还是以那个场景导出类为例,可以看到,SceneExport中有个非常重要的函数需要实现:

       virtual int DoExport(const TCHAR *name,ExpInterface *ei,Interface *i,
       BOOL suppressPrompts=FALSE, DWORD options=0) = 0;

       先看看参数:

      name 表示要导出的文件名。

      ei 用来枚举场景,需要注意的是:由于这个函数是由系统调用的,所以这个参数是系统传递的,不      用去思考怎么实现ExpInterface这个接口。

      i 提供一个用来调用3ds Max方法的指针,可以把它视作一个指向3ds Max的指针。同样,这个指针      也是由系统传递的。

      剩下两个参数暂不关心。

      现在来研究ei和i两个参数:

      class ExpInterface仅包含一个成员:IScene *theScene。这样的类设计的简直是“无耻”。再去研究IScene吧。IScene中有一个很重要的函数:

virtual int EnumTree( ITreeEnumProc *proc )=0;

       根据SDK的说明,该函数的功能是:用来枚举场景中的每个INode。因此需要一个ItreeEnumProc*作为参数,由于是自己调用整个函数,因而必须自己实现ItreeEnumProc接口,还好这个接口不是很复杂,把这个回调函数实现就可以了:

        virtual int callback( INode *node )=0;

    因为是回调函数,所以node也是系统传递进来的,为了证明这一点,我们可以编程实验一下:

class MyEnumProc: public ITreeEnumProc
...{
public: int callback( INode *node )
    ...{
             int a = 0;//在这里设置断点
             return a;
        }
}

在MyExport中添加这一个成员变量:
MyEnumProc MyProc;

int    MyExport:oExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)
...{
        /**//*在函数中添加这行代码*/
    ei->theScene->EnumTree(&this->MyProc );

    if(!suppressPrompts)
        DialogBoxParam(hInstance,
                MAKEINTRESOURCE(IDD_PANEL),
                GetActiveWindow(),
                MY5OptionsDlgProc, (LPARAM)this);
    return FALSE;
}

     调试这个例子,在场景中绘制三个立方体,可以看到系统会调用callback三次,这说明一个物体就是一个Node。那么怎么来导出一个Node几何信息呢?看下面这个代码。

public: int callback( INode *node )
...{
    Object *lobj;
    lobj = node->GetObjectRef();
    if (lobj->SuperClassID()== GEOMOBJECT_CLASS_ID)
    ...{
        GeomObject* gobj = (GeomObject*)lobj;
        Class_ID triID = Class_ID(TRIOBJ_CLASS_ID,0);
        Class_ID boxID = Class_ID(BOXOBJ_CLASS_ID,0);      
        if (lobj->ClassID()==boxID)
        ...{
            if (lobj->CanConvertToType(triID))
            ...{

                TriObject *triobj = (TriObject *)lobj->ConvertToType
                    (0,triID);
                Mesh mesh = triobj->mesh;
                int numVerts = mesh.getNumVerts();
            }

            IParamArray* array = lobj->GetParamBlock();
            float length = 0.0f;
            float height = 0.0f;
            float width = 0.0f;
               
           array->GetValue( lobj->GetParamBlockIndex(BOXOBJ_LENGTH),
                0, length, FOREVER);
           array->GetValue( lobj->GetParamBlockIndex(BOXOBJ_HEIGHT),
                0, height, FOREVER);
           array->GetValue( lobj->GetParamBlockIndex(BOXOBJ_WIDTH),
                0, width, FOREVER);
        }
}
   

首先node->GetObjectRef()会返回这个节点的物体引用。关于ObjectRef有一套几何流水线的说明,这里实在是没功夫写了。接着首先判断这物体的SuperClassID是否为GEOMOBJECT_CLAS- S_ID,如果是,则再看它是否能转换为TriObject,即由三角形组成的物体,至于为什么要这样转,我只能说只有这个类可以返回一个Mesh,而通 过Mesh能够获得诸如顶点,法线,面等一般3D程序所需要的几何信息(这里只获取了该Mesh的面的个数)。当然,对于一个Box,我们可能只想获得它 的长宽高,所以,代码中又提供了另一个方法来返回其几何信息。

      虽然只实现了这么短的代码,但却花了数天的时间,主要对3ds Max的结构不熟悉,加上SDK写得真叫一个乱,还好总算有些进展,正所谓万事开头难。下一步将研究如何导出场景的光照,物体的纹理贴图等信息。

      这里介绍几个网站,感谢它们对我提供的帮助:

      http://www.cgsir.com
      http://discussion.autodesk.com/index.jspa
      也希望看到这篇文章的人能够给予指正,毕竟我是刚开始学3ds Max plug-in.

1

主题

149

帖子

149

积分

注册会员

Rank: 2

积分
149
QQ
发表于 2007-10-25 12:08:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

顶一个.

31

主题

249

帖子

259

积分

中级会员

Rank: 3Rank: 3

积分
259
发表于 2007-10-25 13:48:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

最近我也在做3DsMax9的导出插件,快要完成了。花了8小时看例程和文档,也不是很难。有机会交流交流。
关注中……

4

主题

11

帖子

26

积分

注册会员

Rank: 2

积分
26
 楼主| 发表于 2007-10-26 09:15:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

    最近又在研究插件的UI开发,弄了好半天才把那种添加Utility的方式,就是那种在工具里添加command panel的方式弄明白了。那么我如果想在工具栏或者菜单栏里添加自己的控件该怎么做呢?情各位指教。
    我现在遇到的主要困难是:1.对3ds MAX使用的并不熟练,里面很多名词术语不了解。2.3ds Max的SDK可读性很差(个人感觉),内容又多,学习起来颇费周折。3.给的例子比较庞大,不容易弄清其中的结构。还望各位高手多多指点。

31

主题

249

帖子

259

积分

中级会员

Rank: 3Rank: 3

积分
259
发表于 2007-10-26 16:15:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

文章提到3DsMax的导出插件,个人觉得用IGameExporter更方便

4

主题

17

帖子

23

积分

注册会员

Rank: 2

积分
23
发表于 2007-10-26 21:31:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

顶LZ分享学习心得

29

主题

405

帖子

405

积分

中级会员

Rank: 3Rank: 3

积分
405
发表于 2007-10-26 23:04:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

顶,特地登录顶你的贴

4

主题

11

帖子

26

积分

注册会员

Rank: 2

积分
26
 楼主| 发表于 2007-10-29 11:38:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

因为我现在从事的是地理信息方面的工作,对于EziaSolsky提到的IGameExporter,不知是否也适用于这个方面,希望EziaSolsky能给些简单的介绍,谢谢。

22

主题

309

帖子

353

积分

中级会员

Rank: 3Rank: 3

积分
353
QQ
发表于 2007-10-29 12:39:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

LZ可以提一下Max Script不?优缺点之类的...

18

主题

631

帖子

660

积分

高级会员

Rank: 4

积分
660
发表于 2007-10-29 18:11:00 | 显示全部楼层

Re:3DS Max 插件制作学习心得 1

顶之
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-8-17 02:19

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表