西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁編程開發(fā)其它知識 → 3ds max sdk導(dǎo)出插件編寫心得

3ds max sdk導(dǎo)出插件編寫心得

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:西西整理時間:2014/2/10 22:00:20字體大。A-A+

作者:西西點擊:709次評論:0次標簽: 3DMAX

  • 類型:濾鏡插件大。17.5M語言:中文 評分:3.3
  • 標簽:
立即下載

感覺3ds Max SDK實在是博大精深,初學(xué)者入門還是很不方便,所以覺得以前發(fā)的心得應(yīng)該得到補充,因而寫了這樣一個導(dǎo)出程序介紹,還是抱著學(xué)習(xí)的態(tài)度,不過還是希望能夠?qū)Υ蠹矣兴鶐椭?/p>

想想研究3D MAX 的SDK已經(jīng)有了不短的時間,真正算起來也有兩個月了吧,但是講到收獲,確實不大。作為一個3D MAX二次開發(fā)的學(xué)習(xí)者,我首先學(xué)習(xí)了導(dǎo)出插件的編寫,網(wǎng)上有很多參考資料,寫的都差不多,可是都是寫到關(guān)鍵的地方或者說比較模糊的地方就說不清楚了,今天我就結(jié)合自己所做的工作來講講3D MAX導(dǎo)出插件的編寫心得。

3Ds MAX2009 (3dmax)
5.6
類別: 3D 制作    大。56.6M    語言: 中文
查看詳細信息 >>

環(huán)境配置:

步驟1.首先你得有VS2005,3ds Max 9,如果有就好辦了,否則想辦法搞到手吧,在中國做到這點應(yīng)該不難。至于其他相近版本的IDE和MAX,情況基本類似。

步驟2.在3ds Max9 SDK"maxsdk"howto"3dsmaxPluginWizard中有個readme.txt,它會向你介紹如何配置3ds Max9 plugin的向?qū)А?/p>

步驟3.啟動vs2005,新建Visual C++項目,如果在右側(cè)的模板組中能夠找到”3dsmaxPluginWizard”,并且選擇后能夠彈出歡迎界面,說面配置已經(jīng)成功了。

首先,需要做好如下的準備工作:
1. 安裝一個完整版本的3D MAX與Visual Stdio。
我安裝的是3D MAX 2009,最好是找一個完整的版本,因為完整的版本中有很多的學(xué)習(xí)資料與sdk供學(xué)習(xí),很省事。3D MAX的二次開發(fā)對VS的要求是有一個對應(yīng)關(guān)系的,在SDK文檔中可以找到,3D MAX 2009對應(yīng)的VS開發(fā)版本應(yīng)該是VS 2005,確保電腦上已經(jīng)安裝了VS 2005。
2.定制3D MAX plug-in向?qū)А?br/>a.找到安裝目錄的3dsmaxPluginWizard文件夾(我的安裝目錄是C:\Program Files\Autodesk\3ds Max 9 SDK\maxsdk\howto\3dsmaxPluginWizard
),
b.打開此目錄下的MaxPluginWizard.vsz 文件,編輯ABSOLUTE  PATH參數(shù)為:

Param="ABSOLUTE_PATH=C:\Program Files\Autodesk\3ds Max 9\SDK\maxsdk\howto\3dsmaxPluginWizard"

c.將3dsmaxPluginWizard文件夾下的三個文件3dsmaxPluginWizard.ico、3dsmaxPluginWizard.vsdir、3dsmaxPluginWizard.vsz拷貝到VS 2005安裝目錄的 VC  Projects 目錄下,我電腦上的目錄是C:\Program Files\Microsoft Visual Studio 8\VC\vcprojects。
d.啟動VS 2005,File-New Project,選擇Visual C++就可以看到3ds max Plugin Wizard選項,說明定制成功。
以上只是開發(fā)前的一些準備工作,都可以直接在3D MAX SDK的文檔中直接找到,不過文檔可都是英文的哦,要耐心的讀下去。
在以上準備工作做好以后,就可以開始開發(fā)一個插件了,由簡單到復(fù)雜,先做一個簡單的插件程序。插件程序的編寫有兩種方法,一是用插件向?qū),就是剛才上面所說的;另一種是通過手工創(chuàng)建一個插件項目,在這里暫時只討論用插件向?qū)黹_發(fā),比較便捷,手工開發(fā)以后在補上。
1.第一步,生成一個插件程序的工程,具體如下:
a. 打開File —>New Project —>選擇3ds max Plugin Wizard,輸入project名字,如 “MyExport”。
b. 進入Welcome to the 3ds max Plugin Wizard 畫面,選擇plugin type如圖所示:

c.這里顯示各種插件類型,目前要做的是一個文件的導(dǎo)出插件,所以選擇FileExport類型。
d.下一步,再出現(xiàn)一個對話框



不用去管這些Plugin Detail,會有默認路徑的,。     
e.再下一步,設(shè)置一些路徑,具體見圖及注明。

注明:

Enter your MAXSDK path指的是3D MAX SDK的安裝目錄

Enter your Plugin output path 指的是生成插件文件.dll存放的目錄,可以自己設(shè)置

Enter your 3dsmax.exe path指的是3D MAX的安裝目錄

2.項目生成以后,在MyExport.cpp文件中找到Ext(int n)函數(shù),改為return _T("MY3D"), "MY3D"是根據(jù)自己的要求來添加的;
找到ShortDesc()函數(shù),改為return _T ("MyExportPlugin");
找到DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)內(nèi)添加:

AllocConsole();

_cprintf( "Export Begin\n" );//記得#include <conio.h>

3. 生成并調(diào)試你的插件,系統(tǒng)會執(zhí)行3dsmax.exe以啟動3ds Max,然后選擇“文件”->”導(dǎo)出”,如果能看到"MyExportPlugin(*.My3D)"
說明導(dǎo)出成功,然后定義一個導(dǎo)出文件的名稱即可.這樣一個空的導(dǎo)出插件就編寫成功了!接下來請看: 3D MAX導(dǎo)出插件編寫II    



Export利器:IGame 
古人云:君子生非異也,善假于物也
數(shù)據(jù)導(dǎo)出是一個繁瑣的工作,于是,有了IGame這個解脫程序員的東西:


關(guān)于IGame

IGame是Max提供給游戲開發(fā)的一個用于導(dǎo)入導(dǎo)出的接口。在Max的help里面這個東西叫做3ds Max Data Exchange Interface。有了這個接口,可以大大的簡化導(dǎo)入導(dǎo)出工作的工作量。

如果有經(jīng)歷過用MAX SDK導(dǎo)出關(guān)鍵幀動畫以及骨骼動畫,Skin,Modifier等等的經(jīng)歷的話,我想肯定會記憶深刻。IGame的作用就是把復(fù)雜的Max的概念簡化,封裝。

建立IGame:
IGameScene * m_pIgame= GetIGameInterface()

坐標系:
前面我提到的導(dǎo)出的文章都沒有提這個問題,所有的坐標都是用的MAX本身的坐標系,及Z軸向上。在游戲中坐標系可能千奇百怪,IGame考慮到這點提供了指定坐標系的功能:

IGameConversionManager * cm = GetConversionManager();

cm->SetCoordSystem(IGameConversionManager::IGAME_D3D);

m_pIgame->InitialiseIGame(true); 

其中IGAME_D3D就是指定的坐標系,同樣也可以自定義坐標系:

UserCoord WhackySystem = { 

1,   //Right Handed 

1,   //X axis goes right 

4,   //Y Axis goes in 

3,   //Z Axis goes down. 

0,   //U Tex axis is left 

1, //V Tex axis is Down 

};   


IGameConversionManager * cm = GetConversionManager(); 

cm->SetUserCoordSystem(WhackySystem);                  

IGame要點:
GetTopLevelNodeCount:獲得頂級的Node數(shù)目,不包括Root。

GetRootMaterialCount:獲得所有的材質(zhì)數(shù)目

GetTopLevelNode(i):獲得指定Node

GetIGameObject():獲得Node中包含的Object

GetLocalTM():獲得Node的矩陣



IGameMesh ::GetVertex(i):獲得頂點

IGameMesh ::GetFace(i);獲得面

IGameMesh ::GetNormal(i):獲得法線

至于其他就依次類推了,從函數(shù)的命名,到概念的簡化,無疑都比原始的MAXSDK進步了很多。有了IGame接口,大大減輕了程序員的負擔(dān),我相信沒有哪個愿意把大把的時間花在數(shù)據(jù)的導(dǎo)入導(dǎo)出上。



花了幾十分鐘簡單的試用了一下IGame寫了個小小的導(dǎo)出插件,只導(dǎo)出了頂點,面,材質(zhì),法線以及矩陣,感覺基本上沒什么阻礙。不過IGame最大的功能還是用在骨骼動畫,關(guān)鍵幀動畫上面,僅僅只是簡單的幾何體導(dǎo)出并不能體現(xiàn)出IGame的功效。



最后還是附上代碼和工程吧。不得不提示一下,由于種種曲折的原因,我這個工程是在MAX8 SDK和 MAX8下 完成的,其間省略上千字曲折的經(jīng)歷,不過在MAX9下應(yīng)該可以通過編譯。編譯完成后,記得在Max 中選擇Export Selected而不是試用Export。

3DS MAX PlugIn 材質(zhì)和紋理 材質(zhì)和紋理的信息都位于node 中
材質(zhì)的信息通過類Mtl獲得
紋理的信息位于node中的mesh 中的UVVert

以下是獲得材質(zhì)的代碼:
//////////////////////////////////////////////////////////////////////////
//material
Mtl* nodematerial=node->GetMtl();
if(nodematerial)
{
fprintf(m_fileStream, "%s mtl -- name:<%s>\n", GetIndent(indent),nodematerial->GetName());
}
else
{
DWORD vcolor=node->GetWireColor();
fprintf(m_fileStream,"%s color -- rgb:<%d,%d,%d>\n", GetIndent(indent),GetRValue(vcolor), GetGValue(vcolor), GetBValue(vcolor));
}
//////////////////////////////////////////////////////////////////////////

