前言

  再次地我又来提供花城汇项目相关的解决方案了。
  这一次要解决的是将模型的编号输出到box上。
  因为我们需要制作出编号图给甲方。
我们做的图
  这个图的编号是根据模型的名称输入的。
  但是这需要配合PS手动输入,这个过程繁琐而且累。
  这一次我们做的图是流花展馆,因为流花展馆的装修还没有完成,租户信息尚不完整
  甲方要求我们按照CAD上的房间编号进行制作
我们做的图
  这次我们编号有两千多个,这个工作量足以干死人了
  为此我需要想办法让Maya输出文字模型,从而简化大量的工作。

思路

注:这里解决方案是针对Maya2018新版文字实现的

  • 在Maya中创建文字
  • 修改文字模型的参数
  • 截取模型名称上的编号
  • 输入到文字节点中
  • 复制模型
  • 将复制的模型转换为boundingbox
  • 给文字模型添加最小分段的晶格
  • 将晶格的点和boundingbox的点逐一匹配
  • 选择文字模型
  • 删除历史
  • 居中枢轴
  • 稍微缩放一下文字

  实现的思路并不复杂,代码量也不多。
  核心想法是晶格模型和碰撞盒的匹配。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import maya.cmds as cmds

targets = cmds.ls(selection=True)

Text = []
for target in targets:

# 创建文字
cmds.CreatePolygonType()

# 获取文字的 Transform 节点
TypeTransform = cmds.ls(selection=True)[0]

# 获取 Type 节点
TypeNode = cmds.listConnections(TypeTransform , c=True)[1]
TypeExtrudeNode = cmds.listConnections(TypeNode , t='typeExtrude')[0]

# 设置字体 Generator 为 Python 模式
cmds.setAttr( '%s.generator' % TypeNode, 9 )
# 设置 Python 字符串 传入当前对象的名称 从而实现修改文字
cmds.setAttr( '%s.pythonExpression' % TypeNode, "\"%s\"" % target.split('_')[1] , type="string" )
# 注: textInput 可以修改文字 但是格式为unicode 不太方便

# 设置字体居中
cmds.setAttr( '%s.alignmentMode' % TypeNode, 2)

# 曲线精度 降低为2
cmds.setAttr( '%s.curveResolution' % TypeNode, 2)
# 不使用挤出
cmds.setAttr( '%s.enableExtrusion' % TypeExtrudeNode, 0)

# 给文字 添加晶格
latticeList = cmds.lattice( dv=(2, 2, 2), oc=True )
ffdLatticeNode = latticeList[1]

#####################################

# 复制当前对象
temp = cmds.duplicate( target, rr=True )
# 选择复制物体
cmds.select(temp)
# 转换为碰撞盒
cmds.GeometryToBoundingBox()
# 获取碰撞盒
BBox = cmds.ls(selection=True)[0]

# 获取碰撞盒的点数
vertexNum = cmds.polyEvaluate( BBox , v=True )

# 获取碰撞盒每个点的世界坐标 存入数组中
vertexPos = []
for index in range(vertexNum):
vertexPos.append(cmds.xform( "%s.vtx[%d]" % (BBox,index), q=True,t=True, ws=True))

# 匹配碰撞盒位置
cmds.select("%s.pt[0][1][1]" % ffdLatticeNode )
cmds.xform( a=True, ws=True , t=vertexPos[0])

cmds.select("%s.pt[1][1][1]" % ffdLatticeNode )
cmds.xform( a=True, ws=True , t=vertexPos[1])

cmds.select("%s.pt[1][0][1]" % ffdLatticeNode )
cmds.xform( a=True, ws=True , t=vertexPos[2])

cmds.select("%s.pt[0][0][1]" % ffdLatticeNode )
cmds.xform( a=True, ws=True , t=vertexPos[3])

cmds.select("%s.pt[0][1][0]" % ffdLatticeNode )
cmds.xform( a=True, ws=True , t=vertexPos[4])

cmds.select("%s.pt[0][0][0]" % ffdLatticeNode )
cmds.xform( a=True, ws=True , t=vertexPos[5])

cmds.select("%s.pt[1][0][0]" % ffdLatticeNode )
cmds.xform( a=True, ws=True , t=vertexPos[6])

cmds.select("%s.pt[1][1][0]" % ffdLatticeNode )
cmds.xform( a=True, ws=True , t=vertexPos[7])

# 删除碰撞盒
cmds.delete(BBox)

# 选择文字
cmds.select(TypeTransform)

# 删除历史
cmds.DeleteHistory()

# 居中枢轴
cmds.CenterPivot()

# 缩放
cmds.scale(.7,.7,.7,r=True)

#####################################


遇到的坑

  上面代码是针对Maya2018的新版的字体工具写的。
  刚开始我一直不知道如何才能将获取的box序号输入的文本中。
  最开始是希望通过命令回显来看文字输入的命令的
  然而文字输入并没有任何命令回显出来。
  于是我打开echo all command 来查看所有回显的命令
  结果只是一段不知其所以然,执行然并卵的代码
命令回显

  打开节点编辑器可以看到 type 节点下有 textInput 的端口
type节点
  但是由于没有命令回显,不知道如何操作它。
  于是我尝试着运行相关的命令
type节点
  首先可以确定的是,命令是可以执行的。
  但是执行报错了,提示说需要添加 -type 标志
type节点
  添加之后虽然可以执行但是并没有任何效果。
  于是我就没有继续研究这是什么情况。

  经过一波三折的摸索,我发现 Generator 中的 Python 也可以生成相关的文字。
type节点
  但是无法回显不出操作命令
  于是我只好又一次硬着头皮去试着输入属性了
type节点
  没想到这一次也可以了,只是还是要添加这个type标签。
  于是我去查了 setAttr 相关的帮助文档
type节点
  原来type标签需要输入 “string” 来输入字符串
  于是我尝试操作了一下
type节点
  成功了,我将PythonExpression的属性修改了
  那么 textInput 也可以同理进行操作了
type节点
  然而 textInput 翻车了,通过Python执行可以知道,这个操作会将输入的数据进行 unicode 操作
  反而是输出了我预想之外的字母了。
  这个涉及到编码问题,相当复杂,于是我我就用python更为简单的方案了。

  解决这个问题之后就没有太大的坑了,无非就是控制type节点的属性,基本上都是可以回显命令的。
  另外的难点就在于 晶格 和 boundingbox 的匹配上。
  这个需要自己去匹配相关的点。

  最后的问题是 删除历史
  我想删除文字的历史
  让大纲列表看起来没那么混乱
  但是一旦这样就会爆出很多错误
  我猜测原因可能是因为文字节点创建还需要与很多其他的节点进行交互
  但是代码还没有执行到那里,删除历史就已经执行了,结果就导致很多节点找不到连接的目标。
  不过目前上述的报错并没有造成任何影响,可能会生成一些多余的节点,优化场景可以解决。

总结

  这次开始尝试使用Python写脚本,本次和MEL没有太大的区别
  不过是将MEL转成Python而已,但是这一小步是为了以后的一大步。

  到今天为止,前今天的感冒已经好了很多,后续问题不大。
  考虑到动画实训的缘故,我打算去研究一下如何利用Houdini实现城市自动生成的效果。
  这个不在我的10月计划中,但是我希望近期能够攻克这个难关。
  因此 Houdini17 测试延后。