摘要:本文讲解了3Dmax如何通过MAXScript批量修改贴图名及模型名,希望阅读本篇文章以后大家有所收获,帮助大家对3Dmax的掌握更加熟练。
批量修改模型名
步骤:
1. 建立两个txt文件,一个是用于存放原模型名的列表,一个用于存放新模型名的列表
2. 逐行读取两个txt文件的内容;
3. 读取一行,就搜索场景中名称匹配的模型,然后替换成新名称。
具体实现:
1. 只能手动解决,这个没有什么快捷方式。
2. 可以通过FileStream(文件数据流)的OpenFile方法对文本文件进行I/O操作。切记: maxscript的函数并不是以一对“()”括号来标识的,传参数的方法也不像其他常用语言那样在“()”里填入参数,而是在函数名后“ ”加“空格”然后在后面带上函数参数,如要读取D盘下的maxscript.txt文件内容,应如此写:
source = OpenFile "d:\maxscript.txt" --后面不带封号,不一样的注释符号"--";
而不是:
source = OpenFile("d:\maxscript.txt");
3. 这个步骤主要是获取指定名称的对象。可以通过for循环遍历selection中所有的模型对象,但是此法效率过于低下,因为找一个物体就要遍历一遍selection,没找到更好的方法,将就用吧,下面附上源码:
source = OpenFile "C:\Users\Administrator\Desktop\批量改名\原名.txt" --获取"原名.txt文件"的io流 des = OpenFile "C:\Users\Administrator\Desktop\批量改名\新名.txt" --获取"新名.txt文件"的io流 for j = 1 to 3 do --列表几条记录就写几条,maxscript习惯从1开始计数 ( str = readLine source --逐行读取文本内容 strD = readLine des for obj in selection do --遍历场景中所有模型,注:selection需要选中场景中的模型哦 ( if obj.name==str then --判断模型名称是否与原名一致,如果一致,就替换成新名 ( obj.name = strD exit --退出循环 ) ) )代码是不是有点简单?千万千万不要说我絮絮叨叨的侃了一堆,只写出了这么几行代码,要知道,这几行代码可都是精华呀,好啦,下面才是重头戏。
批量修改贴图名
示例代码:
rm = renderMap $foo.Material.diffuseMap size:[640,480] \fileName: "foodif.bmp" save rm close rm通过上述代码的启发,是不是可以通过 (模型对象).Material.diffuseMap.fileName = “贴图路径”,其实在3DMAX中,贴图名可看成是贴图在硬盘上的路径。测试一下,首先在场景中随便建个Box用于测试,先给其关联上一张贴图,然后再随便选择一个路径放一张其他的贴图,然后将其路径复制下来作为要修改的贴图名,然后打开maxscript侦听器,执行脚本,成功修改贴图名,并关联上硬盘的贴图文件。应该说,核心的问题已经解决了。写代码之前,照例整理一下思路,归纳一下步骤:
1. 保留原贴图路径及位置,将硬盘上的原贴图复制到另一个文件夹下,并修改贴图名,作为新贴图;
2. 将原贴图完整路径与新贴图完整路径分别写进两个txt列表中;
3. 读取两个txt文件,通过遍历模型,找到材质,找到贴图,再将贴图与txt的原贴图进行匹配,匹配成功后,替换成新贴图。
具体实现:
1. 如果对新贴图名的命名并没有什么要求,其实这一个步骤有一个快捷的方法,随便使用什么编程语言,写一个小程序,让程序帮你做复制贴图,并将贴图路径写入各自的txt文件中,几秒就可以搞定第一个步骤;如果对贴图名称有要求,那就比较麻烦了,要一个个改贴图名称,还要一一对应写入列表;
2. 参见1;
3. 使用openfile读取列表,selection遍历模型,并遍历每个模型的材质和贴图,然后替换贴图。上代码:
遍历模型法
source = OpenFile "F:\新名.txt" des = OpenFile "F:\原名.txt" for j = 1 to 39 do ( str = readLine source strD = readLine des print(str) print(strD) for i in selection do --遍历场景中所有选中的物体 ( s = i.Material as string --将材质属性转成字符串格式 if s!="undefined" then( --模型没有材质时,材质为 "undefined" if s.count>18 then ( ss = substring s 1 18 --获得材质属性子字符串,用于判断是否是“多维材质” ) --多维材质 if ss == "#Multi/Sub-Object:" then --子字符串中若含有多维材质的信息,则为多维材质,按多维材质处理 ( for k=1 to i.Material.MaterialList.count do --将多维材质中的子材质放入数组中,并遍历每个子材质中的贴图 ( multi = i.Material.MaterialList[k] as string --将多维材质中的子材质属性转成字符串格式 if multi !="undefined" then --若多维材质无子材质,则为 "undefined" ( dif = i.Material.MaterialList[k].diffuseMap as string --将贴图属性转成字符串格式 if dif !="undefined" then --若材质无贴图,则贴图为 "undefined" ( if i.Material.MaterialList[k].diffuseMap.filename==str then ( i.Material.MaterialList[k].diffuseMap.filename = strD exit --退出循环 ) ) ) ) ) else --标准材质 ( difS = i.material.diffuseMap as string if difS !="undefined" then ( if i.material.diffuseMap.filename==str then ( i.material.diffuseMap.filename = strD exit ) ) ) ) ) )和修改模型名一样的问题,此方法效率低下,耗时太长,当时一个场景5000多个模型,替换一张贴图要50s左右,因为替换一张贴图就要遍历5000多个模型,所以后来也一直在想有没有不通过遍历模型的方式。比如遍历材质,相对而言,材质要少得多,但是也是很久没有发现比较好的方式。那天下班回家又想起了这个问题,终于功夫不负有心人啊,无意中发现手册中3.5.13节一个叫MaterialLibrary(材质库)的类,类中有一个系统变量:SceneMaterials(场景里的材质的集合),于是又优化了一下程序,这次可快得多了,替换一张贴图只需要0.x秒,这么激动人心的时刻,快上代码:
遍历材质法
source = OpenFile "F:\贴图改名程序\原名.txt" des = OpenFile "F:\贴图改名程序\新名.txt" --b = false for j = 1 to 176 do ( str = readLine source strD = readLine des print(str) print(strD) start =timeStamp() for i = 0 to SceneMaterials.count do --SceneMaterials:为系统变量,是一个包含场景中的所有材质的数组。 ( s = SceneMaterials[i] as string --将材质属性转成字符串格式 if s!="undefined" then( --模型没有材质时,材质为 "undefined"(此判断在通过遍历模型中的材质时用到) if s.count>18 then ( ss = substring s 1 18 --获得材质属性子字符串,用于判断是否是“多维材质” ) --多维材质 if ss == "#Multi/Sub-Object:" then --子字符串中若含有多维材质的信息,则为多维材质,按多维材质处理 ( for k=1 to SceneMaterials[i].MaterialList.count do --将多维材质中的子材质放入数组中,并遍历每个子材质中的贴图 ( mat = SceneMaterials[i].MaterialList[k] --将材质赋值给 mat 变量。 multi = mat as string if multi !="undefined" then ( if multi.count>18 then ( sss = substring multi 1 18 ) --多维材质子材质为多维材质 if sss == "#Multi/Sub-Object:" then ( for subk=1 to mat.MaterialList.count do --将多维材质中的子材质放入数组中,并遍历每个子材质中的贴图 ( subMat = mat.MaterialList[subk] --将材质赋值给 subMat 变量。 submulti = subMat as string if submulti !="undefined" then ( if submulti.count>18 then ( ssss = substring submulti 1 18 ) if ssss == "#Multi/Sub-Object:" then ( ) else ( subdif = subMat.diffuseMap as string if subdif !="undefined" then ( if subMat.diffuseMap.filename==str then ( subMat.diffuseMap.filename = strD --exit ) ) ) ) ) ) --多维材质子材质为标准材质 else ( dif = mat.diffuseMap as string if dif !="undefined" then --若材质无贴图,则贴图为 "undefined" ( if mat.diffuseMap.filename==str then ( --b = true mat.diffuseMap.filename = strD --exit ) ) ) ) ) ) --标准材质 else ( difS = SceneMaterials[i].diffuseMap as string if difS !="undefined" then ( if SceneMaterials[i].diffuseMap.filename==str then ( SceneMaterials[i].diffuseMap.filename = replace SceneMaterials[i].diffuseMap.filename 1 SceneMaterials[i].diffuseMap.filename.count strD --exit ) ) ) ) ) end =timeStamp() intervalTime = (end - start)/ 1000.0 print(intervalTime) )
好了,怕大家看不懂,多写了一些注释,大家应该已经懂了,希望这个小程序可以给大家省去很多麻烦,需要注意的是,大家应该看到了,程序中只对diffuseMap(即漫反射贴图)进行了处理,听同事说还有通道贴图,烘焙贴图等等,这个如有需要,大家略微修改程序即可。
本文由职坐标整理发布,学习更多的3Dmax相关知识,请关注职坐标常用软件3Dmax频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号