以下是獲取UV的代碼,需要注意的是,需要對是否有多重貼圖處理:


void OnlyGeometry::ExportUVInfo(Mesh* mesh,int indent)
{
int numTVerts = mesh->getNumTVerts();
if(numTVerts>0)
{
fprintf(m_fileStream, "%s texture channel 1 -- numverts:<%d>\n", GetIndent(indent),numTVerts);
for (int i = 0; i < numTVerts; i++) 
{
UVVert tvert = mesh->tVerts[i];
fprintf(m_fileStream, "%s UVW tvert %d:<%f,%f,%f>\n", GetIndent(indent),i, tvert.x, tvert.y, tvert.z);
}
// print tvert indices used by tvfaces
for (int i = 0; i < mesh->getNumFaces(); i++) 
{
TVFace tface = mesh->tvFace[i];
fprintf(m_fileStream, "%s TVFace %d -- tvertind:<%d,%d,%d>\n", 
GetIndent(indent),i, tface.t[0], tface.t[1], tface.t[2]);
}                    
}
//多重貼圖 
for (int chanloop = 2; chanloop < MAX_MESHMAPS - 1; chanloop++)
{
if (mesh->mapSupport(chanloop)) 
{
numTVerts = mesh->getNumMapVerts(chanloop);
fprintf(m_fileStream, "%s texture channel %d -- numverts:<%d>\n", GetIndent(indent),chanloop, numTVerts);
for (int i = 0; i < numTVerts; i++) 
{
UVVert tvert = mesh->mapVerts(chanloop)[i];
fprintf(m_fileStream, "%s UVW tvert %d:<%f,%f,%f>\n", GetIndent(indent),i, tvert.x, tvert.y, tvert.z);
}
// now, print tvert indices used by tvfaces
for (int i = 0; i < mesh->getNumFaces(); i++) 
{
TVFace tface = mesh->mapFaces(chanloop)[i];
fprintf(m_fileStream, "%s TVFace %d -- tvertind:<%d,%d,%d>\n", GetIndent(indent),
i, tface.t[0], tface.t[1], tface.t[2]);
}                      
}
}
}


從簡單開始 邂逅Geometry

Download[onlygeometry.rar]

幾何體的導(dǎo)出是相當容易的,有了上次獲得Node的基礎(chǔ),獲得幾何體的信息就顯得順其自然了。

幾何體關(guān)心的主要信息就是頂點和三角面,自然還有紋理坐標,法線,頂點顏色,切線,BinNormal等等,不過這些都是后話,首先我們只關(guān)心頂點和面。

同時另外一個重要的信息就是矩陣信息,需要注意的是,在不同的Frame中矩陣信息很可能會發(fā)生變化,這點需要注意下。

在第一個例子的基礎(chǔ)上 只需要添加為數(shù)不多的代碼即可實現(xiàn)。

首先我們需要判斷結(jié)點是不是包含幾何體信息:

BOOL OnlyGeometry::nodeEnum(INode* node,int indent) 

{

……

ObjectState os = node->EvalWorldState(m_ip->GetTime()); 

if (os.obj) 

{

if(os.obj->SuperClassID()==GEOMOBJECT_CLASS_ID) 

{

ExportGeomObject(node,indent); 

}

}

for (int c = 0; c < node->NumberOfChildren(); c++) {

if (!nodeEnum(node->GetChildNode(c),indent+1))

return FALSE;

}

return TRUE;

}

然后在具體的導(dǎo)出幾何體的函數(shù)中,我們還需要再判斷一次:

void OnlyGeometry::ExportGeomObject(INode* node,int indent)

{

TimeValue time= m_ip->GetTime();

ObjectState os=node->EvalWorldState(time);

if(!os.obj)

return;

if (os.obj->ClassID() == Class_ID(TARGET_CLASS_ID, 0))

return;

…………………..

這是因為在3DS MAX中還有很多其他的物體也包含了幾何體信息,例如相機和燈光的Target部分,所以需要過濾一下。

然后就直接獲取我們需要的信息,首先是矩陣:我們使用

INode:: GetObjectTMAfterWSM()來獲得。這里WSM是World Space Modifier的縮寫。意思是在使用了World Space Modifier之后的矩陣。關(guān)于World Space Modifier的詳細信息可以參看SDK的文檔,因為本例中沒有用到任何的World Space Modifier。所以這里如果使用INode::GetObjectTM()的效果也是一樣的。

Matrix3 tm=node->GetObjTMAfterWSM(time);

Point3 row=tm.GetRow(0);

fprintf(m_fileStream,"%s%s<%f %f %f>\n",GetIndent(indent),_T("Matrix Row 0:"),row.x,row.y,row.z);

row=tm.GetRow(1);

fprintf(m_fileStream,"%s%s<%f %f %f>\n",GetIndent(indent),_T("Matrix Row 1:"),row.x,row.y,row.z);

row=tm.GetRow(2);

fprintf(m_fileStream,"%s%s<%f %f %f>\n",GetIndent(indent),_T("Matrix Row 2:"),row.x,row.y,row.z);

row=tm.GetRow(3);

fprintf(m_fileStream,"%s%s<%f %f %f>\n",GetIndent(indent),_T("Matrix Row 3:"),row.x,row.y,row.z);                                              

接下來就是頂點和三角面的導(dǎo)出,在Max中的結(jié)點并沒有直接保存了Mesh的信息,我們?nèi)绻@得Mesh的信息需要首先將Object轉(zhuǎn)化為Mesh,然后再從Mesh獲得具體的信息:

