我在这里挣扎着使用OpenMaya。
我希望能够从定位器列表中获取变换信息,并将这些值插入到粒子形状中。我们的目标是使用超过25000个定位器,所以我不能为每个实例创建一个粒子系统。我真的需要将位置和旋转值存储到粒子本身。
要做到这一点,我开始潜入OpenMaya…(╯°□°)╯╯
无论如何,我现在面临的问题是,我的场景崩溃每次我启动这个脚本,我不知道我做错了什么。我想我已经很接近了,但是撞毁玛雅并不算胜利。
import pymel.core as pm
import maya.OpenMaya as om
import maya.OpenMayaFX as omfx
import random
### A short script to create the scene with bunch of locators with random pos rot
numOfLoc = 5 # this number will eventually be set 25000 when the script will work.
# create locators with random position location(for test)
def create_gazillion_locators(numOfLoc):
for i in range(0, numOfLoc):
# to create variation
tx = random.uniform(-10, 10)
ty = random.uniform(0, 5)
tz = random.uniform(-10, 10)
rx = random.uniform(0, 360)
ry = random.uniform(0, 360)
rz = random.uniform(0, 360)
pm.spaceLocator()
pm.move(tx, ty, tz)
pm.rotate(rx, ry, rz, ws=True)
# Select locators
def select_locators():
pm.select(cl=True)
loc_selection = pm.listRelatives(pm.ls(type = 'locator'), p=True)
pm.select(loc_selection, r=True)
return loc_selection
# delete the locators
def clean_the_scene():
#del locators (for testing purpiose)
sel = select_locators()
if sel is not None:
pm.delete(sel)
clean_the_scene()
create_gazillion_locators(numOfLoc)
### Actual script
# Found this on the internet. it seems to be more neat
class Vector(om.MVector):
def __str__(self):
return '{0}, {1}, {2}'.format(self.x, self.y, self.z)
def __repr__(self):
return '{0}, {1}, {2}'.format(self.x, self.y, self.z)
# OpenMaya treatment
sel = select_locators()
mSel = om.MSelectionList()
om.MGlobal.getActiveSelectionList(mSel)
mSel_iter = om.MItSelectionList(mSel)
mSel_DagPath = om.MDagPath()
# bvariables to store the transform in
pos_array = om.MVectorArray()
rot_array = om.MVectorArray()
mLoc = om.MObject()
# Main loop of selection iterator.
while not mSel_iter.isDone():
# Get list of selected
mSel_iter.getDagPath(mSel_DagPath)
mSel_iter.getDependNode(mLoc)
dep_node_name = om.MFnDependencyNode(mLoc).name()
transl = pm.getAttr('{}.translate'.format(dep_node_name))
rotate = pm.getAttr('{}.rotate'.format(dep_node_name))
print(dep_node_name)
print(Vector(transl[0], transl[1], transl[2]))
print(Vector(rotate[0], rotate[1], rotate[2]))
pos_array.append(Vector(transl[0], transl[1], transl[2]))
rot_array.append(Vector(rotate[0], rotate[1], rotate[2]))
mSel_iter.next()
# Up untill there it seems to work ok.
nparticles_transform, nparticles_shape = pm.nParticle(position = pos_array)
pm.setAttr('nucleus1.gravity', 0.0)
nparticles_shape.computeRotation.set(True)
pm.addAttr(nparticles_shape, ln = 'rotationPP', dt = 'vectorArray')
pm.addAttr(nparticles_shape, ln = 'rotationPP0', dt = 'vectorArray')
pm.particleInstancer(nparticles_shape, name = p_instancer, edit = True, rotation = "rotationPP")
particle_fn = omfx.MFnParticleSystem(nparticles_shape.__apimobject__())
particle_fn.setPerParticleAttribute('rotationPP', rot_array)
particle_fn.setPerParticleAttribute('rotationPP0', rot_array)
我读了很多东西,通过堆栈和谷歌,我基于我发现/学到的其他几个东西的脚本(我听了Chayan Vinayak在Youtube上的OpenMaya课程)…但是我很难理解OpenMaya文档。
我看了一下,如果你需要pymel,在这种情况下不需要使用任何openmaya。我使用cmd来创建定位器,因为它更快一些,所以如果执行速度是一个问题,请尝试将所有内容切换到cmd。我认为没有必要设置computeRotation
,因为它只在模拟时使用。
import pymel.core as pm
import maya.cmds as cmds
import random
numOfLoc = 5000
def c_create_gazillion_locators(num_of_loc):
for i in range(num_of_loc):
tx = random.uniform(-10, 10)
ty = random.uniform(0, 5)
tz = random.uniform(-10, 10)
rx = random.uniform(0, 360)
ry = random.uniform(0, 360)
rz = random.uniform(0, 360)
cmds.spaceLocator()
cmds.move(tx, ty, tz)
cmds.rotate(rx, ry, rz, ws=True)
create_gazillion_locators(numOfLoc)
locs = pm.ls(type="locator")
locs = pm.listRelatives(locs, p=True)
pos = []
rot = []
for loc in locs:
pos.append(loc.translate.get())
rot.append(loc.rotate.get())
nparticles_transform, nparticles_shape = pm.nParticle(position=pos)
pm.setAttr("nucleus1.gravity", 0.0)
pm.addAttr(nparticles_shape, ln="rotationPP", dt="vectorArray")
pm.addAttr(nparticles_shape, ln="rotationPP0", dt="vectorArray")
rpp= pm.Attribute(nparticles_shape+".rotationPP")
rpp0= pm.Attribute(nparticles_shape+".rotationPP0")
rpp.set(rot)
rpp0.set(rot)
我做了一些改变使它工作。我没有检查粒子设置。实际上,主要问题是混合了两种不同的api。要么坚持OpenMaya(或甚至OpenMaya v2.0)或PyMEL。
import pymel.core as pm
import maya.OpenMaya as om
import maya.OpenMayaFX as omfx
import random
### A short script to create the scene with bunch of locators with random pos rot
numOfLoc = 5 # this number will eventually be set 25000 when the script will work.
# create locators with random position location(for test)
def create_gazillion_locators(num_of_loc):
for i in range(num_of_loc):
# to create variation
tx = random.uniform(-10, 10)
ty = random.uniform(0, 5)
tz = random.uniform(-10, 10)
rx = random.uniform(0, 360)
ry = random.uniform(0, 360)
rz = random.uniform(0, 360)
pm.spaceLocator()
pm.move(tx, ty, tz)
pm.rotate(rx, ry, rz, ws=True)
# Select locators
def select_locators():
pm.select(cl=True)
loc_selection = pm.listRelatives(pm.ls(type="locator"), p=True)
pm.select(loc_selection, r=True)
return loc_selection
# delete the locators
def clean_the_scene():
# del locators (for testing purpiose)
sel = select_locators()
if sel is not None:
pm.delete(sel)
clean_the_scene()
create_gazillion_locators(numOfLoc)
### Actual script
# Found this on the internet. it seems to be more neat
class Vector(om.MVector):
def __str__(self):
return "{0}, {1}, {2}".format(self.x, self.y, self.z)
def __repr__(self):
return "{0}, {1}, {2}".format(self.x, self.y, self.z)
# OpenMaya treatment
sel = select_locators()
mSel = om.MSelectionList()
om.MGlobal.getActiveSelectionList(mSel)
mSel_iter = om.MItSelectionList(mSel)
mSel_DagPath = om.MDagPath()
# bvariables to store the transform in
pos_array = []
rot_array = om.MVectorArray()
mLoc = om.MObject()
# Main loop of selection iterator.
while not mSel_iter.isDone():
# Get list of selected
mSel_iter.getDagPath(mSel_DagPath)
mSel_iter.getDependNode(mLoc)
dep_node_name = om.MFnDependencyNode(mLoc).name()
transl = pm.getAttr("{}.translate".format(dep_node_name))
rotate = pm.getAttr("{}.rotate".format(dep_node_name))
print(dep_node_name)
print(Vector(transl[0], transl[1], transl[2]))
print(Vector(rotate[0], rotate[1], rotate[2]))
pos_array.append((transl[0], transl[1], transl[2]))
rot_array.append(Vector(rotate[0], rotate[1], rotate[2]))
mSel_iter.next()
# Up untill there it seems to work ok.
nparticles_transform, nparticles_shape = pm.nParticle(position=pos_array)
pm.setAttr("nucleus1.gravity", 0.0)
nparticles_shape.computeRotation.set(True)
pm.addAttr(nparticles_shape, ln="rotationPP", dt="vectorArray")
pm.addAttr(nparticles_shape, ln="rotationPP0", dt="vectorArray")
# Create an instancer before trying to edit
instancer_node = pm.particleInstancer(nparticles_shape, name="p_instancer")
pm.particleInstancer(
nparticles_shape, name=instancer_node, edit=True, rotation="rotationPP"
)
particle_fn = omfx.MFnParticleSystem(nparticles_shape.__apimobject__())
particle_fn.setPerParticleAttribute("rotationPP", rot_array)
particle_fn.setPerParticleAttribute("rotationPP0", rot_array)