计算从一个方向旋转到另一个方向的旋转矩阵

基于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表示的, 只是普通的四个变量. 要将顺序切换回来.

  

posted @ 2021-12-28 16:15  惊雷阁  阅读(198)  评论(0)    收藏  举报