0
$\begingroup$

I am doing a physics simulation for a demonstration and would love to show an represent the angular velocity of an object (e.g., the axis of rotation). Is there an easy (or hard) way to access that information?

I mainly wish to represent the axis of rotation but the direction and amount would be fantastic as well.

For example, if the disk is spinning on the XY plane (about the Z axis) it would look like this (either the red or green arrow): enter image description here

Whereas if the disk is spinning on the XZ plane (end over end about the Y axis), it would look like this:

enter image description here

Perhaps there's a Python API to access the current rotation information?

$\endgroup$
4
  • 2
    $\begingroup$ How do you want to represent the axis? Do you want the object's original 'up' orientation? Or do you want an axis that around which the rotation from the last frame to the current frame occurred? $\endgroup$
    – Sazerac
    Jul 14 at 4:03
  • $\begingroup$ I want to represent the change between frames. Essentially, I want to turn the change in rotation (rotational velocity) into a position vector. $\endgroup$ Jul 14 at 13:13
  • $\begingroup$ Are you doing this with a live Blender physics simulation? Or are you doing it with animated values? Different solutions for each. $\endgroup$
    – Nathan
    Jul 14 at 17:10
  • $\begingroup$ @Nathan - live simulation, but I plan on baking the simulation into animation frames so either works I suppose? $\endgroup$ Jul 14 at 18:13
2
$\begingroup$

You've said that you're interested in a baked solution, so here's what we can do given keyframes for the object whose axes we wish to track. I assume you already have an object with baked animation; I assume it's not experiencing any translation.

Let's start by making a single bone armature at the location of the tracked object. We'll enter pose mode on the armature, name our single bone "Current" and give it a copy rotation bone constraint targeting our tracked object; for simplicity, then select this bone and apply as rest pose (ctrl a menu in pose.) Then enter edit mode on the armature and duplicate this bone; we'll name this duplicate "minusOne" because it will eventually be tracking our object's rotation at a one frame offset. Play your animation; you'll find that your bones rotate with your object.

Now we can go back into pose mode on the armature. Use the "bake action" operation, and on it's interface, enable "visual keying" and "clear constraints". You'll see the constraints on your bone disappear and you'll have keyframes for your bones in their place; if you play the animation, you'll see the bones do the same thing they did with the constraints.

Now, in pose mode, select minusOne, and then select all keyframes in a timeline view, and move those 1 unit in the X axis in that timeline: 'g x 1 enter.' This means that minusOne now lags Current by one frame. Select Current and give it a "locked track" bone constraint, targeting its own armature but targeting minusOne in that armature. Set the constraint's track axis to -X, its locked axis to Y, and the head/tail to 1.0 to locked track the tail of minusOne:

enter image description here

Now put the armature into rest position in properties/object data/skeleton. Enter object mode, select the axis object, shift select armature, select Current, and ctrl p -> parent bone relative. Return your armature to pose position and play your animation. Your first frame shouldn't make any sense, but it's because you don't have any rotational velocity at frame 1; after that, you'll see that your pole remains perpendicular to the plane formed by Current and minusOne, which is the plane of rotation.

That's our axis of rotation taken care of, which was your primary concern. You're also interested in the direction of rotation. Your direction of rotation is always perpendicular to your axis, so you can parent any object you want to your axis and get the direction of rotation. If the rotation switches direction, the pole will "flip" and anything parented to it will as well. (If you don't want this to happen, it's possible with further constraints, but seeing as how this is going to be a long answer anyways, I'm not going to assume you need that.)

enter image description here

Your final request is to get the amount of velocity represented in the direction. That's possible too. There are a huge number of ways to get it. Let's do it with a mesh object with a few modifiers.

First, we need one more bone. In edit mode, duplicate minusOne, delete its animation, parent it to minusOne, and give it a constraint targeting Current. Give it a locked track constraint, locked Y track +X, at head/tail 1.0. Name this "minusOneChild".

Next, we'll make a weird mesh object. We'll call this object "Skinned". Make a plane, then in edit, delete two vertices. Scale both remaining vertices to zero so they occupy the exact same location at , but do not merge. Parent this plane to your armature with armature deform->empty groups. In edit mode, select one vertex and assign to minusOneChild vertex group at 1.0 weight; assign the other to Current at 1.0 weight. This plane now has an armature modifier due to the parenting; follow this modifier with a skin modifier to turn the line formed into an actual mesh.

This creates a straight line, but we want a circle to describe the direction and velocity of motion. We can do that procedurally, which is something I like. Give Skinned a subdivision modifier, with a few extra iterations, and move it to the top of the modifier stack, above the armature modifier. Then enable "preserve volume" on your armature modifier. The subdivision will interpolate weights between the two vertices automatically, and the armature will now use quaternions to calculate the mix between two bones, giving us an arc of a perfect circle:

enter image description here

The only problem remaining is that it's a little short. We're looking at the difference in rotation between a frame and the one immediately previous, which is small, so the rotational velocity we're showing is small as well. We might want to exaggerate that some, while keeping it proportional to the actual relative velocity (so multiplying it by something, rather than adding it to something.)

Again, there are many different ways to do that. I'll do it with a pair of bones and bone constraints.

Enter edit on your armature. Duplicate minusOneChild twice and parent both copies to Current. Name the first "measureRotation". Name the second "multiplyRotation." Give measureRotation a locked track constraint targeting minusOne, set to lock Z, track +Y, head/tail 1.0. Then give multiplyRotation a transformation constraint targeting measureRotation. Set it to work in local->local, to map rotation to rotation, with extrapolate enabled, and to map -1,1 degrees Z rotation to -10,10 degrees Z rotation-- so we're showing an arc ten times bigger than what we had to begin with.

enter image description here

Select Skinned, and in properties/object data/vertex groups, rename minusOne to multiplyRotation to weight from this new bone. Finally, if we'd like, we can create a cone or something and bone parent it to Current.

enter image description here

Note, of course, that nothing is defined when the object has no rotational velocity! At that point, we're basically dividing by zero. (And remember, at frame 1, it has no rotational velocity yet.) Recommended would be to create a driver that hides your objects when the the local rotation of measureRotation is 0. Again, as something optional in an answer that is already overly long, if you need help with that, I'll leave it for a different question.

$\endgroup$
1
  • $\begingroup$ Thank you so much! Amazing response. $\endgroup$ Jul 17 at 1:23
1
$\begingroup$

Create a mesh in the shape of an arrow. Now use a copy rotation constraint at this object, and pick the target object where you want to retreive the rotation from. Your arrow mesh will follow the rotation of your target object now.

enter image description here

$\endgroup$
1
  • $\begingroup$ This just captures the instantaneous amount of rotation correct? I am looking to represent the change in rotation (angular velocity). I have updated the question to be more precise. $\endgroup$ Jul 14 at 13:09

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.