# Using Blender to investigate the cast of shadows from an object onto a specific point in space

I think that Blender might do what I have in mind, but I am not a Blender and Python guru, so I am looking for directions.

I need to determine if a point in space is obscured by an object, i.e. does it cast the shadow over it (there is one source of light, the sun). This has to be done for:

• many different objects of different shapes but of similar size: they are fairly simple with just a few surfaces (e.g. a collection of cubes of slightly different sizes and orientations). Each is stored in one OBJ, so there are many OBJs. The analysis should be done one by one.
• a collection of many points that need to be tested, each has different 3D coordinates. For each point it should be determined if a shadow is cast over it or not, so the result is binary.
• for a different position of the sun (e.g. 100-200), to mimic the variable position of the sun during the day and throughout the year.

I am interested in two things: how to automate this, and is there a function in Blender that determines if a point is obscured or not.

What I have so far is shown below. For the simplicity of the approach let's assume that all points that need to be tested have the same Z coordinate (i.e. they are planar).

for each OBJ:
+Place a plane at the Z value of the points to be tested
for each position of the sun:
+Render the image so only the plane with the extent of the shadow is visible
(option Cast Only, and the camera is orthogonal and has a top view.)
+Export the image
+Import the image with an image processing library in Python
for each point to be tested is a shadow cast over it:
+Find the pixel in the image that corresponds to
the position of the point
if the pixel value at that point is dark:
it is obscured
if not:
it is not obscured


Is there a better method for this? Please note that the points might have different Z coordinates, so my method is not optimal (it would require multiple planes).

I would like to point out that the blender python has an API for ray_casting objects so you don't have to manually loop over all the faces of the object your self.

http://www.blender.org/api/blender_python_api_2_63_8/bpy.types.Object.html?highlight=object.ray_cast#bpy.types.Object.ray_cast

import bpy
from mathutils import Vector, Matrix

SunObj = bpy.data.objects['Sun']
sun_mx = SunObj.matrix_world

Surface_Object = bpy.data.objects['Test Points']
surface_mx = Surface_Object.matrix_world
for v in Surface_Object.data.vertices:
v.select = False

#here some simple test objects
test_names = ['Torus', 'Suzanne', 'Cone']
test_objs = [bpy.data.objects[name] for name in test_names]
test_mxs = [ob.matrix_world for ob in test_objs]

#we get the sun location from the world matrix
sun_location = Vector((sun_mx[0][3], sun_mx[1][3], sun_mx[2][3]))

#Test test points are stored in object data
test_points = [surface_mx * v.co for v in Surface_Object.data.vertices]

hits = 0
for ob, mx in zip(test_objs, test_mxs):

imx = mx.inverted() #ray_cast happens in local space
for i, pt in enumerate(test_points):
loc, no, indx = ob.ray_cast(imx * sun_location, imx * pt)

#simulate shadow with selection of the test vert
if indx != -1:
hits += 1
Surface_Object.data.vertices[i].select = True

print(hits)


You dont need to render any images or setup any planes. This is what you should do:

for each OBJ:

for each position of sun:
for each point to be tested:
+Create a ray starting at point with direction of sun (sun's local Z axis)
+Test if ray intersects any of OBJs, if yes:
it is obscured
if not:
it is not obscured


sun's local Z axis you get from up_vector=(0,0,1) and sun's world_matrix:

from mathutils import Vector
up = Vector((0,0,1))    # global Z vector
up.rotate(bpy.context.scene.objects['SUN_NAME_HERE'].matrix_world)
# up is now sun's local Z axis - the ray direction


The part Test if line intersects any of OBJs is done by looping over all OBJs triangles and testing mathutils.geometry.intersect_ray_tri() function.

If your object have lots of triangles test the OBJs bounding box first.

• I fixed the api intersect call, it was old 2.49 api. This will work in current blender. Dec 25, 2014 at 11:42
• point_loc = mathutils.Vector((x,y,z)) where x,y,z are coords of point to be tested. sun_loc = sun.location where sun is bpy.data.objects['YOUR_SUN_NAME']. Then ray is (sun_loc - point_loc) and ray origin is point_loc Dec 25, 2014 at 22:37
• Oh sure, i forgot that your rays are parallel. The direction of sun is its local Z axis. Updated the answer with how to get it. Dec 26, 2014 at 10:28
• I see, consider 2 vectors point-intersection and ray. If their dot product is greater than 0 they have the same orientation. If its < 0 the intersection was a false positive then. blender.org/api/blender_python_api_2_60_1/… Dec 29, 2014 at 22:05
• Vectors have same oriented direction if their cross product is zero and dot product is greater than zero. There's no need to test the direction (the vectors are on a line), so the orientation test should be enough. Dec 29, 2014 at 22:09