Writing a deformer with Python

Writing a deformer with Python

Anonymous
Not applicable
2,366 Views
8 Replies
Message 1 of 9

Writing a deformer with Python

Anonymous
Not applicable
I'm trying to write a simple blendshape deformer with Python:

class simpleBlendShape( OpenMayaMPx.MPxDeformerNode ):

geomObject = OpenMaya.MObject()

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

def deform( self, data, itGeo, localToWorldMatrix, mIndex ):
envelope = data.inputValue( simpleBlendShape.envelope ).asFloat()
geoHandle = data.inputValue( simpleBlendShape.geomObject )
geoIter = OpenMaya.MItGeometry( geoHandle )

while ( ( not itGeo.isDone() ) and ( not geoIter.isDone() ) ):
pt = itGeo.position()
geomPt = geoIter.position()
weight = self.weightValue( data, mIndex, itGeo.index() )
w = weight * envelope

pt = ((geomPt - pt) * ww) + pt
iter.setPosition( pt )
return OpenMaya.MStatus.kSuccess


And this is my initialize function:
def initialize():
gAttr = OpenMaya.MFnGenericAttribute()
simpleBlendShape.geomObject = gAttr.create( "geometryObject", "gobj" )
gAttr.addDataAccept( OpenMaya.MFnData.kMesh )
gAttr.addDataAccept( OpenMaya.MFnData.kNurbsSurface )
gAttr.addDataAccept( OpenMaya.MFnData.kNurbsCurve )

simpleBlendShape.addAttribute( simpleBlendShape.geomObject )
simpleBlendShape.attributeAffects( simpleBlendShape.geomObject, simpleBlendShape.outputGeom )

OpenMaya.MGlobal.executeCommand( "makePaintable -attrType multiFloat -sm deformer simpleBlendShape weights" )

return OpenMaya.MStatus.kSuccess


And I'm getting the following error:
#     simpleBlendShape.attributeAffects( simpleBlendShape.geomObject, simpleBlendShape.outputGeom )
# AttributeError: type object 'simpleBlendShape' has no attribute 'outputGeom' //
// Warning: Failed to call script creator function //


I did a dir( OpenMayaMPx.MPxDeformerNode ) and I'm not seeing any of the built-in attributes listed for MPxDeformerNode. Are these missing from the Python libraries?
0 Likes
2,367 Views
8 Replies
Replies (8)
Message 2 of 9

Anonymous
Not applicable
Found my answer in the docs:

Accessing static MObjects of an MPx class

The proxy classes provide some standard information to a developer about the node that is being used. This includes attribute objects that are used to define the node. To access a static class MObject in the Maya Python API, similar code can be used:

envelope = OpenMayaMPx.cvar.MPxDeformerNode_envelope 


After making this call, the envelope will be an MObject for MPxDeformerNode::envelope.
0 Likes
Message 3 of 9

Anonymous
Not applicable
hi chad,

I'm a absolute noob at API and starter in python.. have some experience with mel and tools making and rigging..

