2
$\begingroup$

Say I have an object which has an animation.

(I turned on the motion path to make it more clear)

I have another object which is constrained to a curve. I want it to follow the curve BUT I want it to do it at the same speed as the animated object.

enter image description here

here I am manually moving the object to show what I mean. I want the cube to move along the path, but with the same variations in speed that the moving camera has.

Doing this will essentially let me deform a motion path like you would do with a mesh. I don't know much about coding so if the answer includes writing some kind of script, I would really appreciate it if you gave an example :)

EDIT: batFINGER phrased it well in the comments: "for every frame if Free object moves d units, the path object will move d along the curve"

Also, preferably I would also like to do this live in blender.

$\endgroup$
2
  • $\begingroup$ To clarify, for every frame if Free object moves d units, the path object will move d along the curve? Doing it live, is do-able but tricky. Baking it post animation is simpler, eg using a slow empty one frame behind the camera, d is the distance between. Knowing the length of the curve, offset the path object. $\endgroup$
    – batFINGER
    Oct 1, 2021 at 19:24
  • $\begingroup$ ... noticing your last comment, given you have an animation for the camera,, the empty can be animated via same animation offset via NLA. Please edit any extra details into the question. See blender.stackexchange.com/a/159719/15543 re using array / curve modifiers to give curve dimension. $\endgroup$
    – batFINGER
    Oct 1, 2021 at 19:28

2 Answers 2

4
$\begingroup$

Bake the displacement.

enter image description here

Given

I used a gltf camera path which I exported from a video game, so Its just a keyframe animation

Here is a quick baking script,

Whenever the animation of the camera has been changed, run the script to bake some simple physics.

  • Set scene to first frame of action save the location as previous location
  • For each frame of camera action
  • Calculate the distance from frame location to previous location and store
  • Set the location as previous.

From the data bake in 3 animations on custom properties

  • "speed" The amount of distance travelled that frame

  • "disp" The accumulative displacement

  • "offset" The frame displacement as a fraction of total

  • The values of the 3 are keyframed into the camera action

  • The cube in GIF has a follow path constraint to circle, the relative offset is being driven by cameras custom property "offset" added by script. enter image description here Baked in graph editor enter image description here

Here is a test script, assuming the animated object is scene camera, and it is animated by active action

import bpy
import numpy as np
context = bpy.context
scene = context.scene
cam = scene.camera
action = cam.animation_data.action
frames = np.arange(*action.frame_range)

def gloc(ob):
    return ob.matrix_world.to_translation()



locs = []
scene.frame_set(frames[0])
ploc = gloc(cam)
for f in frames:
    print(f)
    scene.frame_set(f)
    loc = gloc(cam)
    s = (loc - ploc).length
    locs.append(s)
    ploc = loc


def flatten(a, b):
    c = np.empty((a.size + b.size,), dtype=b.dtype)
    c[0::2] = a
    c[1::2] = b
    return c

def fcurve(fcurves, datapath, data):
    cam[datapath] = 0.0
    fc = fcurves.find(datapath)
    if fc:
        fcurves.remove(fc)
    fc = fcurves.new(datapath)
    fc.data_path = f'["{datapath}"]'
    fc.keyframe_points.add(len(frames))

    fc.keyframe_points.foreach_set(
            "co",
            flatten(frames, data)
            )
    fc.convert_to_samples(*action.frame_range)           

# per frame speed    
speed = np.array(locs)
fcurve(action.fcurves, "speed", speed)

# displacement
disp = np.cumsum(speed)
fcurve(action.fcurves, "disp", disp)
# Offset of total displacement

offset = disp / disp[-1]

fcurve(action.fcurves, "offset", offset) 

Note, GIFs shown are not moving two objects same distance each frame, rather the same offset fraction along their asscociated paths per frame. To make it 1:1 distance would require calculating the length of the constraint curve

$\endgroup$
1
$\begingroup$

Edit: sorry it looks like I misunderstood your question as your object A follows a curve path. Anyway I leave my original answer.

Let's say the cone is the object A that goes straight ahead and the cube is the object B that is following a curve.

First, you can do it with Curve modifier and Copy Location constraint:

enter image description here

  • Create a plane, give it a Curve modifier (with the curve as Object) and a Copy Location constraint (with the cone as Target)
  • Select the cube, shift select the plane, select 3 vertices of the plane and CtrlP to parent the cube to the plane vertices
  • Animate the cone, the plane will go along the curve and the cube will follow the plane

enter image description here

You can also do it with Drivers:

Give your cube a Follow Path constraint, enable its Follow Curve option, right click on Offset value and choose Add Driver:

enter image description here

In the pop-up panel, choose the object the cube is supposed to follow, in Expression choose a variable, here *-40 -50 (-0 is here so that it begins at the right position), you can right click on Offset to Open Drivers Editor, press V to make a linear curve, rotate the curve, test the animation:

enter image description here

Here is what it gives for me:

enter image description here

$\endgroup$
3
  • $\begingroup$ Thanks for the reply, I tried using the drivers, and this is what I got: imgur.com/i2VVqFV . The problem is I want it to only progress along the path in one direction. Linking the offset value to the axis-value of object A means it depends on how far away object A is from the origin. Is there some kind of way or expression I can transfer the free movements of object A into the offset value of the constrained object? $\endgroup$
    – nav9
    Oct 1, 2021 at 17:01
  • $\begingroup$ oh ok you're right I completely missed that aspect, it may be doable with script, I hope someone will answer. Btw how do you move your object A? If you make it move along a curve it will make things easier but it looks like not... $\endgroup$
    – moonboots
    Oct 1, 2021 at 17:06
  • $\begingroup$ I used a gltf camera path which I exported from a video game, so Its just a keyframe animation $\endgroup$
    – nav9
    Oct 1, 2021 at 19:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .