2
$\begingroup$

I am trying to build a simple simulation of a tree growing in Blender, using Python. (Note: I am fairly new to Blender). This is what it looks like right now:

Simple tree

I am now trying to calculate how much sunlight would fall on each leaf. To keep things simple, I'm assuming sunlight only comes from directly above. So I'm using ray_cast like this:

def _calculate_sunlight(self):
    context = bpy.context
    scene = context.scene
    for x in range(-1, 2):
        for y in range(-1, 2):
            o = (x, y, 100)  # ray origin
            d = (0, 0, -1)  # ray direction

            hit, loc, norm, idx, obj, mw = scene.ray_cast(context.view_layer.depsgraph, o, d)
            if hit:
                print(x, y, hit, obj.name)
            else:
                print(x, y, "MISS")

In this simplified example, I have a 3x3 grid of rays shooting directly downwards, and I'm printing out which leaves get hit.

Now, the results I'm getting are hard to explain. I think what the code above is doing is shooting a ray from e.g. (0, 1, 100) directly downward, and looking at the top-view, I'd expect this to hit the middle top two leaves at some (0, 1, Z) and (0, -1, Z) coordinates:

Expectation

top view

The output comes close to matching this expectation, but the leaf IDs are somehow incorrect:

-1 -1 MISS
-1 0 MISS
-1 1 MISS
0 -1 True Branch9310279.Leaf0
0 0 MISS
0 1 True Branch9310279.Leaf1
1 -1 MISS
1 0 MISS
1 1 MISS

The leaf IDs printed there correspond to two totally different leaves:

Reality

other leaves get hit

and this is different every time I run the script. It seems to always be two leaves on the same twig, but other than that the hit leaves seem completely random.

What is going on here? Am I misunderstanding something about the scene ray_cast function? Does the obj not correspond to the first object that intersected with the ray?

I would also appreciate your thoughts on whether this is even a good way to be going about this, as I'm mostly just fumbling around in the dark right now. Thank you!

Edit: link to simplified blend file that reproduces the issue when you run the script a few times: https://easyupload.io/t1cl7e

$\endgroup$
2
  • $\begingroup$ can you share the file? $\endgroup$
    – Crantisz
    Commented Nov 10, 2022 at 21:37
  • $\begingroup$ I can't share the full project, but I have uploaded a smaller reproduction of the issue. See the updated question. Interestingly, I couldn't reproduce it using cubes, but using the leaves (with only a single face each) does reproduce it. Running the script a couple of times prints different leaf IDs each time, rather than getting the same one(s) as you would expect. $\endgroup$
    – Oak Leaf
    Commented Nov 11, 2022 at 9:16

1 Answer 1

1
$\begingroup$

Adding context.view_layer.update() should fix the problem

def calculate_sunlight():
    print("-----")
    
    context = bpy.context
    scene = context.scene
    context.view_layer.update()
    
    for x in range(-1, 2):
        for y in range(-1, 2):
            o = (x, y, 100)  # ray 
            d = (0, 0, -1)  # ray direction

            hit, loc, norm, idx, obj, mw = scene.ray_cast(context.view_layer.depsgraph, o, d)
            if hit:
                print(x, y, loc, obj.name)
            else:
                print(x, y, "MISS")
            
$\endgroup$
1
  • $\begingroup$ Indeed, that was it! Thank you! $\endgroup$
    – Oak Leaf
    Commented Nov 11, 2022 at 20:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .