def redoIt(self): mSel = OpenMaya.MSelectionList() mDagPath = OpenMaya.MDagPath() mFnMesh = OpenMaya.MFnMesh() OpenMaya.MGlobal.getActiveSelectionList(mSel) if mSel.length() >= 1: try: mSel.getDagPath(0, mDagPath) mFnMesh.setObject(mDagPath) except: print 'select a poly mesh' else: print 'select some poly Object' print 'I have passed line 46' print mDagPath.fullPathName() mPointArray = OpenMaya.MPointArray() mFnMesh.getPoints(mPointArray, OpenMaya.MSpace.kWorld) print 'I have passed 49' mFnParticle = OpenMayaFX.MFnParticleSystem() self.mObj_particle = mFnParticle.create() mFnParticle = OpenMayaFX.MFnParticleSystem(self.mObj_particle) counter = 0 for i in xrange(mPointArray.length()): if i % self.sparse == 0: mFnParticle.emit(mPointArray[i]) counter += 1 print "Total Points : " + str(counter) mFnParticle.saveInitialState()
def redoIt(self): MSel = om.MSelectionList() MDag = om.MDagPath() MfnMesh = om.MFnMesh() om.MGlobal.getActiveSelectionList(MSel) if MSel.length() >= 1: try: MSel.getDagPath(0, MDag) MfnMesh.setObject(MDag) except: om.MGlobal.displayError("Select a poly mesh") return else: om.MGlobal.displayError("Select mesh object in scene") return # MPointArray = om.MPointArray() MfnMesh.getPoints(MPointArray, om.MSpace.kWorld) # MFnParticle = ofx.MFnParticleSystem() self.MObjParticle = MFnParticle.create() MFnParticle = ofx.MFnParticleSystem(self.MObjParticle) # # counter = 0 for idx in range(MPointArray.length()): if idx % self.sparse == 0: MFnParticle.emit(MPointArray[idx]) counter += 1 om.MGlobal.displayInfo("Total points: {}".format(counter)) MFnParticle.saveInitialState()
def redoIt(self): counter = 0 mSel = OpenMaya.MSelectionList() mDagPath = OpenMaya.MDagPath() mFnMesh = OpenMaya.MFnMesh() OpenMaya.MGlobal.getActiveSelectionList(mSel) if mSel.length() > 0: try: mSel.getDagPath(0, mDagPath) mFnMesh.setObject(mDagPath) except: print "select a poly mesh" return else: print 'select a poly mesh' return mPointArray = OpenMaya.MPointArray() mFnMesh.getPoints(mPointArray, OpenMaya.MSpace.kWorld) print mFnMesh.name() print mPointArray.length() # create a particle system mFnParticle = OpenMayaFX.MFnParticleSystem() self.mObj_particle = mFnParticle.create() # fix some bug issue mFnParticle = OpenMayaFX.MFnParticleSystem(self.mObj_particle) for i in xrange(mPointArray.length()): if i % self.sparse == 0: mFnParticle.emit(mPointArray[i]) counter += 1 print 'Total Points:' + str(counter) mFnParticle.saveInitialState() return
def compareData(self, particleSystemShapes, inputData): if not isinstance(particleSystemShapes, (list, tuple)): particleSystemShapes = [particleSystemShapes] particleFnList = [] sel = OpenMaya.MSelectionList() # Get API objet for particleSystem in particleSystemShapes: sel.add(particleSystem) for i, particleSystem in enumerate(particleSystemShapes): obj = OpenMaya.MObject() sel.getDependNode(i, obj) particleFnList.append(OpenMayaFX.MFnParticleSystem(obj)) frameList = sorted(inputData.keys()) # Compare alembic data with particleData in playback order for frame in inputData.keys(): self.compareAtFrame(inputData, particleFnList, frame) # do it again in a random way, alembic should be consistent when playing randomly or backward random.shuffle(frameList) for frame in frameList: self.compareAtFrame(inputData, particleFnList, frame, info="rand - ")
def runTest(self): fluid = cmds.createNode('fluidShape') selList = om.MSelectionList() selList.add(fluid) dag = om.MDagPath() selList.getDagPath(0, dag) fx.MFnFluid(dag)
def __init__(self, fileHandle, dagPath): """ Set up the objects we're dealing with """ self.fileHandle = fileHandle self.dagPath = dagPath self.fFluid = OpenMayaFX.MFnFluid( dagPath )
def _TestPrototypes(self, instancerName): """ Tests that all of the instancer prototypes made it to USD. """ self.assertTrue(self.stage) instancer = OMFX.MFnInstancer(self._GetDagPath(instancerName)) # Move to the last frame so that we can ensure all of the prototypes # are in use. cmds.currentTime(self.END_TIMECODE, edit=True) paths = OM.MDagPathArray() matrices = OM.MMatrixArray() particlePathStartIndices = OM.MIntArray() pathIndices = OM.MIntArray() instancer.allInstances(paths, matrices, particlePathStartIndices, pathIndices) # Check that the Maya instanced objects are what we think they are. pathStrings = [paths[i].fullPathName() for i in range(paths.length())] self.assertEqual( pathStrings, [ # 0 (logical 0) - Cube "|dummyGroup|pCube1|pCubeShape1", "|dummyGroup|pCube1|pSphere1|pSphereShape1", # 1 (logical 2) - Sphere "|InstancerTest|%s|prototypeUnderInstancer|prototypeUnderInstancerShape" % instancerName, # 2 (logical 3) - Reference "|referencePrototype|NS_referencePrototype:Geom|NS_referencePrototype:Cone|NS_referencePrototype:ConeShape" ]) # Check that the USD prims have correct type name, references, kinds, # kinds, instancerTranslate xformOps. instancerPrim = self.stage.GetPrimAtPath("/InstancerTest/%s" % instancerName) self.assertEqual( Usd.ModelAPI(instancerPrim).GetKind(), Kind.Tokens.subcomponent) prototypesPrim = instancerPrim.GetChild("Prototypes") self.assertEqual(len(prototypesPrim.GetChildren()), 3) self.assertEqual( Usd.ModelAPI(prototypesPrim).GetKind(), Kind.Tokens.subcomponent) # Note that pCube1_0 is a special case where instancerTranslate # isn't the opposite of translate, so both have to be left in. prototype0 = prototypesPrim.GetChild("pCube1_0") self._AssertPrototype(prototype0, "Xform", 2, True) prototype1 = prototypesPrim.GetChild("prototypeUnderInstancer_1") self._AssertPrototype(prototype1, "Mesh", 0, False) prototype2 = prototypesPrim.GetChild("referencePrototype_2") self._AssertPrototype(prototype2, "Xform", 1, False) self.assertEqual( Usd.ModelAPI(prototype2).GetAssetName(), "ConeAssetName")
def redoIt(self): # Read Selection/Actively selected objects mSel = openmaya.MSelectionList() mDagPath = openmaya.MDagPath() mFnMesh = openmaya.MFnMesh() openmaya.MGlobal.getActiveSelectionList(mSel) if mSel.length() >= 1: try: mSel.getDagPath(0, mDagPath) # attach the mesh to the MFnMesh mFnMesh.setObject(mDagPath) except: print "Select a poly mesh" return openmaya.kUnknownParameter else: print "Select a poly mesh" return openmaya.kUnknownParameter # Read vertex positions of selected Mesh mPointArray = openmaya.MPointArray() mFnMesh.getPoints(mPointArray, openmaya.MSpace.kWorld) # Create a particle system mFnParticle = openmayafx.MFnParticleSystem() self.mObj_particle = mFnParticle.create() # Fix maya bug mFnParticle = openmayafx.MFnParticleSystem(self.mObj_particle) # Attach the particles on the vertex positions counter = 0 for i in xrange(mPointArray.length()): if i % self.sparse == 0: mFnParticle.emit(mPointArray[i]) counter += 1 print "Total points :" + str(counter) # After emitting the particle, we have to save the initial state of the particle as well, # otherwise if you apply any dynamics on it, your particles would never come back to their actual positions. mFnParticle.saveInitialState()
def doIt(self, args): ''' Command's first-time execution. ''' # Clear the current selection list to avoid any wrong grouping. OpenMaya.MGlobal.clearSelectionList() # Create the turbulence field self.dagModifier.commandToExecute('turbulence -name "' + self.turbulenceFieldName + '"') self.dagModifier.commandToExecute('scale ' + str(0.5 * self.size_x) + ' ' + str(0.5 * self.size_y) + ' ' + str(0.5 * self.size_z) + ' ' + self.turbulenceFieldName) self.dagModifier.commandToExecute( 'setAttr "' + self.turbulenceFieldName + '.volumeShape" 1') # 1 for cube, 2 for sphere. self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.magnitude" 100') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.attenuation" 0.1') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.frequency" 4') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.interpolationType" 1') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.noiseLevel" 8') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.noiseRatio" 1') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.trapInside" 1') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.trapRadius" 1') # Create the particle system self.dagModifier.commandToExecute('particle -name "' + self.particleSystemName + '"') self.dagModifier.commandToExecute('setAttr "' + self.particleSystemName + 'Shape.conserve" 0.75') self.dagModifier.commandToExecute( 'setAttr "' + self.particleSystemName + 'Shape.particleRenderType" 6') # 3 for points, 6 for streaks # Connect the particle system to the turbulence field. self.dagModifier.commandToExecute( 'connectDynamic -f ' + self.turbulenceFieldName + ' ' + self.particleSystemName + 'Shape') # Execute the commands enqueued in the MDagModifier. self.dagModifier.doIt() # Call a helper function to obtain the MDagPath of the shape. particleShapeDagPath = self.getDagPathToObject(self.particleSystemName + 'Shape') # Create a function set around the particleShapeDagPath. particleSystemFn = OpenMayaFX.MFnParticleSystem(particleShapeDagPath) # Randomly generate the positions of the particles within the volume. for i in range(0, self.numParticles): self.particlePositions.append(random.uniform(0.5 * -self.size_x, 0.5 * self.size_x), random.uniform(0.5 * -self.size_y, 0.5 * self.size_y), random.uniform(0.5 * -self.size_z, 0.5 * self.size_z)) # Emit particles using the particle positions. particleSystemFn.emit(self.particlePositions) # Save the starting positions of the particles, so we can scrub the timeline. particleSystemFn.saveInitialState()
def testTransforms(self): """ Check that the point transforms are correct. """ mayaInstancer = OMFX.MFnInstancer(self._GetDagPath("instancer1")) usdInstancer = UsdGeom.PointInstancer( self.stage.GetPrimAtPath("/InstancerTest/instancer1")) time = self.START_TIMECODE while time <= self.END_TIMECODE: cmds.currentTime(time, edit=True) # Need to do this because MFnInstancer will give instance matrices # as offsets from prototypes' original world space positions. worldPositions = [ self._GetWorldSpacePosition("|dummyGroup|pCube1"), self._GetWorldSpacePosition( "|InstancerTest|instancer1|prototypeUnderInstancer"), self._GetWorldSpacePosition("|referencePrototype") ] paths = OM.MDagPathArray() matrices = OM.MMatrixArray() particlePathStartIndices = OM.MIntArray() pathIndices = OM.MIntArray() mayaInstancer.allInstances(paths, matrices, particlePathStartIndices, pathIndices) usdInstanceTransforms = \ usdInstancer.ComputeInstanceTransformsAtTime(time, time) usdProtoIndices = usdInstancer.GetProtoIndicesAttr().Get(time) self.assertEqual(matrices.length(), len(usdInstanceTransforms)) # Compute the instancer-space position of instances in Maya # (including the protos' transforms). By default, this is what # UsdGeomPointInstancer::ComputeInstanceTransformsAtTime already # gives us. mayaWorldPositions = [ worldPositions[protoIndex] for protoIndex in usdProtoIndices ] mayaGfMatrices = [ mayaWorldPositions[i] * self._MayaToGfMatrix(matrices[i]) for i in xrange(matrices.length()) ] usdGfMatrices = [ usdInstanceTransforms[i] for i in xrange(len(usdInstanceTransforms)) ] for i in xrange(len(usdGfMatrices)): self._AssertXformMatrices(mayaGfMatrices[i], usdGfMatrices[i]) time += 1.0
def redoIt(self): mSel = OpenMaya.MSelectionList() mDagPath = OpenMaya.MDagPath() mFnMesh = OpenMaya.MFnMesh() OpenMaya.MGlobal.getActiveSelectionList( mSel) # return a MselectionList of current selection if mSel.length() >= 1: try: mSel.getDagPath(0, mDagPath) mFnMesh.setObject(mDagPath) except: print 'Select a polymesh' return OpenMaya.kUnknownParameter else: print 'Select a polymesh' return OpenMaya.kUnknownParameter # store vertex points in a MPointArray mPointArray = OpenMaya.MPointArray() mFnMesh.getPoints(mPointArray, OpenMaya.MSpace.kWorld) # Create a particle system mFnParticle = OpenMayaFX.MFnParticleSystem() self.mObj_particle = mFnParticle.create() # to fix maya bug mFnParticle = OpenMayaFX.MFnParticleSystem(self.mObj_particle) counter = 0 for i in xrange(mPointArray.length()): # don't understand this if (i % self.sparse) == 0: mFnParticle.emit(mPointArray[i]) counter += 1 print 'Total points: %s' % str(counter) mFnParticle.saveInitialState() print 'This is self.sparse %s' % self.sparse
def particlePoints(self, selection, scale): dagPath = om.MDagPath() iter = om.MItSelectionList(selection, om.MFn.kParticle) partPoints = [] vec = om.MVectorArray() while not iter.isDone(): iter.getDagPath(dagPath) part = omx.MFnParticleSystem(dagPath) part.position(vec) for i in range(vec.length()): partPoints.append([ vec[i].x * scale, vec[i].y * scale, vec[i].z * scale * -1 ]) iter.next() return partPoints
def testInstancePaths(self): """ Checks that the proto index assigned for each point is correct. """ mayaInstancer = OMFX.MFnInstancer(self._GetDagPath("instancer1")) usdInstancer = UsdGeom.PointInstancer( self.stage.GetPrimAtPath("/InstancerTest/instancer1")) time = self.START_TIMECODE while time <= self.END_TIMECODE: cmds.currentTime(time, edit=True) paths = OM.MDagPathArray() matrices = OM.MMatrixArray() particlePathStartIndices = OM.MIntArray() pathIndices = OM.MIntArray() mayaInstancer.allInstances(paths, matrices, particlePathStartIndices, pathIndices) usdProtoIndices = usdInstancer.GetProtoIndicesAttr().Get(time) # Mapping of proto index to index(es) in the paths array. # Note that in the Maya instancer a single point may map to multiple # DAG paths, which correspond to all the shapes in the instanced # hierarchy. usdIndicesToMayaIndices = { 0: [0, 1], # the first prototype has two shapes in hierarchy 1: [2], # this prototype only has one shape 2: [3], # the reference prototype only has one shape } for i in xrange(len(usdProtoIndices)): usdProtoIndex = usdProtoIndices[i] expectedMayaIndices = usdIndicesToMayaIndices[usdProtoIndex] mayaIndicesStart = particlePathStartIndices[i] mayaIndicesEnd = particlePathStartIndices[i + 1] self.assertEqual(mayaIndicesEnd - mayaIndicesStart, len(expectedMayaIndices)) actualPathIndices = [ pathIndices[i] for i in xrange(mayaIndicesStart, mayaIndicesEnd) ] self.assertEqual(actualPathIndices, expectedMayaIndices) time += 1.0
def particlePoints2(self, selection, scale): dagPath = om.MDagPath() iter = om.MItSelectionList(selection, om.MFn.kParticle) partPoints = [] vec = om.MVectorArray() if self.op['globalpos']: space = 'worldPosition' else: space = 'position' while not iter.isDone(): iter.getDagPath(dagPath) part = omx.MFnParticleSystem(dagPath) part.getPerParticleAttribute(space, vec) for i in range(vec.length()): partPoints.append([ vec[i].x * scale, vec[i].y * scale, vec[i].z * scale * -1 ]) iter.next() return partPoints
def compute(self, plug, data): if plug == testNucleusNode.nextState: if plug.isArray(): # don't support evaluation of the whole array plug, only its elements return OpenMaya.kUnknownParameter logicalIndex = plug.logicalIndex() # get the value of the currentTime currTime = data.inputValue(testNucleusNode.currentTime).asTime() # pull on start state or current state depending on the current time. if currTime.value() <= 0.0: multiDataHandle = data.inputArrayValue( testNucleusNode.startState) multiDataHandle.jumpToElement(logicalIndex) inputData = multiDataHandle.inputValue().data() else: multiDataHandle = data.inputArrayValue( testNucleusNode.currentState) multiDataHandle.jumpToElement(logicalIndex) inputData = multiDataHandle.inputValue().data() inputNData = OpenMayaFX.MFnNObjectData(inputData) nObj = inputNData.getClothObjectPtr() points = OpenMaya.MFloatPointArray() nObj.getPositions(points) for ii in range(points.length()): points[ii].y = math.sin(points[ii].x + currTime.value() * 4.0 * (3.1415 / 180.0)) nObj.setPositions(points) data.setClean(plug) elif plug == testNucleusNode.currentState: data.setClean(plug) elif plug == testNucleusNode.startState: data.setClean(plug) else: return OpenMaya.kUnknownParameter
def getPartticlePos(parDag, parCom): parPos = mom.MVectorArray() parDag.extendToShape() parSysFn = momf.MFnParticleSystem(parDag) parSysFn.position(parPos) isParticle = parDag.hasFn(mom.MFn.kParticle) isNParticle = parDag.hasFn(mom.MFn.kNParticle) if (isParticle == 0) and (isNParticle == 0): return parPos if (parCom.isNull() == 0) and (parCom.apiType() == mom.MFn.kDynParticleSetComponent): compFn = mom.MFnSingleIndexedComponent(parCom) idArray = mom.MIntArray() compFn.getElements(idArray) newPos = mom.MVectorArray() if idArray.length() != 0: for i in range(0, idArray.length()): newPos.append(parPos[idArray[i]]) return newPos else: return parPos return parPos
def doIt(self, args): #command's first-time execution #parse the flags and the arguments!! try: self.parseArgs(args) except Exception: #an exception should be thrown here if the argument/flag syntax is wrong. print('Invalid flag syntax for parse command!') return #END EXECUTION!! dont carry on.. #clear the current selection list to avoid any wrong grouping. OpenMaya.MGlobal.clearSelectionList() #create the "turbulence field". got help online for these! self.dagModifier.commandToExecute('turbulence -name "' + self.tur_field_name + '"') self.dagModifier.commandToExecute('scale ' + str(0.5 * self.size_x) + ' ' + str(0.5 * self.size_y) + ' ' + str(0.5 * self.size_z) + ' ' + self.tur_field_name) self.dagModifier.commandToExecute( 'setAttr "' + self.tur_field_name + '.volumeShape" ' + str(self.volShapeNum) ) # 1 for cube, 2 for sphere ... check maya doc for more (goes uptil 5) self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name + '.magnitude" 100') self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name + '.attenuation" 0.1') self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name + '.frequency" 4') self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name + '.interpolationType" 1') self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name + '.noiseLevel" 8') self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name + '.noiseRatio" 1') self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name + '.trapInside" 1') self.dagModifier.commandToExecute('setAttr "' + self.tur_field_name + '.trapRadius" 1') # create the particle system of "bees" or particles self.dagModifier.commandToExecute('particle -name "' + self.particle_system_name + '"') self.dagModifier.commandToExecute('setAttr "' + self.particle_system_name + 'Shape.conserve" 1.00') self.dagModifier.commandToExecute( 'setAttr "' + self.particle_system_name + 'Shape.particleRenderType" 6') # 3 for points, 6 for streaks #connect the particle system to the turbulence field. #COPIED!! self.dagModifier.commandToExecute('connectDynamic -f ' + self.tur_field_name + ' ' + self.particle_system_name + 'Shape') self.dagModifier.doIt() particleShapeDagPath = self.getDagPathToObject( self.particle_system_name + 'Shape') particleSystemFn = OpenMayaFX.MFnParticleSystem(particleShapeDagPath) #randomly generate the positions of the particles within the volume. for i in range(0, self.numParticles): self.particlePositions.append( random.uniform(0.5 * -self.size_x, 0.5 * self.size_x), random.uniform(0.5 * -self.size_y, 0.5 * self.size_y), random.uniform(0.5 * -self.size_z, 0.5 * self.size_z)) #emit means to display the particles at those positions particleSystemFn.emit(self.particlePositions) particleSystemFn.saveInitialState()
def getData(particleSystemShapes, frameRange=(1, 24), abc=False, customAttribute=[]): ''' Create a dict containing data exemple: dict = { frame : { attibute : [data] } 3: "nParticle_test_1Shape" : {'id': [0.0], 'position': [(-0.0025255996733903885, 4.990767002105713, -0.0024415384978055954)], 'radius': [0.20000000298023224], 'rgbPP': [(0.44199632268870914, 0.2631281241639378, 0.6541382528648185)], 'rotationPP': [(0.0, -0.0, 0.0)], 'velocity': [(-0.6160576343536377, 0.1030367910861969, -0.5955522060394287)]}, ''' if not isinstance(particleSystemShapes, (list, tuple)): particleSystemShapes = [particleSystemShapes] # Get API objet particleFnList = [] sel = OpenMaya.MSelectionList() for particleSystem in particleSystemShapes: sel.add(particleSystem) for i, particleSystem in enumerate(particleSystemShapes): obj = OpenMaya.MObject() stdoutWrite("%d: %s" % (i, particleSystem)) sel.getDependNode(i, obj) particleFnList.append(OpenMayaFX.MFnParticleSystem(obj)) testData = {} # seed on first frame (doing the same before alembic export to correctly match randomly generated attributes) cmds.currentTime(1) maya.mel.eval("seed(1)") frameList = range(frameRange[0], frameRange[1]) perParticleAttr = ("particleId", "position", "acceleration", "velocity", "radius", "force", "rgbPP", "mass", "age", "lifespanPP") for item in customAttribute: perParticleAttr.append(item) # Now eval the frameList for frame in frameList: stdoutWrite("fame: %d" % frame) # Jump to frame OpenMaya.MGlobal.viewFrame(frame) testData[frame] = {} for particleFn in particleFnList: stdoutWrite("\t: %s" % particleFn.name()) # Force evaluate dynamics particleFn.evaluateDynamics(OpenMaya.MTime(frame), False) testData[frame][particleFn.name()] = {} # Get all perParticle attributes for current Shape for attr in perParticleAttr: if cmds.objExists("%s.%s" % (particleFn.name(), attr)): testData[frame][ particleFn.name()][attr] = getParticleAttribute( particleFn, attr, abc=abc) return testData
class Volume(ExportModule): """ Fluid volume export module """ fFluid = OpenMayaFX.MFnFluid() def __init__(self, fileHandle, dagPath): """ Set up the objects we're dealing with """ self.fileHandle = fileHandle self.dagPath = dagPath self.fFluid = OpenMayaFX.MFnFluid( dagPath ) def getOutput(self): """ Read Fluid data and export as volumegrid """ xPtr = OpenMaya.MScriptUtil().asDoublePtr() yPtr = OpenMaya.MScriptUtil().asDoublePtr() zPtr = OpenMaya.MScriptUtil().asDoublePtr() self.fFluid.getDimensions( xPtr, yPtr, zPtr ) dimX = OpenMaya.MScriptUtil( xPtr ).asDouble() / 2 dimY = OpenMaya.MScriptUtil( yPtr ).asDouble() / 2 dimZ = OpenMaya.MScriptUtil( zPtr ).asDouble() / 2 #xrPtr = OpenMaya.MScriptUtil().asIntPtr() #yrPtr = OpenMaya.MScriptUtil().asIntPtr() #zrPtr = OpenMaya.MScriptUtil().asIntPtr() #self.fFluid.getResolution( xrPtr, yrPtr, zrPtr ) #xres = OpenMaya.MScriptUtil( xrPtr ).asInt() #yres = OpenMaya.MScriptUtil( yrPtr ).asInt() #zres = OpenMaya.MScriptUtil( zrPtr ).asInt() # getResolution is NOT IMPLEMENTED !!! ??! # therefore, assume equal res in every direction xres = yres = zres = round(self.fFluid.gridSize()**0.333333333333) self.addToOutput( 'AttributeBegin' ) self.addToOutput( self.translationMatrix(self.dagPath) ) self.addToOutput( '\tVolume "volumegrid"' ) self.addToOutput( '\t\t"color sigma_a" [0.9 0.9 0.9]' ) self.addToOutput( '\t\t"point p0" [%f %f %f]' % (-dimX, -dimY, -dimZ) ) self.addToOutput( '\t\t"point p1" [%f %f %f]' % ( dimX, dimY, dimZ) ) self.addToOutput( '\t\t"integer nx" [%i]' % xres ) self.addToOutput( '\t\t"integer ny" [%i]' % yres ) self.addToOutput( '\t\t"integer nz" [%i]' % zres ) self.addToOutput( '\t\t"float density" [' ) outStr = str() for i in range(0, self.fFluid.gridSize()): outStr += '%f ' % OpenMaya.MScriptUtil.getFloatArrayItem( self.fFluid.density(), i) self.addToOutput( '\t\t\t%s' % outStr ) self.addToOutput( '\t\t]' ) self.addToOutput( 'AttributeEnd' ) self.addToOutput( '' )
def set_initial_state(npNode=None, npFnPart=None): """ Given a particle dependency node calculate the start goalU and and goalV values :param npNode: Particle dependency node to get goal data from :param npFnPart: particle function set we can get the points from and set data """ print '#----------------------------#' print 'Setting initial state' # before we start set the time back to the first frame tMin = int(cmds.playbackOptions(q=True, minTime=True)) cmds.currentTime(tMin, e=True) # a dict of all the base attributes we want to make sure exist! attrs = { 'goalU': { 'longName': 'goalU', 'shortName': 'goalU', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'goalV': { 'longName': 'goalV', 'shortName': 'goalV', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'verticalSpeedPP': { 'longName': 'verticalSpeedPP', 'shortName': 'vSpePP', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'rotationRatePP': { 'longName': 'rotationRatePP', 'shortName': 'rotRtPP', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'jitterIntervalPP': { 'longName': 'jitterIntervalPP', 'shortName': 'jtrIntPP', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'jitterStepPP': { 'longName': 'jitterStepPP', 'shortName': 'jtrStpPP', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'jitterRangePP': { 'longName': 'jitterRangePP', 'shortName': 'jtrRngPP', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'jitterValuePP': { 'longName': 'jitterValuePP', 'shortName': 'jtrValPP', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'isDonePP': { 'longName': 'isDonePP', 'shortName': 'isDonePP', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() }, 'lifespanPP': { 'longName': 'lifespanPP', 'shortName': 'lifespanPP', 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, # @UndefinedVariable 'data': om.MDoubleArray() } } # if nothing passed in we assume we are updating intial state # so need to setup npNode and npFnPart from selection if not npNode: sel = cmds.ls(sl=True, l=True) if len(sel) == 0: print 'Please select a nParticle system to update initial state on!' return # from the list make sure the first object is a nparticle system, get a handle on this # then remove from the list if not cmds.objectType(sel[0]) == 'nParticle': shape = cmds.listRelatives(sel[0])[0] if not cmds.objectType(shape) == 'nParticle': print 'Please select a nParticle system followed by objects to goal to!' return else: npShape = shape else: npShape = sel.pop(0) # now we have our particle system we need to get the # dependency node and particle system function set selList = om.MSelectionList() selList.add(npShape) npDag = om.MDagPath() npMObj = om.MObject() selList.getDependNode(0, npMObj) selList.getDagPath(0, npDag) npNode = om.MFnDependencyNode(npMObj) npFnPart = omfx.MFnParticleSystem(npDag) # make sure that we have a valid function set if npFnPart == None: print '###Error: Please make sure you pass in both a dependency node and function set or neither!' return # get the goalGeometry plug. this can tell us what our # particle is goaled to goalGeo_plug = npNode.findPlug('goalGeometry') # get the first item that is connected as a goal (this will be our initial goal) goal_plug = goalGeo_plug.elementByPhysicalIndex(0) attrName = goal_plug.name() # get the goal index number (this may not be 0) goalIndex = attrName.split('[')[-1].split(']')[0] # create the goal weight attribute attrs['goalWeight{}PP'.format(goalIndex)] = { 'longName': 'goalWeight%sPP' % goalIndex, 'shortName': 'goalWeight%sPP' % goalIndex, 'initialState': True, 'type': om.MFnNumericData.kDoubleArray, 'data': om.MDoubleArray() } # make sure that all the attributes we need exist _create_attributes(npNode, attrs) # get all the objects connected to our goal array plug (should only be 1!) mPlugArray = om.MPlugArray() goal_plug.connectedTo(mPlugArray, True, False) if mPlugArray.length() > 1: print '###Error :More than one object is connected to this goal plug. Weird!' return goalMeshFn = om.MFnMesh() # get the node that is connected the plug and get a mesh function set goal_obj = mPlugArray[0].node() goal_dagpath = om.MDagPath().getAPathTo(goal_obj) goalMeshFn.setObject(goal_dagpath) # get user defined variables verticalOffset = 0 goalWeight_min = 0.2 goalWeight_max = 0.4 verticleSpeed_min = 0.005 verticleSpeed_max = 0.0075 rotationSpeed = 0.1 jitterInterval = 10 jitterRange = 0.01 # setup a bunch of arrays we are about to calculate # then get a list of all the points in our particle system and iterate through them partPosArray = om.MVectorArray() npFnPart.position(partPosArray) # for each particle we want to calculate information on the intial state # for all of our pp attributes we want to set for i in range(partPosArray.length()): # get our particle point as a vector partPoint = partPosArray[i] # get the goal uvs closest to our point uvArray = [0, 0] scriptUtil = om.MScriptUtil() scriptUtil.createFromList(uvArray, 2) uvPoint = scriptUtil.asFloat2Ptr() goalMeshFn.getUVAtPoint(om.MPoint(partPoint), uvPoint, om.MSpace.kWorld) uPoint = om.MScriptUtil.getFloat2ArrayItem(uvPoint, 0, 0) #vPoint = om.MScriptUtil.getFloat2ArrayItem(uvPoint, 0, 1) # append to our goalU and goalV array attrs['goalU']['data'].append(uPoint % 1) attrs['goalV']['data'].append(random.uniform(0, verticalOffset)) goalWeight = random.uniform(goalWeight_min, goalWeight_max) # give this particle a random goal weight attrs['goalWeight%sPP' % goalIndex]['data'].append(goalWeight) #goal_weights.append(1) # set a bunch of attributes used to control motion of particles attrs['verticalSpeedPP']['data'].append( random.uniform(verticleSpeed_min, verticleSpeed_max)) adjustedRot = rotationSpeed * (1.1 - goalWeight) attrs['rotationRatePP']['data'].append(random.uniform(0, adjustedRot)) attrs['jitterIntervalPP']['data'].append( random.randint(1, jitterInterval)) attrs['jitterStepPP']['data'].append(0) attrs['jitterRangePP']['data'].append(jitterRange) attrs['jitterValuePP']['data'].append( random.uniform((-1 * jitterRange), jitterRange)) attrs['isDonePP']['data'].append(0) attrs['lifespanPP']['data'].append(100000000000000000) # for each item in our attrs dictionary we want to set the attribute data for i in attrs: print 'Setting: %s' % i if npFnPart.hasAttribute(i): npFnPart.setPerParticleAttribute(i, attrs[i]['data']) # save our intial state (NB: if the particle sim has moved on from particle start it # will overwrite their positions. Write a check in at the start of function) npFnPart.saveInitialState()
def bake(instancerName, start, end, progress=None): """ Process an instancer node over the specified frame range, reading the positions and objects. With this data objects are duplicated and positioned to mimic the instancer. With the particle data individual objects can be matched over the different frames and animated. When a particle "dies", the visibility is turned off. :param str instancerName: Name if the instancer to bake :param int start: Start frame :param int end: End frame :param QProgressBar progress: Update ui ( Optional ) :return: Group that contains all of the baked information :rtype: str :raises RuntimeError: When the instancer doesn't exist :raises RuntimeError: When there are no particles attached """ # store all particle information in data variable data = {} # get instance if not cmds.objExists(instancerName): raise RuntimeError("Instancer doesn't exist!") return # set visible cmds.setAttr("{0}.visibility".format(instancerName), 1) instancerObj = asMObject(instancerName) instancerDag = asMDagPath(instancerObj) instancer = OpenMayaFX.MFnInstancer(instancerDag) # get particles particleName = cmds.listConnections( "{0}.inputPoints".format(instancerName)) if not particleName: raise RuntimeError("No particles connected!") return particleName = particleName[0] particleObj = asMObject(particleName) particleDag = asMDagPath(particleObj) particle = OpenMayaFX.MFnParticleSystem(particleDag) # variables ages = OpenMaya.MDoubleArray() paths = OpenMaya.MDagPathArray() matrices = OpenMaya.MMatrixArray() particleIndices = OpenMaya.MIntArray() pathIndices = OpenMaya.MIntArray() # create container group container = cmds.group(world=True, empty=True, n="{0}_bake_1".format(instancerName)) # loop time for i in range(start, end + 1): # set time cmds.currentTime(i) # query instancer information instancer.allInstances(paths, matrices, particleIndices, pathIndices) # query particle information particle.age(ages) # loop particle instances num = matrices.length() for j in range(num): # get particles index p = particleIndices[j] # get parent parent = paths[pathIndices[j]].fullPathName() # get age age = ages[j] if data.get(p): # get path and age path = data[p].get("path") oldAge = data[p].get("age") oldParent = data[p].get("parent") # check if age is less than previous if age < oldAge: # hide mesh and delete particle id data keyVisibility(path, i, 0) del (data[p]) # check if parent is the same as previous elif parent != oldParent: # hide mesh and delete particle id data keyVisibility(path, i, 0) del (data[p]) # duplicate path if index not in data if not data.get(p): # get parent name parentShort = parent.split("|")[-1].split(":")[-1] # duplicate mesh name = "{0}_{1}_1".format(instancerName, parentShort) path = cmds.duplicate(parent, n=name)[0] path = cmds.parent(path, container)[0] # handle visibility keyVisibility(path, i, 1) # get dag dag = asMDagPath(asMObject(path)) # get matrix transform = asMFnTransform(dag) matrix = transform.transformation().asMatrix() # store variables data[p] = {} data[p]["path"] = path data[p]["dag"] = dag data[p]["matrix"] = matrix data[p]["parent"] = parent # get variables path = data[p].get("path") dag = data[p].get("dag") matrix = data[p].get("matrix") # store age data[p]["age"] = age # set matrix m = matrix * matrices[j] m = OpenMaya.MTransformationMatrix(m) transform = asMFnTransform(dag) transform.set(m) # set keyframes keyTransform(path, i) # update progress if progress: progress.setValue(i + 1 - start) return container
def sampleColorAtParticle(textureNode, particleShapeNode): # get the particle object as an MObject selectionList = om.MSelectionList() selectionList.add(particleShapeNode) particleObject = om.MObject() selectionList.getDependNode(0, particleObject) # create a MFnParticle to get to the data particleDataFn = omFX.MFnParticleSystem(particleObject) # get the positionPP data posPPArray = om.MVectorArray() particleDataFn.getPerParticleAttribute("position", posPPArray) # these are the arguments required to sample a 3d texture: shadingNodeName = textureNode numSamples = posPPArray.length() pointArray = om.MFloatPointArray() pointArray.setLength(numSamples) refPoints = om.MFloatPointArray() refPoints.setLength(numSamples) for i in range(posPPArray.length()): particlePosVector = om.MVector() particlePosVector = posPPArray[i] location = om.MFloatPoint( particlePosVector[0], particlePosVector[1], particlePosVector[2]) pointArray.set(location, i) refPoints.set(location, i) # but we don't need these useShadowMap = False reuseMaps = False cameraMatrix = om.MFloatMatrix() uCoords = None vCoords = None normals = None tangentUs = None tangentVs = None filterSizes = None # and the return arguments are empty.... resultColors = om.MFloatVectorArray() resultTransparencies = om.MFloatVectorArray() # this is the command wot samples omr.MRenderUtil.sampleShadingNetwork(shadingNodeName, numSamples, useShadowMap, reuseMaps, cameraMatrix, pointArray, uCoords, vCoords, normals, refPoints, tangentUs, tangentVs, filterSizes, resultColors, resultTransparencies) # use the sampled colours to set rgbPP resultPPColors = om.MVectorArray() resultPPColors.clear() for i in range(resultColors.length()): floatVector = om.MFloatVector(resultColors[i]) vector = om.MVector(floatVector) resultPPColors.append(vector) particleDataFn.setPerParticleAttribute("rgbPP", resultPPColors)
def doIt(self, args): # Procesar argumentos try: self.parseArgs(args) except Exception as e: print('[' + commandName + '] Sintaxis de flag invalida') return # Deseleciona todo OpenMaya.MGlobal.clearSelectionList() # Crea el campo de turbulencia self.dagModifier.commandToExecute('turbulence -name "' + self.turbulenceFieldName + '"') self.dagModifier.commandToExecute('scale ' + str(0.5 * self.size_x) + ' ' + str(0.5 * self.size_y) + ' ' + str(0.5 * self.size_z) + ' ' + self.turbulenceFieldName) self.dagModifier.commandToExecute( 'setAttr "' + self.turbulenceFieldName + '.volumeShape" 1') # 1 para cubo, 2 para esfera self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.magnitude" 100') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.attenuation" 0.1') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.frequency" 4') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.interpolationType" 1') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.noiseLevel" 8') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.noiseRatio" 1') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.trapInside" 1') self.dagModifier.commandToExecute('setAttr "' + self.turbulenceFieldName + '.trapRadius" 1') # Crea el sistema de particulas self.dagModifier.commandToExecute('particle -name "' + self.particleSystemName + '"') self.dagModifier.commandToExecute('setAttr "' + self.particleSystemName + 'Shape.conserve" 0.75') self.dagModifier.commandToExecute( 'setAttr "' + self.particleSystemName + 'Shape.particleRenderType" 6') # 3 para puntos, 6 para streaks # Conecta el sistema de particulas con el campo de fuerza self.dagModifier.commandToExecute('connectDynamic -f ' + self.turbulenceFieldName + ' ' + self.particleSystemName + 'Shape') # Ejecuta los comandos encolados self.dagModifier.doIt() # Ayuda a obtener el Dag path del particleShape particleShapeDagPath = self.getDagPathToObject( self.particleSystemName + 'Shape') # Crea una funcion para establecer al particleShapeDagPath particleSystemFn = OpenMayaFX.MFnParticleSystem(particleShapeDagPath) # Genera aleatoriamente las posiciones de las particulas for i in range(0, self.numParticles): self.particlesPositions.append( random.uniform(0.5 * -self.size_x, 0.5 * self.size_x), random.uniform(0.5 * -self.size_y, 0.5 * self.size_y), random.uniform(0.5 * -self.size_z, 0.5 * self.size_z)) # Emite particulas usando las posiciones generadas particleSystemFn.emit(self.particlesPositions) particleSystemFn.saveInitialState()
def set_goals(): sel = cmds.ls(sl=True, l=True) # make sure we have at least two items if len(sel) < 2: print 'Please select a nParticle system followed by the objects to set as goals' return elif len(sel) > 2: print 'For inital goal we want one particle system and one object to goal!' print 'Try again :)' return print sel # from the list make sure the first object is a nparticle system, get a handle on this # then remove from the list if not cmds.objectType(sel[0]) == 'nParticle': shape = cmds.listRelatives(sel[0])[0] if not cmds.objectType(shape) == 'nParticle': print 'Please select a nParticle system followed by objects to goal to!' return else: npSystem = sel.pop(0) npShape = shape else: npShape = sel.pop(0) npSystem = cmds.listRelatives(npShape, parent=True, f=True) obj = sel[0] selList = om.MSelectionList() selList.add(npShape) npDag = om.MDagPath() npMObj = om.MObject() selList.getDependNode(0, npMObj) selList.getDagPath(0, npDag) npNode = om.MFnDependencyNode(npMObj) npFnPart = omfx.MFnParticleSystem(npDag) if _get_goal(npDag): print 'Particle system already has goal. For now we are only supporting one goal!' return cmds.goal(npSystem, g=obj, w=1) set_initial_state(npNode, npFnPart) print '#------------------------------#' creation_dynExpression = ('.goalV = 0;\n' '.goalU = 0;\n' '.goalWeight0PP = .2;\n' '.verticalSpeedPP = rand(0.01, 0.1);\n' '.rotationRatePP = rand(0.03, 0.05);\n' '.jitterIntervalPP = 0;\n' '.jitterStepPP = 0;\n' '.jitterRangePP = 0;\n' '.lifespanPP = 5;') runtime_dynExpression = ('.goalV += .verticalSpeedPP;\n' '.goalU += .rotationRatePP;\n\n' 'if (.jitterIntervalPP > .jitterStepPP)\n' '{\n' '\t.jitterStepPP ++;\n' '}\n' 'else\n' '{\n' '\t.goalU += .jitterValuePP;\n' '\t$hiRange = rand(0, .jitterRangePP);\n' '\t$loRange = $hiRange * -1;\n' '\t.jitterValuePP = rand($loRange, $hiRange);\n' '\t.jitterStepPP = 0;\n' '}\n\n' 'if (.goalU > 1)\n' '{\n' '\t.goalU -= 1;\n' '}\n' 'else if(.goalU < 0)\n' '{\n' '\t.goalU += 1;\n' '}') cmds.dynExpression(npShape, creation=True, string=creation_dynExpression) cmds.dynExpression(npShape, rbd=True, string=runtime_dynExpression) # now we want to make our goal object a passive rigid body so that # the particles don't go through it cmds.select(obj) print 'Selection is: %s' % cmds.ls(sl=True) # make our goal object a passive rigid body so the particles # can collide with it cmd = 'makeCollideNCloth' rigidShape = mel.eval(cmd) # rigid shape is not created if it already exists! if rigidShape: # parent the rigid body to keep things tidy nRigid = cmds.listRelatives(rigidShape[0], parent=True, f=True) #cmds.parent(nRigid, dynamics_grp) # select our particle system to tidy things up cmds.select(npSystem)