deformer node

所需模块:sys,OpenMaya,OpenMayaMPx,math,cmds

代码结构:定义节点名称及ID,变形算法类,定义变形器指针,为deformer Node定义添加属性。

nodeName = "RippleDeformer"
nodeID = om.MTypeId(0x102fff)

定义节点名称及ID

class Ripple(ommpx.MPxDeformerNode):
    mObj_Amplitude = om.MObject()
    mObj_Displace = om.MObject()
    mObj_Matrix = om.MObject()
    def __init__(self):
        ommpx.MPxDeformerNode.__init__(self)
    def deform(self, dataBlock,geoIterator,matrix,geometryIndex):
        input = ommpx.cvar.MPxGeometryFilter_input
        # 1.Attach a handle to input Array Attribute
        dataHandleInputArray = dataBlock.outputArrayValue(input)
        # 2.Jump to particular element
        dataHandleInputArray.jumpToElement(geometryIndex)
        # 3.Attach a handle to specific data block
        dataHandleInputElement = dataHandleInputArray.outputValue()
        # 4.Reach to the child - inputGeom
        inputGeom = ommpx.cvar.MPxGeometryFilter_inputGeom
        dataHandleInputGeom = dataHandleInputElement.child(inputGeom)
        inMesh = dataHandleInputGeom.asMesh()

获取输入数组中的物体,因为我们要对物体进行操作

我们访问内置属性用:Attr = ommpx.cvar.MPxGeometryFilter_(attr)

获取当前数组的句柄:handleinputArray = dataBlock.outputArrayValue(Attr)

跳转到数组中的特定元素:handleinputArray.jumpToElement(geometryIndex)

获取当前数组元素的数据块的句柄:handleinputArray.outputValue()

特定数组元素构成:

 访问特定元素的内置属性:ommpx.cvar.MPxGeometryFilter_inputGeom

inputGeom是特定元素的子属性,获取元素的子属性:dataHandleInputGeom = dataHandleInputElement.child(inputGeom)

将句柄的数据作为mesh返回:inMesh = dataHandleInputGeom.asMesh()

        # Envelope
        envelope = ommpx.cvar.MPxGeometryFilter_envelope
        dataHandleEnvelope = dataBlock.inputValue(envelope)
        envelopeValue = dataHandleEnvelope.asFloat()

        # Amplitude
        dataHandleAmplitude = dataBlock.inputValue(Ripple.mObj_Amplitude)
        amplitudeValue = dataHandleAmplitude.asFloat()

        # Displace
        dataHandleDisplace = dataBlock.inputValue(Ripple.mObj_Displace)
        displaceValue = dataHandleDisplace.asFloat()

        # matrix
        dataHandleMatrix = dataBlock.inputValue(Ripple.mObj_Matrix)
        matrixValue = dataHandleMatrix.asMatrix()

获取内置属性的值:

envelope = ommpx.cvar.MPxGeometryFilter_envelope
dataHandleEnvelope = dataBlock.inputValue(envelope)
envelopeValue = dataHandleEnvelope.asFloat()

获取自定义属性的值:

dataHandleAmplitude = dataBlock.inputValue(Ripple.mObj_Amplitude)
amplitudeValue = dataHandleAmplitude.asFloat()
        # read the translation from matrix
        mTransMatrix = om.MTransformationMatrix(matrixValue)
        translationValue = mTransMatrix.getTranslation(om.MSpace.kObject)

        mFloatVectorArray_normal = om.MFloatVectorArray()
        mFnMesh = om.MFnMesh(inMesh)
        mFnMesh.getVertexNormals(False,mFloatVectorArray_normal,om.MSpace.kObject)

        mPointArray_meshVert = om.MPointArray()
        while( not geoIterator.isDone()):
            pointPosition = geoIterator.position()# 返回当前点的位置
            weight = self.weightValue(dataBlock,geometryIndex,geoIterator.index())
            pointPosition.x = pointPosition.x + math.sin(geoIterator.index() + displaceValue + translationValue[0]) * amplitudeValue * mFloatVectorArray_normal[geoIterator.index()].x * weight * envelopeValue
            pointPosition.y = pointPosition.y + math.sin(geoIterator.index() + displaceValue + translationValue[0]) * amplitudeValue * mFloatVectorArray_normal[geoIterator.index()].y * weight * envelopeValue
            pointPosition.z = pointPosition.z + math.sin(geoIterator.index() + displaceValue + translationValue[0]) * amplitudeValue * mFloatVectorArray_normal[geoIterator.index()].z * weight * envelopeValue
            mPointArray_meshVert.append(pointPosition)
            #geoIterator.setPosition(pointPosition)
            geoIterator.next()
        geoIterator.setAllPositions(mPointArray_meshVert)
        cmds.makePaintable("RippleDeformer", "weights", attrType="multiFloat", shapeMode="deformer")

