围绕球体的轨道相机,同时看着中心(使用四元数)

时间:2012-02-12 11:53:27

标签: c++ 3d camera directx-9 quaternions

我在几个网站上看了很多四元数的例子,包括这个,但是没有找到答案,所以这里有......

我想围绕一个大球体围绕我的相机进行轨道运动,让相机始终指向球体的中心。为了简单起见,球体位于世界{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的单位向量和目标向量调用quaternionRotationBetweenVectors。 然后使用该函数的结果作为视图矩阵的方向,摄像机位置进入视图矩阵的平移部分。

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

//  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 );

......我尝试了解决方案,没有成功。我做错了什么?

2 个答案:

答案 0 :(得分:1)

每当您更新位置时(假设相机指向z轴),它应该像执行以下操作一样简单:

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

很容易找到如何实施quaternionRotationBetweenVectors的示例。您可以从问题“Finding quaternion representing the rotation from one vector to another”开始。

这是使用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进行规范化。

答案 1 :(得分:0)

您需要显示如何计算角度。您有没有使用D3DXMatrixLookAtLH的原因?