Jump to content

Intrinsic transforms, matrices and volumes

Recommended Posts


we are turning some animated geometry (alembic, non-deforming animation) into clouds, but because we want the noise of the clouds to be in local space (not be affected by the animation), I am trying to work out how to apply the animation after the creating the clouds referencing the intrinsic transform of the alembic.

Using an AttributeVOP, I've managed to copy the intrinsic:packedfulltransform of the animated alembic, on to the intrinsic:transform of the static alembic model. I am still trying to get my head around the difference between matrix3 and matrix4 for these transform. Is there a general rule to which matrix type is used in each case?

intrinsic:packedfulltransform is matrix4, intrinsic:transform in packed primitives is matrix3, but intrinsic:transform in VDB is matrix4. So what I put together and works for packed geometry or simple volumes, doesn't work with VDBs unless if I pack them before hand.

Also my understanding is that intrinsic:packedfulltransform  and intrinsic:packedlocaltransform are not writable and I can only change intrinsic:transform . Is that right?


thank you



Share this post

Link to post
Share on other sites

3x3 matrix is a rotation (and also scale) matrix. It does not store translation vector, since there is no space to store it, like in 4x4 transform matrices. We usually use 4x4 matrices to store full transforms (translation, rotation, scale), and 3x3 to store orientations. In later case, additional pivot attribute may be used to store translation. VDB's transform intrinsic may be special, however. Hard to tell without seeing an actual problem.

Edited by f1480187
Snippet not work, so, I removed it.

Share this post

Link to post
Share on other sites

hey, thanks for these pointers.

I have noticed that other than matrix3 intrinsic transform, I also need to set the @P to fully copy the alembic animation onto static packed objects, or volumes.

Somehow though, if you convert a simple volume to a VDB, the intrinsic:transform attribute becomes a 4x4 matrix, so the code you posted doesn't set the matrix correctly. This works though:

@P = point(1,"P", @ptnum);
matrix t = primintrinsic(1, "packedfulltransform", @primnum);
setprimintrinsic(0, "transform", @primnum, t, "multiply");

and confuses me a bit to why it still needs to set the @P even though it's a 4x4 matrix.
As you say volumes and VDBs may be a special case, as I've noticed their bounding box is also stored as scale values within the matrix and that's why I have to set the setprimintrinsic to multiply rather than set.

We are currently face another problem, where the volume jitters after setting these the transform matrix. Somehow it seems that the pivot changes as the cloud patch re-calculates on every frame, which changes the placement.

Thanks again for your time.

Share this post

Link to post
Share on other sites

I have to say though, occasionally I get some strange behavior with VDBs. They update correctly when viewed from the moving camera, but at times they stay still when viewed from the default viewport perspective camera.
At this point it may be safer to extract the translate/rotate/scale components from the matrix and apply them using one transformSOP per primitive.

Share this post

Link to post
Share on other sites

1. Sure. 3x3 matrices do rotate, skew and scale only. Object will stay on it's place. There is two ways, actually. First, and probably most useful, is to set P in point wrangle after setting transform in primitive wrangle, as you did. Second is to use primitive wrangle only and set pivot intrinsic, not sure about drawbacks of this method:

// Primitive wrangle.
matrix t = primintrinsic(1, "packedfulltransform", @primnum);

matrix3 r = (matrix3) t;
setprimintrinsic(0, "transform", @primnum, r);

vector p = primintrinsic(0, "pivot", 0);
p -= cracktransform(0, 0, 0, 0, p, t);
setprimintrinsic(0, "pivot", @primnum, p);

Note that using both @ptnum and @primnum is good only for vertex wrangles over normal geometry. @primnum in point wrangles will always be 0, and @ptnum is equal to 0 in primitive wrangles. Normally, you should split your snippet on two different wrangles. It did work, however, because there is single volume primitive, with only point #0 and primitive #0 exist.

2. I cannot reproduce my own snippet working now, so, never mind. Probably, you shouldn't bother with multiplying, but here is how to cleanly set VDB transform:

// Primitive wrangle.
matrix pft = primintrinsic(1, "packedfulltransform", @primnum);

vector scale = primintrinsic(0, "voxelsize", @primnum);
matrix3 r = (matrix3) pft;
scale(r, scale);

vector translate = cracktransform(0, 0, 0, 0, pft);
matrix t = (matrix) r;
translate(t, translate);

setprimintrinsic(0, "transform", @primnum, t);

3. Updating transform using intrinsic:pivot from animated input may help to get rid of jitter.

4. There is various problems with dealing with VDBs using intrinsics on my build. First is incorrect viewport updating. Caching geometry after wrangle node helps.


Edited by f1480187
  • Like 6
  • Thanks 1

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now