我使用 OpenGL,确切地说是 Cocos3d,在 iPhone/iPad 项目中显示地球。我希望用户能够用手指旋转地球。仅围绕一个轴旋转可以正常工作,但我不知道如何一起解决 3 轴...
捕捉手指运动也可以 -> 我得到 2D (x/y) 值,但是如何在 3D 旋转中转换这些值?
想象一下,在窗口的中心是接触窗口边缘的 3d 球体(不是椭圆)。它位于屏幕空间,而不是世界空间。“屏幕空间”意味着如果您的窗口为 640x480,则球体位于 x=320,y=240 并且半径为 240 ( min(width,height)/2
),无论您的模型视图/投影矩阵如何。
当用户单击按下鼠标按钮时,他/她选择球体上的点。如果单击在该球体之外,则初始点移动到球体边界。让我们称之为这一点pointA
。当用户四处拖动鼠标时,鼠标位置标记用户希望该初始点所在的位置。让我们称之为pointB
。
现在对于一个球体,在给定第一个两个的情况下计算第三个坐标非常容易,因为R^2 = X^2+y^2+z^2
您可以计算初始点的pointA
第三个坐标( )和当前点的第三个坐标(pointB
)。现在使用两个点,您可以计算从球心 ( O
) 到点 ( vectorOA = pointA - O; vectorOB = pointB - O
) 的两个向量。现在,由于您有两个向量,您可以使用它们来计算旋转轴(使用叉积 = rotationAxis = normalize(vecOA x vecOB);
)和旋转角度(使用归一化向量的点积上的 acos = acos(dot(normalize(vecOA), normalize(vecOB))
)。使用轴和角度,您可以在屏幕空间中构建旋转矩阵,然后可以将其转换为您想要的空间并应用于对象。
该技术通常被称为“轨迹球”。它已在 Microsoft DirectX SDK 的一些示例中使用,您应该能够在 NVidia OpenGL SDK 中的某个位置找到它。因此,如果您不理解解释,我建议您使用任何一个 sdk 并调查任何允许您使用鼠标旋转对象的示例。
一种简单的方法是简单地将绕 Y 轴的旋转设置为translationInView
要旋转的 x 分量,并将绕 X 轴的旋转设置为translationInView
y 分量。由于旋转值以弧度为单位,您可能必须将平移除以一定的量。我通常认为给用户 2 个自由度就足够了,但是如果您确实需要允许用户绕 z 轴旋转,您可能需要考虑使用UIRotationGestureRecognizer
单独处理这种情况。
CGPoint translation = [sender translationInView:self.view];
_rotationY = translation.x / 100.0f;
_rotationX = translation.y / 100.0f;