3ds Max导出OBJ的mtl贴图路径不正确

针对3DSMax导出OBJ格式时出现的材质贴图路径错误问题,本文提供了一段MaxScript脚本,用于自动修正相同贴图不同路径及同名材质不同贴图的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


之前流程是写了一个3DSMAX插件把游戏的场景直接导出为自己定义的格式的文件,包含了顶点数据,三角形数据,贴图数据等。现在把插件从3DMAX上分离出来,先通过3DMAX导出OBJ,然后再把OBJ导出为自定义的格式。

3DSMax导出的材质mtl文件漫反射贴图路径不正确

一开始以为是一个Standardmaterial对应漫反射的Map名字一样但是贴图路径不一样导致了OBJ导出出错。写了一个把同一个Map但是对应不同的贴图路径的Map自动重命名的MaxScript脚本,导出发现结果是一样的。
一个Multimaterial下的Standardmaterial和一个Standardmaterial名字一样,但是这二个Standardmaterial的diffusemap的文件路径不一样。从而导致了OBJ导出出错。

自动转换的代码如下:

--My Dictionary
struct dict
(
    public keys = #(),
    public values = #(),
    --methods:
    fn Count = 
    (
        if keys.count == values.count then
        (
            keys.count as integer
        )
        else
        (
            print "Error: keys.count != values.count"
            0
        )
    ),
    fn Add key1 value1 = 
    (
        if findItem keys key1 == 0 then
        (
            append keys key1
            append values value1
            true
        )
        else
        (
            print ("key has already been added! -->" + key1)
            false
        )
    ),
    fn Clear = 
    (
        keys = #()
        values = #()
        true
    ),
    fn Remove key = 
    (
        index = findItem keys key
        if index != 0 then
        (
            deleteItem keys index
            deleteItem values index
            true
        )
        else
        (
            print ("cann't find the key! -->" + key)
            false
        )
    ),
    fn GetItem key = 
    (
        index = findItem keys key
        if index != 0 then
        (
            if keys.count == values.count then
            (
                values[index]
            )
            else
            (
                print "Error: keys.count != values.count"
                undefined
            )
        )
        else
        (
            print ("cann't find the key! -->" + key)
            undefined
        )
    ),
	fn ContainsKey key = 
	(
		index = findItem keys key
		if index != 0 then
		(
			true
		)
		else
		(
			false
		)
	)
) 

struct mtlData
(
	public mapName = "",
	public relalMap
)
openLog "D:\Users\Administrator\Desktop\3DMAX_OBJ\my_log.txt" mode:"a" outputOnly:true
texturePathToMapNameDict = dict()
mapCount = 1000

fn processStandardMaterial mat = 
(
	if (mat.diffusemap != undefined) then
		(
			diffmap = mat.diffusemap
			mapname = diffmap.name
			
			if (diffmap.fileName != undefined) then
			(
				filepath = diffmap.fileName as string
				
				if (texturePathToMapNameDict.ContainsKey filepath) then
				(
					dm = texturePathToMapNameDict.getItem filepath
					--print ("change " + mat.diffusemap.name + " to " + (texturePathToMapNameDict.getItem filepath).name)
					mat.diffusemap = copy dm
					updateMTLInMedit mat.diffusemap
				)
				else
				(
					newMapName = "Map_#" + (mapCount as string)
					mapCount = mapCount + 1
					newDiffuse = mat.diffusemap
					newDiffuse.name = newMapName
					--newDiffuse.reload()
					mat.diffusemap = copy newDiffuse
					texturePathToMapNameDict.add filepath newDiffuse			
				)
				
			)
		)
)

fn processMultimaterial mat = 
(
	materialList = mat.materialList
	for mm in materialList do
	(
		if classof mm == Standardmaterial then
		(
			processStandardMaterial mm
		)
		else if classof mm == Multimaterial then
		(
			processMultimaterial mm
		)
	)
)
--meditMaterials
--SceneMaterials
for mat in SceneMaterials do
(
	if classof mat == Standardmaterial then
	(
		processStandardMaterial mat
	)
	else if classof mat == Multimaterial then
	(
		processMultimaterial mat
	)
)

standardMaterialDic = dict()
matNameCount = 1

fn processRenameStandardMaterial mat =
(
	--print ("process std" + mat.name)
	if (standardMaterialDic.ContainsKey mat.name) then
	(
		diffusemap = standardMaterialDic.getItem mat.name
		if ((diffusemap == undefined and mat.diffusemap == undefined) or (diffusemap != undefined and mat.diffusemap != undefined and diffusemap.name == mat.diffusemap.name)) then
		(
			--print ("same" + diffusemap.name)
		)
		else
		(
			print ("change " + mat.name + " to " + (mat.name + "_" + matNameCount as string))
			mat.name = (mat.name + "_" + matNameCount as string)
			matNameCount = matNameCount + 1
			standardMaterialDic.add mat.name mat.diffusemap
		) 
	)
	else
	(
		--print ("change " + mat.name)
		standardMaterialDic.add mat.name mat.diffusemap
	)
)

fn processRenameMultimaterial mat = 
(
	--print ("process mul" + mat.name)
	materialList = mat.materialList
	for mm in materialList do
	(
		if classof mm == Standardmaterial then
		(
			
			processRenameStandardMaterial mm
		)
		else if classof mm == Multimaterial then
		(
			processRenameMultimaterial mm
		)
	)
)

for mat in SceneMaterials do
(
	if classof mat == Standardmaterial then
	(
		processRenameStandardMaterial mat
	)
	else if classof mat == Multimaterial then
	(
		processRenameMultimaterial mat
	)
)

print ("转换完成!!!")
closeLog()

dict字典代码来自博客

代码很简单,就是先把map同名但是贴图路径不一致名字自动修改map名字,然后Standardmaterial名字一样但是map名字不一致自动修Standardmaterial名字,不考虑Multimaterial名字一样但是里面数据不一样的情况。代码边学边写-_-。主要参考:

  1. API参考:http://docs.autodesk.com/3DSMAX/16/ENU/MAXScript-Help/
  2. 语法参考:<<3ds MAXScript 脚本语言>>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值