豪仕知识网--知识就是力量!

微信
手机版
生活常识

3dsmaxsdk导出插件编写心得

作者 :姑苏慕容 2024-01-08 14:27:38 围观 : 评论

3dsmaxsdk导出插件编写心得

豪士君测试所用平台

以下就是我们整理的3dsmaxsdk导出插件编写心得,一起来看看,希望能帮助到您。

HTTP://WWW.haoz.net◐◐◐◐◐◐◐◐◐◐◐◐◐◐◐◐豪仕知识网

感觉3ds Max SDK实在是博大精深,初学者入门还是很不方便,所以觉得以前发的心得应该得到补充,因而写了这样一个导出程序介绍,还是抱着学习的态度,不过还是希望能够对大家有所帮助。

◐◐◐◐●☛█▼▲◐◐◐◐●☛█▼▲◐◐◐◐●☛█▼▲HTTP://WWW.hAoz.net███████████████████████████东方金报网

想想研究3D MAX 的SDK已经有了不短的时间,真正算起来也有两个月了吧,但是讲到收获,确实不大。作为一个3D MAX二次开发的学习者,我首先学习了导出插件的编写,网上有很多参考资料,写的都差不多,可是都是写到关键的地方或者说比较模糊的地方就说不清楚了,今天我就结合自己所做的工作来讲讲3D MAX导出插件的编写心得。

3Ds MAX2009 (3dmax) 中文精装版_附注册机 评分: 6.3 类别: 3D 制作 大小:56.6M 语言: 中文 查看详细信息 >>

环境配置:

◐◐◐◐●☛█▼▲豪仕知识网███████豪仕知识网HTtp://www.haoZ.net▼▲▼▲▼▲▼▲▼●●●●●●●▼▲▼▲▼▲

步骤1.首先你得有VS2005,3ds Max 9,如果有就好办了,否则想办法搞到手吧,在中国做到这点应该不难。至于其他相近版本的IDE和MAX,情况基本类似。

步骤2.在3ds Max9 SDK"maxsdk"howto"3dsmaxPluginWizard中有个readme.txt,它会向你介绍如何配置3ds Max9 plugin的向导。

步骤3.启动vs2005,新建Visual C++项目,如果在右侧的模板组中能够找到”3dsmaxPluginWizard”,并且选择后能够弹出欢迎界面,说面配置已经成功了。

●☛█▼▲豪仕知识网◐◐◐◐●☛█▼▲◐◐◐◐●☛█▼▲

首先,需要做好如下的准备工作:1. 安装一个完整版本的3D MAX与Visual Stdio。我安装的是3D MAX 2009,最好是找一个完整的版本,因为完整的版本中有很多的学习资料与sdk供学习,很省事。3D MAX的二次开发对VS的要求是有一个对应关系的,在SDK文档中可以找到,3D MAX 2009对应的VS开发版本应该是VS 2005,确保电脑上已经安装了VS 2005。2.定制3D MAX plug-in向导。a.找到安装目录的3dsmaxPluginWizard文件夹(我的安装目录是C:\Program Files\Autodesk\3ds Max 9 SDK\maxsdk\howto\3dsmaxPluginWizard),b.打开此目录下的MaxPluginWizard.vsz 文件,编辑ABSOLUTE PATH参数为: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选项,说明定制成功。以上只是开发前的一些准备工作,都可以直接在3D MAX SDK的文档中直接找到,不过文档可都是英文的哦,要耐心的读下去。在以上准备工作做好以后,就可以开始开发一个插件了,由简单到复杂,先做一个简单的插件程序。插件程序的编写有两种方法,一是用插件向导,就是刚才上面所说的;另一种是通过手工创建一个插件项目,在这里暂时只讨论用插件向导来开发,比较便捷,手工开发以后在补上。1.第一步,生成一个插件程序的工程,具体如下:a. 打开File —>New Project —>选择3ds max Plugin Wizard,输入project名字,如 “MyExport”。b. 进入Welcome to the 3ds max Plugin Wizard 画面,选择plugin type如图所示:

◐◐◐◐●☛█▼▲豪仕知识网███████豪仕知识网HTtp://www.haoZ.net▼▲▼▲▼▲▼▲▼●●●●●●●▼▲▼▲▼▲

c.这里显示各种插件类型,目前要做的是一个文件的导出插件,所以选择FileExport类型。d.下一步,再出现一个对话框

不用去管这些Plugin Detail,会有默认路径的,。 e.再下一步,设置一些路径,具体见图及注明。

注明:Enter your MAXSDK path指的是3D MAX SDK的安装目录Enter your Plugin output path 指的是生成插件文件.dll存放的目录,可以自己设置Enter your 3dsmax.exe path指的是3D MAX的安装目录2.项目生成以后,在MyExport.cpp文件中找到Ext(int n)函数,改为return _T("MY3D"), "MY3D"是根据自己的要求来添加的;找到ShortDesc()函数,改为return _T ("MyExportPlugin");找到DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)内添加:AllocConsole();_cprintf( "Export Begin\n" );//记得#include 3. 生成并调试你的插件,系统会执行3dsmax.exe以启动3ds Max,然后选择“文件”->”导出”,如果能看到"MyExportPlugin(*.My3D)"说明导出成功,然后定义一个导出文件的名称即可.这样一个空的导出插件就编写成功了!接下来请看: 3D MAX导出插件编写II Export利器:IGame古人云:君子生非异也,善假于物也数据导出是一个繁琐的工作,于是,有了IGame这个解脱程序员的东西:关于IGameIGame是Max提供给游戏开发的一个用于导入导出的接口。在Max的help里面这个东西叫做3ds Max Data Exchange Interface。有了这个接口,可以大大的简化导入导出工作的工作量。如果有经历过用MAX SDK导出关键帧动画以及骨骼动画,Skin,Modifier等等的经历的话,我想肯定会记忆深刻。IGame的作用就是把复杂的Max的概念简化,封装。建立IGame:IGameScene * m_pIgame= GetIGameInterface()坐标系:前面我提到的导出的文章都没有提这个问题,所有的坐标都是用的MAX本身的坐标系,及Z轴向上。在游戏中坐标系可能千奇百怪,IGame考虑到这点提供了指定坐标系的功能:IGameConversionManager * cm = GetConversionManager();cm->SetCoordSystem(IGameConversionManager::IGAME_D3D);m_pIgame->InitialiseIGame(true);其中IGAME_D3D就是指定的坐标系,同样也可以自定义坐标系:UserCoord WhackySystem = {1, //Right Handed1, //X axis goes right4, //Y Axis goes in3, //Z Axis goes down.0, //U Tex axis is left1, //V Tex axis is Down}; IGameConversionManager * cm = GetConversionManager();cm->SetUserCoordSystem(WhackySystem); IGame要点:GetTopLevelNodeCount:获得顶级的Node数目,不包括Root。GetRootMaterialCount:获得所有的材质数目GetTopLevelNode(i):获得指定NodeGetIGameObject():获得Node中包含的ObjectGetLocalTM():获得Node的矩阵IGameMesh ::GetVertex(i):获得顶点IGameMesh ::GetFace(i);获得面IGameMesh ::GetNormal(i):获得法线至于其他就依次类推了,从函数的命名,到概念的简化,无疑都比原始的MAXSDK进步了很多。有了IGame接口,大大减轻了程序员的负担,我相信没有哪个愿意把大把的时间花在数据的导入导出上。花了几十分钟简单的试用了一下IGame写了个小小的导出插件,只导出了顶点,面,材质,法线以及矩阵,感觉基本上没什么阻碍。不过IGame最大的功能还是用在骨骼动画,关键帧动画上面,仅仅只是简单的几何体导出并不能体现出IGame的功效。最后还是附上代码和工程吧。不得不提示一下,由于种种曲折的原因,我这个工程是在MAX8 SDK和 MAX8下 完成的,其间省略上千字曲折的经历,不过在MAX9下应该可以通过编译。编译完成后,记得在Max 中选择Export Selected而不是试用Export。3DS MAX PlugIn 材质和纹理 材质和纹理的信息都位于node 中材质的信息通过类Mtl获得纹理的信息位于node中的mesh 中的UVVert以下是获得材质的代码:////////////////////////////////////////////////////////////////////////////materialMtl* 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 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 tvfacesfor (int i = 0; i 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 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 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 tvfacesfor (int i = 0; i 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]);} }}}从简单开始 邂逅GeometryDownload[onlygeometry.rar]几何体的导出是相当容易的,有了上次获得Node的基础,获得几何体的信息就显得顺其自然了。几何体关心的主要信息就是顶点和三角面,自然还有纹理坐标,法线,顶点颜色,切线,BinNormal等等,不过这些都是后话,首先我们只关心顶点和面。同时另外一个重要的信息就是矩阵信息,需要注意的是,在不同的Frame中矩阵信息很可能会发生变化,这点需要注意下。在第一个例子的基础上 只需要添加为数不多的代码即可实现。首先我们需要判断结点是不是包含几何体信息: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 NumberOfChildren(); c++) {if (!nodeEnum(node->GetChildNode(c),indent+1))return FALSE;}return TRUE;}然后在具体的导出几何体的函数中,我们还需要再判断一次: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之后的矩阵。关于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); 接下来就是顶点和三角面的导出,在Max中的结点并没有直接保存了Mesh的信息,我们如果要获得Mesh的信息需要首先将Object转化为Mesh,然后再从Mesh获得具体的信息:TriObject* triobj=0;triobj=(TriObject*)os.obj->ConvertToType(time,Class_ID(TRIOBJ_CLASS_ID,0));这里Max给我们执行的其实是一个Deep Copy,所以我们可以等会转换完成后把内存释放。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;igetNumVerts();++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 getNumFaces(); i++){fprintf(m_fileStream, "%s face %d -- verts:<%d,%d,%d> edgevis:<%d,%d,%d> smoothgrp: 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");}到此为止,我们的初步导出Geometry的工作就顺利完成了,可以打开Max试一试,输出的简单的文件如下:Begin Do HeaderBegin Do NodesTotoal Node Number:3Root Name:Scene RootNode Name:Box01Matrix Row 0:Matrix Row 1:Matrix Row 2:Matrix Row 3:Geometry Data:Vertex Number:8Face Number:12vertex 0:vertex 1:vertex 2:vertex 3:vertex 4:vertex 5:vertex 6:vertex 7:face 0 -- verts: edgevis: smoothgrp: matid:face 1 -- verts: edgevis: smoothgrp: matid:face 2 -- verts: edgevis: smoothgrp: matid:face 3 -- verts: edgevis: smoothgrp: matid:face 4 -- verts: edgevis: smoothgrp: matid:face 5 -- verts: edgevis: smoothgrp: matid:face 6 -- verts: edgevis: smoothgrp: matid:face 7 -- verts: edgevis: smoothgrp: matid:face 8 -- verts: edgevis: smoothgrp: matid:face 9 -- verts: edgevis: smoothgrp: matid:face 10 -- verts: edgevis: smoothgrp: matid:face 11 -- verts: edgevis: smoothgrp: matid:Geometry EndNode Name:Pyramid01Matrix Row 0:Matrix Row 1:Matrix Row 2:Matrix Row 3:Geometry Data:Vertex Number:6Face Number:8vertex 0:vertex 1:vertex 2:vertex 3:vertex 4:vertex 5:face 0 -- verts: edgevis: smoothgrp: matid:face 1 -- verts: edgevis: smoothgrp: matid:face 2 -- verts: edgevis: smoothgrp: matid:face 3 -- verts: edgevis: smoothgrp: matid:face 4 -- verts: edgevis: smoothgrp: matid:face 5 -- verts: edgevis: smoothgrp: matid:face 6 -- verts: edgevis: smoothgrp: matid:face 7 -- verts: edgevis: smoothgrp: matid:Geometry EndNode Name:Box02Matrix Row 0:Matrix Row 1:Matrix Row 2:Matrix Row 3:Geometry Data:Vertex Number:8Face Number:12vertex 0:vertex 1:vertex 2:vertex 3:vertex 4:vertex 5:vertex 6:vertex 7:face 0 -- verts: edgevis: smoothgrp: matid:face 1 -- verts: edgevis: smoothgrp: matid:face 2 -- verts: edgevis: smoothgrp: matid:face 3 -- verts: edgevis: smoothgrp: matid:face 4 -- verts: edgevis: smoothgrp: matid:face 5 -- verts: edgevis: smoothgrp: matid:face 6 -- verts: edgevis: smoothgrp: matid:face 7 -- verts: edgevis: smoothgrp: matid:face 8 -- verts: edgevis: smoothgrp: matid:face 9 -- verts: edgevis: smoothgrp: matid:face 10 -- verts: edgevis: smoothgrp: matid:face 11 -- verts: edgevis: smoothgrp: matid:Geometry EndEND MYEXPORTERMAX Script Export/Import2个工作日写了一套简单的Export/Import插件一直对MAX的 Script感到很好奇说说使用的感受吧。首先,如果要使用这套Script那么 首先会陷入到庞大的MAX的概念的汪洋大海之中MAX中很多概念不同于平常熟知的 RealTime里面的思想例如,MAX中的纹理坐标,每个顶点都有一对UV 这个很正常但是同时 MAX对每个Face也保存了UV,这是因为MAX中的 每个Face都有可能是不同的贴图等等第二,如果熟悉了MAX中的哪些类能够干什么 那么Script也就是很水道渠成的事情了。为了写这2个插件,MAX Script 的help翻了无数次,几乎每写一句就要去翻一次。第三,MAX中的数组起位置是1,但是MAX中有的概念 使用数组表示的时候起始位置为0 ,例如纹理的Channel,起始就是为0,并且Channel0 很危险,写入错误直接让MAX挂掉第四,脚本编写很考验打字的准确度,由于变量没有类型,不需要声明就可以试用,打错一个字母的话那就查吧,运气不好的话,会让你疯掉的,同时MAX的脚本编辑器 超级难用。第五,编写导入插件的时候,发现Script 中读入数据异常痛苦,我在Script的帮助中没有发现任何类似c语言中的fprintf(%...)的东西,只有通过脚本提供的skiptostring来做。第六 Max Script的函数 没有明确的返回值的概念,不习惯第七 那个调试器 太难用了,我打了无数个messagebox总结:对于导入导出插件来说其实用SDK和Script 编写其实差别不大,因为都只是涉及到数据的读取和写入,并不涉及到复杂的逻辑。如果编写渲染类型或者是动画控制类型的插件 我觉得还是用script好一些,因为可以直接在MAX中看到结果,同时还能够一句一句的执行,很方便。我只是初学,希望有经验的人给点经验,最后附上简单的插件代码,导出插件只能到处一个几何体,点击ExportGeo按钮,然后点选几何体,即可输出导入插件没什么特别的操作,导入插件结尾有些仓促以下是导入插件:其实导入插件没什么必要写,反正是在MAX中建模,直接保存为MAX文件就可以了,这里纯属练手macroScript ImportGeo category: "HowTo2"(--从文件中读入某个分割符 后面 的数据--FileStream:文件句柄--needload :储存读取后的值的变量 (string or value)--spliter:分隔符(string)--bReadLine: 是否读取分隔符后所有的数据 1表示读取后面所有fn LoadData FileStream spliter bReadLine=(temp=skiptostring FileStream spliterif bReadLine==1 thenneedload=readline FileStreamelseneedload=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_DiffTexPathBitmapPathchannel_numUVW_Ver_NumUVW_Face_NumVert_UV=#() --所有的顶点的uv都放在这里Face_UV=#() --所有的面的uv都放在这里Vert_UV_Size=#() --用于记录每个channel的顶点的uv总数Face_UV_Size=#() --用语及了每个channel的面uv总数in_name=getopenfilename()if in_name!=undefined then(in_file=openfile in_nameif in_file!=undefined then(--node nametemp= readline in_filetoken=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_filett=readDelimitedString in_file ":"temp=readvalue in_fileappend tm_row1(temp)tt=readDelimitedString in_file ":"temp=readvalue in_fileappend tm_row2(temp)tt=readDelimitedString in_file ":"temp=readvalue in_fileappend tm_row3(temp)tt=readDelimitedString in_file ":"temp=readvalue in_fileappend tm_row4(temp)--************************************************--vertex infotemp= readline in_filetoken=filterString temp " " num_vert=token[token.count] as integerfor i=1 to num_vert do(tt=readDelimitedString in_file ":"temp=readvalue in_fileappend vert_array (temp))--************************************************************--face infotemp=readline in_filetoken=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_fileedge2 = readValue in_fileedge3 = readValue in_fileappend edge_array (#(edge1, edge2, edge3)))--************************************************************--uv info-- in max channel begin with 0--the channel 0 stores the vertex color info,no uv infochannel_num=LoadData in_file ":" 0for b=1 to (channel_num-1) do(--读出Channel idchannel_id=LoadData in_file ":" 0--texture map pathBitmapPath=LoadData in_file "->" 1--读出uv Vertex 的数量temp_size=LoadData in_file ":" 0append Vert_UV_Size temp_size--uv的数据for i=1 to temp_size do(append Vert_UV (readValue in_file))--uv face的 数量temp_size==LoadData in_file ":" 0append Face_UV_Size temp_sizefor i=1 to temp_size do(append Face_uv (readValue in_file))))close in_file)meditmaterials[1].ambient=_Material_Ambientmeditmaterials[1].diffuse=_Material_Diffusemeditmaterials[1].shaderbyname=_Material_typemeditmaterials[1].specular=_material_specularmeditmaterials[1].specularlevel=_material_specular_lvmeditmaterials[1].glossiness=_material_glossinessmeditmaterials[1].selfillumcolor=_Material_SelfillumColormeditmaterials[1].selfillumamount=_Material_SelfillumAmountmeditmaterials[1].diffuseMapEnable=truebmp =bitmaptexture filename: _Material_DiffTexPathmeditmaterials[1].diffusemap=bmpnew_mesh = mesh vertices:vert_array faces:face_array --materialIDs:#(0,1) tverts:vert_uvfor 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.transformnew_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 truemeshop.setMapSupport new_mesh 1 true--set vertex uv for every vertexmeshop.setNumMapVerts new_mesh 1 Vert_UV_Size[1] keep:falsefor i=1 to Vert_UV_Size[1] do(meshop.setMapVert new_mesh 1 i Vert_UV[i])--set face uv for every facemeshop.setnummapfaces new_mesh 1 Face_UV_Size[1] keep:falsefor i=1 to Face_UV_Size[1] do(meshop.setMapFace new_mesh 1 i Face_UV[i])update new_mesh)以下是导出插件:到处插件很容易写,导入插件花了2倍于导出的时间-- export by sssa2000macroScript ExportGeo category:"HowTo2"(fn GetGeometry o =(Superclassof o == Geometryclass and classof o != TargetObject)fn DumpMaterial m file=(--只对Standard类型的材质处理--获得diffuse and diffuse mapismat=iskindof m materialif ismat then(name=m.nameformat "Material Name-> %\n" name to: fileclass_of_mat=classof m--messagebox class_of_matif (class_of_mat )==Standardmaterial then(type=m.shaderByNameformat "Material Type->%\n" type to: file_ambient=m.ambientformat "Ambient Value->%\n" _ambient to:filediffuse_value=m.diffuseformat "Diffuse Value->%\n" diffuse_value to:file_specular=m.specularformat "Specular Value->%\n" _specular to:file_specularLevel =m.specularLevelformat "SpecularLevel Value->%\n" _specularLevel to:file_Glossiness=m.Glossinessformat "Glossiness Value->%\n" _Glossiness to:file_selfIllumColor =m.selfIllumColorformat "SelfIllumColor Value->%\n" _selfIllumColor to:file_selfIllumAmount =m.selfIllumAmountformat "SelfIllumAmount Value->%\n" _selfIllumAmount to:filediffuse_map_path=m.diffusemap.filenameformat "Diffuse Map Path->%\n" diffuse_map_path to:file))format "\n" to: file)--/////////////////////////////////////////////////////////////////////////////////////////obj = pickobject filter:GetGeometryif isValidNode obj then(nodename=obj.name--First export the matrixrow1=obj.transform.row1row2=obj.transform.row2row3=obj.transform.row3row4=obj.transform.row4tmesh = snapshotAsMesh objout_name = GetSaveFileName()if out_name != undefined then(out_file = createfile out_nameformat "Node Name: %\n" nodename to: out_fileformat "\n" to: out_file--******************************************************-- material infonode_material=obj.materialnum_sub_material=getNumSubMtls obj.materialDumpMaterial obj.material out_filefor y=1 to num_sub_material do(sub_mat=getSubMtl obj.material yDumpMaterial sub_mat= out_file)--******************************************************format "Node TM Row1: %\n" row1 to: out_fileformat "Node TM Row2: %\n" row2 to: out_fileformat "Node TM Row3: %\n" row3 to: out_fileformat "Node TM Row4: %\n" row4 to: out_file--******************************************************-- vertex infonum_verts = tmesh.numvertsnum_faces = tmesh.numfacesformat "Number of Ver: %\n" num_verts to:out_filefor v = 1 to num_verts doformat "Ver%: %\n" v (getVert tmesh v) to:out_fileformat "\n" to:out_file--***********************************************--face infoformat "Number of Face: %\n" num_faces to:out_filefor f = 1 to num_faces do(face = getFace tmesh fsgroup = getFaceSmoothGroup tmesh fmatid = getFaceMatId tmesh fedge1 = getEdgeVis tmesh f 1edge2 = getEdgeVis tmesh f 2edge3 = getEdgeVis tmesh f 3format "%,%,%,%,%,%\n" face sgroup matid edge1 edge2 edge3 to:out_file)--******************************************************--uv infochannel=meshop.getnummaps tmesh --number of textureformat "\n" to: out_fileformat "Channel Number:%\n" channel to:out_filefor i=1 to (channel-1) do(-- channel的计数从0开始--channel 0 is vertex color so do not export itIsSupport=meshop.getMapSupport tmesh iif IsSupport==true then(format "Channel ID:%\n" i to:out_fileif classof obj.material.maps[i+1]==Bitmaptexture thenformat "Map File Path->%\n" obj.material.maps[i+1].filename to: out_fileelseformat "Map File Path->Null\n" to: out_filenum_uv_ver=meshop.getNumMapVerts tmesh inum_uv_face=meshop.getNumMapFaces tmesh iformat "UVW Vertex Number:%\n" num_uv_ver to:out_filefor 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_filefor o=1 to num_uv_face do(uvw_face=meshop.getMapFace tmesh i oformat "% \n" uvw_face to: out_file))else(--format "Do Not Support Channel %\n" i to:out_file))close out_fileedit out_name)))

