Think of rotation in webGL as a right-handed coordinate system

  • When the object rotates about the Z axis, from the positive half of the X axis to the negative half of the Y axis counterclockwise, it is the positive rotation, and vice versa
  • When an object rotates about the x axis, from the positive y axis to the positive Z axis counterclockwise, it is positive rotation, and vice versa is negative rotation
  • When the object rotates about the y axis, from the positive z axis to the positive X axis counterclockwise, it is positive rotation, and vice versa is negative rotation

The thinking process

Example: Compute the position of A vertex A at B after it is rotated about the z axis

  1. We have point A, we have point B

  2. < XOB = a + < < b

  3. Bx = cos (< XOB) * OA

  4. By = sin (< XOB) * OA

  5. Use the Pythagorean theorem of triangles to find the length of OA

    Const OA = math.sqrt (ax*ax + ay*ay) //Copy the code
  6. Using the sum Angle formula of a triangle

    Cos (< XOB) = cos (< < a + b) = cos * cos (a) (b) - sin * cos (a) (b) sin (< XOB) = sin (< < a + b) = cos * sin (b) (a) + sin (b) * cos (a)Copy the code
  7. So we can figure out bx,by

    bx=(cos(a)*cos(b) - sin(a)*sin(b))*OA
    by=(cos(b)*sin(a) + sin(b)*cos(a))*OA
    Copy the code
  8. Because ax = cos(a) * OA, ay = sin(a) * OA

    The above formula is reduced to

    bx = cos(a)*cos(b)*OA - sin(a)*sin(b)*OA
    by = cos(b)*sin(a)*OA + sin(b)*cos(a)*OA
    ​
    bx = ax*cos(b) - ay*sin(b)
    by = cos(b)*ay + sin(b)*ax
    ​
    bx = ax*cos(b) - ay*sin(b)
    by = ax*sin(b) + ay*cos(b)
    Copy the code
  9. By vector and matrix multiplication

    [x, y, z, w] * [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, ] = [ ax + by + cz + dw, ex + fy + gz + hw, Ix + jy + kz + lw, mx + ny + oz + pw,] [bx, by, bz, bw] = [cos(b), -sin(b), 0, 0, sin(b), cos(b), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] * [ax, ay, az, aw] = [ ax*cos(b) + ay*-sin(b) + az*0 + aw*0, ax*sin(b) + ay*cos(b) + az*0 + aw*0, ax*0 + ay*0 + az*1 + aw*0, ax*0 + ay*0 + az*0 + aw*1, ] = [ ax*cos(b) - ay*sin(b), ax*sin(b) + ay*cos(b), az, aw ]Copy the code

The calculation process

SQRT (ax*ax + ay*ay) const OA = math.sqrt (ax*ax + ay*ay) by const [bx, by, bz, bw] = [ cos(b)*ax - sin(b)*ay, sin(b)*ay + cos(b)*ax, 1*az, 1*aw ] = [ax, ay, az, aw] * [ cos(b), -sin(b), 0, 0, sin(b), cos(b), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]Copy the code

Based on the above derivation, the matrix needed to calculate the position of point A at B after rotation around z-axis is as follows:

[
    cos(b), -sin(b), 0, 0,
    sin(b),  cos(b), 0, 0,
    0,       0,      1, 0,
    0,       0,      0, 1
]
Copy the code

The source code

The following is the source of three. Js rotation around the X, Y and Z axes respectively

 makeRotationX( theta ) {
    const c = Math.cos( theta ), s = Math.sin( theta );
​
    this.set(
      1, 0, 0, 0,
      0, c, - s, 0,
      0, s, c, 0,
      0, 0, 0, 1
    );
    return this;
  }
​
 makeRotationY( theta ) {
    const c = Math.cos( theta ), s = Math.sin( theta );
​
    this.set(
       c, 0, s, 0,
       0, 1, 0, 0,
      - s, 0, c, 0,
       0, 0, 0, 1
​
    );
    return this;
  }
  makeRotationZ( theta ) {
    const c = Math.cos( theta ), s = Math.sin( theta );
​
    this.set(
      c, - s, 0, 0,
      s, c, 0, 0,
      0, 0, 1, 0,
      0, 0, 0, 1
    );
    return this;
  }
Copy the code

Note ⚠ ️

Generally, in mathematics, matrix is column main order, while in webGL, matrix is row main order. All the above are written in row main order, wherein the this.set() method is to convert the matrix of row main order into the matrix of column main order

Here is the source of the set method

set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
​
    const te = this.elements;
​
    te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
    te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
    te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
    te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
​
    return this;
​
}
Copy the code