Saturday, May 14, 2011

Houdini: Arrow system using Quaternions

Got inspired the last few days to design an "Arrow" system and finally took Friday evening and Saturday morning to figure out a good way to create a system that allows stuck particles (arrows) to change their orientation based on the underlying deforming geometry.

The main concept is getting an origin frame of reference (in this case, it's the primitive normal of the collided polygon that the particle hit, as well as the vector of the first two vertices. These will give a reference frame.), as well as a constantly updating frame of reference (the prim normal and vector again, from the deforming primitive).

Originally, I had used the Align VOP to perform this calculation, however, the align vop simply returns a transform from one vector to another vector via the shortest path. In this case, it is basically a rotation with an axis that is the cross product of the two vectors. What we want is a proper rotation, so I used the look at vop to generate rotation matrices from the two frames of references.

Next, these were converted to Quaternions, and then I used the SLERP function (Spherical Linear Interp VOP) to obtain yet another quaternion that blends the original frame orientation to the final deformed frame.

The issue I encountered was that the SLERP function returns the initial orientation quaternion when both the initial and target orientations are the same - this is obviously the case during the collision frame; both reference and initial orientation are exactly the same.



This, we do not want; as during the collision frame, I want my arrow's normal vector to be operated on by a Quaternion of xyzw = {0,0,0,1}, not the quaternion for the initial frame. Hence, by subtracting the initial frame's quaternion from both the initial frame as well as the target frame (this is done by doing a quaternion multiplication of the conjugate of the initial frame's quaternion against both initial and target quaternions before putting them into the SLERP).

This seemed to work, from the examples above. :)

Woo! Slowly attacking quaternions. And Houdini just makes it so simple.

Other issues I encountered is during rendering: proper motion blur for the arrows. With a stuck particle, the "v" velocity vector is actually locked in place whilst the particle is with the pstate of 16, hence during renders, this is uber incorrect.

Initial tests using to Attribute Transfer velocity vector (calculated using a Trail SOP) did not work out as it was very inconsistent. What I did then, was to do a look up into the geometry (the collision POP stores the posprim attribute, allowing us to find out which primitive to query), and allow the hit arrow to take the velocity of the underlying geometry.

GW

No comments: