11
$\begingroup$

I am doing a space scene with a space ship, and i'm trying to be physically realistic when it comes to how ships move in space. As such, I only want my thruster effects to fire when the Rate of Change of rotation or translation is changing. I could animate it all by hand, but I don't want to if I don't have to.

Is there an input node I can get this information with? Everything i've seen is just plain location data. Oris there an addon or script I haven't been able to find? Can this information even be retrieved with a script and i'm up a creek?

$\endgroup$
6
  • $\begingroup$ Its possible to control nodes values with drivers, did you try that? $\endgroup$
    – Denis
    Commented Apr 27, 2015 at 4:24
  • $\begingroup$ @Denis Thanks for that, I hadn't thought of using those in that way. I was stuck trying to do it only in the nodes. I can drive a shader value off my rotation and translation info, but not the rate of change of that info. At least, not that I can see. $\endgroup$ Commented Apr 27, 2015 at 4:59
  • 2
    $\begingroup$ You can achieve this by considering the F-Curve values in the graph editor. If the change in curve evaluation values between two neighboring time steps is greater than that between the previous time step neighbors, you have acceleration. I'm on mobile now so I can't test how to make this work with the node editor, but I'm sure there is a way. Will post an answer if I can make it work once I reach my computer. $\endgroup$
    – Ulf Aslak
    Commented Apr 27, 2015 at 7:46
  • 1
    $\begingroup$ @UlfAslak There is no way to evaluate an F-Curve at specific frame in driver, because that requires non-build-in function on that curve. This can be done with pydrivers. They don't update right on nodes though (dependencies issue) so when scripting its better to script this with frame change handlers. $\endgroup$ Commented Apr 30, 2015 at 15:32
  • 1
    $\begingroup$ Sorry, didn't know I needed to check a checkmark. Thanks for pinging me on this. $\endgroup$ Commented May 9, 2015 at 15:33

4 Answers 4

18
+50
$\begingroup$

Blender doesn't give value changes off the sleeve. What you need is to evaluate an animation (F-Curve) in current and previous frames and compute the difference. This solution uses a script that adds a custom frame change handler. Other way could be with PyDrivers or using Animation Nodes plugin.

Run this, it will add new properties to objects and it will update them every frame. You can access them in driver:

import bpy
from mathutils import Vector, Euler

curr_frame = None

def frame_handler(scn):
    global curr_frame
    if curr_frame != scn.frame_current:
        curr_frame = scn.frame_current
        for obj in scn.objects:
            obj.speed = (obj.matrix_world.translation - Vector(obj.last_loc)).length
            last_quat = Euler(obj.last_rot).to_quaternion()
            quat = obj.rotation_euler.to_quaternion()
            obj.angular_speed = quat.rotation_difference(last_quat).angle
            obj.last_loc = obj.matrix_world.translation
            obj.last_rot = obj.rotation_euler

bpy.types.Object.last_loc = bpy.props.FloatVectorProperty()
bpy.types.Object.last_rot = bpy.props.FloatVectorProperty()

bpy.types.Object.speed = bpy.props.FloatProperty()
bpy.types.Object.angular_speed = bpy.props.FloatProperty()

if frame_handler not in bpy.app.handlers.frame_change_pre:
    bpy.app.handlers.frame_change_pre.append(frame_handler)

Added props of interest are:

  • speed (in blender units per frame)
  • angular_speed (in rads per frame)

Use them in driver like this:

enter image description here

Here I am driving Y-scale and view-port material color with speed:

enter image description here


Note: this will only work when playing the frames sequentially. If you jump around you will get crazy values. This is a very simple handler using values from last and current frame, but it could be adjusted to read from the Fcurves of objects if you need.

Also it expects rotations in euler, but it transforms it to quaternions anyway. So if you want quaternions no problem.

