Get adjacent vertex positions in maya deformer node? [ Maya Python API ]

Hi all,

I’m trying to write a smooth deformer in Maya using Python API. I need to find the adjacent vertices’ positions for each vertex. I found that MItMeshVertex.getConnectedVertices() does exactly what I need but I can’t create a MItMeshVertex cause it needs an MObject as input and I don’t know how to find the MObject of the current inputGeom.

This is how far I went by now:
##############################################################################

import maya.OpenMaya as om
import maya.OpenMayaMPx as mpx
import sys

pluginName = ‘flattenDeformer’
pluginId = om.MTypeId( 0x0011E183 )

class flattenDeformer( mpx.MPxDeformerNode ):

def __init__( self ):
	mpx.MPxDeformerNode.__init__( self )

def deform( self, block, geoItr, matrix, index ):
	
	# 0. get deformer input
	input = mpx.cvar.MPxDeformerNode_input
	
	# 1. Attach a handle to input Array Attribute.
	inputHandle_array = block.inputArrayValue( input )
	
	# 2. Jump to particular element
	inputHandle_array.jumpToElement( index )
	
	# 3. get value of current element
	inputValue_element = inputHandle_array.inputValue()
		
	# 4. Reach to the child - inputGeom
	inputGeom = mpx.cvar.MPxDeformerNode_inputGeom
	inMeshHandle = inputValue_element.child( inputGeom )
	
	# 5. get Mesh
	inMesh = inMeshHandle.asMesh()
	
	# ----------------------------------where I have problem--------------------------------------
	# vertexMeshItr = om.MItMeshVertex( inMesh )
	
	
	envelope = mpx.cvar.MPxDeformerNode_envelope
	envelopeHandle = block.inputValue( envelope )
	envelopeValue = envelopeHandle.asFloat()
	
			
	while not vertexMeshItr.isDone():
		#connectedVerts = vertexMeshItr.getConnectedVertices( )
		
		position = vertexMeshItr.position( )
		position.y = position.y - (position.y * envelopeValue);
		vertexMeshItr.setPosition( position )
		
		vertexMeshItr.next()
	
	return om.MStatus.kSuccess

def nodeCreator():
return mpx.asMPxPtr( flattenDeformer() )

def nodeInitializer():
pass

def initializePlugin( mObj ):
plugin = mpx.MFnPlugin( mObj, ‘Ehsan HM’, ‘1.0’, ‘any’ )
try:
plugin.registerNode( pluginName, pluginId, nodeCreator, nodeInitializer, mpx.MPxNode.kDeformerNode )
except:
sys.stderr.write( ‘Load plugin failed: %s’ % pluginName )

def uninitializePlugin( mObj ):
plugin = mpx.MFnPlugin( mObj )
try:
plugin.deregisterNode( pluginId )
except:
sys.stderr.write( ‘Unload plugin failed: %s’ % pluginName )

##############################################################################

Any help is appreciated.
Ehsan

I recently discovered this, if you can import pymel.

selection = pm.ls(selection = True)[0]
the_mobject = selection.apimobject()
the_mdagpath = selection.apimdagpath()

From Advanced Topics — PyMEL 1.0.5 documentation

Hope that helps

maybe this can help:


import maya.OpenMaya as om
import maya.cmds as cmds
cmds.sphere()
test = 'pSphere1Shape'
selList = om.MSelectionList()
selList.add(test)
mObj = om.MObject()
selList.getDependNode(0, mObj) # mObj should now contain the MObject equivalent of "pSphere1Shape"

You were close:

def deform(self, data, itGeo, localToWorldMatrix, geomIndex ):
    inputAttribute = OpenMayaMPx.cvar.MPxDeformerNode_input
    inputGeom = OpenMayaMPx.cvar.MPxDeformerNode_inputGeom
    hInput = data.outputArrayValue( inputAttribute )
    hInput.jumpToElement( geomIndex )
    oInputGeom = hInput.outputValue().child( inputGeom ).asMesh()
    itInputMeshVertex = OpenMaya.MItMeshVertex( oInputGeom )

    while not itInputMeshVertex.isDone():
        print 'index', itInputMeshVertex.index()
        itInputMeshVertex.next()

from: http://www.chadvernon.com/blog/resources/maya-api-programming/deformers/getting-the-input-geometry-mobject/

Thank you all guys.

MItMeshVertex.setPosition( pointPosition ) doesn’t seem to have any effect on the object. Could you please check this code ?

#####################################

import maya.OpenMaya as om
import maya.OpenMayaMPx as mpx
import sys

pluginName = ‘ehm_flattenDeformer2’
pluginId = om.MTypeId( 0x0011E183 )

class ehm_flattenDeformer2( mpx.MPxDeformerNode ):

def __init__( self ):
	mpx.MPxDeformerNode.__init__( self )

