前言

  偶然在网上看到了一个视频,视频里面有相关的代码 链接
  感觉实现的效果很赞,所以特意抽时间来研究一下这个东西是怎么实现的。

代码抄写

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# coding:utf-8
from __future__ import unicode_literals,division,print_function

__author__ = 'timmyliang'
__email__ = '820472580@qq.com'
__date__ = '2020-05-23 23:08:58'

"""
https://vimeo.com/85522402
"""

import math,random
from maya import OpenMaya as om
from maya import OpenMayaRender as omr

def placeObjects(filename, duplicates=5):
meshObject = om.MObject()
parentPath= om.MDagPath()
meshPath = om.MDagPath()
meshList = om.MSelectionList()
dgMod = om.MDagModifier()

om.MGlobal.getActiveSelectionList(meshList)

meshList.getDagPath(1,meshPath)
meshList.getDagPath(0,parentPath)
meshList.getDependNode(0,meshObject)

parentFn = om.MFnMesh(parentPath)
meshFn = om.MFnMesh(meshPath)

count = 0
while count < duplicates:

uv = [random.uniform(0.01,1),random.uniform(0.01,1)]
uvUtil = om.MScriptUtil()
uvUtil.createFromList(uv,2)
uvPoint = uvUtil.asFloat2Ptr()

# NOTE 获取随机 UV 的颜色
rgb = getRGBatUV(filename,uv)
if rgb > [0.4,0.4,0.4]:
meshIter = om.MItMeshPolygon(meshObject)
outPoint = om.MPoint()
space = om.MSpace.kWorld

while not meshIter.isDone():
faceId = meshIter.index()

try:
# NOTE 获取模型在 UV 上的点 | 获取失败直接报错跳过
parentFn.getPointAtUV(faceId,outPoint,uvPoint,space)

# NOTE 复制第二个选择的物体
name = meshPath.fullPathName()
dupName = "%s_dup%s" % (name,count+1)
dgMod.commandToExecute('duplicate -n "%s" "%s"' % (dupName,name))
dgMod.doIt()

dgMod.commandToExecute("select -r %s" % dupName)

dupMeshPath = om.MDagPath()
dupList = om.MSelectionList()
om.MGlobal.getActiveSelectionList(dupList)
dupList.getDagPath(0,dupMeshPath)

transform = om.MFnTransform(dupMeshPath)

# NOTE 根据法线计算旋转角度
faceNormal = om.MVector()
dupObjVector = om.MVector(0,1,0)
meshIter.getNormal(faceNormal)

rotAxisOrig = dupObjVector ^ faceNormal
rotAxis = rotAxisOrig.normal()
angleOrig = dupObjVector * faceNormal
angleOrig2 = math.acos(angleOrig)
angleUtil = om.MScriptUtil(angleOrig2)
anglePtr = angleUtil.asFloatPtr()
angle = om.MDoubleArray(anglePtr,1)
quat = om.MQuaternion(angle[0],rotAxis)

tXYZ = om.MVector(outPoint.x,outPoint.y,outPoint.z)

# NOTE 设置位置和角度
transform.setTranslation(tXYZ,om.MSpace.kWorld)
transform.setRotation(quat,om.MSpace.kWorld)

count += 1

except RuntimeError:
pass

meshIter.next()



def getRGBatUV(filename,uv=[0,0]):
# NOTE file 节点名称
texutreFileName = filename
uCoord = uv[0]
vCoord = uv[1]

# NOTE 获取输入的 UV
uUtil = om.MScriptUtil(uCoord)
vUtil = om.MScriptUtil(vCoord)
uPtr = uUtil.asFloatPtr()
vPtr = vUtil.asFloatPtr()
uCoord = om.MDoubleArray(uPtr,1)
vCoord = om.MDoubleArray(vPtr,1)

# NOTE file 节点的 MObject
textureList = om.MSelectionList()
om.MGlobal.getSelectionListByName(texutreFileName,textureList)
textureObject = om.MObject()
textureList.getDependNode(0,textureObject)

# NOTE 获取纹理颜色采样
resultColor = om.MVectorArray()
resultAlpha = om.MDoubleArray()
omr.MRenderUtil.eval2dTexture(textureObject,uCoord,vCoord,resultColor,resultAlpha)

return [resultColor[0].x,resultColor[0].y,resultColor[0].z]

placeObjects("file1",500)

  需要注意 “file1” 传入的名称必须存在 这个名称的 file 节点。
  eval2dTexture 方法将会采样这个节点指向的图片像素数据,从而获取特定UV位置的颜色信息。

  后面我写了一个 OpenMaya2.0 的获取方案,复制圆锥以及旋转都可以用 cmds 来处理,比起 OpenMaya 的方式要简单不少 github

总结

  旋转的处理比较麻烦,如何通过矩阵变换算出欧拉没有搞出来,看 Stack Overflow 的介绍是使用 AimConstraint 约束 链接
  或者使用矩阵变换。
  后面我是使用 cmds.angleBetween 这种取巧的方式。