计算从一个方向旋转到另一个方向的旋转矩阵
基于glm库的客户端实现:
#include <GL/glm/glm.hpp>
#include <GL/glm/gtc/matrix_transform.hpp>
#include <GL/glm/gtc/quaternion.hpp>
glm::dmat4 vecRvec(glm::dvec3 & s, glm::dvec3 & t)
{
s = glm::normalize(s);
t = glm::normalize(t);
const glm::dvec3 half = glm::normalize(s + t);
const double w = glm::dot(s, half);
const glm::dvec3 xyz = glm::cross(s, half);
const glm::quat p = glm::quat(w, xyz);
return glm::mat4_cast(p);
}
着色器代码中的实现:
dmat4 getRotationMatrixFromVectorS2T(dvec3 s, dvec3 t)
{
s = normalize(s);
t = normalize(t);
// firstly, calculate the quaternion from vector s to t
const dvec3 halfst = normalize(s + t);
const double w = dot(s, halfst);
const dvec3 xyz = cross(s, halfst);
//const dvec4 quat(w, xyz);
const dvec4 quat = dvec4(xyz, w);
// secondly, transform the quaternion to rotation maxtrix
const double qxx = quat.x * quat.x;
const double qyy = quat.y * quat.y;
const double qzz = quat.z * quat.z;
const double qxz = quat.x * quat.z;
const double qxy = quat.x * quat.y;
const double qyz = quat.y * quat.z;
const double qwx = quat.w * quat.x;
const double qwy = quat.w * quat.y;
const double qwz = quat.w * quat.z;
return dmat4(
1.0 - 2.0 * (qyy + qzz), 2.0 * (qxy + qwz), 2.0 * (qxz - qwy), 0.0,
2.0 * (qxy - qwz), 1.0 - 2.0 * (qxx + qzz), 2.0 * (qyz + qwx), 0.0,
2.0 * (qxz + qwy), 2.0 * (qyz - qwx), 1.0 - 2.0 * (qxx + qyy), 0.0,
0.0, 0.0, 0.0, 1.0
);
}
这里需要注意的是, glm中的四元数是w在前, xyz在后. 而glsl中四元数是用dvec4表示的, 只是普通的四个变量. 要将顺序切换回来.

浙公网安备 33010602011771号