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