获取matrix属性的变换矩阵:mTransMatrix = om.MTransformationMatrix(matrixValue)

将变换矩阵以厘米为单位返回转换的平移分量:translationValue = mTransMatrix.getTranslation(om.MSpace.kObject)

创建一个MFloatVector数组:mFloatVectorArray_normal = om.MFloatVectorArray()

返回物体的顶点常量,并将常量存储在数组内:

mFnMesh = om.MFnMesh(inMesh)
mFnMesh.getVertexNormals(False,mFloatVectorArray_normal,om.MSpace.kObject)

判断是否已遍历所有项,若没有遍历完则让当前点执行变形算法并将新位置坐标添加到数组中;若遍历完成,一次性设置所有顶点的位置。

将新属性注册为“属性绘制”工具的可绘制属性:

cmds.makePaintable("RippleDeformer", "weights", attrType="multiFloat", shapeMode="deformer")

变形器通常需要一个辅助节点,如定位器,以控制变形的变化。这些辅助节点称为附件。附件节点是可选的,对变形器来说不是必需的。MPxGeometryFilter类的输入属性足以执行变形。只有当您想要使用附件来变形几何图形时,才应该实现accessoryNodeSetup()和accessoryAttribute()方法。

    def accessoryNodeSetup(self, dagModifier):
        # 1.create Accessory Object
        mObjLocator = dagModifier.createNode("locator")

        # 2.Establish Connection
        mFnDependLocator = om.MFnDependencyNode(mObjLocator)
        mPlugWorld = mFnDependLocator.findPlug("worldMatrix")
        mobj_WorldAttr = mPlugWorld.attribute()

        mstatusConnect = dagModifier.connect(mObjLocator,mobj_WorldAttr,self.thisMObject(),Ripple.mObj_Matrix)
        return mstatusConnect
    def accessoryAttribute(self):
        return Ripple.mObj_Matrix

创建定位器,将定位器设置为附属节点,为该节点找到一个plug,返回该plug的属性,将locator属性与自定义Matrix属性连接。

def deformerCreator():
    return ommpx.asMPxPtr(Ripple())
def nodeInitializer():
    '''
    create Attributes
    Attach Attributes
    Design Circuitry
    '''
    # 1.create Attributes
    mFnAttr = om.MFnNumericAttribute()
    Ripple.mObj_Amplitude = mFnAttr.create("AmplitudeValue","AmplitudeVal",om.MFnNumericData.kFloat,0.0)
    mFnAttr.setKeyable(True)
    mFnAttr.setMin(0.0)
    mFnAttr.setMax(1.0)

    Ripple.mObj_Displace = mFnAttr.create("DisplaceValue","DispVal",om.MFnNumericData.kFloat,0.0)
    mFnAttr.setKeyable(True)
    mFnAttr.setMin(0.0)
    mFnAttr.setMax(10.0)

    # 1.Create Matrix Attribute
    mFnMatrixAttr = om.MFnMatrixAttribute()
    Ripple.mObj_Matrix = mFnMatrixAttr.create("MatrixAttribute","matattr")
    mFnMatrixAttr.setStorable(False)
    mFnMatrixAttr.setConnectable(True)

    # 2.Attach Attributes
    Ripple.addAttribute(Ripple.mObj_Amplitude)
    Ripple.addAttribute(Ripple.mObj_Displace)
    Ripple.addAttribute(Ripple.mObj_Matrix)
    '''
    SWIG - Simplified Wrapper Interface Generator
    '''
    # 3.Design Circuitry
    outputGeom = ommpx.cvar.MPxGeometryFilter_outputGeom
    Ripple.attributeAffects(Ripple.mObj_Amplitude,outputGeom)
    Ripple.attributeAffects(Ripple.mObj_Displace,outputGeom)
    Ripple.attributeAffects(Ripple.mObj_Matrix,outputGeom)

初始化节点:创建节点属性,将属性添加到节点上,为自定义节点属性设计Circuitry。

参考文档:Help

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sort_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值