Find objects visible to camera

I’m wondering if it is possible to get the click selection behaviour in OpenMaya.MGlobal.selectFromScreen method. I found this code snippet online

import maya.OpenMaya as om
import maya.OpenMayaUI as omUI
view = omUI.M3dView.active3dView()
om.MGlobal.selectFromScreen( 0, 0, view.portWidth(), view.portHeight(),om.MGlobal.kReplaceList)

It selects everything, even objects behind other objects. So even though the object is in the viewport, you cannot actually see it. Like if I put a sphere at origin and put a plane in between sphere and camera so you can’t see it. Is this possible with selectFromScreen? Or has someone already solved this problem somewhere else?

1 Like

Hi bugs, I’m looking for the exact same thing. I’ve tried the raycasting-from-camera approach with the MFnMesh.allIntersections function. But unfortunately it also seems to ignore meshes and hitpoints in between.
So I’m also wondering, if there is a solution for this problem?

I’ve been doing something similar in my depth of field tool, although I was getting all the meshes visible in the camera frustum. And these methods are now deprecated.

class MMeshDrawTraversal : public MDrawTraversal {
	/* User-defined MDrawTraversal for filtering mesh objects. */
	virtual bool filterNode(const MDagPath &traversalItem) {
		
		bool prune = false;

		// Check to only prune shapes, not transforms.
		if (traversalItem.childCount() == 0) {
			if (!traversalItem.hasFn(MFn::kMesh)) {
				prune = true;
			}
		}

		return prune;
	}
};

and then you just iterate through them and add to an array:

MStatus DepthOfFieldContext::getMeshesInView(MDagPath &cameraPath, unsigned int &portWidth, unsigned int &portHeight) {
	/* Gets all meshes that are visible in the given camera.

	Args:
		cameraPath (MDagPath &): path to a valid scene camera
		portWidth (unsigned int):	width of the viewport to cull against
		portHeight (unsigned int): height of the viewport to cull against

	Returns:
		status code (MStatus): kSuccess if the operation was successful, kFailure if an
			error occured during the operation

	*/
	MStatus status;

	_meshesInView.clear();

	MDrawTraversal *trav = new MMeshDrawTraversal;
	trav->enableFiltering(true);
	trav->setFrustum(cameraPath, portWidth, portHeight);
	trav->traverse();
	for (unsigned int i = 0; i < trav->numberOfItems(); i++) {
		MDagPath dagPath;
		trav->itemPath(i, dagPath);
		_meshesInView.append(dagPath);
	}

	// Clean up pointer
	delete trav; trav = NULL;
	return MS::kSuccess;
}

lastly you have to screen raycast with screen to world in the closestIntersection method.
Check Chad’s Vernonn api series. You have to compare the lenghts of the hits from the camera and return the closest your self. Annoying i know.