Hello Angelo,
Thank you for your reply.
I have some weird effect when I use my custom jiggle deformer on two 
different meshes by only one deform node.
First, my custom deform node has some paintable attributes and all of them 
are the child of one MFnCompoundAttribute().
When I move one mesh, the other mesh or some components of the other mesh 
will perform jiggle effect. That is not what I want.
I think the problem is due to reading(storing) the float array attribute by 
different meshes.
So, my question is how to get paintable attributes (mainly MFloatArray()) 
of a MFnCompoundAttribute()?

Thank you very much.
Yixiong Xu

在 2017年11月25日星期六 UTC+8上午5:07:03,Angelo写道:
>
> def inititialize(self)
>     self.aBindData = cAttr.create('bindData', 'bindData')
>     cAttr.setArray(True)
> def deform(self, data, itGeo, matrix, index):
>     bindArrayData = data.inputArrayValue(self.aBindData)
>     size = bindArrayData.elementCount()
>     
>     for i in range(size):
>         bindData = bindArrayData.inputValue()
>         someVariable = bindData.child(someAttribute).someDataType
>         
>         try:
>             bindArrayData.next()
>         except:
>             pass
>
> This is how i get data from a compound array attribute. I recommend using 
> om.MFnTypedAttribute.MDoubleArray to store weight data since you can obtain 
> all the data in one call which is faster. You only need to use 
> MArrayDataBuilder when you need to add data on an existing array attribute 
> (like outputting an array of matrices). If all you're doing is accessing an 
> array, you can just iterate through them using either 
> inputArrayData.next(), inputArrayData.jumpToLogicalElement() or 
> inputArrayData.jumpToPhysicalElement() The docs for MArrayDataHandle and 
> MArrayDataBuilder should describe this pretty well.
>             
>
>
> On Sunday, November 19, 2017 at 4:12:19 PM UTC-6, degne...@googlemail.com 
> wrote:
>>
>> 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/a14eb246-950a-449d-81c2-b431848f8f83%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to