我已经修改了一个 Vulkano, GLTF viewer example,使其支持键盘和鼠标输入,并应用翻译和旋转到场景中。翻译效果很好,但旋转会导致场景中的物体移动到相机的右侧并拉伸,直到它们看起来像垃圾,当旋转角度在 90 - 180 度之间时。
这是旋转前场景的样子:
这是我创建初始四元数的方式,使用我在这里找到的方程式:
为了应用翻译和旋转,我将矩阵相乘,如下所示:
所以你可以看到,我正在乘以 proj * view * trans_mat * rot_mat……也许这个顺序不对吗?
任何帮助都将不胜感激。我没有很强的数学背景,并且一直在自学CG多年,所以我不知道还能向谁求助。关于这种类型的东西的一些阅读资源也会受到欢迎。
这是旋转前场景的样子:
当旋转角度约为90度时:
我将使用cgmath 四元数 进行旋转。我以前没有使用过四元数,所以我想知道是否有人能告诉我我是否使用得正确,我怀疑问题就出在这里。这是我创建初始四元数的方式,使用我在这里找到的方程式:
let rotation_speed_deg = 0.01;
let rotation_speed = rotation_speed_deg * f32::consts::PI / 180.0;
let rotation_angle_deg = 0.0;
let rotation_angle = rotation_angle_deg * f32::consts::PI / 180.0;
let rotation_axis = Vector3::new(0.0, 1.0, 0.0);
let rotation_scalar = (rotation_angle / 2.0 as f32).cos();
let rotation_vec = Vector3::new(
rotation_axis.x * (rotation_angle / 2.0 as f32).sin(),
rotation_axis.y * (rotation_angle / 2.0 as f32).sin(),
rotation_axis.z * (rotation_angle / 2.0 as f32).sin());
let mut rotation_quat = Quaternion::from_sv(rotation_scalar, rotation_vec);
然后我修改四元数,以此来应用鼠标输入的旋转,就像这样:
let diff_x = position.0 - last_x;
if diff_x > 0.0 {
// println!("turn right");
rotation_quat.v.x += rotation_axis.x * ((rotation_angle + rotation_speed) / 2.0 as f32).sin();
rotation_quat.v.y += rotation_axis.y * ((rotation_angle + rotation_speed) / 2.0 as f32).sin();
rotation_quat.v.z += rotation_axis.z * ((rotation_angle + rotation_speed) / 2.0 as f32).sin();
rotation_quat.s += ((rotation_angle + rotation_speed) / 2.0 as f32).cos();
} else if diff_x < 0.0 {
// println!("turn left");
rotation_quat.v.x += rotation_axis.x * ((rotation_angle - rotation_speed) / 2.0 as f32).sin();
rotation_quat.v.y += rotation_axis.y * ((rotation_angle - rotation_speed) / 2.0 as f32).sin();
rotation_quat.v.z += rotation_axis.z * ((rotation_angle - rotation_speed) / 2.0 as f32).sin();
rotation_quat.s += ((rotation_angle - rotation_speed) / 2.0 as f32).cos();
}
last_x = position.0;
为了应用翻译和旋转,我将矩阵相乘,如下所示:
let fovy = Rad(60.0 * f32::consts::PI / 180.0);
let mut aspect = viewport_dimensions[0] as f32 / viewport_dimensions[1] as f32;
let near = 0.1;
let far = 100.0;
let mut proj = perspective(fovy, aspect, near, far);
let view = Matrix4::look_at(Point3::new(0.0, 1.0, -5.0), Point3::new(0.0, 1.0, 0.0), Vector3::new(0.0, -1.0, 0.0));
let trans_mat = Matrix4::from_translation(trans);
let rot_mat = Matrix4::from(rot);
builder = self.draw_node(node.index(), proj * view * trans_mat * rot_mat, viewport_dimensions, builder);
所以你可以看到,我正在乘以 proj * view * trans_mat * rot_mat……也许这个顺序不对吗?
任何帮助都将不胜感激。我没有很强的数学背景,并且一直在自学CG多年,所以我不知道还能向谁求助。关于这种类型的东西的一些阅读资源也会受到欢迎。