我试图让我的应用程序用户通过在屏幕上拖动手指来旋转在屏幕中央绘制的3D对象。屏幕上的水平移动表示绕固定的Y轴旋转,而垂直移动表示绕X轴旋转。我遇到的问题是,如果我只允许绕一个轴旋转,则对象旋转良好,但是一旦引入第二个旋转,该对象就不会按预期旋转。
这是正在发生的情况的图片:
蓝色轴代表我的固定轴。画出具有此固定蓝色轴的屏幕。这就是我要相对于对象旋转的对象。发生的是红色。
这是我所知道的:
- 围绕Y(0,1,0)的第一次旋转使模型从蓝色空间(称为空间A)移至另一个空间(称为空间B)。
- 尝试再次使用向量(1、0、0)旋转时,空间B中的x轴会旋转,而不是空间A中的x轴旋转,这不是我的意思。
考虑到我(想)知道的内容(为简洁起见,省略了W坐标),这是我尝试的操作:
- 首先使用四元数绕Y(0,1,0)旋转。
- 将旋转Y四元数转换为矩阵。
- 将Y旋转矩阵乘以我的固定轴x矢量(1、0、0),以获得相对于新空间的X轴。
- 使用四元数围绕这个新的X向量旋转。
这是代码:
private float[] rotationMatrix() {
final float[] xAxis = {1f, 0f, 0f, 1f};
final float[] yAxis = {0f, 1f, 0f, 1f};
float[] rotationY = Quaternion.fromAxisAngle(yAxis, -angleX).toMatrix();
// multiply x axis by rotationY to put it in object space
float[] xAxisObjectSpace = new float[4];
multiplyMV(xAxisObjectSpace, 0, rotationY, 0, xAxis, 0);
float[] rotationX = Quaternion.fromAxisAngle(xAxisObjectSpace, -angleY).toMatrix();
float[] rotationMatrix = new float[16];
multiplyMM(rotationMatrix, 0, rotationY, 0, rotationX, 0);
return rotationMatrix;
}
这不符合我的预期。旋转似乎有效,但在某些点上水平移动不会绕Y轴旋转,而是绕Z轴旋转。
我不确定我的理解是错误的,还是其他原因引起了问题。除了旋转之外,我还对对象进行了其他一些转换。在应用旋转之前,我将对象移至中心。我使用上面函数返回的矩阵旋转它,然后在Z方向上将其平移-2以便看到对象。我不认为这会打乱我的工作,但是无论如何这是下面的代码:
private float[] getMvpMatrix() {
// translates the object to where we can see it
final float[] translationMatrix = new float[16];
setIdentityM(translationMatrix, 0);
translateM(translationMatrix, 0, translationMatrix, 0, 0f, 0f, -2);
float[] rotationMatrix = rotationMatrix();
// centers the object
final float[] centeringMatrix = new float[16];
setIdentityM(centeringMatrix, 0);
float moveX = (extents.max[0] + extents.min[0]) / 2f;
float moveY = (extents.max[1] + extents.min[1]) / 2f;
float moveZ = (extents.max[2] + extents.min[2]) / 2f;
translateM(centeringMatrix, 0, //
-moveX, //
-moveY, //
-moveZ //
);
// apply the translations/rotations
final float[] modelMatrix = new float[16];
multiplyMM(modelMatrix, 0, translationMatrix, 0, rotationMatrix, 0);
multiplyMM(modelMatrix, 0, modelMatrix, 0, centeringMatrix, 0);
final float[] mvpMatrix = new float[16];
multiplyMM(mvpMatrix, 0, projectionMatrix, 0, modelMatrix, 0);
return mvpMatrix;
}
我已经坚持了几天。非常感谢您的帮助。
================================================== ================
更新:
使它在Unity中起作用很简单。这是一些旋转以原点为中心的多维数据集的代码:
public class CubeController : MonoBehaviour {
Vector3 xAxis = new Vector3 (1f, 0f, 0f);
Vector3 yAxis = new Vector3 (0f, 1f, 0f);
// Update is called once per frame
void FixedUpdate () {
float horizontal = Input.GetAxis ("Horizontal");
float vertical = Input.GetAxis ("Vertical");
transform.Rotate (xAxis, vertical, Space.World);
transform.Rotate (yAxis, -horizontal, Space.World);
}
}
使旋转行为符合我期望的部分是变换函数的Space.World
参数Rotate
。
如果我可以使用Unity,那么不幸的是,我必须自己编写这种行为。