3
$\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$ 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$ Commented Nov 11, 2022 at 9:16

1 Answer 1

2
$\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$ Commented Nov 11, 2022 at 20:08

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.