Определенно есть много разных подходов, которые вы можете использовать, чтобы разбросать объекты по поверхности. Вы можете использовать геометрические и нормальные зависимости. Есть структура MA SH. Но я думаю, что использование фолликула достаточно просто и требует меньше затрат. Единственная загвоздка в том, что на поверхности должны быть ультрафиолетовые лучи, так как мы будем перемещать фолликул.
Итак, вот что я предлагаю:
- Создайте фолликул и соедините его с поверхностью, на которую вы хотите рассыпать.
- Создайте свой объект травы.
- Каждый раз, когда вы создаете новую траву, выбирайте случайный ультрафиолет для фолликула. Это выровняет его по положению лица и нормали.
- Используйте преобразование фолликула, чтобы переместить / повернуть траву в.
- Промойте и повторите шаги 3 и 4.
Вот полный пример:
import maya.cmds as cmds
import random
surface = "pPlane1" # Specify the object you want to scatter on.
fol_shape = cmds.createNode("follicle") # Create a new follicle object.
fol = cmds.listRelatives(fol_shape, f=True, parent=True)[0] # Get the follicle's transform.
# Below we are connecting the follicle to the surface so we can control it with its uvs.
cmds.connectAttr("{}.outMesh".format(surface), "{}.inputMesh".format(fol))
cmds.connectAttr("{}.worldMatrix[0]".format(surface), "{}.inputWorldMatrix".format(fol))
cmds.connectAttr("{}.outTranslate".format(fol_shape), "{}.translate".format(fol))
cmds.connectAttr("{}.outRotate".format(fol_shape), "{}.rotate".format(fol))
cmds.setAttr("{}.simulationMethod".format(fol_shape), 0)
# Begin creating blade of grass.
blade = cmds.polyCone(sx=3, sy=5, sz=0, r=0.04, h=1, ax=(0, 1, 0))
cmds.setAttr(blade[0] + '.translateY', .5)
cmds.delete(ch=True)
cmds.polySoftEdge(a=0)
# Setting wirecolor to green so it's easier to see.
cmds.setAttr(blade[0] + ".overrideEnabled", True)
cmds.setAttr(blade[0] + ".overrideRGBColors", True)
cmds.setAttr(blade[0] + ".overrideColorRGB", 0.06, 0.2, 0.06)
bend = cmds.nonLinear(type='bend', lowBound=0, highBound=2, curvature=30)
vtxPos = cmds.xform(blade[0] + '.vtx[0]', q=True, t=True, ws=True)
cmds.xform(bend, t=(0, vtxPos[1], 0))
cmds.select(blade[0])
cmds.delete(ch=True)
cmds.makeIdentity(apply=True, t=1, r=1, s=1, n=0)
groupblades = cmds.group(empty=True, name=blade[0] + '_grp#')
for i in range(400):
obj = cmds.instance(blade[0])
# Randomly set the follicle's uv so it's jumps somewhere else on the surface. Value needs to be between 0.0-1.0
cmds.setAttr("{}.parameterU".format(fol_shape), random.random())
cmds.setAttr("{}.parameterV".format(fol_shape), random.random())
cmds.matchTransform(obj, fol) # Make grass match follicle's position/rotation/scale.
cmds.rotate(-90, random.random() * 360, 0, obj, r=True) # Rotate it upright and give it random twist.
cmds.move(0, 0.4, 0, obj, r=True) # The grass's pivot is in the center, so need to offset translation a bit up.
cmds.parent(obj, groupblades)
cmds.delete(fol) # Follicle no longer needed, so delete it.
Есть одна часть, где мне нужно немного поднять траву, потому что точка поворота находится в центре травы. Это небольшой прием, и реальным решением было бы построить траву с точкой поворота в основании. Это решит проблему с любой плавающей травой и упростит случайное масштабирование.
Вот что будет выведено:
![Scatter example](https://i.stack.imgur.com/4fUas.jpg)