如何从代表局部轴的3个向量获取旋转四元数
从局部轴向量生成旋转四元数的问题
我有三个代表物体局部轴的向量,需要从中提取旋转信息生成四元数,用于渲染管线。使用的C语言代码库包含完整的四元数工具,但我对四元数的实际应用掌握不足,虽然理解概念,但不知道具体怎么实现。

轴的对应关系:
- 红色:Y局部向量
- 绿色:Z局部向量
- 蓝色:X局部向量
我原本写了单个轴的四元数生成函数,以为逻辑是对的,但单独使用或组合后结果都不对:
quat getAxisQuaternion(vec3 axisVector, vec3 referenceAxisVector) { axisVector = axisVector.normal(); vec3 a = axisVector.cross(referenceAxisVector); float w = sqrt((axisVector.length() * axisVector.length()) * (referenceAxisVector.length() * referenceAxisVector.length())) + axisVector.dot(referenceAxisVector); return quat(a.x, a.y, a.z, w); } //... quat xQuaternion=getAxisQuaternion((leftJoint-rightJoint), vec3(1,0,0)); quat yQuaternion=getAxisQuaternion((lowJoint-upperJoint), vec3(0,1,0)); quat zQuaternion=getAxisQuaternion((frontJoint-backJoint), vec3(0,0,1));
编辑更新:
我做了一些修改后,Y和Z轴的组合已经能得到正确结果:
quat getAxisQuaternion(vec3 axisVector, vec3 referenceAxisVector, float angleOffset=0) { axisVector = axisVector.normal(); vec3 a = axisVector.cross(referenceAxisVector); float w = sqrt((axisVector.length() * axisVector.length()) * (referenceAxisVector.length() * referenceAxisVector.length())) + axisVector.dot(referenceAxisVector); return quat(a.x, a.y, a.z, w+angleOffset).normal(); } //.. quat xQuaternion=getAxisQuaternion((leftJoint-rightJoint), vec3(1,0,0)); quat yQuaternion=getAxisQuaternion((lowJoint-upperJoint), vec3(0,-1,0), M_PI); quat zQuaternion=getAxisQuaternion((backJoint-frontJoint), vec3(0,0,1), M_PI); rot=yQuaternion*zQuaternion;
修改点包括:归一化生成的四元数、反转Y轴参考向量(因为原《古墓丽影》引擎的Y轴方向是反的)、添加半旋转偏移来匹配正确位置。
但加入X轴四元数后(rot=yQuaternion*zQuaternion*xQuaternion)出现了问题:
- 直接组合时,X轴旋转方向错误,且旋转量是预期的两倍
- 给X轴四元数添加
M_PI/2偏移后,旋转范围被限制在-45°到45°之间(速度和方向是对的,但范围不够) - 添加
M_PI偏移后,X轴完全不旋转
感觉getAxisQuaternion函数把旋转限制在了单个象限里,求解决思路?
内容的提问来源于stack exchange,提问作者RicardoSBA
相关产品推荐
相关产品推荐