TriObject* triobj=0;

triobj=(TriObject*)os.obj->ConvertToType(time,Class_ID(TRIOBJ_CLASS_ID,0));

這里Max給我們執(zhí)行的其實是一個Deep Copy,所以我們可以等會轉(zhuǎn)換完成后把內(nèi)存釋放。

if(triobj!=os.obj) //deep copy

{

Mesh * mesh = &(triobj->GetMesh());

if(mesh)

{

mesh->buildNormals();

fprintf(m_fileStream,"%s%s\n",GetIndent(indent),_T("Geometry Data:"));

fprintf(m_fileStream,"%s%s%d%s%d\n",GetIndent(indent+1),_T("Vertex Number:"),mesh->getNumVerts(),_T("Face Number:"),mesh->getNumFaces());

//頂點信息

for(int i=0;i<mesh->getNumVerts();++i)

{

Point3 vert = tm * mesh->verts[i];

fprintf(m_fileStream, "%s vertex %d:<%f,%f,%f>\n", GetIndent(indent),i, vert.x, vert.y, vert.z);

}

//面信息

for (int i = 0; i < mesh->getNumFaces(); i++) 

{

fprintf(m_fileStream, "%s face %d -- verts:<%d,%d,%d> edgevis:<%d,%d,%d> smoothgrp:<0x%x> matid:<%d>\n", 

GetIndent(indent),

i, 

mesh->faces[i].v[0],

mesh->faces[i].v[1],

mesh->faces[i].v[2],

mesh->faces[i].getEdgeVis(0) ? 1 : 0,

mesh->faces[i].getEdgeVis(1) ? 1 : 0,

mesh->faces[i].getEdgeVis(2) ? 1 : 0,

mesh->faces[i].getSmGroup(),

mesh->faces[i].getMatID());

}

}

}

delete triobj;

fprintf(m_fileStream,"%s%s\n",GetIndent(indent),_T("Geometry End"));

fprintf(m_fileStream, "\n");

}



到此為止,我們的初步導(dǎo)出Geometry的工作就順利完成了,可以打開Max試一試,輸出的簡單的文件如下:

Begin Do Header

Begin Do Nodes

Totoal Node Number:3

Root Name:Scene Root

Node Name:Box01

Matrix Row 0:<1.000000 0.000000 0.000000>

Matrix Row 1:<0.000000 1.000000 0.000000>

Matrix Row 2:<0.000000 0.000000 1.000000>

Matrix Row 3:<-19.448299 -3.523636 0.000000>

Geometry Data:

Vertex Number:8Face Number:12

vertex 0:<-40.204018,-28.128052,0.000000>

vertex 1:<1.307419,-28.128052,0.000000>

vertex 2:<-40.204018,21.080780,0.000000>

vertex 3:<1.307419,21.080780,0.000000>

vertex 4:<-40.204018,-28.128052,24.273842>

vertex 5:<1.307419,-28.128052,24.273842>

vertex 6:<-40.204018,21.080780,24.273842>

vertex 7:<1.307419,21.080780,24.273842>

face 0 -- verts:<0,2,3> edgevis:<1,1,0> smoothgrp:<0x2> matid:<1>

face 1 -- verts:<3,1,0> edgevis:<1,1,0> smoothgrp:<0x2> matid:<1>

face 2 -- verts:<4,5,7> edgevis:<1,1,0> smoothgrp:<0x4> matid:<0>

face 3 -- verts:<7,6,4> edgevis:<1,1,0> smoothgrp:<0x4> matid:<0>

face 4 -- verts:<0,1,5> edgevis:<1,1,0> smoothgrp:<0x8> matid:<4>

face 5 -- verts:<5,4,0> edgevis:<1,1,0> smoothgrp:<0x8> matid:<4>

face 6 -- verts:<1,3,7> edgevis:<1,1,0> smoothgrp:<0x10> matid:<3>

face 7 -- verts:<7,5,1> edgevis:<1,1,0> smoothgrp:<0x10> matid:<3>

face 8 -- verts:<3,2,6> edgevis:<1,1,0> smoothgrp:<0x20> matid:<5>

face 9 -- verts:<6,7,3> edgevis:<1,1,0> smoothgrp:<0x20> matid:<5>

face 10 -- verts:<2,0,4> edgevis:<1,1,0> smoothgrp:<0x40> matid:<2>

face 11 -- verts:<4,6,2> edgevis:<1,1,0> smoothgrp:<0x40> matid:<2>

