メインコンテンツまでスキップ

quatMul: Quaternion Multiplication Operations

Hamilton Product for Rotation Composition

The quatMul function implements the Hamilton product between two quaternions, enabling rotation composition. This operation combines two rotations into a single equivalent rotation, following the non-commutative algebra of quaternion multiplication.

Mathematical Definition: For quaternions q1=(x1,y1,z1,w1)q_1 = (x_1, y_1, z_1, w_1) and q2=(x2,y2,z2,w2)q_2 = (x_2, y_2, z_2, w_2):

q1q2=(q2.xyzw1+q1.xyzw2+q1.xyz×q2.xyzw1w2q1.xyzq2.xyz)q_1 \otimes q_2 = \begin{pmatrix} q_2.xyz \cdot w_1 + q_1.xyz \cdot w_2 + q_1.xyz \times q_2.xyz \\ w_1 \cdot w_2 - q_1.xyz \cdot q_2.xyz \end{pmatrix}

Properties:

  • Non-commutative: q1q2q2q1q_1 \otimes q_2 \neq q_2 \otimes q_1
  • Associative: (q1q2)q3=q1(q2q3)(q_1 \otimes q_2) \otimes q_3 = q_1 \otimes (q_2 \otimes q_3)
  • Rotation composition: Applying q1q_1 then q2q_2 equals applying q2q1q_2 \otimes q_1

The quatMulScalar function provides scalar multiplication for quaternion scaling operations.

Rotation Chain Composition

This example demonstrates sequential quaternion multiplication creating complex rotation sequences. Each multiplication step adds another rotation layer to the transformation chain.

ライブエディター
const fragment = () => {
      const cellPos = uv.mul(4)
      const cell = cellPos.floor()
      const local = cellPos.fract().sub(0.5)

      const hash = cell.x.mul(127.1).add(cell.y.mul(311.7)).sin().mul(43758.5).fract()
      const timeOffset = hash.mul(6.28)

      const baseQ = quatIdentity()
      const rotX = vec4(timeOffset.add(iTime).mul(0.5).sin(), 0, 0, timeOffset.add(iTime).mul(0.5).cos())
      const rotY = vec4(0, timeOffset.add(iTime.mul(0.7)).sin(), 0, timeOffset.add(iTime.mul(0.7)).cos())
      const rotZ = vec4(0, 0, timeOffset.add(iTime.mul(0.3)).sin(), timeOffset.add(iTime.mul(0.3)).cos())

      const step1 = quatMul(baseQ, rotX.normalize())
      const step2 = quatMul(step1, rotY.normalize())
      const final = quatMul(step2, rotZ.normalize())

      const transform = quat2mat3(final).mul(vec3(local, hash))
      const field = transform.length().mul(6).sin().abs()
      const color = vec3(field, field.mul(0.8), field.mul(0.5))

      return vec4(color, 1)

}