四元数,齐次坐标问题及相关回答

来源:互联网 发布:apache tomcat 集群 编辑:程序博客网 时间:2024/06/04 18:57

 

我看了很多书,和文章,可是还是不知道,四元数到底有什么用

好像她的好处就是为了能比矩阵,在相乘的时候,运算次数少

另外,一个包含旋转信息的四元数如何与一个向量运算得到我希望的结果?好像dx没有提供这样的函数啊?难道需要转换为矩阵再计算吗?

D3DXQUATERNIONSlerp函数是做球体上旋转线性插值的吧?他的最后一个参数如何使用?

q=cos(a/2) + sin(a/2)*V  角a是旋转角度吧只要,控制一下是不是就可以达到D3DXQUATERNIONSlerp相同的效果?

旋转的线性插值,四元数应该就是为了这个吧,可是D3DXMatrixRotationAxis函数不是也可吗,那还要四元数干什么?
-----------------------------

齐次坐标:
齐次坐标(x,y,z,w) 转换为向量(x/w,y/w,z/w) 齐次坐标就是为了可以表示无穷远的问题吧(w趋向于0时)
D3DXVec3TransformNormal
D3DXVec3TransformCoord
D3DXVec3Transform
这3个函数有什么区别

真的是看了很长时间书了,可能是我比较笨吧,一直由这些疑问搞不懂,还希望高手能指点一下,谢谢啦

 

你自己都说了:四元数比矩阵在相乘的时候运算次数少。在像动画计算这样没帧都要做大量绕任意轴旋转操作的应用中,四元数比矩阵可以有效降低CPU计算量。另外它可以避免万向锁(Gimbal)问题,你可以到Google上搜一下这个问题。
齐次坐标中的w有个重要的作用是用于消除Z坐标,计算投影坐标影射到屏幕。
这些问题不可能几句话说明白,最后给你推荐一本书:3D Math Primer for Graphics and Game Development,你的这两个问题都可以在里面找到答案,而且此书有中文版!

 

 

我看了那本书,但还是不知道为什么用Quaternion来表示旋转的公式是
qPq^-1

我想可能和eigenvector,eigenvalue(特征值,特征向量)有关系
谁能帮我解释一下?
谢谢

 

 

我看了很多书,和文章,可是还是不知道,四元数到底有什么用

好像她的好处就是为了能比矩阵,在相乘的时候,运算次数少


四元数q = (w,v),表示一个旋转和向量。这样的表示非常简单,这是它的一个优点,而且可以减少一次矩阵相乘。
----------------------------------------------------------------------
另外,一个包含旋转信息的四元数如何与一个向量运算得到我希望的结果?好像dx没有提供这样的函数啊?难道需要转换为矩阵再计算吗?

先看看通过矩阵操作的结果吧
D3DXMatrixRotationAxis( &matRot, &m_v, angle )
D3DXVec3TransformCoord( &vNew, &m_v, &matRot );
这个是vNew向量绕m_v向量旋转angle角度。
D3DXMatrixRotationX(&matTran,fRads);
D3DXMatrixMultiply(&m_matWorld,&matTran,&m_matWorld);
这个是是绕x轴旋转fRads角度。
再看通过四元数的操作
D3DXQuaternionRotationYawPitchRoll (&qR, 0, fRads, 0);
D3DXMatrixRotationQuaternion (&matRot, &qR);
D3DXMatrixTranspose(&matRot,&matRot)//因为四元数是使用右手法则的,所以需要转置一下。
D3DXMatrixMultiply (&m_matWorld,  &m_matWorld,&matRot);
如果不转制也行,那就
D3DXMatrixMultiply (&m_matWorld, &matRot, &m_matWorld);
显然四元数比矩阵要少做一次乘法。
不过确实需要转换成矩阵。

--------------------------------------------------------
D3DXQUATERNIONSlerp函数是做球体上旋转线性插值的吧?他的最后一个参数如何使用?

q=cos(a/2) + sin(a/2)*V  角a是旋转角度吧只要,控制一下是不是就可以达到D3DXQUATERNIONSlerp相同的效果?

旋转的线性插值,四元数应该就是为了这个吧,可是D3DXMatrixRotationAxis函数不是也可吗,那还要四元数干什么?