def deform( self, block, geoItr, matrix, index ):
	
	# 0. get deformer input
	input = mpx.cvar.MPxDeformerNode_input
	
	# 1. Attach a handle to input Array Attribute.
	inputHandle_array = block.inputArrayValue( input )
	
	# 2. Jump to particular element
	inputHandle_array.jumpToElement( index )
	
	# 3. get value of current element
	inputValue_element = inputHandle_array.inputValue()
		
	# 4. Reach to the child - inputGeom
	inputGeom = mpx.cvar.MPxDeformerNode_inputGeom
	inMeshHandle = inputValue_element.child( inputGeom )
	
	# 5. get Mesh
	inMesh = inMeshHandle.asMesh()
	
	# envelope
	envelope = mpx.cvar.MPxDeformerNode_envelope
	envelopeHandle = block.inputValue( envelope )
	envelopeValue = envelopeHandle.asFloat()
	
	
	inmeshVertexItr = om.MItMeshVertex( inMesh )
	# surroundingVertsIndices = om.MIntArray()
	
	while not inmeshVertexItr.isDone():
		pPosition = inmeshVertexItr.position()
		pPosition.y = 0.0
		inmeshVertexItr.setPosition( pPosition )
				
		#inmeshVertexItr.getConnectedVertices( surroundingVertsIndices )

		
		inmeshVertexItr.next()

def nodeCreator():
return mpx.asMPxPtr( ehm_flattenDeformer2() )

def nodeInitializer():
pass

def initializePlugin( mObj ):
plugin = mpx.MFnPlugin( mObj, ‘Ehsan HM’, ‘1.0’, ‘any’ )
try:
plugin.registerNode( pluginName, pluginId, nodeCreator, nodeInitializer, mpx.MPxNode.kDeformerNode )
except:
sys.stderr.write( ‘Load plugin failed: %s’ % pluginName )

def uninitializePlugin( mObj ):
plugin = mpx.MFnPlugin( mObj )
try:
plugin.deregisterNode( pluginId )
except:
sys.stderr.write( ‘Unload plugin failed: %s’ % pluginName )

##################################

Thanks again,

Post your code inside [ CODE ] [ /CODE ] tags (no spaces next to the brackets though), it preserves indentation

Ok, here is the code:

Could you try it? It must work but somehow it doesn’t.

import maya.OpenMaya as om
import maya.OpenMayaMPx as mpx
import sys

pluginName = 'ehm_flattenDeformer2'
pluginId = om.MTypeId( 0x0011E183 )

class ehm_flattenDeformer2( mpx.MPxDeformerNode ):
	
	def __init__( self ):
		mpx.MPxDeformerNode.__init__( self )
	
	def deform( self, block, geoItr, matrix, index ):
		
		# 0. get deformer input
		input = mpx.cvar.MPxDeformerNode_input
		
		# 1. Attach a handle to input Array Attribute.
		inputHandle_array = block.inputArrayValue( input )
		
		# 2. Jump to particular element
		inputHandle_array.jumpToElement( index )
		
		# 3. get value of current element
		inputValue_element = inputHandle_array.inputValue()
			
		# 4. Reach to the child - inputGeom
		inputGeom = mpx.cvar.MPxDeformerNode_inputGeom
		inMeshHandle = inputValue_element.child( inputGeom )
		
		# 5. get Mesh
		inMesh = inMeshHandle.asMesh()
		
		# envelope
		envelope = mpx.cvar.MPxDeformerNode_envelope
		envelopeHandle = block.inputValue( envelope )
		envelopeValue = envelopeHandle.asFloat()
		
		
		inmeshVertexItr = om.MItMeshVertex( inMesh )
			
		while not inmeshVertexItr.isDone():
			pPosition = inmeshVertexItr.position()
			pPosition.y = 0.0
			inmeshVertexItr.setPosition( pPosition )
			inmeshVertexItr.next()
		
		
def nodeCreator():
	return mpx.asMPxPtr( ehm_flattenDeformer2() )

	
def nodeInitializer():
	pass

	
def initializePlugin( mObj ):
	plugin = mpx.MFnPlugin( mObj, 'Ehsan HM', '1.0', 'any' )
	try:
		plugin.registerNode( pluginName, pluginId, nodeCreator, nodeInitializer, mpx.MPxNode.kDeformerNode )
	except:
		sys.stderr.write( 'Load plugin failed: %s' % pluginName )

		
		
def uninitializePlugin( mObj ):
	plugin = mpx.MFnPlugin( mObj )
	try:
		plugin.deregisterNode( pluginId )
	except:
		sys.stderr.write( 'Unload plugin failed: %s' % pluginName )

You aren’t seeing any changes because you aren’t changing the output mesh. You’re retrieving the mesh from the input value, and then setting the vertex positions on that input mesh. You want to change the vertex data on the output mesh.

inputHandle_array = block.inputArrayValue( input )
inputValue_element = inputHandle_array.inputValue()

Should be:

inputHandle_array = block.outputArrayValue( input )
inputValue_element = inputHandle_array.outputValue()

There is also a performance reason to use outputArrayValue and outputValue. From the link I provided earlier:

Notice when I get the data handles, I use outputArrayValue and outputValue. This prevents Maya from triggering a dirty propagation. If I were to use inputArrayValue and inputValue, Maya would recalculate the input geometry, causing an unnecessary graph evaluation since this was already done in the compute method.

[QUOTE=capper;22112]You aren’t seeing any changes because you aren’t changing the output mesh. You’re retrieving the mesh from the input value, and then setting the vertex positions on that input mesh. You want to change the vertex data on the output mesh.

inputHandle_array = block.inputArrayValue( input )
inputValue_element = inputHandle_array.inputValue()

Should be:

inputHandle_array = block.outputArrayValue( input )
inputValue_element = inputHandle_array.outputValue()

There is also a performance reason to use outputArrayValue and outputValue. From the link I provided earlier:[/QUOTE]

Got it, thanks :slight_smile: