detect inside of object


Hi all,
Can anyone help me find a way to check if a point is inside an object or outside? I need better accuracy than coincident to the bounding box, and I strongly prefer mel. I’m basically trying to voxel-ize an object, if that makes sense, imagine a very pixelated image but in 3d.
Thanks for your help


This example should work, though it was written to check one point at a time so it’ll be very slow. But you can use the concept.

   proc int isPointInsideMesh(float $ptPos[], string $meshObj) {
	  // Create a closestPointOnMesh node
	  // We get all of our information about the relationship
	  // between the mesh and the point in space from this node
	  string $cpomNode = `createNode closestPointOnMesh`;
	  // Connect the mesh to the closestPointOnMesh node
	  connectAttr ($meshObj + ".worldMesh") ($cpomNode + ".inMesh");
	  // Set the closestPointOnMesh node input value to the point's position
	  setAttr ($cpomNode + ".inPositionX") $ptPos[0];
	  setAttr ($cpomNode + ".inPositionY") $ptPos[1];
	  setAttr ($cpomNode + ".inPositionZ") $ptPos[2];
	  // Put the point's position values into a vector so we can do math on it
	  vector $queryPoint = <<$ptPos[0], $ptPos[1], $ptPos[2]>>;
	  // Get the closest point on the mesh to the point we are checking
	  float $cPosX = `getAttr ($cpomNode + ".positionX")`;
	  float $cPosY = `getAttr ($cpomNode + ".positionY")`;
	  float $cPosZ = `getAttr ($cpomNode + ".positionZ")`;
	  // Subtrect the point's position and the closest point on the mesh
	  // Normalize the resulting vector using the unit function
	  vector $pos = unit($queryPoint - <<$cPosX, $cPosY, $cPosZ>>);
	  // Get the surface normal at the closest point on the mesh
	  float $nX = `getAttr ($cpomNode + ".normalX")`;
	  float $nY = `getAttr ($cpomNode + ".normalY")`;
	  float $nZ = `getAttr ($cpomNode + ".normalZ")`;
	  // Make the normal into a normalized vector
	  vector $normal = unit(<<$nX, $nY, $nZ>>);
	  // Delete the closestPointOnMesh node because we're done with it
	  delete $cpomNode;
	  // If the dot product of the normal and the normalized difference in positions
	  // is greater than zero, then the point is inside the mesh
	  // This assumes that the mesh normals are pointing outward
	  if (dot($normal, $pos) <= 0) {
		 // If the dot product is less than zero, then we're inside
		 return true;
	  } else {
		 // If the dot product is greater than zero, then we're outside
		 return false;
   string $newSphere[] = `polySphere -r 10.0`;
   float $x, $y, $z;
   for ($x=-10; $x<10; $x++) {
	  for ($y=-10; $y<10; $y++) {
		 for ($z=-10; $z<10; $z++) {
			if (`isPointInsideMesh {$x, $y, $z} $newSphere[0]` == 1) {
			   spaceLocator -p $x $y $z;

Based on the dot product of the surface normal compared to the difference between the position and the closest point on surface, you can tell if you are inside the mesh.

You could speed this up by creating one closestPointOnMesh node and just change the inPosition depending on what you are checking.



Thanks Stev,

I’m hoping to implement something like this in a shatter script. Have a look at the shatter help thread in dynamics.



Here’s one using ray casting. I’m basing it on the fact that if a point’s inside a mesh, a raycast from that point will hit an odd number of faces to get outside. If it hits an even number, we’re already on the outside.

It’s not dependant on normals, only volume based manifold meshes including multiple shells and non-convex hulls.

global proc int isPointInsideOfMesh(vector $point, string $mesh)
  	if (!`pluginInfo -q -loaded "rayIntersect"`)
  		loadPlugin "rayIntersect";
  	string $triNode[] = `polyTriangulate -ch 1 $mesh`; //we can't assume there's no n-sided faces which 'fold'
  	float $tolerance = 0.0001;
  	int $count = 0;
  	if (`rayIntersect -inPosition ($point.x) ($point.y) ($point.z) -direction 0 1 0 -q -i1 $mesh`) //we've hit something
  		float $n[]= (`rayIntersect -inPosition ($point.x) ($point.y) ($point.z) -direction 0 1 0 -q -i2 $mesh`);
  		if ($n[0]) //we've hit n something's
  			int $lastFaceID = `rayIntersect -inPosition ($point.x) ($point.y) ($point.z) -direction 0 1 0 -q -f2 $mesh`;
  			int $faceID = `rayIntersect -inPosition ($point.x) ($point.y) ($point.z) -direction 0 1 0 -q -f1 $mesh`;
  			//get the location of the last 'hit' $newPoint
  			vector $newPoint = 	`rayIntersect -inPosition ($point.x) ($point.y) ($point.z) -direction 0 1 0 -q -p1 $mesh`;
  			while ( $lastFaceID != $faceID) //step through the face until we hit the last.
  				$faceID = `rayIntersect -inPosition ($newPoint.x) ($newPoint.y + $tolerance) ($newPoint.z) -direction 0 1 0 -q -f1 $mesh`;
  				$newPoint =  `rayIntersect -inPosition ($newPoint.x) ($newPoint.y + $tolerance) ($newPoint.z) -direction 0 1 0 -q -p1 $mesh`;
  	delete $triNode[0]; //cleanup
  	return (`fmod $count 2`);
  int $insideOutside = isPointInsideOfMesh(<<0,0,0>> ,"pCube1");
  if ($insideOutside)
  	print "
 Is Inside";
  	print "
 Is Outside";

The triangulation is there incase there’s some iffy n sided faces that are non planar, and we don’t really want to treat them as one face.

The only thing nasty is the tolerance, used to just nudge the previously found intersection along the direction vector and is a limitation of the plugin I’m using (I’ve used +y for this, but it could be any vector really).

The rayIntersect plugin is originaly from Highend3D.


Me too!

I posted this earlier!


Hi all, yep compiling the rayIntersect plug from Highend3D is the way to go with this. But, I did wonder if anyone knows how to use that API command using a bit of py†hon? I’d seen an example using pymel… but again that’s something that’s not in a standard installation. Is it possible in the clunky maya python implementation?



Hmmmm interesting! This will come in handy with the shatter script! :smiley: Nice job Paul!


Heres a little wrapper function for the allIntersections api call in python.
It just returns whether your point is inside the mesh or not, the wrapper could be made to return any of the possible informtion provided by the api function.

#A simple wrapper for the maya api function allIntersections to test if  point lies inside of a mesh or not
  #returns true or false if the point is inside the mesh or not
  #point is the position of interest in world space
  #direction is the ray direction to test in
  #mesh is the geometry to test against
  import maya.OpenMaya as OM
  from math import fmod
  def rayIntersect(mesh, point, direction=(0.0, 1.0, 0.0)):
  	sList = OM.MSelectionList()
  	#Assign current selection to the selection list object
  	item = OM.MDagPath()
  	sList.getDagPath(0, item)
  	fnMesh = OM.MFnMesh(item)
  	raySource = OM.MFloatPoint(point[0], point[1], point[2], 1.0)
  	rayDir = OM.MFloatVector(direction[0], direction[1], direction[2])
  	faceIds = None
  	triIds = None
  	idsSorted = False
  	testBothDirections = False
  	worldSpace = OM.MSpace.kWorld
  	maxParam = 999999
  	accelParams = None
  	sortHits = True
  	hitPoints = OM.MFloatPointArray()
  	#hitRayParams = OM.MScriptUtil().asFloatPtr()
  	hitRayParams = OM.MFloatArray()
  	hitFaces = OM.MIntArray()
  	hitTris = None
  	hitBarys1 = None
  	hitBarys2 = None
  	tolerance = 0.0001
  	hit = fnMesh.allIntersections(raySource, rayDir, faceIds, triIds, idsSorted, worldSpace, maxParam, testBothDirections, accelParams, sortHits, hitPoints, hitRayParams, hitFaces, hitTris, hitBarys1, hitBarys2, tolerance)
  	result = int(fmod(len(hitFaces), 2))
  	#clear selection as may cause problem if the function is called multiple times in succession
  	return result

Maybe someone finds it useful.



Octupe, nice work! I tried your code and passed the name of a mesh and a vector for the position of a locator and it worked great. Although I think i broke something now because it keeps giving me an error whenever i try to pass a vector to it again . . . :-\ Not sure what I changed / did wrong.


Nevermind, haha, just figured it out. I was passing the name of an object like:

mesh = “pSphere1”

when it should be:

mesh = ‘pSphere1’

Awesome script!! :smiley:


very nice wrapper indeed. Thanks for sharing!:applause:


:love: Joy! thank U!


This is great, thanks very much:)


This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.