0
\$\begingroup\$

I am trying to rotate a cube using a quaternion matrix with WGPU. However, whenever I try to rotate it, I end up with

Flattened Cube

I am using the matrix from https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation. I have also tried multiplying the matrix and the vector in the wrong order, which in some occasions, results in something looking like a cube, but with a corner oddly stretched out.

My shader code is

fn vs_main(
    model: VertexInput,
    entity: EntityInput,
) -> VertexOutput {

    let rotation = mat4x4<f32> (
        vec4<f32>(entity.rotation_one, 0.0),
        vec4<f32>(entity.rotation_two, 0.0),
        vec4<f32>(entity.rotation_three, 0.0),
        vec4<f32>(0.0,0.0,0.0,1.0),  
    );
    let translation = mat4x4<f32> (
        vec4<f32>(1.0,0.0,0.0,0.0),
        vec4<f32>(0.0,1.0,0.0,0.0),
        vec4<f32>(0.0,0.0,1.0,0.0),
        vec4<f32>(0.0,0.0,5.0,1.0), 
    );
    let transformation = translation * rotation;
    var out: VertexOutput;
    out.tex_pos = model.tex_pos;
    out.clip_position = camera_mat * transformation * vec4<f32>(model.position, 1.0);
    return out;
}

and the rotation matrix I am using is

        let w = (self.angle.to_f32().unwrap().to_radians() / 2.0).cos();
        let angle = self.angle.to_f32().unwrap().to_radians();
        let x = self.axis.x.to_f32().unwrap() * (angle / 2.0).sin();
        let y = self.axis.y.to_f32().unwrap() * (angle / 2.0).sin();
        let z = self.axis.z.to_f32().unwrap() * (angle / 2.0).sin();
        // https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
        [
            [
                w.powi(2) + x.powi(2) - y.powi(2) - z.powi(2),
                2.0 * x * y + 2.0 * w * z,
                2.0 * x * z - 2.0 * w * y,
            ],
            [
                2.0 * x * y - 2.0 * w * z,
                w.powi(2) - x.powi(2) + y.powi(2) - z.powi(2),
                2.0 * y * z + 2.0 * w * x,
            ],
            [
                2.0 * x * z + 2.0 * w * y,
                2.0 * y * z - 2.0 * w * x,
                w.powi(2) - x.powi(2) - y.powi(2) + z.powi(2),
            ],
        ]

The WGSL shader code is column-major.

EDIT: I have corrected the mistakes in my matrix as pointed out by ratchet freak.

\$\endgroup\$
2
  • \$\begingroup\$ Is the object flattened immediately, or does it distort over a series of incremental rotations until it becomes completely flat? If the latter, this can be due to compounding rounding errors when you use an already-transformed vector or matrix as the input to compute the next incremental transformation. A small error can snowball and amplify with each iteration until you get to a singular case like this. \$\endgroup\$
    – DMGregory
    Aug 23, 2023 at 16:05
  • \$\begingroup\$ It flattens immediately. \$\endgroup\$
    – CyberFlow
    Aug 23, 2023 at 16:16

2 Answers 2

0
\$\begingroup\$

a in the formula under "From a quaternion to an orthogonal matrix" isn't the angle, it is the real or the w component of the quaternion. The value of which should be cos(angle/2).

and you are not consistent whether to convert to radians.

let w = (self.angle.to_f32().unwrap().to_radians() / 2.0).cos();
let x = self.axis.x.to_f32().unwrap() * (self.angle.to_f32().unwrap().to_radians()/ 2.0).sin();
let y = self.axis.y.to_f32().unwrap() * (self.angle.to_f32().unwrap().to_radians()/ 2.0).sin();
let z = self.axis.z.to_f32().unwrap() * (self.angle.to_f32().unwrap().to_radians()/ 2.0).sin();

and then replace angle with w in the computation of the matrix.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you. My conversion to radians is consistent, however, as you pointed out, I had misused w as the angle, and I have corrected this. However, the same symptoms are still displayed. \$\endgroup\$
    – CyberFlow
    Aug 23, 2023 at 15:49
0
\$\begingroup\$

I resolved the issue, it turns out then when I was defining the descriptor for the vertex buffer layout, I miscalculated the memory locations, and thus a column of the rotation matrix was being excluded.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .