Quaternions
Rotate quaternion by axis and angle
Next example shows how to rotate quaternion by axis and angle with vex:
vector up = {0,1,0};vector n = @N;vector axis = chv("axis");float angle = radians(ch("angle"));vector4 qrot = quaternion(maketransform(n, up));vector4 qrot2 = quaternion(angle, axis);@orient = qmultiply(qrot, qrot2);
Add random quaternion rotation by axis and blend with existing @orient
I’m using simple random weight control for each axis here. This is a straightforward approach for understanding.
However, if you plan to use this for animation, it can cause problems when blending two quaternions.
In this case, it’s better to use the slerp()
function and a weight
mask for blending the quaternions by axis.
int pt = @ptnum;int i = @ptnum + 1;vector4 orient_base = p@orient;
float random_x = rand(pt + i + 1) * 2 - 1;float random_y = rand(pt + i + 2) * 2 - 1;float random_z = rand(pt + i + 3) * 2 - 1;vector random_axis = normalize(set(random_x, random_y, random_z));random_axis.x *= chf("random_x");random_axis.y *= * chf("random_y");
float angle_min = chf("angle_min");float angle_max = chf("angle_max");float random_angle = fit(rand(pt + i + 4), 0, 1, angle_min, angle_max);
vector4 random_orient = quaternion(radians(random_angle), random_axis);vector4 rand_orient = qmultiply(orient_base, random_orient);@orient = rand_orient;
Blending two quaternions with slerp()
int pt = @ptnum;int i = @ptnum + 1;vector4 orient_base = p@orient;// Generate random angles for each axisfloat angle_min = chf("angle_min");float angle_max = chf("angle_max");float random_angle_x = fit(rand(pt + i + 1), 0, 1, angle_min, angle_max);float random_angle_y = fit(rand(pt + i + 2), 0, 1, angle_min, angle_max);float random_angle_z = fit(rand(pt + i + 3), 0, 1, angle_min, angle_max);
// Create quaternions for random rotations around each axisvector4 random_orient_x = quaternion(radians(random_angle_x), set(1, 0, 0));vector4 random_orient_y = quaternion(radians(random_angle_y), set(0, 1, 0));vector4 random_orient_z = quaternion(radians(random_angle_z), set(0, 0, 1));
// Define blend factors for each axisfloat blend_factor_x = chf("blend_factor_x");float blend_factor_y = chf("blend_factor_y");float blend_factor_z = chf("blend_factor_z");
// Blend orientations for each axisvector4 blended_orient_x = slerp(orient_base, qmultiply(orient_base, random_orient_x), blend_factor_x);vector4 blended_orient_y = slerp(blended_orient_x, qmultiply(blended_orient_x, random_orient_y), blend_factor_y);vector4 final_orient = slerp(blended_orient_y, qmultiply(blended_orient_y, random_orient_z), blend_factor_z);
@orient = final_orient; // Update the orientation attribute with the final quaternion