●☛█▼▲豪仕知识网◐◐◐◐●☛█▼▲◐◐◐◐●☛█▼▲

感觉3ds Max SDK实在是博大精深,初学者入门还是很不方便,所以觉得以前发的心得应该得到补充,因而写了这样一个导出程序介绍,还是抱着学习的态度,不过还是希望能够对大家有所帮助。

想想研究3D MAX 的SDK已经有了不短的时间,真正算起来也有两个月了吧,但是讲到收获,确实不大。作为一个3D MAX二次开发的学习者,我首先学习了导出插件的编写,网上有很多参考资料,写的都差不多,可是都是写到关键的地方或者说比较模糊的地方就说不清楚了,今天我就结合自己所做的工作来讲讲3D MAX导出插件的编写心得。

●☛█▼▲豪仕知识网◐◐◐◐●☛█▼▲◐◐◐◐●☛█▼▲

3Ds MAX2009 (3dmax) 中文精装版_附注册机 评分: 6.3 类别: 3D 制作 大小:56.6M 语言: 中文 查看详细信息 >>

环境配置:

◐◐◐◐●☛█▼▲豪仕知识网http://www.haOz.net▼▲▼▲▼▲▼▲▼●●●●●●●▼▲▼▲▼▲

步骤1.首先你得有VS2005,3ds Max 9,如果有就好办了,否则想办法搞到手吧,在中国做到这点应该不难。至于其他相近版本的IDE和MAX,情况基本类似。