$\endgroup$
3
  • $\begingroup$ This a pretty awesome solution! Addressing your comment to my comment, you can get the F-Curve value at every frame, so my clever idea was to write a script that evaluates the acceleration at each frame using this property and then somehow implement it as a node that would output a value between 0 and 1, to be routed into e.g. a mix shader in the node editor. Didn't get that far in the process, and your solution seems to be working pretty great, so cheers! $\endgroup$
    – Ulf Aslak
    Commented Apr 30, 2015 at 19:35
  • $\begingroup$ @UlfAslak Oh I meant you cannot get the Fcurve value with driver native functions. With scripting (PyDrivers, OSL script nodes, etc.) the possibilities are indeed endless. $\endgroup$ Commented Apr 30, 2015 at 20:15
  • $\begingroup$ @Jerryno too bad it can't be done directly with the drivers, but this solution is neat! $\endgroup$
    – Denis
    Commented May 6, 2015 at 0:56
4
$\begingroup$

You could also play with Animation Nodes Addon by using Location Velocity and Rotation Velocity values of the Object Info Node. Following example uses translation velocity values to drive the strength value of an emission shader:

enter image description here
Test rendering of a simple sphere animation

  • Create an Object Info Node,
  • Split the velocity values (x,y,z) into single ones by the help of a Seperate Vector Node,
  • Add Math Nodes to calculate the sum of the x,y,z velocity and
  • Add a Cycles Material Output Node to plug the result into a shader value:

enter image description here Scene Setup (click to enlarge)

This example is just an idea, things like combining Location Velocity and Rotation Velocity values or creating a color by these values are also possible with simple math, of course.

enter image description here Preview Scene (click to enlarge)

$\endgroup$
2
  • $\begingroup$ I don't see Object Info node anymore, do you know what node to use instead in latest version? $\endgroup$
    – Neil
    Commented Jun 9, 2016 at 12:49
  • $\begingroup$ @Neil unfortunately Velocity sockets have been removed in latest versions, see: blender.stackexchange.com/questions/44556/… I'll update the answer as soon as possible. $\endgroup$
    – p2or
    Commented Jun 10, 2016 at 7:46
3
$\begingroup$

Using Animation Nodes, you can compute the velocity of an object based on the F-Curves of its animation as described in this answer. You can then pass that velocity to Cycles in a form of vertex color map per object using the Set Vertex Color node.

$\endgroup$
1
$\begingroup$

To calculate velocity, you need to know where the object is (which is easy with Animation Nodes) and where the object was (which is harder!).

Here's a slightly hacky little trick that works in Blender 2.8. It uses Python to store data from the previous frame, which you can then use in your simulation. This only works when playing the frames in order, if you jump around on the timeline it won't evaluate correctly without some additional stuff.

This approach is a much-simplified version of that suggested in Omar's excellent answer here: How to store particle locations in a list?

The process is as follows:

  1. Important: set Auto Execution to Frame Changed only.
  2. Read the data from the previous frame - in this case a Vector3D storing location XYZ. This is done with the node labelled 'Read Data', which is an expression node set to animation_nodes.previousTransformValue
  3. Do whatever you want with the stored value. In this case, wejust set the sphere to the cube's previous position using an Object Transforms Output.
  4. Read the new transformation data (with the Object Transforms Input).
  5. Overwrite the temporary data with the current frame's data. This is done with another expression node, labelled Write Data, with the expression animation_nodes.previousTransformValue=[newTransformValue, dummyInput][0]. It has two inputs, newTransformValue (a Vector3D with the new location data) and dummyInput, an Object Input. Dummy Input actually isn't used in the calculation, but having it connected forces the nodes to evaluate in the correct order. If we left that out, we might end up writing over the data before we'd used it in our calculations, which would leave us with the current frame's value instead of the previous frame's!

Note: This approach only works when frames are playing sequentially, and will be incorrect on the very first frame. You could add extra data which specifies what frame the data is from, and then initialize the data to a known value if the data is from the wrong frame, but the simpler option is just to start playback one frame earlier.

Frame Delay Setup

$\endgroup$

You must log in to answer this question.

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