can you post a post with explanation of how u go about making a deformer in python ? I know that basics of what is a MPx node or why to derive from such a node etc.. and what is a class and how do you write a class for your own node.. is supposed to be known.. (which i'm studying myself)

but in general if you can write a commented tutorial about overall approach of - "noobs guide to writing deformers in python" , basic workflow of a plugin or a node ...... what are the basic thumbrules and what shud go where,,,,, kinda explanation, would help all of the community alot !!

any tips and guidance is much appreciated 🙂
0 Likes
Message 4 of 9

Anonymous
Not applicable
not sure if chadmv would like to do that since it`s lot of work, but you can buy this DVD about making Maya deformers and other DVD about Python API, both DVDs will tell you exactly how to make Python deformer in Maya:

http://www.creationengine.com/html/p.lasso?p=14460

http://store.autodesk.com/servlet/ControllerServlet?Action=DisplayPage&Env=BASE&Locale=en_US&SiteID=...
0 Likes
Message 5 of 9

Anonymous
Not applicable
Unfortunately, the "Writing Creature Deformers" DVD is no longer available from Autodesk. I have been actively searching for it ever since they removed it from the store, as that just happened to be around the day I decided to purchase it. I have the Python in Maya DVD they released. But, the content on that disc is rather weak, lackluster. It doesn't explain hardly anything, especially when it comes to deformers.

The documentation and resources for using the Maya API are relatively slim. When you look for ways to use it with Python, it seems the supply of learning material dwindles to a few brief mentions in the dark corners of random artists' websites. However, most of that material seems geared towards people who already have experience writing plug-ins with C++.

"Writing Creature Deformers" was the closest thing I've seen to a deformer-oriented guide to the API. Sadly, I can no longer purchase that from Autodesk. And, seeing as how the DVD is a special order item at other online stores, their supply of that particular title comes from the manufacturer directly. Hence, it cannot be purchased anywhere.

If anyone has access to this DVD, I would greatly appreciate the opportunity to view a copy of it. Since it looks to be out of print, I'm sure Autodesk wouldn't mind allowing us to share this invaluable material that cannot be found anywhere else. Please make a post here or contact me if you know of how I can secure a viewing of this title.
0 Likes
Message 6 of 9

Anonymous
Not applicable
I agree, Python seems not supported enough. I got the Python DVD as well but didn`t have the opportunity to look at it. Well, at least Autodesk released `something` about Python, dunno about the quality though.
It`s really a shame when Autodesk stops supporting their or Alias DVDs since they have released so many great titles. Especially about Maya API and rigging.
I got the Writing Creature Deformers DVD and now I feel really lucky as it`s kinda exclusive item. I don`t feel like it`s legal to share it on public though. What`s better I think, if everyone who wants this or more materials should contact Autodesk directly. I`m sure there`s more people who have problem with getting learning DVDs.
Once I have sent about 3 emails complaining when Autodesk removed J.Schleifer`s old rigging DVDs and some time after they released his Rigging Bundle.
0 Likes
Message 7 of 9

Anonymous
Not applicable
May I ask which email you were sending your complaints to? I tried contacting Autodesk several days ago about this, but I couldn't seem to find an appropriate person or department to voice my opinions to.
Regarding the sharing of media... Yes, it is wrong to take something for free when its creator has it available for purchase. However, when vendors no longer carry that item, and the manufacturer no longer produces it, they cut themselves off from any profit on the item. It's their choice, of course, but that doesn't mean that it should be forbidden to the people who weren't able to buy it.
0 Likes
Message 8 of 9

Anonymous
Not applicable
I agree, but it`s copyrighted anyway 🙂
about the email, it was about year ago, so just try to find some Contact Support email at Learning Curve or Learning DVDs or how they currently call it. Maybe Sales or Sales Marketing Support, you need to find out.
Honeslty I don`t see any logic of removing this item and many others too. Of course they loose profit, especially on Download DVDs which cost them nothing to sell as they don`t send anything by mail. Also they should support Maya users by making all learning materials available. Hopefully they`ll fix it.
I wanted to buy Writing Deformers half year ago, but it was only for US and maybe Canada and Japan. It wasn`t available to Europe for couple of months. At least not from their website, not sure about local reseller. That`s what you could try as well, if you know any Local Maya Reseller in your area, it might be easier to get your DVD copy.
0 Likes
Message 9 of 9

Anonymous
Not applicable
I've been going through C++ examples of simple plug-ins, trying to convert them over to Python plug-ins and teach myself how they are built with the language. The example below, followed from David Gould's book, is not working.

import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import math, sys

kPluginNodeTypeName = "TwistDeformer"
NodeTypeId = OpenMaya.MTypeId( 0x6696003 )

# Node Definition
class TwistDeformer ( OpenMayaMPx.MPxDeformerNode ) :
# Class Variables
startDist = OpenMaya.MObject()
endDist = OpenMaya.MObject()

# Constructor
def __init__ (self) :
OpenMayaMPx.MPxDeformerNode.__init__(self)
# Deform Function
def deform ( self, dataBlock, geoIt, matrix, multiIndex ) :
# Get the envelope
envelope = OpenMayaMPx.cvar.MPxDeformerNode_envelope
envelopeValue = dataBlock.inputValue( envelope ).asFloat()

# Get the start and end distance values
startDist = dataBlock.inputValue( self.startDist ).asDouble()
endDist = dataBlock.inputValue( self.endDist ).asDouble()

# Iterate over the object and change point positions
while geoIt.isDone() == False :
weight = self.weightValue( dataBlock, multiIndex, geoIt.index() )
if weight == 0.0 :
continue

point = geoIt.position()
dist = math.sqrt( point.x**2 + point.z**2 )
if dist < startDist or dist > endDist :
continue

distFactor = 1 - ((dist - startDist) / (endDist - startDist))

angle = distFactor * math.pi * 2.0 * envelopeValue * weight
if angle == 0.0 :
continue

cosAng = math.cos( angle )
sinAng = math.sin( angle )
x = point.x * cosAng - point.z * sinAng
point.z = point.x * sinAng + point.z * cosAng
point.x = x

geoIt.setPosition( point )
geoIt.next()

# Node Creator
def nodeCreator () :
return OpenMayaMPx.asMPxPtr( TwistDeformer() )

# Node Initializer
def nodeInitializer () :
# '.startDist' Attribute
uAttr = OpenMaya.MFnUnitAttribute()
TwistDeformer.startDist = uAttr.create( "startDist", "sd", OpenMaya.MFnUnitAttribute.kDistance )
uAttr.setDefault( OpenMaya.MDistance( 0.0, OpenMaya.MDistance.uiUnit() ) )
uAttr.setMin( OpenMaya.MDistance( 0.0, OpenMaya.MDistance.uiUnit() ) )
uAttr.setKeyable(True)

# '.endDist' Attribute
TwistDeformer.endDist = uAttr.create( "endDist", "ed", OpenMaya.MFnUnitAttribute.kDistance )
uAttr.setDefault( OpenMaya.MDistance( 3.0, OpenMaya.MDistance.uiUnit() ) )
uAttr.setMin( OpenMaya.MDistance( 0.0, OpenMaya.MDistance.uiUnit() ) )
uAttr.setKeyable(True)

# Add Attributes
try :
TwistDeformer.addAttribute( TwistDeformer.startDist )
TwistDeformer.addAttribute( TwistDeformer.endDist )
outputGeo = OpenMayaMPx.cvar.MPxDeformerNode_outputGeom
TwistDeformer.attributeAffects( TwistDeformer.startDist, outputGeo )
TwistDeformer.attributeAffects( TwistDeformer.endDist, outputGeo )
except :
sys.stderr.write( "Failed to add attributes to %s node\n" % kPluginNodeTypeName )

# Initialize the Script Plug-in
def initializePlugin ( mobject ) :
mplugin = OpenMayaMPx.MFnPlugin( mobject )
try :
mplugin.registerNode( kPluginNodeTypeName, NodeTypeId, nodeCreator, nodeInitializer, OpenMayaMPx.MPxNode.kDeformerNode )
except :
sys.stderr.write( "Failed to register node: %s\n" % kPluginNodeTypeName )
raise

# Uninitialize the Script Plug-in
def uninitializePlugin ( mobject ) :
mplugin = OpenMayaMPx.MFnPlugin( mobject )
try :
mplugin.deregisterNode( NodeTypeId )
except :
sys.stderr.write( "Failed to unregister node: %s\n" % kPluginNodeTypeName )
pass


I keep getting the following error:

// Error: (kInvalidParameter): Object is incompatible with this method
# Traceback (most recent call last):
# File "/Users/....../TwistDeformer.py", line 24, in deform
# startDist = dataBlock.inputValue( self.startDist ).asDouble()
# RuntimeError: (kInvalidParameter): Object is incompatible with this method //


What am I doing wrong here? And, once that is answered, what exactly is the line mentioned above intended to do? I'm struggling to understand why things are constructed in the manner presented in what few examples I have available to me. Unfortunately, due to my inability to find any good reference for Python Plug-in scripting, I am stuck with stumbling through the experience.
0 Likes