Geometry End



Node Name:Pyramid01

Matrix Row 0:<1.000000 0.000000 0.000000>

Matrix Row 1:<0.000000 1.000000 0.000000>

Matrix Row 2:<0.000000 0.000000 1.000000>

Matrix Row 3:<24.578979 -52.777748 0.005000>

Geometry Data:

Vertex Number:6Face Number:8

vertex 0:<24.578979,-52.777748,43.850536>

vertex 1:<-1.593857,-72.522881,0.005000>

vertex 2:<50.751816,-72.522881,0.005000>

vertex 3:<50.751816,-33.032616,0.005000>

vertex 4:<-1.593857,-33.032616,0.005000>

vertex 5:<24.578979,-52.777748,0.005000>

face 0 -- verts:<0,1,2> edgevis:<1,1,1> smoothgrp:<0x4> matid:<0>

face 1 -- verts:<0,2,3> edgevis:<1,1,1> smoothgrp:<0x2> matid:<0>

face 2 -- verts:<0,3,4> edgevis:<1,1,1> smoothgrp:<0x10> matid:<0>

face 3 -- verts:<0,4,1> edgevis:<1,1,1> smoothgrp:<0x20> matid:<0>

face 4 -- verts:<1,5,2> edgevis:<1,1,1> smoothgrp:<0x8> matid:<0>

face 5 -- verts:<2,5,3> edgevis:<1,1,1> smoothgrp:<0x8> matid:<0>

face 6 -- verts:<3,5,4> edgevis:<1,1,1> smoothgrp:<0x8> matid:<0>

face 7 -- verts:<4,5,1> edgevis:<1,1,1> smoothgrp:<0x8> matid:<0>

Geometry End

Node Name:Box02

Matrix Row 0:<1.000000 0.000000 0.000000>

Matrix Row 1:<0.000000 1.000000 0.000000>

Matrix Row 2:<0.000000 0.000000 1.000000>

Matrix Row 3:<128.516830 57.409515 0.000000>

Geometry Data:

Vertex Number:8Face Number:12

vertex 0:<111.216064,37.396194,0.000000>

vertex 1:<145.817596,37.396194,0.000000>

vertex 2:<111.216064,77.422836,0.000000>

vertex 3:<145.817596,77.422836,0.000000>

vertex 4:<111.216064,37.396194,-40.238293>

vertex 5:<145.817596,37.396194,-40.238293>

vertex 6:<111.216064,77.422836,-40.238293>

vertex 7:<145.817596,77.422836,-40.238293>

face 0 -- verts:<2,0,3> edgevis:<1,0,1> smoothgrp:<0x2> matid:<0>

face 1 -- verts:<1,3,0> edgevis:<1,0,1> smoothgrp:<0x2> matid:<0>

face 2 -- verts:<5,4,7> edgevis:<1,0,1> smoothgrp:<0x4> matid:<1>

face 3 -- verts:<6,7,4> edgevis:<1,0,1> smoothgrp:<0x4> matid:<1>

face 4 -- verts:<1,0,5> edgevis:<1,0,1> smoothgrp:<0x8> matid:<4>

face 5 -- verts:<4,5,0> edgevis:<1,0,1> smoothgrp:<0x8> matid:<4>

face 6 -- verts:<3,1,7> edgevis:<1,0,1> smoothgrp:<0x10> matid:<3>

face 7 -- verts:<5,7,1> edgevis:<1,0,1> smoothgrp:<0x10> matid:<3>

face 8 -- verts:<2,3,6> edgevis:<1,0,1> smoothgrp:<0x20> matid:<5>

face 9 -- verts:<7,6,3> edgevis:<1,0,1> smoothgrp:<0x20> matid:<5>

face 10 -- verts:<0,2,4> edgevis:<1,0,1> smoothgrp:<0x40> matid:<2>

face 11 -- verts:<6,4,2> edgevis:<1,0,1> smoothgrp:<0x40> matid:<2>

Geometry End

END MYEXPORTER

MAX Script Export/Import 
2個工作日
寫了一套簡單的Export/Import插件
一直對MAX的 Script感到很好奇
說說使用的感受吧。

首先,如果要使用這套Script那么 首先會陷入到龐大的MAX的概念的汪洋大海之中
MAX中很多概念不同于平常熟知的 RealTime里面的思想
例如,MAX中的紋理坐標,每個頂點都有一對UV 這個很正常
但是同時 MAX對每個Face也保存了UV,這是因為MAX中的 每個Face都有可能是不同的貼圖
等等

第二,如果熟悉了MAX中的哪些類能夠干什么 那么Script也就是很水道渠成的事情了。為了寫這2個插件,MAX Script 的help翻了無數(shù)次,幾乎每寫一句就要去翻一次。

第三,MAX中的數(shù)組起位置是1,但是MAX中有的概念 使用數(shù)組表示的時候起始位置為0 ,例如紋理的Channel,起始就是為0,并且Channel0  很危險,寫入錯誤直接讓MAX掛掉

