如何用Rust nalgebra将4×4矩阵左上块设为旋转矩阵?
在Rust的nalgebra中实现Eigen风格的4×4矩阵子块操作
问题场景
尝试将4×4矩阵的左上3×3块替换为旋转矩阵,同时完成缩放、平移操作,复刻以下Eigen C++代码的逻辑,但原Rust代码因类型不匹配编译失败:
原Eigen C++代码
Eigen::Quaternionf rotation = joint_animation.SampleRotation(t); Eigen::Vector3f translation = joint_animation.SampleTranslation(t); Eigen::Vector3f scale = joint_animation.SampleScaling(t); Eigen::Matrix4f t_mat = skin.joint_matrices[i]; t_mat.block(0, 0, 3, 3) = (rotation).toRotationMatrix(); t_mat.row(0).head<3>() *= scale(0); t_mat.row(1).head<3>() *= scale(1); t_mat.row(2).head<3>() *= scale(2); t_mat(0, 3) = translation[0]; t_mat(1, 3) = translation[1]; t_mat(2, 3) = translation[2];
原Rust代码(编译失败)
let mut mat = Mat4::identity(); mat.set_column(3, &Vec4::new(trans.x, trans.y, trans.z, 1.0)); let slice = &mat.slice((0,0), (3,3)); slice = &rot.to_rotation_matrix().matrix().slice((0,0), (3,3));
已定义的类型别名
pub type Quatf = na::UnitQuaternion<f32>; pub type Mat2 = na::Matrix2<f32>; pub type Mat3 = na::Matrix3<f32>; pub type Mat4 = na::Matrix4<f32>;
修正后的Rust代码
nalgebra中不能直接通过引用赋值子矩阵,需要使用可变视图复制数据,同时按逻辑加入缩放、平移操作:
// 初始化矩阵(如果是从已有矩阵复制,替换成对应获取方式) let mut mat = Mat4::identity(); // 1. 将旋转矩阵写入左上3×3子块 let rot_mat = rot.to_rotation_matrix().matrix(); mat.fixed_view_mut::<3, 3>(0, 0).copy_from(&rot_mat); // 2. 对每一行的前3个元素应用缩放 let mut row0 = mat.row_mut(0); row0.x *= scale.x; row0.y *= scale.x; row0.z *= scale.x; let mut row1 = mat.row_mut(1); row1.x *= scale.y; row1.y *= scale.y; row1.z *= scale.y; let mut row2 = mat.row_mut(2); row2.x *= scale.z; row2.y *= scale.z; row2.z *= scale.z; // 3. 设置平移列 mat[(0, 3)] = trans.x; mat[(1, 3)] = trans.y; mat[(2, 3)] = trans.z;
关键说明
- 使用
fixed_view_mut::<3,3>(0,0)获取4×4矩阵左上角3×3的可变视图,再通过copy_from将旋转矩阵的数据复制进去,这是nalgebra中修改子矩阵的标准方式 - 原代码错误在于尝试给不可变引用重新赋值,同时没有正确处理子矩阵的数据复制逻辑
- 缩放操作直接操作行元素,完全对应Eigen中
row.head<3>() *= scale的逻辑
内容的提问来源于stack exchange,提问作者Makogan
相关产品推荐
相关产品推荐

