• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            永遠也不完美的程序

            不斷學習,不斷實踐,不斷的重構……

            常用鏈接

            統計

            積分與排名

            好友鏈接

            最新評論

            3DS Max 插件制作學習心得(轉)

            來源:yhforchina的專欄 - CSDNBlog

              要從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::DoExport(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寫得真叫一個亂,還好總算有些進展,正所謂萬事開頭難。下一步將研究如何導出場景的光照,物體的紋理貼圖等信息。

            posted on 2009-01-05 16:15 狂爛球 閱讀(1158) 評論(0)  編輯 收藏 引用 所屬分類: 圖形編程

            亚洲精品乱码久久久久久久久久久久| 国产亚洲精午夜久久久久久| 久久精品中文无码资源站| 久久亚洲AV永久无码精品| 精品国产99久久久久久麻豆| 午夜精品久久久久久99热| 精品久久久噜噜噜久久久| 国产99久久久国产精免费| 久久久久亚洲av成人网人人软件 | 欧美久久精品一级c片片| 久久精品国产亚洲Aⅴ香蕉| 久久精品国产久精国产一老狼| 久久综合丝袜日本网| 怡红院日本一道日本久久 | 亚洲中文久久精品无码| 97久久久精品综合88久久| 色老头网站久久网| 国产成人精品久久亚洲高清不卡| 久久精品国产99国产精品导航| 一本大道加勒比久久综合| 色偷偷88888欧美精品久久久| 久久久久九国产精品| 99久久免费国产精品| 久久香蕉超碰97国产精品| 亚洲日本久久久午夜精品| 久久久久99精品成人片| 97超级碰碰碰久久久久| 婷婷五月深深久久精品| 99久久做夜夜爱天天做精品| 亚洲国产日韩欧美综合久久| 国产成人99久久亚洲综合精品| 国产精品久久久天天影视| 久久无码高潮喷水| 亚洲欧美日韩久久精品| 国产成人精品久久一区二区三区av | 久久国产视屏| 久久久久亚洲精品中文字幕| 精品久久综合1区2区3区激情| 日韩精品国产自在久久现线拍| 精品综合久久久久久97超人| 久久综合久久综合久久|