第四,腳本編寫很考驗打字的準確度,由于變量沒有類型,不需要聲明就可以試用,打錯一個字母的話那就查吧,運氣不好的話,會讓你瘋掉的,同時MAX的腳本編輯器 超級難用。

第五,編寫導(dǎo)入插件的時候,發(fā)現(xiàn)Script 中讀入數(shù)據(jù)異常痛苦,我在Script的幫助中沒有發(fā)現(xiàn)任何類似c語言中的fprintf(%...)的東西,只有通過腳本提供的skiptostring來做。

第六 Max Script的函數(shù) 沒有明確的返回值的概念,不習(xí)慣

第七 那個調(diào)試器 太難用了,我打了無數(shù)個messagebox

總結(jié):對于導(dǎo)入導(dǎo)出插件來說其實用SDK和Script 編寫其實差別不大,因為都只是涉及到數(shù)據(jù)的讀取和寫入,并不涉及到復(fù)雜的邏輯。如果編寫渲染類型或者是動畫控制類型的插件 我覺得還是用script好一些,因為可以直接在MAX中看到結(jié)果,同時還能夠一句一句的執(zhí)行,很方便。

我只是初學(xué),希望有經(jīng)驗的人給點經(jīng)驗,最后附上簡單的插件代碼,
導(dǎo)出插件只能到處一個幾何體,點擊ExportGeo按鈕,然后點選幾何體,即可輸出
導(dǎo)入插件沒什么特別的操作,導(dǎo)入插件結(jié)尾有些倉促

以下是導(dǎo)入插件:其實導(dǎo)入插件沒什么必要寫,反正是在MAX中建模,直接保存為MAX文件就可以了,這里
純屬練手

