2
$\begingroup$

I'm trying to use blender to test the probabilities associated with different faces of non-cubic dice (some of you may even know why). I've already written a python script that randomly sets the objects position, rotation, initial linear velocity and initial angular velocity, then bakes the physics and jumps to a frame where the shape is likely in a settled position. The problem is that the rotation data at this frame seems to be the same as the frame right before the physics engine took over. It looks like the physics engine doesn't operate directly on object transformations. Is there a way to get this rotation information from python? Right now I can't even seem to find it in the UI.

$\endgroup$
6
  • $\begingroup$ I am not confident, but you might want to investigate parsing the values from a physics cache. blender.stackexchange.com/questions/15577/… has some techniques and particle system examples. $\endgroup$
    – Mutant Bob
    Commented Sep 16, 2016 at 15:44
  • $\begingroup$ are you sure the physics have been baked properly? When I create a scene like that (simple cube in rotated orientation falling on a plane) and bake those physics, I do see changing rotation values in the transform panel. Are you using the 'Bake to Keyframes' button in the Physics Panel? $\endgroup$
    – aliasguru
    Commented Sep 16, 2016 at 16:14
  • $\begingroup$ @aliasguru What version of python are you using? I'm using 2.77a. Also, what rotation mode are you using? I've tried this for Axis angle, XYZ Euler, and Quaternion, and have not been able to see results in the object transformation panel. $\endgroup$
    – AIGuy110
    Commented Sep 17, 2016 at 3:27
  • $\begingroup$ I've tested this with both 2.76 and the current release candidate of 2.78. The important part of my last comment was if you are using the 'bake to keyframes' function. Baking the physics via the Poperties Panel shows the behavior you see. Using the bake to keyframes function gives you access to the rotation and location values. The Python command is bpy.ops.rigidbody.bake_to_keyframes(). You'll need to set the rotation to quarternions before baking! $\endgroup$
    – aliasguru
    Commented Sep 17, 2016 at 6:45
  • $\begingroup$ Ah, thanks @aliasguru! I was not able to find the "Bake to Keyframes" button, and none of the seemingly related buttons in the Scene > Rigid Body Cache panel seemed to do the trick, but "bpy.ops.rigidbody,bake_to_keyframes()" did exactly what I was looking for! $\endgroup$
    – AIGuy110
    Commented Sep 20, 2016 at 10:48

2 Answers 2

0
$\begingroup$

To be able to read out transformation values from rigid body physics simulations, those simulations need to be baked to keyframes. Baking the Physics from the Physics tab is not enough. Find the Bake to Keyframes button here:

bake to keyframes

From Python you can access the function via this operator:

bpy.ops.rigidbody.bake_to_keyframes()

You will be asked to enter a framerange when using the interactive operator:

framerange

Again, in Python you can use these keyword arguments to achieve the same thing:

bpy.ops.rigidbody.bake_to_keyframes(frame_start=1, frame_end=250, step=1)

Before baking, you should set the rotation mode to either Quarternions or Euler, depending on what you need to read out later. After baking, you can see the generated keyframes in the Timeline:

keyframes

Here are two comparison screenshots after the baking process, the first one is at frame 1, the other one at frame 250:

frame 1

frame 250

$\endgroup$
1
  • $\begingroup$ This is simply untrue and misleading, I think. .matrix_local and .matrix_world seem to include rigid body simulation transformations. Do .matrix_local.to_quaternion() for quaternions. Some latency may apply. (I'm still investigating the latency. I think it's just a caching issue.) $\endgroup$
    – Will Chen
    Commented Mar 20, 2021 at 21:15
5
$\begingroup$

enter image description here

There's a fairly simple way to get the transformations of an object under a physics simulation without baking (which also applies to other situations such as parent-child relationships, constraints, etc).

To do this you simply need to access the object's world matrix property. Here are some examples you can test through the interactive python console:

# Accessing through the location property will give the initial value before the simulation starts
>>> C.object.location
Vector((0.0, 0.0, 14.47101879119873))

# The world matrix though gives the real, simulated location
>>> C.object.matrix_world.to_translation()
Vector((0.5996798276901245, 1.5040934085845947, 1.7373782396316528))

# Same goes for rotation
>>> [ degrees(a) for a in C.object.rotation_euler ]
[0.0, 0.0, 0.0]

>>> [ degrees(a) for a in C.object.matrix_world.to_euler() ]
[176.1907675277052, -11.192468775907107, -74.38630617504491]

# To access quaternion rotation values, simply use "to_quaternion"
>>> C.object.matrix_world.to_quaternion()
Quaternion((0.17901940643787384, -0.7067779302597046, 0.6757702231407166, -0.10840550810098648))

You can also add an app handler that calculates and prints the simulated location and rotation after every frame change:

import bpy
from math import degrees

def print_simulated_loc_rot( scene ):
    C = bpy.context
    o = C.object

    simulated_loc   = o.matrix_world.to_translation()
    simulated_rot   = o.matrix_world.to_euler()
    sim_rot_degrees = [ degrees(v) for v in simulated_rot ]

    print_friendly_loc = [ round( v, 2 ) for v in simulated_loc   ]
    print_friendly_rot = [ round( v, 2 ) for v in sim_rot_degrees ]

    print( "Location: ", print_friendly_loc )
    print( "Rotation: ", print_friendly_rot )

bpy.app.handlers.frame_change_post.append( print_simulated_loc_rot )
$\endgroup$

You must log in to answer this question.

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