hi together,

I have been trying to write a custom deformer using the maya python api which 
basically is a shrink wrap deformer using a custom vector to project each 
vertex to the another mesh.

The deformer works fine as is. I really would like to add one option though 
which I cannot figure out how to achieve as I am new to the api and the logics 
of it in general. I would like to add an array attribute to the deformer node 
which for each input geometry vertex saves the index of another vertex which 
should be included into the calculation of the deform function.

My question is: How do I create the array attribute and also how do I populate 
and access it in the deform function?

I guess I have already somewhat figured out how to create the Array using 
setArray() function and also adding child attributes to it but I still have 
troubles understanding where and how to populate and access the array 
attribute. There is a lot of information out there concerning MPlugs and 
arrayDataBuilder but I simply have not been able to understand it. Can somebody 
provide me with an example or explain me how to properly do using the python 
api? Any help is greatly appreciated!

This is the code, that I was able put together with the examples available 
online:

import maya.OpenMaya as OpenMaya
import maya.OpenMayaAnim as OpenMayaAnim
import maya.OpenMayaMPx as OpenMayaMPx
import maya.cmds as cmds


class surfaceSlideDeformer(OpenMayaMPx.MPxDeformerNode):
    kPluginNodeId = OpenMaya.MTypeId(0x00000012)
    kPluginNodeTypeName = "surfaceSlideDeformer"

    bindData = OpenMaya.MObject()
    sampleWeights = OpenMaya.MObject()



    def __init__(self):
        OpenMayaMPx.MPxDeformerNode.__init__(self)
        self.accelParameters = OpenMaya.MMeshIsectAccelParams()  # speeds up 
intersect calculation


    def deform(self, block, geoItr, matrix, index):

        # get ENVELOPE
        envelope = OpenMayaMPx.cvar.MPxGeometryFilter_envelope
        envelopeHandle = block.inputValue(envelope)
        envelopeVal = envelopeHandle.asFloat()

        if envelopeVal!=0:
            # get target MESH (as worldMesh)
            targetHandle = block.inputValue(self.targetMesh)
            inTargetMesh = targetHandle.asMesh()

            if not inTargetMesh.isNull():

                #get target fn  mesh
                inTargetFn = OpenMaya.MFnMesh(inTargetMesh)

                inMesh = self.get_input_geom(block, index)

                inMeshFn = OpenMaya.MFnMesh(inMesh)
                inPointArray = OpenMaya.MPointArray()
                inMeshFn.getPoints(inPointArray, OpenMaya.MSpace.kWorld)

                # create array to store final points and set to correct length
                length = inPointArray.length()
                finalPositionArray = OpenMaya.MPointArray()
                finalPositionArray.setLength(length)
                finalPositionArray = inPointArray

                # loop through all points
                while not geoItr.isDone():
                    w = self.weightValue(block, index, geoItr.index())


                    point = inPointArray[geoItr.index()]

                    raySource = OpenMaya.MFloatPoint(point.x, point.y, point.z)
                    rayDirection = OpenMaya.MVector()
                    inMeshFn.getVertexNormal(geoItr.index(), False, 
rayDirection)
                    rayDirection = OpenMaya.MFloatVector(rayDirection.x, 0.0, 
rayDirection.z)

                    hitPoint = OpenMaya.MFloatPoint()

                    # rest of the args
                    hitFacePtr = OpenMaya.MScriptUtil().asIntPtr()
                    idsSorted = False
                    testBothDirections = True
                    faceIds = None
                    triIds = None
                    accelParams = self.accelParameters
                    hitRayParam = None
                    hitTriangle = None
                    hitBary1 = None
                    hitBary2 = None
                    maxParamPtr = 99999999

                    hit = inTargetFn.closestIntersection(raySource,
                                                         rayDirection,
                                                         faceIds,
                                                         triIds,
                                                         idsSorted,
                                                         OpenMaya.MSpace.kWorld,
                                                         maxParamPtr,
                                                         testBothDirections,
                                                         accelParams,
                                                         hitPoint,
                                                         hitRayParam,
                                                         hitFacePtr,
                                                         hitTriangle,
                                                         hitBary1,
                                                         hitBary2)

                    if hit:

                        finalPositionArray.set(OpenMaya.MPoint(point.x + 
envelopeVal*w*(hitPoint.x-point.x), point.y + 
envelopeVal*w*(hitPoint.y-point.y), point.z + 
envelopeVal*w*(hitPoint.z-point.z)), geoItr.index())
                    else:
                        finalPositionArray.set(point, geoItr.index())

                    geoItr.next()
                inMeshFn.setPoints(finalPositionArray, OpenMaya.MSpace.kWorld)

    def get_input_geom(self, block, index):
            input_attr = OpenMayaMPx.cvar.MPxGeometryFilter_input
            input_geom_attr = OpenMayaMPx.cvar.MPxGeometryFilter_inputGeom
            input_handle = block.outputArrayValue(input_attr)
            input_handle.jumpToElement(index)
            input_geom_obj = 
input_handle.outputValue().child(input_geom_attr).asMesh()
            return input_geom_obj

def creator():
    return OpenMayaMPx.asMPxPtr(surfaceSlideDeformer())

def initialize():
    gAttr = OpenMaya.MFnGenericAttribute()
    mAttr = OpenMaya.MFnMatrixAttribute()
    nAttr = OpenMaya.MFnNumericAttribute()
    tAttr = OpenMaya.MFnTypedAttribute()
    cAttr = OpenMaya.MFnCompoundAttribute()

    outMesh = OpenMayaMPx.cvar.MPxGeometryFilter_outputGeom

    surfaceSlideDeformer.targetMesh = gAttr.create("targetMesh", "target")
    gAttr.addDataAccept(OpenMaya.MFnData.kMesh)
    surfaceSlideDeformer.addAttribute(surfaceSlideDeformer.targetMesh)

    surfaceSlideDeformer.sampleWeights = 
nAttr.create('sampleWeights','sampleWeights',OpenMaya.MFnNumericData.k2Int)
    nAttr.setArray(True)

    surfaceSlideDeformer.bindData = cAttr.create('bindData','bindData')
    cAttr.setArray(True)
    cAttr.setStorable(True)
    cAttr.addChild(surfaceSlideDeformer.sampleWeights)

    surfaceSlideDeformer.addAttribute(surfaceSlideDeformer.bindData)

    surfaceSlideDeformer.attributeAffects(surfaceSlideDeformer.bindData, 
outMesh)
    surfaceSlideDeformer.attributeAffects(surfaceSlideDeformer.targetMesh, 
outMesh)

    cmds.makePaintable('surfaceSlideDeformer', 'weights', 
attrType='multiFloat', shapeMode='deformer')


def initializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj, 'Degner', '1.0', 'Any')


    try:
        plugin.registerNode('surfaceSlideDeformer', 
surfaceSlideDeformer.kPluginNodeId, creator, initialize,
                            OpenMayaMPx.MPxNode.kDeformerNode)
    except:
        raise RuntimeError, 'Failed to register node'


def uninitializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj)
    try:
        plugin.deregisterNode(surfaceSlideDeformer.kPluginNodeId)
    except:
        raise RuntimeError, 'Failed to deregister node'

-- 
You received this message because you are subscribed to the Google Groups 
"Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to python_inside_maya+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/python_inside_maya/1f27b821-74eb-4f55-bfb3-382397a48184%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to