You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从代表局部轴的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)出现了问题:

  1. 直接组合时,X轴旋转方向错误,且旋转量是预期的两倍
  2. 给X轴四元数添加M_PI/2偏移后,旋转范围被限制在-45°到45°之间(速度和方向是对的,但范围不够)
  3. 添加M_PI偏移后,X轴完全不旋转

感觉getAxisQuaternion函数把旋转限制在了单个象限里,求解决思路?


内容的提问来源于stack exchange,提问作者RicardoSBA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:10:02