0

I'm developing a collision deformer-based Maya PythonApi. At that point, the deformer is working, and I can apply it on the go, but nothing happens when it collides with another geo.

In the second script, you can find the connections from the second geo to the collision deformer. I think the issue is from the calculations or the bounding box, but I can't figure it out.

Thanks

from maya import OpenMaya
from maya import OpenMayaMPx
import sys

nodeName = "CollisionDeformer"
nodeID = OpenMaya.MTypeId(0x102fff)

class Collision(OpenMayaMPx.MPxDeformerNode):
    collider = OpenMaya.MObject()
    boundingBoxMin = OpenMaya.MObject()
    boundingBoxMax = OpenMaya.MObject()
    matrix = OpenMaya.MObject()
    
    def __init__(self):
        OpenMayaMPx.MPxDeformerNode.__init__(self)
        
    def deform(self, dataBlock, geoIterator, matrix, geometryIndex):
        
        # Get the input geometry data
        input = OpenMayaMPx.cvar.MPxGeometryFilter_input
        
        dataHandleInputArray = dataBlock.outputArrayValue(input)
        dataHandleInputArray.jumpToElement(geometryIndex)
        dataHandleInputElement = dataHandleInputArray.outputValue()
        
        inputGeo = OpenMayaMPx.cvar.MPxGeometryFilter_inputGeom
        dataHandleGeo = dataHandleInputElement.child(inputGeo).asMesh()
        
        # Define envelope
        envelope = OpenMayaMPx.cvar.MPxGeometryFilter_envelope
        envelopeValue = dataBlock.inputValue(envelope).asFloat()
        
        # Collider handle
        colliderHandle = dataBlock.inputValue(Collision.collider)
        colliderBoundingBox = OpenMaya.MBoundingBox()
        try:
            # Get the collider mesh 
            colliderMesh = colliderHandle.asMesh()
            mFnColliderMesh = OpenMaya.mFnMesh(colliderMesh)
            closestPoint = OpenMaya.MPoint()
            closestNormal = OpenMaya.MVector()
        except:
            return
            
        # Get the collider boundingBox abd build new boundingBox
        boundingBoxMinHandle = dataBlock.inputValue(Collision.boundingBoxMin)
        boundingBoxMinValue =  boundingBoxMinHandle.asFloat3()
        colliderBoundingBoxMin = OpenMaya.MPoint(boundingBoxMinValue[0], boundingBoxMinValue[1], boundingBoxMinValue[2])
        colliderBoundingBox.expand(colliderBoundingBoxMin)
        
        boundingBoxMaxHandle = dataBlock.inputValue(Collision.boundingBoxMax)
        boundingBoxMaxValue =  boundingBoxMaxHandle.asFloat3()
        colliderBoundingBoxMax = OpenMaya.MPoint(boundingBoxMaxValue[0], boundingBoxMaxValue[1], boundingBoxMaxValue[2])
        colliderBoundingBox.expand(colliderBoundingBoxMax)
        
        # Get the mesh vertices normals
        mFloatVectorArrayNormal = OpenMaya.MFloatVectorArray()
        mFnMesh = OpenMaya.mFnMesh(dataHandleGeo)
        mFnMesh.getVertexNormals(True, mFloatVectorArrayNormal, OpenMaya.MSpace.kTransform)
        
        # Get the original points of the collider
        mPointArrayMeshVertex = OpenMaya.MPointArray()
        mFnMesh.getPoints(mPointArrayMeshVertex, OpenMaya.MSpace.kWorld)
        
        # Get the final points  
        pointsArray = mPointArrayMeshVertex.length()  
        mPointArray = OpenMaya.MPointArray()  
        mPointArray.setLength(pointsArray)
        
        colliderIterator = OpenMaya.MItMeshVertex(dataHandleGeo)
        
        
        if envelopeValue != 0:
            while not geoIterator.isDone():
                pointPosition = geoIterator.position()
                if colliderBoundingBox.contains(pointPosition):
                    mFloatPoint = OpenMaya.MFloatPoint(pointPosition) 
                    mFloatPointArray = OpenMaya.MFloatPointArray()   
                    intersectionsData = mFnColliderMesh.allIntersections(mFloatPoint, OpenMaya.MFloatVector(0, 1, 0), False, False, False,
                                                        OpenMaya.MSpace.kWorld, 100000, False,
                                                        mFnMesh.autoUniformGridParams(), False, mFloatPointArray,
                                                        OpenMaya.MFloatArray(), None, None, None,
                                                        None, 0.0001) 
                                                        
                    if mFloatPointArray:
                        mFnColliderMesh.getClosestPoint(pointPosition, closestPoint, OpenMaya.MSpace.kWorld, None)
                        mFnColliderMesh.getClosestNormal(closestPoint, closestNormal, OpenMaya.MSpace.kWorld, None)
                        vertexDelta = pointPosition - closestPoint
                        
                        
                        mPointArray.set(pointPosition - vertexDelta, geometryIndex.index())  
                        
                    else:
                        mPointArray.set(geoIterator.position(), geoIterator.index())
                else:
                    mPointArray.set(pointPosition, geometryIndex.index())  
                #geoIterator.next()
                mFnMesh.setPoints(mPointArray, OpenMaya.MSpace.kWorld)
                        
