【发布时间】:2010-03-29 22:27:13
【问题描述】:
我正在尝试弄清楚如何根据设备方向(即根据加速度计的重力矢量和指南针的方向)正确显示 OpenGL 指定的对象。
GLGravity 示例项目有一个几乎像这样的示例(尽管忽略了标题),但它有一些小故障。例如,当设备的视角穿过地平线时,茶壶会跳跃 180 度,如果您将设备从纵向倾斜到横向,它也会虚假旋转。这对于这个应用程序的上下文来说很好,因为它只是展示了一个对象,它做这些事情并不重要。但这意味着当您尝试根据设备的方向模拟 OpenGL 对象的真实查看时,该代码将不起作用。发生的情况是它几乎可以工作,但是您从指南针应用的航向旋转被 GLGravity 示例项目中看到的虚假附加旋转“破坏”。
谁能提供示例代码来说明如何正确调整设备方向(即重力矢量),或修复 GLGravity 示例以使其不包含虚假的航向变化?
//Clear matrix to be used to rotate from the current referential to one based on the gravity vector
bzero(matrix, sizeof(matrix));
matrix[3][3] = 1.0;
//Setup first matrix column as gravity vector
matrix[0][0] = accel[0] / length;
matrix[0][1] = accel[1] / length;
matrix[0][2] = accel[2] / length;
//Setup second matrix column as an arbitrary vector in the plane perpendicular to the gravity vector {Gx, Gy, Gz} defined by by the equation "Gx * x + Gy * y + Gz * z = 0" in which we arbitrarily set x=0 and y=1
matrix[1][0] = 0.0;
matrix[1][1] = 1.0;
matrix[1][2] = -accel[1] / accel[2];
length = sqrtf(matrix[1][0] * matrix[1][0] + matrix[1][1] * matrix[1][1] + matrix[1][2] * matrix[1][2]);
matrix[1][0] /= length;
matrix[1][1] /= length;
matrix[1][2] /= length;
//Setup third matrix column as the cross product of the first two
matrix[2][0] = matrix[0][1] * matrix[1][2] - matrix[0][2] * matrix[1][1];
matrix[2][1] = matrix[1][0] * matrix[0][2] - matrix[1][2] * matrix[0][0];
matrix[2][2] = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
//Finally load matrix
glMultMatrixf((GLfloat*)matrix);
这是一个说明,说明如何获得 gluLookAt 解决方案所需的高度和倾斜度,如我上一个答案所示:
// elevation comes from z component (0 = facing horizon)
elevationRadians = asin(gravityVector.z / Vector3DMagnitude(gravityVector));
// tilt is how far screen is from vertical, looking along z axis
tiltRadians = atan2(-gravityVector.y, -gravityVector.x) - M_PI_2;
跟进 Chris 的建议:由于行/列顺序和标题 cw 或 ccw 的不同约定,我不确定我是否完全正确。但是下面的代码是我想出的:
Vector3D forward = Vector3DMake(0.0f, 0.0f, -1.0f);
// Multiply it by current rotation matrix to get teapot direction
Vector3D direction;
direction.x = matrix[0][0] * forward.x + matrix[1][0] * forward.y + matrix[2][0] * forward.z;
direction.y = matrix[0][1] * forward.x + matrix[1][1] * forward.y + matrix[2][1] * forward.z;
direction.z = matrix[0][2] * forward.x + matrix[1][2] * forward.y + matrix[2][2] * forward.z;
heading = atan2(direction.z, direction.x) * 180 / M_PI;
// Use this heading to adjust the teapot direction back to keep it fixed
// Rotate about vertical axis (Y), as it is a heading adjustment
glRotatef(heading, 0.0, 1.0, 0.0);
当我运行这段代码时,茶壶的行为显然已经“改进”了,例如。当设备屏幕(纵向视图)通过直立向前/向后倾斜时,航向不再翻转 180 度。但是,当设备(在横向视图中)向前/向后倾斜时,它仍然会在航向上发生重大跳跃。所以有些不对劲。提示上述实际航向计算不正确...
【问题讨论】:
标签: iphone objective-c opengl-es