2
$\begingroup$

I am trying to modify the vertices of Bezier Curve to maneuver around any obstacles if existing in their way. So far, I am able to create curves through script but still unable to detect any overlap of other objects with this curve so that the vertices (left and right hands could be modified accordingly to maneuver around that obstacle). Basically, I want to make some object follow that curve path but it should avoid every existing obstacle in their way.

from bpy import ops, context, data
from mathutils import Vector

ops.curve.primitive_bezier_curve_add(enter_editmode=False)
curve = context.active_object
curve.name = 'Trajectory'
bez_points = curve.data.splines[0].bezier_points        

bez_points[0].co = Vector((0.0, 0.0, 0.0))
bez_points[0].handle_left = Vector((0.0, 0.0, 0.0)) + Vector((0.5, 0.0, 0.0))
bez_points[0].handle_right = Vector((0.0, 0.0, 0.0)) + Vector((-0.5, 0.0, 0.0))

bez_points[1].co = Vector((10.0, 10.0, 10.0))
bez_points[1].handle_left = Vector((10.0, 10.0, 10.0)) - Vector((0.5, 0.0, 0.))
bez_points[1].handle_right = Vector((10.0, 10.0, 10.0)) - Vector((-0.5, 0.0, 0.))

I want to modify the curve so that the object following that path should avoid any obstacle in their way. I have illustrated it for better understanding.

enter image description here

enter image description here

$\endgroup$
3
$\begingroup$

Raycast into the scene

enter image description here

As a proof of concept have put together a "dodgy" artillery trajectory.

  • Define the two end points in scene
  • Target from point to point and shoot a ray into scene
  • If it hits an object, raise elevation by one degree and try again
  • If it does not hit, using current aim vector, extend the right handle of the source knot to where it intersects the plane defined by target point and source to target normal.
  • The incoming handle is lazily set to vertical.

Note haven't put any checks and balances in to test if there is no possible LOS trajectory A to B.

To improve could use same method going other way. Have found only the trajectory on the vertical plane. Spinning the aim around point to point axis could be considered to find shortest two point bezier path that misses object obstacles between two points. Another way to put this would be we are looking at pitch, could also consider roll, moving our aim around ever increasing concentric circles until a miss

Test code.

from bpy import ops, context, data
from mathutils import Vector, Matrix
from mathutils.geometry import intersect_line_plane
from math import radians

scene = context.scene
pt0 = Vector((-5, 0, 0))
pt1 = Vector((5, 0, 0))
up = Vector((0, 0, 1))
t = d = (pt1 - pt0).normalized()
axis = d.cross(up)
d_elev = radians(1)

hit = scene.ray_cast(
        context.view_layer, 
        pt0,
        d,
        )[0]

R = Matrix.Rotation(d_elev, 3, axis)
while hit:
    t = R @ t
    
    hit = scene.ray_cast(
            context.view_layer, 
            pt0,
            t,
            
            )[0]

t = R @ t # rotate one more time
pt2 = intersect_line_plane(
    pt0,
    pt0 + 1000 * t,
    pt1,
    d,
    )

ops.curve.primitive_bezier_curve_add()
curve = context.active_object
curve.name = 'Trajectory'
bez_points = curve.data.splines[0].bezier_points        

bez_points[0].co = pt0
bez_points[0].handle_left = pt0 - t
bez_points[0].handle_right = pt2

bez_points[1].co = pt1
bez_points[1].handle_left = pt2
bez_points[1].handle_right = pt1

Added one more rotation after miss. Raycast can be a little dodgy if it hits an edge.

enter image description here

Some test results of moving two cubes, active curve is last result with cubes in current location.

As mentioned this is simply a proof of concept of manipulating the handle of a bezier curve to emulate lobbing over an obstacle in LOS changing degree of elevation.

Doing this using points of a right angled triangle with right angle at destination point.

To make this a "shortest" curve that misses obstacles would require more bezier points or investigating looking from other end moving the apex of the triangle that is the intersection of handle right of source point and handle left of destination point vectors.

$\endgroup$
2
  • $\begingroup$ Yes, it seems a working solution, but I want a shortest distance from pt1 to pt2. So, if I put one cube above the curve and one in the line of curve, it is still making a projectile like path and not like passing through obstacles. I added an image in my question for reference. $\endgroup$
    – mGm
    Sep 6 '20 at 14:39
  • $\begingroup$ As mentioned answer put forward of proof of concept that to make sure a projectile "lobs" over the obstacle can extend a handle to the plane. Raycast is a bit dodgy around edges, adding an extra rotation t = R @ t after the first miss avoids this somewhat. As mentioned for a closer result look at raycasting from the other end. or adding more curve points. For any direction would need to roll our target eg trace around ever increasing concentric circles with the line A to B as the center. To put this another way have shown how to raycast from A to B and see if there is something inbetween. $\endgroup$
    – batFINGER
    Sep 6 '20 at 15:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.