Skip to content

Instantly share code, notes, and snippets.

@Arakade
Last active January 4, 2023 09:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Arakade/14462f3bede08cd541c27f492e33c25b to your computer and use it in GitHub Desktop.
Save Arakade/14462f3bede08cd541c27f492e33c25b to your computer and use it in GitHub Desktop.
Blender Python (bpy) code to iterate raycast until a predicate passes
import bpy
import bmesh
import mathutils
from math import radians, degrees
from mathutils.bvhtree import BVHTree
def rayCastConditional(ray, rayTarget, increment, predicate):
"""Cast multiple rays until 'predicate' passes.
ray: (p, direction)
rayTarget: something with ray_cast() such as:
mathutils.bvhtree.BVHTree
bpy.types.Object
bpy.types.Scene
predicate: function(ray, ray_cast_hitTuple) that returns whether hit is satisfactory.
N.b. different rayTarget types have different return tuples! Check the docs.
returns: hit tuple from whichever rayTarget was provided.
Example usage:
rayCastConditional((Vector((0, 0, 2)), Vector((0, 0, -1))), bpy.context.scene, 0.01, lambda ray, hitTuple: ray[1].angle(hitTuple[2]) > radians(150))
"""
assert 2 == len(ray), "Non-2 len:%d of ray:%s" % (len(ray), ray)
p, direction = ray
p = p.copy() # since we are modifying and it might not be a copy already
while True:
hitTuple = rayTarget.ray_cast(p, direction)
if hitTuple[1] is None:
return hitTuple
if predicate(ray, hitTuple):
return hitTuple
p += direction * increment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment