Maya、3dsMax开发——中文命名规律,uv通道查找失败问题,Python2、Python3中unicode转字面string

若使用C++的FBX SDK开发,可以跳转下方官方手册目录查看说明!

1. 规律

        起因是发现同样的fbx文件导入maya和max后,由于模型自身默认自带中文名,在Autodesk这两个软件中的名称不同(对比Maya2020(左)、3ds Max2022(右)。可能是默认编码方式原因)

        中文命名在maya后台中,通过fbxRootNode.GetChild(0).GetName()得到的是unicode格式

u'\u5e73\u9762'   # 平面

        而实际上在场景中它的名字是一个string

’FBXASC229FBXASC185FBXASC179FBXASC233FBXASC157FBXASC162

        规律十分简单:将unicode用UTF-8编码,得到的bytes(Python3)或string(Python2)的样式为:

b'\x e5\x b9\x b3\x e9\x 9d\x a2'

        仔细观察可发现,e5、b9、b3、e9、9d、a2六个十六进制的数字转化为十进制分别为229、185、179、233、157、162。正好是每个FBXASC前缀后面带的三个数字。

2.问题

        maya中用户无法将mesh名字改成中文或者带有其他“非法字符”的名字。但是如果mesh在导入之前就是中文名字,导入后就是这一长串FBXASC格式。(可能是因为maya2020默认编码方式为Ascii)这并不影响普通用户使用,因为它即使导出maya后,它存储的仍然是unicode格式,重新导入max后,还是能正常显示中文“平面”。

        然而这可苦了开发者。理论上既然mesh的name保存的是unicode,其他对于命名的搜索,应该也是按unicode格式。但Autodesk剑走偏锋,例如像uv通道的获取方式就是按照FBXASC这个命名搜索的。如例:

fbxMeshName = ...
DGpath = om.MDagPath.getAPathTo(om.MSelectionList().add(fbxMeshName).getDependNode(0))

        上例为fbx sdk官方文档中按照mesh名称(fbxMeshName)获取其uv通道的写法。若使用Unicode,在om.MSelectionList().add(fbxMeshName)时就丢失了查找对象,导致getDependNode(0)查找空的对象,报错。但是如果使用FBXASC...进行查找则能成功找到uv通道。

3.代码

        了解了规律后,要做的事情非常简单。但是Python这个时候跳出来说:“让我再压榨你一点时间罢”。

        原因在于Maya2020使用的是Python2,Maya直到2022版本才改用Python3,而3ds Max则是在2021版本兼容Python2 & Python3,2022版以后则为Python3。

        Python3:

unicode_str = u'\u5e73\u9762'
print(type(unicode_str))
hex_str = unicode_str.encode('UTF-8')
print(hex_str,type(hex_str))
h = hex_str.hex()
print(h,type(h))

# <class 'str'>
# b'\xe5\xb9\xb3\xe9\x9d\xa2' <class 'bytes'>
# e5b9b3e99da2 <class 'str'>

        Python3的hex()函数可以直接将bytes转换为string格式。往后的字符操作略去。

        Python2:

unicode_str = u'\u5e73\u9762'
print('------------------------')
print(type(unicode_str))
h = unicode_str.encode('UTF-8')
print(h,type(h))
result = ''
for hli in h:
    print('ord()',ord(hli),type(ord(hli)))
    result += 'FBXASC' + str(ord(hli))
print(result)

# ------------------------
# <type 'unicode'>
# ('\xe5\xb9\xb3\xe9\x9d\xa2', <type 'str'>)
# ('ord()', 229, <type 'int'>)
# ('ord()', 185, <type 'int'>)
# ('ord()', 179, <type 'int'>)
# ('ord()', 233, <type 'int'>)
# ('ord()', 157, <type 'int'>)
# ('ord()', 162, <type 'int'>)
# FBXASC229FBXASC185FBXASC179FBXASC233FBXASC157FBXASC162

        Python2的ord()函数则能将string类型的Unicode直接解码成十进制。

        二者不能共存的原因读者可以自己试试。这边给出报错结论。将py2方法放进py3环境:

TypeError: ord() expected string of length 1, but int found

        将py3方法放入py2环境:

# 错误: AttributeError: file <maya console> line 5: 'str' object has no attribute 'hex' # 

4.官方手册

FBX SDK Help | List of Python Fbx classes | Autodesk

这是python环境下拥有的fbx class。至于相比于C++的使用则写在/Scripting with Python FBX/Difference between FBX SDK and Python FBX。

同时C++似乎有一个API能够直接将字符编码方式转换(虽然本人使用python开发,没有使用过。非常可惜Autodesk并没有将这个功能放到Python FBX中,导致这个文章的出现(悲

FBX SDK Help | Supported string formats | Autodesk

同时,Maya API手册也是极好的(喜不自胜

Maya Help | C++ API Reference: Maya API Reference | Autodesk