在观察中心的同时(使用四元数)围绕球体动态观察相机

Orbit camera around sphere while looking at the center (using quaternions)

本文关键字:观察 相机 动态 四元数      更新时间:2023-10-16

我在包括这一个在内的几个站点上查看了大量的四元数示例,但没有找到答案,所以下面是。。。

我想围绕一个大球体环绕我的相机,并使相机始终指向球体的中心。为了简化操作,球体位于世界中的{0,0,0}处。我使用四元数作为相机方向,使用向量作为相机位置。问题是,摄影机的位置完全围绕球体运行,但始终看起来是一个不变的方向,而不是在球体运行时调整为指向中心。

这一定很简单,但我是四元数的新手。。。我错过了什么?

我使用的是C++,DirectX9。这是我的代码:

// Note: g_camRotAngleYawDir and g_camRotAnglePitchDir are set to either 1.0f, -1.0f according to keypresses, otherwise equal 0.0f
// Also, g_camOrientationQuat is just an identity quat to begin with.
float theta = 0.05f;
D3DXQUATERNION g_deltaQuat( 0.0f, 0.0f, 0.0f, 1.0f );
D3DXQuaternionRotationYawPitchRoll(&g_deltaQuat, g_camRotAngleYawDir * theta, g_camRotAnglePitchDir * theta, g_camRotAngleRollDir * theta);
D3DXQUATERNION tempQuat = g_camOrientationQuat;
D3DXQuaternionMultiply(&g_camOrientationQuat, &tempQuat, &g_deltaQuat);
D3DXMatrixRotationQuaternion(&g_viewMatrix, &g_camOrientationQuat);
g_viewMatrix._41 = g_camPosition.x;
g_viewMatrix._42 = g_camPosition.y;
g_viewMatrix._43 = g_camPosition.z;
g_direct3DDevice9->SetTransform( D3DTS_VIEW, &g_viewMatrix );

【编辑-2012年2月13日】

好的,到目前为止我的理解是:

使用每帧的角度增量移动相机。获取从中心到摄影机点的矢量。使用面向z的单位向量和目标向量调用向量之间的四元数旋转。然后将该函数的结果用于视图矩阵的方向,并且相机位置进入视图矩阵的平移部分。

这是新代码(称为每帧)。。。

//  This part orbits the position around the sphere according to deltas for yaw, pitch, roll
D3DXQuaternionRotationYawPitchRoll(&deltaQuat, yawDelta, pitchDelta, rollDelta);
D3DXMatrixRotationQuaternion(&mat1, &deltaQuat);
D3DXVec3Transform(&g_camPosition, &g_camPosition, &mat1);

//该部分将相机的方向调整为指向球体的中心

dir1 = normalize(vec3(0.0f, 0.0f, 0.0f) - g_camPosition);
QuaternionRotationBetweenVectors(&g_camOrientationQuat, vec3(0.0f, 0.0f, 1.0f), &dir1);

D3DXMatrixRotationQuaternion(&g_viewMatrix, &g_camOrientationQuat);
g_viewMatrix._41 = g_camPosition.x;
g_viewMatrix._42 = g_camPosition.y;
g_viewMatrix._43 = g_camPosition.z;

g_direct3DDevice9->SetTransform( D3DTS_VIEW, &g_viewMatrix );

我尝试过那个解决方案,但没有成功。我做错了什么?

无论何时更新位置(假设相机指向z轴),都应该像执行以下操作一样简单:

direction = normalize(center - position)
orientation = quaternionRotationBetweenVectors(vec3(0,0,1), direction)

很容易找到如何实现quaternionRotationBetweenVectors的示例。您可以从"查找表示从一个向量到另一个向量的旋转的四元数"这个问题开始。

以下是使用DirectX9 API实现的未经测试的示意图:

D3DXQUATERNION* quaternionRotationBetweenVectors(__inout D3DXQUATERNION* result, __in const D3DXVECTOR3* v1, __in const D3DXVECTOR3* v2)
{
    D3DXVECTOR3 axis;
    D3DXVec3Cross(&axis, v1, v2);
    D3DXVec3Normalize(&axis, &axis);
    float angle = acos(D3DXVec3Dot(v1, v2));
    D3DXQuaternionRotationAxis(result, &axis, angle);
    return result;
}

此实现期望v1, v2被规范化。

您需要展示如何计算角度。你为什么不使用D3DXMatrixLookAtLH?