旋转对象以匹配矢量

时间:2015-04-17 23:36:14

标签: c++ vector rotation direct3d

我认为我这样做的时间最长,但我相信我可能会以非常错误的方式这样做。

我有一个具有世界地形的3D引擎,物体可以放置在地面上,当它们被放置时,它们会定向到它们所处的地形(旋转)。我这样做的方式是这样的:

D3DXVECTOR3 tNormal = GetNormalFromFile( ... );  //Get the terrain's normal

placeItemData.placeMesh.meshRot.z = (acos(tNormal.x) - (D3DX_PI/2));
placeItemData.placeMesh.meshRot.x = -(acos(tNormal.z) - (D3DX_PI/2)); 

我将旋转存储为以弧度为单位的向量:x,y,z旋转,其中Y为向上。所以我计算X轴和Z轴的旋转并相应地旋转。玩家可以在放置之前手动旋转Y轴周围的物体,所有这些都可以正常工作。

当我继续改进我的物品放置代码时,我意识到这不适用于近乎垂直的飞机。例如,尝试将图片放在墙上。这段代码似乎可以将物品放置在近水平(平坦)的地形上,但是垂直墙的旋转方式很远。

我在这里错过了一个简单的计算吗?我需要以某种方式计算y轴值吗?我试图使用atan2函数来计算旋转:

placeItemData.placeMesh.meshRot.z = (atan2(finalNormal.x,finalNormal.y) );
placeItemData.placeMesh.meshRot.x = (atan2(finalNormal.z,finalNormal.y) );

但我遇到了类似的问题。

我是否需要使用四元数进行这些计算?我能够轻松地将最终旋转值再次存储在3D矢量(x,y,z)中吗?

我感谢任何帮助!

更新1

以下是使用此代码的图片:

meshRot.z = - atan2(sqrt(finalNormal.y^2 + finalNormal.z^2), finalNormal.x);
meshRot.x = - atan2(finalNormal.y, finalNormal.z);

prob1 http://www.crystaldragon.com/TempImages/prob1.png

当您将鼠标悬停在石头上时,会计算三角形的法线(对于图片,石面的法线为(0.637,-0.014,0.770))。当然,你在石头上看到的木块应该直接放在石头的顶部(就像悬挂在图片上一样)。

更新2

通过在我的世界中测试位于z轴上的“墙”,我似乎只为y = 0的所有情况提供了代码。我可以将物体放在所有垂直墙上,但不能放在墙的水平(顶部)上。

以下是当前代码:

placeItemData.placeMesh.meshRot.x =  -(atan2(finalNormal.y, sqrt((finalNormal.x * finalNormal.x ) + (finalNormal.z * finalNormal.z)) ) + (D3DX_PI/2));
placeItemData.placeMesh.meshRot.z =  -(atan2(finalNormal.z, finalNormal.x ) + (D3DX_PI/2)); 

只要y-normal的值为0,对象就会附着到每个垂直墙上,但不会附着在水平上(因为y-normal显然是非负数)。希望最后一步是弄清楚我需要输入的最终计算作为y值进入等式,但我仍然想出失败的尝试。

3 个答案:

答案 0 :(得分:0)

对于近水平(平坦)地形,地形位于 XZ 平面上,因此法线的 y 值很可能是1.0,这应该会给你没有使用y法线的正确旋转。

但是,在向墙添加对象时,将需要 y 法线来计算旋转的 y 组件。您说播放器可以在放置之前手动旋转 Y 轴周围的对象。

您是否正在使用法线的 y 值计算旋转的y分量?如果没有,请确保您也在计算它。否则,您将计算2D中的旋转,并以某种方式将其外推至3D。

答案 1 :(得分:0)

我会推荐Quaternions。您可以在没有它们的情况下使用它,但是您的代码必须对零进行大量检查,如果您尝试对任何内容进行动画处理,则会出现不连续性。四元数有一点学习曲线但是一旦你有了:

  • 轮换方法

  • 从笛卡儿(或极地或其他)到四元数的转换

  • 从四元数到笛卡尔(或其他)的转换

使用起来非常简单,它们是3d操作的正确选择。

我会诚实地说,你不必理解数学要么让它发挥作用;你必须能够遵循四元数学的规则。

答案 2 :(得分:0)

我不知道Direct3D,但是通过快速查看文档,看起来好像这就是你想要的:

meshRot.z = - atan2(sqrt(finalNormal.y^2 + finalNormal.z^2), finalNormal.x);
meshRot.x = - atan2(finalNormal.y, finalNormal.z);

(我不知道这是否是正确的语法,例如sqrt,但你看到我正在尝试做什么。)

关于Y(“偏航”)的旋转可以留给用户 - 它对应于将雕像从朝北朝向东方旋转,或者将画面倒挂在墙上。

我假设旋转是关​​于物体固定的轴。如果情况并非如此,那么解决方案将看起来完全不同。尝试一下,如果它不起作用,我们可以尝试几个简单的测试用例来确定它。