Search code examples
pythonmayamaya-api

MFnMesh allIntersections returning wrong results


I'm trying to use Maya's api to test if a point is inside a certain mesh by shooting a ray and seeing how many faces it hits. I'm doing this with MFnMesh.allIntersections. The issue I'm coming up with is that sometimes the method returns results that I don't expect and that don't make sense! For example, I'm testing a point at the bottom of a sphere with its normal like so:

Example

Like in the image, it should hit 2 points, yet for some reason it says it hits 3 instead! Why is this happening? I'm including code that should replicate this example:

import maya.cmds as cmds
import maya.OpenMaya as OpenMaya


cmds.file(new=True, force=True)

cmds.polyCube(subdivisionsWidth=4, subdivisionsHeight=4, subdivisionsDepth=4)
cmds.setAttr("pCube1.translate", 0, 0.236, 0)

cmds.polySphere(subdivisionsAxis=25, subdivisionsHeight=25)
cmds.setAttr("pSphere1.translate", 0, 2, 0)

dag_path = OpenMaya.MDagPath()
sel = OpenMaya.MSelectionList()
sel.add("pCube1")
sel.getDagPath(0, dag_path)

mfn_mesh = OpenMaya.MFnMesh(dag_path)

hit_points = OpenMaya.MFloatPointArray()
hit_ray_params = OpenMaya.MFloatArray()
hit_faces = OpenMaya.MIntArray()

has_int = mfn_mesh.allIntersections(
    OpenMaya.MFloatPoint(0, 1, 0), # Should match pSphere1.vtx[600]'s world position
    OpenMaya.MFloatVector(1.1905393115796414e-08, -1.0, 1.8535209278525144e-07), # Should match pSphere1.vtx[600]'s normal
    None,
    None,
    False,
    OpenMaya.MSpace.kWorld,
    999999,
    False,
    mfn_mesh.autoUniformGridParams(),
    False,
    hit_points,
    hit_ray_params,
    hit_faces,
    None,
    None,
    None,
    0.0001
)

print hit_points.length() # Should return 2 but returns 3!!!

Solution

  • So turns out when MFnMesh.allIntersections intersects exactly against an edge or vertex, instead of returning one hit point it'll return multiple, so it's possible to get many hits at the same position. I played around with the method's tolerance value and it had no effect. So instead when a hit occurs I can use MFloatVector.isEquivalent and trim out any positions that are almost identical. Now I'm getting the expected output.