1
votes

I would like to use this JavaScript matrix library: Matrix3D

My target is to implement a function which takes the CSS transform properties as arguments and returns with the proper matrix3d() CSS transform declaration.

function 3d(x, y, z, rotateX, rotateY, rotateZ){
  var m = Matrix3D.create();
  Matrix3D.translateX(m, x);
  Matrix3D.translateY(m, y);
  Matrix3D.translateZ(m, z);

  Matrix3D.rotateX(m,this.data.rotateX);
  Matrix3D.rotateY(m,this.data.rotateY);
  Matrix3D.rotateZ(m,this.data.rotateZ);

  return Matrix3D.toTransform3D(m);
}

It works fine for the x,y,z and the rotateZ parameters, but it is unable to merge the rotation matrices into one matrix, instead it overwrites the rotation.

Could you help me how should I combine matrices to behave in the right way?

UPDATE #1

I just found out that I should need to create a quaternion from the three euler rotation axis. euler to quaternion

    function eulerToQuaternion(rotateX, rotateY, rotateZ) {
    // Assuming the angles are in radians.
    var c1 = Math.cos(rotateX / 2),
        s1 = Math.sin(rotateX / 2),
        c2 = Math.cos(rotateY / 2),
        s2 = Math.sin(rotateY / 2),
        c3 = Math.cos(rotateZ / 2),
        s3 = Math.sin(rotateZ / 2),
        c1c2 = c1 * c2,
        s1s2 = s1 * s2,
        w = c1c2 * c3 - s1s2 * s3,
        x = c1c2 * s3 + s1s2 * c3,
        y = s1 * c2 * c3 + c1 * s2 * s3,
        z = c1 * s2 * c3 - s1 * c2 * s3;
    return [w, x, y, z]
}

function deg2rad(deg) {
    return deg * (Math.PI / 180);
};

console.log(eulerToQuaternion(deg2rad(45), 0, deg2rad(45)));

But here I'm stuck again. How can I add this quaternion to my matrix?

2

2 Answers

1
votes

Found the solution:

function a(x, y, z, scaleX, scaleY, rotateX, rotateY, rotateZ) {
    var D = 2;
    var Y = Math.cos(rotateX * (Math.PI / 180)).toFixed(D),
        Z = Math.sin(rotateX * (Math.PI / 180)).toFixed(D),
        b = Math.cos(rotateY * (Math.PI / 180)).toFixed(D),
        F = Math.sin(rotateY * (Math.PI / 180)).toFixed(D),
        I = Math.cos(rotateZ * (Math.PI / 180)).toFixed(D),
        P = Math.sin(rotateZ * (Math.PI / 180)).toFixed(D);

    var a = new Array(16);

    a[0] = b * I * scaleX;
    a[1] = -1 * P;
    a[2] = F;
    a[3] = 0;
    a[4] = P;
    a[5] = Y * I * scaleY;
    a[6] = Z;
    a[7] = 0;
    a[8] = -1 * F;
    a[9] = -1 * Z;
    a[10] = b * Y;
    a[11] = 0;
    a[12] = x;
    a[13] = y;
    a[14] = z;
    a[15] = 1;


    console.log("transform: matrix3d(" + a[0] + "," + a[1] + "," + a[2] + "," + a[3] + "," + a[4] + "," + a[5] + "," + a[6] + "," + a[7] + "," + a[8] + "," + a[9] + "," + a[10] + "," + a[11] + "," + a[12] + "," + a[13] + "," + a[14] + "," + a[15] + ");");
}
0
votes

What about passing 2 parameters to the Matrix3D.rotateXYZ() method like below

Matrix3D.rotateX(m, this.data.rotateX)

I don't know which version you are using, but that method needs 2 parameters according to https://gist.github.com/f5io/7466669.

If you omit the first parameter, this.data.rotateX will be understood as a result array, not a rotation, and this is not what you wanted to do.