旋转对象以匹配向量

问题描述 投票:2回答:3

我以为我在最长的时间内正确地执行了此操作,但是我相信我可能以非常错误的方式进行了此操作。

我有一个具有世界地形的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(来源:crystaldragon.com

[将鼠标悬停在石头上时,将计算三角形的法线(对于图片,石头面的法线为(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值输入方程的最终计算,但是我仍然想出失败的尝试。

c++ vector rotation direct3d
3个回答
0
投票

对于接近水平(平坦)的地形,该地形位于XZ平面上,因此法线的y值很可能是1.0,这应该为您提供正确的旋转而不使用y正常。

但是,将对象添加到墙壁时,将需要y法线来计算旋转的y分量。您说播放器可以在放置对象之前绕Y轴手动旋转对象。

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


0
投票

我会推荐四元数。您可以在没有它们的情况下使其正常工作,但是您的代码必须对零进行大量检查,并且如果尝试对任何东西进行动画处理,都将出现中断。四元数有点学习曲线,但是一旦有了:

  • 一种旋转方法

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

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

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

老实说,您不必理解数学就可以使数学起作用;您只需要能够遵循四元数数学的规则。


0
投票

我不知道Direct3D,但快速浏览一下文档,看起来好像是您想要的:

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

((我不知道这是否是正确的语法,例如sqrt,但是您看到了我要执行的操作。)

关于Y的旋转(“偏航”)可以留给用户-它相当于将雕像从朝北旋转到朝东,或者将画上下颠倒地挂在墙上。

我假设旋转是围绕对象固定的轴进行的。如果不是这种情况,那么解决方案将看起来完全不同。试试看,如果它不起作用,我们可以尝试几个简单的测试用例来确定它。

© www.soinside.com 2019 - 2024. All rights reserved.