Use a curve for each segment between timestamped camera points
For the follow path constraint, with fixed position, offset, 0 is start point and offset 1 is the other end point of curve. If instead of using an n point bezier curve, we use n - 1
"segment" beziers, we can use this feature simply.
The curve of points [p0, p1, p2]
becomes two curves [p0, p1]
and [p1, p2]
. At the frame specified for camera to be at p1
can either be offset 1 of first segment, 0 of next Note segments don't have to be 2 point beziers, just require last point to match first point of next.
A follow path constraint is added for each segment.
To make the object use the particular segment we set the influence to 1 to use this constraint 0 otherwise. (or set hide inversely). We want the influence of the constraint to be 1 when the current frame is between the end point frames (from your data), Otherwise it is set to 0 and has no effect.
The offset can be calculated using (current_frame - p0.frame) / (p1.frame - p0.frame)
A test case setup using drivers
To each bezier curve segment we add two custom propeties, "frame_start" and "frame_end" ( curve_object["frame_start"] = 44
) indicating the frames at which to be at end points. (I've used integers here, floats would be much better in hindsight)
via UI, adjust the min / max to suit
Now we set up a couple of drivers. The use_self
option of the driver is handy here. The constraint itself is self
, the path is self.target
, from which we can get the frame range for this curve.
setup in UI, make sure use_self
is checked. Might have to click "Update Dependencies".
The driver expressions used are in_segment(self, frame)
for influence, (could also drive is_expanded and hide) and segment_offset(self, frame)
for offset. The argument frame
is known to the driver name space and is context.scene.frame_current
. Run script below to define methods and register to the driver namespace
import bpy
def in_segment(self, frame):
segment = self.target
if not segment:
print("No target")
return False
frame_start = segment.get("frame_start", 0)
frame_end = segment.get("frame_end", 0)
return frame_start <= frame < frame_end
def segment_offset(self, frame):
segment = self.target
if not segment:
print("No target")
return 0
frame_start = segment.get("frame_start", 0)
frame_end = segment.get("frame_end", 0)
duration = frame_end - frame_start
if not duration:
return 0
return (frame - frame_start) / duration
bpy.app.driver_namespace["in_segment"] = in_segment
bpy.app.driver_namespace["segment_offset"] = segment_offset
Now with this setup can add a bezier curve, set the custom properties, then add a follow path constraint, set as curve target, and the constrained object will follow that curve for the defined frame duration.
_Cube switching between four bezier circles. The constraints expand is also driven by the influence. Each circle has a 10 frame duration, hence on the smaller circle cube apppears slower. _