Skip to content

Instantly share code, notes, and snippets.

@danbradham
Created October 23, 2017 20:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save danbradham/3a7929280ccd46990ca42eb9d867f596 to your computer and use it in GitHub Desktop.
Save danbradham/3a7929280ccd46990ca42eb9d867f596 to your computer and use it in GitHub Desktop.
Simple collision detection node network for Maya
from maya import cmds
def simple_collision_check(obj_xform, collider_shape):
'''
Create a node network that checks whether an objects xform is colliding with a mesh. Returns a condition node where outputX, Y, and Z are 1
for colliding and 0 when not colliding.
:param obj_xform: Path to object transform
:param collider_shape: Path to mesh transform
'''
# Create nodes
pnt_mat_mult = cmds.createNode('pointMatrixMult', name='obj_to_ws#')
closest_pnt = cmds.createNode('closestPointOnMesh')
minus = cmds.createNode('plusMinusAverage', name='ray_dir#')
dot_product = cmds.createNode('vectorProduct', name='R_dot_N#')
condition = cmds.createNode('condition', name='is_colliding#')
# Object xform to world space
cmds.connectAttr(obj_xform + '.parentMatrix[0]', pnt_mat_mult + '.inMatrix')
cmds.connectAttr(obj_xform + '.translate', pnt_mat_mult + '.inPoint')
# Nearest point on collider mesh
cmds.connectAttr(pnt_mat_mult + '.output', closest_pnt + '.inPosition')
cmds.connectAttr(collider_shape + '.worldMatrix', closest_pnt + '.inputMatrix')
cmds.connectAttr(collider_shape + '.worldMesh[0]', closest_pnt + '.inMesh')
# Direction to collider mesh
cmds.setAttr(minus + '.operation', 2) # Operation 2 is Subtract
cmds.connectAttr(closest_pnt + '.position', minus + '.input3D[0]')
cmds.connectAttr(pnt_mat_mult + '.output', minus + '.input3D[1]')
# Direction dot collider normal (Angle between mesh normal and xform)
cmds.setAttr(dot_product + '.operation', 1) # Operation 1 is Dot Product
cmds.setAttr(dot_product + '.normalizeOutput', 1) # Ensure value -1 to 1
cmds.connectAttr(closest_pnt + '.normal', dot_product + '.input1')
cmds.connectAttr(minus + '.output3D', dot_product + '.input2')
# Check angle for collision
# Dot product > 0 is a collision
cmds.setAttr(condition + '.operation', 2) # Operation 2 is Greater Than
cmds.setAttr(condition + '.colorIfTrue', 1, 1, 1)
cmds.setAttr(condition + '.colorIfFalse', 0, 0, 0)
cmds.connectAttr(dot_product + '.outputX', condition + '.firstTerm')
return condition
def hide_on_collide(obj_xform, collider_xform):
'''
Hide a transform when colliding with a mesh.
:param obj_xform: Path to a transform node
:param collider_xform: Path to a meshes transform node
'''
collider_xform = cmds.listRelatives(
collider_xform,
shapes=True,
type='mesh',
noIntermediate=True
)[0]
# Create nodes
condition = simple_collision_check(obj_xform, collider_xform)
vis_condition = cmds.createNode('reverse', name='vis_condition#')
cmds.connectAttr(condition + '.outColor', vis_condition + '.input')
cmds.connectAttr(
vis_condition + '.outputX',
obj_xform + '.visibility',
force=True
)
def hide_on_collide_selected():
'''
Hides transforms when colliding with a mesh. Select some transforms
then a collision mesh.
'''
xforms = cmds.ls(sl=True, long=True, transforms=True)
if len(xforms) < 2:
cmds.warning('Select multiple transforms then a collider mesh')
return
obj_xforms = xforms[:-1]
collider_xform = xforms[-1]
for obj_xform in obj_xforms:
hide_on_collide(obj_xform, collider_xform)
if __name__ == '__main__':
hide_on_collide_selected()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment