Skip to content

Intrinsic attributes

Extract transform matrix from packed primitive

The following example shows how to extract the transformation matrix from a packed primitive and convert it to a quaternion. This is a useful technique when you need to extract the transformation from an RBD packed object and replace pieces with new geometry after sim.

Extract matrix4 from packed transform and convert it to quaternion. "packfulltransform" - is a matrix4 attribute that contains the full transform of the primitive.

Primitive.wrangle
matrix xform = primintrinsic(0, "packedfulltransform", @primnum);
removeprim(0, @primnum, 0);
matrix3 rotation = matrix3(xform);
vector4 orient = quaternion(rotation);
@orient = orient;

Extract matrix3 from packed transform and convert it to quaternion. "transform" - is a matrix3 attribute that contains the rotation of the primitive.

Primitive.wrangle
matrix3 xform = primintrinsic(0, "transform", @primnum);
removeprim(0, @primnum, 0);
vector4 orient = quaternion(xform);
@orient = orient;

Houdini packed primintrinsic() transform

Sometimes you want to apply a post-transformation to your packed primitives after simulation, etc. A good question is how to do that: Houdini stores the transformation of packeds in a primintrinsic attribute called "fullpackedtransform", which includes a 4×4 matrix for translation, rotation, and scale, and a "transform" attribute that holds a 3×3 matrix for rotation and scale.

Now that you know this, you can fetch the transformation matrix using primintrinsic(0, "transform", @primnum); and then extract the needed information to modify rotation and scale in local space. In the example below, I’m using cracktransform to get the correct packed scale. Then I created a few variables:

  • reset_scale - resets the packed primitive’s scale back to 1.0 (identity), useful if you want to get the rest scale.
  • scale_blend - blends between the original scale and the reset scale using lerp() with a float mask.

primintrinsic transform

I’m also using quaternion functions to apply rotation in local space. Finally, I convert everything back to a matrix and apply the new transformation to the packed primitive using setprimintrinsic(0, "transform", @primnum, matrix);:

Primitive.wrangle
matrix3 M = primintrinsic(0, "transform", @primnum);
vector rot = normalize(cracktransform(0, 0, 1, @P, M));
vector scale = cracktransform(0, 0, 2, @P, M);
v@s = scale;
vector scale_m = set(
chf("scale_x"),
chf("scale_y"),
chf("scale_z")
);
vector reset_scale = 1.0 / scale;
vector scale_blend = lerp(scale_m, reset_scale, chf("scale_blend"));
vector4 quat_x = quaternion(radians(chf("rot_x")), {1,0,0});
vector4 quat_y = quaternion(radians(chf("rot_y")), {0,1,0});
vector4 quat_z = quaternion(radians(chf("rot_z")), {0,0,1});
vector4 quat = qmultiply( quat_z, qmultiply(quat_y, quat_x));
matrix3 R = qconvert(quat);
matrix3 S = diag(scale_blend) * M;
R *= S;
setprimintrinsic(0, "transform", @primnum, R);