How to correctly pre-orient Python state xform handles?

   450   4   2
User Avatar
Member
404 posts
Joined: 4月 2017
オフライン
Let's say I'm building a Python state that has a few objects that need to rotate in their own local spaces, driven by handles. We have the handy "xform" handle for this. However, the various parameters of the handle are undocumented and it's not always easy to know how they work.

I'm running into a problem where I need the output parameters to be in local space, but the handle's parameters are always in world space. I can do a little matrix math to extract Eulers from the object in question, but if I map those values to r[xyz]on the handle, now when the user drags the handle the values are all in world space instead of local.

I can see that there's rpre[xyz]and roffset[xyz]and rpivot[xyz]but regardless of which one I abuse, the output values for the r[xyz]parms that I'm using the handle for are always coming out in world space. So how is this supposed to work under the hood? Am I supposed to compute a transform from the Eulers and multiply it by the inverse parent matrix and then extract the Eulers back from the result to bind the handle values? Is there not a more direct way to do this with the xform handle?
Edited by toadstorm - 2025年9月15日 21:19:25
MOPs (Motion Operators for Houdini): http://www.motionoperators.com [www.motionoperators.com]
User Avatar
Member
133 posts
Joined: 8月 2013
オフライン
I just got a chill down my spine... This is one of those things that I (silently) requested, maybe more hoped for for H21.
User Avatar
スタッフ
50 posts
Joined: 9月 2023
オフライン
If I am understanding correctly, you have some local space, which is some translation and axis rotation, defined as a 4x4 matrix.

What you can do is use the handle's preform parameters to express the local space transformation. If you explode your local space matrix, you can shove the resulting translate, rotate, scale, and shear into pivot_comp_t*, pivot_comp_r*, pivot_comp_s*, and pivot_comp_shear_*, respectively. This can be done in onStateToHandle.

With this, the handle should be oriented based on the local space you used. If you interactively move the handle, the value you receive in onHandleToState will be in the local space. So for example, if you simply move the handle's red "x-axis" translation component, the handle will effectively experience displacement in all 3 world space axes, due to it being oriented to your local space. But you'd only receive meaningful updates to "tx" in onHandleToState (the updates to "ty" and "tz" will be 0, or some negligibly small value).

I am assuming you have node parameters that match those within the handle (similar to the Transform or Edit SOP, which have node parms for translate, rotate, etc, that are bound to the handle). Because you've shoved your local space information into the preform, which is the first step in the handle's matrix sequence computation, the remaining parms will all be applied in the local space.
For instance, in onStateToHandle, say you shove your node's translate parms directly into the handle's tx, ty, and tz. If you start adjusting your node's tx parm in the parm dialogue, the handle will begin to move that amount in the local space x-axis (since the preform will have been applied by the time the handle applies tx).

So, if you treat the handle's preform parms I mentioned above as representative of the local space, the remaining parms can just be bound directly in onStateToHandle and onHandleToState, without needing any special matrix manipulation or extraction.
Things might get more complex if your node also has options for user-defined preforms, like the Edit SOP has. Because then your handle's preform parms will have to be a combination of the local space, and the true preform.
But please let me know if you have further questions.
User Avatar
Member
404 posts
Joined: 4月 2017
オフライン
Thanks very much for the reply! I stumbled onto the pivot_comp_* parameters a few days after making this post and it's exactly what I needed to get local space values returned by the handles.

I would love it if these things were a little better documented. Python state handles and custom viewer handles are pretty arcane as it is, it's even tougher going in half-blind. Thanks again for the detailed explanation.
MOPs (Motion Operators for Houdini): http://www.motionoperators.com [www.motionoperators.com]
User Avatar
Member
133 posts
Joined: 8月 2013
オフライン
toadstorm
I would love it if these things were a little better documented.
  • Quick Links