我接受了某人的建议,但它并没有像我预期的那样工作:
M=inverse(inverse(M)*rotation_matrix);
这是我的更新代码:
void TestApp::Update(float dt) {
DirectX::SimpleMath::Matrix rotation =
Matrix::CreateFromYawPitchRoll(rot.y, rot.x, 0.0f); //Rotation Matrix
DirectX::SimpleMath::Matrix position =
Matrix::CreateTranslation(pos); //Postion Matrix
m_view =
DirectX::XMMatrixInverse(nullptr, DirectX::XMMatrixMultiply(
DirectX::XMMatrixInverse(nullptr, position), rotation)); //This uses the advice
//m_view is the Camera/View Matrix
for (int i = 0; i < 256; ++i) {
if (GetAsyncKeyState(i)) {
if (i == 87) { // W
pos.z += dt * playerSpeed; //Move Forward
continue;
}
else if (i == 68) { //D
pos.x -= dt * playerSpeed; //Move Right
continue;
}
else if(i == 83){//S
pos.z -= dt * playerSpeed; //Move Backwards
continue;
}
else if (i == 65) { // A
pos.x += dt * playerSpeed; //Move Left
continue;
}
else if (i == VK_NUMPAD8) {
rot.x -= dt;
continue;
}
else if (i == VK_NUMPAD4) {
rot.y += dt;
}
else if (i == VK_NUMPAD5) {
rot.x += dt;
continue;
}
else if (i == VK_NUMPAD6) {
rot.y -= dt;
}
}
}
运动完美无瑕,但旋转效果不佳。它围绕世界起源旋转,而不像FPS相机。有什么帮助吗?
我正在使用DirectX 11和DirectX工具包。模型呈现精细,向前,向后,向左,向右移动就像一个FPS相机,但它是围绕世界原点旋转(0,0)。
答案 0 :(得分:0)
以下是使用OpenGL而不是Direct X的旧游戏引擎的片段。您可能需要调整坐标系的灵活性,但基本原则仍然适用。在3D环境中进行移动时;相机,玩家或世界物体经历的运动应该通过switch
语句而不是一堆if else
语句来完成。
看一下这个片段,了解在OpenGL游戏引擎中完成的旋转运动。
void Player::move( Action action, float fDeltaTime ) {
v3LookDirection = m_v3LookCenter - m_v3Position;
switch( action ) {
case MOVING_FORWARD: {
// ... code here ...
}
case MOVING_BACK: {
// ... code here ...
}
case MOVING_RIGHT: {
// ... code here ...
}
case MOVING_LEFT: {
// ... code here ...
}
case LOOKING_LEFT: {
/*float fSin = -sin( fDeltaTime * m_fAngularSpeed );
float fCos = cos( fDeltaTime * m_fAngularSpeed );
m_v3LookCenter.m_fX = m_v3Position.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX );
m_v3LookCenter.m_fZ = m_v3Position.m_fZ + ( fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX );
break;*/
// Third Person
float fSin = sin( fDeltaTime * m_fAngularSpeed );
float fCos = -cos( fDeltaTime * m_fAngularSpeed );
m_v3Position.m_fX = m_v3LookCenter.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX );
m_v3Position.m_fZ = m_v3LookCenter.m_fZ + ( fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX );
break;
}
case LOOKING_RIGHT: {
/*float fSin = sin( fDeltaTime * m_fAngularSpeed );
float fCos = cos( fDeltaTime * m_fAngularSpeed );
m_v3LookCenter.m_fX = m_v3Position.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX );
m_v3LookCenter.m_fZ = m_v3Position.m_fZ + ( fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX );
break;*/
// Third Person
float fSin = -sin( fDeltaTime * m_fAngularSpeed );
float fCos = -cos( fDeltaTime * m_fAngularSpeed );
m_v3Position.m_fX = m_v3LookCenter.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX );
m_v3Position.m_fZ = m_v3LookCenter.m_fZ + ( fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX );
break;
}
case LOOKING_UP: {
m_v3LookCenter.m_fY -= fDeltaTime * m_fAngularSpeed * m_MouseLookState;
// Check Maximum Values
if ( m_v3LookCenter.m_fY > (m_v3Position.m_fY + m_fMaxUp ) ) {
m_v3LookCenter.m_fY = m_v3Position.m_fY + m_fMaxUp;
} else if ( m_v3LookCenter.m_fY < (m_v3Position.m_fY - m_fMaxDown) ) {
m_v3LookCenter.m_fY = m_v3Position.m_fY - m_fMaxDown;
}
break;
}
} // switch
}
所有以m_v3...
开头的声明的本地和成员变量都是Vector3对象。 Vector3对象有一个x,y,z
个组件,可以对向量进行所有可用的数学运算,Action是一个枚举类型。
此函数在我的Scene
类中调用。
void Scene::playerAction( float fMouseXDelta, float fMouseYDelta ) {
if ( fMouseXDelta != 0.0f ) {
m_player.move( LOOKING_RIGHT, fMouseXDelta );
}
if ( fMouseYDelta != 0.0f ) {
m_player.move( LOOKING_UP, fMouseYDelta );
}
}
还有Scene::update()
void Scene::update() {
UserSettings* pUserSettings = UserSettings::get();
AudioManager* pAudio = AudioManager::getAudio();
bool bPlayerMoving = false;
// Movement
if ( pUserSettings->isAction( MOVING_FORWARD ) ) {
m_player.move( MOVING_FORWARD, GameOGL::getPhysicsTimeStep() );
bPlayerMoving = true;
}
if ( pUserSettings->isAction( MOVING_BACK ) ) {
m_player.move( MOVING_BACK, GameOGL::getPhysicsTimeStep() );
bPlayerMoving = true;
}
if ( pUserSettings->isAction( MOVING_LEFT ) ) {
m_player.move( MOVING_LEFT, GameOGL::getPhysicsTimeStep() );
bPlayerMoving = true;
}
if ( pUserSettings->isAction( MOVING_RIGHT ) ) {
m_player.move( MOVING_RIGHT, GameOGL::getPhysicsTimeStep() );
bPlayerMoving = true;
}
if ( bPlayerMoving && !m_bPlayerWalking ) {
pAudio->setLooping( AUDIO_FOOTSTEPS, true );
pAudio->play( AUDIO_FOOTSTEPS );
m_bPlayerWalking = true;
}
else if ( !bPlayerMoving && m_bPlayerWalking ) {
pAudio->stop( AUDIO_FOOTSTEPS );
m_bPlayerWalking = false;
}
// Bunch more code here.
}
这也与GameOGL
类相关联,该messageHandler()
类与Player
一起使用,我将不会在此处显示。这是一个由大约5万行代码组成的中型到大型项目。这里显示每个工件都很大,所以请不要问,因为这个引擎中的所有东西都集成在一起。我正在展示用于进行旋转运动的基本数学运算,无论是通过按键还是鼠标移动来调用。
现在你必须记住这一点,因为它很重要。您看到来自执行轮换的DirectX's
类的实际计算可能无法直接使用。如果坐标系的手性不同于此处使用的坐标系;您必须使用适当的三角函数到适当的坐标轴成员,并使用适当的符号进行计算才能正确。当旋向性改变时,所暗示的旋转轴以及旋转的初始方向也改变。不是3D数学乐趣吗?
修改强>
哦我也注意到你正在使用::CreateFromYawPitchRoll()
Quaternions
来创建旋转矩阵;这没关系,但你需要注意使用标准欧拉角的旋转。如果你开始同时以超过一个运动程度进行旋转;你最终会体验到万向节锁。避免在3D旋转中使用万向节锁定问题;最好使用GLM
对它们的数学有点难以理解,它们的概念并不难理解,但使用它们实际上非常简单,并且计算效率也很高。许多数学库包含它们; DirectX的数学库以及开放源代码{{1}}数学库应该与OpenGL&amp; GLSL。如果您不确定Gimbal Lock和Quaternions,您可以通过Google搜索来查找这些主题;那里有很多关于他们的信息。不是高级3D ......呃下摆...... 4D数学乐趣?
答案 1 :(得分:0)
你说它从世界原点来看是旋转的,就像“如果你留在旋转木马的边缘而你正在看中心”
我认为你希望你的物体从它自己的中心旋转。
解决方案是你应该旋转你的对象,然后应用你的位置矩阵。
这是负责任的
m_view =
DirectX::XMMatrixInverse(nullptr, DirectX::XMMatrixMultiply(
DirectX::XMMatrixInverse(nullptr, position), rotation))
我认为修复应该是在旋转后应用位置 在OpenGl中,您可以在Model matrice上应用旋转
glm :: mat4 MVPmatrix = projection * view * model;
您可以旋转视图或模型矩阵,并获得2个不同的结果。
我一般都不知道你的代码和DirectX,但也许你应该反转2
m_view =
DirectX::XMMatrixInverse(nullptr, DirectX::XMMatrixMultiply(
DirectX::XMMatrixInverse(nullptr, rotation), position))
看看http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/