import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMayaRender as OpenMayaRender
import math
import random
import sys
kSimpleEmitterNodeName = "spSimpleEmitter"
kSimpleEmitterNodeID = OpenMaya.MTypeId(0x8700F)
SEGMENTS = 20
EDGES = 30
TORUS_PI = 3.14159265
TORUS_2PI = 2.0 * TORUS_PI
glRenderer = OpenMayaRender.MHardwareRenderer.theRenderer()
glFT = glRenderer.glFunctionTable()
class simpleEmitter(OpenMayaMPx.MPxEmitterNode):
def __init__(self):
OpenMayaMPx.MPxEmitterNode.__init__(self)
def isFullValue( self, plugIndex, block ):
value = 1
mIsFull = OpenMayaMPx.cvar.MPxEmitterNode_mIsFull
try:
mhValue = block.inputArrayValue( mIsFull )
mhValue.jumpToElement( plugIndex )
hValue = mhValue.inputValue( )
value = hValue.asBool()
except:
sys.stderr.write("Error getting the input array value\n")
raise
return value
def getWorldPosition( self, point ):
try:
thisNode = simpleEmitter.thisMObject( self )
fnThisNode = OpenMaya.MFnDependencyNode(thisNode)
worldMatrixAttr = fnThisNode.attribute( "worldMatrix" )
matrixPlug = OpenMaya.MPlug( thisNode, worldMatrixAttr )
matrixPlug = matrixPlug.elementByLogicalIndex( 0 )
matrixObject = OpenMaya.MObject()
matrixObject = matrixPlug.asMObject( )
worldMatrixData = OpenMaya.MFnMatrixData( matrixObject )
worldMatrix = worldMatrixData.matrix( )
point.x = worldMatrix( 3, 0 )
point.y = worldMatrix( 3, 1 )
point.z = worldMatrix( 3, 2 )
except:
sys.stderr.write( "Error in getWorldPosition\n" )
raise
def currentTimeValue( self, block ):
try:
mCurrentTime = OpenMayaMPx.cvar.MPxEmitterNode_mCurrentTime
hValue = block.inputValue( mCurrentTime )
value = hValue.asTime()
except:
sys.stderr.write("Error getting current time value, returning 0")
value = OpenMaya.MTime(0.0)
return value
def startTimeValue( self, plugIndex, block ):
try:
mStartTime = OpenMayaMPx.cvar.MPxEmitterNode_mStartTime
mhValue = block.inputArrayValue( mStartTime )
mhValue.jumpToElement( plugIndex )
hValue = mhValue.inputValue( )
value = hValue.asTime( )
except:
sys.stderr.write("Error getting start time value, setting to 0")
value = OpenMaya.MTime(0.0)
return value
def deltaTimeValue( self, plugIndex, block ):
try:
mDeltaTime = OpenMayaMPx.cvar.MPxEmitterNode_mDeltaTime
mhValue = block.inputArrayValue( mDeltaTime )
mhValue.jumpToElement( plugIndex )
hValue = mhValue.inputValue()
value = hValue.asTime()
except:
sys.stderr.write("Error getting delta time value, setting to 0\n")
value = OpenMaya.MTime(0.0)
return value
def rateValue( self, block ):
try:
mRate = OpenMayaMPx.cvar.MPxEmitterNode_mRate
hValue = block.inputValue( mRate )
value = hValue.asDouble()
except:
sys.stderr.write("Error getting rate value, setting to 0\n")
value = 0.0
return value
def directionValue( self, block ):
try:
mDirection = OpenMayaMPx.cvar.MPxEmitterNode_mDirection
hValue = block.inputValue( mDirection )
value = hValue.asDouble3()
dirV = OpenMaya.MVector(value[0], value[1], value[2])
except:
sys.stderr.write("Error getting direction value, setting to 0,0,0\n")
dirV = OpenMaya.MVector(0.0, 0.0, 0.0)
return dirV
def speedValue( self, block ):
try:
mSpeed = OpenMayaMPx.cvar.MPxEmitterNode_mSpeed
hValue = block.inputValue( mSpeed )
value = hValue.asDouble()
except:
sys.stderr.write("Error getting speed value, setting to 0\n")
value = 0.0
return value
def inheritFactorValue( self, plugIndex, block ):
try:
mInheritFactor = OpenMayaMPx.cvar.MPxEmitterNode_mInheritFactor
mhValue = block.inputArrayValue( mInheritFactor )
mhValue.jumpToElement( plugIndex )
hValue = mhValue.inputValue( )
value = hValue.asDouble()
except:
sys.stderr.write("Error getting inherit factor value, setting to 0\n")
value = 0.0
return value
def useRotation( self, direction ):
try:
thisNode = simpleEmitter.thisMObject(self)
fnThisNode = OpenMaya.MFnDependencyNode( thisNode )
worldMatrixAttr = fnThisNode.attribute( "worldMatrix" )
matrixPlug = OpenMaya.MPlug( thisNode, worldMatrixAttr )
matrixPlug = matrixPlug.elementByLogicalIndex( 0 )
matrixObject = OpenMaya.MObject()
matrixObject = matrixPlug.asMObject( )
worldMatrixData = OpenMaya.MFnMatrixData( matrixObject )
worldMatrix = worldMatrixData.matrix( )
rotatedVector = OpenMaya.MVector()
rotatedVector = direction * worldMatrix
except:
sys.stderr.write("Error getting rotation value, setting to 0,0,0\n")
rotatedVector = OpenMaya.MVector(0.0, 0.0, 0.0)
return rotatedVector
def compute(self, plug, block):
mOutput = OpenMayaMPx.cvar.MPxEmitterNode_mOutput
if plug == mOutput:
try:
multiIndex = plug.logicalIndex( )
hOutArray = block.outputArrayValue ( mOutput )
bOutArray = hOutArray.builder( )
hOut = bOutArray.addElement( multiIndex )
fnOutput = OpenMaya.MFnArrayAttrsData()
dOutput = fnOutput.create( )
beenFull = simpleEmitter.isFullValue( self, multiIndex, block )
if beenFull == 1:
return
inPosAry = OpenMaya.MVectorArray()
inPosAry.clear()
worldPos = OpenMaya.MPoint(0.0, 0.0, 0.0)
simpleEmitter.getWorldPosition( self, worldPos )
worldV = OpenMaya.MVector(worldPos[0], worldPos[1], worldPos[2])
inPosAry.append( worldV )
inVelAry = OpenMaya.MVectorArray()
inVelAry.clear()
velocity = OpenMaya.MVector(0, 0, 0)
inVelAry.append( velocity )
cT = simpleEmitter.currentTimeValue( self, block )
sT = simpleEmitter.startTimeValue( self, multiIndex, block )
dT = simpleEmitter.deltaTimeValue( self, multiIndex, block )
dTValue = dT.value()
if cT <= sT or dTValue <= 0.0:
hOut.setMObject( dOutput )
block.setClean( plug )
return
emitCountPP = OpenMaya.MIntArray()
emitCountPP.clear()
plugIndex = plug.logicalIndex( )
rate = simpleEmitter.rateValue( self, block )
dtRate = simpleEmitter.deltaTimeValue( self, plugIndex, block )
dtRateDbl = dtRate.as( OpenMaya.MTime.kSeconds )
dblCount = rate * dtRateDbl
intCount = int(dblCount)
emitCountPP.append( intCount )
speed = simpleEmitter.speedValue( self, block )
dirV = simpleEmitter.directionValue( self, block )
inheritFactor = simpleEmitter.inheritFactorValue( self, multiIndex, block )
fnOutPos = fnOutput.vectorArray( "position" )
fnOutVel = fnOutput.vectorArray( "velocity" )
fnOutTime = fnOutput.doubleArray( "timeInStep" )
dt = dT.as( OpenMaya.MTime.kSeconds )
rotatedV = simpleEmitter.useRotation( self, dirV )
simpleEmitter.emit( self, inPosAry, inVelAry, emitCountPP, dt, speed, inheritFactor,\
rotatedV, fnOutPos, fnOutVel, fnOutTime)
hOut.setMObject( dOutput )
block.setClean( plug )
except:
sys.stderr.write("simpleEmitter compute error\n")
raise
else:
return OpenMaya.kUnknownParameter
def emit( self, inPosAry, inVelAry, emitCountPP, dt, speed, inheritFactor, dirV, outPosAry, outVelAry, outTimeAry):
try:
posLength = inPosAry.length()
velLength = inVelAry.length()
countLength = emitCountPP.length()
if not posLength == velLength or not posLength == countLength:
return
totalCount = 0
for index in range(countLength):
totalCount += emitCountPP[index]
if totalCount <= 0:
return
dirV.normalize()
for index in range(posLength):
emitCount = emitCountPP[index]
if emitCount <= 0:
continue
sPos = inPosAry[index]
sVel = inVelAry[index]
prePos = sPos - sVel * dt
for i in range(emitCount):
alpha = ( float(i) + random.random() ) / float(emitCount)
newPos = prePos * (1.0 - alpha) + sPos * alpha
newVel = dirV * speed
newPos += newVel * ( dt * (1.0 - alpha) )
newVel += sVel * inheritFactor
outPosAry.append( newPos )
outVelAry.append( newVel )
outTimeAry.append( alpha )
except Exception, e:
sys.stderr.write( "Error in simpleEmitter.emit\n" )
raise
def draw( self, view, path, style, status):
view.beginGL()
for j in range(0, SEGMENTS):
glFT.glPushMatrix()
glFT.glRotatef(float(360.0 * j/SEGMENTS), 0.0, 1.0, 0.0)
glFT.glTranslatef( 1.5, 0.0, 0.0)
for i in range(0, EDGES):
glFT.glBegin(OpenMayaRender.MGL_LINE_STRIP)
p0 = float(TORUS_2PI * i/EDGES)
p1 = float(TORUS_2PI * (i+1)/EDGES)
glFT.glVertex2f(math.cos(p0), math.sin(p0))
glFT.glVertex2f(math.cos(p1), math.sin(p1))
glFT.glEnd()
glFT.glPopMatrix()
view.endGL()
def nodeCreator():
return OpenMayaMPx.asMPxPtr( simpleEmitter() )
def nodeInitializer():
return
def initializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.registerNode( kSimpleEmitterNodeName, kSimpleEmitterNodeID, \
nodeCreator, nodeInitializer, OpenMayaMPx.MPxNode.kEmitterNode )
except:
sys.stderr.write( "Failed to register node: %s\n" % kSimpleEmitterNodeName )
raise
def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.deregisterNode( kSimpleEmitterNodeID )
except:
sys.stderr.write( "Failed to unregister node: %s\n" % kSimpleEmitterNodeName )
raise