I am trying to rotate a flat 2D image around a 2D origin in 3D space. The problem I am having is that the image becomes stretched after the rotation. I am using the WGSL from this tutorial, but with the camera logic removed. The clip-coordinates have to be a 3d vector + w
.
Here is what the sprite is meant to look like:
Here is what the sprite looks like when rotated 45 degrees:
I am using the cgmath crate for the quaternions. I have tried creating a quarternion from the Z angle:
let rotation = Quaternion::from_angle_z(cgmath::Deg(rotation));
And also tried manually:
let rotation = Quaternion::from_axis_angle(
Vector3 {
x: 0.0,
y: 0.0,
z: 1.0,
},
cgmath::Deg(rotation).normalize(),
);
I tried making a matrix that looks like this:
$$\begin{bmatrix} \cos \theta & -\sin \theta & 0 & 0\\ \sin \theta & \cos \theta & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}$$
and I have also tried calling from_axis_angle
using the normalised position as the axis argument.
All of these solutions have resulted in the same effect.
I also tried manually rotating the vertices, however, this just caused the position of the 2D image to rotate further.
Vertex shader to manually rotate each vertex:
struct EntityInput {
@location(5) position: vec2<f32>,
@location(6) origin: vec2<f32>,
@location(7) rotation: f32,
@location(8) scale: f32,
}
@vertex
fn vs_main(
model: VertexInput,
entity: EntityInput,
) -> VertexOutput {
var out: VertexOutput;
var orig_x: f32 = model.position.x - entity.origin.x;
var orig_y: f32 = model.position.y - entity.origin.y;
var new_x = (orig_x * cos(entity.rotation)) - (orig_y * sin(entity.rotation));
var new_y = (orig_y * cos(entity.rotation)) + (orig_x * sin(entity.rotation));
var final_x = new_x + entity.origin.x;
var final_y = new_y + entity.origin.y;
var final_vec = (vec4<f32>(final_x, final_y, 1.0, 1.0) + vec4<f32>(entity.position, 0.0, 0.0));
final_vec.x = final_vec.x * entity.scale;
final_vec.y = final_vec.y * entity.scale;
out.tex_coords = model.tex_coords;
out.clip_position = final_vec;
return out;
}
90
degrees, using the methods you mentioned, what would the result be? Would the sprite still look stretched? \$\endgroup\$cgmath
so I can't help much there, but the rotation matrix you posted looks correct. I'm not sure if it would help if you'd post the steps you followed to calculate the rotation manually with the matrix. \$\endgroup\$