macroScript ImportGeo category: "HowTo2"
(
--從文件中讀入某個分割符 后面 的數(shù)據(jù)
--FileStream:文件句柄
--needload :儲存讀取后的值的變量 (string or value)
--spliter:分隔符(string)
--bReadLine: 是否讀取分隔符后所有的數(shù)據(jù)  1表示讀取后面所有
fn LoadData FileStream spliter bReadLine=
(
temp=skiptostring FileStream spliter
if bReadLine==1 then
needload=readline FileStream
else
needload=readvalue FileStream

)
--***************************************************
--******************************************************
--****************************************************
vert_array = #()
face_array = #()
sgroup_array = #()
matid_array = #()
edge_array = #()

tm_row1=#()
tm_row2=#()
tm_row3=#()
tm_row4=#()
nodename=""
--以下均為material變量
_Material_Name
_Material_Type
_Material_Ambient
_Material_Diffuse
_Material_Specular
_Material_Specular_Lv
_Material_Glossiness
_Material_SelfillumColor
_Material_SelfillumAmount
_Material_DiffTexPath
BitmapPath

channel_num
UVW_Ver_Num
UVW_Face_Num
Vert_UV=#()          --所有的頂點的uv都放在這里
Face_UV=#()          --所有的面的uv都放在這里
Vert_UV_Size=#()  --用于記錄每個channel的頂點的uv總數(shù)
Face_UV_Size=#()  --用語及了每個channel的面uv總數(shù)

in_name=getopenfilename()
if in_name!=undefined then
(
in_file=openfile in_name
if in_file!=undefined then
(
--node name
temp= readline in_file 
token=filterString temp    " "    
nodename=(token[token.count] as string)
--**************************************************
--material info

_Material_Name=LoadData in_file  "->" 1
_Material_Type=LoadData in_file  "->" 1
_Material_Ambient=LoadData in_file  "->" 0
_Material_Diffuse=LoadData in_file  "->" 0
_Material_Specular=LoadData in_file  "->" 0
_Material_Specular_Lv=LoadData in_file  "->" 0
_Material_Glossiness=LoadData in_file  "->" 0
_Material_SelfillumColor=LoadData in_file  "->" 0
_Material_SelfillumAmount=LoadData in_file  "->" 0
_Material_DiffTexPath=LoadData in_file  "->" 1
--**************************************************

--node matrix
--temp= readline in_file

tt=readDelimitedString in_file ":"
temp=readvalue in_file
append tm_row1(temp)

tt=readDelimitedString in_file ":"
temp=readvalue in_file
append tm_row2(temp)

tt=readDelimitedString in_file ":"
temp=readvalue in_file
append tm_row3(temp)

tt=readDelimitedString in_file ":"
temp=readvalue in_file
append tm_row4(temp)

--************************************************
--vertex info
temp= readline in_file 
token=filterString temp    " "    
num_vert=token[token.count] as integer
for i=1 to num_vert do
(
tt=readDelimitedString in_file ":"
temp=readvalue in_file
append vert_array (temp)
)
--************************************************************
--face info
temp=readline in_file
token=filterstring temp " "
num_face=(token[token.count] as integer)
for j=1 to num_face do
(
append face_array (readValue in_file)
append sgroup_array (readValue in_file)
append matid_array (readValue in_file)
edge1 = readValue in_file
edge2 = readValue in_file
edge3 = readValue in_file
append edge_array (#(edge1, edge2, edge3))

)
--************************************************************
--uv info
-- in max channel begin with 0
--the channel 0 stores the vertex color info,no uv info

channel_num=LoadData in_file  ":" 0
for b=1 to (channel_num-1) do
(
--讀出Channel id
channel_id=LoadData in_file  ":" 0

--texture map path
BitmapPath=LoadData in_file  "->" 1

--讀出uv Vertex 的數(shù)量
temp_size=LoadData in_file ":" 0
append Vert_UV_Size temp_size

--uv的數(shù)據(jù)
for i=1 to temp_size do
(
append Vert_UV (readValue in_file)
)

--uv face的 數(shù)量
temp_size==LoadData in_file  ":" 0
append Face_UV_Size temp_size

for i=1 to temp_size do
(
append Face_uv (readValue in_file)
)

)
)
close in_file

)
meditmaterials[1].ambient=_Material_Ambient
meditmaterials[1].diffuse=_Material_Diffuse
meditmaterials[1].shaderbyname=_Material_type
meditmaterials[1].specular=_material_specular
meditmaterials[1].specularlevel=_material_specular_lv
meditmaterials[1].glossiness=_material_glossiness
meditmaterials[1].selfillumcolor=_Material_SelfillumColor
meditmaterials[1].selfillumamount=_Material_SelfillumAmount
meditmaterials[1].diffuseMapEnable=true
bmp =bitmaptexture filename: _Material_DiffTexPath
meditmaterials[1].diffusemap=bmp

new_mesh = mesh vertices:vert_array faces:face_array --materialIDs:#(0,1) tverts:vert_uv
for f = 1 to num_face do
(
setFaceSmoothGroup new_mesh f sgroup_array[f]
setFaceMatID new_mesh f matid_array[f]
setEdgeVis new_mesh f 1 edge_array[f][1] 
setEdgeVis new_mesh f 2 edge_array[f][2] 
setEdgeVis new_mesh f 3 edge_array[f][3] 
)
myTransform = new_mesh.transform
new_mesh.transform.row1 = tm_row1[1]
new_mesh.transform.row2 = tm_row2[1]
new_mesh.transform.row3 = tm_row3[1]
new_mesh.transform.row4 = tm_row4[1]

new_mesh.name=(nodename as string)

new_mesh.material=meditmaterials[1]

meshop.setMapSupport new_mesh 0 true
meshop.setMapSupport new_mesh 1 true

--set vertex uv for every vertex
meshop.setNumMapVerts new_mesh 1 Vert_UV_Size[1] keep:false
for i=1 to Vert_UV_Size[1] do
(
meshop.setMapVert new_mesh 1 i Vert_UV[i]
)

--set face uv for every face
meshop.setnummapfaces new_mesh 1 Face_UV_Size[1] keep:false
for i=1 to Face_UV_Size[1] do
(
meshop.setMapFace new_mesh 1 i Face_UV[i]
)

update new_mesh

)


以下是導(dǎo)出插件:
到處插件很容易寫,導(dǎo)入插件花了2倍于導(dǎo)出的時間


-- export by sssa2000
macroScript ExportGeo category:"HowTo2"
(
fn GetGeometry o = 
(

Superclassof o == Geometryclass and classof o != TargetObject 
)

fn DumpMaterial m file=
(
--只對Standard類型的材質(zhì)處理
--獲得diffuse and diffuse map
ismat=iskindof m material 
if ismat then
(

name=m.name
format "Material Name-> %\n" name to: file

class_of_mat=classof m
--messagebox class_of_mat
if (class_of_mat )==Standardmaterial then
(

type=m.shaderByName 
format "Material Type->%\n" type to: file

_ambient=m.ambient
format "Ambient Value->%\n" _ambient to:file

diffuse_value=m.diffuse
format "Diffuse Value->%\n" diffuse_value to:file

_specular=m.specular 
format "Specular Value->%\n" _specular to:file

_specularLevel =m.specularLevel 
format "SpecularLevel Value->%\n" _specularLevel to:file


_Glossiness=m.Glossiness 
format "Glossiness Value->%\n" _Glossiness to:file

_selfIllumColor =m.selfIllumColor 
format "SelfIllumColor Value->%\n" _selfIllumColor to:file

_selfIllumAmount =m.selfIllumAmount 
format "SelfIllumAmount Value->%\n" _selfIllumAmount to:file


diffuse_map_path=m.diffusemap.filename
format "Diffuse Map Path->%\n" diffuse_map_path to:file
)
)
format "\n" to: file
)
--/////////////////////////////////////////////////////////////////////////////////////////
obj = pickobject filter:GetGeometry

if isValidNode obj then
(
nodename=obj.name
--First export the matrix
row1=obj.transform.row1
row2=obj.transform.row2
row3=obj.transform.row3
row4=obj.transform.row4

tmesh = snapshotAsMesh obj 
out_name = GetSaveFileName()
if out_name != undefined then
(
out_file = createfile out_name

format "Node Name: %\n" nodename to: out_file
format "\n" to: out_file
--******************************************************
-- material info
node_material=obj.material
num_sub_material=getNumSubMtls obj.material
DumpMaterial obj.material out_file
for y=1 to num_sub_material do
(
sub_mat=getSubMtl obj.material y
DumpMaterial sub_mat= out_file
)
--******************************************************

format "Node TM Row1: %\n" row1 to: out_file
format "Node TM Row2: %\n" row2 to: out_file
format "Node TM Row3: %\n" row3 to: out_file
format "Node TM Row4: %\n" row4 to: out_file
--******************************************************
-- vertex info
num_verts = tmesh.numverts 
num_faces = tmesh.numfaces
format "Number of Ver: %\n" num_verts to:out_file
for v = 1 to num_verts do
format "Ver%: %\n" v (getVert tmesh v) to:out_file
format "\n" to:out_file
--***********************************************
--face info
format "Number of Face: %\n" num_faces to:out_file
for f = 1 to num_faces do
(
face = getFace tmesh f
sgroup = getFaceSmoothGroup tmesh f
matid = getFaceMatId tmesh f
edge1 = getEdgeVis tmesh f 1
edge2 = getEdgeVis tmesh f 2
edge3 = getEdgeVis tmesh f 3
format "%,%,%,%,%,%\n" face sgroup matid edge1 edge2 edge3 to:out_file
)
--******************************************************
--uv info
channel=meshop.getnummaps tmesh --number of texture
format "\n" to: out_file
format "Channel Number:%\n" channel to:out_file
for i=1 to (channel-1) do
(

-- channel的計數(shù)從0開始
--channel 0 is vertex color so do not export it
IsSupport=meshop.getMapSupport tmesh i
if IsSupport==true then
(
format "Channel ID:%\n" i to:out_file
if classof obj.material.maps[i+1]==Bitmaptexture then
format "Map File Path->%\n" obj.material.maps[i+1].filename to: out_file
else
format "Map File Path->Null\n" to: out_file
num_uv_ver=meshop.getNumMapVerts tmesh i
num_uv_face=meshop.getNumMapFaces tmesh i
format "UVW Vertex Number:%\n" num_uv_ver to:out_file
for j=1 to num_uv_ver do
(
vert_uvw=meshop.getMapVert tmesh i j 
--messagebox (vert_uvw as string)
format "% \n" vert_uvw to: out_file
)
format "UVW Face Number:%\n" num_uv_face to:out_file
for o=1 to num_uv_face do
(
uvw_face=meshop.getMapFace tmesh i o
format "% \n" uvw_face to: out_file
)
)
else
(
--format "Do Not Support Channel %\n" i to:out_file
)
)
close out_file
edit out_name
)

)

)

    3dmax插件大全
    (19)3dmax插件大全
    除了能夠制作出精細的模型外,其中最大的一個亮點就是它的插件功能強大,只要你能夠想到的效果,都有相應(yīng)的插件可以替你實現(xiàn)。這里西西給大家收集了很多非常實用的插件。插件后綴名介紹.位于建立命令面板中,可創(chuàng)建包括建模增加輔助物等的新對象。.位于變動命令面板中,增加新的修改命令,可在中找到。.屬于大氣效果燈或渲染類插件,位于的環(huán)境編輯器中,也可在菜單的面板中找到。.屬于特殊用途的插件,位于程序命令面板。.屬于后期...更多>>
    • 3dmax2010中文路徑貼圖補丁

      10-20 / 85.5M

      推薦理由:3dmax2010是我目前用的3dmax軟件中比較好的版本了,剛開始用這個軟件的童鞋,就會發(fā)現(xiàn)不能貼圖,你們想想國
    • 3dsmax森林插件 Forest Pack Pro3.

      04-02 / 30M

      推薦理由:Forest Pack Pro(森林插件)為3ds max提供了創(chuàng)建大面積森林及植被的完整解決方案,使用此插件你能夠創(chuàng)建數(shù)百
    • 幻景大師DreamScape for 3dsmax 20

      05-15 / 47.0M

      推薦理由: 由Ma5漢化。智能安裝,不需原版,內(nèi)附示例、教程、授權(quán)程序及安裝說明。 DreamScape又稱幻景大師,是
    • V-Ray for 3ds max 20112.00.02 中

      03-01 / 26.8M

      推薦理由: V-Ray 頂渲中英文雙語切換版,是學(xué)習(xí)及掌握V-Ray的最佳選擇,在使用時,可進行中英文自由切換,從而對
    • 3dmax模型三角面轉(zhuǎn)四邊面插件

      08-03 / 14KB

      推薦理由: 1 解壓 2打開(4polybomb mutimse)文件會看見 文件夾(scripts)和文件夾(ui)3 將scripts完全打開(
    • 3dmax森林制作插件(Forest Pack Pr

      10-19 / 25.9M

      推薦理由:Forest Pack Pro (專業(yè)森林制作)是 Itoo 出品的一款可以讓你在短時間內(nèi)做出專業(yè)的大面積樹林,草叢,人群等

    相關(guān)評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字數(shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)