Skip to content

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 axis
float 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 axis
vector4 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 axis
float 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 axis
vector4 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