def deformerCreator():
    deformerPtr = OpenMayaMPx.asMPxPtr(Collision())
    return deformerPtr
    
def initialize():
   genAttr = OpenMaya.MFnGenericAttribute()
   Collision.collider = genAttr.create('collider', 'col')
   genAttr.addDataAccept(OpenMaya.MFnData.kMesh)
   
   matAttr = OpenMaya.MFnMatrixAttribute()
   Collision.matrix = matAttr.create('matrix', 'mat', OpenMaya.MFnNumericData.kFloat)
   matAttr.setHidden(True)  
   
   numAttr = OpenMaya.MFnNumericAttribute()
   Collision.boundingBoxMin = numAttr.createPoint('boundingBoxMin', 'bbMin')
   numAttr.setDisconnectBehavior(0)
   
   Collision.boundingBoxMax = numAttr.createPoint('boundingBoxMax', 'bbMax')
   numAttr.setDisconnectBehavior(0)
   
   Collision.addAttribute(Collision.collider)
   Collision.addAttribute(Collision.matrix)
   Collision.addAttribute(Collision.boundingBoxMin)
   Collision.addAttribute(Collision.boundingBoxMax)
   
   outputGeo = OpenMayaMPx.cvar.MPxGeometryFilter_outputGeom
   Collision.attributeAffects(Collision.collider, outputGeo)
   Collision.attributeAffects(Collision.matrix, outputGeo)
   Collision.attributeAffects(Collision.boundingBoxMin, outputGeo)
   Collision.attributeAffects(Collision.boundingBoxMax, outputGeo)
   
def initializePlugin(mObject):
    mPlugin = OpenMayaMPx.MFnPlugin(mObject)
    try:
        mPlugin.registerNode(nodeName, nodeID, deformerCreator, initialize, OpenMayaMPx.MPxNode.kDeformerNode)
    except:
        sys.stderr.write("Failed to register" + nodeName)
        
def uninitializePlugin(mObject):
    mPlugin = OpenMayaMPx.MFnPlugin(mObject)
    try:
        mPlugin.deregisterCommand(nodeID)
    except:
        sys.stderr.write("Failed to deregister" + nodeName)
        

'''
Apply the collisionDeformer on the first geo then connect the second geo to the collisionDeformer as following
'''
cmds.connectAttr('pCube2.worldMesh', 'CollisionDeformer1.collider')  
cmds.connectAttr('pCube2.matrix', 'CollisionDeformer1.matrix')  
cmds.connectAttr('pCube2.boundingBox.boundingBoxMin', 'CollisionDeformer1.boundingBoxMin')  
cmds.connectAttr('pCube2.boundingBox.boundingBoxMax', 'CollisionDeformer1.boundingBoxMax') 

0 Answers0