I have a scene in which I randomize the locations of several 3D objects. Naturally, sometimes the objects occlude one another:

enter image description here

How can I, using Python, check to see if an object is 100% visible by the camera and if not, regenerate its position (randomly) until an unobstructed position is found? E.g:

enter image description here

My ideas are:

  1. Iterate over each object and for each object, cast a ray from the center of the camera at the vertices of that object. If not hit, some part of the object is occluded, so regenerate its location and test again.
  2. Map the 3D region of each object to 2D space, then for each mapping, check for intersections. If an intersection exists, regenerate a location for one of the objects.

I have tried 1) but for some reason, the ray always hits as long as the target object is within camera view frustum, even if there is an object between it and the camera (it ignores occlusions). I have no idea where to begin with 2).

I am new to Blender and the BPY API and would appreciate some help.

  • 1
    $\begingroup$ What about this: i.imgur.com/r3GL8tj.png the vertices of each object aren't occluded by any other object… $\endgroup$ Dec 5, 2022 at 16:02
  • $\begingroup$ @MarkusvonBroady There is definitely occlusion there; both occlude one another. In that case, I would want to just select and randomize the location of one of them. $\endgroup$
    – pookie
    Dec 5, 2022 at 16:08
  • $\begingroup$ I would approach it by making a loop that adds an object, makes a preliminary check (for optimization) if the vertices happen to be on the non-transparent pixels of the previously rendered image. If not, then I would subdivide the object, I think that might be enough? Maybe I could limit the subdivisions to just faces with big area. Then check again. If still all is good, render to update the mask with a new object and repeat the process… $\endgroup$ Dec 5, 2022 at 16:10
  • $\begingroup$ Another highly convoluted idea : Render your objects using cryptomatte (or object ID) on single view layers separately, then together. Check if the number of pixels with their ID is the same in both cases, if not, then there is some occlusion. I don't know how it would behave with transparency though $\endgroup$
    – Gorgious
    Dec 5, 2022 at 16:20
  • 1
    $\begingroup$ Unless you cast 1 ray for every expected pixel of the object appearing in the image you won't be certain the object is not occluded. Unless you're fine with having a level of uncertainty. But I think you're taking the problem in the wrong way, and you take the risk of facing a potentially very inefficient program, or even one that will indefinitely hang if no solution is ever found. What if the green cube were to take all the space of the camera ? I think you should look for a possible solution at the time you're instancing the red cube. Seems more sane, you can even use the green bounding box $\endgroup$
    – Gorgious
    Dec 5, 2022 at 16:26


You must log in to answer this question.

Browse other questions tagged .