步骤2.在3ds Max9 SDK"maxsdk"howto"3dsmaxPluginWizard中有个readme.txt,它会向你介绍如何配置3ds Max9 plugin的向导。

步骤3.启动vs2005,新建Visual C++项目,如果在右侧的模板组中能够找到”3dsmaxPluginWizard”,并且选择后能够弹出欢迎界面,说面配置已经成功了。

◐◐◐◐●☛█▼▲豪仕知识网http://www.haOz.net▼▲▼▲▼▲▼▲▼●●●●●●●▼▲▼▲▼▲

首先,需要做好如下的准备工作:1. 安装一个完整版本的3D MAX与Visual Stdio。我安装的是3D MAX 2009,最好是找一个完整的版本,因为完整的版本中有很多的学习资料与sdk供学习,很省事。3D MAX的二次开发对VS的要求是有一个对应关系的,在SDK文档中可以找到,3D MAX 2009对应的VS开发版本应该是VS 2005,确保电脑上已经安装了VS 2005。2.定制3D MAX plug-in向导。a.找到安装目录的3dsmaxPluginWizard文件夹(我的安装目录是C:\Program Files\Autodesk\3ds Max 9 SDK\maxsdk\howto\3dsmaxPluginWizard),b.打开此目录下的MaxPluginWizard.vsz 文件,编辑ABSOLUTE PATH参数为: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选项,说明定制成功。以上只是开发前的一些准备工作,都可以直接在3D MAX SDK的文档中直接找到,不过文档可都是英文的哦,要耐心的读下去。在以上准备工作做好以后,就可以开始开发一个插件了,由简单到复杂,先做一个简单的插件程序。插件程序的编写有两种方法,一是用插件向导,就是刚才上面所说的;另一种是通过手工创建一个插件项目,在这里暂时只讨论用插件向导来开发,比较便捷,手工开发以后在补上。1.第一步,生成一个插件程序的工程,具体如下:a. 打开File —>New Project —>选择3ds max Plugin Wizard,输入project名字,如 “MyExport”。b. 进入Welcome to the 3ds max Plugin Wizard 画面,选择plugin type如图所示:

c.这里显示各种插件类型,目前要做的是一个文件的导出插件,所以选择FileExport类型。d.下一步,再出现一个对话框

不用去管这些Plugin Detail,会有默认路径的,。 e.再下一步,设置一些路径,具体见图及注明。

◐◐◐◐●☛█▼▲豪仕知识网http://www.haOz.net▼▲▼▲▼▲▼▲▼●●●●●●●▼▲▼▲▼▲

注明:Enter your MAXSDK path指的是3D MAX SDK的安装目录Enter your Plugin output path 指的是生成插件文件.dll存放的目录,可以自己设置Enter your 3dsmax.exe path指的是3D MAX的安装目录2.项目生成以后,在MyExport.cpp文件中找到Ext(int n)函数,改为return _T("MY3D"), "MY3D"是根据自己的要求来添加的;找到ShortDesc()函数,改为return _T ("MyExportPlugin");找到DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)内添加:AllocConsole();_cprintf( "Export Begin\n" );//记得#include 3. 生成并调试你的插件,系统会执行3dsmax.exe以启动3ds Max,然后选择“文件”->”导出”,如果能看到"MyExportPlugin(*.My3D)"说明导出成功,然后定义一个导出文件的名称即可.这样一个空的导出插件就编写成功了!接下来请看: 3D MAX导出插件编写II Export利器:IGame古人云:君子生非异也,善假于物也数据导出是一个繁琐的工作,于是,有了IGame这个解脱程序员的东西:关于IGameIGame是Max提供给游戏开发的一个用于导入导出的接口。在Max的help里面这个东西叫做3ds Max Data Exchange Interface。有了这个接口,可以大大的简化导入导出工作的工作量。如果有经历过用MAX SDK导出关键帧动画以及骨骼动画,Skin,Modifier等等的经历的话,我想肯定会记忆深刻。IGame的作用就是把复杂的Max的概念简化,封装。建立IGame:IGameScene * m_pIgame= GetIGameInterface()坐标系:前面我提到的导出的文章都没有提这个问题,所有的坐标都是用的MAX本身的坐标系,及Z轴向上。在游戏中坐标系可能千奇百怪,IGame考虑到这点提供了指定坐标系的功能:IGameConversionManager * cm = GetConversionManager();cm->SetCoordSystem(IGameConversionManager::IGAME_D3D);m_pIgame->InitialiseIGame(true);其中IGAME_D3D就是指定的坐标系,同样也可以自定义坐标系:UserCoord WhackySystem = {1, //Right Handed1, //X axis goes right4, //Y Axis goes in3, //Z Axis goes down.0, //U Tex axis is left1, //V Tex axis is Down}; IGameConversionManager * cm = GetConversionManager();cm->SetUserCoordSystem(WhackySystem); IGame要点:GetTopLevelNodeCount:获得顶级的Node数目,不包括Root。GetRootMaterialCount:获得所有的材质数目GetTopLevelNode(i):获得指定NodeGetIGameObject():获得Node中包含的ObjectGetLocalTM():获得Node的矩阵IGameMesh ::GetVertex(i):获得顶点IGameMesh ::GetFace(i);获得面IGameMesh ::GetNormal(i):获得法线至于其他就依次类推了,从函数的命名,到概念的简化,无疑都比原始的MAXSDK进步了很多。有了IGame接口,大大减轻了程序员的负担,我相信没有哪个愿意把大把的时间花在数据的导入导出上。花了几十分钟简单的试用了一下IGame写了个小小的导出插件,只导出了顶点,面,材质,法线以及矩阵,感觉基本上没什么阻碍。不过IGame最大的功能还是用在骨骼动画,关键帧动画上面,仅仅只是简单的几何体导出并不能体现出IGame的功效。最后还是附上代码和工程吧。不得不提示一下,由于种种曲折的原因,我这个工程是在MAX8 SDK和 MAX8下 完成的,其间省略上千字曲折的经历,不过在MAX9下应该可以通过编译。编译完成后,记得在Max 中选择Export Selected而不是试用Export。3DS MAX PlugIn 材质和纹理 材质和纹理的信息都位于node 中材质的信息通过类Mtl获得纹理的信息位于node中的mesh 中的UVVert以下是获得材质的代码:////////////////////////////////////////////////////////////////////////////materialMtl* 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 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 tvfacesfor (int i = 0; i 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 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 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 tvfacesfor (int i = 0; i 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]);} }}}从简单开始 邂逅GeometryDownload[onlygeometry.rar]几何体的导出是相当容易的,有了上次获得Node的基础,获得几何体的信息就显得顺其自然了。几何体关心的主要信息就是顶点和三角面,自然还有纹理坐标,法线,顶点颜色,切线,BinNormal等等,不过这些都是后话,首先我们只关心顶点和面。同时另外一个重要的信息就是矩阵信息,需要注意的是,在不同的Frame中矩阵信息很可能会发生变化,这点需要注意下。在第一个例子的基础上 只需要添加为数不多的代码即可实现。首先我们需要判断结点是不是包含几何体信息: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 NumberOfChildren(); c++) {if (!nodeEnum(node->GetChildNode(c),indent+1))return FALSE;}return TRUE;}然后在具体的导出几何体的函数中,我们还需要再判断一次: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之后的矩阵。关于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); 接下来就是顶点和三角面的导出,在Max中的结点并没有直接保存了Mesh的信息,我们如果要获得Mesh的信息需要首先将Object转化为Mesh,然后再从Mesh获得具体的信息:TriObject* triobj=0;triobj=(TriObject*)os.obj->ConvertToType(time,Class_ID(TRIOBJ_CLASS_ID,0));这里Max给我们执行的其实是一个Deep Copy,所以我们可以等会转换完成后把内存释放。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;igetNumVerts();++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 getNumFaces(); i++){fprintf(m_fileStream, "%s face %d -- verts:<%d,%d,%d> edgevis:<%d,%d,%d> smoothgrp: 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");}到此为止,我们的初步导出Geometry的工作就顺利完成了,可以打开Max试一试,输出的简单的文件如下:Begin Do HeaderBegin Do NodesTotoal Node Number:3Root Name:Scene RootNode Name:Box01Matrix Row 0:Matrix Row 1:Matrix Row 2:Matrix Row 3:Geometry Data:Vertex Number:8Face Number:12vertex 0:vertex 1:vertex 2:vertex 3:vertex 4:vertex 5:vertex 6:vertex 7:face 0 -- verts: edgevis: smoothgrp: matid:face 1 -- verts: edgevis: smoothgrp: matid:face 2 -- verts: edgevis: smoothgrp: matid:face 3 -- verts: edgevis: smoothgrp: matid:face 4 -- verts: edgevis: smoothgrp: matid:face 5 -- verts: edgevis: smoothgrp: matid:face 6 -- verts: edgevis: smoothgrp: matid:face 7 -- verts: edgevis: smoothgrp: matid:face 8 -- verts: edgevis: smoothgrp: matid:face 9 -- verts: edgevis: smoothgrp: matid:face 10 -- verts: edgevis: smoothgrp: matid:face 11 -- verts: edgevis: smoothgrp: matid:Geometry EndNode Name:Pyramid01Matrix Row 0:Matrix Row 1:Matrix Row 2:Matrix Row 3:Geometry Data:Vertex Number:6Face Number:8vertex 0:vertex 1:vertex 2:vertex 3:vertex 4:vertex 5:face 0 -- verts: edgevis: smoothgrp: matid:face 1 -- verts: edgevis: smoothgrp: matid:face 2 -- verts: edgevis: smoothgrp: matid:face 3 -- verts: edgevis: smoothgrp: matid:face 4 -- verts: edgevis: smoothgrp: matid:face 5 -- verts: edgevis: smoothgrp: matid:face 6 -- verts: edgevis: smoothgrp: matid:face 7 -- verts: edgevis: smoothgrp: matid:Geometry EndNode Name:Box02Matrix Row 0:Matrix Row 1:Matrix Row 2:Matrix Row 3:Geometry Data:Vertex Number:8Face Number:12vertex 0:vertex 1:vertex 2:vertex 3:vertex 4:vertex 5:vertex 6:vertex 7:face 0 -- verts: edgevis: smoothgrp: matid:face 1 -- verts: edgevis: smoothgrp: matid:face 2 -- verts: edgevis: smoothgrp: matid:face 3 -- verts: edgevis: smoothgrp: matid:face 4 -- verts: edgevis: smoothgrp: matid:face 5 -- verts: edgevis: smoothgrp: matid:face 6 -- verts: edgevis: smoothgrp: matid:face 7 -- verts: edgevis: smoothgrp: matid:face 8 -- verts: edgevis: smoothgrp: matid:face 9 -- verts: edgevis: smoothgrp: matid:face 10 -- verts: edgevis: smoothgrp: matid:face 11 -- verts: edgevis: smoothgrp: matid:Geometry EndEND MYEXPORTERMAX Script Export/Import2个工作日写了一套简单的Export/Import插件一直对MAX的 Script感到很好奇说说使用的感受吧。首先,如果要使用这套Script那么 首先会陷入到庞大的MAX的概念的汪洋大海之中MAX中很多概念不同于平常熟知的 RealTime里面的思想例如,MAX中的纹理坐标,每个顶点都有一对UV 这个很正常但是同时 MAX对每个Face也保存了UV,这是因为MAX中的 每个Face都有可能是不同的贴图等等第二,如果熟悉了MAX中的哪些类能够干什么 那么Script也就是很水道渠成的事情了。为了写这2个插件,MAX Script 的help翻了无数次,几乎每写一句就要去翻一次。第三,MAX中的数组起位置是1,但是MAX中有的概念 使用数组表示的时候起始位置为0 ,例如纹理的Channel,起始就是为0,并且Channel0 很危险,写入错误直接让MAX挂掉第四,脚本编写很考验打字的准确度,由于变量没有类型,不需要声明就可以试用,打错一个字母的话那就查吧,运气不好的话,会让你疯掉的,同时MAX的脚本编辑器 超级难用。第五,编写导入插件的时候,发现Script 中读入数据异常痛苦,我在Script的帮助中没有发现任何类似c语言中的fprintf(%...)的东西,只有通过脚本提供的skiptostring来做。第六 Max Script的函数 没有明确的返回值的概念,不习惯第七 那个调试器 太难用了,我打了无数个messagebox总结:对于导入导出插件来说其实用SDK和Script 编写其实差别不大,因为都只是涉及到数据的读取和写入,并不涉及到复杂的逻辑。如果编写渲染类型或者是动画控制类型的插件 我觉得还是用script好一些,因为可以直接在MAX中看到结果,同时还能够一句一句的执行,很方便。我只是初学,希望有经验的人给点经验,最后附上简单的插件代码,导出插件只能到处一个几何体,点击ExportGeo按钮,然后点选几何体,即可输出导入插件没什么特别的操作,导入插件结尾有些仓促以下是导入插件:其实导入插件没什么必要写,反正是在MAX中建模,直接保存为MAX文件就可以了,这里纯属练手macroScript ImportGeo category: "HowTo2"(--从文件中读入某个分割符 后面 的数据--FileStream:文件句柄--needload :储存读取后的值的变量 (string or value)--spliter:分隔符(string)--bReadLine: 是否读取分隔符后所有的数据 1表示读取后面所有fn LoadData FileStream spliter bReadLine=(temp=skiptostring FileStream spliterif bReadLine==1 thenneedload=readline FileStreamelseneedload=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_DiffTexPathBitmapPathchannel_numUVW_Ver_NumUVW_Face_NumVert_UV=#() --所有的顶点的uv都放在这里Face_UV=#() --所有的面的uv都放在这里Vert_UV_Size=#() --用于记录每个channel的顶点的uv总数Face_UV_Size=#() --用语及了每个channel的面uv总数in_name=getopenfilename()if in_name!=undefined then(in_file=openfile in_nameif in_file!=undefined then(--node nametemp= readline in_filetoken=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_filett=readDelimitedString in_file ":"temp=readvalue in_fileappend tm_row1(temp)tt=readDelimitedString in_file ":"temp=readvalue in_fileappend tm_row2(temp)tt=readDelimitedString in_file ":"temp=readvalue in_fileappend tm_row3(temp)tt=readDelimitedString in_file ":"temp=readvalue in_fileappend tm_row4(temp)--************************************************--vertex infotemp= readline in_filetoken=filterString temp " " num_vert=token[token.count] as integerfor i=1 to num_vert do(tt=readDelimitedString in_file ":"temp=readvalue in_fileappend vert_array (temp))--************************************************************--face infotemp=readline in_filetoken=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_fileedge2 = readValue in_fileedge3 = readValue in_fileappend edge_array (#(edge1, edge2, edge3)))--************************************************************--uv info-- in max channel begin with 0--the channel 0 stores the vertex color info,no uv infochannel_num=LoadData in_file ":" 0for b=1 to (channel_num-1) do(--读出Channel idchannel_id=LoadData in_file ":" 0--texture map pathBitmapPath=LoadData in_file "->" 1--读出uv Vertex 的数量temp_size=LoadData in_file ":" 0append Vert_UV_Size temp_size--uv的数据for i=1 to temp_size do(append Vert_UV (readValue in_file))--uv face的 数量temp_size==LoadData in_file ":" 0append Face_UV_Size temp_sizefor i=1 to temp_size do(append Face_uv (readValue in_file))))close in_file)meditmaterials[1].ambient=_Material_Ambientmeditmaterials[1].diffuse=_Material_Diffusemeditmaterials[1].shaderbyname=_Material_typemeditmaterials[1].specular=_material_specularmeditmaterials[1].specularlevel=_material_specular_lvmeditmaterials[1].glossiness=_material_glossinessmeditmaterials[1].selfillumcolor=_Material_SelfillumColormeditmaterials[1].selfillumamount=_Material_SelfillumAmountmeditmaterials[1].diffuseMapEnable=truebmp =bitmaptexture filename: _Material_DiffTexPathmeditmaterials[1].diffusemap=bmpnew_mesh = mesh vertices:vert_array faces:face_array --materialIDs:#(0,1) tverts:vert_uvfor 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.transformnew_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 truemeshop.setMapSupport new_mesh 1 true--set vertex uv for every vertexmeshop.setNumMapVerts new_mesh 1 Vert_UV_Size[1] keep:falsefor i=1 to Vert_UV_Size[1] do(meshop.setMapVert new_mesh 1 i Vert_UV[i])--set face uv for every facemeshop.setnummapfaces new_mesh 1 Face_UV_Size[1] keep:falsefor i=1 to Face_UV_Size[1] do(meshop.setMapFace new_mesh 1 i Face_UV[i])update new_mesh)以下是导出插件:到处插件很容易写,导入插件花了2倍于导出的时间-- export by sssa2000macroScript ExportGeo category:"HowTo2"(fn GetGeometry o =(Superclassof o == Geometryclass and classof o != TargetObject)fn DumpMaterial m file=(--只对Standard类型的材质处理--获得diffuse and diffuse mapismat=iskindof m materialif ismat then(name=m.nameformat "Material Name-> %\n" name to: fileclass_of_mat=classof m--messagebox class_of_matif (class_of_mat )==Standardmaterial then(type=m.shaderByNameformat "Material Type->%\n" type to: file_ambient=m.ambientformat "Ambient Value->%\n" _ambient to:filediffuse_value=m.diffuseformat "Diffuse Value->%\n" diffuse_value to:file_specular=m.specularformat "Specular Value->%\n" _specular to:file_specularLevel =m.specularLevelformat "SpecularLevel Value->%\n" _specularLevel to:file_Glossiness=m.Glossinessformat "Glossiness Value->%\n" _Glossiness to:file_selfIllumColor =m.selfIllumColorformat "SelfIllumColor Value->%\n" _selfIllumColor to:file_selfIllumAmount =m.selfIllumAmountformat "SelfIllumAmount Value->%\n" _selfIllumAmount to:filediffuse_map_path=m.diffusemap.filenameformat "Diffuse Map Path->%\n" diffuse_map_path to:file))format "\n" to: file)--/////////////////////////////////////////////////////////////////////////////////////////obj = pickobject filter:GetGeometryif isValidNode obj then(nodename=obj.name--First export the matrixrow1=obj.transform.row1row2=obj.transform.row2row3=obj.transform.row3row4=obj.transform.row4tmesh = snapshotAsMesh objout_name = GetSaveFileName()if out_name != undefined then(out_file = createfile out_nameformat "Node Name: %\n" nodename to: out_fileformat "\n" to: out_file--******************************************************-- material infonode_material=obj.materialnum_sub_material=getNumSubMtls obj.materialDumpMaterial obj.material out_filefor y=1 to num_sub_material do(sub_mat=getSubMtl obj.material yDumpMaterial sub_mat= out_file)--******************************************************format "Node TM Row1: %\n" row1 to: out_fileformat "Node TM Row2: %\n" row2 to: out_fileformat "Node TM Row3: %\n" row3 to: out_fileformat "Node TM Row4: %\n" row4 to: out_file--******************************************************-- vertex infonum_verts = tmesh.numvertsnum_faces = tmesh.numfacesformat "Number of Ver: %\n" num_verts to:out_filefor v = 1 to num_verts doformat "Ver%: %\n" v (getVert tmesh v) to:out_fileformat "\n" to:out_file--***********************************************--face infoformat "Number of Face: %\n" num_faces to:out_filefor f = 1 to num_faces do(face = getFace tmesh fsgroup = getFaceSmoothGroup tmesh fmatid = getFaceMatId tmesh fedge1 = getEdgeVis tmesh f 1edge2 = getEdgeVis tmesh f 2edge3 = getEdgeVis tmesh f 3format "%,%,%,%,%,%\n" face sgroup matid edge1 edge2 edge3 to:out_file)--******************************************************--uv infochannel=meshop.getnummaps tmesh --number of textureformat "\n" to: out_fileformat "Channel Number:%\n" channel to:out_filefor i=1 to (channel-1) do(-- channel的计数从0开始--channel 0 is vertex color so do not export itIsSupport=meshop.getMapSupport tmesh iif IsSupport==true then(format "Channel ID:%\n" i to:out_fileif classof obj.material.maps[i+1]==Bitmaptexture thenformat "Map File Path->%\n" obj.material.maps[i+1].filename to: out_fileelseformat "Map File Path->Null\n" to: out_filenum_uv_ver=meshop.getNumMapVerts tmesh inum_uv_face=meshop.getNumMapFaces tmesh iformat "UVW Vertex Number:%\n" num_uv_ver to:out_filefor 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_filefor o=1 to num_uv_face do(uvw_face=meshop.getMapFace tmesh i oformat "% \n" uvw_face to: out_file))else(--format "Do Not Support Channel %\n" i to:out_file))close out_fileedit out_name)))

◐◐◐◐●☛█▼▲豪仕知识网http://www.haOz.net▼▲▼▲▼▲▼▲▼●●●●●●●▼▲▼▲▼▲

关于3dsmaxsdk导出插件编写心得的介绍到此就结束了,字数约45490字,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,豪仕知识网往后会继续推荐3dsmaxsdk导出插件编写心得相关内容。

相关文章