0
$\begingroup$

Is it possible to know if an object moves or not with python in Blender? Is there any object's attribute/state/other that gives this information?

EDIT: Here I speak of movement in world space. More precisely, if the world positions of the vertices of an object don't move between two frames, I consider the object doesn't move. If the camera moves but the objects don't, then their world positions shouldn't change and I consider they don't move.

I saw some answer using Blender Game Engine with an active object, but I just use a rigid solids simulation in Cycles. EDIT bis: My goal is to know when the objects in the simulation are in their final state basically.

Example: a wrecking ball breaks a stack of cubes. Some cubes fall, and after some time they stop sliding on the ground: the object's state should tell me that now they are "inactive". If they get hit by other falling cubes, then their state should change back to "active", until they "stabilize" again.

Thanks !

$\endgroup$
  • $\begingroup$ Movement is relative. E.g. if your camera moves in world space and all other objects do not, all objects will move relative to the camera, So what is movement for you? $\endgroup$ – user2859 Sep 24 '14 at 20:47
  • $\begingroup$ Thanks @user2859, I tried to be more precise and added an example :) $\endgroup$ – Yauda Sep 24 '14 at 21:01
  • 1
    $\begingroup$ So you need to know per vertex or would watching the objects world matrix be enough? You could add a frame handler and compare the world matrix of each object with the old one when the frame changed (for simplicity all matrices stored in a dict maybe). $\endgroup$ – user2859 Sep 24 '14 at 23:23
1
$\begingroup$

Here is a simple setup with script that displays the velocity vector of the active object and an indicator of that vector's length: http://www.pasteall.org/blend/31772

If you run the modal operator and start the playback, you'll see how velocity changes, but that it never settles to completely zero. Thus, use some epsilon (tolerance value), such as
min and max out of 30 samples from diff vector lengths < 0.1
(use a collections.deque(maxlen=30) for that, it's a capped array)

At the core of the script, I access Object.matrix_world.translation to get the current location in 3D world. Note that you need to .copy() this vector if you want to store the start vector, otherwise it will be an alias and the difference therefore zero.

Ridgid Body Animation velocity depiction

It could be made a bit more efficient if one used an app handler (frame_change_post).

$\endgroup$
  • $\begingroup$ Just to be sure : here at each frame you make the difference between the matrix_world.translation of the previous frame and the one of the current frame ? Are you suggesting to run it several times (like 30 times) because of floating point precision ? WHat is the difference with the object's attribute "delta_location" ? $\endgroup$ – Yauda Sep 26 '14 at 20:54
  • $\begingroup$ It measures the difference, a simple before / after, which usually means previous frame. If you manually change current frame however, it will not be the previous frame in time of course. Not sure how to use delta_location, it always gave me a zero vector in a quick test. I'm not suggestion to run it 30 times 'cause of floating point precision, it is not precision problem. It is really that the simulation may never settle down, so you need to take that into account. Multiple samples are just to prevent an early break, e.g. when the movement direction is about to reverse. $\endgroup$ – CoDEmanX Sep 26 '14 at 22:21

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.