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')