给你看一段关键帧动画中的四元数插值。
// Rotation
if (pAnim->m_NumRotationKeys > 0 && !pAnim->m_vRotationKeys.empty())
{
// Loop for matching rotation key
for (j=0;j<pAnim->m_NumRotationKeys;j++)
{
if (Time < pAnim->m_vRotationKeys[j].m_Time) {
dwKey2 = j;
break;
}
}
dwKey1 = (dwKey2 == 0) ? 0 : dwKey2 - 1;
// Get difference in keys' times
DWORD dwTimeDiff = pAnim->m_vRotationKeys[dwKey2].m_Time -
pAnim->m_vRotationKeys[dwKey1].m_Time;
if(dwTimeDiff == 0)
fScalar = 0;
else// Calculate a scalar value to use
fScalar = (Time - pAnim->m_vRotationKeys[dwKey1].m_Time) / dwTimeDiff;
// slerp rotation values
D3DXQUATERNION quatRotation,q1,q2;
q1.x = -pAnim->m_vRotationKeys[dwKey1].m_quatKey.x;
q1.y = -pAnim->m_vRotationKeys[dwKey1].m_quatKey.y;
q1.z = -pAnim->m_vRotationKeys[dwKey1].m_quatKey.z;
q1.w = pAnim->m_vRotationKeys[dwKey1].m_quatKey.w;
q2.x = -pAnim->m_vRotationKeys[dwKey2].m_quatKey.x;
q2.y = -pAnim->m_vRotationKeys[dwKey2].m_quatKey.y;
q2.z = -pAnim->m_vRotationKeys[dwKey2].m_quatKey.z;
q2.w = pAnim->m_vRotationKeys[dwKey2].m_quatKey.w;
D3DXQuaternionSlerp(&quatRotation,&q1,&q2,fScalar);
// Create rotation matrix and combine with transformation
D3DXMATRIX matRotation;
D3DXMatrixRotationQuaternion(&matRotation,&quatRotation);
pAnim->m_Bone->TransformationMatrix *= matRotation;
}

D3DXQuaternionSlerp只是进行了线形插值。最后一个参数表示权值。

其他的那些函数,你看看msdn,实在不明白也没关系,等你用到了也许就知道了,多看看别人的代码有好处,最好自己再实做一下更好!

 

 

 

我来回答一下,表达得可能不太清楚.实在是不知道怎么说才好.

D3DXQUATERNIONSlerp函数最后一个参数是用来控制插值过渡速度.

D3DXQUATERNIONSlerp做的是球型插值,而D3DXMatrixRotationAxis则是线性插值.

两种方法所得到的结果是完全不一样的,一个是走的弧线,一个走的直线
-----------------------------

D3DXVec3TransformNormal
D3DXVec3TransformCoord
区别在于
一个是W=1,一个是W=0

要我表达清楚很难…自己试试吧

 

 

 

Quaterion 是球面空间的位移 球面空间里的直线就是 笛卡儿坐标空间里的一段弧 对quaterion在球面空间里进行线性插值 就相当于 在笛卡儿坐标空间里对旋转做圆滑插值。

不记得什么时候看过的类似的描述 也不知道记错了没有 不过大概的道理是对的

不用quaternion很难对旋转做圆滑的插值, 或者说做起来比较麻烦 没用quaterion那么简洁。

 

 

齐次坐标系中的坐标和向量都是4维的, 只不过为了简单一般都忽略第4维 w 直接使用3维

齐次坐标系中的点 的w = 1
齐次坐标系中的向量的 w = 0;

D3DXVec3TransformNormal
D3DXVec3TransformCoord

上面两个方法的参数是3维向量 xyz, 第一个函数的参数的隐含w = 0(因为法线是向量), 第二个函数的参数的隐含w = 1

D3DXVec3Transform 和 D3DXVec3TransformCoord的区别在于 输出结果一个是4维的 一个是3维的
D3DXVec3TransformCoord将结果的每个分量都 除以 w 最后得出的结果是忽略了 w的 3维向量(因为w = 1)
D3DXVec3Transform 的结果是4维的结果 w 不一定等于 1

原创粉丝点击